Unified · Split
| @@ -366,10 +366,7 @@ namespace · 365 unmodified lines | |||
| 366 | 366 | ||
| 367 | if (parts.size() == 3) | 367 | if (parts.size() == 3) |
| 368 | { | 368 | { |
| 369 | item.size_in_bytes = std::strtol(parts[2].c_str(), nullptr, 10); | 369 | item.size_in_bytes = std::stoi(parts[2]); |
| 370 | if (item.size_in_bytes == 0 && errno != 0) | ||
| 371 | throw std::runtime_error{ "Invalid adt size" }; | ||
| 372 | |||
| 373 | item.id_table = read_id_table(r, tt, fc); | 370 | item.id_table = read_id_table(r, tt, fc); |
| 374 | } | 371 | } |
| 375 | 372 | ||
| @@ -429,9 +426,6 @@ namespace · 53 unmodified lines | |||
| 429 | { | 426 | { |
| 430 | auto type_index = r.get_as_string_until('\n'); | 427 | auto type_index = r.get_as_string_until('\n'); |
| 431 | const auto idx = std::stoi(type_index); | 428 | const auto idx = std::stoi(type_index); |
| 432 | if (idx == 0) | ||
| 433 | throw std::runtime_error{ "Invalid type index" }; | ||
| 434 | |||
| 435 | t.value_index_1 = type_table_t::types_mask | idx; | 429 | t.value_index_1 = type_table_t::types_mask | idx; |
| 436 | break; | 430 | break; |
| 437 | } | 431 | } |
| @@ -681,6 +675,11 @@ namespace · 243 unmodified lines | |||
| 681 | return _file->header.module_name; | 675 | return _file->header.module_name; |
| 682 | } | 676 | } |
| 683 | 677 | ||
| 678 | size_t get_instruction_count() const | ||
| 679 | { | ||
| 680 | return _file->pc_table.size(); | ||
| 681 | } | ||
| 682 | |||
| 684 | std::unique_ptr<symbol_debug_t> get_debug() override | 683 | std::unique_ptr<symbol_debug_t> get_debug() override |
| 685 | { | 684 | { |
| 686 | return std::make_unique<sbl_symbol_debug>(_file); | 685 | return std::make_unique<sbl_symbol_debug>(_file); |
| @@ -5,6 +5,7 @@ · 4 unmodified lines | |||
| 5 | // | 5 | // |
| 6 | 6 | ||
| 7 | #include <iostream> | 7 | #include <iostream> |
| 8 | #include <fstream> | ||
| 8 | #include <iomanip> | 9 | #include <iomanip> |
| 9 | #include <sstream> | 10 | #include <sstream> |
| 10 | #include <string> | 11 | #include <string> |
| @@ -117,16 +118,26 @@ namespace · 106 unmodified lines | |||
| 117 | dbg_cmd_exec_t exec; | 118 | dbg_cmd_exec_t exec; |
| 118 | }; | 119 | }; |
| 119 | 120 | ||
| 120 | std::string stack_to_string(const vm_registers_t &r) | 121 | std::string stack_to_string(const vm_registers_t &r, debugger &dbg) |
| 121 | { | 122 | { |
| 122 | auto msg = std::stringstream{}; | 123 | auto msg = std::stringstream{}; |
| 123 | walk_stack(r, [&msg](const pointer_t, const vm_pc_t pc, const vm_module_ref_t &module_ref) | 124 | walk_stack(r, [&msg, &dbg](const pointer_t, const vm_pc_t pc, const vm_module_ref_t &module_ref) |
| 124 | { | 125 | { |
| 125 | auto module_name = "<No Name>"; | 126 | auto resolved_name = dbg.resolve_function_source_line(module_ref.module, pc); |
| 126 | if (module_ref.module->module_name != nullptr) | 127 | if (!resolved_name.empty()) |
| 127 | module_name = module_ref.module->module_name->str(); | 128 | { |
| 129 | msg << resolved_name; | ||
| 130 | } | ||
| 131 | else | ||
| 132 | { | ||
| 133 | auto module_name = "<No Name>"; | ||
| 134 | if (module_ref.module->module_name != nullptr) | ||
| 135 | module_name = module_ref.module->module_name->str(); | ||
| 136 | |||
| 137 | msg << module_name << "@" << pc; | ||
| 138 | } | ||
| 128 | 139 | ||
| 129 | msg << module_name << "@" << pc << "\n"; | 140 | msg << "\n"; |
| 130 | return true; | 141 | return true; |
| 131 | }); | 142 | }); |
| 132 | 143 | ||
| @@ -215,7 +226,7 @@ namespace · 82 unmodified lines | |||
| 215 | ss << "channel\n" | 226 | ss << "channel\n" |
| 216 | << "\tbuffer size: " << c->get_buffer_size() << "\n"; | 227 | << "\tbuffer size: " << c->get_buffer_size() << "\n"; |
| 217 | 228 | ||
| 218 | return ss; | 229 | return ss; |
| 219 | } | 230 | } |
| 220 | 231 | ||
| 221 | std::ostream& operator<<(std::ostream &ss, const vm_alloc_t *alloc) | 232 | std::ostream& operator<<(std::ostream &ss, const vm_alloc_t *alloc) |
| @@ -330,7 +341,7 @@ namespace · 108 unmodified lines | |||
| 330 | auto module_instance = m.module.lock(); | 341 | auto module_instance = m.module.lock(); |
| 331 | if (module_instance != nullptr) | 342 | if (module_instance != nullptr) |
| 332 | { | 343 | { |
| 333 | msg << std::setw(3) << m.load_id << ": " | 344 | msg << std::setw(3) << m.vm_id << ": " |
| 334 | << std::setw(16) << module_instance->module_name->str() | 345 | << std::setw(16) << module_instance->module_name->str() |
| 335 | << std::setw(0) << " - " << m.origin->str() << "\n"; | 346 | << std::setw(0) << " - " << m.origin->str() << "\n"; |
| 336 | } | 347 | } |
| @@ -372,7 +383,7 @@ namespace · 35 unmodified lines | |||
| 372 | 383 | ||
| 373 | cxt.vm.enum_loaded_modules([module_id, &module](const loaded_vm_module_t &m) | 384 | cxt.vm.enum_loaded_modules([module_id, &module](const loaded_vm_module_t &m) |
| 374 | { | 385 | { |
| 375 | if (module_id != m.load_id) | 386 | if (module_id != m.vm_id) |
| 376 | return true; | 387 | return true; |
| 377 | 388 | ||
| 378 | // Found the matching ID so stop | 389 | // Found the matching ID so stop |
| @@ -500,7 +511,7 @@ namespace · 121 unmodified lines | |||
| 500 | for (auto t : thread_registers) | 511 | for (auto t : thread_registers) |
| 501 | { | 512 | { |
| 502 | msg << "Thread " << t.first << ":\n"; | 513 | msg << "Thread " << t.first << ":\n"; |
| 503 | msg << stack_to_string(*t.second); | 514 | msg << stack_to_string(*t.second, cxt.dbg); |
| 504 | msg << "\n"; | 515 | msg << "\n"; |
| 505 | } | 516 | } |
| 506 | 517 | ||
| @@ -856,6 +867,30 @@ debugger::debugger(const debugger_options opt) · 349 unmodified lines | |||
| 856 | , controller{ nullptr } | 867 | , controller{ nullptr } |
| 857 | { } | 868 | { } |
| 858 | 869 | ||
| 870 | std::string debugger::resolve_function_source_line(std::shared_ptr<const vm_module_t> m, vm_pc_t pc) | ||
| 871 | { | ||
| 872 | if (m == nullptr) | ||
| 873 | return{}; | ||
| 874 | |||
| 875 | auto iter = _vm_id_to_symbol_debug.find(m->vm_id); | ||
| 876 | if (iter == std::end(_vm_id_to_symbol_debug)) | ||
| 877 | return{}; | ||
| 878 | |||
| 879 | std::stringstream ss; | ||
| 880 | auto &d = *(iter->second); | ||
| 881 | |||
| 882 | // Position the debug symbol iterator | ||
| 883 | d.set_current_pc(pc); | ||
| 884 | |||
| 885 | ss << m->module_name->str() | ||
| 886 | << '!' | ||
| 887 | << d.current_function_name() | ||
| 888 | << ' ' | ||
| 889 | << d.current_source_location().begin_line; | ||
| 890 | |||
| 891 | return ss.str(); | ||
| 892 | } | ||
| 893 | |||
| 859 | void debugger::on_load(vm_tool_controller_t &controller_, std::size_t tool_id) | 894 | void debugger::on_load(vm_tool_controller_t &controller_, std::size_t tool_id) |
| 860 | { | 895 | { |
| 861 | _tool_id = tool_id; | 896 | _tool_id = tool_id; |
| @@ -909,6 +944,13 @@ void debugger::on_load(vm_tool_controller_t &controller_, std::size_t tool_id) · 47 unmodified lines | |||
| 909 | prompt(*this, *cxt.value1.registers); | 944 | prompt(*this, *cxt.value1.registers); |
| 910 | })); | 945 | })); |
| 911 | 946 | ||
| 947 | _event_cookies.emplace(controller->subscribe_event(vm_event_t::module_vm_load, [&](vm_event_t, vm_event_context_t &cxt) | ||
| 948 | { | ||
| 949 | auto loaded_mod = cxt.value1.loaded_mod; | ||
| 950 | assert(loaded_mod != nullptr); | ||
| 951 | load_symbols(*loaded_mod); | ||
| 952 | })); | ||
| 953 | |||
| 912 | _event_cookies.emplace(controller->subscribe_event(vm_event_t::module_thread_load, [&](vm_event_t, vm_event_context_t &cxt) | 954 | _event_cookies.emplace(controller->subscribe_event(vm_event_t::module_thread_load, [&](vm_event_t, vm_event_context_t &cxt) |
| 913 | { | 955 | { |
| 914 | auto m = (*cxt.value2.module); | 956 | auto m = (*cxt.value2.module); |
| @@ -960,4 +1002,73 @@ void debugger::on_unload() · 45 unmodified lines | |||
| 960 | controller->unsubscribe_event(ec); | 1002 | controller->unsubscribe_event(ec); |
| 961 | 1003 | ||
| 962 | controller = nullptr; | 1004 | controller = nullptr; |
| 1005 | } | ||
| 1006 | |||
| 1007 | void debugger::load_symbols(const disvm::loaded_vm_module_t &loaded_mod) | ||
| 1008 | { | ||
| 1009 | auto m = loaded_mod.module.lock(); | ||
| 1010 | assert(m != nullptr && "Loaded module event should have valid module reference"); | ||
| 1011 | |||
| 1012 | auto symbol_extension = ".sbl"; | ||
| 1013 | std::string symbol_path_maybe{ loaded_mod.origin->str() }; | ||
| 1014 | const auto ext_index = symbol_path_maybe.find_last_of('.'); | ||
| 1015 | if (ext_index == std::string::npos) | ||
| 1016 | { | ||
| 1017 | // Module doesn't have an extension so just append the symbol extension. | ||
| 1018 | symbol_path_maybe.append(symbol_extension); | ||
| 1019 | } | ||
| 1020 | else | ||
| 1021 | { | ||
| 1022 | // Replace the module extension with the symbol extension. | ||
| 1023 | symbol_path_maybe.replace(ext_index, std::string::npos, symbol_extension); | ||
| 1024 | } | ||
| 1025 | |||
| 1026 | std::ifstream sbl_file{ symbol_path_maybe, std::ifstream::in }; | ||
| 1027 | if (!sbl_file.is_open()) | ||
| 1028 | return; | ||
| 1029 | |||
| 1030 | std::unique_ptr<symbol::symbol_data_t> symbol_data; | ||
| 1031 | try | ||
| 1032 | { | ||
| 1033 | symbol_data = symbol::read(sbl_file); | ||
| 1034 | } | ||
| 1035 | catch (const std::runtime_error &e) | ||
| 1036 | { | ||
| 1037 | // File with assumed symbol name/extension is not the correct format | ||
| 1038 | std::stringstream msg; | ||
| 1039 | msg << "Assumed symbol file '" | ||
| 1040 | << symbol_path_maybe | ||
| 1041 | << "' has invalid symbol format. (" | ||
| 1042 | << e.what() | ||
| 1043 | << ")"; | ||
| 1044 | debug_print_error(msg.str()); | ||
| 1045 | return; | ||
| 1046 | } | ||
| 1047 | |||
| 1048 | // Check if the symbol data matches the loaded module | ||
| 1049 | if (0 != symbol_data->get_module_name().compare(m->module_name->str()) | ||
| 1050 | || symbol_data->get_instruction_count() != m->code_section.size()) | ||
| 1051 | { | ||
| 1052 | // Symbol file does not match the loaded modules - stale file? | ||
| 1053 | std::stringstream msg; | ||
| 1054 | msg << "Symbol file '" | ||
| 1055 | << symbol_path_maybe | ||
| 1056 | << "' does not match loaded module '" | ||
| 1057 | << loaded_mod.origin->str() | ||
| 1058 | << "'."; | ||
| 1059 | debug_print_error(msg.str()); | ||
| 1060 | return; | ||
| 1061 | } | ||
| 1062 | |||
| 1063 | const auto vm_id = loaded_mod.vm_id; | ||
| 1064 | assert(_vm_id_to_symbol_debug.find(vm_id) == std::end(_vm_id_to_symbol_debug) && "Module VM ID should be unique"); | ||
| 1065 | _vm_id_to_symbol_debug[vm_id] = symbol_data->get_debug(); | ||
| 1066 | |||
| 1067 | std::stringstream msg; | ||
| 1068 | msg << "Symbol file '" | ||
| 1069 | << symbol_path_maybe | ||
| 1070 | << "' loaded for '" | ||
| 1071 | << loaded_mod.origin->str() | ||
| 1072 | << "'."; | ||
| 1073 | debug_print_info(msg.str()); | ||
| 963 | } | 1074 | } |
| @@ -16,9 +16,10 @@ · 15 unmodified lines | |||
| 16 | enum class debugger_options | 16 | enum class debugger_options |
| 17 | { | 17 | { |
| 18 | none = 0, | 18 | none = 0, |
| 19 | break_on_enter = 1, | 19 | break_on_enter = (1 << 0), |
| 20 | break_on_module_load = 2, | 20 | break_on_module_load = (1 << 1), |
| 21 | break_on_exception = 4, | 21 | break_on_exception = (1 << 2), |
| 22 | disable_symbol_loading = (1 << 3), | ||
| 22 | }; | 23 | }; |
| 23 | 24 | ||
| 24 | DEFINE_ENUM_FLAG_OPERATORS(debugger_options); | 25 | DEFINE_ENUM_FLAG_OPERATORS(debugger_options); |
| @@ -30,6 +31,8 @@ class debugger final : public disvm::runtime::vm_tool_t · 5 unmodified lines | |||
| 30 | public: | 31 | public: |
| 31 | debugger(const debugger_options); | 32 | debugger(const debugger_options); |
| 32 | 33 | ||
| 34 | std::string resolve_function_source_line(std::shared_ptr<const disvm::runtime::vm_module_t> m, disvm::runtime::vm_pc_t pc); | ||
| 35 | |||
| 33 | public: // vm_tool_t | 36 | public: // vm_tool_t |
| 34 | void on_load(disvm::runtime::vm_tool_controller_t &, std::size_t tool_id) override; | 37 | void on_load(disvm::runtime::vm_tool_controller_t &, std::size_t tool_id) override; |
| 35 | 38 | ||
| @@ -40,9 +43,12 @@ public: · 4 unmodified lines | |||
| 40 | std::unordered_set<disvm::runtime::cookie_t> breakpoint_cookies; | 43 | std::unordered_set<disvm::runtime::cookie_t> breakpoint_cookies; |
| 41 | 44 | ||
| 42 | private: | 45 | private: |
| 46 | void load_symbols(const disvm::loaded_vm_module_t &); | ||
| 47 | |||
| 43 | debugger_options _options; | 48 | debugger_options _options; |
| 44 | std::size_t _tool_id; | 49 | std::size_t _tool_id; |
| 45 | std::unordered_set<disvm::runtime::cookie_t> _event_cookies; | 50 | std::unordered_set<disvm::runtime::cookie_t> _event_cookies; |
| 51 | std::unordered_map<std::size_t, std::unique_ptr<disvm::symbol::symbol_debug_t>> _vm_id_to_symbol_debug; | ||
| 46 | }; | 52 | }; |
| 47 | 53 | ||
| 48 | #endif // _DISVM_SRC_EXEC_EXEC_H_ | 54 | #endif // _DISVM_SRC_EXEC_EXEC_H_ |
| @@ -39,7 +39,7 @@ namespace disvm · 38 unmodified lines | |||
| 39 | class loaded_vm_module_t final | 39 | class loaded_vm_module_t final |
| 40 | { | 40 | { |
| 41 | public: | 41 | public: |
| 42 | std::size_t load_id; | 42 | runtime::module_id_t vm_id; |
| 43 | 43 | ||
| 44 | // Origin of module | 44 | // Origin of module |
| 45 | std::unique_ptr<runtime::vm_string_t> origin; | 45 | std::unique_ptr<runtime::vm_string_t> origin; |
| @@ -89,7 +89,7 @@ namespace disvm · 43 unmodified lines | |||
| 89 | const runtime::vm_frame_t &initial_frame, | 89 | const runtime::vm_frame_t &initial_frame, |
| 90 | runtime::vm_pc_t initial_pc); | 90 | runtime::vm_pc_t initial_pc); |
| 91 | 91 | ||
| 92 | // Load the module at the supplied path into the virtual machine | 92 | // Load the module at the supplied path into the virtual machine. |
| 93 | std::shared_ptr<runtime::vm_module_t> load_module(const char *path); | 93 | std::shared_ptr<runtime::vm_module_t> load_module(const char *path); |
| 94 | 94 | ||
| 95 | // Enumerate all loaded modules - this can include references to modules that | 95 | // Enumerate all loaded modules - this can include references to modules that |
| @@ -566,6 +566,8 @@ namespace disvm · 565 unmodified lines | |||
| 566 | using import_section_t = std::vector<import_vm_module_t>; | 566 | using import_section_t = std::vector<import_vm_module_t>; |
| 567 | using handler_section_t = std::vector<handler_t>; | 567 | using handler_section_t = std::vector<handler_t>; |
| 568 | 568 | ||
| 569 | using module_id_t = std::size_t; | ||
| 570 | |||
| 569 | // VM module | 571 | // VM module |
| 570 | struct vm_module_t | 572 | struct vm_module_t |
| 571 | { | 573 | { |
| @@ -575,6 +577,10 @@ namespace disvm · 3 unmodified lines | |||
| 575 | 577 | ||
| 576 | ~vm_module_t(); | 578 | ~vm_module_t(); |
| 577 | 579 | ||
| 580 | // This is a unique ID assigned to the module by the VM. It is associated with the path of the module and is idempotent | ||
| 581 | // with respect to the number of times the module is loaded. It is considered read-only. | ||
| 582 | module_id_t vm_id; | ||
| 583 | |||
| 578 | // Contains a magic number, digital signature, runtime flags, sizes of the other sections, and a description of the entry point | 584 | // Contains a magic number, digital signature, runtime flags, sizes of the other sections, and a description of the entry point |
| 579 | header_t header; | 585 | header_t header; |
| 580 | 586 | ||
| @@ -441,6 +441,9 @@ namespace disvm · 440 unmodified lines | |||
| 441 | // Get name of the module | 441 | // Get name of the module |
| 442 | virtual const std::string& get_module_name() const = 0; | 442 | virtual const std::string& get_module_name() const = 0; |
| 443 | 443 | ||
| 444 | // Get instruction count in the symbol data | ||
| 445 | virtual size_t get_instruction_count() const = 0; | ||
| 446 | |||
| 444 | // Get interface over symbol data targeted for debugging | 447 | // Get interface over symbol data targeted for debugging |
| 445 | virtual std::unique_ptr<symbol_debug_t> get_debug() = 0; | 448 | virtual std::unique_ptr<symbol_debug_t> get_debug() = 0; |
| 446 | }; | 449 | }; |
| @@ -28,6 +28,7 @@ namespace disvm · 27 unmodified lines | |||
| 28 | const vm_thread_t *thread; | 28 | const vm_thread_t *thread; |
| 29 | const vm_string_t *str; | 29 | const vm_string_t *str; |
| 30 | const vm_alloc_t *alloc; | 30 | const vm_alloc_t *alloc; |
| 31 | const loaded_vm_module_t *loaded_mod; | ||
| 31 | }; | 32 | }; |
| 32 | 33 | ||
| 33 | // Event context | 34 | // Event context |
| @@ -41,8 +42,7 @@ namespace disvm · 7 unmodified lines | |||
| 41 | // List of possible events | 42 | // List of possible events |
| 42 | enum class vm_event_t | 43 | enum class vm_event_t |
| 43 | { | 44 | { |
| 44 | module_vm_load, // value1: std::shared_ptr<vm_module_t> | 45 | module_vm_load, // value1: const loaded_vm_module_t |
| 45 | // value2: const vm_string_t - path on disk | ||
| 46 | 46 | ||
| 47 | module_thread_load, // value1: vm_registers_t | 47 | module_thread_load, // value1: vm_registers_t |
| 48 | // value2: std::shared_ptr<vm_module_t> | 48 | // value2: std::shared_ptr<vm_module_t> |
| @@ -126,13 +126,10 @@ void vm_tool_dispatch_t::on_exception_unhandled(vm_registers_t &r, const vm_stri · 125 unmodified lines | |||
| 126 | _events.fire_event_callbacks(vm_event_t::exception_unhandled, cxt); | 126 | _events.fire_event_callbacks(vm_event_t::exception_unhandled, cxt); |
| 127 | } | 127 | } |
| 128 | 128 | ||
| 129 | void vm_tool_dispatch_t::on_module_vm_load(std::shared_ptr<vm_module_t> &m, const vm_string_t &path) | 129 | void vm_tool_dispatch_t::on_module_vm_load(const loaded_vm_module_t &m) |
| 130 | { | 130 | { |
| 131 | assert(m != nullptr); | ||
| 132 | |||
| 133 | vm_event_context_t cxt{}; | 131 | vm_event_context_t cxt{}; |
| 134 | cxt.value1.module = &m; | 132 | cxt.value1.loaded_mod = &m; |
| 135 | cxt.value2.str = &path; | ||
| 136 | 133 | ||
| 137 | _events.fire_event_callbacks(vm_event_t::module_vm_load, cxt); | 134 | _events.fire_event_callbacks(vm_event_t::module_vm_load, cxt); |
| 138 | } | 135 | } |
| @@ -43,9 +43,9 @@ namespace disvm · 42 unmodified lines | |||
| 43 | void on_exception_unhandled(vm_registers_t &r, const vm_string_t &id, vm_alloc_t &e); | 43 | void on_exception_unhandled(vm_registers_t &r, const vm_string_t &id, vm_alloc_t &e); |
| 44 | 44 | ||
| 45 | // Callback for when the VM loads a module from disk | 45 | // Callback for when the VM loads a module from disk |
| 46 | void on_module_vm_load(std::shared_ptr<vm_module_t> &m, const vm_string_t &path); | 46 | void on_module_vm_load(const loaded_vm_module_t &loaded_module); |
| 47 | 47 | ||
| 48 | // Callback for when a thread loads a module into its scope | 48 | // Callback for when a thread loads a module into its scope. |
| 49 | void on_module_thread_load(vm_registers_t &r, std::shared_ptr<vm_module_t> &m); | 49 | void on_module_thread_load(vm_registers_t &r, std::shared_ptr<vm_module_t> &m); |
| 50 | 50 | ||
| 51 | // Callback when thread lifetime begins. | 51 | // Callback when thread lifetime begins. |
| @@ -134,6 +134,8 @@ std::shared_ptr<runtime::vm_module_t> vm_t::load_module(const char *path) · 133 unmodified lines | |||
| 134 | if (module == nullptr) | 134 | if (module == nullptr) |
| 135 | { | 135 | { |
| 136 | module = std::shared_ptr<vm_module_t>{ std::move(read_module(path)) }; | 136 | module = std::shared_ptr<vm_module_t>{ std::move(read_module(path)) }; |
| 137 | module->vm_id = iter->vm_id; | ||
| 138 | |||
| 137 | iter->module = module; | 139 | iter->module = module; |
| 138 | 140 | ||
| 139 | debug::log_msg(debug::component_trace_t::module, debug::log_level_t::debug, "reload: vm module: >>%s<<\n", path); | 141 | debug::log_msg(debug::component_trace_t::module, debug::log_level_t::debug, "reload: vm module: >>%s<<\n", path); |
| @@ -157,11 +159,12 @@ std::shared_ptr<runtime::vm_module_t> vm_t::load_module(const char *path) · 17 unmodified lines | |||
| 157 | 159 | ||
| 158 | auto path_local = std::make_unique<vm_string_t>(std::strlen(path), reinterpret_cast<const uint8_t *>(path)); | 160 | auto path_local = std::make_unique<vm_string_t>(std::strlen(path), reinterpret_cast<const uint8_t *>(path)); |
| 159 | 161 | ||
| 160 | auto load_id_next = std::size_t{ 0 }; | 162 | auto vm_id_next = std::size_t{ 1 }; |
| 161 | if (!_modules.empty()) | 163 | if (!_modules.empty()) |
| 162 | load_id_next = (_modules.front().load_id + 1); | 164 | vm_id_next = (_modules.front().vm_id + 1); |
| 163 | 165 | ||
| 164 | _modules.push_front(std::move(loaded_vm_module_t{ load_id_next, std::move(path_local), new_module })); | 166 | new_module->vm_id = vm_id_next; |
| 167 | _modules.push_front(std::move(loaded_vm_module_t{ vm_id_next, std::move(path_local), new_module })); | ||
| 165 | new_module_iter = _modules.begin(); | 168 | new_module_iter = _modules.begin(); |
| 166 | } | 169 | } |
| 167 | 170 | ||
| @@ -169,7 +172,7 @@ std::shared_ptr<runtime::vm_module_t> vm_t::load_module(const char *path) · 1 unmodified line | |||
| 169 | { | 172 | { |
| 170 | std::lock_guard<std::mutex> lock{ _tool_dispatch_lock }; | 173 | std::lock_guard<std::mutex> lock{ _tool_dispatch_lock }; |
| 171 | if (_tool_dispatch != nullptr) | 174 | if (_tool_dispatch != nullptr) |
| 172 | _tool_dispatch->on_module_vm_load(new_module, *new_module_iter->origin); | 175 | _tool_dispatch->on_module_vm_load(*new_module_iter); |
| 173 | } | 176 | } |
| 174 | 177 | ||
| 175 | if (debug::is_component_tracing_enabled<debug::component_trace_t::module>()) | 178 | if (debug::is_component_tracing_enabled<debug::component_trace_t::module>()) |