From 31d38c864c7c93585f51a0e16d063bcf5a36b94b Mon Sep 17 00:00:00 2001 From: zhupu Date: Fri, 3 Jan 2025 10:21:35 +0800 Subject: [PATCH] parse symbol and print stack modify Signed-off-by: zhupu --- interfaces/innerkits/unwinder/unwinder.cpp | 4 +- tools/process_dump/dfx_fault_stack.cpp | 16 ---- tools/process_dump/dfx_thread.cpp | 7 +- tools/process_dump/dfx_thread.h | 4 +- tools/process_dump/dfx_unwind_remote.cpp | 105 +++++++++++++++------ tools/process_dump/dfx_unwind_remote.h | 7 +- tools/process_dump/process_dumper.cpp | 39 ++++---- tools/process_dump/process_dumper.h | 1 + 8 files changed, 116 insertions(+), 67 deletions(-) diff --git a/interfaces/innerkits/unwinder/unwinder.cpp b/interfaces/innerkits/unwinder/unwinder.cpp index dcc8eb133..99a4e2376 100644 --- a/interfaces/innerkits/unwinder/unwinder.cpp +++ b/interfaces/innerkits/unwinder/unwinder.cpp @@ -1392,7 +1392,9 @@ void Unwinder::Impl::GetFramesByPcs(std::vector& frames, std::vector maps, std::vectorname; - int64_t loadBias = 0; - struct stat st; - if (stat(map->name.c_str(), &st) == 0 && (st.st_mode & S_IFREG)) { - auto elf = DfxElf::Create(frame.mapName); - if (elf == nullptr || !elf->IsValid()) { - DFXLOGE("%{public}s : Failed to create DfxElf, elf path(%{public}s).", __func__, - frame.mapName.c_str()); - continue; - } - loadBias = elf->GetLoadBias(); - frame.buildId = elf->GetBuildId(); - } else { - DFXLOGW("%{public}s : mapName(%{public}s) is not file.", __func__, frame.mapName.c_str()); - } - - frame.relPc = frame.pc - map->begin + map->offset + static_cast(loadBias); frames.emplace_back(frame); hasAddFrame = true; constexpr int MAX_VALID_ADDRESS_NUM = 32; diff --git a/tools/process_dump/dfx_thread.cpp b/tools/process_dump/dfx_thread.cpp index 1dec8154a..937c898ca 100644 --- a/tools/process_dump/dfx_thread.cpp +++ b/tools/process_dump/dfx_thread.cpp @@ -74,7 +74,7 @@ void DfxThread::AddFrame(DfxFrame& frame) frames_.emplace_back(frame); } -const std::vector& DfxThread::GetFrames() const +std::vector& DfxThread::GetFrames() { return frames_; } @@ -151,5 +151,10 @@ std::shared_ptr DfxThread::GetFaultStack() const { return faultStack_; } + +void DfxThread::ParseSymbol(std::shared_ptr unwinder) +{ + unwinder->FillFrames(frames_); +} } // namespace HiviewDFX } // nampespace OHOS diff --git a/tools/process_dump/dfx_thread.h b/tools/process_dump/dfx_thread.h index c2e720aa2..18ef0b9cf 100644 --- a/tools/process_dump/dfx_thread.h +++ b/tools/process_dump/dfx_thread.h @@ -26,6 +26,7 @@ #include "dfx_frame.h" #include "dfx_maps.h" #include "dfx_regs.h" +#include "unwinder.h" namespace OHOS { namespace HiviewDFX { @@ -46,9 +47,10 @@ public: std::shared_ptr GetThreadRegs() const; void SetThreadRegs(const std::shared_ptr ®s); void AddFrame(DfxFrame& frame); - const std::vector& GetFrames() const; + std::vector& GetFrames(); void SetFrames(const std::vector& frames); void InitFaultStack(bool needParseStack = false); + void ParseSymbol(std::shared_ptr unwinder); std::shared_ptr GetFaultStack() const; std::string ToString() const; diff --git a/tools/process_dump/dfx_unwind_remote.cpp b/tools/process_dump/dfx_unwind_remote.cpp index f7e6fe66a..06c16d83f 100644 --- a/tools/process_dump/dfx_unwind_remote.cpp +++ b/tools/process_dump/dfx_unwind_remote.cpp @@ -74,22 +74,57 @@ DfxUnwindRemote &DfxUnwindRemote::GetInstance() return ins; } -bool DfxUnwindRemote::UnwindProcess(std::shared_ptr request, std::shared_ptr process, - std::shared_ptr unwinder, pid_t vmPid) +void DfxUnwindRemote::ParseSymbol(std::shared_ptr request, std::shared_ptr process, + std::shared_ptr unwinder) { - DFX_TRACE_SCOPED("UnwindProcess"); - if (process == nullptr || unwinder == nullptr) { - DFXLOGW("%{public}s::process or unwinder is not initialized.", __func__); - return false; + if (request == nullptr || process == nullptr || unwinder == nullptr) { + return; } - SetCrashProcInfo(process->processInfo_.processName, process->processInfo_.pid, - process->processInfo_.uid); - int unwCnt = UnwindKeyThread(request, process, unwinder, vmPid) ? 1 : 0; + std::shared_ptr unwThread = process->keyThread_; + if (ProcessDumper::GetInstance().IsCrash() && (process->vmThread_ != nullptr)) { + unwThread = process->vmThread_; + } + DFX_TRACE_START("ParseSymbol keyThread:%d", unwThread->threadInfo_.nsTid); + unwThread->ParseSymbol(unwinder); + DFX_TRACE_FINISH(); + if (ProcessDumper::GetInstance().IsCrash() || request->siginfo.si_value.sival_int == 0) { + for (auto &thread : process->GetOtherThreads()) { + DFX_TRACE_START("ParseSymbol otherThread:%d", thread->threadInfo_.nsTid); + thread->ParseSymbol(unwinder); + DFX_TRACE_FINISH(); + } + } +} - // dumpt -p -t will not unwind other thread +void DfxUnwindRemote::PrintUnwindResultInfo(std::shared_ptr request, + std::shared_ptr process, + std::shared_ptr unwinder, + pid_t vmPid) +{ + if (request == nullptr || process == nullptr || unwinder == nullptr) { + return; + } + + // print key thread + Printer::PrintDumpHeader(request, process, unwinder); + Printer::PrintThreadHeaderByConfig(process->keyThread_, true); + Printer::PrintThreadBacktraceByConfig(process->keyThread_, true); + if (ProcessDumper::GetInstance().IsCrash()) { + // Registers of unwThread has been changed, we should print regs from request context. + process->regs_ = DfxRegs::CreateFromUcontext(request->context); + Printer::PrintRegsByConfig(process->regs_); + Printer::PrintLongInformation(process->extraCrashInfo); + // print other thread head info + Printer::PrintOtherThreadHeaderByConfig(); + } + + // print other thread if (ProcessDumper::GetInstance().IsCrash() || request->siginfo.si_value.sival_int == 0) { - unwCnt += UnwindOtherThread(process, unwinder, vmPid); + for (auto &thread : process->GetOtherThreads()) { + Printer::PrintThreadHeaderByConfig(thread, false); + Printer::PrintThreadBacktraceByConfig(thread, false); + } } if (ProcessDumper::GetInstance().IsCrash()) { @@ -112,6 +147,35 @@ bool DfxUnwindRemote::UnwindProcess(std::shared_ptr request, Printer::PrintProcessMapsByConfig(unwinder->GetMaps()); Printer::PrintLongInformation(process->openFiles); } +} + +void DfxUnwindRemote::ProcessAfterUnwind(std::shared_ptr request, + std::shared_ptr process, + std::shared_ptr unwinder, + pid_t vmPid) +{ + ParseSymbol(request, process, unwinder); + PrintUnwindResultInfo(request, process, unwinder, vmPid); +} + +bool DfxUnwindRemote::UnwindProcess(std::shared_ptr request, std::shared_ptr process, + std::shared_ptr unwinder, pid_t vmPid) +{ + DFX_TRACE_SCOPED("UnwindProcess"); + if (process == nullptr || unwinder == nullptr) { + DFXLOGW("%{public}s::process or unwinder is not initialized.", __func__); + return false; + } + + unwinder->EnableFillFrames(false); + SetCrashProcInfo(process->processInfo_.processName, process->processInfo_.pid, + process->processInfo_.uid); + int unwCnt = UnwindKeyThread(request, process, unwinder, vmPid) ? 1 : 0; + + // dumpt -p -t will not unwind other thread + if (ProcessDumper::GetInstance().IsCrash() || request->siginfo.si_value.sival_int == 0) { + unwCnt += UnwindOtherThread(process, unwinder, vmPid); + } if (isVmProcAttach) { DfxPtrace::Detach(vmPid); @@ -154,16 +218,6 @@ bool DfxUnwindRemote::UnwindKeyThread(std::shared_ptr reques process->processInfo_.uid, CrashExceptionCode::CRASH_UNWIND_ESTACK); process->extraCrashInfo += ("ExtraCrashInfo(Unwindstack):\n" + unwindAsyncThread->unwindFailTip); } - - Printer::PrintDumpHeader(request, process, unwinder); - Printer::PrintThreadHeaderByConfig(process->keyThread_, true); - Printer::PrintThreadBacktraceByConfig(unwThread, true); - if (ProcessDumper::GetInstance().IsCrash()) { - // Registers of unwThread has been changed, we should print regs from request context. - process->regs_ = DfxRegs::CreateFromUcontext(request->context); - Printer::PrintRegsByConfig(process->regs_); - Printer::PrintLongInformation(process->extraCrashInfo); - } return result; } @@ -174,15 +228,9 @@ int DfxUnwindRemote::UnwindOtherThread(std::shared_ptr process, std: return 0; } unwinder->SetIsJitCrashFlag(false); - size_t index = 0; int unwCnt = 0; for (auto &thread : process->GetOtherThreads()) { - if ((index == 0) && ProcessDumper::GetInstance().IsCrash()) { - Printer::PrintOtherThreadHeaderByConfig(); - } - if (isVmProcAttach || thread->Attach(PTRACE_ATTATCH_OTHER_THREAD_TIMEOUT)) { - Printer::PrintThreadHeaderByConfig(thread, false); auto regs = thread->GetThreadRegs(); unwinder->SetRegs(regs); bool withRegs = regs != nullptr; @@ -190,7 +238,6 @@ int DfxUnwindRemote::UnwindOtherThread(std::shared_ptr process, std: DFXLOGD("%{public}s, unwind tid(%{public}d) start", __func__, tid); if (isVmProcAttach && !withRegs) { GetThreadKernelStack(thread); - Printer::PrintThreadBacktraceByConfig(thread, false); continue; } auto pid = (vmPid != 0 && isVmProcAttach) ? vmPid : tid; @@ -211,9 +258,7 @@ int DfxUnwindRemote::UnwindOtherThread(std::shared_ptr process, std: } else { unwCnt++; } - Printer::PrintThreadBacktraceByConfig(thread, false); } - index++; } return unwCnt; } diff --git a/tools/process_dump/dfx_unwind_remote.h b/tools/process_dump/dfx_unwind_remote.h index 5ca75a144..de7d01808 100644 --- a/tools/process_dump/dfx_unwind_remote.h +++ b/tools/process_dump/dfx_unwind_remote.h @@ -39,7 +39,8 @@ public: bool UnwindProcess(std::shared_ptr request, std::shared_ptr process, std::shared_ptr unwinder, pid_t vmPid = 0); bool InitProcessAllThreadRegs(std::shared_ptr request, std::shared_ptr process); - + void ProcessAfterUnwind(std::shared_ptr request, std::shared_ptr process, + std::shared_ptr unwinder, pid_t vmPid = 0); private: DfxUnwindRemote() = default; bool UnwindKeyThread(std::shared_ptr request, std::shared_ptr process, @@ -50,6 +51,10 @@ private: DISALLOW_COPY_AND_MOVE(DfxUnwindRemote); bool InitTargetKeyThreadRegs(std::shared_ptr request, std::shared_ptr process); void InitOtherThreadRegs(std::shared_ptr process); + void ParseSymbol(std::shared_ptr request, std::shared_ptr process, + std::shared_ptr unwinder); + void PrintUnwindResultInfo(std::shared_ptr request, std::shared_ptr process, + std::shared_ptr unwinder, pid_t vmPid); bool isVmProcAttach = false; }; } // namespace HiviewDFX diff --git a/tools/process_dump/process_dumper.cpp b/tools/process_dump/process_dumper.cpp index 71b6b078d..869febe03 100644 --- a/tools/process_dump/process_dumper.cpp +++ b/tools/process_dump/process_dumper.cpp @@ -412,21 +412,6 @@ void ProcessDumper::Dump() startTime_ = GetTimeMillisec(); std::shared_ptr request = std::make_shared(); resDump_ = DumpProcess(request); - if (process_ == nullptr) { - DFXLOGE("Dump process failed, please check permission and whether pid is valid."); - } else { - if (isCrash_ && process_->vmThread_ != nullptr) { - process_->vmThread_->Detach(); - } - if (!IsDumpSignal(request->siginfo.si_signo) && (request->dumpMode == FUSION_MODE)) { - InfoCrashUnwindResult(request, resDump_ == DumpErrorCode::DUMP_ESUCCESS); - BlockCrashProcExit(request); - } - if (process_->keyThread_ != nullptr) { - process_->keyThread_->Detach(); - } - process_->Detach(); - } std::string jsonInfo; if (isJsonDump_ || isCrash_) { @@ -679,11 +664,30 @@ bool ProcessDumper::Unwind(std::shared_ptr request, int &dum dumpRes = DumpErrorCode::DUMP_ESTOPUNWIND; return false; } - - UnwindWriteJit(*request); return true; } +void ProcessDumper::FinishUnwind(std::shared_ptr request, pid_t vmPid) +{ + if (process_ == nullptr) { + DFXLOGE("Dump process failed, please check permission and whether pid is valid."); + } else { + if (isCrash_ && process_->vmThread_ != nullptr) { + process_->vmThread_->Detach(); + } + if (!IsDumpSignal(request->siginfo.si_signo) && (request->dumpMode == FUSION_MODE)) { + InfoCrashUnwindResult(request, resDump_ == DumpErrorCode::DUMP_ESUCCESS); + BlockCrashProcExit(request); + } + if (process_->keyThread_ != nullptr) { + process_->keyThread_->Detach(); + } + process_->Detach(); + DfxUnwindRemote::GetInstance().ProcessAfterUnwind(request, process_, unwinder_, vmPid); + UnwindWriteJit(*request); + } +} + int ProcessDumper::DumpProcess(std::shared_ptr request) { DFX_TRACE_SCOPED("DumpProcess"); @@ -729,6 +733,7 @@ int ProcessDumper::DumpProcess(std::shared_ptr request) if (!Unwind(request, dumpRes, vmPid)) { DFXLOGE("unwind fail."); } + FinishUnwind(request, vmPid); } while (false); if (dumpRes == DumpErrorCode::DUMP_ESUCCESS && !IsTargetProcessAlive(request)) { dumpRes = DumpErrorCode::DUMP_EGETPPID; diff --git a/tools/process_dump/process_dumper.h b/tools/process_dump/process_dumper.h index 376dff42a..6ba2560e2 100644 --- a/tools/process_dump/process_dumper.h +++ b/tools/process_dump/process_dumper.h @@ -67,6 +67,7 @@ private: std::string ReadCrashObjMemory(pid_t tid, uintptr_t addr, size_t length) const; void GetCrashObj(std::shared_ptr request); void ReportAddrSanitizer(ProcessDumpRequest &request, std::string &jsonInfo); + void FinishUnwind(std::shared_ptr request, pid_t vmPid); private: std::shared_ptr process_ = nullptr; -- Gitee