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 | if (!func_maybe.empty()) | 128 | if (!func_maybe.empty()) |
| 129 | { | 129 | { |
| 130 | assert(func_maybe.size() == 1); | 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 | else | 133 | else |
| 134 | { | 134 | { |
| @@ -136,10 +136,10 @@ namespace · 1 unmodified line | |||
| 136 | if (module_ref.module->module_name != nullptr) | 136 | if (module_ref.module->module_name != nullptr) |
| 137 | module_name = module_ref.module->module_name->str(); | 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 | return true; | 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" | 203 | ss << escaped_string.str() << " length: " << s->get_length() << " string"; |
| 204 | << "\tlength: " << s->get_length() << "\n" | ||
| 205 | << "\tvalue: \"" << escaped_string.str() << "\"\n"; | ||
| 206 | 204 | ||
| 207 | return ss; | 205 | return ss; |
| 208 | } | 206 | } |
| 209 | 207 | ||
| 210 | std::ostream& operator<<(std::ostream &ss, const vm_array_t *a) | 208 | std::ostream& operator<<(std::ostream &ss, const vm_array_t *a) |
| 211 | { | 209 | { |
| 212 | ss << "array\n" | 210 | ss << "length: " << a->get_length() << " array"; |
| 213 | << "\tlength: " << a->get_length() << "\n"; | ||
| 214 | 211 | ||
| 215 | return ss; | 212 | return ss; |
| 216 | } | 213 | } |
| 217 | 214 | ||
| 218 | std::ostream& operator<<(std::ostream &ss, const vm_list_t *l) | 215 | std::ostream& operator<<(std::ostream &ss, const vm_list_t *l) |
| 219 | { | 216 | { |
| 220 | ss << "list\n" | 217 | ss << "length: " << l->get_length() << " list"; |
| 221 | << "\tlength: " << l->get_length() << "\n"; | ||
| 222 | 218 | ||
| 223 | return ss; | 219 | return ss; |
| 224 | } | 220 | } |
| 225 | 221 | ||
| 226 | std::ostream& operator<<(std::ostream &ss, const vm_channel_t *c) | 222 | std::ostream& operator<<(std::ostream &ss, const vm_channel_t *c) |
| 227 | { | 223 | { |
| 228 | ss << "channel\n" | 224 | ss << "buffer size: " << c->get_buffer_size() << " channel"; |
| 229 | << "\tbuffer size: " << c->get_buffer_size() << "\n"; | ||
| 230 | 225 | ||
| 231 | return ss; | 226 | return ss; |
| 232 | } | 227 | } |
| @@ -255,11 +250,11 @@ namespace · 22 unmodified lines | |||
| 255 | } | 250 | } |
| 256 | else | 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 | enum_pointer_fields(*alloc->alloc_type, alloc->get_allocation(), [&ss](pointer_t p, std::size_t o) | 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 | auto msg = std::stringstream{}; | 380 | auto msg = std::stringstream{}; |
| 386 | auto module_funcs = cxt.dbg.get_module_functions(vm_id, name_to_match); | 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 | for (auto &f : module_funcs) | 383 | for (auto &f : module_funcs) |
| 389 | msg << "\n " << f; | 384 | msg << "\n " << f; |
| 390 | 385 | ||
| @@ -501,14 +496,10 @@ namespace · 110 unmodified lines | |||
| 501 | if (!func_maybe.empty()) | 496 | if (!func_maybe.empty()) |
| 502 | { | 497 | { |
| 503 | assert(func_maybe.size() == 1); | 498 | assert(func_maybe.size() == 1); |
| 504 | msg << "!" << func_maybe[0]; | 499 | msg << "!" << func_maybe[0] << " "; |
| 505 | } | ||
| 506 | else | ||
| 507 | { | ||
| 508 | msg << "@" << details.pc; | ||
| 509 | } | 500 | } |
| 510 | 501 | ||
| 511 | msg << "\n"; | 502 | msg << "@" << details.pc << "\n"; |
| 512 | } | 503 | } |
| 513 | 504 | ||
| 514 | debug_print_info(msg.str()); | 505 | debug_print_info(msg.str()); |
| @@ -603,12 +594,20 @@ namespace · 88 unmodified lines | |||
| 603 | 594 | ||
| 604 | void cmd_disassemble(const std::vector<std::string> &a, dbg_cmd_cxt_t &cxt) | 595 | void cmd_disassemble(const std::vector<std::string> &a, dbg_cmd_cxt_t &cxt) |
| 605 | { | 596 | { |
| 597 | auto absolute_pc = false; | ||
| 606 | auto disassemble_length = int{ 4 }; | 598 | auto disassemble_length = int{ 4 }; |
| 607 | if (a.size() > 1) | 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 | try | 608 | try |
| 610 | { | 609 | { |
| 611 | disassemble_length = std::stoi(a[1]); | 610 | disassemble_length = std::stoi(disassemble_length_maybe); |
| 612 | } | 611 | } |
| 613 | catch (...) | 612 | catch (...) |
| 614 | { | 613 | { |
| @@ -620,26 +619,36 @@ namespace · 5 unmodified lines | |||
| 620 | const auto &r = *cxt.current_register; | 619 | const auto &r = *cxt.current_register; |
| 621 | const auto &code_section = r.module_ref->code_section; | 620 | const auto &code_section = r.module_ref->code_section; |
| 622 | 621 | ||
| 623 | auto begin_pc = static_cast<std::size_t>(r.pc); | 622 | // The current PC is actually the next PC to execute. |
| 624 | auto end_pc = static_cast<std::size_t>(r.pc); | 623 | auto begin_pc = r.pc == 0 ? r.pc : r.pc - 1; |
| 625 | if (disassemble_length < 0) | 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; | 636 | const auto begin_maybe = begin_pc - (-disassemble_length); |
| 628 | begin_pc = static_cast<std::size_t>(std::max(begin_maybe, 0)); | 637 | begin_pc = std::max(begin_maybe, 0); |
| 629 | } | 638 | } |
| 630 | else | 639 | else |
| 631 | { | 640 | { |
| 632 | const auto end_maybe = static_cast<std::size_t>(r.pc + disassemble_length); | 641 | const auto end_maybe = begin_pc + disassemble_length; |
| 633 | end_pc = std::min(end_maybe, code_section.size() - 1); | 642 | end_pc = std::min(end_maybe, static_cast<int32_t>(code_section.size() - 1)); |
| 634 | } | 643 | } |
| 635 | 644 | ||
| 636 | 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); | 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 | assert(resolved_pc.empty() || resolved_pc.size() == (end_pc - begin_pc + 1) && "Resolved PCs should have failed or match the PC count"); | 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 | auto msg = std::stringstream{}; | 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 | auto op_prefix = " "; | 653 | auto op_prefix = " "; |
| 645 | 654 | ||
| @@ -650,7 +659,7 @@ namespace · 4 unmodified lines | |||
| 650 | for (auto bp_cookie : dbg.breakpoint_cookies) | 659 | for (auto bp_cookie : dbg.breakpoint_cookies) |
| 651 | { | 660 | { |
| 652 | const auto details = dbg.controller->get_breakpoint_details(bp_cookie); | 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 | op.opcode = details.original_opcode; | 664 | op.opcode = details.original_opcode; |
| 656 | op_prefix = " b"; | 665 | op_prefix = " b"; |
| @@ -662,12 +671,12 @@ namespace · 5 unmodified lines | |||
| 662 | // Print source location if resolved | 671 | // Print source location if resolved |
| 663 | if (!resolved_pc.empty()) | 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 | if (!rpc.empty()) | 675 | if (!rpc.empty()) |
| 667 | msg << rpc << "\n"; | 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 | debug_print_info(msg.str()); | 682 | debug_print_info(msg.str()); |
| @@ -723,9 +732,9 @@ namespace · 49 unmodified lines | |||
| 723 | 732 | ||
| 724 | auto msg = std::stringstream{}; | 733 | auto msg = std::stringstream{}; |
| 725 | if (byte_offset2 != -1) | 734 | if (byte_offset2 != -1) |
| 726 | msg << " " << byte_offset2 << "(" << byte_offset1 << "(" << a[1] << ")):\n"; | 735 | msg << byte_offset2 << "(" << byte_offset1 << "(" << a[1] << ")):\n"; |
| 727 | else | 736 | else |
| 728 | msg << " " << byte_offset1 << "(" << a[1] << "):\n"; | 737 | msg << byte_offset1 << "(" << a[1] << "):\n"; |
| 729 | 738 | ||
| 730 | auto value_is_pointer = bool{ false }; | 739 | auto value_is_pointer = bool{ false }; |
| 731 | const auto pointer_offset1 = byte_offset1 / pointer_size; | 740 | const auto pointer_offset1 = byte_offset1 / pointer_size; |
| @@ -872,7 +881,7 @@ namespace · 140 unmodified lines | |||
| 872 | 881 | ||
| 873 | { "sw", "Stack walk for the current or supplied thread", "sw ([0-9]+|\\*)?", "sw, sw 34, sw *", cmd_stackwalk }, | 882 | { "sw", "Stack walk for the current or supplied thread", "sw ([0-9]+|\\*)?", "sw, sw 34, sw *", cmd_stackwalk }, |
| 874 | { "~", "Switch to thread", "~ [0-9]+", "~ 42", cmd_switchthread }, | 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 | { "x", "Examine memory", "x [mp|fp] [0-9]+ ([0-9]+)?", "x mp 3, x fp 20 6", cmd_examine }, | 885 | { "x", "Examine memory", "x [mp|fp] [0-9]+ ([0-9]+)?", "x mp 3, x fp 20 6", cmd_examine }, |
| 877 | 886 | ||
| 878 | { "set" , "Set a debug option", "set [ _a-zA-Z0-9]*", "'set' for available options", set_value_cmd }, | 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 | { "tlk~*", nullptr, nullptr, nullptr, cmd_tlk_tilde_star } | 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 | dbg_cmd_exec_t find_cmd(const std::string &cmd_maybe) | 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 | if (cmd_maybe.compare(cmds[i].cmd) == 0) | 900 | if (cmd_maybe.compare(cmds[i].cmd) == 0) |
| 890 | return cmds[i].exec; | 901 | return cmds[i].exec; |
| @@ -898,7 +909,7 @@ namespace · 7 unmodified lines | |||
| 898 | { | 909 | { |
| 899 | auto msg = std::stringstream{}; | 910 | auto msg = std::stringstream{}; |
| 900 | msg << "Commands:\n"; | 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 | auto &c = cmds[i]; | 914 | auto &c = cmds[i]; |
| 904 | 915 | ||
| @@ -906,13 +917,13 @@ namespace · 1 unmodified line | |||
| 906 | if (c.description == nullptr) | 917 | if (c.description == nullptr) |
| 907 | continue; | 918 | continue; |
| 908 | 919 | ||
| 909 | msg << " " << c.cmd << "\t" << c.description << "\n"; | 920 | msg << " " << c.cmd << " " << c.description << "\n"; |
| 910 | 921 | ||
| 911 | if (c.syntax != nullptr) | 922 | if (c.syntax != nullptr) |
| 912 | msg << "\t Syntax: " << c.syntax << "\n"; | 923 | msg << " Syntax: " << c.syntax << "\n"; |
| 913 | 924 | ||
| 914 | if (c.example != nullptr) | 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 | debug_print_info(msg.str()); | 929 | debug_print_info(msg.str()); |
| @@ -959,7 +970,7 @@ namespace · 40 unmodified lines | |||
| 959 | 970 | ||
| 960 | std::getline(std::cin, cmd); | 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 | execute_single_command(cxt, cmd); | 974 | execute_single_command(cxt, cmd); |
| 964 | if (cxt.exit_break) | 975 | if (cxt.exit_break) |
| 965 | break; | 976 | break; |
| @@ -1038,12 +1049,12 @@ std::vector<std::string> debugger::get_module_functions(disvm::runtime::module_i · 72 unmodified lines | |||
| 1038 | continue; | 1049 | continue; |
| 1039 | 1050 | ||
| 1040 | std::stringstream ss; | 1051 | std::stringstream ss; |
| 1041 | ss << fi.name | 1052 | ss << "[" |
| 1042 | << " [" | 1053 | << std::setw(5) << fi.entry_pc |
| 1043 | << fi.entry_pc | 1054 | << "," |
| 1044 | << ", " | 1055 | << std::setw(5) << fi.limit_pc |
| 1045 | << fi.limit_pc | 1056 | << "] " |
| 1046 | << "]"; | 1057 | << fi.name; |
| 1047 | 1058 | ||
| 1048 | funcs.push_back(ss.str()); | 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 | << t->get_thread_id() | 1095 | << t->get_thread_id() |
| 1085 | << " started in " | 1096 | << " started in " |
| 1086 | << t->get_registers().module_ref->module->module_name->str() | 1097 | << t->get_registers().module_ref->module->module_name->str() |
| 1087 | << " @ " | 1098 | << " @" |
| 1088 | << t->get_registers().pc; | 1099 | << t->get_registers().pc; |
| 1089 | 1100 | ||
| 1090 | debug_print_info(ss.str()); | 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 | // Reset the break on enter flag and set a breakpoint | 1162 | // Reset the break on enter flag and set a breakpoint |
| 1152 | // on the entry PC for the module - 'break on enter' | 1163 | // on the entry PC for the module - 'break on enter' |
| 1153 | _options ^= debugger_options::break_on_enter; | 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 | if (util::has_flag(_options, debugger_options::break_on_module_load)) | 1168 | if (util::has_flag(_options, debugger_options::break_on_module_load)) |