mirror of https://github.com/mgba-emu/mgba.git
Debugger: Modularize CLI debugger
This commit is contained in:
parent
474f1c6e9c
commit
a0d223eef7
1
CHANGES
1
CHANGES
|
@ -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:
|
||||||
|
|
|
@ -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}")
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
13
src/gb/cli.c
13
src/gb/cli.c
|
@ -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
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue