fix some bugs in dfx

Signed-off-by: wangyue <guowanlong@huawei.com>
Change-Id: I4d8e3e05b2586aa10a0ceaf854358b2cd47811a9
This commit is contained in:
wangyue 2024-06-11 15:15:30 +04:00
parent 9c4d2e765d
commit c98e819e10
7 changed files with 64 additions and 77 deletions

View File

@ -44,8 +44,7 @@ bool IsFastJitFunctionFrame(const FrameType frameType)
return frameType == FrameType::FASTJIT_FUNCTION_FRAME || frameType == FrameType::FASTJIT_FAST_CALL_FUNCTION_FRAME; 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, std::string JsStackInfo::BuildMethodTrace(Method *method, uint32_t pcOffset, bool enableStackSourceFile)
bool enableStackSourceFile)
{ {
std::string data; std::string data;
data.append(" at "); data.append(" at ");
@ -53,9 +52,6 @@ std::string JsStackInfo::BuildMethodTrace(Method *method, uint32_t pcOffset, con
if (name.empty()) { if (name.empty()) {
name = "anonymous"; name = "anonymous";
} }
if (IsFastJitFunctionFrame(frameType)) {
LOG_ECMA(ERROR) << "jit : js crash at method : " << name;
}
data += name; data += name;
data.append(" ("); data.append(" (");
// source file // source file
@ -93,8 +89,7 @@ std::string JsStackInfo::BuildMethodTrace(Method *method, uint32_t pcOffset, con
return data; return data;
} }
std::string JsStackInfo::BuildInlinedMethodTrace(const JSPandaFile *pf, std::map<uint32_t, uint32_t> &methodOffsets, std::string JsStackInfo::BuildInlinedMethodTrace(const JSPandaFile *pf, std::map<uint32_t, uint32_t> &methodOffsets)
const FrameType frameType)
{ {
std::string data; std::string data;
std::map<uint32_t, uint32_t>::reverse_iterator it; std::map<uint32_t, uint32_t>::reverse_iterator it;
@ -110,9 +105,6 @@ std::string JsStackInfo::BuildInlinedMethodTrace(const JSPandaFile *pf, std::map
} }
} }
data.append(" at "); data.append(" at ");
if (IsFastJitFunctionFrame(frameType)) {
LOG_ECMA(ERROR) << "jit : js crash at method : " << name;
}
data.append(name); data.append(name);
data.append(" (maybe inlined)."); data.append(" (maybe inlined).");
data.append(" depth: "); data.append(" depth: ");
@ -123,18 +115,6 @@ std::string JsStackInfo::BuildInlinedMethodTrace(const JSPandaFile *pf, std::map
return data; 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) void JsStackInfo::DumpJitCode(JSThread *thread)
{ {
JSTaggedType exception = thread->GetException().GetRawData(); JSTaggedType exception = thread->GetException().GetRawData();
@ -143,22 +123,30 @@ void JsStackInfo::DumpJitCode(JSThread *thread)
if (jitCode == jitCodeMaps.end()) { if (jitCode == jitCodeMaps.end()) {
return; return;
} }
std::set<MachineCode*> memos;
JsJitDumpElf jitDumpElf; JsJitDumpElf jitDumpElf;
jitDumpElf.Init(); jitDumpElf.Init();
int64 idx = 0; int64 idx = 0;
size_t offset = 0; size_t offset = 0;
for (auto it = jitCode->second->begin(); it != jitCode->second->end(); it++) { auto jitCodeVec = jitCodeMaps[exception];
auto machineCode = it->first; for (size_t i = 0; i < jitCodeVec->size(); i++) {
std::string methodName = it->second; auto item = (*jitCodeVec)[i];
char *funcAddr = reinterpret_cast<char *>(machineCode->GetFuncAddr()); auto machineCode = std::get<0>(item);
size_t len = machineCode->GetTextSize(); std::string methodName = std::get<1>(item);
std::vector<uint8> vec(len); uintptr_t pcOffset = std::get<2>(item);
if (memmove_s(vec.data(), len, funcAddr, len) != EOK) { auto res = memos.insert(machineCode);
LOG_ECMA(ERROR) << "Fail to get machineCode on function addr: " << funcAddr; 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 fileName = "jitCode-" + std::to_string(getpid());
std::string realOutPath; std::string realOutPath;
@ -172,7 +160,8 @@ void JsStackInfo::DumpJitCode(JSThread *thread)
close(fd); 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()); ASSERT(!jsErrorObj.GetTaggedValue().IsUndefined());
JSTaggedValue machineCodeTagVal = func->GetMachineCode(); JSTaggedValue machineCodeTagVal = func->GetMachineCode();
@ -181,7 +170,7 @@ void AssembleJitCodeMap(JSThread *thread, const JSHandle<JSObject> &jsErrorObj,
if (methodName.empty()) { if (methodName.empty()) {
methodName = "anonymous"; 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) std::string JsStackInfo::BuildJsStackTrace(JSThread *thread, bool needNative, const JSHandle<JSObject> &jsErrorObj)
@ -239,16 +228,15 @@ std::string JsStackInfo::BuildJsStackTraceInfo(JSThread *thread, Method *method,
FrameType frameType = it.GetFrameType(); FrameType frameType = it.GetFrameType();
if (IsFastJitFunctionFrame(frameType)) { if (IsFastJitFunctionFrame(frameType)) {
JSFunction *func = static_cast<JSFunction*>(it.GetFunction().GetTaggedObject()); JSFunction *func = static_cast<JSFunction*>(it.GetFunction().GetTaggedObject());
PrintJSCrashOffset(it.GetOptimizedReturnAddr(), func);
if (!jsErrorObj.GetTaggedValue().IsUndefined()) { if (!jsErrorObj.GetTaggedValue().IsUndefined()) {
AssembleJitCodeMap(thread, jsErrorObj, func, method); AssembleJitCodeMap(thread, jsErrorObj, func, method, it.GetOptimizedReturnAddr());
} }
} }
return BuildInlinedMethodTrace(pf, methodOffsets, frameType) + return BuildInlinedMethodTrace(pf, methodOffsets) +
BuildMethodTrace(method, pcOffset, frameType, thread->GetEnableStackSourceFile()); 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) { if (JsStackInfo::loader == nullptr || JsStackInfo::options == nullptr) {
LOG_ECMA(ERROR) << "loader or options Initial error."; LOG_ECMA(ERROR) << "loader or options Initial error.";
@ -262,8 +250,11 @@ void JsStackInfo::BuildCrashInfo(bool isJsCrash, uintptr_t pc, JSThread *thread)
ohos::RuntimeInfoType type; ohos::RuntimeInfoType type;
if (isJsCrash) { if (isJsCrash) {
type = ohos::RuntimeInfoType::JS; 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; type = ohos::RuntimeInfoType::AOT;
} else if (IsFastJitFunctionFrame(frameType)) {
type = ohos::RuntimeInfoType::JIT;
} else { } else {
type = ohos::RuntimeInfoType::OTHERS; type = ohos::RuntimeInfoType::OTHERS;
} }
@ -943,16 +934,20 @@ bool ArkWriteJitCode([[maybe_unused]] void *ctx, [[maybe_unused]] ReadMemFunc re
{ {
JsJitDumpElf jitDumpElf; JsJitDumpElf jitDumpElf;
jitDumpElf.Init(); jitDumpElf.Init();
std::set<uintptr_t> memos;
int64 idx = 0; int64 idx = 0;
size_t offset = 0; size_t offset = 0;
for (size_t i = 0; i < jitSize; i++) { for (size_t i = 0; i < jitSize; i++) {
uintptr_t methodId = jitCodeArray[i]; uintptr_t methodId = jitCodeArray[i];
std::vector<uint8> codeVec = JsStackInfo::machineCodeMap[EntityId(methodId)]; auto res = memos.insert(methodId);
std::string name = JsStackInfo::nameMap[EntityId(methodId)]; if (res.second) {
size_t len = codeVec.size(); std::vector<uint8> codeVec = JsStackInfo::machineCodeMap[EntityId(methodId)];
jitDumpElf.AppendData(codeVec); std::string name = JsStackInfo::nameMap[EntityId(methodId)];
jitDumpElf.AppendSymbolToSymTab(idx++, offset, len, name); size_t len = codeVec.size();
offset += len; jitDumpElf.AppendData(codeVec);
jitDumpElf.AppendSymbolToSymTab(idx++, offset, len, name);
offset += len;
}
} }
jitDumpElf.WriteJitElfFile(fd); jitDumpElf.WriteJitElfFile(fd);
JsStackInfo::nameMap.clear(); JsStackInfo::nameMap.clear();

View File

@ -155,8 +155,7 @@ private:
class JsStackInfo { class JsStackInfo {
public: public:
static std::string BuildInlinedMethodTrace(const JSPandaFile *pf, std::map<uint32_t, uint32_t> &methodOffsets, static std::string BuildInlinedMethodTrace(const JSPandaFile *pf, std::map<uint32_t, uint32_t> &methodOffsets);
const FrameType frameType);
static inline std::string BuildJsStackTrace(JSThread *thread, bool needNative) 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 // 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::string BuildJsStackTrace(JSThread *thread, bool needNative, const JSHandle<JSObject> &jsErrorObj);
static std::vector<JsFrameInfo> BuildJsStackInfo(JSThread *thread, bool currentStack = false); static std::vector<JsFrameInfo> BuildJsStackInfo(JSThread *thread, bool currentStack = false);
static std::string BuildMethodTrace(Method *method, uint32_t pcOffset, const FrameType frameType, static std::string BuildMethodTrace(Method *method, uint32_t pcOffset, bool enableStackSourceFile = true);
bool enableStackSourceFile = true);
static AOTFileManager *loader; static AOTFileManager *loader;
static JSRuntimeOptions *options; 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) 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::string> nameMap;
static std::unordered_map<EntityId, std::vector<uint8>> machineCodeMap; static std::unordered_map<EntityId, std::vector<uint8>> machineCodeMap;

View File

@ -111,21 +111,14 @@ static struct sigaction s_oldSa[SIGSYS + 1]; // SIGSYS = 31
void GetSignalHandler(int signal, siginfo_t *info, void *context) void GetSignalHandler(int signal, siginfo_t *info, void *context)
{ {
[[maybe_unused]] ucontext_t *ucontext = reinterpret_cast<ucontext_t*>(context); #if defined(__aarch64__) && !defined(PANDA_TARGET_MACOS) && !defined(PANDA_TARGET_IOS)
[[maybe_unused]] mcontext_t &mcontext = ucontext->uc_mcontext; ucontext_t *ucontext = static_cast<ucontext_t*>(context);
uintptr_t pc = 0; uintptr_t fp = ucontext->uc_mcontext.regs[29];
#if defined(PANDA_TARGET_AMD64) FrameIterator frame(reinterpret_cast<JSTaggedType *>(fp));
pc = static_cast<uintptr_t>(mcontext.gregs[REG_RIP]); ecmascript::JsStackInfo::BuildCrashInfo(false, frame.GetFrameType());
#elif defined(PANDA_TARGET_ARM64) #else
pc = static_cast<uintptr_t>(mcontext.pc); ecmascript::JsStackInfo::BuildCrashInfo(false);
#endif #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); sigaction(signal, &s_oldSa[signal], nullptr);
int rc = syscall(SYS_rt_tgsigqueueinfo, getpid(), syscall(SYS_gettid), info->si_signo, info); int rc = syscall(SYS_rt_tgsigqueueinfo, getpid(), syscall(SYS_gettid), info->si_signo, info);
if (rc != 0) { if (rc != 0) {

View File

@ -922,18 +922,18 @@ public:
return glueData_.taskInfo_; 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); auto it = jitCodeMaps_.find(exception);
if (it != jitCodeMaps_.end()) { if (it != jitCodeMaps_.end()) {
it->second->emplace(machineCode, methodName); it->second->push_back(std::make_tuple(machineCode, methodName, offset));
} else { } else {
JitCodeMap *jitCode = new JitCodeMap {{machineCode, methodName}}; JitCodeVector *jitCode = new JitCodeVector {std::make_tuple(machineCode, methodName, offset)};
jitCodeMaps_.emplace(exception, jitCode); jitCodeMaps_.emplace(exception, jitCode);
} }
} }
std::map<JSTaggedType, JitCodeMap*> &GetJitCodeMaps() std::map<JSTaggedType, JitCodeVector*> &GetJitCodeMaps()
{ {
return jitCodeMaps_; return jitCodeMaps_;
} }
@ -1626,7 +1626,7 @@ private:
#endif #endif
// Collect a map from JsError to MachineCode objects, JsError objects with stack frame generated by jit in the map. // 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. // 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> needTermination_ {false};
std::atomic<bool> hasTerminated_ {false}; std::atomic<bool> hasTerminated_ {false};

View File

@ -54,8 +54,8 @@ struct MachineCodeDesc {
}; };
class MachineCode; class MachineCode;
using JitCodeMap = std::map<MachineCode*, std::string>; using JitCodeVector = std::vector<std::tuple<MachineCode*, std::string, uintptr_t>>;
using JitCodeMapVisitor = std::function<void(std::map<JSTaggedType, JitCodeMap*>&)>; using JitCodeMapVisitor = std::function<void(std::map<JSTaggedType, JitCodeVector*>&)>;
// BaselineCode object layout: // BaselineCode object layout:
// +-----------------------------------+ // +-----------------------------------+

View File

@ -57,7 +57,7 @@ void Marker::MarkJitCodeMap(uint32_t threadId)
ProcessMarkStack(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()) { if (!heap_->IsFullMark()) {
return; return;
@ -71,7 +71,7 @@ void Marker::HandleVisitJitCodeMap(uint32_t threadId, std::map<JSTaggedType, Jit
continue; continue;
} }
for (auto jitCodeMap : *(it->second)) { for (auto jitCodeMap : *(it->second)) {
auto jitCode = jitCodeMap.first; auto jitCode = std::get<0>(jitCodeMap);
Region *jitCodeRegion = Region::ObjectAddressToRange(reinterpret_cast<TaggedObject *>(jitCode)); Region *jitCodeRegion = Region::ObjectAddressToRange(reinterpret_cast<TaggedObject *>(jitCode));
if (!jitCodeRegion->Test(jitCode)) { if (!jitCodeRegion->Test(jitCode)) {
MarkObject(threadId, jitCode); MarkObject(threadId, jitCode);

View File

@ -46,7 +46,7 @@ public:
void ProcessSnapshotRSet(uint32_t threadId); // for SemiGC void ProcessSnapshotRSet(uint32_t threadId); // for SemiGC
void ProcessSnapshotRSetNoMarkStack(uint32_t threadId); void ProcessSnapshotRSetNoMarkStack(uint32_t threadId);
void MarkJitCodeMap(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) virtual void ProcessMarkStack([[maybe_unused]] uint32_t threadId)
{ {