all repos — mgba @ 87ec3f3d4a8a28f4d7dde5b1069ae86183fcb12a

mGBA Game Boy Advance Emulator

ARM Debugger: Disassembler now resolves addresses to symbol names
Vicki Pfau vi@endrift.com
Mon, 07 Sep 2020 15:54:49 -0700
commit

87ec3f3d4a8a28f4d7dde5b1069ae86183fcb12a

parent

17ca8f524a165cb15856b76925a17d68b2cdb09d

M CHANGESCHANGES

@@ -9,6 +9,7 @@ - Read-only support for MBC6 flash memory

- New unlicensed GB mappers: Pokémon Jade/Diamond, BBD, and Hitek - Stack tracing tools in ARM debugger (by ahigerd) - Command scripts for CLI debugger (by ahigerd) + - ARM disassembler now resolves addresses to symbol names Emulation fixes: - ARM: Fix ALU reading PC after shifting - ARM: Fix STR storing PC after address calculation
M include/mgba/internal/arm/decoder.hinclude/mgba/internal/arm/decoder.h

@@ -212,11 +212,12 @@ unsigned sDataCycles : 10;

unsigned nDataCycles : 10; }; +struct mDebuggerSymbols; void ARMDecodeARM(uint32_t opcode, struct ARMInstructionInfo* info); void ARMDecodeThumb(uint16_t opcode, struct ARMInstructionInfo* info); bool ARMDecodeThumbCombine(struct ARMInstructionInfo* info1, struct ARMInstructionInfo* info2, struct ARMInstructionInfo* out); -int ARMDisassemble(struct ARMInstructionInfo* info, uint32_t pc, char* buffer, int blen); +int ARMDisassemble(struct ARMInstructionInfo* info, struct ARMCore* core, const struct mDebuggerSymbols* symbols, uint32_t pc, char* buffer, int blen); uint32_t ARMResolveMemoryAccess(struct ARMInstructionInfo* info, struct ARMRegisterFile* regs, uint32_t pc); CXX_GUARD_END
M src/arm/debugger/cli-debugger.csrc/arm/debugger/cli-debugger.c

@@ -98,28 +98,29 @@ }

static inline uint32_t _printLine(struct CLIDebugger* debugger, uint32_t address, enum ExecutionMode mode) { struct CLIDebuggerBackend* be = debugger->backend; + struct mCore* core = debugger->d.core; char disassembly[64]; struct ARMInstructionInfo info; be->printf(be, "%08X: ", address); if (mode == MODE_ARM) { - uint32_t instruction = debugger->d.core->busRead32(debugger->d.core, address); + uint32_t instruction = core->busRead32(core, address); ARMDecodeARM(instruction, &info); - ARMDisassemble(&info, address + WORD_SIZE_ARM * 2, disassembly, sizeof(disassembly)); + ARMDisassemble(&info, core->cpu, core->symbolTable, address + WORD_SIZE_ARM * 2, disassembly, sizeof(disassembly)); be->printf(be, "%08X\t%s\n", instruction, disassembly); return WORD_SIZE_ARM; } else { struct ARMInstructionInfo info2; struct ARMInstructionInfo combined; - uint16_t instruction = debugger->d.core->busRead16(debugger->d.core, address); - uint16_t instruction2 = debugger->d.core->busRead16(debugger->d.core, address + WORD_SIZE_THUMB); + uint16_t instruction = core->busRead16(core, address); + uint16_t instruction2 = core->busRead16(core, address + WORD_SIZE_THUMB); ARMDecodeThumb(instruction, &info); ARMDecodeThumb(instruction2, &info2); if (ARMDecodeThumbCombine(&info, &info2, &combined)) { - ARMDisassemble(&combined, address + WORD_SIZE_THUMB * 2, disassembly, sizeof(disassembly)); + ARMDisassemble(&combined, core->cpu, core->symbolTable, address + WORD_SIZE_THUMB * 2, disassembly, sizeof(disassembly)); be->printf(be, "%04X %04X\t%s\n", instruction, instruction2, disassembly); return WORD_SIZE_THUMB * 2; } else { - ARMDisassemble(&info, address + WORD_SIZE_THUMB * 2, disassembly, sizeof(disassembly)); + ARMDisassemble(&info, core->cpu, core->symbolTable, address + WORD_SIZE_THUMB * 2, disassembly, sizeof(disassembly)); be->printf(be, "%04X \t%s\n", instruction, disassembly); return WORD_SIZE_THUMB; }
M src/arm/debugger/debugger.csrc/arm/debugger/debugger.c

@@ -467,6 +467,7 @@

static void ARMDebuggerTrace(struct mDebuggerPlatform* d, char* out, size_t* length) { struct ARMDebugger* debugger = (struct ARMDebugger*) d; struct ARMCore* cpu = debugger->cpu; + struct mCore* core = d->p->core; char disassembly[64];

@@ -475,17 +476,17 @@ bool isWideInstruction = ARMDecodeCombined(cpu, &info);

if (cpu->executionMode == MODE_ARM) { uint32_t instruction = cpu->prefetch[0]; sprintf(disassembly, "%08X: ", instruction); - ARMDisassemble(&info, cpu->gprs[ARM_PC], disassembly + strlen("00000000: "), sizeof(disassembly) - strlen("00000000: ")); + ARMDisassemble(&info, cpu, core->symbolTable, cpu->gprs[ARM_PC], 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->gprs[ARM_PC], disassembly + strlen("00000000: "), sizeof(disassembly) - strlen("00000000: ")); + ARMDisassemble(&info, cpu, core->symbolTable, cpu->gprs[ARM_PC], disassembly + strlen("00000000: "), sizeof(disassembly) - strlen("00000000: ")); } else { sprintf(disassembly, " %04X: ", instruction); - ARMDisassemble(&info, cpu->gprs[ARM_PC], disassembly + strlen("00000000: "), sizeof(disassembly) - strlen("00000000: ")); + ARMDisassemble(&info, cpu, core->symbolTable, cpu->gprs[ARM_PC], disassembly + strlen("00000000: "), sizeof(disassembly) - strlen("00000000: ")); } }
M src/arm/decoder.csrc/arm/decoder.c

@@ -6,6 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include <mgba/internal/arm/decoder.h> #include <mgba/internal/arm/decoder-inlines.h> +#include <mgba/internal/debugger/symbols.h> #include <mgba-util/string.h> #define ADVANCE(AMOUNT) \

@@ -20,8 +21,8 @@

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, uint32_t pc, char* buffer, int blen); -static int _decodeMemory(struct ARMMemoryAccess memory, int pc, 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 const char* _armConditions[] = {

@@ -141,23 +142,66 @@ }

return total; } -static int _decodePCRelative(uint32_t address, uint32_t pc, char* buffer, int blen) { - return snprintf(buffer, blen, "$%08X", address + pc); +static int _decodePCRelative(uint32_t address, const struct mDebuggerSymbols* symbols, uint32_t pc, bool thumbBranch, char* buffer, int blen) { + address += pc; + const char* label = NULL; + if (symbols) { + label = mDebuggerSymbolReverseLookup(symbols, address, -1); + if (!label && thumbBranch) { + label = mDebuggerSymbolReverseLookup(symbols, address | 1, -1); + } + } + if (label) { + return strlcpy(buffer, label, blen); + } else { + return snprintf(buffer, blen, "0x%08X", address); + } } -static int _decodeMemory(struct ARMMemoryAccess memory, int pc, char* buffer, int blen) { +static int _decodeMemory(struct ARMMemoryAccess memory, struct ARMCore* cpu, const struct mDebuggerSymbols* symbols, int pc, char* buffer, int blen) { if (blen <= 1) { return 0; } int total = 0; - strlcpy(buffer, "[", blen); - ADVANCE(1); + bool elideClose = false; int written; if (memory.format & ARM_MEMORY_REGISTER_BASE) { if (memory.baseReg == ARM_PC && memory.format & ARM_MEMORY_IMMEDIATE_OFFSET) { - written = _decodePCRelative(memory.format & ARM_MEMORY_OFFSET_SUBTRACT ? -memory.offset.immediate : memory.offset.immediate, pc & 0xFFFFFFFC, buffer, blen); - ADVANCE(written); + uint32_t addrBase = memory.format & ARM_MEMORY_OFFSET_SUBTRACT ? -memory.offset.immediate : memory.offset.immediate; + if (!cpu) { + strlcpy(buffer, "[", blen); + ADVANCE(1); + written = _decodePCRelative(addrBase, symbols, pc & 0xFFFFFFFC, false, buffer, blen); + ADVANCE(written); + } else { + uint32_t value; + addrBase += pc & 0xFFFFFFFC; // Thumb does not have PC-relative LDRH/LDRB + switch (memory.width & 7) { + case 1: + value = cpu->memory.load8(cpu, addrBase, NULL); + break; + case 2: + value = cpu->memory.load16(cpu, addrBase, NULL); + break; + case 4: + value = cpu->memory.load32(cpu, addrBase, NULL); + break; + } + const char* label = NULL; + if (symbols) { + label = mDebuggerSymbolReverseLookup(symbols, value, -1); + } + if (label) { + written = snprintf(buffer, blen, "=%s", label); + } else { + written = snprintf(buffer, blen, "=0x%08X", value); + } + ADVANCE(written); + elideClose = true; + } } else { + strlcpy(buffer, "[", blen); + ADVANCE(1); written = _decodeRegister(memory.baseReg, buffer, blen); ADVANCE(written); if (memory.format & (ARM_MEMORY_REGISTER_OFFSET | ARM_MEMORY_IMMEDIATE_OFFSET) && !(memory.format & ARM_MEMORY_POST_INCREMENT)) {

@@ -165,10 +209,14 @@ strlcpy(buffer, ", ", blen);

ADVANCE(2); } } + } else { + strlcpy(buffer, "[", blen); + ADVANCE(1); } if (memory.format & ARM_MEMORY_POST_INCREMENT) { strlcpy(buffer, "], ", blen); ADVANCE(3); + elideClose = true; } if (memory.format & ARM_MEMORY_IMMEDIATE_OFFSET && memory.baseReg != ARM_PC) { if (memory.format & ARM_MEMORY_OFFSET_SUBTRACT) {

@@ -191,7 +239,7 @@ written = _decodeShift(memory.offset, false, buffer, blen);

ADVANCE(written); } - if (!(memory.format & ARM_MEMORY_POST_INCREMENT)) { + if (!elideClose) { strlcpy(buffer, "]", blen); ADVANCE(1); }

@@ -322,7 +370,7 @@ "",

"" }; -int ARMDisassemble(struct ARMInstructionInfo* info, uint32_t pc, char* buffer, int blen) { +int ARMDisassemble(struct ARMInstructionInfo* info, struct ARMCore* cpu, const struct mDebuggerSymbols* symbols, uint32_t pc, char* buffer, int blen) { const char* mnemonic = _armMnemonicStrings[info->mnemonic]; int written; int total = 0;

@@ -394,7 +442,7 @@ break;

case ARM_MN_B: case ARM_MN_BL: if (info->operandFormat & ARM_OPERAND_IMMEDIATE_1) { - written = _decodePCRelative(info->op1.immediate, pc, buffer, blen); + written = _decodePCRelative(info->op1.immediate, symbols, pc, true, buffer, blen); ADVANCE(written); } break;

@@ -403,7 +451,7 @@ if (info->operandFormat & ARM_OPERAND_IMMEDIATE_1) {

written = snprintf(buffer, blen, "#%i", info->op1.immediate); ADVANCE(written); } else if (info->operandFormat & ARM_OPERAND_MEMORY_1) { - written = _decodeMemory(info->memory, pc, buffer, blen); + written = _decodeMemory(info->memory, cpu, symbols, pc, buffer, blen); ADVANCE(written); } else if (info->operandFormat & ARM_OPERAND_REGISTER_1) { written = _decodeRegister(info->op1.reg, buffer, blen);

@@ -428,7 +476,7 @@ if (info->operandFormat & ARM_OPERAND_IMMEDIATE_2) {

written = snprintf(buffer, blen, "#%i", info->op2.immediate); ADVANCE(written); } else if (info->operandFormat & ARM_OPERAND_MEMORY_2) { - written = _decodeMemory(info->memory, pc, buffer, blen); + written = _decodeMemory(info->memory, cpu, symbols, pc, buffer, blen); ADVANCE(written); } else if (info->operandFormat & ARM_OPERAND_REGISTER_2) { written = _decodeRegister(info->op2.reg, buffer, blen);

@@ -449,7 +497,7 @@ if (info->operandFormat & ARM_OPERAND_IMMEDIATE_3) {

written = snprintf(buffer, blen, "#%i", info->op3.immediate); ADVANCE(written); } else if (info->operandFormat & ARM_OPERAND_MEMORY_3) { - written = _decodeMemory(info->memory, pc, buffer, blen); + written = _decodeMemory(info->memory, cpu, symbols, pc, buffer, blen); ADVANCE(written); } else if (info->operandFormat & ARM_OPERAND_REGISTER_3) { written = _decodeRegister(info->op3.reg, buffer, blen);

@@ -470,7 +518,7 @@ if (info->operandFormat & ARM_OPERAND_IMMEDIATE_4) {

written = snprintf(buffer, blen, "#%i", info->op4.immediate); ADVANCE(written); } else if (info->operandFormat & ARM_OPERAND_MEMORY_4) { - written = _decodeMemory(info->memory, pc, buffer, blen); + written = _decodeMemory(info->memory, cpu, symbols, pc, buffer, blen); ADVANCE(written); } else if (info->operandFormat & ARM_OPERAND_REGISTER_4) { written = _decodeRegister(info->op4.reg, buffer, blen);