Skip to content

Commit 217c214

Browse files
Copilotxusheng6
authored andcommitted
Enhance the debugger status bar with function and address information using stack trace symbolization (#842)
1 parent 4f40cf1 commit 217c214

1 file changed

Lines changed: 66 additions & 2 deletions

File tree

ui/statusbar.cpp

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ limitations under the License.
2323
using namespace BinaryNinja;
2424
using namespace BinaryNinjaDebuggerAPI;
2525

26-
constexpr int STATUS_STRING_MAX_LEN = 50;
26+
constexpr int STATUS_STRING_MAX_LEN = 100;
2727

2828
DebuggerStatusBarWidget::DebuggerStatusBarWidget(QWidget* parent, ViewFrame* frame, BinaryViewRef data) :
2929
QWidget(parent), m_parent(parent), m_view(frame)
@@ -105,7 +105,71 @@ void DebuggerStatusBarWidget::updateStatusText(const DebuggerEvent& event)
105105
{
106106
DebugStopReason reason = event.data.targetStoppedData.reason;
107107
const std::string reasonString = DebuggerController::GetDebugStopReasonString(reason);
108-
setStatusText(QString::fromStdString(fmt::format("Stopped ({})", reasonString)));
108+
109+
std::string statusMessage = fmt::format("Stopped ({})", reasonString);
110+
111+
// Add address and symbol information if debugger is available
112+
if (m_debugger) {
113+
// Get current instruction pointer
114+
uint64_t currentIP = m_debugger->IP();
115+
116+
// Get the current thread's stack frames to retrieve function information
117+
// (same approach as stack trace widget)
118+
auto activeThread = m_debugger->GetActiveThread();
119+
auto frames = m_debugger->GetFramesOfThread(activeThread.m_tid);
120+
std::string locationString;
121+
122+
if (!frames.empty()) {
123+
// Use the first frame (current execution context) for function information
124+
const auto& currentFrame = frames[0];
125+
126+
// Format function + offset the same way as stack trace widget
127+
auto trimmedFunctionName = currentFrame.m_functionName;
128+
auto prefix = currentFrame.m_module + '!';
129+
if (trimmedFunctionName.compare(0, prefix.size(), prefix) == 0)
130+
trimmedFunctionName.erase(0, prefix.size());
131+
132+
// Calculate offset from function start
133+
uint64_t offset = currentFrame.m_pc - currentFrame.m_functionStart;
134+
if (offset != 0 && !trimmedFunctionName.empty()) {
135+
locationString = fmt::format(" at 0x{:x} ({} + 0x{:x})", currentIP, trimmedFunctionName, offset);
136+
} else if (offset == 0 && !trimmedFunctionName.empty()) {
137+
locationString = fmt::format(" at 0x{:x} ({})", currentIP, trimmedFunctionName);
138+
} else {
139+
// Fall back to module + offset when function info is not available
140+
auto moduleInfo = m_debugger->AbsoluteAddressToRelative(currentIP);
141+
if (!moduleInfo.module.empty()) {
142+
// Extract just the filename from the full path
143+
std::string moduleName = moduleInfo.module;
144+
size_t lastSlash = moduleName.find_last_of("/\\");
145+
if (lastSlash != std::string::npos) {
146+
moduleName = moduleName.substr(lastSlash + 1);
147+
}
148+
locationString = fmt::format(" at 0x{:x} ({} + 0x{:x})", currentIP, moduleName, moduleInfo.offset);
149+
} else {
150+
locationString = fmt::format(" at 0x{:x} (?? + 0x{:x})", currentIP, currentIP);
151+
}
152+
}
153+
} else {
154+
// Fall back to module + offset when no frames are available
155+
auto moduleInfo = m_debugger->AbsoluteAddressToRelative(currentIP);
156+
if (!moduleInfo.module.empty()) {
157+
// Extract just the filename from the full path
158+
std::string moduleName = moduleInfo.module;
159+
size_t lastSlash = moduleName.find_last_of("/\\");
160+
if (lastSlash != std::string::npos) {
161+
moduleName = moduleName.substr(lastSlash + 1);
162+
}
163+
locationString = fmt::format(" at 0x{:x} ({} + 0x{:x})", currentIP, moduleName, moduleInfo.offset);
164+
} else {
165+
locationString = fmt::format(" at 0x{:x} (?? + 0x{:x})", currentIP, currentIP);
166+
}
167+
}
168+
169+
statusMessage += locationString;
170+
}
171+
172+
setStatusText(QString::fromStdString(statusMessage));
109173
break;
110174
}
111175
case TargetExitedEventType:

0 commit comments

Comments
 (0)