mirror of https://github.com/mgba-emu/mgba.git
Stack trace: implement data structures
This commit is contained in:
parent
d156e48da2
commit
fadd0391d6
|
@ -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
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
Loading…
Reference in New Issue