Debugger: Modularize CLI debugger

This commit is contained in:
Jeffrey Pfau 2016-10-25 21:12:35 -07:00
parent 474f1c6e9c
commit a0d223eef7
18 changed files with 380 additions and 267 deletions

View File

@ -29,6 +29,7 @@ Misc:
- PSP2: Improved controller rumble - PSP2: Improved controller rumble
- GB, GBA: Prevent loading null ROMs - GB, GBA: Prevent loading null ROMs
- VFS: Allow truncating memory chunk VFiles - VFS: Allow truncating memory chunk VFiles
- Debugger: Modularize CLI debugger
0.5.1: (2016-10-05) 0.5.1: (2016-10-05)
Bugfixes: Bugfixes:

View File

@ -6,7 +6,7 @@ if(NOT MSVC)
else() else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CRT_SECURE_NO_WARNINGS /wd4003 /wd4244 /wd4146") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CRT_SECURE_NO_WARNINGS /wd4003 /wd4244 /wd4146")
endif() endif()
set(USE_CLI_DEBUGGER ON CACHE BOOL "Whether or not to enable the CLI-mode ARM debugger") set(USE_EDITLINE ON CACHE BOOL "Whether or not to enable the CLI-mode debugger")
set(USE_GDB_STUB ON CACHE BOOL "Whether or not to enable the GDB stub ARM debugger") set(USE_GDB_STUB ON CACHE BOOL "Whether or not to enable the GDB stub ARM debugger")
set(USE_FFMPEG ON CACHE BOOL "Whether or not to enable FFmpeg support") set(USE_FFMPEG ON CACHE BOOL "Whether or not to enable FFmpeg support")
set(USE_ZLIB ON CACHE BOOL "Whether or not to enable zlib support") set(USE_ZLIB ON CACHE BOOL "Whether or not to enable zlib support")
@ -314,7 +314,7 @@ if(CMAKE_SYSTEM_NAME MATCHES .*BSD)
list(APPEND LIBEDIT_LIBRARIES -ltermcap) list(APPEND LIBEDIT_LIBRARIES -ltermcap)
endif() endif()
else() else()
find_feature(USE_CLI_DEBUGGER "libedit") find_feature(USE_EDITLINE "libedit")
endif() endif()
if(BUILD_GL) if(BUILD_GL)
find_package(OpenGL QUIET) find_package(OpenGL QUIET)
@ -350,7 +350,11 @@ find_feature(USE_EPOXY "epoxy")
find_feature(USE_CMOCKA "cmocka") find_feature(USE_CMOCKA "cmocka")
# Features # Features
set(DEBUGGER_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/debugger/debugger.c) set(DEBUGGER_SRC
${CMAKE_CURRENT_SOURCE_DIR}/src/debugger/debugger.c
${CMAKE_CURRENT_SOURCE_DIR}/src/debugger/parser.c
${CMAKE_CURRENT_SOURCE_DIR}/src/debugger/cli-debugger.c)
set(FEATURE_SRC) set(FEATURE_SRC)
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6") set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6")
@ -358,21 +362,13 @@ if(DISABLE_DEPS)
set(USE_GDB_STUB OFF) set(USE_GDB_STUB OFF)
endif() endif()
if(USE_CLI_DEBUGGER) if(USE_EDITLINE)
list(APPEND FEATURES CLI_DEBUGGER) list(APPEND FEATURES EDITLINE)
list(APPEND FEATURE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/debugger/cli-debugger.c)
list(APPEND FEATURE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/debugger/parser.c)
if(M_CORE_GBA)
list(APPEND FEATURE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/arm/debugger/cli-debugger.c)
list(APPEND FEATURE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/gba/extra/cli.c)
endif()
if(M_CORE_GB)
list(APPEND FEATURE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/lr35902/debugger/cli-debugger.c)
endif()
include_directories(AFTER ${LIBEDIT_INCLUDE_DIRS}) include_directories(AFTER ${LIBEDIT_INCLUDE_DIRS})
link_directories(${LIBEDIT_LIBRARY_DIRS}) link_directories(${LIBEDIT_LIBRARY_DIRS})
set(DEBUGGER_LIB ${LIBEDIT_LIBRARIES}) set(DEBUGGER_LIB ${LIBEDIT_LIBRARIES})
set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libedit2") set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libedit2")
list(APPEND FEATURE_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/feature/editline/cli-el-backend.c")
else() else()
set(DEBUGGER_LIB "") set(DEBUGGER_LIB "")
endif() endif()
@ -548,6 +544,8 @@ if(M_CORE_GB)
${CMAKE_CURRENT_SOURCE_DIR}/src/lr35902/debugger/debugger.c ${CMAKE_CURRENT_SOURCE_DIR}/src/lr35902/debugger/debugger.c
${GB_SRC} ${GB_SRC}
${GB_RENDERER_SRC}) ${GB_RENDERER_SRC})
list(APPEND CLI_SRC
${CMAKE_CURRENT_SOURCE_DIR}/src/lr35902/debugger/cli-debugger.c)
list(APPEND TEST_SRC list(APPEND TEST_SRC
${LR35902_TEST_SRC} ${LR35902_TEST_SRC}
${GB_TEST_SRC}) ${GB_TEST_SRC})
@ -562,6 +560,9 @@ if(M_CORE_GBA)
${GBA_SRC} ${GBA_SRC}
${GBA_CHEATS_SRC} ${GBA_CHEATS_SRC}
${GBA_RENDERER_SRC}) ${GBA_RENDERER_SRC})
list(APPEND CLI_SRC
${CMAKE_CURRENT_SOURCE_DIR}/src/arm/debugger/cli-debugger.c
${CMAKE_CURRENT_SOURCE_DIR}/src/gba/extra/cli.c)
list(APPEND TEST_SRC list(APPEND TEST_SRC
${ARM_TEST_SRC} ${ARM_TEST_SRC}
${GBA_TEST_SRC}) ${GBA_TEST_SRC})
@ -801,7 +802,7 @@ if(NOT QUIET)
message(STATUS " Game Boy Advance: ${M_CORE_GBA}") message(STATUS " Game Boy Advance: ${M_CORE_GBA}")
message(STATUS " Game Boy: ${M_CORE_GB}") message(STATUS " Game Boy: ${M_CORE_GB}")
message(STATUS "Features:") message(STATUS "Features:")
message(STATUS " CLI debugger: ${USE_CLI_DEBUGGER}") message(STATUS " CLI debugger: ${USE_EDITLINE}")
message(STATUS " GDB stub: ${USE_GDB_STUB}") message(STATUS " GDB stub: ${USE_GDB_STUB}")
message(STATUS " Video recording: ${USE_FFMPEG}") message(STATUS " Video recording: ${USE_FFMPEG}")
message(STATUS " GIF recording: ${USE_MAGICK}") message(STATUS " GIF recording: ${USE_MAGICK}")

View File

@ -5,7 +5,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "cli-debugger.h" #include "cli-debugger.h"
#ifdef USE_CLI_DEBUGGER
#include "arm/debugger/debugger.h" #include "arm/debugger/debugger.h"
#include "arm/debugger/memory-debugger.h" #include "arm/debugger/memory-debugger.h"
#include "arm/decoder.h" #include "arm/decoder.h"
@ -38,15 +37,15 @@ static struct CLIDebuggerCommandSummary _armCommands[] = {
{ 0, 0, 0, 0 } { 0, 0, 0, 0 }
}; };
static inline void _printPSR(union PSR psr) { static inline void _printPSR(struct CLIDebuggerBackend* be, union PSR psr) {
printf("%08X [%c%c%c%c%c%c%c]\n", psr.packed, be->printf(be, "%08X [%c%c%c%c%c%c%c]\n", psr.packed,
psr.n ? 'N' : '-', psr.n ? 'N' : '-',
psr.z ? 'Z' : '-', psr.z ? 'Z' : '-',
psr.c ? 'C' : '-', psr.c ? 'C' : '-',
psr.v ? 'V' : '-', psr.v ? 'V' : '-',
psr.i ? 'I' : '-', psr.i ? 'I' : '-',
psr.f ? 'F' : '-', psr.f ? 'F' : '-',
psr.t ? 'T' : '-'); psr.t ? 'T' : '-');
} }
static void _disassemble(struct CLIDebuggerSystem* debugger, struct CLIDebugVector* dv) { static void _disassemble(struct CLIDebuggerSystem* debugger, struct CLIDebugVector* dv) {
@ -95,14 +94,15 @@ static void _disassembleMode(struct CLIDebugger* debugger, struct CLIDebugVector
} }
static inline uint32_t _printLine(struct CLIDebugger* debugger, uint32_t address, enum ExecutionMode mode) { static inline uint32_t _printLine(struct CLIDebugger* debugger, uint32_t address, enum ExecutionMode mode) {
struct CLIDebuggerBackend* be = debugger->backend;
char disassembly[48]; char disassembly[48];
struct ARMInstructionInfo info; struct ARMInstructionInfo info;
printf("%08X: ", address); be->printf(be, "%08X: ", address);
if (mode == MODE_ARM) { if (mode == MODE_ARM) {
uint32_t instruction = debugger->d.core->busRead32(debugger->d.core, address); uint32_t instruction = debugger->d.core->busRead32(debugger->d.core, address);
ARMDecodeARM(instruction, &info); ARMDecodeARM(instruction, &info);
ARMDisassemble(&info, address + WORD_SIZE_ARM * 2, disassembly, sizeof(disassembly)); ARMDisassemble(&info, address + WORD_SIZE_ARM * 2, disassembly, sizeof(disassembly));
printf("%08X\t%s\n", instruction, disassembly); be->printf(be, "%08X\t%s\n", instruction, disassembly);
return WORD_SIZE_ARM; return WORD_SIZE_ARM;
} else { } else {
struct ARMInstructionInfo info2; struct ARMInstructionInfo info2;
@ -113,27 +113,28 @@ static inline uint32_t _printLine(struct CLIDebugger* debugger, uint32_t address
ARMDecodeThumb(instruction2, &info2); ARMDecodeThumb(instruction2, &info2);
if (ARMDecodeThumbCombine(&info, &info2, &combined)) { if (ARMDecodeThumbCombine(&info, &info2, &combined)) {
ARMDisassemble(&combined, address + WORD_SIZE_THUMB * 2, disassembly, sizeof(disassembly)); ARMDisassemble(&combined, address + WORD_SIZE_THUMB * 2, disassembly, sizeof(disassembly));
printf("%04X %04X\t%s\n", instruction, instruction2, disassembly); be->printf(be, "%04X %04X\t%s\n", instruction, instruction2, disassembly);
return WORD_SIZE_THUMB * 2; return WORD_SIZE_THUMB * 2;
} else { } else {
ARMDisassemble(&info, address + WORD_SIZE_THUMB * 2, disassembly, sizeof(disassembly)); ARMDisassemble(&info, address + WORD_SIZE_THUMB * 2, disassembly, sizeof(disassembly));
printf("%04X \t%s\n", instruction, disassembly); be->printf(be, "%04X \t%s\n", instruction, disassembly);
return WORD_SIZE_THUMB; return WORD_SIZE_THUMB;
} }
} }
} }
static void _printStatus(struct CLIDebuggerSystem* debugger) { static void _printStatus(struct CLIDebuggerSystem* debugger) {
struct CLIDebuggerBackend* be = debugger->p->backend;
struct ARMCore* cpu = debugger->p->d.core->cpu; struct ARMCore* cpu = debugger->p->d.core->cpu;
int r; int r;
for (r = 0; r < 4; ++r) { for (r = 0; r < 4; ++r) {
printf("%08X %08X %08X %08X\n", be->printf(be, "%08X %08X %08X %08X\n",
cpu->gprs[r << 2], cpu->gprs[r << 2],
cpu->gprs[(r << 2) + 1], cpu->gprs[(r << 2) + 1],
cpu->gprs[(r << 2) + 2], cpu->gprs[(r << 2) + 2],
cpu->gprs[(r << 2) + 3]); cpu->gprs[(r << 2) + 3]);
} }
_printPSR(cpu->cpsr); _printPSR(be, cpu->cpsr);
int instructionLength; int instructionLength;
enum ExecutionMode mode = cpu->cpsr.t; enum ExecutionMode mode = cpu->cpsr.t;
if (mode == MODE_ARM) { if (mode == MODE_ARM) {
@ -145,13 +146,14 @@ static void _printStatus(struct CLIDebuggerSystem* debugger) {
} }
static void _writeRegister(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { static void _writeRegister(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
struct CLIDebuggerBackend* be = debugger->backend;
struct ARMCore* cpu = debugger->d.core->cpu; struct ARMCore* cpu = debugger->d.core->cpu;
if (!dv || dv->type != CLIDV_INT_TYPE) { if (!dv || dv->type != CLIDV_INT_TYPE) {
printf("%s\n", ERROR_MISSING_ARGS); be->printf(be, "%s\n", ERROR_MISSING_ARGS);
return; return;
} }
if (!dv->next || dv->next->type != CLIDV_INT_TYPE) { if (!dv->next || dv->next->type != CLIDV_INT_TYPE) {
printf("%s\n", ERROR_MISSING_ARGS); be->printf(be, "%s\n", ERROR_MISSING_ARGS);
return; return;
} }
uint32_t regid = dv->intValue; uint32_t regid = dv->intValue;
@ -163,8 +165,9 @@ static void _writeRegister(struct CLIDebugger* debugger, struct CLIDebugVector*
} }
static void _setBreakpointARM(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { static void _setBreakpointARM(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
struct CLIDebuggerBackend* be = debugger->backend;
if (!dv || dv->type != CLIDV_INT_TYPE) { if (!dv || dv->type != CLIDV_INT_TYPE) {
printf("%s\n", ERROR_MISSING_ARGS); be->printf(be, "%s\n", ERROR_MISSING_ARGS);
return; return;
} }
uint32_t address = dv->intValue; uint32_t address = dv->intValue;
@ -172,8 +175,9 @@ static void _setBreakpointARM(struct CLIDebugger* debugger, struct CLIDebugVecto
} }
static void _setBreakpointThumb(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { static void _setBreakpointThumb(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
struct CLIDebuggerBackend* be = debugger->backend;
if (!dv || dv->type != CLIDV_INT_TYPE) { if (!dv || dv->type != CLIDV_INT_TYPE) {
printf("%s\n", ERROR_MISSING_ARGS); be->printf(be, "%s\n", ERROR_MISSING_ARGS);
return; return;
} }
uint32_t address = dv->intValue; uint32_t address = dv->intValue;
@ -215,5 +219,3 @@ void ARMCLIDebuggerCreate(struct CLIDebuggerSystem* debugger) {
debugger->platformName = "ARM"; debugger->platformName = "ARM";
debugger->platformCommands = _armCommands; debugger->platformCommands = _armCommands;
} }
#endif

View File

@ -5,11 +5,10 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "cli-debugger.h" #include "cli-debugger.h"
#ifdef USE_CLI_DEBUGGER
#include "core/core.h" #include "core/core.h"
#include "core/version.h" #include "core/version.h"
#include "parser.h" #include "debugger/parser.h"
#include "util/string.h"
#include <signal.h> #include <signal.h>
@ -20,8 +19,6 @@
const char* ERROR_MISSING_ARGS = "Arguments missing"; // TODO: share const char* ERROR_MISSING_ARGS = "Arguments missing"; // TODO: share
const char* ERROR_OVERFLOW = "Arguments overflow"; const char* ERROR_OVERFLOW = "Arguments overflow";
static struct CLIDebugger* _activeDebugger;
#ifndef NDEBUG #ifndef NDEBUG
static void _breakInto(struct CLIDebugger*, struct CLIDebugVector*); static void _breakInto(struct CLIDebugger*, struct CLIDebugVector*);
#endif #endif
@ -48,8 +45,6 @@ static void _dumpByte(struct CLIDebugger*, struct CLIDebugVector*);
static void _dumpHalfword(struct CLIDebugger*, struct CLIDebugVector*); static void _dumpHalfword(struct CLIDebugger*, struct CLIDebugVector*);
static void _dumpWord(struct CLIDebugger*, struct CLIDebugVector*); static void _dumpWord(struct CLIDebugger*, struct CLIDebugVector*);
static void _breakIntoDefault(int signal);
static struct CLIDebuggerCommandSummary _debuggerCommands[] = { static struct CLIDebuggerCommandSummary _debuggerCommands[] = {
{ "b", _setBreakpoint, CLIDVParse, "Set a breakpoint" }, { "b", _setBreakpoint, CLIDVParse, "Set a breakpoint" },
{ "break", _setBreakpoint, CLIDVParse, "Set a breakpoint" }, { "break", _setBreakpoint, CLIDVParse, "Set a breakpoint" },
@ -133,68 +128,64 @@ static void _disassemble(struct CLIDebugger* debugger, struct CLIDebugVector* dv
} }
static void _print(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { static void _print(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
UNUSED(debugger);
for (; dv; dv = dv->next) { for (; dv; dv = dv->next) {
printf(" %u", dv->intValue); debugger->backend->printf(debugger->backend, " %u", dv->intValue);
} }
printf("\n"); debugger->backend->printf(debugger->backend, "\n");
} }
static void _printBin(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { static void _printBin(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
UNUSED(debugger);
for (; dv; dv = dv->next) { for (; dv; dv = dv->next) {
printf(" 0b"); debugger->backend->printf(debugger->backend, " 0b");
int i = 32; int i = 32;
while (i--) { while (i--) {
printf("%u", (dv->intValue >> i) & 1); debugger->backend->printf(debugger->backend, "%u", (dv->intValue >> i) & 1);
} }
} }
printf("\n"); debugger->backend->printf(debugger->backend, "\n");
} }
static void _printHex(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { static void _printHex(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
UNUSED(debugger);
for (; dv; dv = dv->next) { for (; dv; dv = dv->next) {
printf(" 0x%08X", dv->intValue); debugger->backend->printf(debugger->backend, " 0x%08X", dv->intValue);
} }
printf("\n"); debugger->backend->printf(debugger->backend, "\n");
} }
static void _printHelp(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { static void _printHelp(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
UNUSED(debugger);
UNUSED(dv); UNUSED(dv);
if (!dv) { if (!dv) {
puts("Generic commands:"); debugger->backend->printf(debugger->backend, "Generic commands:");
int i; int i;
for (i = 0; _debuggerCommands[i].name; ++i) { for (i = 0; _debuggerCommands[i].name; ++i) {
printf("%-10s %s\n", _debuggerCommands[i].name, _debuggerCommands[i].summary); debugger->backend->printf(debugger->backend, "%-10s %s\n", _debuggerCommands[i].name, _debuggerCommands[i].summary);
} }
if (debugger->system) { if (debugger->system) {
printf("%s commands:\n", debugger->system->platformName); debugger->backend->printf(debugger->backend, "%s commands:\n", debugger->system->platformName);
for (i = 0; debugger->system->platformCommands[i].name; ++i) { for (i = 0; debugger->system->platformCommands[i].name; ++i) {
printf("%-10s %s\n", debugger->system->platformCommands[i].name, debugger->system->platformCommands[i].summary); debugger->backend->printf(debugger->backend, "%-10s %s\n", debugger->system->platformCommands[i].name, debugger->system->platformCommands[i].summary);
} }
printf("%s commands:\n", debugger->system->name); debugger->backend->printf(debugger->backend, "%s commands:\n", debugger->system->name);
for (i = 0; debugger->system->commands[i].name; ++i) { for (i = 0; debugger->system->commands[i].name; ++i) {
printf("%-10s %s\n", debugger->system->commands[i].name, debugger->system->commands[i].summary); debugger->backend->printf(debugger->backend, "%-10s %s\n", debugger->system->commands[i].name, debugger->system->commands[i].summary);
} }
} }
} else { } else {
int i; int i;
for (i = 0; _debuggerCommands[i].name; ++i) { for (i = 0; _debuggerCommands[i].name; ++i) {
if (strcmp(_debuggerCommands[i].name, dv->charValue) == 0) { if (strcmp(_debuggerCommands[i].name, dv->charValue) == 0) {
printf(" %s\n", _debuggerCommands[i].summary); debugger->backend->printf(debugger->backend, " %s\n", _debuggerCommands[i].summary);
} }
} }
if (debugger->system) { if (debugger->system) {
for (i = 0; debugger->system->platformCommands[i].name; ++i) { for (i = 0; debugger->system->platformCommands[i].name; ++i) {
if (strcmp(debugger->system->platformCommands[i].name, dv->charValue) == 0) { if (strcmp(debugger->system->platformCommands[i].name, dv->charValue) == 0) {
printf(" %s\n", debugger->system->platformCommands[i].summary); debugger->backend->printf(debugger->backend, " %s\n", debugger->system->platformCommands[i].summary);
} }
} }
for (i = 0; debugger->system->commands[i].name; ++i) { for (i = 0; debugger->system->commands[i].name; ++i) {
if (strcmp(debugger->system->commands[i].name, dv->charValue) == 0) { if (strcmp(debugger->system->commands[i].name, dv->charValue) == 0) {
printf(" %s\n", debugger->system->commands[i].summary); debugger->backend->printf(debugger->backend, " %s\n", debugger->system->commands[i].summary);
} }
} }
} }
@ -208,12 +199,12 @@ static void _quit(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
static void _readByte(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { static void _readByte(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
if (!dv || dv->type != CLIDV_INT_TYPE) { if (!dv || dv->type != CLIDV_INT_TYPE) {
printf("%s\n", ERROR_MISSING_ARGS); debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS);
return; return;
} }
uint32_t address = dv->intValue; uint32_t address = dv->intValue;
uint8_t value = debugger->d.core->busRead8(debugger->d.core, address); uint8_t value = debugger->d.core->busRead8(debugger->d.core, address);
printf(" 0x%02X\n", value); debugger->backend->printf(debugger->backend, " 0x%02X\n", value);
} }
static void _reset(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { static void _reset(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
@ -224,37 +215,37 @@ static void _reset(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
static void _readHalfword(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { static void _readHalfword(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
if (!dv || dv->type != CLIDV_INT_TYPE) { if (!dv || dv->type != CLIDV_INT_TYPE) {
printf("%s\n", ERROR_MISSING_ARGS); debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS);
return; return;
} }
uint32_t address = dv->intValue; uint32_t address = dv->intValue;
uint16_t value = debugger->d.core->busRead16(debugger->d.core, address & ~1); uint16_t value = debugger->d.core->busRead16(debugger->d.core, address & ~1);
printf(" 0x%04X\n", value); debugger->backend->printf(debugger->backend, " 0x%04X\n", value);
} }
static void _readWord(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { static void _readWord(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
if (!dv || dv->type != CLIDV_INT_TYPE) { if (!dv || dv->type != CLIDV_INT_TYPE) {
printf("%s\n", ERROR_MISSING_ARGS); debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS);
return; return;
} }
uint32_t address = dv->intValue; uint32_t address = dv->intValue;
uint32_t value = debugger->d.core->busRead32(debugger->d.core, address & ~3); uint32_t value = debugger->d.core->busRead32(debugger->d.core, address & ~3);
printf(" 0x%08X\n", value); debugger->backend->printf(debugger->backend, " 0x%08X\n", value);
} }
static void _writeByte(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { static void _writeByte(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
if (!dv || dv->type != CLIDV_INT_TYPE) { if (!dv || dv->type != CLIDV_INT_TYPE) {
printf("%s\n", ERROR_MISSING_ARGS); debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS);
return; return;
} }
if (!dv->next || dv->next->type != CLIDV_INT_TYPE) { if (!dv->next || dv->next->type != CLIDV_INT_TYPE) {
printf("%s\n", ERROR_MISSING_ARGS); debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS);
return; return;
} }
uint32_t address = dv->intValue; uint32_t address = dv->intValue;
uint32_t value = dv->next->intValue; uint32_t value = dv->next->intValue;
if (value > 0xFF) { if (value > 0xFF) {
printf("%s\n", ERROR_OVERFLOW); debugger->backend->printf(debugger->backend, "%s\n", ERROR_OVERFLOW);
return; return;
} }
debugger->d.core->busWrite8(debugger->d.core, address, value); debugger->d.core->busWrite8(debugger->d.core, address, value);
@ -262,17 +253,17 @@ static void _writeByte(struct CLIDebugger* debugger, struct CLIDebugVector* dv)
static void _writeHalfword(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { static void _writeHalfword(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
if (!dv || dv->type != CLIDV_INT_TYPE) { if (!dv || dv->type != CLIDV_INT_TYPE) {
printf("%s\n", ERROR_MISSING_ARGS); debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS);
return; return;
} }
if (!dv->next || dv->next->type != CLIDV_INT_TYPE) { if (!dv->next || dv->next->type != CLIDV_INT_TYPE) {
printf("%s\n", ERROR_MISSING_ARGS); debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS);
return; return;
} }
uint32_t address = dv->intValue; uint32_t address = dv->intValue;
uint32_t value = dv->next->intValue; uint32_t value = dv->next->intValue;
if (value > 0xFFFF) { if (value > 0xFFFF) {
printf("%s\n", ERROR_OVERFLOW); debugger->backend->printf(debugger->backend, "%s\n", ERROR_OVERFLOW);
return; return;
} }
debugger->d.core->busWrite16(debugger->d.core, address, value); debugger->d.core->busWrite16(debugger->d.core, address, value);
@ -280,11 +271,11 @@ static void _writeHalfword(struct CLIDebugger* debugger, struct CLIDebugVector*
static void _writeWord(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { static void _writeWord(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
if (!dv || dv->type != CLIDV_INT_TYPE) { if (!dv || dv->type != CLIDV_INT_TYPE) {
printf("%s\n", ERROR_MISSING_ARGS); debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS);
return; return;
} }
if (!dv->next || dv->next->type != CLIDV_INT_TYPE) { if (!dv->next || dv->next->type != CLIDV_INT_TYPE) {
printf("%s\n", ERROR_MISSING_ARGS); debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS);
return; return;
} }
uint32_t address = dv->intValue; uint32_t address = dv->intValue;
@ -294,7 +285,7 @@ static void _writeWord(struct CLIDebugger* debugger, struct CLIDebugVector* dv)
static void _dumpByte(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { static void _dumpByte(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
if (!dv || dv->type != CLIDV_INT_TYPE) { if (!dv || dv->type != CLIDV_INT_TYPE) {
printf("%s\n", ERROR_MISSING_ARGS); debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS);
return; return;
} }
uint32_t address = dv->intValue; uint32_t address = dv->intValue;
@ -307,18 +298,18 @@ static void _dumpByte(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
if (line > words) { if (line > words) {
line = words; line = words;
} }
printf("0x%08X:", address); debugger->backend->printf(debugger->backend, "0x%08X:", address);
for (; line > 0; --line, ++address, --words) { for (; line > 0; --line, ++address, --words) {
uint32_t value = debugger->d.core->busRead8(debugger->d.core, address); uint32_t value = debugger->d.core->busRead8(debugger->d.core, address);
printf(" %02X", value); debugger->backend->printf(debugger->backend, " %02X", value);
} }
printf("\n"); debugger->backend->printf(debugger->backend, "\n");
} }
} }
static void _dumpHalfword(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { static void _dumpHalfword(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
if (!dv || dv->type != CLIDV_INT_TYPE) { if (!dv || dv->type != CLIDV_INT_TYPE) {
printf("%s\n", ERROR_MISSING_ARGS); debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS);
return; return;
} }
uint32_t address = dv->intValue; uint32_t address = dv->intValue;
@ -331,18 +322,18 @@ static void _dumpHalfword(struct CLIDebugger* debugger, struct CLIDebugVector* d
if (line > words) { if (line > words) {
line = words; line = words;
} }
printf("0x%08X:", address); debugger->backend->printf(debugger->backend, "0x%08X:", address);
for (; line > 0; --line, address += 2, --words) { for (; line > 0; --line, address += 2, --words) {
uint32_t value = debugger->d.core->busRead16(debugger->d.core, address); uint32_t value = debugger->d.core->busRead16(debugger->d.core, address);
printf(" %04X", value); debugger->backend->printf(debugger->backend, " %04X", value);
} }
printf("\n"); debugger->backend->printf(debugger->backend, "\n");
} }
} }
static void _dumpWord(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { static void _dumpWord(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
if (!dv || dv->type != CLIDV_INT_TYPE) { if (!dv || dv->type != CLIDV_INT_TYPE) {
printf("%s\n", ERROR_MISSING_ARGS); debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS);
return; return;
} }
uint32_t address = dv->intValue; uint32_t address = dv->intValue;
@ -355,18 +346,18 @@ static void _dumpWord(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
if (line > words) { if (line > words) {
line = words; line = words;
} }
printf("0x%08X:", address); debugger->backend->printf(debugger->backend, "0x%08X:", address);
for (; line > 0; --line, address += 4, --words) { for (; line > 0; --line, address += 4, --words) {
uint32_t value = debugger->d.core->busRead32(debugger->d.core, address); uint32_t value = debugger->d.core->busRead32(debugger->d.core, address);
printf(" %08X", value); debugger->backend->printf(debugger->backend, " %08X", value);
} }
printf("\n"); debugger->backend->printf(debugger->backend, "\n");
} }
} }
static void _setBreakpoint(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { static void _setBreakpoint(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
if (!dv || dv->type != CLIDV_INT_TYPE) { if (!dv || dv->type != CLIDV_INT_TYPE) {
printf("%s\n", ERROR_MISSING_ARGS); debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS);
return; return;
} }
uint32_t address = dv->intValue; uint32_t address = dv->intValue;
@ -375,11 +366,11 @@ static void _setBreakpoint(struct CLIDebugger* debugger, struct CLIDebugVector*
static void _setWatchpoint(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { static void _setWatchpoint(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
if (!dv || dv->type != CLIDV_INT_TYPE) { if (!dv || dv->type != CLIDV_INT_TYPE) {
printf("%s\n", ERROR_MISSING_ARGS); debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS);
return; return;
} }
if (!debugger->d.platform->setWatchpoint) { if (!debugger->d.platform->setWatchpoint) {
printf("Watchpoints are not supported by this platform.\n"); debugger->backend->printf(debugger->backend, "Watchpoints are not supported by this platform.\n");
return; return;
} }
uint32_t address = dv->intValue; uint32_t address = dv->intValue;
@ -388,7 +379,7 @@ static void _setWatchpoint(struct CLIDebugger* debugger, struct CLIDebugVector*
static void _clearBreakpoint(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { static void _clearBreakpoint(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
if (!dv || dv->type != CLIDV_INT_TYPE) { if (!dv || dv->type != CLIDV_INT_TYPE) {
printf("%s\n", ERROR_MISSING_ARGS); debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS);
return; return;
} }
uint32_t address = dv->intValue; uint32_t address = dv->intValue;
@ -398,11 +389,6 @@ static void _clearBreakpoint(struct CLIDebugger* debugger, struct CLIDebugVector
} }
} }
static void _breakIntoDefault(int signal) {
UNUSED(signal);
mDebuggerEnter(&_activeDebugger->d, DEBUGGER_ENTER_MANUAL, 0);
}
static void _printStatus(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { static void _printStatus(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
UNUSED(dv); UNUSED(dv);
debugger->system->printStatus(debugger->system); debugger->system->printStatus(debugger->system);
@ -537,8 +523,7 @@ struct CLIDebugVector* CLIDVStringParse(struct CLIDebugger* debugger, const char
} else { } else {
adjusted = length; adjusted = length;
} }
dvTemp.charValue = malloc(adjusted); dvTemp.charValue = strndup(string, adjusted);
strncpy(dvTemp.charValue, string, adjusted);
length -= adjusted; length -= adjusted;
string += adjusted; string += adjusted;
@ -579,13 +564,13 @@ static int _tryCommands(struct CLIDebugger* debugger, struct CLIDebuggerCommandS
if (args) { if (args) {
dv = commands[i].parser(debugger, args, argsLen); dv = commands[i].parser(debugger, args, argsLen);
if (dv && dv->type == CLIDV_ERROR_TYPE) { if (dv && dv->type == CLIDV_ERROR_TYPE) {
printf("Parse error\n"); debugger->backend->printf(debugger->backend, "Parse error\n");
_DVFree(dv); _DVFree(dv);
return false; return false;
} }
} }
} else if (args) { } else if (args) {
printf("Wrong number of arguments\n"); debugger->backend->printf(debugger->backend, "Wrong number of arguments\n");
return false; return false;
} }
commands[i].command(debugger, dv); commands[i].command(debugger, dv);
@ -617,155 +602,88 @@ static bool _parse(struct CLIDebugger* debugger, const char* line, size_t count)
} }
} }
if (result < 0) { if (result < 0) {
printf("Command not found\n"); debugger->backend->printf(debugger->backend, "Command not found\n");
} }
return false; return false;
} }
static char* _prompt(EditLine* el) {
UNUSED(el);
return "> ";
}
static void _commandLine(struct mDebugger* debugger) { static void _commandLine(struct mDebugger* debugger) {
struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger; struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger;
const char* line; const char* line;
size_t len;
_printStatus(cliDebugger, 0); _printStatus(cliDebugger, 0);
int count = 0;
HistEvent ev;
while (debugger->state == DEBUGGER_PAUSED) { while (debugger->state == DEBUGGER_PAUSED) {
line = el_gets(cliDebugger->elstate, &count); line = cliDebugger->backend->readline(cliDebugger->backend, &len);
if (!line) { if (!line || len == 0) {
debugger->state = DEBUGGER_SHUTDOWN; debugger->state = DEBUGGER_SHUTDOWN;
return; return;
} }
if (line[0] == '\n') { if (line[0] == '\n') {
if (history(cliDebugger->histate, &ev, H_FIRST) >= 0) { line = cliDebugger->backend->historyLast(cliDebugger->backend, &len);
_parse(cliDebugger, ev.str, strlen(ev.str) - 1); if (line && len) {
_parse(cliDebugger, line, len);
} }
} else { } else {
_parse(cliDebugger, line, count - 1); _parse(cliDebugger, line, len);
history(cliDebugger->histate, &ev, H_ENTER, line); cliDebugger->backend->historyAppend(cliDebugger->backend, line);
} }
} }
} }
static void _reportEntry(struct mDebugger* debugger, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info) { static void _reportEntry(struct mDebugger* debugger, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info) {
UNUSED(debugger); struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger;
switch (reason) { switch (reason) {
case DEBUGGER_ENTER_MANUAL: case DEBUGGER_ENTER_MANUAL:
case DEBUGGER_ENTER_ATTACHED: case DEBUGGER_ENTER_ATTACHED:
break; break;
case DEBUGGER_ENTER_BREAKPOINT: case DEBUGGER_ENTER_BREAKPOINT:
if (info) { if (info) {
printf("Hit breakpoint at 0x%08X\n", info->address); cliDebugger->backend->printf(cliDebugger->backend, "Hit breakpoint at 0x%08X\n", info->address);
} else { } else {
printf("Hit breakpoint\n"); cliDebugger->backend->printf(cliDebugger->backend, "Hit breakpoint\n");
} }
break; break;
case DEBUGGER_ENTER_WATCHPOINT: case DEBUGGER_ENTER_WATCHPOINT:
if (info) { if (info) {
if (info->accessType & WATCHPOINT_WRITE) { if (info->accessType & WATCHPOINT_WRITE) {
printf("Hit watchpoint at 0x%08X: (new value = 0x%08x, old value = 0x%08X)\n", info->address, info->newValue, info->oldValue); cliDebugger->backend->printf(cliDebugger->backend, "Hit watchpoint at 0x%08X: (new value = 0x%08x, old value = 0x%08X)\n", info->address, info->newValue, info->oldValue);
} else { } else {
printf("Hit watchpoint at 0x%08X: (value = 0x%08x)\n", info->address, info->oldValue); cliDebugger->backend->printf(cliDebugger->backend, "Hit watchpoint at 0x%08X: (value = 0x%08x)\n", info->address, info->oldValue);
} }
} else { } else {
printf("Hit watchpoint\n"); cliDebugger->backend->printf(cliDebugger->backend, "Hit watchpoint\n");
} }
break; break;
case DEBUGGER_ENTER_ILLEGAL_OP: case DEBUGGER_ENTER_ILLEGAL_OP:
if (info) { if (info) {
printf("Hit illegal opcode at 0x%08X: 0x%08X\n", info->address, info->opcode); cliDebugger->backend->printf(cliDebugger->backend, "Hit illegal opcode at 0x%08X: 0x%08X\n", info->address, info->opcode);
} else { } else {
printf("Hit illegal opcode\n"); cliDebugger->backend->printf(cliDebugger->backend, "Hit illegal opcode\n");
} }
break; break;
} }
} }
static unsigned char _tabComplete(EditLine* elstate, int ch) {
UNUSED(ch);
const LineInfo* li = el_line(elstate);
if (!li->buffer[0]) {
return CC_ERROR;
}
const char* commandPtr;
size_t cmd = 0, len = 0;
const char* name = 0;
for (commandPtr = li->buffer; commandPtr <= li->cursor; ++commandPtr, ++len) {
for (; (name = _debuggerCommands[cmd].name); ++cmd) {
int cmp = strncasecmp(name, li->buffer, len);
if (cmp > 0) {
return CC_ERROR;
}
if (cmp == 0) {
break;
}
}
}
if (!name) {
return CC_ERROR;
}
if (_debuggerCommands[cmd + 1].name && strlen(_debuggerCommands[cmd + 1].name) >= len - 1 && name[len - 2] == _debuggerCommands[cmd + 1].name[len - 2]) {
--len;
const char* next = 0;
int i;
for (i = cmd + 1; _debuggerCommands[i].name; ++i) {
if (strncasecmp(name, _debuggerCommands[i].name, len)) {
break;
}
next = _debuggerCommands[i].name;
}
if (!next) {
return CC_ERROR;
}
for (; name[len]; ++len) {
if (name[len] != next[len]) {
break;
}
char out[2] = { name[len], '\0' };
el_insertstr(elstate, out);
}
return CC_REDISPLAY;
}
name += len - 1;
el_insertstr(elstate, name);
el_insertstr(elstate, " ");
return CC_REDISPLAY;
}
static void _cliDebuggerInit(struct mDebugger* debugger) { static void _cliDebuggerInit(struct mDebugger* debugger) {
struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger; struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger;
// TODO: get argv[0] cliDebugger->backend->init(cliDebugger->backend);
cliDebugger->elstate = el_init(binaryName, stdin, stdout, stderr);
el_set(cliDebugger->elstate, EL_PROMPT, _prompt);
el_set(cliDebugger->elstate, EL_EDITOR, "emacs");
el_set(cliDebugger->elstate, EL_CLIENTDATA, cliDebugger);
el_set(cliDebugger->elstate, EL_ADDFN, "tab-complete", "Tab completion", _tabComplete);
el_set(cliDebugger->elstate, EL_BIND, "\t", "tab-complete", 0);
cliDebugger->histate = history_init();
HistEvent ev;
history(cliDebugger->histate, &ev, H_SETSIZE, 200);
el_set(cliDebugger->elstate, EL_HIST, history, cliDebugger->histate);
_activeDebugger = cliDebugger;
signal(SIGINT, _breakIntoDefault);
} }
static void _cliDebuggerDeinit(struct mDebugger* debugger) { static void _cliDebuggerDeinit(struct mDebugger* debugger) {
struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger; struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger;
history_end(cliDebugger->histate);
el_end(cliDebugger->elstate);
if (cliDebugger->system) { if (cliDebugger->system) {
if (cliDebugger->system->deinit) { if (cliDebugger->system->deinit) {
cliDebugger->system->deinit(cliDebugger->system); cliDebugger->system->deinit(cliDebugger->system);
} }
free(cliDebugger->system); free(cliDebugger->system);
cliDebugger->system = 0; cliDebugger->system = NULL;
}
if (cliDebugger->backend) {
if (cliDebugger->backend->deinit) {
cliDebugger->backend->deinit(cliDebugger->backend);
}
free(cliDebugger->backend);
cliDebugger->backend = NULL;
} }
} }
@ -787,7 +705,8 @@ void CLIDebuggerCreate(struct CLIDebugger* debugger) {
debugger->d.paused = _commandLine; debugger->d.paused = _commandLine;
debugger->d.entered = _reportEntry; debugger->d.entered = _reportEntry;
debugger->system = 0; debugger->system = NULL;
debugger->backend = NULL;
} }
void CLIDebuggerAttachSystem(struct CLIDebugger* debugger, struct CLIDebuggerSystem* system) { void CLIDebuggerAttachSystem(struct CLIDebugger* debugger, struct CLIDebuggerSystem* system) {
@ -802,4 +721,61 @@ void CLIDebuggerAttachSystem(struct CLIDebugger* debugger, struct CLIDebuggerSys
system->p = debugger; system->p = debugger;
} }
#endif void CLIDebuggerAttachBackend(struct CLIDebugger* debugger, struct CLIDebuggerBackend* backend) {
if (debugger->backend) {
if (debugger->backend->deinit) {
debugger->backend->deinit(debugger->backend);
}
free(debugger->backend);
}
debugger->backend = backend;
backend->p = debugger;
}
bool CLIDebuggerTabComplete(struct CLIDebugger* debugger, const char* token, bool initial, size_t tokenLen) {
size_t cmd = 0;
size_t len;
const char* name = 0;
for (len = 1; len <= tokenLen; ++len) {
for (; (name = _debuggerCommands[cmd].name); ++cmd) {
int cmp = strncasecmp(name, token, len);
if (cmp > 0) {
return false;
}
if (cmp == 0) {
break;
}
}
}
if (!name) {
return false;
}
if (_debuggerCommands[cmd + 1].name && strlen(_debuggerCommands[cmd + 1].name) >= len && name[len - 1] == _debuggerCommands[cmd + 1].name[len - 1]) {
--len;
const char* next = 0;
int i;
for (i = cmd + 1; _debuggerCommands[i].name; ++i) {
if (strncasecmp(name, _debuggerCommands[i].name, len)) {
break;
}
next = _debuggerCommands[i].name;
}
if (!next) {
return false;
}
for (; name[len]; ++len) {
if (name[len] != next[len]) {
break;
}
char out[2] = { name[len], '\0' };
debugger->backend->lineAppend(debugger->backend, out);
}
return true;
}
name += len - 1;
debugger->backend->lineAppend(debugger->backend, name);
debugger->backend->lineAppend(debugger->backend, " ");
return true;
}

View File

@ -1,4 +1,4 @@
/* 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 * 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 * License, v. 2.0. If a copy of the MPL was not distributed with this
@ -10,9 +10,6 @@
#include "debugger.h" #include "debugger.h"
#ifdef USE_CLI_DEBUGGER
#include <histedit.h>
struct CLIDebugger; struct CLIDebugger;
struct CLIDebugVector { struct CLIDebugVector {
@ -59,13 +56,25 @@ struct CLIDebuggerSystem {
const char* platformName; const char* platformName;
}; };
struct CLIDebuggerBackend {
struct CLIDebugger* p;
void (*init)(struct CLIDebuggerBackend*);
void (*deinit)(struct CLIDebuggerBackend*);
ATTRIBUTE_FORMAT(printf, 2, 3)
void (*printf)(struct CLIDebuggerBackend*, const char* fmt, ...);
const char* (*readline)(struct CLIDebuggerBackend*, size_t* len);
void (*lineAppend)(struct CLIDebuggerBackend*, const char* line);
const char* (*historyLast)(struct CLIDebuggerBackend*, size_t* len);
void (*historyAppend)(struct CLIDebuggerBackend*, const char* line);
};
struct CLIDebugger { struct CLIDebugger {
struct mDebugger d; struct mDebugger d;
struct CLIDebuggerSystem* system; struct CLIDebuggerSystem* system;
struct CLIDebuggerBackend* backend;
EditLine* elstate;
History* histate;
}; };
struct CLIDebugVector* CLIDVParse(struct CLIDebugger* debugger, const char* string, size_t length); struct CLIDebugVector* CLIDVParse(struct CLIDebugger* debugger, const char* string, size_t length);
@ -73,6 +82,8 @@ struct CLIDebugVector* CLIDVStringParse(struct CLIDebugger* debugger, const char
void CLIDebuggerCreate(struct CLIDebugger*); void CLIDebuggerCreate(struct CLIDebugger*);
void CLIDebuggerAttachSystem(struct CLIDebugger*, struct CLIDebuggerSystem*); void CLIDebuggerAttachSystem(struct CLIDebugger*, struct CLIDebuggerSystem*);
#endif void CLIDebuggerAttachBackend(struct CLIDebugger*, struct CLIDebuggerBackend*);
bool CLIDebuggerTabComplete(struct CLIDebugger*, const char* token, bool initial, size_t len);
#endif #endif

View File

@ -7,9 +7,7 @@
#include "core/core.h" #include "core/core.h"
#ifdef USE_CLI_DEBUGGER
#include "debugger/cli-debugger.h" #include "debugger/cli-debugger.h"
#endif
#ifdef USE_GDB_STUB #ifdef USE_GDB_STUB
#include "debugger/gdb-stub.h" #include "debugger/gdb-stub.h"
@ -29,9 +27,7 @@ struct mDebugger* mDebuggerCreate(enum mDebuggerType type, struct mCore* core) {
union DebugUnion { union DebugUnion {
struct mDebugger d; struct mDebugger d;
#ifdef USE_CLI_DEBUGGER
struct CLIDebugger cli; struct CLIDebugger cli;
#endif
#ifdef USE_GDB_STUB #ifdef USE_GDB_STUB
struct GDBStub gdb; struct GDBStub gdb;
#endif #endif
@ -40,13 +36,11 @@ struct mDebugger* mDebuggerCreate(enum mDebuggerType type, struct mCore* core) {
union DebugUnion* debugger = malloc(sizeof(union DebugUnion)); union DebugUnion* debugger = malloc(sizeof(union DebugUnion));
switch (type) { switch (type) {
#ifdef USE_CLI_DEBUGGER
case DEBUGGER_CLI: case DEBUGGER_CLI:
CLIDebuggerCreate(&debugger->cli); CLIDebuggerCreate(&debugger->cli);
struct CLIDebuggerSystem* sys = core->cliDebuggerSystem(core); struct CLIDebuggerSystem* sys = core->cliDebuggerSystem(core);
CLIDebuggerAttachSystem(&debugger->cli, sys); CLIDebuggerAttachSystem(&debugger->cli, sys);
break; break;
#endif
#ifdef USE_GDB_STUB #ifdef USE_GDB_STUB
case DEBUGGER_GDB: case DEBUGGER_GDB:
GDBStubCreate(&debugger->gdb); GDBStubCreate(&debugger->gdb);

View File

@ -18,9 +18,7 @@ extern const uint32_t DEBUGGER_ID;
enum mDebuggerType { enum mDebuggerType {
DEBUGGER_NONE = 0, DEBUGGER_NONE = 0,
#ifdef USE_CLI_DEBUGGER
DEBUGGER_CLI, DEBUGGER_CLI,
#endif
#ifdef USE_GDB_STUB #ifdef USE_GDB_STUB
DEBUGGER_GDB, DEBUGGER_GDB,
#endif #endif

View File

@ -31,7 +31,7 @@ static const struct option _options[] = {
{ "bios", required_argument, 0, 'b' }, { "bios", required_argument, 0, 'b' },
{ "cheats", required_argument, 0, 'c' }, { "cheats", required_argument, 0, 'c' },
{ "frameskip", required_argument, 0, 's' }, { "frameskip", required_argument, 0, 's' },
#ifdef USE_CLI_DEBUGGER #ifdef USE_EDITLINE
{ "debug", no_argument, 0, 'd' }, { "debug", no_argument, 0, 'd' },
#endif #endif
#ifdef USE_GDB_STUB #ifdef USE_GDB_STUB
@ -51,7 +51,7 @@ bool parseArguments(struct mArguments* args, int argc, char* const* argv, struct
int ch; int ch;
char options[64] = char options[64] =
"b:c:hl:p:s:v:" "b:c:hl:p:s:v:"
#ifdef USE_CLI_DEBUGGER #ifdef USE_EDITLINE
"d" "d"
#endif #endif
#ifdef USE_GDB_STUB #ifdef USE_GDB_STUB
@ -82,7 +82,7 @@ bool parseArguments(struct mArguments* args, int argc, char* const* argv, struct
case 'c': case 'c':
args->cheatsFile = strdup(optarg); args->cheatsFile = strdup(optarg);
break; break;
#ifdef USE_CLI_DEBUGGER #ifdef USE_EDITLINE
case 'd': case 'd':
if (args->debuggerType != DEBUGGER_NONE) { if (args->debuggerType != DEBUGGER_NONE) {
return false; return false;
@ -209,7 +209,7 @@ void usage(const char* arg0, const char* extraOptions) {
puts("\nGeneric options:"); puts("\nGeneric options:");
puts(" -b, --bios FILE GBA BIOS file to use"); puts(" -b, --bios FILE GBA BIOS file to use");
puts(" -c, --cheats FILE Apply cheat codes from a file"); puts(" -c, --cheats FILE Apply cheat codes from a file");
#ifdef USE_CLI_DEBUGGER #ifdef USE_EDITLINE
puts(" -d, --debug Use command-line debugger"); puts(" -d, --debug Use command-line debugger");
#endif #endif
#ifdef USE_GDB_STUB #ifdef USE_GDB_STUB

View File

@ -0,0 +1,122 @@
/* 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 "cli-el-backend.h"
#include "core/version.h"
#include <signal.h>
static struct CLIDebugger* _activeDebugger;
static char* _prompt(EditLine* el) {
UNUSED(el);
return "> ";
}
static void _breakIntoDefault(int signal) {
UNUSED(signal);
mDebuggerEnter(&_activeDebugger->d, DEBUGGER_ENTER_MANUAL, 0);
}
static unsigned char _tabComplete(EditLine* elstate, int ch) {
UNUSED(ch);
const LineInfo* li = el_line(elstate);
if (!li->buffer[0]) {
return CC_ERROR;
}
struct CLIDebuggerEditLineBackend* elbe;
el_get(elstate, EL_CLIENTDATA, &elbe);
// TODO: not always true
if (CLIDebuggerTabComplete(elbe->d.p, li->buffer, true, li->cursor - li->buffer)) {
return CC_REDISPLAY;
}
return CC_ERROR;
}
ATTRIBUTE_FORMAT(printf, 2, 3)
void _CLIDebuggerEditLinePrintf(struct CLIDebuggerBackend* be, const char* fmt, ...) {
UNUSED(be);
va_list args;
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
}
void _CLIDebuggerEditLineInit(struct CLIDebuggerBackend* be) {
struct CLIDebuggerEditLineBackend* elbe = (struct CLIDebuggerEditLineBackend*) be;
// TODO: get argv[0]
elbe->elstate = el_init(binaryName, stdin, stdout, stderr);
el_set(elbe->elstate, EL_PROMPT, _prompt);
el_set(elbe->elstate, EL_EDITOR, "emacs");
el_set(elbe->elstate, EL_CLIENTDATA, elbe);
el_set(elbe->elstate, EL_ADDFN, "tab-complete", "Tab completion", _tabComplete);
el_set(elbe->elstate, EL_BIND, "\t", "tab-complete", 0);
elbe->histate = history_init();
HistEvent ev;
history(elbe->histate, &ev, H_SETSIZE, 200);
el_set(elbe->elstate, EL_HIST, history, elbe->histate);
_activeDebugger = be->p;
signal(SIGINT, _breakIntoDefault);
}
void _CLIDebuggerEditLineDeinit(struct CLIDebuggerBackend* be) {
struct CLIDebuggerEditLineBackend* elbe = (struct CLIDebuggerEditLineBackend*) be;
history_end(elbe->histate);
el_end(elbe->elstate);
}
const char* _CLIDebuggerEditLineReadLine(struct CLIDebuggerBackend* be, size_t* len) {
struct CLIDebuggerEditLineBackend* elbe = (struct CLIDebuggerEditLineBackend*) be;
int count;
*len = 0;
const char* line = el_gets(elbe->elstate, &count);
if (line && count >= 1) {
// Crop off newline
*len = (size_t) count - 1;
}
return line;
}
void _CLIDebuggerEditLineLineAppend(struct CLIDebuggerBackend* be, const char* line) {
struct CLIDebuggerEditLineBackend* elbe = (struct CLIDebuggerEditLineBackend*) be;
el_insertstr(elbe->elstate, line);
}
const char* _CLIDebuggerEditLineHistoryLast(struct CLIDebuggerBackend* be, size_t* len) {
struct CLIDebuggerEditLineBackend* elbe = (struct CLIDebuggerEditLineBackend*) be;
HistEvent ev;
if (history(elbe->histate, &ev, H_FIRST) < 0) {
*len = 0;
return NULL;
}
const char* newline = strchr(ev.str, '\n');
if (!newline) {
*len = strlen(ev.str);
} else {
*len = newline - ev.str;
}
return ev.str;
}
void _CLIDebuggerEditLineHistoryAppend(struct CLIDebuggerBackend* be, const char* line) {
struct CLIDebuggerEditLineBackend* elbe = (struct CLIDebuggerEditLineBackend*) be;
HistEvent ev;
history(elbe->histate, &ev, H_ENTER, line);
}
struct CLIDebuggerBackend* CLIDebuggerEditLineBackendCreate(void) {
struct CLIDebuggerEditLineBackend* elbe = malloc(sizeof(*elbe));
elbe->d.printf = _CLIDebuggerEditLinePrintf;
elbe->d.init = _CLIDebuggerEditLineInit;
elbe->d.deinit = _CLIDebuggerEditLineDeinit;
elbe->d.readline = _CLIDebuggerEditLineReadLine;
elbe->d.lineAppend = _CLIDebuggerEditLineLineAppend;
elbe->d.historyLast = _CLIDebuggerEditLineHistoryLast;
elbe->d.historyAppend = _CLIDebuggerEditLineHistoryAppend;
return &elbe->d;
}

View File

@ -0,0 +1,23 @@
/* 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/. */
#ifndef CLI_EL_BACKEND_H
#define CLI_EL_BACKEND_H
#include "debugger/cli-debugger.h"
#include "util/common.h"
#include <histedit.h>
struct CLIDebuggerEditLineBackend {
struct CLIDebuggerBackend d;
EditLine* elstate;
History* histate;
};
struct CLIDebuggerBackend* CLIDebuggerEditLineBackendCreate(void);
#endif

View File

@ -12,8 +12,6 @@
#include "gb/video.h" #include "gb/video.h"
#include "lr35902/debugger/cli-debugger.h" #include "lr35902/debugger/cli-debugger.h"
#ifdef USE_CLI_DEBUGGER
static void _GBCLIDebuggerInit(struct CLIDebuggerSystem*); static void _GBCLIDebuggerInit(struct CLIDebuggerSystem*);
static bool _GBCLIDebuggerCustom(struct CLIDebuggerSystem*); static bool _GBCLIDebuggerCustom(struct CLIDebuggerSystem*);
static uint32_t _GBCLIDebuggerLookupIdentifier(struct CLIDebuggerSystem*, const char* name, struct CLIDebugVector* dv); static uint32_t _GBCLIDebuggerLookupIdentifier(struct CLIDebuggerSystem*, const char* name, struct CLIDebugVector* dv);
@ -90,14 +88,15 @@ static void _frame(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
} }
static void _load(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { static void _load(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
struct CLIDebuggerBackend* be = debugger->backend;
if (!dv || dv->type != CLIDV_INT_TYPE) { if (!dv || dv->type != CLIDV_INT_TYPE) {
printf("%s\n", ERROR_MISSING_ARGS); be->printf(be, "%s\n", ERROR_MISSING_ARGS);
return; return;
} }
int state = dv->intValue; int state = dv->intValue;
if (state < 1 || state > 9) { if (state < 1 || state > 9) {
printf("State %u out of range", state); be->printf(be, "State %u out of range", state);
} }
struct GBCLIDebugger* gbDebugger = (struct GBCLIDebugger*) debugger->system; struct GBCLIDebugger* gbDebugger = (struct GBCLIDebugger*) debugger->system;
@ -106,18 +105,18 @@ static void _load(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
} }
static void _save(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { static void _save(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
struct CLIDebuggerBackend* be = debugger->backend;
if (!dv || dv->type != CLIDV_INT_TYPE) { if (!dv || dv->type != CLIDV_INT_TYPE) {
printf("%s\n", ERROR_MISSING_ARGS); be->printf(be, "%s\n", ERROR_MISSING_ARGS);
return; return;
} }
int state = dv->intValue; int state = dv->intValue;
if (state < 1 || state > 9) { if (state < 1 || state > 9) {
printf("State %u out of range", state); be->printf(be, "State %u out of range", state);
} }
struct GBCLIDebugger* gbDebugger = (struct GBCLIDebugger*) debugger->system; struct GBCLIDebugger* gbDebugger = (struct GBCLIDebugger*) debugger->system;
mCoreSaveState(gbDebugger->core, dv->intValue, SAVESTATE_SCREENSHOT); mCoreSaveState(gbDebugger->core, dv->intValue, SAVESTATE_SCREENSHOT);
} }
#endif

View File

@ -6,7 +6,6 @@
#ifndef GB_CLI_H #ifndef GB_CLI_H
#define GB_CLI_H #define GB_CLI_H
#ifdef USE_CLI_DEBUGGER
#include "debugger/cli-debugger.h" #include "debugger/cli-debugger.h"
struct GBCLIDebugger { struct GBCLIDebugger {
@ -19,6 +18,5 @@ struct GBCLIDebugger {
}; };
struct CLIDebuggerSystem* GBCLIDebuggerCreate(struct mCore*); struct CLIDebuggerSystem* GBCLIDebuggerCreate(struct mCore*);
#endif
#endif #endif

View File

@ -430,10 +430,8 @@ static void _GBCoreRawWrite32(struct mCore* core, uint32_t address, int segment,
static bool _GBCoreSupportsDebuggerType(struct mCore* core, enum mDebuggerType type) { static bool _GBCoreSupportsDebuggerType(struct mCore* core, enum mDebuggerType type) {
UNUSED(core); UNUSED(core);
switch (type) { switch (type) {
#ifdef USE_CLI_DEBUGGER
case DEBUGGER_CLI: case DEBUGGER_CLI:
return true; return true;
#endif
default: default:
return false; return false;
} }
@ -448,12 +446,7 @@ static struct mDebuggerPlatform* _GBCoreDebuggerPlatform(struct mCore* core) {
} }
static struct CLIDebuggerSystem* _GBCoreCliDebuggerSystem(struct mCore* core) { static struct CLIDebuggerSystem* _GBCoreCliDebuggerSystem(struct mCore* core) {
#ifdef USE_CLI_DEBUGGER
return GBCLIDebuggerCreate(core); return GBCLIDebuggerCreate(core);
#else
UNUSED(core);
return NULL;
#endif
} }
static void _GBCoreAttachDebugger(struct mCore* core, struct mDebugger* debugger) { static void _GBCoreAttachDebugger(struct mCore* core, struct mDebugger* debugger) {

View File

@ -442,10 +442,8 @@ static void _GBACoreRawWrite32(struct mCore* core, uint32_t address, int segment
static bool _GBACoreSupportsDebuggerType(struct mCore* core, enum mDebuggerType type) { static bool _GBACoreSupportsDebuggerType(struct mCore* core, enum mDebuggerType type) {
UNUSED(core); UNUSED(core);
switch (type) { switch (type) {
#ifdef USE_CLI_DEBUGGER
case DEBUGGER_CLI: case DEBUGGER_CLI:
return true; return true;
#endif
#ifdef USE_GDB_STUB #ifdef USE_GDB_STUB
case DEBUGGER_GDB: case DEBUGGER_GDB:
return true; return true;
@ -464,12 +462,7 @@ static struct mDebuggerPlatform* _GBACoreDebuggerPlatform(struct mCore* core) {
} }
static struct CLIDebuggerSystem* _GBACoreCliDebuggerSystem(struct mCore* core) { static struct CLIDebuggerSystem* _GBACoreCliDebuggerSystem(struct mCore* core) {
#ifdef USE_CLI_DEBUGGER
return &GBACLIDebuggerCreate(core)->d; return &GBACLIDebuggerCreate(core)->d;
#else
UNUSED(core);
return NULL;
#endif
} }
static void _GBACoreAttachDebugger(struct mCore* core, struct mDebugger* debugger) { static void _GBACoreAttachDebugger(struct mCore* core, struct mDebugger* debugger) {

View File

@ -10,8 +10,6 @@
#include "gba/io.h" #include "gba/io.h"
#include "gba/serialize.h" #include "gba/serialize.h"
#ifdef USE_CLI_DEBUGGER
static void _GBACLIDebuggerInit(struct CLIDebuggerSystem*); static void _GBACLIDebuggerInit(struct CLIDebuggerSystem*);
static bool _GBACLIDebuggerCustom(struct CLIDebuggerSystem*); static bool _GBACLIDebuggerCustom(struct CLIDebuggerSystem*);
static uint32_t _GBACLIDebuggerLookupIdentifier(struct CLIDebuggerSystem*, const char* name, struct CLIDebugVector* dv); static uint32_t _GBACLIDebuggerLookupIdentifier(struct CLIDebuggerSystem*, const char* name, struct CLIDebugVector* dv);
@ -87,14 +85,15 @@ static void _frame(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
} }
static void _load(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { static void _load(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
struct CLIDebuggerBackend* be = debugger->backend;
if (!dv || dv->type != CLIDV_INT_TYPE) { if (!dv || dv->type != CLIDV_INT_TYPE) {
printf("%s\n", ERROR_MISSING_ARGS); be->printf(be, "%s\n", ERROR_MISSING_ARGS);
return; return;
} }
int state = dv->intValue; int state = dv->intValue;
if (state < 1 || state > 9) { if (state < 1 || state > 9) {
printf("State %u out of range", state); be->printf(be, "State %u out of range", state);
} }
struct GBACLIDebugger* gbaDebugger = (struct GBACLIDebugger*) debugger->system; struct GBACLIDebugger* gbaDebugger = (struct GBACLIDebugger*) debugger->system;
@ -105,18 +104,18 @@ static void _load(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
// TODO: Put back rewind // TODO: Put back rewind
static void _save(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { static void _save(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
struct CLIDebuggerBackend* be = debugger->backend;
if (!dv || dv->type != CLIDV_INT_TYPE) { if (!dv || dv->type != CLIDV_INT_TYPE) {
printf("%s\n", ERROR_MISSING_ARGS); be->printf(be, "%s\n", ERROR_MISSING_ARGS);
return; return;
} }
int state = dv->intValue; int state = dv->intValue;
if (state < 1 || state > 9) { if (state < 1 || state > 9) {
printf("State %u out of range", state); be->printf(be, "State %u out of range", state);
} }
struct GBACLIDebugger* gbaDebugger = (struct GBACLIDebugger*) debugger->system; struct GBACLIDebugger* gbaDebugger = (struct GBACLIDebugger*) debugger->system;
mCoreSaveState(gbaDebugger->core, dv->intValue, SAVESTATE_SCREENSHOT); mCoreSaveState(gbaDebugger->core, dv->intValue, SAVESTATE_SCREENSHOT);
} }
#endif

View File

@ -6,7 +6,6 @@
#ifndef GBA_CLI_H #ifndef GBA_CLI_H
#define GBA_CLI_H #define GBA_CLI_H
#ifdef USE_CLI_DEBUGGER
#include "debugger/cli-debugger.h" #include "debugger/cli-debugger.h"
struct mCore; struct mCore;
@ -21,6 +20,5 @@ struct GBACLIDebugger {
}; };
struct GBACLIDebugger* GBACLIDebuggerCreate(struct mCore*); struct GBACLIDebugger* GBACLIDebuggerCreate(struct mCore*);
#endif
#endif #endif

View File

@ -5,7 +5,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "cli-debugger.h" #include "cli-debugger.h"
#ifdef USE_CLI_DEBUGGER
#include "core/core.h" #include "core/core.h"
#include "debugger/cli-debugger.h" #include "debugger/cli-debugger.h"
#include "lr35902/lr35902.h" #include "lr35902/lr35902.h"
@ -16,22 +15,23 @@ static struct CLIDebuggerCommandSummary _lr35902Commands[] = {
{ 0, 0, 0, 0 } { 0, 0, 0, 0 }
}; };
static inline void _printFlags(union FlagRegister f) { static inline void _printFlags(struct CLIDebuggerBackend* be, union FlagRegister f) {
printf("[%c%c%c%c]\n", be->printf(be, "[%c%c%c%c]\n",
f.z ? 'Z' : '-', f.z ? 'Z' : '-',
f.n ? 'N' : '-', f.n ? 'N' : '-',
f.h ? 'H' : '-', f.h ? 'H' : '-',
f.c ? 'C' : '-'); f.c ? 'C' : '-');
} }
static void _printStatus(struct CLIDebuggerSystem* debugger) { static void _printStatus(struct CLIDebuggerSystem* debugger) {
struct CLIDebuggerBackend* be = debugger->p->backend;
struct LR35902Core* cpu = debugger->p->d.core->cpu; struct LR35902Core* cpu = debugger->p->d.core->cpu;
printf("A: %02X F: %02X (AF: %04X)\n", cpu->a, cpu->f.packed, cpu->af); be->printf(be, "A: %02X F: %02X (AF: %04X)\n", cpu->a, cpu->f.packed, cpu->af);
printf("B: %02X C: %02X (BC: %04X)\n", cpu->b, cpu->c, cpu->bc); be->printf(be, "B: %02X C: %02X (BC: %04X)\n", cpu->b, cpu->c, cpu->bc);
printf("D: %02X E: %02X (DE: %04X)\n", cpu->d, cpu->e, cpu->de); be->printf(be, "D: %02X E: %02X (DE: %04X)\n", cpu->d, cpu->e, cpu->de);
printf("H: %02X L: %02X (HL: %04X)\n", cpu->h, cpu->l, cpu->hl); be->printf(be, "H: %02X L: %02X (HL: %04X)\n", cpu->h, cpu->l, cpu->hl);
printf("PC: %04X SP: %04X\n", cpu->pc, cpu->sp); be->printf(be, "PC: %04X SP: %04X\n", cpu->pc, cpu->sp);
_printFlags(cpu->f); _printFlags(be, cpu->f);
} }
static uint32_t _lookupPlatformIdentifier(struct CLIDebuggerSystem* debugger, const char* name, struct CLIDebugVector* dv) { static uint32_t _lookupPlatformIdentifier(struct CLIDebuggerSystem* debugger, const char* name, struct CLIDebugVector* dv) {
@ -89,5 +89,3 @@ void LR35902CLIDebuggerCreate(struct CLIDebuggerSystem* debugger) {
debugger->platformName = "GB-Z80"; debugger->platformName = "GB-Z80";
debugger->platformCommands = _lr35902Commands; debugger->platformCommands = _lr35902Commands;
} }
#endif

View File

@ -5,13 +5,14 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "main.h" #include "main.h"
#ifdef USE_CLI_DEBUGGER
#include "debugger/cli-debugger.h" #include "debugger/cli-debugger.h"
#endif
#ifdef USE_GDB_STUB #ifdef USE_GDB_STUB
#include "debugger/gdb-stub.h" #include "debugger/gdb-stub.h"
#endif #endif
#ifdef USE_EDITLINE
#include "feature/editline/cli-el-backend.h"
#endif
#include "core/core.h" #include "core/core.h"
#include "core/config.h" #include "core/config.h"
@ -169,6 +170,12 @@ int mSDLRun(struct mSDLRenderer* renderer, struct mArguments* args) {
mCoreAutoloadSave(renderer->core); mCoreAutoloadSave(renderer->core);
struct mDebugger* debugger = mDebuggerCreate(args->debuggerType, renderer->core); struct mDebugger* debugger = mDebuggerCreate(args->debuggerType, renderer->core);
if (debugger) { if (debugger) {
#ifdef USE_EDITLINE
if (args->debuggerType == DEBUGGER_CLI) {
struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger;
CLIDebuggerAttachBackend(cliDebugger, CLIDebuggerEditLineBackendCreate());
}
#endif
mDebuggerAttach(debugger, renderer->core); mDebuggerAttach(debugger, renderer->core);
mDebuggerEnter(debugger, DEBUGGER_ENTER_MANUAL, NULL); mDebuggerEnter(debugger, DEBUGGER_ENTER_MANUAL, NULL);
} }