mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-11-24 02:30:03 +00:00
!7753 fix some jit bug in dfx
Merge pull request !7753 from wangyue/fixbuginjitdfx
This commit is contained in:
commit
346e30374b
@ -45,8 +45,7 @@ bool IsFastJitFunctionFrame(const FrameType frameType)
|
||||
return frameType == FrameType::FASTJIT_FUNCTION_FRAME || frameType == FrameType::FASTJIT_FAST_CALL_FUNCTION_FRAME;
|
||||
}
|
||||
|
||||
std::string JsStackInfo::BuildMethodTrace(Method *method, uint32_t pcOffset, const FrameType frameType,
|
||||
bool enableStackSourceFile)
|
||||
std::string JsStackInfo::BuildMethodTrace(Method *method, uint32_t pcOffset, bool enableStackSourceFile)
|
||||
{
|
||||
std::string data;
|
||||
data.append(" at ");
|
||||
@ -54,9 +53,6 @@ std::string JsStackInfo::BuildMethodTrace(Method *method, uint32_t pcOffset, con
|
||||
if (name.empty()) {
|
||||
name = "anonymous";
|
||||
}
|
||||
if (IsFastJitFunctionFrame(frameType)) {
|
||||
LOG_ECMA(ERROR) << "jit : js crash at method : " << name;
|
||||
}
|
||||
data += name;
|
||||
data.append(" (");
|
||||
// source file
|
||||
@ -94,8 +90,7 @@ std::string JsStackInfo::BuildMethodTrace(Method *method, uint32_t pcOffset, con
|
||||
return data;
|
||||
}
|
||||
|
||||
std::string JsStackInfo::BuildInlinedMethodTrace(const JSPandaFile *pf, std::map<uint32_t, uint32_t> &methodOffsets,
|
||||
const FrameType frameType)
|
||||
std::string JsStackInfo::BuildInlinedMethodTrace(const JSPandaFile *pf, std::map<uint32_t, uint32_t> &methodOffsets)
|
||||
{
|
||||
std::string data;
|
||||
std::map<uint32_t, uint32_t>::reverse_iterator it;
|
||||
@ -111,9 +106,6 @@ std::string JsStackInfo::BuildInlinedMethodTrace(const JSPandaFile *pf, std::map
|
||||
}
|
||||
}
|
||||
data.append(" at ");
|
||||
if (IsFastJitFunctionFrame(frameType)) {
|
||||
LOG_ECMA(ERROR) << "jit : js crash at method : " << name;
|
||||
}
|
||||
data.append(name);
|
||||
data.append(" (maybe inlined).");
|
||||
data.append(" depth: ");
|
||||
@ -124,18 +116,6 @@ std::string JsStackInfo::BuildInlinedMethodTrace(const JSPandaFile *pf, std::map
|
||||
return data;
|
||||
}
|
||||
|
||||
void PrintJSCrashOffset(uintptr_t pcOffset, JSFunction *func)
|
||||
{
|
||||
if (func->GetMachineCode() == JSTaggedValue::Undefined()) {
|
||||
return;
|
||||
}
|
||||
MachineCode *machineCode = MachineCode::Cast(func->GetMachineCode().GetTaggedObject());
|
||||
uintptr_t funcAddr = machineCode->GetFuncAddr();
|
||||
uintptr_t pc = pcOffset + funcAddr;
|
||||
LOG_ECMA(ERROR) << "jit : Current pc is : " << pc << ". Current funcAddr is : " << funcAddr <<
|
||||
". Current crash offset is : " << pcOffset;
|
||||
}
|
||||
|
||||
void JsStackInfo::DumpJitCode(JSThread *thread)
|
||||
{
|
||||
JSTaggedType exception = thread->GetException().GetRawData();
|
||||
@ -144,22 +124,30 @@ void JsStackInfo::DumpJitCode(JSThread *thread)
|
||||
if (jitCode == jitCodeMaps.end()) {
|
||||
return;
|
||||
}
|
||||
std::set<MachineCode*> memos;
|
||||
JsJitDumpElf jitDumpElf;
|
||||
jitDumpElf.Init();
|
||||
int64 idx = 0;
|
||||
size_t offset = 0;
|
||||
for (auto it = jitCode->second->begin(); it != jitCode->second->end(); it++) {
|
||||
auto machineCode = it->first;
|
||||
std::string methodName = it->second;
|
||||
char *funcAddr = reinterpret_cast<char *>(machineCode->GetFuncAddr());
|
||||
size_t len = machineCode->GetTextSize();
|
||||
std::vector<uint8> vec(len);
|
||||
if (memmove_s(vec.data(), len, funcAddr, len) != EOK) {
|
||||
LOG_ECMA(ERROR) << "Fail to get machineCode on function addr: " << funcAddr;
|
||||
auto jitCodeVec = jitCodeMaps[exception];
|
||||
for (size_t i = 0; i < jitCodeVec->size(); i++) {
|
||||
auto item = (*jitCodeVec)[i];
|
||||
auto machineCode = std::get<0>(item);
|
||||
std::string methodName = std::get<1>(item);
|
||||
uintptr_t pcOffset = std::get<2>(item);
|
||||
auto res = memos.insert(machineCode);
|
||||
if (res.second) {
|
||||
LOG_ECMA(ERROR) << "jit : js crash at method : " << methodName << ", offset :" << pcOffset;
|
||||
char *funcAddr = reinterpret_cast<char *>(machineCode->GetFuncAddr());
|
||||
size_t len = machineCode->GetTextSize();
|
||||
std::vector<uint8> vec(len);
|
||||
if (memmove_s(vec.data(), len, funcAddr, len) != EOK) {
|
||||
LOG_ECMA(ERROR) << "Fail to get machineCode on function addr: " << funcAddr;
|
||||
}
|
||||
jitDumpElf.AppendData(vec);
|
||||
jitDumpElf.AppendSymbolToSymTab(idx++, offset, len, methodName);
|
||||
offset += len;
|
||||
}
|
||||
jitDumpElf.AppendData(vec);
|
||||
jitDumpElf.AppendSymbolToSymTab(idx++, offset, len, methodName);
|
||||
offset += len;
|
||||
}
|
||||
std::string fileName = "jitCode-" + std::to_string(getpid());
|
||||
std::string realOutPath;
|
||||
@ -173,7 +161,8 @@ void JsStackInfo::DumpJitCode(JSThread *thread)
|
||||
close(fd);
|
||||
}
|
||||
|
||||
void AssembleJitCodeMap(JSThread *thread, const JSHandle<JSObject> &jsErrorObj, JSFunction *func, Method *method)
|
||||
void AssembleJitCodeMap(JSThread *thread, const JSHandle<JSObject> &jsErrorObj, JSFunction *func, Method *method,
|
||||
uintptr_t offset)
|
||||
{
|
||||
ASSERT(!jsErrorObj.GetTaggedValue().IsUndefined());
|
||||
JSTaggedValue machineCodeTagVal = func->GetMachineCode();
|
||||
@ -182,7 +171,7 @@ void AssembleJitCodeMap(JSThread *thread, const JSHandle<JSObject> &jsErrorObj,
|
||||
if (methodName.empty()) {
|
||||
methodName = "anonymous";
|
||||
}
|
||||
thread->SetJitCodeMap(jsErrorObj.GetTaggedValue().GetRawData(), machineCode, methodName);
|
||||
thread->SetJitCodeMap(jsErrorObj.GetTaggedValue().GetRawData(), machineCode, methodName, offset);
|
||||
}
|
||||
|
||||
std::string JsStackInfo::BuildJsStackTrace(JSThread *thread, bool needNative, const JSHandle<JSObject> &jsErrorObj)
|
||||
@ -240,16 +229,15 @@ std::string JsStackInfo::BuildJsStackTraceInfo(JSThread *thread, Method *method,
|
||||
FrameType frameType = it.GetFrameType();
|
||||
if (IsFastJitFunctionFrame(frameType)) {
|
||||
JSFunction *func = static_cast<JSFunction*>(it.GetFunction().GetTaggedObject());
|
||||
PrintJSCrashOffset(it.GetOptimizedReturnAddr(), func);
|
||||
if (!jsErrorObj.GetTaggedValue().IsUndefined()) {
|
||||
AssembleJitCodeMap(thread, jsErrorObj, func, method);
|
||||
AssembleJitCodeMap(thread, jsErrorObj, func, method, it.GetOptimizedReturnAddr());
|
||||
}
|
||||
}
|
||||
return BuildInlinedMethodTrace(pf, methodOffsets, frameType) +
|
||||
BuildMethodTrace(method, pcOffset, frameType, thread->GetEnableStackSourceFile());
|
||||
return BuildInlinedMethodTrace(pf, methodOffsets) +
|
||||
BuildMethodTrace(method, pcOffset, thread->GetEnableStackSourceFile());
|
||||
}
|
||||
|
||||
void JsStackInfo::BuildCrashInfo(bool isJsCrash, uintptr_t pc, JSThread *thread)
|
||||
void JsStackInfo::BuildCrashInfo(bool isJsCrash, FrameType frameType, JSThread *thread)
|
||||
{
|
||||
if (JsStackInfo::loader == nullptr || JsStackInfo::options == nullptr) {
|
||||
LOG_ECMA(ERROR) << "Loader or options initialization error.";
|
||||
@ -263,8 +251,11 @@ void JsStackInfo::BuildCrashInfo(bool isJsCrash, uintptr_t pc, JSThread *thread)
|
||||
ohos::RuntimeInfoType type;
|
||||
if (isJsCrash) {
|
||||
type = ohos::RuntimeInfoType::JS;
|
||||
} else if (pc != 0 && JsStackInfo::loader != nullptr && JsStackInfo::loader->InsideAOT(pc)) {
|
||||
} else if (frameType == FrameType::OPTIMIZED_JS_FUNCTION_FRAME ||
|
||||
frameType == FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME) {
|
||||
type = ohos::RuntimeInfoType::AOT;
|
||||
} else if (IsFastJitFunctionFrame(frameType)) {
|
||||
type = ohos::RuntimeInfoType::JIT;
|
||||
} else {
|
||||
type = ohos::RuntimeInfoType::OTHERS;
|
||||
}
|
||||
@ -943,16 +934,20 @@ bool ArkWriteJitCode([[maybe_unused]] void *ctx, [[maybe_unused]] ReadMemFunc re
|
||||
{
|
||||
JsJitDumpElf jitDumpElf;
|
||||
jitDumpElf.Init();
|
||||
std::set<uintptr_t> memos;
|
||||
int64 idx = 0;
|
||||
size_t offset = 0;
|
||||
for (size_t i = 0; i < jitSize; i++) {
|
||||
uintptr_t methodId = jitCodeArray[i];
|
||||
std::vector<uint8> codeVec = JsStackInfo::machineCodeMap[EntityId(methodId)];
|
||||
std::string name = JsStackInfo::nameMap[EntityId(methodId)];
|
||||
size_t len = codeVec.size();
|
||||
jitDumpElf.AppendData(codeVec);
|
||||
jitDumpElf.AppendSymbolToSymTab(idx++, offset, len, name);
|
||||
offset += len;
|
||||
auto res = memos.insert(methodId);
|
||||
if (res.second) {
|
||||
std::vector<uint8> codeVec = JsStackInfo::machineCodeMap[EntityId(methodId)];
|
||||
std::string name = JsStackInfo::nameMap[EntityId(methodId)];
|
||||
size_t len = codeVec.size();
|
||||
jitDumpElf.AppendData(codeVec);
|
||||
jitDumpElf.AppendSymbolToSymTab(idx++, offset, len, name);
|
||||
offset += len;
|
||||
}
|
||||
}
|
||||
jitDumpElf.WriteJitElfFile(fd);
|
||||
JsStackInfo::nameMap.clear();
|
||||
|
@ -155,8 +155,7 @@ private:
|
||||
|
||||
class JsStackInfo {
|
||||
public:
|
||||
static std::string BuildInlinedMethodTrace(const JSPandaFile *pf, std::map<uint32_t, uint32_t> &methodOffsets,
|
||||
const FrameType frameType);
|
||||
static std::string BuildInlinedMethodTrace(const JSPandaFile *pf, std::map<uint32_t, uint32_t> &methodOffsets);
|
||||
static inline std::string BuildJsStackTrace(JSThread *thread, bool needNative)
|
||||
{
|
||||
// If jsErrorObj not be pass in, MachineCode object of its stack frame while not be keep alive
|
||||
@ -165,14 +164,14 @@ public:
|
||||
}
|
||||
static std::string BuildJsStackTrace(JSThread *thread, bool needNative, const JSHandle<JSObject> &jsErrorObj);
|
||||
static std::vector<JsFrameInfo> BuildJsStackInfo(JSThread *thread, bool currentStack = false);
|
||||
static std::string BuildMethodTrace(Method *method, uint32_t pcOffset, const FrameType frameType,
|
||||
bool enableStackSourceFile = true);
|
||||
static std::string BuildMethodTrace(Method *method, uint32_t pcOffset, bool enableStackSourceFile = true);
|
||||
static AOTFileManager *loader;
|
||||
static JSRuntimeOptions *options;
|
||||
static void BuildCrashInfo(bool isJsCrash, uintptr_t pc = 0, JSThread *thread = nullptr);
|
||||
static void BuildCrashInfo(bool isJsCrash, FrameType frameType = FrameType::OPTIMIZED_FRAME,
|
||||
JSThread *thread = nullptr);
|
||||
static inline void BuildCrashInfo(JSThread *thread)
|
||||
{
|
||||
BuildCrashInfo(true, 0, thread); // pc is useless for JsCrash, pass 0 as placeholder
|
||||
BuildCrashInfo(true, FrameType::OPTIMIZED_FRAME, thread); // pc is useless for JsCrash, pass 0 as placeholder
|
||||
}
|
||||
static std::unordered_map<EntityId, std::string> nameMap;
|
||||
static std::unordered_map<EntityId, std::vector<uint8>> machineCodeMap;
|
||||
|
@ -113,21 +113,14 @@ static struct sigaction s_oldSa[SIGSYS + 1]; // SIGSYS = 31
|
||||
|
||||
void GetSignalHandler(int signal, siginfo_t *info, void *context)
|
||||
{
|
||||
[[maybe_unused]] ucontext_t *ucontext = reinterpret_cast<ucontext_t*>(context);
|
||||
[[maybe_unused]] mcontext_t &mcontext = ucontext->uc_mcontext;
|
||||
uintptr_t pc = 0;
|
||||
#if defined(PANDA_TARGET_AMD64)
|
||||
pc = static_cast<uintptr_t>(mcontext.gregs[REG_RIP]);
|
||||
#elif defined(PANDA_TARGET_ARM64)
|
||||
pc = static_cast<uintptr_t>(mcontext.pc);
|
||||
#if defined(__aarch64__) && !defined(PANDA_TARGET_MACOS) && !defined(PANDA_TARGET_IOS)
|
||||
ucontext_t *ucontext = static_cast<ucontext_t*>(context);
|
||||
uintptr_t fp = ucontext->uc_mcontext.regs[29];
|
||||
FrameIterator frame(reinterpret_cast<JSTaggedType *>(fp));
|
||||
ecmascript::JsStackInfo::BuildCrashInfo(false, frame.GetFrameType());
|
||||
#else
|
||||
ecmascript::JsStackInfo::BuildCrashInfo(false);
|
||||
#endif
|
||||
if (JsStackInfo::loader == nullptr) {
|
||||
ecmascript::JsStackInfo::BuildCrashInfo(false);
|
||||
} else if (!JsStackInfo::loader->InsideStub(pc) && !JsStackInfo::loader->InsideAOT(pc)) {
|
||||
ecmascript::JsStackInfo::BuildCrashInfo(false);
|
||||
} else {
|
||||
ecmascript::JsStackInfo::BuildCrashInfo(false, pc);
|
||||
}
|
||||
sigaction(signal, &s_oldSa[signal], nullptr);
|
||||
int rc = syscall(SYS_rt_tgsigqueueinfo, getpid(), syscall(SYS_gettid), info->si_signo, info);
|
||||
if (rc != 0) {
|
||||
|
@ -922,18 +922,18 @@ public:
|
||||
return glueData_.taskInfo_;
|
||||
}
|
||||
|
||||
void SetJitCodeMap(JSTaggedType exception, MachineCode* machineCode, std::string &methodName)
|
||||
void SetJitCodeMap(JSTaggedType exception, MachineCode* machineCode, std::string &methodName, uintptr_t offset)
|
||||
{
|
||||
auto it = jitCodeMaps_.find(exception);
|
||||
if (it != jitCodeMaps_.end()) {
|
||||
it->second->emplace(machineCode, methodName);
|
||||
it->second->push_back(std::make_tuple(machineCode, methodName, offset));
|
||||
} else {
|
||||
JitCodeMap *jitCode = new JitCodeMap {{machineCode, methodName}};
|
||||
JitCodeVector *jitCode = new JitCodeVector {std::make_tuple(machineCode, methodName, offset)};
|
||||
jitCodeMaps_.emplace(exception, jitCode);
|
||||
}
|
||||
}
|
||||
|
||||
std::map<JSTaggedType, JitCodeMap*> &GetJitCodeMaps()
|
||||
std::map<JSTaggedType, JitCodeVector*> &GetJitCodeMaps()
|
||||
{
|
||||
return jitCodeMaps_;
|
||||
}
|
||||
@ -1631,7 +1631,7 @@ private:
|
||||
#endif
|
||||
// Collect a map from JsError to MachineCode objects, JsError objects with stack frame generated by jit in the map.
|
||||
// It will be used to keep MachineCode objects alive (for dump) before JsError object be free.
|
||||
std::map<JSTaggedType, JitCodeMap*> jitCodeMaps_;
|
||||
std::map<JSTaggedType, JitCodeVector*> jitCodeMaps_;
|
||||
|
||||
std::atomic<bool> needTermination_ {false};
|
||||
std::atomic<bool> hasTerminated_ {false};
|
||||
|
@ -54,8 +54,8 @@ struct MachineCodeDesc {
|
||||
};
|
||||
|
||||
class MachineCode;
|
||||
using JitCodeMap = std::map<MachineCode*, std::string>;
|
||||
using JitCodeMapVisitor = std::function<void(std::map<JSTaggedType, JitCodeMap*>&)>;
|
||||
using JitCodeVector = std::vector<std::tuple<MachineCode*, std::string, uintptr_t>>;
|
||||
using JitCodeMapVisitor = std::function<void(std::map<JSTaggedType, JitCodeVector*>&)>;
|
||||
|
||||
// BaselineCode object layout:
|
||||
// +-----------------------------------+
|
||||
|
@ -57,7 +57,7 @@ void Marker::MarkJitCodeMap(uint32_t threadId)
|
||||
ProcessMarkStack(threadId);
|
||||
}
|
||||
|
||||
void Marker::HandleVisitJitCodeMap(uint32_t threadId, std::map<JSTaggedType, JitCodeMap *> &jitCodeMaps)
|
||||
void Marker::HandleVisitJitCodeMap(uint32_t threadId, std::map<JSTaggedType, JitCodeVector *> &jitCodeMaps)
|
||||
{
|
||||
if (!heap_->IsFullMark()) {
|
||||
return;
|
||||
@ -71,7 +71,7 @@ void Marker::HandleVisitJitCodeMap(uint32_t threadId, std::map<JSTaggedType, Jit
|
||||
continue;
|
||||
}
|
||||
for (auto jitCodeMap : *(it->second)) {
|
||||
auto jitCode = jitCodeMap.first;
|
||||
auto jitCode = std::get<0>(jitCodeMap);
|
||||
Region *jitCodeRegion = Region::ObjectAddressToRange(reinterpret_cast<TaggedObject *>(jitCode));
|
||||
if (!jitCodeRegion->Test(jitCode)) {
|
||||
MarkObject(threadId, jitCode);
|
||||
|
@ -46,7 +46,7 @@ public:
|
||||
void ProcessSnapshotRSet(uint32_t threadId); // for SemiGC
|
||||
void ProcessSnapshotRSetNoMarkStack(uint32_t threadId);
|
||||
void MarkJitCodeMap(uint32_t threadId);
|
||||
void HandleVisitJitCodeMap(uint32_t threadId, std::map<JSTaggedType, JitCodeMap *> &jitCodeMap);
|
||||
void HandleVisitJitCodeMap(uint32_t threadId, std::map<JSTaggedType, JitCodeVector *> &jitCodeMap);
|
||||
|
||||
virtual void ProcessMarkStack([[maybe_unused]] uint32_t threadId)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user