Showing the changes to src/exec/debugger.cpp (1 of 31 files). Show all
Unified · Split
| @@ -18,8 +18,36 @@ · 17 unmodified lines | |||
| 18 | #include <exceptions.h> | 18 | #include <exceptions.h> |
| 19 | #include "exec.h" | 19 | #include "exec.h" |
| 20 | 20 | ||
| 21 | using namespace disvm; | 21 | using disvm::vm_t; |
| 22 | using namespace disvm::runtime; | 22 | using disvm::loaded_vm_module_t; |
| 23 | using disvm::opcode_t; | ||
| 24 | |||
| 25 | using disvm::runtime::type_descriptor_t; | ||
| 26 | using disvm::runtime::intrinsic_type_desc; | ||
| 27 | using disvm::runtime::word_t; | ||
| 28 | using disvm::runtime::pointer_t; | ||
| 29 | using disvm::runtime::module_id_t; | ||
| 30 | using disvm::runtime::runtime_flags_t; | ||
| 31 | using disvm::runtime::cookie_t; | ||
| 32 | using disvm::runtime::vm_pc_t; | ||
| 33 | using disvm::runtime::vm_registers_t; | ||
| 34 | using disvm::runtime::vm_module_t; | ||
| 35 | using disvm::runtime::vm_module_ref_t; | ||
| 36 | using disvm::runtime::vm_alloc_t; | ||
| 37 | using disvm::runtime::vm_string_t; | ||
| 38 | using disvm::runtime::vm_array_t; | ||
| 39 | using disvm::runtime::vm_list_t; | ||
| 40 | using disvm::runtime::vm_channel_t; | ||
| 41 | using disvm::runtime::vm_thread_state_t; | ||
| 42 | using disvm::runtime::vm_trap_flags_t; | ||
| 43 | using disvm::runtime::vm_term_request; | ||
| 44 | using disvm::runtime::vm_tool_controller_t; | ||
| 45 | using disvm::runtime::vm_event_t; | ||
| 46 | using disvm::runtime::vm_event_context_t; | ||
| 47 | |||
| 48 | using disvm::symbol::function_name_format_t; | ||
| 49 | using disvm::symbol::advance_pc_t; | ||
| 50 | using disvm::symbol::symbol_data_t; | ||
| 23 | 51 | ||
| 24 | namespace | 52 | namespace |
| 25 | { | 53 | { |
| @@ -146,7 +174,7 @@ namespace · 120 unmodified lines | |||
| 146 | auto msg = std::stringstream{}; | 174 | auto msg = std::stringstream{}; |
| 147 | walk_stack(r, [&msg, &dbg](const pointer_t, const vm_pc_t pc, const vm_module_ref_t &module_ref) | 175 | walk_stack(r, [&msg, &dbg](const pointer_t, const vm_pc_t pc, const vm_module_ref_t &module_ref) |
| 148 | { | 176 | { |
| 149 | auto func_maybe = dbg.resolve_to_function_source_line(module_ref.module->vm_id, pc, pc, symbol::function_name_format_t::name); | 177 | auto func_maybe = dbg.resolve_to_function_source_line(module_ref.module->vm_id, pc, pc, function_name_format_t::name); |
| 150 | if (!func_maybe.empty()) | 178 | if (!func_maybe.empty()) |
| 151 | { | 179 | { |
| 152 | assert(func_maybe.size() == 1); | 180 | assert(func_maybe.size() == 1); |
| @@ -507,7 +535,7 @@ namespace · 354 unmodified lines | |||
| 507 | { | 535 | { |
| 508 | throw debug_cmd_error_t{ "Invalid module ID" }; | 536 | throw debug_cmd_error_t{ "Invalid module ID" }; |
| 509 | } | 537 | } |
| 510 | else if (util::has_flag(module->header.runtime_flag, runtime_flags_t::builtin)) | 538 | else if (disvm::util::has_flag(module->header.runtime_flag, runtime_flags_t::builtin)) |
| 511 | { | 539 | { |
| 512 | throw debug_cmd_error_t{ "Unable to set breakpoint in built-in module" }; | 540 | throw debug_cmd_error_t{ "Unable to set breakpoint in built-in module" }; |
| 513 | } | 541 | } |
| @@ -569,7 +597,7 @@ namespace · 55 unmodified lines | |||
| 569 | << std::setw(16) << details.module->module_name->str() | 597 | << std::setw(16) << details.module->module_name->str() |
| 570 | << std::setw(0); | 598 | << std::setw(0); |
| 571 | 599 | ||
| 572 | auto func_maybe = cxt.dbg.resolve_to_function_source_line(details.module->vm_id, details.pc, details.pc, symbol::function_name_format_t::name); | 600 | auto func_maybe = cxt.dbg.resolve_to_function_source_line(details.module->vm_id, details.pc, details.pc, function_name_format_t::name); |
| 573 | if (!func_maybe.empty()) | 601 | if (!func_maybe.empty()) |
| 574 | { | 602 | { |
| 575 | assert(func_maybe.size() == 1); | 603 | assert(func_maybe.size() == 1); |
| @@ -720,7 +748,7 @@ namespace · 144 unmodified lines | |||
| 720 | end_pc = std::min(end_maybe, static_cast<int32_t>(code_section.size() - 1)); | 748 | end_pc = std::min(end_maybe, static_cast<int32_t>(code_section.size() - 1)); |
| 721 | } | 749 | } |
| 722 | 750 | ||
| 723 | 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); | 751 | auto resolved_pc = dbg.resolve_to_function_source_line(r.module_ref->module->vm_id, begin_pc, end_pc, function_name_format_t::name); |
| 724 | assert(resolved_pc.empty() || resolved_pc.size() == (end_pc - begin_pc + 1) && "Resolved PCs should have failed or match the PC count"); | 752 | assert(resolved_pc.empty() || resolved_pc.size() == (end_pc - begin_pc + 1) && "Resolved PCs should have failed or match the PC count"); |
| 725 | 753 | ||
| 726 | auto msg = std::stringstream{}; | 754 | auto msg = std::stringstream{}; |
| @@ -817,7 +845,7 @@ namespace · 90 unmodified lines | |||
| 817 | auto value_is_pointer = bool{ false }; | 845 | auto value_is_pointer = bool{ false }; |
| 818 | const auto pointer_offset1 = byte_offset1 / pointer_size; | 846 | const auto pointer_offset1 = byte_offset1 / pointer_size; |
| 819 | auto value_to_examine = reinterpret_cast<pointer_t>(base_pointer[pointer_offset1]); | 847 | auto value_to_examine = reinterpret_cast<pointer_t>(base_pointer[pointer_offset1]); |
| 820 | if (runtime::is_offset_pointer(*base_type, pointer_offset1)) | 848 | if (disvm::runtime::is_offset_pointer(*base_type, pointer_offset1)) |
| 821 | { | 849 | { |
| 822 | value_is_pointer = true; | 850 | value_is_pointer = true; |
| 823 | auto alloc_to_examine = vm_alloc_t::from_allocation(value_to_examine); | 851 | auto alloc_to_examine = vm_alloc_t::from_allocation(value_to_examine); |
| @@ -835,7 +863,7 @@ namespace · 11 unmodified lines | |||
| 835 | 863 | ||
| 836 | const auto pointer_offset2 = byte_offset2 / pointer_size; | 864 | const auto pointer_offset2 = byte_offset2 / pointer_size; |
| 837 | value_to_examine = reinterpret_cast<pointer_t>(base_pointer[pointer_offset2]); | 865 | value_to_examine = reinterpret_cast<pointer_t>(base_pointer[pointer_offset2]); |
| 838 | value_is_pointer = runtime::is_offset_pointer(*base_type, pointer_offset2); | 866 | value_is_pointer = disvm::runtime::is_offset_pointer(*base_type, pointer_offset2); |
| 839 | } | 867 | } |
| 840 | } | 868 | } |
| 841 | 869 | ||
| @@ -1022,7 +1050,7 @@ namespace · 180 unmodified lines | |||
| 1022 | 1050 | ||
| 1023 | void execute_single_command(dbg_cmd_cxt_t &cxt, std::string cmd) | 1051 | void execute_single_command(dbg_cmd_cxt_t &cxt, std::string cmd) |
| 1024 | { | 1052 | { |
| 1025 | const auto cmd_tokens = util::split(cmd); | 1053 | const auto cmd_tokens = disvm::util::split(cmd); |
| 1026 | if (cmd_tokens.empty()) | 1054 | if (cmd_tokens.empty()) |
| 1027 | return; | 1055 | return; |
| 1028 | 1056 | ||
| @@ -1081,9 +1109,9 @@ namespace · 52 unmodified lines | |||
| 1081 | 1109 | ||
| 1082 | std::ostream& operator<<(std::ostream &ss, const debugger_options o) | 1110 | std::ostream& operator<<(std::ostream &ss, const debugger_options o) |
| 1083 | { | 1111 | { |
| 1084 | ss << "Break on enter: " << std::boolalpha << util::has_flag(o, debugger_options::break_on_enter) << "\n" | 1112 | ss << "Break on enter: " << std::boolalpha << disvm::util::has_flag(o, debugger_options::break_on_enter) << "\n" |
| 1085 | << "Break on module load: " << std::boolalpha << util::has_flag(o, debugger_options::break_on_module_load) << "\n" | 1113 | << "Break on module load: " << std::boolalpha << disvm::util::has_flag(o, debugger_options::break_on_module_load) << "\n" |
| 1086 | << "Break on exception: " << std::boolalpha << util::has_flag(o, debugger_options::break_on_exception) << "\n"; | 1114 | << "Break on exception: " << std::boolalpha << disvm::util::has_flag(o, debugger_options::break_on_exception) << "\n"; |
| 1087 | 1115 | ||
| 1088 | return ss; | 1116 | return ss; |
| 1089 | } | 1117 | } |
| @@ -1096,10 +1124,10 @@ debugger::debugger(const debugger_options opt) · 6 unmodified lines | |||
| 1096 | { } | 1124 | { } |
| 1097 | 1125 | ||
| 1098 | std::vector<std::string> debugger::resolve_to_function_source_line( | 1126 | std::vector<std::string> debugger::resolve_to_function_source_line( |
| 1099 | disvm::runtime::module_id_t vm_id, | 1127 | module_id_t vm_id, |
| 1100 | vm_pc_t begin_pc, | 1128 | vm_pc_t begin_pc, |
| 1101 | vm_pc_t end_pc, | 1129 | vm_pc_t end_pc, |
| 1102 | symbol::function_name_format_t fmt) const | 1130 | function_name_format_t fmt) const |
| 1103 | { | 1131 | { |
| 1104 | auto iter = _vm_id_to_symbol_info.find(vm_id); | 1132 | auto iter = _vm_id_to_symbol_info.find(vm_id); |
| 1105 | if (iter == std::cend(_vm_id_to_symbol_info)) | 1133 | if (iter == std::cend(_vm_id_to_symbol_info)) |
| @@ -1129,18 +1157,18 @@ std::vector<std::string> debugger::resolve_to_function_source_line( · 23 unmodified lines | |||
| 1129 | 1157 | ||
| 1130 | resolved_functions_by_pc[next_pc - begin_pc] = std::move(ss.str()); | 1158 | resolved_functions_by_pc[next_pc - begin_pc] = std::move(ss.str()); |
| 1131 | 1159 | ||
| 1132 | } while (d.try_advance_pc(symbol::advance_pc_t::next_debug_statement, &next_pc)); | 1160 | } while (d.try_advance_pc(advance_pc_t::next_debug_statement, &next_pc)); |
| 1133 | 1161 | ||
| 1134 | return resolved_functions_by_pc; | 1162 | return resolved_functions_by_pc; |
| 1135 | } | 1163 | } |
| 1136 | 1164 | ||
| 1137 | std::vector<std::string> debugger::get_module_functions(disvm::runtime::module_id_t vm_id, const char *match) const | 1165 | std::vector<std::string> debugger::get_module_functions(module_id_t vm_id, const char *match) const |
| 1138 | { | 1166 | { |
| 1139 | std::vector<std::string> funcs; | 1167 | std::vector<std::string> funcs; |
| 1140 | auto iter = _vm_id_to_symbol_info.find(vm_id); | 1168 | auto iter = _vm_id_to_symbol_info.find(vm_id); |
| 1141 | if (iter != std::cend(_vm_id_to_symbol_info)) | 1169 | if (iter != std::cend(_vm_id_to_symbol_info)) |
| 1142 | { | 1170 | { |
| 1143 | auto f_infos = iter->second.data->get_functions(symbol::function_name_format_t::declaration); | 1171 | auto f_infos = iter->second.data->get_functions(function_name_format_t::declaration); |
| 1144 | for (auto &fi : f_infos) | 1172 | for (auto &fi : f_infos) |
| 1145 | { | 1173 | { |
| 1146 | // Only return functions that match the supplied string | 1174 | // Only return functions that match the supplied string |
| @@ -1163,7 +1191,7 @@ std::vector<std::string> debugger::get_module_functions(disvm::runtime::module_i · 16 unmodified lines | |||
| 1163 | return funcs; | 1191 | return funcs; |
| 1164 | } | 1192 | } |
| 1165 | 1193 | ||
| 1166 | bool debugger::symbols_exist(disvm::runtime::module_id_t vm_id) const | 1194 | bool debugger::symbols_exist(module_id_t vm_id) const |
| 1167 | { | 1195 | { |
| 1168 | return _vm_id_to_symbol_info.find(vm_id) != std::cend(_vm_id_to_symbol_info); | 1196 | return _vm_id_to_symbol_info.find(vm_id) != std::cend(_vm_id_to_symbol_info); |
| 1169 | } | 1197 | } |
| @@ -1220,7 +1248,7 @@ void debugger::on_load(vm_tool_controller_t &controller_, std::size_t tool_id) · 50 unmodified lines | |||
| 1220 | 1248 | ||
| 1221 | debug_print_info(ss.str()); | 1249 | debug_print_info(ss.str()); |
| 1222 | 1250 | ||
| 1223 | if (util::has_flag(_options, debugger_options::break_on_exception)) | 1251 | if (disvm::util::has_flag(_options, debugger_options::break_on_exception)) |
| 1224 | prompt(*this, *cxt.value1.registers); | 1252 | prompt(*this, *cxt.value1.registers); |
| 1225 | })); | 1253 | })); |
| 1226 | 1254 | ||
| @@ -1250,14 +1278,14 @@ void debugger::on_load(vm_tool_controller_t &controller_, std::size_t tool_id) · 23 unmodified lines | |||
| 1250 | << m->module_name->str() | 1278 | << m->module_name->str() |
| 1251 | << " loaded"; | 1279 | << " loaded"; |
| 1252 | 1280 | ||
| 1253 | if (util::has_flag(m->header.runtime_flag, runtime_flags_t::builtin)) | 1281 | if (disvm::util::has_flag(m->header.runtime_flag, runtime_flags_t::builtin)) |
| 1254 | ss << " (built-in)"; | 1282 | ss << " (built-in)"; |
| 1255 | 1283 | ||
| 1256 | debug_print_info(ss.str()); | 1284 | debug_print_info(ss.str()); |
| 1257 | 1285 | ||
| 1258 | // If the break on enter flag was set, it will be true | 1286 | // If the break on enter flag was set, it will be true |
| 1259 | // and the first module load will be the user entry module. | 1287 | // and the first module load will be the user entry module. |
| 1260 | if (util::has_flag(_options, debugger_options::break_on_enter)) | 1288 | if (disvm::util::has_flag(_options, debugger_options::break_on_enter)) |
| 1261 | { | 1289 | { |
| 1262 | // Reset the break on enter flag and set a breakpoint | 1290 | // Reset the break on enter flag and set a breakpoint |
| 1263 | // on the entry PC for the module - 'break on enter' | 1291 | // on the entry PC for the module - 'break on enter' |
| @@ -1265,7 +1293,7 @@ void debugger::on_load(vm_tool_controller_t &controller_, std::size_t tool_id) · 1 unmodified line | |||
| 1265 | breakpoint_cookies.emplace(controller->set_breakpoint(m, m->header.entry_pc)); | 1293 | breakpoint_cookies.emplace(controller->set_breakpoint(m, m->header.entry_pc)); |
| 1266 | } | 1294 | } |
| 1267 | 1295 | ||
| 1268 | if (util::has_flag(_options, debugger_options::break_on_module_load)) | 1296 | if (disvm::util::has_flag(_options, debugger_options::break_on_module_load)) |
| 1269 | prompt(*this, *cxt.value1.registers); | 1297 | prompt(*this, *cxt.value1.registers); |
| 1270 | })); | 1298 | })); |
| 1271 | 1299 | ||
| @@ -1334,10 +1362,10 @@ void debugger::load_symbols(const disvm::loaded_vm_module_t &loaded_mod) · 62 unmodified lines | |||
| 1334 | if (!sbl_file.is_open()) | 1362 | if (!sbl_file.is_open()) |
| 1335 | return; | 1363 | return; |
| 1336 | 1364 | ||
| 1337 | std::unique_ptr<symbol::symbol_data_t> symbol_data; | 1365 | std::unique_ptr<symbol_data_t> symbol_data; |
| 1338 | try | 1366 | try |
| 1339 | { | 1367 | { |
| 1340 | symbol_data = symbol::read(sbl_file); | 1368 | symbol_data = disvm::symbol::read(sbl_file); |
| 1341 | } | 1369 | } |
| 1342 | catch (const std::runtime_error &e) | 1370 | catch (const std::runtime_error &e) |
| 1343 | { | 1371 | { |