From bfe64192a3ca375f581d96857581a4a048572b7a Mon Sep 17 00:00:00 2001 From: Lawrence Kesteloot Date: Thu, 2 Aug 2018 16:07:42 -0700 Subject: [PATCH] Parse ld65 map file for symbolic debugging. --- apple2e.cpp | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 97 insertions(+), 2 deletions(-) diff --git a/apple2e.cpp b/apple2e.cpp index 3145d56..b969f81 100644 --- a/apple2e.cpp +++ b/apple2e.cpp @@ -45,6 +45,9 @@ APPLE2Einterface::ModeHistory mode_history; const float paddle_max_pulse_seconds = .00282; +// Map from memory address to name of function (from the ld65 map file). +static map address_to_function_name; + typedef unsigned long long clk_t; struct system_clock { @@ -86,6 +89,73 @@ bool read_blob(char *name, unsigned char *b, size_t sz) return true; } +/** + * Parse a map entry from an ld65 map file and add it to the address_to_function_name map. + */ +static void add_map_entry(char *line) +{ + // Find end of function name and terminate it. + char *s = line; + while (*s != ' ') { + s++; + } + *s = '\0'; + string function_name = string(line); + + // Parse hex address. + int address = strtol(line + 26, NULL, 16); + + // See if we have a duplicate. We define our own symbols (like _pushax) as aliases + // to cc65-defined ones (like pushax) so we can access them from C. + string old_function_name = address_to_function_name[address]; + if (old_function_name.size() != 0 && old_function_name.size() < function_name.size()) { + // Skip this one, we already have one that's shorter (probably without + // leading underscore). + } else { + // Add to map. + address_to_function_name[address] = line; + } +} + +/** + * Read a map file generated by ld65. Puts symbols into the address_to_function_name map. + */ +static bool read_map(char *name) +{ + char line[100]; + FILE *fp = fopen(name, "r"); + int state = 0; + + while (state != 3 && fgets(line, sizeof(line), fp) != NULL) { + switch (state) { + case 0: + if (strncmp(line, "Exports list by name:", 21) == 0) { + // Found header. + state = 1; + } + break; + + case 1: + // Skip line with dashes. + state = 2; + break; + + case 2: + // Parse table. + if (strlen(line) <= 76) { + // End of table. + state = 3; + } + add_map_entry(line); + add_map_entry(line + 40); + break; + } + } + + fclose(fp); + return true; +} + struct SoftSwitch { string name; @@ -1051,6 +1121,7 @@ struct MAINboard : board_base disassemble_buffer = new unsigned char[data]; disassemble_size = data; disassemble_index = 0; + printf("Size of buffer: %d bytes\n", disassemble_size); } return true; } else if (addr == 0xBFFF) { @@ -1063,7 +1134,17 @@ struct MAINboard : board_base string dis; for (int i = 0; i < disassemble_size; i += bytes) { tie(bytes, dis) = disassemble_6502(i, disassemble_buffer + i); - printf("%s\n", dis.c_str()); + printf("%-32s", dis.c_str()); + if (bytes == 3) { + // Print function name if we have it. + int address = disassemble_buffer[i + 1] + + (disassemble_buffer[i + 2] << 8); + auto search = address_to_function_name.find(address); + if (search != address_to_function_name.end()) { + printf(" ; %s", search->second.c_str()); + } + } + printf("\n"); } printf("---\n"); delete[] disassemble_buffer; @@ -2695,7 +2776,7 @@ struct CPU6502 void usage(char *progname) { printf("\n"); - printf("usage: %s [-debugger] [-fast] ROM.bin\n", progname); + printf("usage: %s [-debugger] [-fast] [-map ld65.map] ROM.bin\n", progname); printf("\n"); printf("\n"); } @@ -2933,6 +3014,7 @@ int main(int argc, char **argv) argc -= 1; argv += 1; char *diskII_rom_name = NULL, *floppy1_name = NULL, *floppy2_name = NULL; + char *map_name = NULL; while((argc > 0) && (argv[0][0] == '-')) { if(strcmp(argv[0], "-debugger") == 0) { @@ -2965,6 +3047,14 @@ int main(int argc, char **argv) } argv += 2; argc -= 2; + } else if(strcmp(argv[0], "-map") == 0) { + if(argc < 2) { + fprintf(stderr, "-map option requires an ld65 map filename.\n"); + exit(EXIT_FAILURE); + } + map_name = argv[1]; + argv += 2; + argc -= 2; } else if( (strcmp(argv[0], "-help") == 0) || (strcmp(argv[0], "-h") == 0) || @@ -2996,6 +3086,11 @@ int main(int argc, char **argv) exit(EXIT_FAILURE); } + if(map_name != NULL) { + if(!read_map(map_name)) + exit(EXIT_FAILURE); + } + system_clock clk; MAINboard* mainboard;