Mercurial > repos > blastem
comparison debug.c @ 2214:7591c67b8d1e
Support for loading symbols in debugger for use during name resolution and disassembly
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Mon, 29 Aug 2022 23:01:46 -0700 |
parents | 3809a0bd680e |
children | 4e27c36f947c |
comparison
equal
deleted
inserted
replaced
2213:53411df7fc71 | 2214:7591c67b8d1e |
---|---|
623 uint32_t right; | 623 uint32_t right; |
624 switch(e->type) | 624 switch(e->type) |
625 { | 625 { |
626 case EXPR_SCALAR: | 626 case EXPR_SCALAR: |
627 if (e->op.type == TOKEN_NAME) { | 627 if (e->op.type == TOKEN_NAME) { |
628 return root->resolve(root, e->op.v.str, out); | 628 if (root->resolve(root, e->op.v.str, out)) { |
629 return 1; | |
630 } | |
631 tern_val v; | |
632 if (tern_find(root->symbols, e->op.v.str, &v)) { | |
633 *out = v.intval; | |
634 return 1; | |
635 } | |
636 return 0; | |
629 } else { | 637 } else { |
630 *out = e->op.v.num; | 638 *out = e->op.v.num; |
631 return 1; | 639 return 1; |
632 } | 640 } |
633 case EXPR_UNARY: | 641 case EXPR_UNARY: |
1652 (*target)->condition = NULL; | 1660 (*target)->condition = NULL; |
1653 } | 1661 } |
1654 return 1; | 1662 return 1; |
1655 } | 1663 } |
1656 | 1664 |
1665 static void symbol_max_len(char *key, tern_val val, uint8_t valtype, void *data) | |
1666 { | |
1667 size_t *max_len = data; | |
1668 size_t len = strlen(key); | |
1669 if (len > *max_len) { | |
1670 *max_len = len; | |
1671 } | |
1672 } | |
1673 | |
1674 static void print_symbol(char *key, tern_val val, uint8_t valtype, void *data) | |
1675 { | |
1676 size_t *padding = data; | |
1677 size_t len = strlen(key); | |
1678 fputs(key, stdout); | |
1679 while (len < *padding) | |
1680 { | |
1681 putchar(' '); | |
1682 len++; | |
1683 } | |
1684 printf("%X\n", (uint32_t)val.intval); | |
1685 } | |
1686 | |
1687 static uint8_t cmd_symbols(debug_root *root, parsed_command *cmd) | |
1688 { | |
1689 char *filename = cmd->raw ? strip_ws(cmd->raw) : NULL; | |
1690 if (filename && *filename) { | |
1691 FILE *f = fopen(filename, "r"); | |
1692 if (!f) { | |
1693 fprintf(stderr, "Failed to open %s for reading\n", filename); | |
1694 return 1; | |
1695 } | |
1696 char linebuf[1024]; | |
1697 while (fgets(linebuf, sizeof(linebuf), f)) | |
1698 { | |
1699 char *line = strip_ws(linebuf); | |
1700 if (*line) { | |
1701 char *end; | |
1702 uint32_t address = strtol(line, &end, 16); | |
1703 if (end != line) { | |
1704 if (*end == '=') { | |
1705 char *name = strip_ws(end + 1); | |
1706 add_label(root->disasm, name, address); | |
1707 root->symbols = tern_insert_int(root->symbols, name, address); | |
1708 } | |
1709 } | |
1710 } | |
1711 } | |
1712 } else { | |
1713 size_t max_len = 0; | |
1714 tern_foreach(root->symbols, symbol_max_len, &max_len); | |
1715 max_len += 2; | |
1716 tern_foreach(root->symbols, print_symbol, &max_len); | |
1717 } | |
1718 return 1; | |
1719 } | |
1720 | |
1657 static uint8_t cmd_delete_m68k(debug_root *root, parsed_command *cmd) | 1721 static uint8_t cmd_delete_m68k(debug_root *root, parsed_command *cmd) |
1658 { | 1722 { |
1659 bp_def **this_bp = find_breakpoint_idx(&root->breakpoints, cmd->args[0].value); | 1723 bp_def **this_bp = find_breakpoint_idx(&root->breakpoints, cmd->args[0].value); |
1660 if (!*this_bp) { | 1724 if (!*this_bp) { |
1661 fprintf(stderr, "Breakpoint %d does not exist\n", cmd->args[0].value); | 1725 fprintf(stderr, "Breakpoint %d does not exist\n", cmd->args[0].value); |
2114 .impl = cmd_while, | 2178 .impl = cmd_while, |
2115 .min_args = 1, | 2179 .min_args = 1, |
2116 .max_args = 1, | 2180 .max_args = 1, |
2117 .has_block = 1, | 2181 .has_block = 1, |
2118 .accepts_else = 1 | 2182 .accepts_else = 1 |
2183 }, | |
2184 { | |
2185 .names = (const char *[]){ | |
2186 "symbols", NULL | |
2187 }, | |
2188 .usage = "symbols [FILENAME]", | |
2189 .desc = "Loads a list of symbols from the file indicated by FILENAME or lists currently loaded symbols if FILENAME is omitted", | |
2190 .impl = cmd_symbols, | |
2191 .min_args = 0, | |
2192 .max_args = 1, | |
2193 .raw_args = 1 | |
2119 } | 2194 } |
2120 }; | 2195 }; |
2121 #define NUM_COMMON (sizeof(common_commands)/sizeof(*common_commands)) | 2196 #define NUM_COMMON (sizeof(common_commands)/sizeof(*common_commands)) |
2122 | 2197 |
2123 command_def m68k_commands[] = { | 2198 command_def m68k_commands[] = { |
2601 root->commands = tern_insert_ptr(root->commands, defs[i].names[j], defs + i); | 2676 root->commands = tern_insert_ptr(root->commands, defs[i].names[j], defs + i); |
2602 } | 2677 } |
2603 } | 2678 } |
2604 } | 2679 } |
2605 | 2680 |
2681 static void symbol_map(char *key, tern_val val, uint8_t valtype, void *data) | |
2682 { | |
2683 debug_root *root = data; | |
2684 label_def *label = val.ptrval; | |
2685 for (uint32_t i = 0; i < label->num_labels; i++) | |
2686 { | |
2687 root->symbols = tern_insert_int(root->symbols, label->labels[i], label->full_address); | |
2688 } | |
2689 } | |
2690 | |
2606 debug_root *find_m68k_root(m68k_context *context) | 2691 debug_root *find_m68k_root(m68k_context *context) |
2607 { | 2692 { |
2608 debug_root *root = find_root(context); | 2693 debug_root *root = find_root(context); |
2609 if (root && !root->commands) { | 2694 if (root && !root->commands) { |
2610 add_commands(root, common_commands, NUM_COMMON); | 2695 add_commands(root, common_commands, NUM_COMMON); |
2611 add_commands(root, m68k_commands, NUM_68K); | 2696 add_commands(root, m68k_commands, NUM_68K); |
2612 root->read_mem = read_m68k; | 2697 root->read_mem = read_m68k; |
2613 root->write_mem = write_m68k; | 2698 root->write_mem = write_m68k; |
2614 root->set = set_m68k; | 2699 root->set = set_m68k; |
2700 root->disasm = create_68000_disasm(); | |
2615 switch (current_system->type) | 2701 switch (current_system->type) |
2616 { | 2702 { |
2617 case SYSTEM_GENESIS: | 2703 case SYSTEM_GENESIS: |
2618 case SYSTEM_SEGACD: | 2704 case SYSTEM_SEGACD: |
2619 //check if this is the main CPU | 2705 //check if this is the main CPU |
2620 if (context->system == current_system) { | 2706 if (context->system == current_system) { |
2621 root->resolve = resolve_genesis; | 2707 root->resolve = resolve_genesis; |
2622 add_commands(root, genesis_commands, NUM_GENESIS); | 2708 add_commands(root, genesis_commands, NUM_GENESIS); |
2623 if (current_system->type == SYSTEM_SEGACD) { | 2709 if (current_system->type == SYSTEM_SEGACD) { |
2710 add_segacd_maincpu_labels(root->disasm); | |
2624 add_commands(root, scd_main_commands, NUM_SCD_MAIN); | 2711 add_commands(root, scd_main_commands, NUM_SCD_MAIN); |
2625 } | 2712 } |
2626 break; | 2713 break; |
2627 } else { | 2714 } else { |
2715 add_segacd_subcpu_labels(root->disasm); | |
2628 add_commands(root, scd_sub_commands, NUM_SCD_SUB); | 2716 add_commands(root, scd_sub_commands, NUM_SCD_SUB); |
2629 } | 2717 } |
2630 default: | 2718 default: |
2631 root->resolve = resolve_m68k; | 2719 root->resolve = resolve_m68k; |
2632 } | 2720 } |
2721 tern_foreach(root->disasm->labels, symbol_map, root); | |
2633 } | 2722 } |
2634 return root; | 2723 return root; |
2635 } | 2724 } |
2636 | 2725 |
2637 #ifndef NO_Z80 | 2726 #ifndef NO_Z80 |
3291 { | 3380 { |
3292 eval_expr(root, cur->args[i].parsed, &cur->args[i].value); | 3381 eval_expr(root, cur->args[i].parsed, &cur->args[i].value); |
3293 do_print(root, format_str, cur->args[i].raw, cur->args[i].value); | 3382 do_print(root, format_str, cur->args[i].raw, cur->args[i].value); |
3294 } | 3383 } |
3295 } | 3384 } |
3296 m68k_disasm(&inst, input_buf); | 3385 m68k_disasm_labels(&inst, input_buf, root->disasm); |
3297 printf("%X: %s\n", address, input_buf); | 3386 printf("%X: %s\n", address, input_buf); |
3298 debugger_repl(root); | 3387 debugger_repl(root); |
3299 return; | 3388 return; |
3300 } | 3389 } |