all repos — mgba @ 1cc0bdeec140cbe411020b8239f3dd47852a9e2f

mGBA Game Boy Advance Emulator

Debugger: Refactor large portions of debugger to allow for multiplatform
Jeffrey Pfau jeffrey@endrift.com
Mon, 25 Apr 2016 21:47:40 -0700
commit

1cc0bdeec140cbe411020b8239f3dd47852a9e2f

parent

a4e29886c9aab8a54a1232bac1bf4a4b7eb1b3db

M CMakeLists.txtCMakeLists.txt

@@ -316,7 +316,7 @@ find_feature(USE_MAGICK "MagickWand")

find_feature(USE_EPOXY "epoxy") # Features -set(DEBUGGER_SRC ${CMAKE_SOURCE_DIR}/src/debugger/debugger.c ${CMAKE_SOURCE_DIR}/src/debugger/memory-debugger.c) +set(DEBUGGER_SRC ${CMAKE_SOURCE_DIR}/src/debugger/debugger.c) set(FEATURE_SRC) set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6")

@@ -326,9 +326,9 @@ endif()

if(USE_CLI_DEBUGGER) list(APPEND FEATURES CLI_DEBUGGER) - list(APPEND FEATURE_SRC ${CMAKE_SOURCE_DIR}/src/debugger/cli-debugger.c) - list(APPEND FEATURE_SRC ${CMAKE_SOURCE_DIR}/src/debugger/parser.c) - list(APPEND FEATURE_SRC ${CMAKE_SOURCE_DIR}/src/gba/supervisor/cli.c) + list(APPEND DEBUGGER_SRC ${CMAKE_SOURCE_DIR}/src/debugger/cli-debugger.c) + list(APPEND DEBUGGER_SRC ${CMAKE_SOURCE_DIR}/src/debugger/parser.c) + list(APPEND DEBUGGER_SRC ${CMAKE_SOURCE_DIR}/src/gba/supervisor/cli.c) include_directories(AFTER ${LIBEDIT_INCLUDE_DIRS}) link_directories(${LIBEDIT_LIBRARY_DIRS}) set(DEBUGGER_LIB ${LIBEDIT_LIBRARIES})
A src/arm/cli-debugger.c

@@ -0,0 +1,225 @@

+/* 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 "cli-debugger.h" + +#ifdef USE_CLI_DEBUGGER +#include "arm/memory-debugger.h" +#include "arm/decoder.h" +#include "core/core.h" +#include "debugger/cli-debugger.h" + +static void _printStatus(struct CLIDebuggerSystem*); + +static void _disassembleArm(struct CLIDebugger*, struct CLIDebugVector*); +static void _disassembleThumb(struct CLIDebugger*, struct CLIDebugVector*); +static void _setBreakpointARM(struct CLIDebugger*, struct CLIDebugVector*); +static void _setBreakpointThumb(struct CLIDebugger*, struct CLIDebugVector*); +static void _writeRegister(struct CLIDebugger*, struct CLIDebugVector*); + +static void _disassembleMode(struct CLIDebugger*, struct CLIDebugVector*, enum ExecutionMode mode); +static uint32_t _printLine(struct CLIDebugger* debugger, uint32_t address, enum ExecutionMode mode); + +static struct CLIDebuggerCommandSummary _armCommands[] = { + { "b/a", _setBreakpointARM, CLIDVParse, "Set a software breakpoint as ARM" }, + { "b/t", _setBreakpointThumb, CLIDVParse, "Set a software breakpoint as Thumb" }, + { "break/a", _setBreakpointARM, CLIDVParse, "Set a software breakpoint as ARM" }, + { "break/t", _setBreakpointThumb, CLIDVParse, "Set a software breakpoint as Thumb" }, + { "dis/a", _disassembleArm, CLIDVParse, "Disassemble instructions as ARM" }, + { "dis/t", _disassembleThumb, CLIDVParse, "Disassemble instructions as Thumb" }, + { "disasm/a", _disassembleArm, CLIDVParse, "Disassemble instructions as ARM" }, + { "disasm/t", _disassembleThumb, CLIDVParse, "Disassemble instructions as Thumb" }, + { "disassemble/a", _disassembleArm, CLIDVParse, "Disassemble instructions as ARM" }, + { "disassemble/t", _disassembleThumb, CLIDVParse, "Disassemble instructions as Thumb" }, + { "w/r", _writeRegister, CLIDVParse, "Write a register" }, + { 0, 0, 0, 0 } +}; + +static inline void _printPSR(union PSR psr) { + printf("%08X [%c%c%c%c%c%c%c]\n", psr.packed, + psr.n ? 'N' : '-', + psr.z ? 'Z' : '-', + psr.c ? 'C' : '-', + psr.v ? 'V' : '-', + psr.i ? 'I' : '-', + psr.f ? 'F' : '-', + psr.t ? 'T' : '-'); +} + +static void _disassemble(struct CLIDebuggerSystem* debugger, struct CLIDebugVector* dv) { + struct ARMCore* cpu = debugger->p->d.core->cpu; + _disassembleMode(debugger->p, dv, cpu->executionMode); +} + +static void _disassembleArm(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { + _disassembleMode(debugger, dv, MODE_ARM); +} + +static void _disassembleThumb(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { + _disassembleMode(debugger, dv, MODE_THUMB); +} + +static void _disassembleMode(struct CLIDebugger* debugger, struct CLIDebugVector* dv, enum ExecutionMode mode) { + struct ARMCore* cpu = debugger->d.core->cpu; + uint32_t address; + int size; + int wordSize; + + if (mode == MODE_ARM) { + wordSize = WORD_SIZE_ARM; + } else { + wordSize = WORD_SIZE_THUMB; + } + + if (!dv || dv->type != CLIDV_INT_TYPE) { + address = cpu->gprs[ARM_PC] - wordSize; + } else { + address = dv->intValue; + dv = dv->next; + } + + if (!dv || dv->type != CLIDV_INT_TYPE) { + size = 1; + } else { + size = dv->intValue; + dv = dv->next; // TODO: Check for excess args + } + + int i; + for (i = 0; i < size; ++i) { + address += _printLine(debugger, address, mode); + } +} + +static inline uint32_t _printLine(struct CLIDebugger* debugger, uint32_t address, enum ExecutionMode mode) { + char disassembly[48]; + struct ARMInstructionInfo info; + printf("%08X: ", address); + if (mode == MODE_ARM) { + uint32_t instruction = debugger->d.core->busRead32(debugger->d.core, address); + ARMDecodeARM(instruction, &info); + ARMDisassemble(&info, address + WORD_SIZE_ARM * 2, disassembly, sizeof(disassembly)); + printf("%08X\t%s\n", instruction, disassembly); + return WORD_SIZE_ARM; + } else { + struct ARMInstructionInfo info2; + struct ARMInstructionInfo combined; + uint16_t instruction = debugger->d.core->busRead16(debugger->d.core, address); + uint16_t instruction2 = debugger->d.core->busRead16(debugger->d.core, address + WORD_SIZE_THUMB); + ARMDecodeThumb(instruction, &info); + ARMDecodeThumb(instruction2, &info2); + if (ARMDecodeThumbCombine(&info, &info2, &combined)) { + ARMDisassemble(&combined, address + WORD_SIZE_THUMB * 2, disassembly, sizeof(disassembly)); + printf("%04X %04X\t%s\n", instruction, instruction2, disassembly); + return WORD_SIZE_THUMB * 2; + } else { + ARMDisassemble(&info, address + WORD_SIZE_THUMB * 2, disassembly, sizeof(disassembly)); + printf("%04X \t%s\n", instruction, disassembly); + return WORD_SIZE_THUMB; + } + } +} + +static void _printStatus(struct CLIDebuggerSystem* debugger) { + struct ARMCore* cpu = debugger->p->d.core->cpu; + int r; + for (r = 0; r < 4; ++r) { + printf("%08X %08X %08X %08X\n", + cpu->gprs[r << 2], + cpu->gprs[(r << 2) + 1], + cpu->gprs[(r << 2) + 2], + cpu->gprs[(r << 2) + 3]); + } + _printPSR(cpu->cpsr); + int instructionLength; + enum ExecutionMode mode = cpu->cpsr.t; + if (mode == MODE_ARM) { + instructionLength = WORD_SIZE_ARM; + } else { + instructionLength = WORD_SIZE_THUMB; + } + _printLine(debugger->p, cpu->gprs[ARM_PC] - instructionLength, mode); +} + +static void _writeRegister(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { + struct ARMCore* cpu = debugger->d.core->cpu; + if (!dv || dv->type != CLIDV_INT_TYPE) { + printf("%s\n", ERROR_MISSING_ARGS); + return; + } + if (!dv->next || dv->next->type != CLIDV_INT_TYPE) { + printf("%s\n", ERROR_MISSING_ARGS); + return; + } + uint32_t regid = dv->intValue; + uint32_t value = dv->next->intValue; + if (regid >= ARM_PC) { + return; + } + cpu->gprs[regid] = value; +} + +static void _setBreakpointARM(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { + if (!dv || dv->type != CLIDV_INT_TYPE) { + printf("%s\n", ERROR_MISSING_ARGS); + return; + } + uint32_t address = dv->intValue; + ARMDebuggerSetSoftwareBreakpoint(&debugger->d, address, MODE_ARM); +} + +static void _setBreakpointThumb(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { + if (!dv || dv->type != CLIDV_INT_TYPE) { + printf("%s\n", ERROR_MISSING_ARGS); + return; + } + uint32_t address = dv->intValue; + ARMDebuggerSetSoftwareBreakpoint(&debugger->d, address, MODE_THUMB); +} + +static uint32_t _lookupIdentifier(struct mDebugger* debugger, const char* name, struct CLIDebugVector* dv) { + struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger; + struct ARMCore* cpu = debugger->core->cpu; + if (strcmp(name, "sp") == 0) { + return cpu->gprs[ARM_SP]; + } + if (strcmp(name, "lr") == 0) { + return cpu->gprs[ARM_LR]; + } + if (strcmp(name, "pc") == 0) { + return cpu->gprs[ARM_PC]; + } + if (strcmp(name, "cpsr") == 0) { + return cpu->cpsr.packed; + } + // TODO: test if mode has SPSR + if (strcmp(name, "spsr") == 0) { + return cpu->spsr.packed; + } + if (name[0] == 'r' && name[1] >= '0' && name[1] <= '9') { + int reg = atoi(&name[1]); + if (reg < 16) { + return cpu->gprs[reg]; + } + } + if (cliDebugger->system) { + uint32_t value = cliDebugger->system->lookupIdentifier(cliDebugger->system, name, dv); + if (dv->type != CLIDV_ERROR_TYPE) { + return value; + } + } else { + dv->type = CLIDV_ERROR_TYPE; + } + return 0; +} + +void ARMCLIDebuggerCreate(struct CLIDebuggerSystem* debugger) { + debugger->printStatus = _printStatus; + debugger->disassemble = _disassemble; + debugger->platformName = "ARM"; + debugger->platformCommands = _armCommands; +} + +#endif
A src/arm/cli-debugger.h

@@ -0,0 +1,14 @@

+/* 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/. */ +#ifndef ARM_CLI_DEBUGGER_H +#define ARM_CLI_DEBUGGER_H + +#include "util/common.h" + +struct CLIDebuggerSystem; +void ARMCLIDebuggerCreate(struct CLIDebuggerSystem* debugger); + +#endif
A src/arm/debugger.c

@@ -0,0 +1,172 @@

+/* Copyright (c) 2013-2014 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 "debugger.h" + +#include "arm/arm.h" +#include "arm/isa-inlines.h" +#include "arm/memory-debugger.h" +#include "core/core.h" + +DEFINE_VECTOR(ARMDebugBreakpointList, struct ARMDebugBreakpoint); +DEFINE_VECTOR(ARMDebugWatchpointList, struct ARMDebugWatchpoint); + +static struct ARMDebugBreakpoint* _lookupBreakpoint(struct ARMDebugBreakpointList* breakpoints, uint32_t address) { + size_t i; + for (i = 0; i < ARMDebugBreakpointListSize(breakpoints); ++i) { + if (ARMDebugBreakpointListGetPointer(breakpoints, i)->address == address) { + return ARMDebugBreakpointListGetPointer(breakpoints, i); + } + } + return 0; +} + +static void ARMDebuggerCheckBreakpoints(struct mDebuggerPlatform* d) { + struct ARMDebugger* debugger = (struct ARMDebugger*) d; + int instructionLength; + enum ExecutionMode mode = debugger->cpu->cpsr.t; + if (mode == MODE_ARM) { + instructionLength = WORD_SIZE_ARM; + } else { + instructionLength = WORD_SIZE_THUMB; + } + struct ARMDebugBreakpoint* breakpoint = _lookupBreakpoint(&debugger->breakpoints, debugger->cpu->gprs[ARM_PC] - instructionLength); + if (!breakpoint) { + return; + } + struct mDebuggerEntryInfo info = { + .address = breakpoint->address + }; + mDebuggerEnter(d->p, DEBUGGER_ENTER_BREAKPOINT, &info); +} + +static void ARMDebuggerInit(void* cpu, struct mDebuggerPlatform* platform); +static void ARMDebuggerDeinit(struct mDebuggerPlatform* platform); + +static void ARMDebuggerEnter(struct mDebuggerPlatform* d, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info); + +static void ARMDebuggerSetBreakpoint(struct mDebuggerPlatform*, uint32_t address); +static void ARMDebuggerClearBreakpoint(struct mDebuggerPlatform*, uint32_t address); +static void ARMDebuggerSetWatchpoint(struct mDebuggerPlatform*, uint32_t address, enum mWatchpointType type); +static void ARMDebuggerClearWatchpoint(struct mDebuggerPlatform*, uint32_t address); +static void ARMDebuggerCheckBreakpoints(struct mDebuggerPlatform*); +static bool ARMDebuggerHasBreakpoints(struct mDebuggerPlatform*); + +struct mDebuggerPlatform* ARMDebuggerPlatformCreate(void) { + struct mDebuggerPlatform* platform = malloc(sizeof(struct ARMDebugger)); + platform->entered = ARMDebuggerEnter; + platform->init = ARMDebuggerInit; + platform->deinit = ARMDebuggerDeinit; + platform->setBreakpoint = ARMDebuggerSetBreakpoint; + platform->clearBreakpoint = ARMDebuggerClearBreakpoint; + platform->setWatchpoint = ARMDebuggerSetWatchpoint; + platform->clearWatchpoint = ARMDebuggerClearWatchpoint; + platform->checkBreakpoints = ARMDebuggerCheckBreakpoints; + platform->hasBreakpoints = ARMDebuggerHasBreakpoints; + return platform; +} + +void ARMDebuggerInit(void* cpu, struct mDebuggerPlatform* platform) { + struct ARMDebugger* debugger = (struct ARMDebugger*) platform; + debugger->cpu = cpu; + debugger->originalMemory = debugger->cpu->memory; + ARMDebugBreakpointListInit(&debugger->breakpoints, 0); + ARMDebugBreakpointListInit(&debugger->swBreakpoints, 0); + ARMDebugWatchpointListInit(&debugger->watchpoints, 0); +} + +void ARMDebuggerDeinit(struct mDebuggerPlatform* platform) { + struct ARMDebugger* debugger = (struct ARMDebugger*) platform; + ARMDebugBreakpointListDeinit(&debugger->breakpoints); + ARMDebugBreakpointListDeinit(&debugger->swBreakpoints); + ARMDebugWatchpointListDeinit(&debugger->watchpoints); +} + +static void ARMDebuggerEnter(struct mDebuggerPlatform* platform, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info) { + struct ARMDebugger* debugger = (struct ARMDebugger*) platform; + struct ARMCore* cpu = debugger->cpu; + cpu->nextEvent = cpu->cycles; + if (reason == DEBUGGER_ENTER_BREAKPOINT) { + struct ARMDebugBreakpoint* breakpoint = _lookupBreakpoint(&debugger->swBreakpoints, _ARMPCAddress(cpu)); + if (breakpoint && breakpoint->isSw) { + info->address = breakpoint->address; + if (debugger->clearSoftwareBreakpoint) { + debugger->clearSoftwareBreakpoint(debugger, breakpoint->address, breakpoint->sw.mode, breakpoint->sw.opcode); + } + + ARMRunFake(cpu, breakpoint->sw.opcode); + + if (debugger->setSoftwareBreakpoint) { + debugger->setSoftwareBreakpoint(debugger, breakpoint->address, breakpoint->sw.mode, &breakpoint->sw.opcode); + } + } + } + if (debugger->entered) { + debugger->entered(debugger->d.p, reason, info); + } +} + +bool ARMDebuggerSetSoftwareBreakpoint(struct mDebuggerPlatform* d, uint32_t address, enum ExecutionMode mode) { + struct ARMDebugger* debugger = (struct ARMDebugger*) d; + uint32_t opcode; + if (!debugger->setSoftwareBreakpoint || !debugger->setSoftwareBreakpoint(debugger, address, mode, &opcode)) { + return false; + } + + struct ARMDebugBreakpoint* breakpoint = ARMDebugBreakpointListAppend(&debugger->swBreakpoints); + breakpoint->address = address; + breakpoint->isSw = true; + breakpoint->sw.opcode = opcode; + breakpoint->sw.mode = mode; + + return true; +} + +static void ARMDebuggerSetBreakpoint(struct mDebuggerPlatform* d, uint32_t address) { + struct ARMDebugger* debugger = (struct ARMDebugger*) d; + struct ARMDebugBreakpoint* breakpoint = ARMDebugBreakpointListAppend(&debugger->breakpoints); + breakpoint->address = address; + breakpoint->isSw = false; +} + +static void ARMDebuggerClearBreakpoint(struct mDebuggerPlatform* d, uint32_t address) { + struct ARMDebugger* debugger = (struct ARMDebugger*) d; + struct ARMDebugBreakpointList* breakpoints = &debugger->breakpoints; + size_t i; + for (i = 0; i < ARMDebugBreakpointListSize(breakpoints); ++i) { + if (ARMDebugBreakpointListGetPointer(breakpoints, i)->address == address) { + ARMDebugBreakpointListShift(breakpoints, i, 1); + } + } +} + +static bool ARMDebuggerHasBreakpoints(struct mDebuggerPlatform* d) { + struct ARMDebugger* debugger = (struct ARMDebugger*) d; + return ARMDebugBreakpointListSize(&debugger->breakpoints) || ARMDebugWatchpointListSize(&debugger->watchpoints); +} + +static void ARMDebuggerSetWatchpoint(struct mDebuggerPlatform* d, uint32_t address, enum mWatchpointType type) { + struct ARMDebugger* debugger = (struct ARMDebugger*) d; + if (!ARMDebugWatchpointListSize(&debugger->watchpoints)) { + ARMDebuggerInstallMemoryShim(debugger); + } + struct ARMDebugWatchpoint* watchpoint = ARMDebugWatchpointListAppend(&debugger->watchpoints); + watchpoint->address = address; + watchpoint->type = type; +} + +static void ARMDebuggerClearWatchpoint(struct mDebuggerPlatform* d, uint32_t address) { + struct ARMDebugger* debugger = (struct ARMDebugger*) d; + struct ARMDebugWatchpointList* watchpoints = &debugger->watchpoints; + size_t i; + for (i = 0; i < ARMDebugWatchpointListSize(watchpoints); ++i) { + if (ARMDebugWatchpointListGetPointer(watchpoints, i)->address == address) { + ARMDebugWatchpointListShift(watchpoints, i, 1); + } + } + if (!ARMDebugWatchpointListSize(&debugger->watchpoints)) { + ARMDebuggerRemoveMemoryShim(debugger); + } +}
A src/arm/debugger.h

@@ -0,0 +1,41 @@

+/* Copyright (c) 2013-2014 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 "debugger/debugger.h" + +struct ARMDebugBreakpoint { + uint32_t address; + bool isSw; + struct { + uint32_t opcode; + enum ExecutionMode mode; + } sw; +}; + +struct ARMDebugWatchpoint { + uint32_t address; + enum mWatchpointType type; +}; + +DECLARE_VECTOR(ARMDebugBreakpointList, struct ARMDebugBreakpoint); +DECLARE_VECTOR(ARMDebugWatchpointList, struct ARMDebugWatchpoint); + +struct ARMDebugger { + struct mDebuggerPlatform d; + struct ARMCore* cpu; + + struct ARMDebugBreakpointList breakpoints; + struct ARMDebugBreakpointList swBreakpoints; + struct ARMDebugWatchpointList watchpoints; + struct ARMMemory originalMemory; + + void (*entered)(struct mDebugger*, enum mDebuggerEntryReason, struct mDebuggerEntryInfo*); + + bool (*setSoftwareBreakpoint)(struct ARMDebugger*, uint32_t address, enum ExecutionMode mode, uint32_t* opcode); + bool (*clearSoftwareBreakpoint)(struct ARMDebugger*, uint32_t address, enum ExecutionMode mode, uint32_t opcode); +}; + +struct mDebuggerPlatform* ARMDebuggerPlatformCreate(void); +bool ARMDebuggerSetSoftwareBreakpoint(struct mDebuggerPlatform* debugger, uint32_t address, enum ExecutionMode mode);
M src/core/core.hsrc/core/core.h

@@ -16,6 +16,7 @@ #ifndef MINIMAL_CORE

#include "core/input.h" #endif #include "core/interface.h" +#include "debugger/debugger.h" enum mPlatform { PLATFORM_NONE = -1,

@@ -33,6 +34,7 @@ struct mCoreSync;

struct mCore { void* cpu; void* board; + struct mDebugger* debugger; #if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 struct mDirectorySet dirs;

@@ -93,6 +95,20 @@

void (*setRTC)(struct mCore*, struct mRTCSource*); void (*setRotation)(struct mCore*, struct mRotationSource*); void (*setRumble)(struct mCore*, struct mRumble*); + + uint32_t (*busRead8)(struct mCore*, uint32_t address); + uint32_t (*busRead16)(struct mCore*, uint32_t address); + uint32_t (*busRead32)(struct mCore*, uint32_t address); + + void (*busWrite8)(struct mCore*, uint32_t address, uint8_t); + void (*busWrite16)(struct mCore*, uint32_t address, uint16_t); + void (*busWrite32)(struct mCore*, uint32_t address, uint32_t); + + bool (*supportsDebuggerType)(struct mCore*, enum mDebuggerType); + struct mDebuggerPlatform* (*debuggerPlatform)(struct mCore*); + struct CLIDebuggerSystem* (*cliDebuggerSystem)(struct mCore*); + void (*attachDebugger)(struct mCore*, struct mDebugger*); + void (*detachDebugger)(struct mCore*); }; #if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
M src/core/cpu.hsrc/core/cpu.h

@@ -8,6 +8,12 @@ #define M_CPU_H

#include "util/common.h" +enum mCPUComponentType { + CPU_COMPONENT_DEBUGGER, + CPU_COMPONENT_CHEAT_DEVICE, + CPU_COMPONENT_MAX +}; + struct mCPUComponent { uint32_t id; void (*init)(void* cpu, struct mCPUComponent* component);
M src/core/thread.csrc/core/thread.c

@@ -116,7 +116,17 @@

_changeState(threadContext, THREAD_RUNNING, true); while (threadContext->state < THREAD_EXITING) { - core->runLoop(core); + struct mDebugger* debugger = core->debugger; + if (debugger) { + mDebuggerRun(debugger); + if (debugger->state == DEBUGGER_SHUTDOWN) { + _changeState(threadContext, THREAD_EXITING, false); + } + } else { + while (threadContext->state == THREAD_RUNNING) { + core->runLoop(core); + } + } int resetScheduled = 0; MutexLock(&threadContext->stateMutex);
M src/debugger/cli-debugger.csrc/debugger/cli-debugger.c

@@ -4,7 +4,10 @@ * 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 "cli-debugger.h" -#include "decoder.h" + +#ifdef USE_CLI_DEBUGGER + +#include "core/core.h" #include "parser.h" #include <signal.h>

@@ -13,8 +16,8 @@ #ifdef USE_PTHREADS

#include <pthread.h> #endif -static const char* ERROR_MISSING_ARGS = "Arguments missing"; // TODO: share -static const char* ERROR_OVERFLOW = "Arguments overflow"; +const char* ERROR_MISSING_ARGS = "Arguments missing"; // TODO: share +const char* ERROR_OVERFLOW = "Arguments overflow"; static struct CLIDebugger* _activeDebugger;

@@ -23,8 +26,6 @@ static void _breakInto(struct CLIDebugger*, struct CLIDebugVector*);

#endif static void _continue(struct CLIDebugger*, struct CLIDebugVector*); static void _disassemble(struct CLIDebugger*, struct CLIDebugVector*); -static void _disassembleArm(struct CLIDebugger*, struct CLIDebugVector*); -static void _disassembleThumb(struct CLIDebugger*, struct CLIDebugVector*); static void _next(struct CLIDebugger*, struct CLIDebugVector*); static void _print(struct CLIDebugger*, struct CLIDebugVector*); static void _printBin(struct CLIDebugger*, struct CLIDebugVector*);

@@ -37,42 +38,27 @@ static void _reset(struct CLIDebugger*, struct CLIDebugVector*);

static void _readHalfword(struct CLIDebugger*, struct CLIDebugVector*); static void _readWord(struct CLIDebugger*, struct CLIDebugVector*); static void _setBreakpoint(struct CLIDebugger*, struct CLIDebugVector*); -static void _setBreakpointARM(struct CLIDebugger*, struct CLIDebugVector*); -static void _setBreakpointThumb(struct CLIDebugger*, struct CLIDebugVector*); static void _clearBreakpoint(struct CLIDebugger*, struct CLIDebugVector*); static void _setWatchpoint(struct CLIDebugger*, struct CLIDebugVector*); static void _writeByte(struct CLIDebugger*, struct CLIDebugVector*); static void _writeHalfword(struct CLIDebugger*, struct CLIDebugVector*); static void _writeWord(struct CLIDebugger*, struct CLIDebugVector*); -static void _writeRegister(struct CLIDebugger*, struct CLIDebugVector*); static void _dumpByte(struct CLIDebugger*, struct CLIDebugVector*); static void _dumpHalfword(struct CLIDebugger*, struct CLIDebugVector*); static void _dumpWord(struct CLIDebugger*, struct CLIDebugVector*); static void _breakIntoDefault(int signal); -static void _disassembleMode(struct CLIDebugger*, struct CLIDebugVector*, enum ExecutionMode mode); -static uint32_t _printLine(struct CLIDebugger* debugger, uint32_t address, enum ExecutionMode mode); static struct CLIDebuggerCommandSummary _debuggerCommands[] = { { "b", _setBreakpoint, CLIDVParse, "Set a breakpoint" }, - { "b/a", _setBreakpointARM, CLIDVParse, "Set a software breakpoint as ARM" }, - { "b/t", _setBreakpointThumb, CLIDVParse, "Set a software breakpoint as Thumb" }, { "break", _setBreakpoint, CLIDVParse, "Set a breakpoint" }, - { "break/a", _setBreakpointARM, CLIDVParse, "Set a software breakpoint as ARM" }, - { "break/t", _setBreakpointThumb, CLIDVParse, "Set a software breakpoint as Thumb" }, { "c", _continue, 0, "Continue execution" }, { "continue", _continue, 0, "Continue execution" }, { "d", _clearBreakpoint, CLIDVParse, "Delete a breakpoint" }, { "delete", _clearBreakpoint, CLIDVParse, "Delete a breakpoint" }, { "dis", _disassemble, CLIDVParse, "Disassemble instructions" }, - { "dis/a", _disassembleArm, CLIDVParse, "Disassemble instructions as ARM" }, - { "dis/t", _disassembleThumb, CLIDVParse, "Disassemble instructions as Thumb" }, { "disasm", _disassemble, CLIDVParse, "Disassemble instructions" }, - { "disasm/a", _disassembleArm, CLIDVParse, "Disassemble instructions as ARM" }, - { "disasm/t", _disassembleThumb, CLIDVParse, "Disassemble instructions as Thumb" }, { "disassemble", _disassemble, CLIDVParse, "Disassemble instructions" }, - { "disassemble/a", _disassembleArm, CLIDVParse, "Disassemble instructions as ARM" }, - { "disassemble/t", _disassembleThumb, CLIDVParse, "Disassemble instructions as Thumb" }, { "h", _printHelp, CLIDVStringParse, "Print help" }, { "help", _printHelp, CLIDVStringParse, "Print help" }, { "i", _printStatus, 0, "Print the current status" },

@@ -93,11 +79,10 @@ { "r/2", _readHalfword, CLIDVParse, "Read a halfword from a specified offset" },

{ "r/4", _readWord, CLIDVParse, "Read a word from a specified offset" }, { "status", _printStatus, 0, "Print the current status" }, { "w", _setWatchpoint, CLIDVParse, "Set a watchpoint" }, - { "watch", _setWatchpoint, CLIDVParse, "Set a watchpoint" }, { "w/1", _writeByte, CLIDVParse, "Write a byte at a specified offset" }, { "w/2", _writeHalfword, CLIDVParse, "Write a halfword at a specified offset" }, { "w/4", _writeWord, CLIDVParse, "Write a word at a specified offset" }, - { "w/r", _writeRegister, CLIDVParse, "Write a register" }, + { "watch", _setWatchpoint, CLIDVParse, "Set a watchpoint" }, { "x/1", _dumpByte, CLIDVParse, "Examine bytes at a specified offset" }, { "x/2", _dumpHalfword, CLIDVParse, "Examine halfwords at a specified offset" }, { "x/4", _dumpWord, CLIDVParse, "Examine words at a specified offset" },

@@ -107,17 +92,6 @@ #endif

{ 0, 0, 0, 0 } }; -static inline void _printPSR(union PSR psr) { - printf("%08X [%c%c%c%c%c%c%c]\n", psr.packed, - psr.n ? 'N' : '-', - psr.z ? 'Z' : '-', - psr.c ? 'C' : '-', - psr.v ? 'V' : '-', - psr.i ? 'I' : '-', - psr.f ? 'F' : '-', - psr.t ? 'T' : '-'); -} - #ifndef NDEBUG static void _handleDeath(int sig) { UNUSED(sig);

@@ -149,57 +123,12 @@ }

static void _next(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { UNUSED(dv); - if (debugger->d.currentBreakpoint) { - if (debugger->d.currentBreakpoint->isSw && debugger->d.setSoftwareBreakpoint) { - debugger->d.setSoftwareBreakpoint(&debugger->d, debugger->d.currentBreakpoint->address, debugger->d.currentBreakpoint->sw.mode, &debugger->d.currentBreakpoint->sw.opcode); - } - debugger->d.currentBreakpoint = 0; - } - ARMRun(debugger->d.cpu); + debugger->d.core->step(debugger->d.core); _printStatus(debugger, 0); } static void _disassemble(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { - _disassembleMode(debugger, dv, debugger->d.cpu->executionMode); -} - -static void _disassembleArm(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { - _disassembleMode(debugger, dv, MODE_ARM); -} - -static void _disassembleThumb(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { - _disassembleMode(debugger, dv, MODE_THUMB); -} - -static void _disassembleMode(struct CLIDebugger* debugger, struct CLIDebugVector* dv, enum ExecutionMode mode) { - uint32_t address; - int size; - int wordSize; - - if (mode == MODE_ARM) { - wordSize = WORD_SIZE_ARM; - } else { - wordSize = WORD_SIZE_THUMB; - } - - if (!dv || dv->type != CLIDV_INT_TYPE) { - address = debugger->d.cpu->gprs[ARM_PC] - wordSize; - } else { - address = dv->intValue; - dv = dv->next; - } - - if (!dv || dv->type != CLIDV_INT_TYPE) { - size = 1; - } else { - size = dv->intValue; - dv = dv->next; // TODO: Check for excess args - } - - int i; - for (i = 0; i < size; ++i) { - address += _printLine(debugger, address, mode);; - } + debugger->system->disassemble(debugger->system, dv); } static void _print(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {

@@ -234,12 +163,16 @@ static void _printHelp(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {

UNUSED(debugger); UNUSED(dv); if (!dv) { - puts("ARM commands:"); + puts("Generic commands:"); int i; for (i = 0; _debuggerCommands[i].name; ++i) { printf("%-10s %s\n", _debuggerCommands[i].name, _debuggerCommands[i].summary); } if (debugger->system) { + printf("%s commands:\n", debugger->system->platformName); + for (i = 0; debugger->system->platformCommands[i].name; ++i) { + printf("%-10s %s\n", debugger->system->platformCommands[i].name, debugger->system->platformCommands[i].summary); + } printf("%s commands:\n", debugger->system->name); for (i = 0; debugger->system->commands[i].name; ++i) { printf("%-10s %s\n", debugger->system->commands[i].name, debugger->system->commands[i].summary);

@@ -253,7 +186,11 @@ printf(" %s\n", _debuggerCommands[i].summary);

} } if (debugger->system) { - printf("\n%s commands:\n", debugger->system->name); + for (i = 0; debugger->system->platformCommands[i].name; ++i) { + if (strcmp(debugger->system->platformCommands[i].name, dv->charValue) == 0) { + printf(" %s\n", debugger->system->platformCommands[i].summary); + } + } for (i = 0; debugger->system->commands[i].name; ++i) { if (strcmp(debugger->system->commands[i].name, dv->charValue) == 0) { printf(" %s\n", debugger->system->commands[i].summary);

@@ -263,56 +200,6 @@ }

} } -static inline uint32_t _printLine(struct CLIDebugger* debugger, uint32_t address, enum ExecutionMode mode) { - char disassembly[48]; - struct ARMInstructionInfo info; - printf("%08X: ", address); - if (mode == MODE_ARM) { - uint32_t instruction = debugger->d.cpu->memory.load32(debugger->d.cpu, address, 0); - ARMDecodeARM(instruction, &info); - ARMDisassemble(&info, address + WORD_SIZE_ARM * 2, disassembly, sizeof(disassembly)); - printf("%08X\t%s\n", instruction, disassembly); - return WORD_SIZE_ARM; - } else { - struct ARMInstructionInfo info2; - struct ARMInstructionInfo combined; - uint16_t instruction = debugger->d.cpu->memory.load16(debugger->d.cpu, address, 0); - uint16_t instruction2 = debugger->d.cpu->memory.load16(debugger->d.cpu, address + WORD_SIZE_THUMB, 0); - ARMDecodeThumb(instruction, &info); - ARMDecodeThumb(instruction2, &info2); - if (ARMDecodeThumbCombine(&info, &info2, &combined)) { - ARMDisassemble(&combined, address + WORD_SIZE_THUMB * 2, disassembly, sizeof(disassembly)); - printf("%04X %04X\t%s\n", instruction, instruction2, disassembly); - return WORD_SIZE_THUMB * 2; - } else { - ARMDisassemble(&info, address + WORD_SIZE_THUMB * 2, disassembly, sizeof(disassembly)); - printf("%04X \t%s\n", instruction, disassembly); - return WORD_SIZE_THUMB; - } - } -} - -static void _printStatus(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { - UNUSED(dv); - int r; - for (r = 0; r < 4; ++r) { - printf("%08X %08X %08X %08X\n", - debugger->d.cpu->gprs[r << 2], - debugger->d.cpu->gprs[(r << 2) + 1], - debugger->d.cpu->gprs[(r << 2) + 2], - debugger->d.cpu->gprs[(r << 2) + 3]); - } - _printPSR(debugger->d.cpu->cpsr); - int instructionLength; - enum ExecutionMode mode = debugger->d.cpu->cpsr.t; - if (mode == MODE_ARM) { - instructionLength = WORD_SIZE_ARM; - } else { - instructionLength = WORD_SIZE_THUMB; - } - _printLine(debugger, debugger->d.cpu->gprs[ARM_PC] - instructionLength, mode); -} - static void _quit(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { UNUSED(dv); debugger->d.state = DEBUGGER_SHUTDOWN;

@@ -324,13 +211,13 @@ printf("%s\n", ERROR_MISSING_ARGS);

return; } uint32_t address = dv->intValue; - uint8_t value = debugger->d.cpu->memory.load8(debugger->d.cpu, address, 0); + uint8_t value = debugger->d.core->busRead8(debugger->d.core, address); printf(" 0x%02X\n", value); } static void _reset(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { UNUSED(dv); - ARMReset(debugger->d.cpu); + debugger->d.core->reset(debugger->d.core); _printStatus(debugger, 0); }

@@ -340,7 +227,7 @@ printf("%s\n", ERROR_MISSING_ARGS);

return; } uint32_t address = dv->intValue; - uint16_t value = debugger->d.cpu->memory.load16(debugger->d.cpu, address & ~1, 0); + uint16_t value = debugger->d.core->busRead16(debugger->d.core, address & ~1); printf(" 0x%04X\n", value); }

@@ -350,7 +237,7 @@ printf("%s\n", ERROR_MISSING_ARGS);

return; } uint32_t address = dv->intValue; - uint32_t value = debugger->d.cpu->memory.load32(debugger->d.cpu, address & ~3, 0); + uint32_t value = debugger->d.core->busRead32(debugger->d.core, address & ~3); printf(" 0x%08X\n", value); }

@@ -369,7 +256,7 @@ if (value > 0xFF) {

printf("%s\n", ERROR_OVERFLOW); return; } - debugger->d.cpu->memory.store8(debugger->d.cpu, address, value, 0); + debugger->d.core->busWrite8(debugger->d.core, address, value); } static void _writeHalfword(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {

@@ -387,7 +274,7 @@ if (value > 0xFFFF) {

printf("%s\n", ERROR_OVERFLOW); return; } - debugger->d.cpu->memory.store16(debugger->d.cpu, address, value, 0); + debugger->d.core->busWrite16(debugger->d.core, address, value); } static void _writeWord(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {

@@ -401,24 +288,7 @@ return;

} uint32_t address = dv->intValue; uint32_t value = dv->next->intValue; - debugger->d.cpu->memory.store32(debugger->d.cpu, address, value, 0); -} - -static void _writeRegister(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { - if (!dv || dv->type != CLIDV_INT_TYPE) { - printf("%s\n", ERROR_MISSING_ARGS); - return; - } - if (!dv->next || dv->next->type != CLIDV_INT_TYPE) { - printf("%s\n", ERROR_MISSING_ARGS); - return; - } - uint32_t regid = dv->intValue; - uint32_t value = dv->next->intValue; - if (regid >= ARM_PC) { - return; - } - debugger->d.cpu->gprs[regid] = value; + debugger->d.core->busWrite32(debugger->d.core, address, value); } static void _dumpByte(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {

@@ -438,7 +308,7 @@ line = words;

} printf("0x%08X:", address); for (; line > 0; --line, ++address, --words) { - uint32_t value = debugger->d.cpu->memory.load8(debugger->d.cpu, address, 0); + uint32_t value = debugger->d.core->busRead8(debugger->d.core, address); printf(" %02X", value); } printf("\n");

@@ -462,7 +332,7 @@ line = words;

} printf("0x%08X:", address); for (; line > 0; --line, address += 2, --words) { - uint32_t value = debugger->d.cpu->memory.load16(debugger->d.cpu, address, 0); + uint32_t value = debugger->d.core->busRead16(debugger->d.core, address); printf(" %04X", value); } printf("\n");

@@ -486,7 +356,7 @@ line = words;

} printf("0x%08X:", address); for (; line > 0; --line, address += 4, --words) { - uint32_t value = debugger->d.cpu->memory.load32(debugger->d.cpu, address, 0); + uint32_t value = debugger->d.core->busRead32(debugger->d.core, address); printf(" %08X", value); } printf("\n");

@@ -499,25 +369,16 @@ printf("%s\n", ERROR_MISSING_ARGS);

return; } uint32_t address = dv->intValue; - DebuggerSetBreakpoint(&debugger->d, address); -} - -static void _setBreakpointARM(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { - if (!dv || dv->type != CLIDV_INT_TYPE) { - printf("%s\n", ERROR_MISSING_ARGS); - return; - } - uint32_t address = dv->intValue; - DebuggerSetSoftwareBreakpoint(&debugger->d, address, MODE_ARM); + debugger->d.platform->setBreakpoint(debugger->d.platform, address); } -static void _setBreakpointThumb(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { +static void _setWatchpoint(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { if (!dv || dv->type != CLIDV_INT_TYPE) { printf("%s\n", ERROR_MISSING_ARGS); return; } uint32_t address = dv->intValue; - DebuggerSetSoftwareBreakpoint(&debugger->d, address, MODE_THUMB); + debugger->d.platform->setWatchpoint(debugger->d.platform, address, WATCHPOINT_RW); // TODO: ro/wo } static void _clearBreakpoint(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {

@@ -526,22 +387,18 @@ printf("%s\n", ERROR_MISSING_ARGS);

return; } uint32_t address = dv->intValue; - DebuggerClearBreakpoint(&debugger->d, address); - DebuggerClearWatchpoint(&debugger->d, address); + debugger->d.platform->clearBreakpoint(debugger->d.platform, address); + debugger->d.platform->clearWatchpoint(debugger->d.platform, address); } -static void _setWatchpoint(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { - if (!dv || dv->type != CLIDV_INT_TYPE) { - printf("%s\n", ERROR_MISSING_ARGS); - return; - } - uint32_t address = dv->intValue; - DebuggerSetWatchpoint(&debugger->d, address, WATCHPOINT_RW); // TODO: ro/wo +static void _breakIntoDefault(int signal) { + UNUSED(signal); + mDebuggerEnter(&_activeDebugger->d, DEBUGGER_ENTER_MANUAL, 0); } -static void _breakIntoDefault(int signal) { - UNUSED(signal); - DebuggerEnter(&_activeDebugger->d, DEBUGGER_ENTER_MANUAL, 0); +static void _printStatus(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { + UNUSED(dv); + debugger->system->printStatus(debugger->system); } static uint32_t _performOperation(enum Operation operation, uint32_t current, uint32_t next, struct CLIDebugVector* dv) {

@@ -570,30 +427,8 @@ }

return current; } -static uint32_t _lookupIdentifier(struct Debugger* debugger, const char* name, struct CLIDebugVector* dv) { +static uint32_t _lookupIdentifier(struct mDebugger* debugger, const char* name, struct CLIDebugVector* dv) { struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger; - if (strcmp(name, "sp") == 0) { - return debugger->cpu->gprs[ARM_SP]; - } - if (strcmp(name, "lr") == 0) { - return debugger->cpu->gprs[ARM_LR]; - } - if (strcmp(name, "pc") == 0) { - return debugger->cpu->gprs[ARM_PC]; - } - if (strcmp(name, "cpsr") == 0) { - return debugger->cpu->cpsr.packed; - } - // TODO: test if mode has SPSR - if (strcmp(name, "spsr") == 0) { - return debugger->cpu->spsr.packed; - } - if (name[0] == 'r' && name[1] >= '0' && name[1] <= '9') { - int reg = atoi(&name[1]); - if (reg < 16) { - return debugger->cpu->gprs[reg]; - } - } if (cliDebugger->system) { uint32_t value = cliDebugger->system->lookupIdentifier(cliDebugger->system, name, dv); if (dv->type != CLIDV_ERROR_TYPE) {

@@ -605,7 +440,7 @@ }

return 0; } -static uint32_t _evaluateParseTree(struct Debugger* debugger, struct ParseTree* tree, struct CLIDebugVector* dv) { +static uint32_t _evaluateParseTree(struct mDebugger* debugger, struct ParseTree* tree, struct CLIDebugVector* dv) { switch (tree->token.type) { case TOKEN_UINT_TYPE: return tree->token.uintValue;

@@ -753,6 +588,9 @@ }

int result = _tryCommands(debugger, _debuggerCommands, line, cmdLength, args, count - cmdLength - 1); if (result < 0 && debugger->system) { result = _tryCommands(debugger, debugger->system->commands, line, cmdLength, args, count - cmdLength - 1); + if (result < 0) { + result = _tryCommands(debugger, debugger->system->platformCommands, line, cmdLength, args, count - cmdLength - 1); + } } if (result < 0) { printf("Command not found\n");

@@ -765,7 +603,7 @@ UNUSED(el);

return "> "; } -static void _commandLine(struct Debugger* debugger) { +static void _commandLine(struct mDebugger* debugger) { struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger; const char* line; _printStatus(cliDebugger, 0);

@@ -787,7 +625,7 @@ }

} } -static void _reportEntry(struct Debugger* debugger, enum DebuggerEntryReason reason, struct DebuggerEntryInfo* info) { +static void _reportEntry(struct mDebugger* debugger, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info) { UNUSED(debugger); switch (reason) { case DEBUGGER_ENTER_MANUAL:

@@ -874,7 +712,7 @@ el_insertstr(elstate, " ");

return CC_REDISPLAY; } -static void _cliDebuggerInit(struct Debugger* debugger) { +static void _cliDebuggerInit(struct mDebugger* debugger) { struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger; // TODO: get argv[0] cliDebugger->elstate = el_init(binaryName, stdin, stdout, stderr);

@@ -892,7 +730,7 @@ _activeDebugger = cliDebugger;

signal(SIGINT, _breakIntoDefault); } -static void _cliDebuggerDeinit(struct Debugger* debugger) { +static void _cliDebuggerDeinit(struct mDebugger* debugger) { struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger; history_end(cliDebugger->histate); el_end(cliDebugger->elstate);

@@ -904,7 +742,7 @@ cliDebugger->system = 0;

} } -static void _cliDebuggerCustom(struct Debugger* debugger) { +static void _cliDebuggerCustom(struct mDebugger* debugger) { struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger; bool retain = false; if (cliDebugger->system) {

@@ -916,7 +754,6 @@ }

} void CLIDebuggerCreate(struct CLIDebugger* debugger) { - DebuggerCreate(&debugger->d); debugger->d.init = _cliDebuggerInit; debugger->d.deinit = _cliDebuggerDeinit; debugger->d.custom = _cliDebuggerCustom;

@@ -935,3 +772,5 @@

debugger->system = system; system->p = debugger; } + +#endif
M src/debugger/cli-debugger.hsrc/debugger/cli-debugger.h

@@ -45,14 +45,18 @@ void (*init)(struct CLIDebuggerSystem*);

void (*deinit)(struct CLIDebuggerSystem*); bool (*custom)(struct CLIDebuggerSystem*); + void (*disassemble)(struct CLIDebuggerSystem*, struct CLIDebugVector* dv); uint32_t (*lookupIdentifier)(struct CLIDebuggerSystem*, const char* name, struct CLIDebugVector* dv); + void (*printStatus)(struct CLIDebuggerSystem*); struct CLIDebuggerCommandSummary* commands; const char* name; + struct CLIDebuggerCommandSummary* platformCommands; + const char* platformName; }; struct CLIDebugger { - struct Debugger d; + struct mDebugger d; struct CLIDebuggerSystem* system;
M src/debugger/debugger.csrc/debugger/debugger.c

@@ -1,94 +1,92 @@

-/* Copyright (c) 2013-2014 Jeffrey Pfau +/* 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 "debugger.h" -#include "arm.h" -#include "isa-inlines.h" +#include "core/core.h" -#include "memory-debugger.h" +#ifdef USE_CLI_DEBUGGER +#include "debugger/cli-debugger.h" +#include "gba/supervisor/cli.h" +#endif -const uint32_t DEBUGGER_ID = 0xDEADBEEF; +#ifdef USE_GDB_STUB +#include "debugger/gdb-stub.h" +#endif -DEFINE_VECTOR(DebugBreakpointList, struct DebugBreakpoint); -DEFINE_VECTOR(DebugWatchpointList, struct DebugWatchpoint); +const uint32_t DEBUGGER_ID = 0xDEADBEEF; mLOG_DEFINE_CATEGORY(DEBUGGER, "Debugger"); -static struct DebugBreakpoint* _lookupBreakpoint(struct DebugBreakpointList* breakpoints, uint32_t address) { - size_t i; - for (i = 0; i < DebugBreakpointListSize(breakpoints); ++i) { - if (DebugBreakpointListGetPointer(breakpoints, i)->address == address) { - return DebugBreakpointListGetPointer(breakpoints, i); - } - } - return 0; -} +static void mDebuggerInit(void* cpu, struct mCPUComponent* component); +static void mDebuggerDeinit(struct mCPUComponent* component); -static void _checkBreakpoints(struct Debugger* debugger) { - int instructionLength; - enum ExecutionMode mode = debugger->cpu->cpsr.t; - if (mode == MODE_ARM) { - instructionLength = WORD_SIZE_ARM; - } else { - instructionLength = WORD_SIZE_THUMB; - } - struct DebugBreakpoint* breakpoint = _lookupBreakpoint(&debugger->breakpoints, debugger->cpu->gprs[ARM_PC] - instructionLength); - if (!breakpoint) { - return; +struct mDebugger* mDebuggerCreate(enum mDebuggerType type, struct mCore* core) { + if (!core->supportsDebuggerType(core, type)) { + return NULL; } - struct DebuggerEntryInfo info = { - .address = breakpoint->address + + union DebugUnion { + struct mDebugger d; +#ifdef USE_CLI_DEBUGGER + struct CLIDebugger cli; +#endif +#ifdef USE_GDB_STUB + struct GDBStub gdb; +#endif }; - DebuggerEnter(debugger, DEBUGGER_ENTER_BREAKPOINT, &info); -} -static void DebuggerInit(void* cpu, struct mCPUComponent*); -static void DebuggerDeinit(struct mCPUComponent*); + union DebugUnion* debugger = malloc(sizeof(union DebugUnion)); -void DebuggerCreate(struct Debugger* debugger) { - debugger->d.id = DEBUGGER_ID; - debugger->d.init = DebuggerInit; - debugger->d.deinit = DebuggerDeinit; -} + switch (type) { +#ifdef USE_CLI_DEBUGGER + case DEBUGGER_CLI: + CLIDebuggerCreate(&debugger->cli); + struct CLIDebuggerSystem* sys = core->cliDebuggerSystem(core); + CLIDebuggerAttachSystem(&debugger->cli, sys); + break; +#endif +#ifdef USE_GDB_STUB + case DEBUGGER_GDB: + GDBStubCreate(&debugger->gdb); + GDBStubListen(&debugger->gdb, 2345, 0); + break; +#endif + case DEBUGGER_NONE: + case DEBUGGER_MAX: + free(debugger); + return 0; + break; + } -void DebuggerInit(void* cpu, struct mCPUComponent* component) { - struct Debugger* debugger = (struct Debugger*) component; - debugger->cpu = cpu; - debugger->state = DEBUGGER_RUNNING; - debugger->originalMemory = debugger->cpu->memory; - debugger->currentBreakpoint = 0; - DebugBreakpointListInit(&debugger->breakpoints, 0); - DebugBreakpointListInit(&debugger->swBreakpoints, 0); - DebugWatchpointListInit(&debugger->watchpoints, 0); - if (debugger->init) { - debugger->init(debugger); - } + return &debugger->d; } -void DebuggerDeinit(struct mCPUComponent* component) { - struct Debugger* debugger = (struct Debugger*) component; - debugger->deinit(debugger); - DebugBreakpointListDeinit(&debugger->breakpoints); - DebugBreakpointListDeinit(&debugger->swBreakpoints); - DebugWatchpointListDeinit(&debugger->watchpoints); +void mDebuggerAttach(struct mDebugger* debugger, struct mCore* core) { + debugger->d.id = DEBUGGER_ID; + debugger->d.init = mDebuggerInit; + debugger->d.deinit = mDebuggerDeinit; + debugger->core = core; + debugger->platform = core->debuggerPlatform(core); + debugger->platform->p = debugger; + core->attachDebugger(core, debugger); } -void DebuggerRun(struct Debugger* debugger) { +void mDebuggerRun(struct mDebugger* debugger) { switch (debugger->state) { case DEBUGGER_RUNNING: - if (!DebugBreakpointListSize(&debugger->breakpoints) && !DebugWatchpointListSize(&debugger->watchpoints)) { - ARMRunLoop(debugger->cpu); + if (!debugger->platform->hasBreakpoints(debugger->platform)) { + debugger->core->runLoop(debugger->core); } else { - ARMRun(debugger->cpu); - _checkBreakpoints(debugger); + debugger->core->step(debugger->core); + debugger->platform->checkBreakpoints(debugger->platform); } break; case DEBUGGER_CUSTOM: - ARMRun(debugger->cpu); - _checkBreakpoints(debugger); + debugger->core->step(debugger->core); + debugger->platform->checkBreakpoints(debugger->platform); debugger->custom(debugger); break; case DEBUGGER_PAUSED:

@@ -97,89 +95,32 @@ debugger->paused(debugger);

} else { debugger->state = DEBUGGER_RUNNING; } - if (debugger->state != DEBUGGER_PAUSED && debugger->currentBreakpoint) { - if (debugger->currentBreakpoint->isSw && debugger->setSoftwareBreakpoint) { - debugger->setSoftwareBreakpoint(debugger, debugger->currentBreakpoint->address, debugger->currentBreakpoint->sw.mode, &debugger->currentBreakpoint->sw.opcode); - } - debugger->currentBreakpoint = 0; - } break; case DEBUGGER_SHUTDOWN: return; } } -void DebuggerEnter(struct Debugger* debugger, enum DebuggerEntryReason reason, struct DebuggerEntryInfo* info) { +void mDebuggerEnter(struct mDebugger* debugger, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info) { debugger->state = DEBUGGER_PAUSED; - struct ARMCore* cpu = debugger->cpu; - cpu->nextEvent = cpu->cycles; - if (reason == DEBUGGER_ENTER_BREAKPOINT) { - struct DebugBreakpoint* breakpoint = _lookupBreakpoint(&debugger->swBreakpoints, _ARMPCAddress(cpu)); - debugger->currentBreakpoint = breakpoint; - if (breakpoint && breakpoint->isSw) { - info->address = breakpoint->address; - if (debugger->clearSoftwareBreakpoint) { - debugger->clearSoftwareBreakpoint(debugger, breakpoint->address, breakpoint->sw.mode, breakpoint->sw.opcode); - } - - ARMRunFake(cpu, breakpoint->sw.opcode); - } - } if (debugger->entered) { debugger->entered(debugger, reason, info); } } -void DebuggerSetBreakpoint(struct Debugger* debugger, uint32_t address) { - struct DebugBreakpoint* breakpoint = DebugBreakpointListAppend(&debugger->breakpoints); - breakpoint->address = address; - breakpoint->isSw = false; -} - -bool DebuggerSetSoftwareBreakpoint(struct Debugger* debugger, uint32_t address, enum ExecutionMode mode) { - uint32_t opcode; - if (!debugger->setSoftwareBreakpoint || !debugger->setSoftwareBreakpoint(debugger, address, mode, &opcode)) { - return false; +static void mDebuggerInit(void* cpu, struct mCPUComponent* component) { + struct mDebugger* debugger = (struct mDebugger*) component; + debugger->state = DEBUGGER_RUNNING; + debugger->platform->init(cpu, debugger->platform); + if (debugger->init) { + debugger->init(debugger); } - - struct DebugBreakpoint* breakpoint = DebugBreakpointListAppend(&debugger->swBreakpoints); - breakpoint->address = address; - breakpoint->isSw = true; - breakpoint->sw.opcode = opcode; - breakpoint->sw.mode = mode; - - return true; } -void DebuggerClearBreakpoint(struct Debugger* debugger, uint32_t address) { - struct DebugBreakpointList* breakpoints = &debugger->breakpoints; - size_t i; - for (i = 0; i < DebugBreakpointListSize(breakpoints); ++i) { - if (DebugBreakpointListGetPointer(breakpoints, i)->address == address) { - DebugBreakpointListShift(breakpoints, i, 1); - } +static void mDebuggerDeinit(struct mCPUComponent* component) { + struct mDebugger* debugger = (struct mDebugger*) component; + if (debugger->deinit) { + debugger->deinit(debugger); } - -} - -void DebuggerSetWatchpoint(struct Debugger* debugger, uint32_t address, enum WatchpointType type) { - if (!DebugWatchpointListSize(&debugger->watchpoints)) { - DebuggerInstallMemoryShim(debugger); - } - struct DebugWatchpoint* watchpoint = DebugWatchpointListAppend(&debugger->watchpoints); - watchpoint->address = address; - watchpoint->type = type; -} - -void DebuggerClearWatchpoint(struct Debugger* debugger, uint32_t address) { - struct DebugWatchpointList* watchpoints = &debugger->watchpoints; - size_t i; - for (i = 0; i < DebugWatchpointListSize(watchpoints); ++i) { - if (DebugWatchpointListGetPointer(watchpoints, i)->address == address) { - DebugWatchpointListShift(watchpoints, i, 1); - } - } - if (!DebugWatchpointListSize(&debugger->watchpoints)) { - DebuggerRemoveMemoryShim(debugger); - } + debugger->platform->deinit(debugger->platform); }
M src/debugger/debugger.hsrc/debugger/debugger.h

@@ -16,7 +16,7 @@ mLOG_DECLARE_CATEGORY(DEBUGGER);

extern const uint32_t DEBUGGER_ID; -enum DebuggerType { +enum mDebuggerType { DEBUGGER_NONE = 0, #ifdef USE_CLI_DEBUGGER DEBUGGER_CLI,

@@ -27,37 +27,20 @@ #endif

DEBUGGER_MAX }; -enum DebuggerState { +enum mDebuggerState { DEBUGGER_PAUSED, DEBUGGER_RUNNING, DEBUGGER_CUSTOM, DEBUGGER_SHUTDOWN }; -struct DebugBreakpoint { - uint32_t address; - bool isSw; - struct { - uint32_t opcode; - enum ExecutionMode mode; - } sw; -}; - -enum WatchpointType { +enum mWatchpointType { WATCHPOINT_WRITE = 1, WATCHPOINT_READ = 2, WATCHPOINT_RW = WATCHPOINT_WRITE | WATCHPOINT_READ }; -struct DebugWatchpoint { - uint32_t address; - enum WatchpointType type; -}; - -DECLARE_VECTOR(DebugBreakpointList, struct DebugBreakpoint); -DECLARE_VECTOR(DebugWatchpointList, struct DebugWatchpoint); - -enum DebuggerEntryReason { +enum mDebuggerEntryReason { DEBUGGER_ENTER_MANUAL, DEBUGGER_ENTER_ATTACHED, DEBUGGER_ENTER_BREAKPOINT,

@@ -65,14 +48,17 @@ DEBUGGER_ENTER_WATCHPOINT,

DEBUGGER_ENTER_ILLEGAL_OP }; -struct DebuggerEntryInfo { +extern const char* ERROR_MISSING_ARGS; +extern const char* ERROR_OVERFLOW; + +struct mDebuggerEntryInfo { uint32_t address; union { struct { uint32_t oldValue; uint32_t newValue; - enum WatchpointType watchType; - enum WatchpointType accessType; + enum mWatchpointType watchType; + enum mWatchpointType accessType; }; struct {

@@ -81,35 +67,40 @@ };

}; }; -struct Debugger { - struct mCPUComponent d; - enum DebuggerState state; - struct ARMCore* cpu; +struct mDebugger; +struct mDebuggerPlatform { + struct mDebugger* p; + + void (*init)(void* cpu, struct mDebuggerPlatform*); + void (*deinit)(struct mDebuggerPlatform*); + void (*entered)(struct mDebuggerPlatform*, enum mDebuggerEntryReason, struct mDebuggerEntryInfo*); - struct DebugBreakpointList breakpoints; - struct DebugBreakpointList swBreakpoints; - struct DebugWatchpointList watchpoints; - struct ARMMemory originalMemory; + bool (*hasBreakpoints)(struct mDebuggerPlatform*); + void (*setBreakpoint)(struct mDebuggerPlatform*, uint32_t address); + void (*clearBreakpoint)(struct mDebuggerPlatform*, uint32_t address); + void (*setWatchpoint)(struct mDebuggerPlatform*, uint32_t address, enum mWatchpointType type); + void (*clearWatchpoint)(struct mDebuggerPlatform*, uint32_t address); + void (*checkBreakpoints)(struct mDebuggerPlatform*); +}; - struct DebugBreakpoint* currentBreakpoint; +struct mDebugger { + struct mCPUComponent d; + struct mDebuggerPlatform* platform; + enum mDebuggerState state; + struct mCore* core; - void (*init)(struct Debugger*); - void (*deinit)(struct Debugger*); - void (*paused)(struct Debugger*); - void (*entered)(struct Debugger*, enum DebuggerEntryReason, struct DebuggerEntryInfo*); - void (*custom)(struct Debugger*); + void (*init)(struct mDebugger*); + void (*deinit)(struct mDebugger*); - bool (*setSoftwareBreakpoint)(struct Debugger*, uint32_t address, enum ExecutionMode mode, uint32_t* opcode); - bool (*clearSoftwareBreakpoint)(struct Debugger*, uint32_t address, enum ExecutionMode mode, uint32_t opcode); + void (*paused)(struct mDebugger*); + void (*entered)(struct mDebugger*, enum mDebuggerEntryReason, struct mDebuggerEntryInfo*); + void (*custom)(struct mDebugger*); }; -void DebuggerCreate(struct Debugger*); -void DebuggerRun(struct Debugger*); -void DebuggerEnter(struct Debugger*, enum DebuggerEntryReason, struct DebuggerEntryInfo*); -void DebuggerSetBreakpoint(struct Debugger* debugger, uint32_t address); -bool DebuggerSetSoftwareBreakpoint(struct Debugger* debugger, uint32_t address, enum ExecutionMode mode); -void DebuggerClearBreakpoint(struct Debugger* debugger, uint32_t address); -void DebuggerSetWatchpoint(struct Debugger* debugger, uint32_t address, enum WatchpointType type); -void DebuggerClearWatchpoint(struct Debugger* debugger, uint32_t address); +struct mDebugger* mDebuggerCreate(enum mDebuggerType type, struct mCore*); +void mDebuggerAttach(struct mDebugger*, struct mCore*); +void mDebuggerRun(struct mDebugger*); +void mDebuggerEnter(struct mDebugger*, enum mDebuggerEntryReason, struct mDebuggerEntryInfo*); + #endif
M src/debugger/gdb-stub.csrc/debugger/gdb-stub.c

@@ -5,6 +5,8 @@ * 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 "gdb-stub.h" +#include "core/core.h" + #include <signal.h> #ifndef SIGTRAP

@@ -26,14 +28,14 @@ };

static void _sendMessage(struct GDBStub* stub); -static void _gdbStubDeinit(struct Debugger* debugger) { +static void _gdbStubDeinit(struct mDebugger* debugger) { struct GDBStub* stub = (struct GDBStub*) debugger; if (!SOCKET_FAILED(stub->socket)) { GDBStubShutdown(stub); } } -static void _gdbStubEntered(struct Debugger* debugger, enum DebuggerEntryReason reason, struct DebuggerEntryInfo* info) { +static void _gdbStubEntered(struct mDebugger* debugger, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info) { struct GDBStub* stub = (struct GDBStub*) debugger; switch (reason) { case DEBUGGER_ENTER_MANUAL:

@@ -76,7 +78,7 @@ }

_sendMessage(stub); } -static void _gdbStubPoll(struct Debugger* debugger) { +static void _gdbStubPoll(struct mDebugger* debugger) { struct GDBStub* stub = (struct GDBStub*) debugger; --stub->untilPoll; if (stub->untilPoll > 0) {

@@ -87,7 +89,7 @@ stub->shouldBlock = false;

GDBStubUpdate(stub); } -static void _gdbStubWait(struct Debugger* debugger) { +static void _gdbStubWait(struct mDebugger* debugger) { struct GDBStub* stub = (struct GDBStub*) debugger; stub->shouldBlock = true; GDBStubUpdate(stub);

@@ -201,7 +203,7 @@ UNUSED(message);

} static void _step(struct GDBStub* stub, const char* message) { - ARMRun(stub->d.cpu); + stub->d.core->step(stub->d.core); snprintf(stub->outgoing, GDB_STUB_MAX_LINE - 4, "S%02x", SIGTRAP); _sendMessage(stub); // TODO: parse message

@@ -218,7 +220,7 @@ if (size > 512) {

_error(stub, GDB_BAD_ARGUMENTS); return; } - struct ARMCore* cpu = stub->d.cpu; + struct ARMCore* cpu = stub->d.core->cpu; int writeAddress = 0; for (i = 0; i < size; ++i, writeAddress += 2) { uint8_t byte = cpu->memory.load8(cpu, address + i, 0);

@@ -229,11 +231,12 @@ _sendMessage(stub);

} static void _readGPRs(struct GDBStub* stub, const char* message) { + struct ARMCore* cpu = stub->d.core->cpu; UNUSED(message); int r; int i = 0; for (r = 0; r < 16; ++r) { - _int2hex32(stub->d.cpu->gprs[r], &stub->outgoing[i]); + _int2hex32(cpu->gprs[r], &stub->outgoing[i]); i += 8; } stub->outgoing[i] = 0;

@@ -241,14 +244,15 @@ _sendMessage(stub);

} static void _readRegister(struct GDBStub* stub, const char* message) { + struct ARMCore* cpu = stub->d.core->cpu; const char* readAddress = message; unsigned i = 0; uint32_t reg = _readHex(readAddress, &i); uint32_t value; if (reg < 0x10) { - value = stub->d.cpu->gprs[reg]; + value = cpu->gprs[reg]; } else if (reg == 0x19) { - value = stub->d.cpu->cpsr.packed; + value = cpu->cpsr.packed; } else { stub->outgoing[0] = '\0'; _sendMessage(stub);

@@ -298,7 +302,7 @@ static void _processVReadCommand(struct GDBStub* stub, const char* message) {

stub->outgoing[0] = '\0'; if (!strncmp("Attach", message, 6)) { strncpy(stub->outgoing, "1", GDB_STUB_MAX_LINE - 4); - DebuggerEnter(&stub->d, DEBUGGER_ENTER_MANUAL, 0); + mDebuggerEnter(&stub->d, DEBUGGER_ENTER_MANUAL, 0); } _sendMessage(stub); }

@@ -314,22 +318,22 @@

switch (message[0]) { case '0': // Memory breakpoints are not currently supported case '1': - DebuggerSetBreakpoint(&stub->d, address); + stub->d.platform->setBreakpoint(stub->d.platform, address); strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4); _sendMessage(stub); break; case '2': - DebuggerSetWatchpoint(&stub->d, address, WATCHPOINT_WRITE); + stub->d.platform->setWatchpoint(stub->d.platform, address, WATCHPOINT_WRITE); strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4); _sendMessage(stub); break; case '3': - DebuggerSetWatchpoint(&stub->d, address, WATCHPOINT_READ); + stub->d.platform->setWatchpoint(stub->d.platform, address, WATCHPOINT_READ); strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4); _sendMessage(stub); break; case '4': - DebuggerSetWatchpoint(&stub->d, address, WATCHPOINT_RW); + stub->d.platform->setWatchpoint(stub->d.platform, address, WATCHPOINT_RW); strncpy(stub->outgoing, "OK", GDB_STUB_MAX_LINE - 4); _sendMessage(stub); break;

@@ -347,12 +351,12 @@ uint32_t address = _readHex(readAddress, &i);

switch (message[0]) { case '0': // Memory breakpoints are not currently supported case '1': - DebuggerClearBreakpoint(&stub->d, address); + stub->d.platform->clearBreakpoint(stub->d.platform, address); break; case '2': case '3': case '4': - DebuggerClearWatchpoint(&stub->d, address); + stub->d.platform->clearWatchpoint(stub->d.platform, address); break; default: break;

@@ -375,7 +379,7 @@ case '$':

++message; break; case '\x03': - DebuggerEnter(&stub->d, DEBUGGER_ENTER_MANUAL, 0); + mDebuggerEnter(&stub->d, DEBUGGER_ENTER_MANUAL, 0); return parsed; default: _nak(stub);

@@ -462,7 +466,6 @@ return parsed;

} void GDBStubCreate(struct GDBStub* stub) { - DebuggerCreate(&stub->d); stub->socket = INVALID_SOCKET; stub->connection = INVALID_SOCKET; stub->d.init = 0;

@@ -536,7 +539,7 @@ if (!SOCKET_FAILED(stub->connection)) {

if (!SocketSetBlocking(stub->connection, false)) { goto connectionLost; } - DebuggerEnter(&stub->d, DEBUGGER_ENTER_ATTACHED, 0); + mDebuggerEnter(&stub->d, DEBUGGER_ENTER_ATTACHED, 0); } else if (SocketWouldBlock()) { return; } else {
M src/debugger/gdb-stub.hsrc/debugger/gdb-stub.h

@@ -23,7 +23,7 @@ GDB_ACK_OFF

}; struct GDBStub { - struct Debugger d; + struct mDebugger d; char line[GDB_STUB_MAX_LINE]; char outgoing[GDB_STUB_MAX_LINE];
M src/debugger/memory-debugger.csrc/arm/memory-debugger.c

@@ -5,13 +5,13 @@ * 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 "memory-debugger.h" -#include "debugger.h" +#include "arm/debugger.h" #include "util/math.h" #include <string.h> -static bool _checkWatchpoints(struct Debugger* debugger, uint32_t address, struct DebuggerEntryInfo* info, enum WatchpointType type, uint32_t newValue, int width); +static bool _checkWatchpoints(struct ARMDebugger* debugger, uint32_t address, struct mDebuggerEntryInfo* info, enum mWatchpointType type, uint32_t newValue, int width); #define FIND_DEBUGGER(DEBUGGER, CPU) \ { \

@@ -19,7 +19,7 @@ DEBUGGER = 0; \

size_t i; \ for (i = 0; i < CPU->numComponents; ++i) { \ if (CPU->components[i]->id == DEBUGGER_ID) { \ - DEBUGGER = (struct Debugger*) cpu->components[i]; \ + DEBUGGER = (struct ARMDebugger*) cpu->components[i]; \ break; \ } \ } \

@@ -27,36 +27,36 @@ }

#define CREATE_SHIM(NAME, RETURN, TYPES, ...) \ static RETURN DebuggerShim_ ## NAME TYPES { \ - struct Debugger* debugger; \ + struct ARMDebugger* debugger; \ FIND_DEBUGGER(debugger, cpu); \ return debugger->originalMemory.NAME(cpu, __VA_ARGS__); \ } #define CREATE_WATCHPOINT_READ_SHIM(NAME, WIDTH, RETURN, TYPES, ...) \ static RETURN DebuggerShim_ ## NAME TYPES { \ - struct Debugger* debugger; \ + struct ARMDebugger* debugger; \ FIND_DEBUGGER(debugger, cpu); \ - struct DebuggerEntryInfo info; \ + struct mDebuggerEntryInfo info; \ if (_checkWatchpoints(debugger, address, &info, WATCHPOINT_READ, 0, WIDTH)) { \ - DebuggerEnter(debugger, DEBUGGER_ENTER_WATCHPOINT, &info); \ + mDebuggerEnter(debugger->d.p, DEBUGGER_ENTER_WATCHPOINT, &info); \ } \ return debugger->originalMemory.NAME(cpu, __VA_ARGS__); \ } #define CREATE_WATCHPOINT_WRITE_SHIM(NAME, WIDTH, RETURN, TYPES, ...) \ static RETURN DebuggerShim_ ## NAME TYPES { \ - struct Debugger* debugger; \ + struct ARMDebugger* debugger; \ FIND_DEBUGGER(debugger, cpu); \ - struct DebuggerEntryInfo info; \ + struct mDebuggerEntryInfo info; \ if (_checkWatchpoints(debugger, address, &info, WATCHPOINT_WRITE, value, WIDTH)) { \ - DebuggerEnter(debugger, DEBUGGER_ENTER_WATCHPOINT, &info); \ + mDebuggerEnter(debugger->d.p, DEBUGGER_ENTER_WATCHPOINT, &info); \ } \ return debugger->originalMemory.NAME(cpu, __VA_ARGS__); \ } #define CREATE_MULTIPLE_WATCHPOINT_SHIM(NAME, ACCESS_TYPE) \ static uint32_t DebuggerShim_ ## NAME (struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) { \ - struct Debugger* debugger; \ + struct ARMDebugger* debugger; \ FIND_DEBUGGER(debugger, cpu); \ uint32_t popcount = popcount32(mask); \ int offset = 4; \

@@ -70,9 +70,9 @@ base += offset; \

} \ unsigned i; \ for (i = 0; i < popcount; ++i) { \ - struct DebuggerEntryInfo info; \ + struct mDebuggerEntryInfo info; \ if (_checkWatchpoints(debugger, base + 4 * i, &info, ACCESS_TYPE, 0, 4)) { \ - DebuggerEnter(debugger, DEBUGGER_ENTER_WATCHPOINT, &info); \ + mDebuggerEnter(debugger->d.p, DEBUGGER_ENTER_WATCHPOINT, &info); \ } \ } \ return debugger->originalMemory.NAME(cpu, address, mask, direction, cycleCounter); \

@@ -88,12 +88,12 @@ CREATE_MULTIPLE_WATCHPOINT_SHIM(loadMultiple, WATCHPOINT_READ)

CREATE_MULTIPLE_WATCHPOINT_SHIM(storeMultiple, WATCHPOINT_WRITE) CREATE_SHIM(setActiveRegion, void, (struct ARMCore* cpu, uint32_t address), address) -static bool _checkWatchpoints(struct Debugger* debugger, uint32_t address, struct DebuggerEntryInfo* info, enum WatchpointType type, uint32_t newValue, int width) { +static bool _checkWatchpoints(struct ARMDebugger* debugger, uint32_t address, struct mDebuggerEntryInfo* info, enum mWatchpointType type, uint32_t newValue, int width) { --width; - struct DebugWatchpoint* watchpoint; + struct ARMDebugWatchpoint* watchpoint; size_t i; - for (i = 0; i < DebugWatchpointListSize(&debugger->watchpoints); ++i) { - watchpoint = DebugWatchpointListGetPointer(&debugger->watchpoints, i); + for (i = 0; i < ARMDebugWatchpointListSize(&debugger->watchpoints); ++i) { + watchpoint = ARMDebugWatchpointListGetPointer(&debugger->watchpoints, i); if (!((watchpoint->address ^ address) & ~width) && watchpoint->type & type) { switch (width + 1) { case 1:

@@ -116,7 +116,7 @@ }

return false; } -void DebuggerInstallMemoryShim(struct Debugger* debugger) { +void ARMDebuggerInstallMemoryShim(struct ARMDebugger* debugger) { debugger->originalMemory = debugger->cpu->memory; debugger->cpu->memory.store32 = DebuggerShim_store32; debugger->cpu->memory.store16 = DebuggerShim_store16;

@@ -129,7 +129,7 @@ debugger->cpu->memory.loadMultiple = DebuggerShim_loadMultiple;

debugger->cpu->memory.setActiveRegion = DebuggerShim_setActiveRegion; } -void DebuggerRemoveMemoryShim(struct Debugger* debugger) { +void ARMDebuggerRemoveMemoryShim(struct ARMDebugger* debugger) { debugger->cpu->memory.store32 = debugger->originalMemory.store32; debugger->cpu->memory.store16 = debugger->originalMemory.store16; debugger->cpu->memory.store8 = debugger->originalMemory.store8;
M src/debugger/memory-debugger.hsrc/arm/memory-debugger.h

@@ -8,11 +8,9 @@ #define MEMORY_DEBUGGER_H

#include "util/common.h" -#include "arm.h" - -struct Debugger; +struct ARMDebugger; -void DebuggerInstallMemoryShim(struct Debugger* debugger); -void DebuggerRemoveMemoryShim(struct Debugger* debugger); +void ARMDebuggerInstallMemoryShim(struct ARMDebugger* debugger); +void ARMDebuggerRemoveMemoryShim(struct ARMDebugger* debugger); #endif
M src/gb/core.csrc/gb/core.c

@@ -254,12 +254,56 @@ struct GB* gb = core->board;

gb->memory.rumble = rumble; } +static uint32_t _GBCoreBusRead8(struct mCore* core, uint32_t address) { + struct LR35902Core* cpu = core->cpu; + return cpu->memory.load8(cpu, address); +} + +static uint32_t _GBCoreBusRead16(struct mCore* core, uint32_t address) { + struct LR35902Core* cpu = core->cpu; + return cpu->memory.load8(cpu, address) | (cpu->memory.load8(cpu, address + 1) << 8); +} + +static uint32_t _GBCoreBusRead32(struct mCore* core, uint32_t address) { + struct LR35902Core* cpu = core->cpu; + return cpu->memory.load8(cpu, address) | (cpu->memory.load8(cpu, address + 1) << 8) | + (cpu->memory.load8(cpu, address + 2) << 16) | (cpu->memory.load8(cpu, address + 3) << 24); +} + +static void _GBCoreBusWrite8(struct mCore* core, uint32_t address, uint8_t value) { + struct LR35902Core* cpu = core->cpu; + cpu->memory.store8(cpu, address, value); +} + +static void _GBCoreBusWrite16(struct mCore* core, uint32_t address, uint16_t value) { + struct LR35902Core* cpu = core->cpu; + cpu->memory.store8(cpu, address, value); + cpu->memory.store8(cpu, address + 1, value >> 8); +} + +static void _GBCoreBusWrite32(struct mCore* core, uint32_t address, uint32_t value) { + struct LR35902Core* cpu = core->cpu; + cpu->memory.store8(cpu, address, value); + cpu->memory.store8(cpu, address + 1, value >> 8); + cpu->memory.store8(cpu, address + 2, value >> 16); + cpu->memory.store8(cpu, address + 3, value >> 24); +} + +static bool _GBCoreSupportsDebuggerType(struct mCore* core, enum mDebuggerType type) { + return false; +} + +static struct mDebuggerPlatform* _GBCoreDebuggerPlatform(struct mCore* core) { + return 0; +} + struct mCore* GBCoreCreate(void) { struct GBCore* gbcore = malloc(sizeof(*gbcore)); struct mCore* core = &gbcore->d; memset(&core->opts, 0, sizeof(core->opts)); - core->cpu = 0; - core->board = 0; + core->cpu = NULL; + core->board = NULL; + core->debugger = NULL; core->init = _GBCoreInit; core->deinit = _GBCoreDeinit; core->platform = _GBCorePlatform;

@@ -295,5 +339,13 @@ core->getGameCode = _GBCoreGetGameCode;

core->setRTC = _GBCoreSetRTC; core->setRotation = _GBCoreSetRotation; core->setRumble = _GBCoreSetRumble; + core->busRead8 = _GBCoreBusRead8; + core->busRead16 = _GBCoreBusRead16; + core->busRead32 = _GBCoreBusRead32; + core->busWrite8 = _GBCoreBusWrite8; + core->busWrite16 = _GBCoreBusWrite16; + core->busWrite32 = _GBCoreBusWrite32; + core->supportsDebuggerType = _GBCoreSupportsDebuggerType; + core->debuggerPlatform = _GBCoreDebuggerPlatform; return core; }
M src/gba/cheats.csrc/gba/cheats.c

@@ -165,11 +165,12 @@ }

} void GBACheatAttachDevice(struct GBA* gba, struct GBACheatDevice* device) { - if (gba->cpu->components[GBA_COMPONENT_CHEAT_DEVICE]) { - ARMHotplugDetach(gba->cpu, GBA_COMPONENT_CHEAT_DEVICE); + // TODO: Remove this function + if (gba->cpu->components[CPU_COMPONENT_CHEAT_DEVICE]) { + ARMHotplugDetach(gba->cpu, CPU_COMPONENT_CHEAT_DEVICE); } - gba->cpu->components[GBA_COMPONENT_CHEAT_DEVICE] = &device->d; - ARMHotplugAttach(gba->cpu, GBA_COMPONENT_CHEAT_DEVICE); + gba->cpu->components[CPU_COMPONENT_CHEAT_DEVICE] = &device->d; + ARMHotplugAttach(gba->cpu, CPU_COMPONENT_CHEAT_DEVICE); } void GBACheatAddSet(struct GBACheatDevice* device, struct GBACheatSet* cheats) {
M src/gba/core.csrc/gba/core.c

@@ -11,6 +11,7 @@ #include "gba/gba.h"

#include "gba/context/overrides.h" #include "gba/renderers/video-software.h" #include "gba/serialize.h" +#include "gba/supervisor/cli.h" #include "util/memory.h" #include "util/patch.h" #include "util/vfs.h"

@@ -19,8 +20,9 @@ struct GBACore {

struct mCore d; struct GBAVideoSoftwareRenderer renderer; int keys; - struct mCPUComponent* components[GBA_COMPONENT_MAX]; + struct mCPUComponent* components[CPU_COMPONENT_MAX]; const struct Configuration* overrides; + struct mDebuggerPlatform* debuggerPlatform; }; static bool _GBACoreInit(struct mCore* core) {

@@ -35,12 +37,14 @@ return false;

} core->cpu = cpu; core->board = gba; + core->debugger = NULL; + gbacore->debuggerPlatform = NULL; gbacore->overrides = 0; GBACreate(gba); // TODO: Restore debugger and cheats memset(gbacore->components, 0, sizeof(gbacore->components)); - ARMSetComponents(cpu, &gba->d, GBA_COMPONENT_MAX, gbacore->components); + ARMSetComponents(cpu, &gba->d, CPU_COMPONENT_MAX, gbacore->components); ARMInit(cpu); GBAVideoSoftwareRendererCreate(&gbacore->renderer);

@@ -288,12 +292,90 @@ struct GBA* gba = core->board;

gba->rumble = rumble; } +static uint32_t _GBACoreBusRead8(struct mCore* core, uint32_t address) { + struct ARMCore* cpu = core->cpu; + return cpu->memory.load8(cpu, address, 0); +} + +static uint32_t _GBACoreBusRead16(struct mCore* core, uint32_t address) { + struct ARMCore* cpu = core->cpu; + return cpu->memory.load8(cpu, address, 0); + +} + +static uint32_t _GBACoreBusRead32(struct mCore* core, uint32_t address) { + struct ARMCore* cpu = core->cpu; + return cpu->memory.load32(cpu, address, 0); +} + +static void _GBACoreBusWrite8(struct mCore* core, uint32_t address, uint8_t value) { + struct ARMCore* cpu = core->cpu; + cpu->memory.store8(cpu, address, value, 0); +} + +static void _GBACoreBusWrite16(struct mCore* core, uint32_t address, uint16_t value) { + struct ARMCore* cpu = core->cpu; + cpu->memory.store16(cpu, address, value, 0); +} + +static void _GBACoreBusWrite32(struct mCore* core, uint32_t address, uint32_t value) { + struct ARMCore* cpu = core->cpu; + cpu->memory.store32(cpu, address, value, 0); +} + +static bool _GBACoreSupportsDebuggerType(struct mCore* core, enum mDebuggerType type) { + UNUSED(core); + switch (type) { +#ifdef USE_CLI_DEBUGGER + case DEBUGGER_CLI: + return true; +#endif +#ifdef USE_GDB_STUB + case DEBUGGER_GDB: + return true; +#endif + default: + return false; + } +} + +static struct mDebuggerPlatform* _GBACoreDebuggerPlatform(struct mCore* core) { + struct GBACore* gbacore = (struct GBACore*) core; + if (!gbacore->debuggerPlatform) { + gbacore->debuggerPlatform = ARMDebuggerPlatformCreate(); + } + return gbacore->debuggerPlatform; +} + +static struct CLIDebuggerSystem* _GBACoreCliDebuggerSystem(struct mCore* core) { +#ifdef USE_CLI_DEBUGGER + return &GBACLIDebuggerCreate(core)->d; +#else + UNUSED(core); + return NULL; +#endif +} + +static void _GBACoreAttachDebugger(struct mCore* core, struct mDebugger* debugger) { + if (core->debugger) { + GBADetachDebugger(core->board); + } + GBAAttachDebugger(core->board, debugger); + core->debugger = debugger; +} + +static void _GBACoreDetachDebugger(struct mCore* core) { + GBADetachDebugger(core->board); + core->debugger = NULL; +} + struct mCore* GBACoreCreate(void) { struct GBACore* gbacore = malloc(sizeof(*gbacore)); struct mCore* core = &gbacore->d; memset(&core->opts, 0, sizeof(core->opts)); - core->cpu = 0; - core->board = 0; + core->cpu = NULL; + core->board = NULL; + core->debugger = NULL; core->init = _GBACoreInit; core->deinit = _GBACoreDeinit; core->platform = _GBACorePlatform;

@@ -329,5 +411,16 @@ core->getGameCode = _GBACoreGetGameCode;

core->setRTC = _GBACoreSetRTC; core->setRotation = _GBACoreSetRotation; core->setRumble = _GBACoreSetRumble; + core->busRead8 = _GBACoreBusRead8; + core->busRead16 = _GBACoreBusRead16; + core->busRead32 = _GBACoreBusRead32; + core->busWrite8 = _GBACoreBusWrite8; + core->busWrite16 = _GBACoreBusWrite16; + core->busWrite32 = _GBACoreBusWrite32; + core->supportsDebuggerType = _GBACoreSupportsDebuggerType; + core->debuggerPlatform = _GBACoreDebuggerPlatform; + core->cliDebuggerSystem = _GBACoreCliDebuggerSystem; + core->attachDebugger = _GBACoreAttachDebugger; + core->detachDebugger = _GBACoreDetachDebugger; return core; }
M src/gba/gba.csrc/gba/gba.c

@@ -42,8 +42,8 @@ static void GBAHitStub(struct ARMCore* cpu, uint32_t opcode);

static void GBAIllegal(struct ARMCore* cpu, uint32_t opcode); static void GBABreakpoint(struct ARMCore* cpu, int immediate); -static bool _setSoftwareBreakpoint(struct Debugger*, uint32_t address, enum ExecutionMode mode, uint32_t* opcode); -static bool _clearSoftwareBreakpoint(struct Debugger*, uint32_t address, enum ExecutionMode mode, uint32_t opcode); +static bool _setSoftwareBreakpoint(struct ARMDebugger*, uint32_t address, enum ExecutionMode mode, uint32_t* opcode); +static bool _clearSoftwareBreakpoint(struct ARMDebugger*, uint32_t address, enum ExecutionMode mode, uint32_t opcode); #ifdef _3DS

@@ -403,18 +403,18 @@ }

return nextEvent; } -void GBAAttachDebugger(struct GBA* gba, struct Debugger* debugger) { - debugger->setSoftwareBreakpoint = _setSoftwareBreakpoint; - debugger->clearSoftwareBreakpoint = _clearSoftwareBreakpoint; - gba->debugger = debugger; - gba->cpu->components[GBA_COMPONENT_DEBUGGER] = &debugger->d; - ARMHotplugAttach(gba->cpu, GBA_COMPONENT_DEBUGGER); +void GBAAttachDebugger(struct GBA* gba, struct mDebugger* debugger) { + gba->debugger = (struct ARMDebugger*) debugger->platform; + gba->debugger->setSoftwareBreakpoint = _setSoftwareBreakpoint; + gba->debugger->clearSoftwareBreakpoint = _clearSoftwareBreakpoint; + gba->cpu->components[CPU_COMPONENT_DEBUGGER] = &debugger->d; + ARMHotplugAttach(gba->cpu, CPU_COMPONENT_DEBUGGER); } void GBADetachDebugger(struct GBA* gba) { gba->debugger = 0; - ARMHotplugDetach(gba->cpu, GBA_COMPONENT_DEBUGGER); - gba->cpu->components[GBA_COMPONENT_DEBUGGER] = 0; + ARMHotplugDetach(gba->cpu, CPU_COMPONENT_DEBUGGER); + gba->cpu->components[CPU_COMPONENT_DEBUGGER] = 0; } bool GBALoadMB(struct GBA* gba, struct VFile* vf) {

@@ -731,11 +731,11 @@

void GBAHitStub(struct ARMCore* cpu, uint32_t opcode) { struct GBA* gba = (struct GBA*) cpu->master; if (gba->debugger) { - struct DebuggerEntryInfo info = { + struct mDebuggerEntryInfo info = { .address = _ARMPCAddress(cpu), .opcode = opcode }; - DebuggerEnter(gba->debugger, DEBUGGER_ENTER_ILLEGAL_OP, &info); + mDebuggerEnter(gba->debugger->d.p, DEBUGGER_ENTER_ILLEGAL_OP, &info); } // TODO: More sensible category? mLOG(GBA, ERROR, "Stub opcode: %08x", opcode);

@@ -748,11 +748,11 @@ // TODO: More sensible category?

mLOG(GBA, WARN, "Illegal opcode: %08x", opcode); } if (gba->debugger) { - struct DebuggerEntryInfo info = { + struct mDebuggerEntryInfo info = { .address = _ARMPCAddress(cpu), .opcode = opcode }; - DebuggerEnter(gba->debugger, DEBUGGER_ENTER_ILLEGAL_OP, &info); + mDebuggerEnter(gba->debugger->d.p, DEBUGGER_ENTER_ILLEGAL_OP, &info); } else { ARMRaiseUndefined(cpu); }

@@ -760,21 +760,21 @@ }

void GBABreakpoint(struct ARMCore* cpu, int immediate) { struct GBA* gba = (struct GBA*) cpu->master; - if (immediate >= GBA_COMPONENT_MAX) { + if (immediate >= CPU_COMPONENT_MAX) { return; } switch (immediate) { - case GBA_COMPONENT_DEBUGGER: + case CPU_COMPONENT_DEBUGGER: if (gba->debugger) { - struct DebuggerEntryInfo info = { + struct mDebuggerEntryInfo info = { .address = _ARMPCAddress(cpu) }; - DebuggerEnter(gba->debugger, DEBUGGER_ENTER_BREAKPOINT, &info); + mDebuggerEnter(gba->debugger->d.p, DEBUGGER_ENTER_BREAKPOINT, &info); } break; - case GBA_COMPONENT_CHEAT_DEVICE: - if (gba->cpu->components[GBA_COMPONENT_CHEAT_DEVICE]) { - struct GBACheatDevice* device = (struct GBACheatDevice*) gba->cpu->components[GBA_COMPONENT_CHEAT_DEVICE]; + case CPU_COMPONENT_CHEAT_DEVICE: + if (gba->cpu->components[CPU_COMPONENT_CHEAT_DEVICE]) { + struct GBACheatDevice* device = (struct GBACheatDevice*) gba->cpu->components[CPU_COMPONENT_CHEAT_DEVICE]; struct GBACheatHook* hook = 0; size_t i; for (i = 0; i < GBACheatSetsSize(&device->cheats); ++i) {

@@ -807,8 +807,8 @@ if (gba->rr) {

gba->rr->nextFrame(gba->rr); } - if (gba->cpu->components && gba->cpu->components[GBA_COMPONENT_CHEAT_DEVICE]) { - struct GBACheatDevice* device = (struct GBACheatDevice*) gba->cpu->components[GBA_COMPONENT_CHEAT_DEVICE]; + if (gba->cpu->components && gba->cpu->components[CPU_COMPONENT_CHEAT_DEVICE]) { + struct GBACheatDevice* device = (struct GBACheatDevice*) gba->cpu->components[CPU_COMPONENT_CHEAT_DEVICE]; size_t i; for (i = 0; i < GBACheatSetsSize(&device->cheats); ++i) { struct GBACheatSet* cheats = *GBACheatSetsGetPointer(&device->cheats, i);

@@ -877,12 +877,12 @@ GBAPatch16(gba->cpu, address, opcode, 0);

} } -static bool _setSoftwareBreakpoint(struct Debugger* debugger, uint32_t address, enum ExecutionMode mode, uint32_t* opcode) { - GBASetBreakpoint((struct GBA*) debugger->cpu->master, &debugger->d, address, mode, opcode); +static bool _setSoftwareBreakpoint(struct ARMDebugger* debugger, uint32_t address, enum ExecutionMode mode, uint32_t* opcode) { + GBASetBreakpoint((struct GBA*) debugger->cpu->master, &debugger->d.p->d, address, mode, opcode); return true; } -static bool _clearSoftwareBreakpoint(struct Debugger* debugger, uint32_t address, enum ExecutionMode mode, uint32_t opcode) { +static bool _clearSoftwareBreakpoint(struct ARMDebugger* debugger, uint32_t address, enum ExecutionMode mode, uint32_t opcode) { GBAClearBreakpoint((struct GBA*) debugger->cpu->master, address, mode, opcode); return true; }
M src/gba/gba.hsrc/gba/gba.h

@@ -9,8 +9,8 @@

#include "util/common.h" #include "arm/arm.h" +#include "arm/debugger.h" #include "core/log.h" -#include "debugger/debugger.h" #include "gba/interface.h" #include "gba/memory.h"

@@ -37,12 +37,6 @@ IRQ_KEYPAD = 0xC,

IRQ_GAMEPAK = 0xD }; -enum GBAComponent { - GBA_COMPONENT_DEBUGGER, - GBA_COMPONENT_CHEAT_DEVICE, - GBA_COMPONENT_MAX -}; - enum GBAIdleLoopOptimization { IDLE_LOOP_IGNORE = -1, IDLE_LOOP_REMOVE = 0,

@@ -87,7 +81,7 @@ struct GBASIO sio;

struct mCoreSync* sync; - struct Debugger* debugger; + struct ARMDebugger* debugger; uint32_t bus; int performingDMA;

@@ -161,7 +155,7 @@ void GBATestIRQ(struct ARMCore* cpu);

void GBAHalt(struct GBA* gba); void GBAStop(struct GBA* gba); -void GBAAttachDebugger(struct GBA* gba, struct Debugger* debugger); +void GBAAttachDebugger(struct GBA* gba, struct mDebugger* debugger); void GBADetachDebugger(struct GBA* gba); void GBASetBreakpoint(struct GBA* gba, struct mCPUComponent* component, uint32_t address, enum ExecutionMode mode,
M src/gba/serialize.csrc/gba/serialize.c

@@ -382,8 +382,8 @@ }

svf->close(svf); } struct VFile* cheatVf = 0; - if (flags & SAVESTATE_CHEATS && gba->cpu->components && gba->cpu->components[GBA_COMPONENT_CHEAT_DEVICE]) { - struct GBACheatDevice* device = (struct GBACheatDevice*) gba->cpu->components[GBA_COMPONENT_CHEAT_DEVICE]; + if (flags & SAVESTATE_CHEATS && gba->cpu->components && gba->cpu->components[CPU_COMPONENT_CHEAT_DEVICE]) { + struct GBACheatDevice* device = (struct GBACheatDevice*) gba->cpu->components[CPU_COMPONENT_CHEAT_DEVICE]; cheatVf = VFileMemChunk(0, 0); if (cheatVf) { GBACheatSaveFile(device, cheatVf);

@@ -477,9 +477,9 @@ if (svf) {

svf->close(svf); } } - if (flags & SAVESTATE_CHEATS && gba->cpu->components && gba->cpu->components[GBA_COMPONENT_CHEAT_DEVICE] && GBAExtdataGet(&extdata, EXTDATA_CHEATS, &item)) { + if (flags & SAVESTATE_CHEATS && gba->cpu->components && gba->cpu->components[CPU_COMPONENT_CHEAT_DEVICE] && GBAExtdataGet(&extdata, EXTDATA_CHEATS, &item)) { if (item.size) { - struct GBACheatDevice* device = (struct GBACheatDevice*) gba->cpu->components[GBA_COMPONENT_CHEAT_DEVICE]; + struct GBACheatDevice* device = (struct GBACheatDevice*) gba->cpu->components[CPU_COMPONENT_CHEAT_DEVICE]; struct VFile* svf = VFileFromMemory(item.data, item.size); if (svf) { GBACheatDeviceClear(device);
M src/gba/supervisor/cli.csrc/gba/supervisor/cli.c

@@ -5,12 +5,11 @@ * 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 "cli.h" +#include "arm/cli-debugger.h" #include "gba/io.h" #include "gba/serialize.h" #ifdef USE_CLI_DEBUGGER - -static const char* ERROR_MISSING_ARGS = "Arguments missing"; // TODO: share static void _GBACLIDebuggerInit(struct CLIDebuggerSystem*); static void _GBACLIDebuggerDeinit(struct CLIDebuggerSystem*);

@@ -32,6 +31,7 @@ };

struct GBACLIDebugger* GBACLIDebuggerCreate(struct mCore* core) { struct GBACLIDebugger* debugger = malloc(sizeof(struct GBACLIDebugger)); + ARMCLIDebuggerCreate(&debugger->d); debugger->d.init = _GBACLIDebuggerInit; debugger->d.deinit = _GBACLIDebuggerDeinit; debugger->d.custom = _GBACLIDebuggerCustom;

@@ -60,7 +60,7 @@ struct GBACLIDebugger* gbaDebugger = (struct GBACLIDebugger*) debugger;

if (gbaDebugger->frameAdvance) { if (!gbaDebugger->inVblank && GBARegisterDISPSTATIsInVblank(((struct GBA*) gbaDebugger->core->board)->memory.io[REG_DISPSTAT >> 1])) { - DebuggerEnter(&gbaDebugger->d.p->d, DEBUGGER_ENTER_MANUAL, 0); + mDebuggerEnter(&gbaDebugger->d.p->d, DEBUGGER_ENTER_MANUAL, 0); gbaDebugger->frameAdvance = false; return false; }
M src/platform/commandline.csrc/platform/commandline.c

@@ -4,19 +4,6 @@ * 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 "commandline.h" - -#include "debugger/debugger.h" - -#ifdef USE_CLI_DEBUGGER -#include "debugger/cli-debugger.h" -#include "gba/supervisor/cli.h" -#endif - -#ifdef USE_GDB_STUB -#include "debugger/gdb-stub.h" -#endif - -#include "gba/video.h" #include "util/string.h" #include <fcntl.h>

@@ -209,46 +196,6 @@

void _applyGraphicsArgs(struct mSubParser* parser, struct mCoreConfig* config) { struct mGraphicsOpts* graphicsOpts = parser->opts; mCoreConfigSetOverrideIntValue(config, "fullscreen", graphicsOpts->fullscreen); -} - -struct Debugger* createDebugger(struct mArguments* opts, struct mCore* core) { -#ifndef USE_CLI_DEBUGGER - UNUSED(core); -#endif - union DebugUnion { - struct Debugger d; -#ifdef USE_CLI_DEBUGGER - struct CLIDebugger cli; -#endif -#ifdef USE_GDB_STUB - struct GDBStub gdb; -#endif - }; - - union DebugUnion* debugger = malloc(sizeof(union DebugUnion)); - - switch (opts->debuggerType) { -#ifdef USE_CLI_DEBUGGER - case DEBUGGER_CLI: - CLIDebuggerCreate(&debugger->cli); - struct GBACLIDebugger* gbaDebugger = GBACLIDebuggerCreate(core); - CLIDebuggerAttachSystem(&debugger->cli, &gbaDebugger->d); - break; -#endif -#ifdef USE_GDB_STUB - case DEBUGGER_GDB: - GDBStubCreate(&debugger->gdb); - GDBStubListen(&debugger->gdb, 2345, 0); - break; -#endif - case DEBUGGER_NONE: - case DEBUGGER_MAX: - free(debugger); - return 0; - break; - } - - return &debugger->d; } void usage(const char* arg0, const char* extraOptions) {
M src/platform/commandline.hsrc/platform/commandline.h

@@ -19,7 +19,7 @@ char* bios;

int logLevel; int frameskip; - enum DebuggerType debuggerType; + enum mDebuggerType debuggerType; bool debugAtStart; bool showHelp; bool showVersion;

@@ -48,7 +48,5 @@ void usage(const char* arg0, const char* extraOptions);

void version(const char* arg0); void initParserForGraphics(struct mSubParser* parser, struct mGraphicsOpts* opts); -struct mCore; -struct Debugger* createDebugger(struct mArguments* opts, struct mCore* core); #endif
M src/platform/qt/GDBController.cppsrc/platform/qt/GDBController.cpp

@@ -41,12 +41,12 @@ return;

} m_gameController->setDebugger(&m_gdbStub.d); if (m_gameController->isLoaded()) { - DebuggerEnter(&m_gdbStub.d, DEBUGGER_ENTER_ATTACHED, 0); + mDebuggerEnter(&m_gdbStub.d, DEBUGGER_ENTER_ATTACHED, 0); } else { QObject::disconnect(m_autoattach); m_autoattach = connect(m_gameController, &GameController::gameStarted, [this]() { QObject::disconnect(m_autoattach); - DebuggerEnter(&m_gdbStub.d, DEBUGGER_ENTER_ATTACHED, 0); + mDebuggerEnter(&m_gdbStub.d, DEBUGGER_ENTER_ATTACHED, 0); }); } }

@@ -81,6 +81,6 @@ if (!isAttached()) {

return; } m_gameController->threadInterrupt(); - DebuggerEnter(&m_gdbStub.d, DEBUGGER_ENTER_MANUAL, 0); + mDebuggerEnter(&m_gdbStub.d, DEBUGGER_ENTER_MANUAL, 0); m_gameController->threadContinue(); }
M src/platform/qt/GameController.cppsrc/platform/qt/GameController.cpp

@@ -271,14 +271,20 @@ }

} #ifdef USE_GDB_STUB -Debugger* GameController::debugger() { - // TODO: Put back debugger - return nullptr; +mDebugger* GameController::debugger() { + if (!isLoaded()) { + return nullptr; + } + return m_threadContext.core->debugger; } -void GameController::setDebugger(Debugger* debugger) { +void GameController::setDebugger(mDebugger* debugger) { threadInterrupt(); - // TODO: Put back debugger + if (debugger) { + mDebuggerAttach(debugger, m_threadContext.core); + } else { + m_threadContext.core->detachDebugger(m_threadContext.core); + } threadContinue(); } #endif
M src/platform/qt/GameController.hsrc/platform/qt/GameController.h

@@ -30,7 +30,7 @@

struct GBAAudio; struct mCoreConfig; struct Configuration; -struct Debugger; +struct mDebugger; class QThread;

@@ -79,8 +79,8 @@

int stateSlot() const { return m_stateSlot; } #ifdef USE_GDB_STUB - Debugger* debugger(); - void setDebugger(Debugger*); + mDebugger* debugger(); + void setDebugger(mDebugger*); #endif signals:
M src/platform/sdl/main.csrc/platform/sdl/main.c

@@ -158,7 +158,11 @@ if (!mCoreLoadFile(renderer->core, args->fname)) {

return 1; } mCoreAutoloadSave(renderer->core); - // TODO: Put back debugger + struct mDebugger* debugger = mDebuggerCreate(args->debuggerType, renderer->core); + if (debugger) { + mDebuggerAttach(debugger, renderer->core); + mDebuggerEnter(debugger, DEBUGGER_ENTER_MANUAL, NULL); + } if (args->patch) { struct VFile* patch = VFileOpen(args->patch, O_RDONLY);
M src/platform/sdl/sdl-events.csrc/platform/sdl/sdl-events.c

@@ -407,7 +407,9 @@ }

if (event->type == SDL_KEYDOWN) { switch (event->keysym.sym) { case SDLK_F11: - // TODO: Put back debugger + if (context->core->debugger) { + mDebuggerEnter(context->core->debugger, DEBUGGER_ENTER_MANUAL, NULL); + } return; #ifdef USE_PNG case SDLK_F12: