Stack trace: implement data structures

This commit is contained in:
Adam Higerd 2020-07-26 23:45:51 -05:00
parent d156e48da2
commit fadd0391d6
3 changed files with 121 additions and 2 deletions

View File

@ -0,0 +1,56 @@
/* Copyright (c) 2013-2019 Jeffrey Pfau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
#ifndef STACK_TRACE_H
#define STACK_TRACE_H
#include <mgba-util/common.h>
CXX_GUARD_START
#include <mgba/core/cpu.h>
#include <mgba/core/log.h>
#include <mgba-util/vector.h>
enum mStackTraceMode {
STACK_TRACE_DISABLED = 0,
STACK_TRACE_ENABLED = 1,
STACK_TRACE_BREAK_ON_RETURN = 2,
STACK_TRACE_BREAK_ON_CALL = 4,
STACK_TRACE_BREAK_ON_BOTH = STACK_TRACE_BREAK_ON_RETURN | STACK_TRACE_BREAK_ON_CALL,
STACK_TRACE_RUN_TO_FINISH = 8
};
struct mStackFrame {
uint32_t instruction;
uint32_t callAddress;
uint32_t entryAddress;
uint32_t frameBaseAddress;
void* regs;
bool finished;
bool breakWhenFinished;
};
DECLARE_VECTOR(mStackFrames, struct mStackFrame);
struct mStackTrace {
struct mStackFrames stack;
size_t registersSize;
void (*formatRegisters)(struct mStackFrame* frame, char* out, size_t* length);
};
void mStackTraceInit(struct mStackTrace* stack, size_t registersSize);
void mStackTraceDeinit(struct mStackTrace* stack);
void mStackTraceClear(struct mStackTrace* stack);
size_t mStackTraceGetDepth(struct mStackTrace* stack);
struct mStackFrame* mStackTracePush(struct mStackTrace* stack, uint32_t instruction, uint32_t pc, uint32_t destAddress, uint32_t sp, void* regs);
struct mStackFrame* mStackTraceGetFrame(struct mStackTrace* stack, size_t frame);
void mStackTracePop(struct mStackTrace* stack);
CXX_GUARD_END
#endif

View File

@ -3,7 +3,8 @@ set(SOURCE_FILES
cli-debugger.c
debugger.c
parser.c
symbols.c)
symbols.c
stack-trace.c)
set(TEST_FILES
test/lexer.c
@ -13,4 +14,4 @@ source_group("Debugger" FILES ${SOURCE_FILES})
source_group("Debugger tests" FILES ${TEST_FILES})
export_directory(DEBUGGER SOURCE_FILES)
export_directory(DEBUGGER_TEST TEST_FILES)
export_directory(DEBUGGER_TEST TEST_FILES)

View File

@ -0,0 +1,62 @@
/* Copyright (c) 2013-2016 Jeffrey Pfau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* 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 <mgba/internal/debugger/stack-trace.h>
#include <mgba/core/core.h>
DEFINE_VECTOR(mStackFrames, struct mStackFrame);
void mStackTraceInit(struct mStackTrace* stack, size_t registersSize) {
mStackFramesInit(&stack->stack, 0);
}
void mStackTraceDeinit(struct mStackTrace* stack) {
mStackTraceClear(stack);
mStackFramesDeinit(&stack->stack);
}
void mStackTraceClear(struct mStackTrace* stack) {
ssize_t i = mStackTraceGetDepth(stack) - 1;
while (i >= 0) {
free(mStackTraceGetFrame(stack, i)->regs);
--i;
}
}
size_t mStackTraceGetDepth(struct mStackTrace* stack) {
return mStackFramesSize(&stack->stack);
}
struct mStackFrame* mStackTracePush(struct mStackTrace* stack, uint32_t instruction, uint32_t pc, uint32_t destAddress, uint32_t sp, void* regs) {
struct mStackFrame* frame = mStackFramesAppend(&stack->stack);
frame->instruction = instruction;
frame->callAddress = pc;
frame->entryAddress = destAddress;
frame->frameBaseAddress = sp;
frame->regs = malloc(stack->registersSize);
frame->finished = false;
frame->breakWhenFinished = false;
memcpy(frame->regs, regs, stack->registersSize);
return frame;
}
struct mStackFrame* mStackTraceGetFrame(struct mStackTrace* stack, size_t frame) {
size_t depth = mStackTraceGetDepth(stack);
if (frame >= depth) {
return NULL;
}
return mStackFramesGetPointer(&stack->stack, depth - frame - 1);
}
void mStackTracePop(struct mStackTrace* stack) {
size_t depth = mStackTraceGetDepth(stack);
if (depth == 0) {
return;
}
struct mStackFrame* frame = mStackFramesGetPointer(&stack->stack, depth - 1);
free(frame->regs);
mStackFramesResize(&stack->stack, depth - 1);
}