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;
}
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 ");
@ -53,9 +52,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
@ -93,8 +89,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;
@ -110,9 +105,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: ");
@ -123,18 +115,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();
@ -143,22 +123,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;
@ -172,7 +160,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();
@ -181,7 +170,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)
@ -239,16 +228,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 Initial error.";
@ -262,8 +250,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();

View File

@ -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;

View File

@ -111,21 +111,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) {

View File

@ -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_;
}
@ -1626,7 +1626,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};

View File

@ -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:
// +-----------------------------------+

View File

@ -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);

View File

@ -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)
{