From d1f0e0e74824e1b13e1315b3371ffea3045ec3b7 Mon Sep 17 00:00:00 2001 From: Xusheng Date: Fri, 11 Oct 2024 16:43:46 +0800 Subject: [PATCH] Use the function name info from the analysis to augment the stack trace. Fix https://github.com/Vector35/debugger/issues/353 --- core/debuggerstate.cpp | 42 +++++++++++++++++++++++++++++++++++++++++- core/debuggerstate.h | 2 ++ ui/threadframes.h | 15 ++++++++++++--- 3 files changed, 55 insertions(+), 4 deletions(-) diff --git a/core/debuggerstate.cpp b/core/debuggerstate.cpp index ee0f421..ffce244 100644 --- a/core/debuggerstate.cpp +++ b/core/debuggerstate.cpp @@ -149,6 +149,38 @@ void DebuggerThreads::MarkDirty() } +void DebuggerThreads::SymbolizeFrames(std::vector& frames) +{ + if (!m_state || !m_state->GetController()) + return; + + auto data = m_state->GetController()->GetData(); + if (!data) + return; + + for (DebugFrame& frame: frames) + { + // Try to find a better symbol than the one provided by the debugger backend + auto funcs = data->GetAnalysisFunctionsContainingAddress(frame.m_pc); + if (!funcs.empty()) + { + auto func = funcs[0]; + if (!func) + continue; + + frame.m_functionStart = func->GetStart(); + auto symbol = func->GetSymbol(); + if (symbol) + frame.m_functionName = symbol->GetShortName(); + else + frame.m_functionName = fmt::format("sub_{:x}", func->GetStart()); + + continue; + } + } +} + + void DebuggerThreads::Update() { if (!m_state) @@ -166,7 +198,9 @@ void DebuggerThreads::Update() std::vector newThreads = adapter->GetThreadList(); for (auto thread = newThreads.begin(); thread != newThreads.end(); thread++) { - m_frames[thread->m_tid] = adapter->GetFramesOfThread(thread->m_tid); + auto frames = adapter->GetFramesOfThread(thread->m_tid); + SymbolizeFrames(frames); + m_frames[thread->m_tid] = frames; // update thread states in new thread list auto oldThread = std::find_if(m_threads.begin(), m_threads.end(), [&](DebugThread const& t) { @@ -957,6 +991,12 @@ void DebuggerState::SetInputFile(const std::string& path) } +std::string DebuggerState::GetInputFile() +{ + return m_inputFile; +} + + void DebuggerState::SetWorkingDirectory(const std::string& directory) { m_workingDirectory = directory; diff --git a/core/debuggerstate.h b/core/debuggerstate.h index bcec78f..49b1c90 100644 --- a/core/debuggerstate.h +++ b/core/debuggerstate.h @@ -114,6 +114,7 @@ namespace BinaryNinjaDebugger { std::vector GetFramesOfThread(uint32_t tid); bool SuspendThread(std::uint32_t tid); bool ResumeThread(std::uint32_t tid); + void SymbolizeFrames(std::vector& frames); }; enum MemoryByteCacheStatus @@ -212,6 +213,7 @@ namespace BinaryNinjaDebugger { void SetAdapterType(const std::string& adapter); void SetExecutablePath(const std::string& path); void SetInputFile(const std::string& path); + std::string GetInputFile(); void SetWorkingDirectory(const std::string& directory); void SetCommandLineArguments(const std::string& arguments); void SetRemoteHost(const std::string& host); diff --git a/ui/threadframes.h b/ui/threadframes.h index be66749..348f3af 100644 --- a/ui/threadframes.h +++ b/ui/threadframes.h @@ -30,6 +30,7 @@ limitations under the License. #include "debuggerapi.h" #include "inttypes.h" #include "ui.h" +#include "fmt/format.h" using namespace BinaryNinjaDebuggerAPI; @@ -49,10 +50,18 @@ class FrameItem m_isFrame(true), m_tid(thread.m_tid), m_threadPc(thread.m_rip), m_frameIndex(frame.m_index), m_module(frame.m_module), m_framePc(frame.m_pc), m_sp(frame.m_sp), m_fp(frame.m_fp), m_parentItem(parentItem) { - uint64_t offset = frame.m_pc - frame.m_functionStart; - QString funcName = QString::asprintf("%s + 0x%" PRIx64, frame.m_functionName.c_str(), offset); + // WinDbg always reports the function name with the module prefix, we remove it for conciseness + auto trimmedFunctionName = frame.m_functionName; + auto prefix = m_module + '!'; + if (trimmedFunctionName.compare(0, prefix.size(), prefix) == 0) + trimmedFunctionName.erase(0, prefix.size()); - m_function = funcName.toStdString(); + // Only show the offset if it is not 0x0 + uint64_t offset = frame.m_pc - frame.m_functionStart; + if (offset != 0) + m_function = fmt::format("{} + {:#x}", trimmedFunctionName, offset); + else + m_function = trimmedFunctionName; } ~FrameItem();