Skip to content

Added the disass-style command to the debugger #2907

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions include/mgba/debugger/debugger.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ enum mDebuggerEntryReason {
DEBUGGER_ENTER_STACK
};

enum mDisassemblyStyle {
DISASSEMBLY_STYLE_DECIMAL,
DISASSEMBLY_STYLE_HEX
};

struct mDebuggerEntryInfo {
uint32_t address;
union {
Expand Down Expand Up @@ -102,6 +107,7 @@ struct mDebugger;
struct ParseTree;
struct mDebuggerPlatform {
struct mDebugger* p;
enum mDisassemblyStyle disassemblyStyle;

void (*init)(void* cpu, struct mDebuggerPlatform*);
void (*deinit)(struct mDebuggerPlatform*);
Expand Down
3 changes: 2 additions & 1 deletion include/mgba/internal/arm/decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

CXX_GUARD_START

#include <mgba/debugger/debugger.h>
#include <mgba/internal/arm/arm.h>

// Bit 0: a register is involved with this operand
Expand Down Expand Up @@ -223,7 +224,7 @@ uint32_t ARMResolveMemoryAccess(struct ARMInstructionInfo* info, struct ARMRegis

#ifdef USE_DEBUGGERS
struct mDebuggerSymbols;
int ARMDisassemble(const struct ARMInstructionInfo* info, struct ARMCore* core, const struct mDebuggerSymbols* symbols, uint32_t pc, char* buffer, int blen);
int ARMDisassemble(const struct ARMInstructionInfo* info, struct ARMCore* core, const struct mDebuggerSymbols* symbols, uint32_t pc, enum mDisassemblyStyle disassemblyStyle, char* buffer, int blen);
#endif

CXX_GUARD_END
Expand Down
4 changes: 3 additions & 1 deletion include/mgba/internal/sm83/decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

CXX_GUARD_START

#include <mgba/debugger/debugger.h>

enum SM83Condition {
SM83_COND_NONE = 0x0,
SM83_COND_C = 0x1,
Expand Down Expand Up @@ -105,7 +107,7 @@ struct SM83InstructionInfo {
};

size_t SM83Decode(uint8_t opcode, struct SM83InstructionInfo* info);
int SM83Disassemble(struct SM83InstructionInfo* info, uint16_t pc, char* buffer, int blen);
int SM83Disassemble(struct SM83InstructionInfo* info, uint16_t pc, enum mDisassemblyStyle, char* buffer, int blen);

CXX_GUARD_END

Expand Down
6 changes: 3 additions & 3 deletions src/arm/debugger/cli-debugger.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ static inline uint32_t _printLine(struct CLIDebugger* debugger, uint32_t address
if (mode == MODE_ARM) {
uint32_t instruction = core->busRead32(core, address & ~(WORD_SIZE_ARM - 1));
ARMDecodeARM(instruction, &info);
ARMDisassemble(&info, core->cpu, core->symbolTable, address + WORD_SIZE_ARM * 2, disassembly, sizeof(disassembly));
ARMDisassemble(&info, core->cpu, core->symbolTable, address + WORD_SIZE_ARM * 2, debugger->d.platform->disassemblyStyle, disassembly, sizeof(disassembly));
be->printf(be, "%08X\t%s\n", instruction, disassembly);
return WORD_SIZE_ARM;
} else {
Expand All @@ -117,11 +117,11 @@ static inline uint32_t _printLine(struct CLIDebugger* debugger, uint32_t address
ARMDecodeThumb(instruction, &info);
ARMDecodeThumb(instruction2, &info2);
if (ARMDecodeThumbCombine(&info, &info2, &combined)) {
ARMDisassemble(&combined, core->cpu, core->symbolTable, address + WORD_SIZE_THUMB * 2, disassembly, sizeof(disassembly));
ARMDisassemble(&combined, core->cpu, core->symbolTable, address + WORD_SIZE_THUMB * 2, debugger->d.platform->disassemblyStyle, disassembly, sizeof(disassembly));
be->printf(be, "%04X %04X\t%s\n", instruction, instruction2, disassembly);
return WORD_SIZE_THUMB * 2;
} else {
ARMDisassemble(&info, core->cpu, core->symbolTable, address + WORD_SIZE_THUMB * 2, disassembly, sizeof(disassembly));
ARMDisassemble(&info, core->cpu, core->symbolTable, address + WORD_SIZE_THUMB * 2, debugger->d.platform->disassemblyStyle, disassembly, sizeof(disassembly));
be->printf(be, "%04X \t%s\n", instruction, disassembly);
return WORD_SIZE_THUMB;
}
Expand Down
6 changes: 3 additions & 3 deletions src/arm/debugger/debugger.c
Original file line number Diff line number Diff line change
Expand Up @@ -472,17 +472,17 @@ static void ARMDebuggerTrace(struct mDebuggerPlatform* d, char* out, size_t* len
if (cpu->executionMode == MODE_ARM) {
uint32_t instruction = cpu->prefetch[0];
sprintf(disassembly, "%08X: ", instruction);
ARMDisassemble(&info, cpu, core->symbolTable, cpu->gprs[ARM_PC], disassembly + strlen("00000000: "), sizeof(disassembly) - strlen("00000000: "));
ARMDisassemble(&info, cpu, core->symbolTable, cpu->gprs[ARM_PC], d->disassemblyStyle, disassembly + strlen("00000000: "), sizeof(disassembly) - strlen("00000000: "));
} else {
uint16_t instruction = cpu->prefetch[0];
ARMDecodeThumb(instruction, &info);
if (isWideInstruction) {
uint16_t instruction2 = cpu->prefetch[1];
sprintf(disassembly, "%04X%04X: ", instruction, instruction2);
ARMDisassemble(&info, cpu, core->symbolTable, cpu->gprs[ARM_PC], disassembly + strlen("00000000: "), sizeof(disassembly) - strlen("00000000: "));
ARMDisassemble(&info, cpu, core->symbolTable, cpu->gprs[ARM_PC], d->disassemblyStyle, disassembly + strlen("00000000: "), sizeof(disassembly) - strlen("00000000: "));
} else {
sprintf(disassembly, " %04X: ", instruction);
ARMDisassemble(&info, cpu, core->symbolTable, cpu->gprs[ARM_PC], disassembly + strlen("00000000: "), sizeof(disassembly) - strlen("00000000: "));
ARMDisassemble(&info, cpu, core->symbolTable, cpu->gprs[ARM_PC], d->disassemblyStyle, disassembly + strlen("00000000: "), sizeof(disassembly) - strlen("00000000: "));
}
}

Expand Down
61 changes: 36 additions & 25 deletions src/arm/decoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <mgba/internal/arm/decoder-inlines.h>
#include <mgba/internal/debugger/symbols.h>
#include <mgba/debugger/debugger.h>
#include <mgba-util/string.h>

#ifdef USE_DEBUGGERS
Expand All @@ -19,12 +20,13 @@
buffer += AMOUNT; \
blen -= AMOUNT;

static int _decodeImmediate(int imm, enum mDisassemblyStyle disassemblyStyle, char* buffer, int blen);
static int _decodeRegister(int reg, char* buffer, int blen);
static int _decodeRegisterList(int list, char* buffer, int blen);
static int _decodePSR(int bits, char* buffer, int blen);
static int _decodePCRelative(uint32_t address, const struct mDebuggerSymbols* symbols, uint32_t pc, bool thumbBranch, char* buffer, int blen);
static int _decodeMemory(struct ARMMemoryAccess memory, struct ARMCore* cpu, const struct mDebuggerSymbols* symbols, int pc, char* buffer, int blen);
static int _decodeShift(union ARMOperand operand, bool reg, char* buffer, int blen);
static int _decodeMemory(struct ARMMemoryAccess memory, struct ARMCore* cpu, const struct mDebuggerSymbols* symbols, int pc, enum mDisassemblyStyle disassemblyStyle, char* buffer, int blen);
static int _decodeShift(union ARMOperand operand, bool reg, enum mDisassemblyStyle disassemblyStyle, char* buffer, int blen);

static const char* _armConditions[] = {
"eq",
Expand All @@ -45,6 +47,15 @@ static const char* _armConditions[] = {
"nv"
};

static int _decodeImmediate(int imm, enum mDisassemblyStyle disassemblyStyle, char* buffer, int blen) {
switch(disassemblyStyle) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
switch(disassemblyStyle) {
switch (disassemblyStyle) {

Also, I meant having both the default and explicit cases separately listed, but it should probably be done with an if/else like you have in the SM83 implementation.

case DISASSEMBLY_STYLE_HEX:
return snprintf(buffer, blen, "#0x%x", imm);
default:
return snprintf(buffer, blen, "#%i", imm);
}
}

static int _decodeRegister(int reg, char* buffer, int blen) {
switch (reg) {
case ARM_SP:
Expand Down Expand Up @@ -159,7 +170,7 @@ static int _decodePCRelative(uint32_t address, const struct mDebuggerSymbols* sy
}
}

static int _decodeMemory(struct ARMMemoryAccess memory, struct ARMCore* cpu, const struct mDebuggerSymbols* symbols, int pc, char* buffer, int blen) {
static int _decodeMemory(struct ARMMemoryAccess memory, struct ARMCore* cpu, const struct mDebuggerSymbols* symbols, int pc, enum mDisassemblyStyle disassemblyStyle, char* buffer, int blen) {
if (blen <= 1) {
return 0;
}
Expand Down Expand Up @@ -227,10 +238,10 @@ static int _decodeMemory(struct ARMMemoryAccess memory, struct ARMCore* cpu, con
}
if (memory.format & ARM_MEMORY_IMMEDIATE_OFFSET && memory.baseReg != ARM_PC) {
if (memory.format & ARM_MEMORY_OFFSET_SUBTRACT) {
written = snprintf(buffer, blen, "#-%i", memory.offset.immediate);
written = _decodeImmediate(-memory.offset.immediate, disassemblyStyle, buffer, blen);
ADVANCE(written);
} else {
written = snprintf(buffer, blen, "#%i", memory.offset.immediate);
written = _decodeImmediate(memory.offset.immediate, disassemblyStyle, buffer, blen);
ADVANCE(written);
}
} else if (memory.format & ARM_MEMORY_REGISTER_OFFSET) {
Expand All @@ -242,7 +253,7 @@ static int _decodeMemory(struct ARMMemoryAccess memory, struct ARMCore* cpu, con
ADVANCE(written);
}
if (memory.format & ARM_MEMORY_SHIFTED_OFFSET) {
written = _decodeShift(memory.offset, false, buffer, blen);
written = _decodeShift(memory.offset, false, disassemblyStyle, buffer, blen);
ADVANCE(written);
}

Expand All @@ -261,7 +272,7 @@ static int _decodeMemory(struct ARMMemoryAccess memory, struct ARMCore* cpu, con
return total;
}

static int _decodeShift(union ARMOperand op, bool reg, char* buffer, int blen) {
static int _decodeShift(union ARMOperand op, bool reg, enum mDisassemblyStyle disassemblyStyle, char* buffer, int blen) {
if (blen <= 1) {
return 0;
}
Expand Down Expand Up @@ -292,7 +303,7 @@ static int _decodeShift(union ARMOperand op, bool reg, char* buffer, int blen) {
return total;
}
if (!reg) {
written = snprintf(buffer, blen, "#%i", op.shifterImm);
written = _decodeImmediate(op.shifterImm, disassemblyStyle, buffer, blen);
} else {
written = _decodeRegister(op.shifterReg, buffer, blen);
}
Expand Down Expand Up @@ -381,7 +392,7 @@ static const char* _armAccessTypeStrings[] = {
""
};

int ARMDisassemble(const struct ARMInstructionInfo* info, struct ARMCore* cpu, const struct mDebuggerSymbols* symbols, uint32_t pc, char* buffer, int blen) {
int ARMDisassemble(const struct ARMInstructionInfo* info, struct ARMCore* cpu, const struct mDebuggerSymbols* symbols, uint32_t pc, enum mDisassemblyStyle disassemblyStyle, char* buffer, int blen) {
const char* mnemonic = _armMnemonicStrings[info->mnemonic];
int written;
int total = 0;
Expand Down Expand Up @@ -465,10 +476,10 @@ int ARMDisassemble(const struct ARMInstructionInfo* info, struct ARMCore* cpu, c
break;
default:
if (info->operandFormat & ARM_OPERAND_IMMEDIATE_1) {
written = snprintf(buffer, blen, "#%i", info->op1.immediate);
written = _decodeImmediate(info->op1.immediate, disassemblyStyle, buffer, blen);
ADVANCE(written);
} else if (info->operandFormat & ARM_OPERAND_MEMORY_1) {
written = _decodeMemory(info->memory, cpu, symbols, pc, buffer, blen);
written = _decodeMemory(info->memory, cpu, symbols, pc, disassemblyStyle, buffer, blen);
ADVANCE(written);
} else if (info->operandFormat & ARM_OPERAND_REGISTER_1) {
written = _decodeRegister(info->op1.reg, buffer, blen);
Expand All @@ -479,31 +490,31 @@ int ARMDisassemble(const struct ARMInstructionInfo* info, struct ARMCore* cpu, c
}
}
if (info->operandFormat & ARM_OPERAND_SHIFT_REGISTER_1) {
written = _decodeShift(info->op1, true, buffer, blen);
written = _decodeShift(info->op1, true, disassemblyStyle, buffer, blen);
ADVANCE(written);
} else if (info->operandFormat & ARM_OPERAND_SHIFT_IMMEDIATE_1) {
written = _decodeShift(info->op1, false, buffer, blen);
written = _decodeShift(info->op1, false, disassemblyStyle, buffer, blen);
ADVANCE(written);
}
if (info->operandFormat & ARM_OPERAND_2) {
strlcpy(buffer, ", ", blen);
ADVANCE(2);
}
if (info->operandFormat & ARM_OPERAND_IMMEDIATE_2) {
written = snprintf(buffer, blen, "#%i", info->op2.immediate);
written = _decodeImmediate(info->op2.immediate, disassemblyStyle, buffer, blen);
ADVANCE(written);
} else if (info->operandFormat & ARM_OPERAND_MEMORY_2) {
written = _decodeMemory(info->memory, cpu, symbols, pc, buffer, blen);
written = _decodeMemory(info->memory, cpu, symbols, pc, disassemblyStyle, buffer, blen);
ADVANCE(written);
} else if (info->operandFormat & ARM_OPERAND_REGISTER_2) {
written = _decodeRegister(info->op2.reg, buffer, blen);
ADVANCE(written);
}
if (info->operandFormat & ARM_OPERAND_SHIFT_REGISTER_2) {
written = _decodeShift(info->op2, true, buffer, blen);
written = _decodeShift(info->op2, true, disassemblyStyle, buffer, blen);
ADVANCE(written);
} else if (info->operandFormat & ARM_OPERAND_SHIFT_IMMEDIATE_2) {
written = _decodeShift(info->op2, false, buffer, blen);
written = _decodeShift(info->op2, false, disassemblyStyle, buffer, blen);
ADVANCE(written);
}
if (!skip3) {
Expand All @@ -512,20 +523,20 @@ int ARMDisassemble(const struct ARMInstructionInfo* info, struct ARMCore* cpu, c
ADVANCE(2);
}
if (info->operandFormat & ARM_OPERAND_IMMEDIATE_3) {
written = snprintf(buffer, blen, "#%i", info->op3.immediate);
written = _decodeImmediate(info->op3.immediate, disassemblyStyle, buffer, blen);
ADVANCE(written);
} else if (info->operandFormat & ARM_OPERAND_MEMORY_3) {
written = _decodeMemory(info->memory, cpu, symbols, pc, buffer, blen);
written = _decodeMemory(info->memory, cpu, symbols, pc, disassemblyStyle, buffer, blen);
ADVANCE(written);
} else if (info->operandFormat & ARM_OPERAND_REGISTER_3) {
written = _decodeRegister(info->op3.reg, buffer, blen);
ADVANCE(written);
}
if (info->operandFormat & ARM_OPERAND_SHIFT_REGISTER_3) {
written = _decodeShift(info->op3, true, buffer, blen);
written = _decodeShift(info->op3, true, disassemblyStyle, buffer, blen);
ADVANCE(written);
} else if (info->operandFormat & ARM_OPERAND_SHIFT_IMMEDIATE_3) {
written = _decodeShift(info->op3, false, buffer, blen);
written = _decodeShift(info->op3, false, disassemblyStyle, buffer, blen);
ADVANCE(written);
}
}
Expand All @@ -534,20 +545,20 @@ int ARMDisassemble(const struct ARMInstructionInfo* info, struct ARMCore* cpu, c
ADVANCE(2);
}
if (info->operandFormat & ARM_OPERAND_IMMEDIATE_4) {
written = snprintf(buffer, blen, "#%i", info->op4.immediate);
written = _decodeImmediate(info->op4.immediate, disassemblyStyle, buffer, blen);
ADVANCE(written);
} else if (info->operandFormat & ARM_OPERAND_MEMORY_4) {
written = _decodeMemory(info->memory, cpu, symbols, pc, buffer, blen);
written = _decodeMemory(info->memory, cpu, symbols, pc, disassemblyStyle, buffer, blen);
ADVANCE(written);
} else if (info->operandFormat & ARM_OPERAND_REGISTER_4) {
written = _decodeRegister(info->op4.reg, buffer, blen);
ADVANCE(written);
}
if (info->operandFormat & ARM_OPERAND_SHIFT_REGISTER_4) {
written = _decodeShift(info->op4, true, buffer, blen);
written = _decodeShift(info->op4, true, disassemblyStyle, buffer, blen);
ADVANCE(written);
} else if (info->operandFormat & ARM_OPERAND_SHIFT_IMMEDIATE_4) {
written = _decodeShift(info->op4, false, buffer, blen);
written = _decodeShift(info->op4, false, disassemblyStyle, buffer, blen);
ADVANCE(written);
}
break;
Expand Down
22 changes: 22 additions & 0 deletions src/debugger/cli-debugger.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ static void _writeWord(struct CLIDebugger*, struct CLIDebugVector*);
static void _dumpByte(struct CLIDebugger*, struct CLIDebugVector*);
static void _dumpHalfword(struct CLIDebugger*, struct CLIDebugVector*);
static void _dumpWord(struct CLIDebugger*, struct CLIDebugVector*);
static void _setDisassemblyStyle(struct CLIDebugger*, struct CLIDebugVector*);
static void _events(struct CLIDebugger*, struct CLIDebugVector*);
#ifdef ENABLE_SCRIPTING
static void _source(struct CLIDebugger*, struct CLIDebugVector*);
Expand Down Expand Up @@ -125,6 +126,7 @@ static struct CLIDebuggerCommandSummary _debuggerCommands[] = {
{ "x/1", _dumpByte, "Ii", "Examine bytes at a specified offset" },
{ "x/2", _dumpHalfword, "Ii", "Examine halfwords at a specified offset" },
{ "x/4", _dumpWord, "Ii", "Examine words at a specified offset" },
{ "disasm-style", _setDisassemblyStyle, "S", "Set the disassembly style" },
#ifdef ENABLE_SCRIPTING
{ "source", _source, "S", "Load a script" },
#endif
Expand Down Expand Up @@ -584,6 +586,26 @@ static void _dumpWord(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
}
}

static void _setDisassemblyStyle(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
if (!dv) {
debugger->backend->printf(debugger->backend, "decimal disassemble instruction immediates as decimal(default)\n");
debugger->backend->printf(debugger->backend, "hex disassemble instruction immediates as hex\n");
return;
}
if (dv->type != CLIDV_CHAR_TYPE) {
debugger->backend->printf(debugger->backend, "%s\n", ERROR_INVALID_ARGS);
return;
}
struct mDebuggerPlatform* platform = debugger->d.platform;
if (strcmp(dv->charValue, "decimal") == 0) {
platform->disassemblyStyle = DISASSEMBLY_STYLE_DECIMAL;
} else if (strcmp(dv->charValue, "hex") == 0) {
platform->disassemblyStyle = DISASSEMBLY_STYLE_HEX;
} else {
debugger->backend->printf(debugger->backend, "%s\n", ERROR_INVALID_ARGS);
}
}

#ifdef ENABLE_SCRIPTING
static void _source(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
if (!dv) {
Expand Down
2 changes: 1 addition & 1 deletion src/sm83/debugger/cli-debugger.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ static inline uint16_t _printLine(struct CLIDebugger* debugger, uint16_t address
};
disPtr[0] = '\t';
++disPtr;
SM83Disassemble(&info, address, disPtr, sizeof(disassembly) - (disPtr - disassembly));
SM83Disassemble(&info, address, debugger->d.platform->disassemblyStyle, disPtr, sizeof(disassembly) - (disPtr - disassembly));
be->printf(be, "%s\n", disassembly);
return address;
}
Expand Down
2 changes: 1 addition & 1 deletion src/sm83/debugger/debugger.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ static void SM83DebuggerTrace(struct mDebuggerPlatform* d, char* out, size_t* le
disPtr[0] = ':';
disPtr[1] = ' ';
disPtr += 2;
SM83Disassemble(&info, address, disPtr, sizeof(disassembly) - (disPtr - disassembly));
SM83Disassemble(&info, address, d->disassemblyStyle, disPtr, sizeof(disassembly) - (disPtr - disassembly));

*length = snprintf(out, *length, "A: %02X F: %02X B: %02X C: %02X D: %02X E: %02X H: %02X L: %02X SP: %04X PC: %02X:%04X | %s",
cpu->a, cpu->f.packed, cpu->b, cpu->c,
Expand Down
Loading