From 002e9c8802e93766f4cd544432779e57f706a929 Mon Sep 17 00:00:00 2001 From: Adam Higerd Date: Fri, 31 Jul 2020 20:01:23 -0500 Subject: [PATCH] Debugger: look up symbols in stack traces --- include/mgba/internal/debugger/stack-trace.h | 8 ++- src/debugger/stack-trace.c | 53 +++++++++++++++----- 2 files changed, 48 insertions(+), 13 deletions(-) diff --git a/include/mgba/internal/debugger/stack-trace.h b/include/mgba/internal/debugger/stack-trace.h index 443faa64c..11268aae3 100644 --- a/include/mgba/internal/debugger/stack-trace.h +++ b/include/mgba/internal/debugger/stack-trace.h @@ -14,6 +14,8 @@ CXX_GUARD_START #include #include +struct mDebuggerSymbols; + enum mStackTraceMode { STACK_TRACE_DISABLED = 0, STACK_TRACE_ENABLED = 1, @@ -23,8 +25,11 @@ enum mStackTraceMode { }; struct mStackFrame { + int callSegment; uint32_t callAddress; + int entrySegment; uint32_t entryAddress; + int frameBaseSegment; uint32_t frameBaseAddress; void* regs; bool finished; @@ -47,8 +52,9 @@ void mStackTraceDeinit(struct mStackTrace* stack); void mStackTraceClear(struct mStackTrace* stack); size_t mStackTraceGetDepth(struct mStackTrace* stack); struct mStackFrame* mStackTracePush(struct mStackTrace* stack, uint32_t pc, uint32_t destAddress, uint32_t sp, void* regs); +struct mStackFrame* mStackTracePushSegmented(struct mStackTrace* stack, int pcSegment, uint32_t pc, int destSegment, uint32_t destAddress, int spSegment, uint32_t sp, void* regs); struct mStackFrame* mStackTraceGetFrame(struct mStackTrace* stack, uint32_t frame); -void mStackTraceFormatFrame(struct mStackTrace* stack, uint32_t frame, char* out, size_t* length); +void mStackTraceFormatFrame(struct mStackTrace* stack, struct mDebuggerSymbols* st, uint32_t frame, char* out, size_t* length); void mStackTracePop(struct mStackTrace* stack); CXX_GUARD_END diff --git a/src/debugger/stack-trace.c b/src/debugger/stack-trace.c index 4d6357698..a10c0bde8 100644 --- a/src/debugger/stack-trace.c +++ b/src/debugger/stack-trace.c @@ -4,6 +4,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include +#include #include @@ -40,8 +41,11 @@ size_t mStackTraceGetDepth(struct mStackTrace* stack) { struct mStackFrame* mStackTracePush(struct mStackTrace* stack, uint32_t pc, uint32_t destAddress, uint32_t sp, void* regs) { struct mStackFrame* frame = mStackFramesAppend(&stack->stack); + frame->callSegment = -1; frame->callAddress = pc; + frame->entrySegment = -1; frame->entryAddress = destAddress; + frame->frameBaseSegment = -1; frame->frameBaseAddress = sp; frame->regs = malloc(stack->registersSize); frame->finished = false; @@ -51,6 +55,14 @@ struct mStackFrame* mStackTracePush(struct mStackTrace* stack, uint32_t pc, uint return frame; } +struct mStackFrame* mStackTracePushSegmented(struct mStackTrace* stack, int pcSegment, uint32_t pc, int destSegment, uint32_t destAddress, int spSegment, uint32_t sp, void* regs) { + struct mStackFrame* frame = mStackTracePush(stack, pc, destAddress, sp, regs); + frame->callSegment = pcSegment; + frame->entrySegment = destSegment; + frame->frameBaseSegment = spSegment; + return frame; +} + struct mStackFrame* mStackTraceGetFrame(struct mStackTrace* stack, uint32_t frame) { size_t depth = mStackTraceGetDepth(stack); if (frame >= depth) { @@ -59,20 +71,26 @@ struct mStackFrame* mStackTraceGetFrame(struct mStackTrace* stack, uint32_t fram return mStackFramesGetPointer(&stack->stack, depth - frame - 1); } -void mStackTraceFormatFrame(struct mStackTrace* stack, uint32_t frame, char* out, size_t* length) { +void mStackTraceFormatFrame(struct mStackTrace* stack, struct mDebuggerSymbols* st, uint32_t frame, char* out, size_t* length) { struct mStackFrame* stackFrame = mStackTraceGetFrame(stack, frame); struct mStackFrame* prevFrame = mStackTraceGetFrame(stack, frame + 1); size_t written = snprintf(out, *length, "#%d ", frame); CHECK_LENGTH(); - if (prevFrame) { - written += snprintf(out + written, *length - written, "0x%08X ", prevFrame->entryAddress); - CHECK_LENGTH(); - } if (!stackFrame) { - written += snprintf(out + written, *length - written, "no stack frame available)\n"); + written += snprintf(out + written, *length - written, "(no stack frame available)\n"); *length = written; return; - } else if (stack->formatRegisters) { + } + const char* functionName = mDebuggerSymbolReverseLookup(st, stackFrame->entryAddress, stackFrame->entrySegment); + if (functionName) { + written += snprintf(out + written, *length - written, "%s ", functionName); + } else if (prevFrame->entrySegment >= 0) { + written += snprintf(out + written, *length - written, "0x%02X:%08X ", stackFrame->entrySegment, stackFrame->entryAddress); + } else { + written += snprintf(out + written, *length - written, "0x%08X ", stackFrame->entryAddress); + } + CHECK_LENGTH(); + if (stack->formatRegisters) { written += snprintf(out + written, *length - written, "("); CHECK_LENGTH(); char buffer[1024]; @@ -81,16 +99,27 @@ void mStackTraceFormatFrame(struct mStackTrace* stack, uint32_t frame, char* out written += snprintf(out + written, *length - written, "%s)\n ", buffer); CHECK_LENGTH(); } + if (stackFrame->callSegment >= 0) { + written += snprintf(out + written, *length - written, "at 0x%02X:%08X", stackFrame->callSegment, stackFrame->callAddress); + } else { + written += snprintf(out + written, *length - written, "at 0x%08X", stackFrame->callAddress); + } + CHECK_LENGTH(); if (prevFrame) { int32_t offset = stackFrame->callAddress - prevFrame->entryAddress; if (offset >= 0) { - written += snprintf(out + written, *length - written, "at 0x%08X [0x%08X+%d]\n", stackFrame->callAddress, prevFrame->entryAddress, offset); - } else { - written += snprintf(out + written, *length - written, "at 0x%08X\n", stackFrame->callAddress); + functionName = mDebuggerSymbolReverseLookup(st, prevFrame->entryAddress, prevFrame->entrySegment); + if (functionName) { + written += snprintf(out + written, *length - written, " [%s+%d]", functionName, offset); + } else if (stackFrame->entrySegment >= 0) { + written += snprintf(out + written, *length - written, " [0x%02X:%08X+%d]", prevFrame->entrySegment, prevFrame->entryAddress, offset); + } else { + written += snprintf(out + written, *length - written, " [0x%08X+%d]", prevFrame->entryAddress, offset); + } } - } else { - written += snprintf(out + written, *length - written, "at 0x%08X\n", stackFrame->callAddress); } + CHECK_LENGTH(); + written += snprintf(out + written, *length - written, "\n"); *length = written; }