Showing the changes to src/exec/debugger.cpp (1 of 5 files). Show all
Unified · Split
| @@ -128,7 +128,7 @@ namespace · 127 unmodified lines | ||
| 128 | 128 | if (!func_maybe.empty()) |
| 129 | 129 | { |
| 130 | 130 | assert(func_maybe.size() == 1); |
| 131 | − msg << module_ref.module->module_name->str() << "!" << func_maybe[0]; | |
| 131 | + msg << module_ref.module->module_name->str() << "!" << func_maybe[0] << " "; | |
| 132 | 132 | } |
| 133 | 133 | else |
| 134 | 134 | { |
| @@ -136,10 +136,10 @@ namespace · 1 unmodified line | ||
| 136 | 136 | if (module_ref.module->module_name != nullptr) |
| 137 | 137 | module_name = module_ref.module->module_name->str(); |
| 138 | 138 | |
| 139 | − msg << module_name << "@" << pc; | |
| 139 | + msg << module_name; | |
| 140 | 140 | } |
| 141 | 141 | |
| 142 | − msg << "\n"; | |
| 142 | + msg << "@" << pc << "\n"; | |
| 143 | 143 | return true; |
| 144 | 144 | }); |
| 145 | 145 | |
| @@ -200,33 +200,28 @@ namespace · 54 unmodified lines | ||
| 200 | 200 | } |
| 201 | 201 | } |
| 202 | 202 | |
| 203 | − ss << "string\n" | |
| 204 | − << "\tlength: " << s->get_length() << "\n" | |
| 205 | − << "\tvalue: \"" << escaped_string.str() << "\"\n"; | |
| 203 | + ss << escaped_string.str() << " length: " << s->get_length() << " string"; | |
| 206 | 204 | |
| 207 | 205 | return ss; |
| 208 | 206 | } |
| 209 | 207 | |
| 210 | 208 | std::ostream& operator<<(std::ostream &ss, const vm_array_t *a) |
| 211 | 209 | { |
| 212 | − ss << "array\n" | |
| 213 | − << "\tlength: " << a->get_length() << "\n"; | |
| 210 | + ss << "length: " << a->get_length() << " array"; | |
| 214 | 211 | |
| 215 | 212 | return ss; |
| 216 | 213 | } |
| 217 | 214 | |
| 218 | 215 | std::ostream& operator<<(std::ostream &ss, const vm_list_t *l) |
| 219 | 216 | { |
| 220 | − ss << "list\n" | |
| 221 | − << "\tlength: " << l->get_length() << "\n"; | |
| 217 | + ss << "length: " << l->get_length() << " list"; | |
| 222 | 218 | |
| 223 | 219 | return ss; |
| 224 | 220 | } |
| 225 | 221 | |
| 226 | 222 | std::ostream& operator<<(std::ostream &ss, const vm_channel_t *c) |
| 227 | 223 | { |
| 228 | − ss << "channel\n" | |
| 229 | − << "\tbuffer size: " << c->get_buffer_size() << "\n"; | |
| 224 | + ss << "buffer size: " << c->get_buffer_size() << " channel"; | |
| 230 | 225 | |
| 231 | 226 | return ss; |
| 232 | 227 | } |
| @@ -255,11 +250,11 @@ namespace · 22 unmodified lines | ||
| 255 | 250 | } |
| 256 | 251 | else |
| 257 | 252 | { |
| 258 | − ss << "alloc - size: " << alloc->alloc_type->size_in_bytes << "\n"; | |
| 253 | + ss << "size: " << alloc->alloc_type->size_in_bytes << " alloc"; | |
| 259 | 254 | |
| 260 | 255 | enum_pointer_fields(*alloc->alloc_type, alloc->get_allocation(), [&ss](pointer_t p, std::size_t o) |
| 261 | 256 | { |
| 262 | − ss << " [" << o << "] " << vm_alloc_t::from_allocation(p); | |
| 257 | + ss << "\n [" << o << "] " << vm_alloc_t::from_allocation(p); | |
| 263 | 258 | }); |
| 264 | 259 | } |
| 265 | 260 | |
| @@ -384,7 +379,7 @@ namespace · 118 unmodified lines | ||
| 384 | 379 | |
| 385 | 380 | auto msg = std::stringstream{}; |
| 386 | 381 | auto module_funcs = cxt.dbg.get_module_functions(vm_id, name_to_match); |
| 387 | − msg << "Function name [PC range]"; | |
| 382 | + msg << "[PC range] Function"; | |
| 388 | 383 | for (auto &f : module_funcs) |
| 389 | 384 | msg << "\n " << f; |
| 390 | 385 | |
| @@ -501,14 +496,10 @@ namespace · 110 unmodified lines | ||
| 501 | 496 | if (!func_maybe.empty()) |
| 502 | 497 | { |
| 503 | 498 | assert(func_maybe.size() == 1); |
| 504 | − msg << "!" << func_maybe[0]; | |
| 505 | − } | |
| 506 | − else | |
| 507 | − { | |
| 508 | − msg << "@" << details.pc; | |
| 499 | + msg << "!" << func_maybe[0] << " "; | |
| 509 | 500 | } |
| 510 | 501 | |
| 511 | − msg << "\n"; | |
| 502 | + msg << "@" << details.pc << "\n"; | |
| 512 | 503 | } |
| 513 | 504 | |
| 514 | 505 | debug_print_info(msg.str()); |
| @@ -603,12 +594,20 @@ namespace · 88 unmodified lines | ||
| 603 | 594 | |
| 604 | 595 | void cmd_disassemble(const std::vector<std::string> &a, dbg_cmd_cxt_t &cxt) |
| 605 | 596 | { |
| 597 | + auto absolute_pc = false; | |
| 606 | 598 | auto disassemble_length = int{ 4 }; |
| 607 | 599 | if (a.size() > 1) |
| 608 | 600 | { |
| 601 | + auto disassemble_length_maybe = a[1]; | |
| 602 | + if (disassemble_length_maybe[0] == '@') | |
| 603 | + { | |
| 604 | + absolute_pc = true; | |
| 605 | + disassemble_length_maybe.erase(0, 1); | |
| 606 | + } | |
| 607 | + | |
| 609 | 608 | try |
| 610 | 609 | { |
| 611 | − disassemble_length = std::stoi(a[1]); | |
| 610 | + disassemble_length = std::stoi(disassemble_length_maybe); | |
| 612 | 611 | } |
| 613 | 612 | catch (...) |
| 614 | 613 | { |
| @@ -620,26 +619,36 @@ namespace · 5 unmodified lines | ||
| 620 | 619 | const auto &r = *cxt.current_register; |
| 621 | 620 | const auto &code_section = r.module_ref->code_section; |
| 622 | 621 | |
| 623 | − auto begin_pc = static_cast<std::size_t>(r.pc); | |
| 624 | − auto end_pc = static_cast<std::size_t>(r.pc); | |
| 625 | − if (disassemble_length < 0) | |
| 622 | + // The current PC is actually the next PC to execute. | |
| 623 | + auto begin_pc = r.pc == 0 ? r.pc : r.pc - 1; | |
| 624 | + auto end_pc = begin_pc; | |
| 625 | + if (absolute_pc) | |
| 626 | + { | |
| 627 | + begin_pc = disassemble_length; | |
| 628 | + end_pc = disassemble_length; | |
| 629 | + disassemble_length = 0; | |
| 630 | + | |
| 631 | + if (begin_pc < 0 || static_cast<int32_t>(code_section.size()) <= end_pc) | |
| 632 | + throw debug_cmd_error_t{ "Invalid absolute pc" }; | |
| 633 | + } | |
| 634 | + else if (disassemble_length < 0) | |
| 626 | 635 | { |
| 627 | − const auto begin_maybe = r.pc - (-disassemble_length) + 1; | |
| 628 | − begin_pc = static_cast<std::size_t>(std::max(begin_maybe, 0)); | |
| 636 | + const auto begin_maybe = begin_pc - (-disassemble_length); | |
| 637 | + begin_pc = std::max(begin_maybe, 0); | |
| 629 | 638 | } |
| 630 | 639 | else |
| 631 | 640 | { |
| 632 | − const auto end_maybe = static_cast<std::size_t>(r.pc + disassemble_length); | |
| 633 | − end_pc = std::min(end_maybe, code_section.size() - 1); | |
| 641 | + const auto end_maybe = begin_pc + disassemble_length; | |
| 642 | + end_pc = std::min(end_maybe, static_cast<int32_t>(code_section.size() - 1)); | |
| 634 | 643 | } |
| 635 | 644 | |
| 636 | 645 | auto resolved_pc = dbg.resolve_to_function_source_line(r.module_ref->module->vm_id, begin_pc, end_pc, symbol::function_name_format_t::name); |
| 637 | 646 | assert(resolved_pc.empty() || resolved_pc.size() == (end_pc - begin_pc + 1) && "Resolved PCs should have failed or match the PC count"); |
| 638 | 647 | |
| 639 | 648 | auto msg = std::stringstream{}; |
| 640 | − for (auto i = begin_pc; i <= end_pc; ++i) | |
| 649 | + for (auto curr_pc = begin_pc; curr_pc <= end_pc; ++curr_pc) | |
| 641 | 650 | { |
| 642 | − auto op = code_section[i].op; | |
| 651 | + auto op = code_section[curr_pc].op; | |
| 643 | 652 | |
| 644 | 653 | auto op_prefix = " "; |
| 645 | 654 | |
| @@ -650,7 +659,7 @@ namespace · 4 unmodified lines | ||
| 650 | 659 | for (auto bp_cookie : dbg.breakpoint_cookies) |
| 651 | 660 | { |
| 652 | 661 | const auto details = dbg.controller->get_breakpoint_details(bp_cookie); |
| 653 | − if (details.pc == i && details.module == r.module_ref->module) | |
| 662 | + if (details.pc == curr_pc && details.module == r.module_ref->module) | |
| 654 | 663 | { |
| 655 | 664 | op.opcode = details.original_opcode; |
| 656 | 665 | op_prefix = " b"; |
| @@ -662,12 +671,12 @@ namespace · 5 unmodified lines | ||
| 662 | 671 | // Print source location if resolved |
| 663 | 672 | if (!resolved_pc.empty()) |
| 664 | 673 | { |
| 665 | − const auto &rpc = resolved_pc[i - begin_pc]; | |
| 674 | + const auto &rpc = resolved_pc[curr_pc - begin_pc]; | |
| 666 | 675 | if (!rpc.empty()) |
| 667 | 676 | msg << rpc << "\n"; |
| 668 | 677 | } |
| 669 | 678 | |
| 670 | − msg << op_prefix << std::setw(5) << i << ": " << op << "\n"; | |
| 679 | + msg << op_prefix << std::setw(5) << curr_pc << ": " << op << "\n"; | |
| 671 | 680 | } |
| 672 | 681 | |
| 673 | 682 | debug_print_info(msg.str()); |
| @@ -723,9 +732,9 @@ namespace · 49 unmodified lines | ||
| 723 | 732 | |
| 724 | 733 | auto msg = std::stringstream{}; |
| 725 | 734 | if (byte_offset2 != -1) |
| 726 | − msg << " " << byte_offset2 << "(" << byte_offset1 << "(" << a[1] << ")):\n"; | |
| 735 | + msg << byte_offset2 << "(" << byte_offset1 << "(" << a[1] << ")):\n"; | |
| 727 | 736 | else |
| 728 | − msg << " " << byte_offset1 << "(" << a[1] << "):\n"; | |
| 737 | + msg << byte_offset1 << "(" << a[1] << "):\n"; | |
| 729 | 738 | |
| 730 | 739 | auto value_is_pointer = bool{ false }; |
| 731 | 740 | const auto pointer_offset1 = byte_offset1 / pointer_size; |
| @@ -872,7 +881,7 @@ namespace · 140 unmodified lines | ||
| 872 | 881 | |
| 873 | 882 | { "sw", "Stack walk for the current or supplied thread", "sw ([0-9]+|\\*)?", "sw, sw 34, sw *", cmd_stackwalk }, |
| 874 | 883 | { "~", "Switch to thread", "~ [0-9]+", "~ 42", cmd_switchthread }, |
| 875 | − { "d", "Disassemble the next/previous N instructions (default N = 4)", "d (-?[0-9]+)?", "d, d -4, d 5", cmd_disassemble }, | |
| 884 | + { "d", "Disassemble the next/previous N instructions (default N = 4)", "d (@?-?[0-9]+)?", "d, d -4, d 5, d @36", cmd_disassemble }, | |
| 876 | 885 | { "x", "Examine memory", "x [mp|fp] [0-9]+ ([0-9]+)?", "x mp 3, x fp 20 6", cmd_examine }, |
| 877 | 886 | |
| 878 | 887 | { "set" , "Set a debug option", "set [ _a-zA-Z0-9]*", "'set' for available options", set_value_cmd }, |
| @@ -882,9 +891,11 @@ namespace · 3 unmodified lines | ||
| 882 | 891 | { "tlk~*", nullptr, nullptr, nullptr, cmd_tlk_tilde_star } |
| 883 | 892 | }; |
| 884 | 893 | |
| 894 | + const auto cmds_length = sizeof(cmds) / sizeof(cmds[0]); | |
| 895 | + | |
| 885 | 896 | dbg_cmd_exec_t find_cmd(const std::string &cmd_maybe) |
| 886 | 897 | { |
| 887 | − for (auto i = std::size_t{}; i < sizeof(cmds) / sizeof(cmds[0]); ++i) | |
| 898 | + for (auto i = std::size_t{}; i < cmds_length; ++i) | |
| 888 | 899 | { |
| 889 | 900 | if (cmd_maybe.compare(cmds[i].cmd) == 0) |
| 890 | 901 | return cmds[i].exec; |
| @@ -898,7 +909,7 @@ namespace · 7 unmodified lines | ||
| 898 | 909 | { |
| 899 | 910 | auto msg = std::stringstream{}; |
| 900 | 911 | msg << "Commands:\n"; |
| 901 | − for (auto i = std::size_t{}; i < sizeof(cmds) / sizeof(cmds[0]); ++i) | |
| 912 | + for (auto i = std::size_t{}; i < cmds_length; ++i) | |
| 902 | 913 | { |
| 903 | 914 | auto &c = cmds[i]; |
| 904 | 915 | |
| @@ -906,13 +917,13 @@ namespace · 1 unmodified line | ||
| 906 | 917 | if (c.description == nullptr) |
| 907 | 918 | continue; |
| 908 | 919 | |
| 909 | − msg << " " << c.cmd << "\t" << c.description << "\n"; | |
| 920 | + msg << " " << c.cmd << " " << c.description << "\n"; | |
| 910 | 921 | |
| 911 | 922 | if (c.syntax != nullptr) |
| 912 | − msg << "\t Syntax: " << c.syntax << "\n"; | |
| 923 | + msg << " Syntax: " << c.syntax << "\n"; | |
| 913 | 924 | |
| 914 | 925 | if (c.example != nullptr) |
| 915 | − msg << "\t Example(s): " << c.example << "\n"; | |
| 926 | + msg << " Example(s): " << c.example << "\n"; | |
| 916 | 927 | } |
| 917 | 928 | |
| 918 | 929 | debug_print_info(msg.str()); |
| @@ -959,7 +970,7 @@ namespace · 40 unmodified lines | ||
| 959 | 970 | |
| 960 | 971 | std::getline(std::cin, cmd); |
| 961 | 972 | |
| 962 | − assert(!cxt.exit_break && "Pre-condition on exit_break state before execute failed"); | |
| 973 | + assert(!cxt.exit_break && "Precondition on exit_break state before execute failed"); | |
| 963 | 974 | execute_single_command(cxt, cmd); |
| 964 | 975 | if (cxt.exit_break) |
| 965 | 976 | break; |
| @@ -1038,12 +1049,12 @@ std::vector<std::string> debugger::get_module_functions(disvm::runtime::module_i · 72 unmodified lines | ||
| 1038 | 1049 | continue; |
| 1039 | 1050 | |
| 1040 | 1051 | std::stringstream ss; |
| 1041 | − ss << fi.name | |
| 1042 | − << " [" | |
| 1043 | − << fi.entry_pc | |
| 1044 | − << ", " | |
| 1045 | − << fi.limit_pc | |
| 1046 | − << "]"; | |
| 1052 | + ss << "[" | |
| 1053 | + << std::setw(5) << fi.entry_pc | |
| 1054 | + << "," | |
| 1055 | + << std::setw(5) << fi.limit_pc | |
| 1056 | + << "] " | |
| 1057 | + << fi.name; | |
| 1047 | 1058 | |
| 1048 | 1059 | funcs.push_back(ss.str()); |
| 1049 | 1060 | } |
| @@ -1084,7 +1095,7 @@ void debugger::on_load(vm_tool_controller_t &controller_, std::size_t tool_id) · 34 unmodified lines | ||
| 1084 | 1095 | << t->get_thread_id() |
| 1085 | 1096 | << " started in " |
| 1086 | 1097 | << t->get_registers().module_ref->module->module_name->str() |
| 1087 | − << " @ " | |
| 1098 | + << " @" | |
| 1088 | 1099 | << t->get_registers().pc; |
| 1089 | 1100 | |
| 1090 | 1101 | debug_print_info(ss.str()); |
| @@ -1151,7 +1162,7 @@ void debugger::on_load(vm_tool_controller_t &controller_, std::size_t tool_id) · 60 unmodified lines | ||
| 1151 | 1162 | // Reset the break on enter flag and set a breakpoint |
| 1152 | 1163 | // on the entry PC for the module - 'break on enter' |
| 1153 | 1164 | _options ^= debugger_options::break_on_enter; |
| 1154 | − controller->set_breakpoint(m, m->header.entry_pc); | |
| 1165 | + breakpoint_cookies.emplace(controller->set_breakpoint(m, m->header.entry_pc)); | |
| 1155 | 1166 | } |
| 1156 | 1167 | |
| 1157 | 1168 | if (util::has_flag(_options, debugger_options::break_on_module_load)) |