mirror of https://github.com/mgba-emu/mgba.git
Debugger: Separate aliases from main commands
This commit is contained in:
parent
84000ed7fc
commit
a6fc606a2d
1
CHANGES
1
CHANGES
|
@ -108,6 +108,7 @@ Other fixes:
|
||||||
Misc:
|
Misc:
|
||||||
- GB Memory: Support manual SRAM editing (fixes mgba.io/i/1580)
|
- GB Memory: Support manual SRAM editing (fixes mgba.io/i/1580)
|
||||||
- SDL: Use controller GUID instead of name
|
- SDL: Use controller GUID instead of name
|
||||||
|
- Debugger: Separate aliases from main commands
|
||||||
|
|
||||||
0.8 beta 1: (2019-10-20)
|
0.8 beta 1: (2019-10-20)
|
||||||
- Initial beta for 0.8
|
- Initial beta for 0.8
|
||||||
|
|
|
@ -42,6 +42,11 @@ struct CLIDebuggerCommandSummary {
|
||||||
const char* summary;
|
const char* summary;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CLIDebuggerCommandAlias {
|
||||||
|
const char* name;
|
||||||
|
const char* original;
|
||||||
|
};
|
||||||
|
|
||||||
struct CLIDebuggerSystem {
|
struct CLIDebuggerSystem {
|
||||||
struct CLIDebugger* p;
|
struct CLIDebugger* p;
|
||||||
|
|
||||||
|
@ -53,8 +58,10 @@ struct CLIDebuggerSystem {
|
||||||
void (*printStatus)(struct CLIDebuggerSystem*);
|
void (*printStatus)(struct CLIDebuggerSystem*);
|
||||||
|
|
||||||
struct CLIDebuggerCommandSummary* commands;
|
struct CLIDebuggerCommandSummary* commands;
|
||||||
|
struct CLIDebuggerCommandAlias* commandAliases;
|
||||||
const char* name;
|
const char* name;
|
||||||
struct CLIDebuggerCommandSummary* platformCommands;
|
struct CLIDebuggerCommandSummary* platformCommands;
|
||||||
|
struct CLIDebuggerCommandAlias* platformCommandAliases;
|
||||||
const char* platformName;
|
const char* platformName;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -22,19 +22,23 @@ static void _disassembleMode(struct CLIDebugger*, struct CLIDebugVector*, enum E
|
||||||
static uint32_t _printLine(struct CLIDebugger* debugger, uint32_t address, enum ExecutionMode mode);
|
static uint32_t _printLine(struct CLIDebugger* debugger, uint32_t address, enum ExecutionMode mode);
|
||||||
|
|
||||||
static struct CLIDebuggerCommandSummary _armCommands[] = {
|
static struct CLIDebuggerCommandSummary _armCommands[] = {
|
||||||
{ "b/a", _setBreakpointARM, "I", "Set a software breakpoint as ARM" },
|
|
||||||
{ "b/t", _setBreakpointThumb, "I", "Set a software breakpoint as Thumb" },
|
|
||||||
{ "break/a", _setBreakpointARM, "I", "Set a software breakpoint as ARM" },
|
{ "break/a", _setBreakpointARM, "I", "Set a software breakpoint as ARM" },
|
||||||
{ "break/t", _setBreakpointThumb, "I", "Set a software breakpoint as Thumb" },
|
{ "break/t", _setBreakpointThumb, "I", "Set a software breakpoint as Thumb" },
|
||||||
{ "dis/a", _disassembleArm, "Ii", "Disassemble instructions as ARM" },
|
|
||||||
{ "dis/t", _disassembleThumb, "Ii", "Disassemble instructions as Thumb" },
|
|
||||||
{ "disasm/a", _disassembleArm, "Ii", "Disassemble instructions as ARM" },
|
|
||||||
{ "disasm/t", _disassembleThumb, "Ii", "Disassemble instructions as Thumb" },
|
|
||||||
{ "disassemble/a", _disassembleArm, "Ii", "Disassemble instructions as ARM" },
|
{ "disassemble/a", _disassembleArm, "Ii", "Disassemble instructions as ARM" },
|
||||||
{ "disassemble/t", _disassembleThumb, "Ii", "Disassemble instructions as Thumb" },
|
{ "disassemble/t", _disassembleThumb, "Ii", "Disassemble instructions as Thumb" },
|
||||||
{ 0, 0, 0, 0 }
|
{ 0, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct CLIDebuggerCommandAlias _armCommandAliases[] = {
|
||||||
|
{ "b/a", "break/a" },
|
||||||
|
{ "b/t", "break/t" },
|
||||||
|
{ "dis/a", "disassemble/a" },
|
||||||
|
{ "dis/t", "disassemble/t" },
|
||||||
|
{ "disasm/a", "disassemble/a" },
|
||||||
|
{ "disasm/t", "disassemble/t" },
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
static inline void _printPSR(struct CLIDebuggerBackend* be, union PSR psr) {
|
static inline void _printPSR(struct CLIDebuggerBackend* be, union PSR psr) {
|
||||||
be->printf(be, "%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' : '-',
|
||||||
|
@ -175,4 +179,5 @@ void ARMCLIDebuggerCreate(struct CLIDebuggerSystem* debugger) {
|
||||||
debugger->disassemble = _disassemble;
|
debugger->disassemble = _disassemble;
|
||||||
debugger->platformName = "ARM";
|
debugger->platformName = "ARM";
|
||||||
debugger->platformCommands = _armCommands;
|
debugger->platformCommands = _armCommands;
|
||||||
|
debugger->platformCommandAliases = _armCommandAliases;
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,32 +71,17 @@ static void _source(struct CLIDebugger*, struct CLIDebugVector*);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static struct CLIDebuggerCommandSummary _debuggerCommands[] = {
|
static struct CLIDebuggerCommandSummary _debuggerCommands[] = {
|
||||||
{ "b", _setBreakpoint, "Is", "Set a breakpoint" },
|
|
||||||
{ "break", _setBreakpoint, "Is", "Set a breakpoint" },
|
{ "break", _setBreakpoint, "Is", "Set a breakpoint" },
|
||||||
{ "c", _continue, "", "Continue execution" },
|
|
||||||
{ "continue", _continue, "", "Continue execution" },
|
{ "continue", _continue, "", "Continue execution" },
|
||||||
{ "d", _clearBreakpoint, "I", "Delete a breakpoint or watchpoint" },
|
|
||||||
{ "delete", _clearBreakpoint, "I", "Delete a breakpoint or watchpoint" },
|
{ "delete", _clearBreakpoint, "I", "Delete a breakpoint or watchpoint" },
|
||||||
{ "dis", _disassemble, "Ii", "Disassemble instructions" },
|
|
||||||
{ "disasm", _disassemble, "Ii", "Disassemble instructions" },
|
|
||||||
{ "disassemble", _disassemble, "Ii", "Disassemble instructions" },
|
{ "disassemble", _disassemble, "Ii", "Disassemble instructions" },
|
||||||
{ "h", _printHelp, "S", "Print help" },
|
|
||||||
{ "help", _printHelp, "S", "Print help" },
|
{ "help", _printHelp, "S", "Print help" },
|
||||||
{ "i", _printStatus, "", "Print the current status" },
|
|
||||||
{ "info", _printStatus, "", "Print the current status" },
|
|
||||||
{ "lb", _listBreakpoints, "", "List breakpoints" },
|
|
||||||
{ "listb", _listBreakpoints, "", "List breakpoints" },
|
{ "listb", _listBreakpoints, "", "List breakpoints" },
|
||||||
{ "lw", _listWatchpoints, "", "List watchpoints" },
|
|
||||||
{ "listw", _listWatchpoints, "", "List watchpoints" },
|
{ "listw", _listWatchpoints, "", "List watchpoints" },
|
||||||
{ "n", _next, "", "Execute next instruction" },
|
|
||||||
{ "next", _next, "", "Execute next instruction" },
|
{ "next", _next, "", "Execute next instruction" },
|
||||||
{ "p", _print, "S+", "Print a value" },
|
|
||||||
{ "p/t", _printBin, "S+", "Print a value as binary" },
|
|
||||||
{ "p/x", _printHex, "S+", "Print a value as hexadecimal" },
|
|
||||||
{ "print", _print, "S+", "Print a value" },
|
{ "print", _print, "S+", "Print a value" },
|
||||||
{ "print/t", _printBin, "S+", "Print a value as binary" },
|
{ "print/t", _printBin, "S+", "Print a value as binary" },
|
||||||
{ "print/x", _printHex, "S+", "Print a value as hexadecimal" },
|
{ "print/x", _printHex, "S+", "Print a value as hexadecimal" },
|
||||||
{ "q", _quit, "", "Quit the emulator" },
|
|
||||||
{ "quit", _quit, "", "Quit the emulator" },
|
{ "quit", _quit, "", "Quit the emulator" },
|
||||||
{ "reset", _reset, "", "Reset the emulation" },
|
{ "reset", _reset, "", "Reset the emulation" },
|
||||||
{ "r/1", _readByte, "I", "Read a byte from a specified offset" },
|
{ "r/1", _readByte, "I", "Read a byte from a specified offset" },
|
||||||
|
@ -104,7 +89,6 @@ static struct CLIDebuggerCommandSummary _debuggerCommands[] = {
|
||||||
{ "r/4", _readWord, "I", "Read a word from a specified offset" },
|
{ "r/4", _readWord, "I", "Read a word from a specified offset" },
|
||||||
{ "status", _printStatus, "", "Print the current status" },
|
{ "status", _printStatus, "", "Print the current status" },
|
||||||
{ "trace", _trace, "Is", "Trace a number of instructions" },
|
{ "trace", _trace, "Is", "Trace a number of instructions" },
|
||||||
{ "w", _setReadWriteWatchpoint, "Is", "Set a watchpoint" },
|
|
||||||
{ "w/1", _writeByte, "II", "Write a byte at a specified offset" },
|
{ "w/1", _writeByte, "II", "Write a byte at a specified offset" },
|
||||||
{ "w/2", _writeHalfword, "II", "Write a halfword at a specified offset" },
|
{ "w/2", _writeHalfword, "II", "Write a halfword at a specified offset" },
|
||||||
{ "w/r", _writeRegister, "SI", "Write a register" },
|
{ "w/r", _writeRegister, "SI", "Write a register" },
|
||||||
|
@ -125,6 +109,26 @@ static struct CLIDebuggerCommandSummary _debuggerCommands[] = {
|
||||||
{ 0, 0, 0, 0 }
|
{ 0, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct CLIDebuggerCommandAlias _debuggerCommandAliases[] = {
|
||||||
|
{ "b", "break" },
|
||||||
|
{ "c", "continue" },
|
||||||
|
{ "d", "delete" },
|
||||||
|
{ "dis", "disassemble" },
|
||||||
|
{ "disasm", "disassemble" },
|
||||||
|
{ "h", "help" },
|
||||||
|
{ "i", "status" },
|
||||||
|
{ "info", "status" },
|
||||||
|
{ "lb", "listb" },
|
||||||
|
{ "lw", "listw" },
|
||||||
|
{ "n", "next" },
|
||||||
|
{ "p", "print" },
|
||||||
|
{ "p/t", "print/t" },
|
||||||
|
{ "p/x", "print/x" },
|
||||||
|
{ "q", "quit" },
|
||||||
|
{ "w", "watch" },
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
#if !defined(NDEBUG) && !defined(_WIN32)
|
#if !defined(NDEBUG) && !defined(_WIN32)
|
||||||
static void _handleDeath(int sig) {
|
static void _handleDeath(int sig) {
|
||||||
UNUSED(sig);
|
UNUSED(sig);
|
||||||
|
@ -232,42 +236,71 @@ static void _printHex(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
|
||||||
debugger->backend->printf(debugger->backend, " 0x%08X\n", intValue);
|
debugger->backend->printf(debugger->backend, " 0x%08X\n", intValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _printCommands(struct CLIDebugger* debugger, struct CLIDebuggerCommandSummary* commands, struct CLIDebuggerCommandAlias* aliases) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; commands[i].name; ++i) {
|
||||||
|
debugger->backend->printf(debugger->backend, "%-15s %s\n", commands[i].name, commands[i].summary);
|
||||||
|
if (aliases) {
|
||||||
|
bool printedAlias = false;
|
||||||
|
int j;
|
||||||
|
for (j = 0; aliases[j].name; ++j) {
|
||||||
|
if (strcmp(aliases[j].original, commands[i].name) == 0) {
|
||||||
|
if (!printedAlias) {
|
||||||
|
debugger->backend->printf(debugger->backend, " Aliases:");
|
||||||
|
printedAlias = true;
|
||||||
|
}
|
||||||
|
debugger->backend->printf(debugger->backend, " %s", aliases[j].name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (printedAlias) {
|
||||||
|
debugger->backend->printf(debugger->backend, "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _printCommandSummary(struct CLIDebugger* debugger, const char* name, struct CLIDebuggerCommandSummary* commands, struct CLIDebuggerCommandAlias* aliases) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; commands[i].name; ++i) {
|
||||||
|
if (strcmp(commands[i].name, name) == 0) {
|
||||||
|
debugger->backend->printf(debugger->backend, " %s\n", commands[i].summary);
|
||||||
|
if (aliases) {
|
||||||
|
bool printedAlias = false;
|
||||||
|
int j;
|
||||||
|
for (j = 0; aliases[j].name; ++j) {
|
||||||
|
if (strcmp(aliases[j].original, commands[i].name) == 0) {
|
||||||
|
if (!printedAlias) {
|
||||||
|
debugger->backend->printf(debugger->backend, " Aliases:");
|
||||||
|
printedAlias = true;
|
||||||
|
}
|
||||||
|
debugger->backend->printf(debugger->backend, " %s", aliases[j].name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (printedAlias) {
|
||||||
|
debugger->backend->printf(debugger->backend, "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void _printHelp(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
|
static void _printHelp(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
|
||||||
UNUSED(dv);
|
UNUSED(dv);
|
||||||
if (!dv) {
|
if (!dv) {
|
||||||
debugger->backend->printf(debugger->backend, "Generic commands:\n");
|
debugger->backend->printf(debugger->backend, "Generic commands:\n");
|
||||||
int i;
|
_printCommands(debugger, _debuggerCommands, _debuggerCommandAliases);
|
||||||
for (i = 0; _debuggerCommands[i].name; ++i) {
|
|
||||||
debugger->backend->printf(debugger->backend, "%-10s %s\n", _debuggerCommands[i].name, _debuggerCommands[i].summary);
|
|
||||||
}
|
|
||||||
if (debugger->system) {
|
if (debugger->system) {
|
||||||
debugger->backend->printf(debugger->backend, "%s commands:\n", debugger->system->platformName);
|
debugger->backend->printf(debugger->backend, "\n%s commands:\n", debugger->system->platformName);
|
||||||
for (i = 0; debugger->system->platformCommands[i].name; ++i) {
|
_printCommands(debugger, debugger->system->platformCommands, debugger->system->platformCommandAliases);
|
||||||
debugger->backend->printf(debugger->backend, "%-10s %s\n", debugger->system->platformCommands[i].name, debugger->system->platformCommands[i].summary);
|
debugger->backend->printf(debugger->backend, "\n%s commands:\n", debugger->system->name);
|
||||||
}
|
_printCommands(debugger, debugger->system->commands, debugger->system->commandAliases);
|
||||||
debugger->backend->printf(debugger->backend, "%s commands:\n", debugger->system->name);
|
|
||||||
for (i = 0; debugger->system->commands[i].name; ++i) {
|
|
||||||
debugger->backend->printf(debugger->backend, "%-10s %s\n", debugger->system->commands[i].name, debugger->system->commands[i].summary);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int i;
|
_printCommandSummary(debugger, dv->charValue, _debuggerCommands, _debuggerCommandAliases);
|
||||||
for (i = 0; _debuggerCommands[i].name; ++i) {
|
|
||||||
if (strcmp(_debuggerCommands[i].name, dv->charValue) == 0) {
|
|
||||||
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) {
|
_printCommandSummary(debugger, dv->charValue, debugger->system->platformCommands, debugger->system->platformCommandAliases);
|
||||||
if (strcmp(debugger->system->platformCommands[i].name, dv->charValue) == 0) {
|
_printCommandSummary(debugger, dv->charValue, debugger->system->commands, debugger->system->commandAliases);
|
||||||
debugger->backend->printf(debugger->backend, " %s\n", debugger->system->platformCommands[i].summary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (i = 0; debugger->system->commands[i].name; ++i) {
|
|
||||||
if (strcmp(debugger->system->commands[i].name, dv->charValue) == 0) {
|
|
||||||
debugger->backend->printf(debugger->backend, " %s\n", debugger->system->commands[i].summary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -784,11 +817,22 @@ static struct CLIDebugVector* _parseArg(struct CLIDebugger* debugger, const char
|
||||||
return dv;
|
return dv;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _tryCommands(struct CLIDebugger* debugger, struct CLIDebuggerCommandSummary* commands, const char* command, size_t commandLen, const char* args, size_t argsLen) {
|
static int _tryCommands(struct CLIDebugger* debugger, struct CLIDebuggerCommandSummary* commands, struct CLIDebuggerCommandAlias* aliases, const char* command, size_t commandLen, const char* args, size_t argsLen) {
|
||||||
struct CLIDebugVector* dv = NULL;
|
struct CLIDebugVector* dv = NULL;
|
||||||
struct CLIDebugVector* dvLast = NULL;
|
struct CLIDebugVector* dvLast = NULL;
|
||||||
int i;
|
int i;
|
||||||
const char* name;
|
const char* name;
|
||||||
|
if (aliases) {
|
||||||
|
for (i = 0; (name = aliases[i].name); ++i) {
|
||||||
|
if (strlen(name) != commandLen) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (strncasecmp(name, command, commandLen) == 0) {
|
||||||
|
command = aliases[i].original;
|
||||||
|
commandLen = strlen(aliases[i].original);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
for (i = 0; (name = commands[i].name); ++i) {
|
for (i = 0; (name = commands[i].name); ++i) {
|
||||||
if (strlen(name) != commandLen) {
|
if (strlen(name) != commandLen) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -885,11 +929,11 @@ static bool _parse(struct CLIDebugger* debugger, const char* line, size_t count)
|
||||||
if (firstSpace) {
|
if (firstSpace) {
|
||||||
args = firstSpace + 1;
|
args = firstSpace + 1;
|
||||||
}
|
}
|
||||||
int result = _tryCommands(debugger, _debuggerCommands, line, cmdLength, args, count - cmdLength - 1);
|
int result = _tryCommands(debugger, _debuggerCommands, _debuggerCommandAliases, line, cmdLength, args, count - cmdLength - 1);
|
||||||
if (result < 0 && debugger->system) {
|
if (result < 0 && debugger->system) {
|
||||||
result = _tryCommands(debugger, debugger->system->commands, line, cmdLength, args, count - cmdLength - 1);
|
result = _tryCommands(debugger, debugger->system->commands, debugger->system->commandAliases, line, cmdLength, args, count - cmdLength - 1);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
result = _tryCommands(debugger, debugger->system->platformCommands, line, cmdLength, args, count - cmdLength - 1);
|
result = _tryCommands(debugger, debugger->system->platformCommands, debugger->system->platformCommandAliases, line, cmdLength, args, count - cmdLength - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
|
|
|
@ -36,6 +36,7 @@ struct CLIDebuggerSystem* GBCLIDebuggerCreate(struct mCore* core) {
|
||||||
|
|
||||||
debugger->d.name = "Game Boy";
|
debugger->d.name = "Game Boy";
|
||||||
debugger->d.commands = _GBCLIDebuggerCommands;
|
debugger->d.commands = _GBCLIDebuggerCommands;
|
||||||
|
debugger->d.commandAliases = NULL;
|
||||||
|
|
||||||
debugger->core = core;
|
debugger->core = core;
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ struct GBACLIDebugger* GBACLIDebuggerCreate(struct mCore* core) {
|
||||||
|
|
||||||
debugger->d.name = "Game Boy Advance";
|
debugger->d.name = "Game Boy Advance";
|
||||||
debugger->d.commands = _GBACLIDebuggerCommands;
|
debugger->d.commands = _GBACLIDebuggerCommands;
|
||||||
|
debugger->d.commandAliases = NULL;
|
||||||
|
|
||||||
debugger->core = core;
|
debugger->core = core;
|
||||||
|
|
||||||
|
|
|
@ -108,4 +108,5 @@ void LR35902CLIDebuggerCreate(struct CLIDebuggerSystem* debugger) {
|
||||||
debugger->disassemble = _disassemble;
|
debugger->disassemble = _disassemble;
|
||||||
debugger->platformName = "GB-Z80";
|
debugger->platformName = "GB-Z80";
|
||||||
debugger->platformCommands = _lr35902Commands;
|
debugger->platformCommands = _lr35902Commands;
|
||||||
|
debugger->platformCommandAliases = NULL;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue