std::stringstream ss; ss << fi.name << " [" << fi.entry_pc << ", " << fi.limit_pc << "]"; funcs.push_back(ss.str()); } } return funcs;} bool debugger::symbols_exist(disvm::runtime::module_id_t vm_id) const{ return _vm_id_to_symbol_info.find(vm_id) != std::cend(_vm_id_to_symbol_info);} void debugger::on_load(vm_tool_controller_t &controller_, std::size_t tool_id){ _tool_id = tool_id; controller = &controller_; _event_cookies.emplace(controller->subscribe_event(vm_event_t::thread_begin, [](vm_event_t, vm_event_context_t &cxt) { auto t = cxt.value1.thread; auto ss = std::stringstream{}; ss << "Thread " << t->get_thread_id() << " started in " << t->get_registers().module_ref->module->module_name->str() << " @ " << t->get_registers().pc; debug_print_info(ss.str()); })); _event_cookies.emplace(controller->subscribe_event(vm_event_t::thread_end, [](vm_event_t, vm_event_context_t &cxt) { auto ss = std::stringstream{}; ss << "Thread " << cxt.value1.thread->get_thread_id() << " ended."; debug_print_info(ss.str()); })); _event_cookies.emplace(controller->subscribe_event(vm_event_t::exception_raised, [&](vm_event_t, vm_event_context_t &cxt) { auto ss = std::stringstream{}; ss << "Exception '" << cxt.value2.str->str() << "' thrown."; debug_print_info(ss.str()); if (util::has_flag(_options, debugger_options::break_on_exception)) prompt(*this, *cxt.value1.registers); })); _event_cookies.emplace(controller->subscribe_event(vm_event_t::exception_unhandled, [&](vm_event_t, vm_event_context_t &cxt) { auto ss = std::stringstream{}; ss << "Unhandled exception '" << cxt.value2.str->str() << "'"; debug_print_error(ss.str()); prompt(*this, *cxt.value1.registers); })); _event_cookies.emplace(controller->subscribe_event(vm_event_t::module_vm_load, [&](vm_event_t, vm_event_context_t &cxt) { auto loaded_mod = cxt.value1.loaded_mod; assert(loaded_mod != nullptr); load_symbols(*loaded_mod); })); _event_cookies.emplace(controller->subscribe_event(vm_event_t::module_thread_load, [&](vm_event_t, vm_event_context_t &cxt) { auto m = (*cxt.value2.module); auto ss = std::stringstream{}; ss << "Module " << m->module_name->str() << " loaded"; if (util::has_flag(m->header.runtime_flag, runtime_flags_t::builtin)) ss << " (built-in)"; debug_print_info(ss.str()); // If the break on enter flag was set, it will be true // and the first module load will be the user entry module. if (util::has_flag(_options, debugger_options::break_on_enter)) { // Reset the break on enter flag and set a breakpoint // on the entry PC for the module - 'break on enter' _options ^= debugger_options::break_on_enter; controller->set_breakpoint(m, m->header.entry_pc); } if (util::has_flag(_options, debugger_options::break_on_module_load)) prompt(*this, *cxt.value1.registers); })); _event_cookies.emplace(controller->subscribe_event(vm_event_t::breakpoint, [&](vm_event_t, vm_event_context_t &cxt) { auto ss = std::stringstream{}; ss << "Breakpoint hit"; if (cxt.value2.cookie != 0) ss << " [" << cxt.value2.cookie << "]"; debug_print_info(ss.str()); auto reg_str = registers_to_string(*cxt.value1.registers); debug_print_info(reg_str); prompt(*this, *cxt.value1.registers); }));} void debugger::on_unload(){ assert(controller != nullptr); for (auto ec : _event_cookies) controller->unsubscribe_event(ec); controller = nullptr;} void debugger::load_symbols(const disvm::loaded_vm_module_t &loaded_mod){ auto m = loaded_mod.module.lock(); assert(m != nullptr && "Loaded module event should have valid module reference"); auto symbol_extension = ".sbl"; std::string symbol_path_maybe{ loaded_mod.origin->str() }; const auto ext_index = symbol_path_maybe.find_last_of('.'); if (ext_index == std::string::npos) { // Module doesn't have an extension so just append the symbol extension. symbol_path_maybe.append(symbol_extension); } else { // Replace the module extension with the symbol extension. symbol_path_maybe.replace(ext_index, std::string::npos, symbol_extension); } std::ifstream sbl_file{ symbol_path_maybe, std::ifstream::in }; if (!sbl_file.is_open()) return; std::unique_ptr<symbol::symbol_data_t> symbol_data; try { symbol_data = symbol::read(sbl_file); } catch (const std::runtime_error &e) { // File with assumed symbol name/extension is not the correct format std::stringstream msg; msg << "Assumed symbol file '" << symbol_path_maybe << "' has invalid symbol format. (" << e.what() << ")"; debug_print_error(msg.str()); return; } // Check if the symbol data matches the loaded module if (0 != symbol_data->get_module_name().compare(m->module_name->str()) || symbol_data->get_instruction_count() != m->code_section.size()) { // Symbol file does not match the loaded modules - stale file? std::stringstream msg; msg << "Symbol file '" << symbol_path_maybe << "' does not match loaded module '" << loaded_mod.origin->str() << "'."; debug_print_error(msg.str()); return; } const auto vm_id = loaded_mod.vm_id; assert(_vm_id_to_symbol_info.find(vm_id) == std::end(_vm_id_to_symbol_info) && "Module VM ID should be unique"); auto symbol_iter = symbol_data->get_pc_iter(); _vm_id_to_symbol_info[vm_id] = { std::move(symbol_data), std::move(symbol_iter) }; std::stringstream msg; msg << "Symbol file '" << symbol_path_maybe << "' loaded for '" << loaded_mod.origin->str() << "'."; debug_print_info(msg.str());}Lines 1001–1203 of 1203. Previous lines
std::stringstream ss; ss << fi.name << " [" << fi.entry_pc << ", " << fi.limit_pc << "]"; funcs.push_back(ss.str()); } } return funcs; } bool debugger::symbols_exist(disvm::runtime::module_id_t vm_id) const { return _vm_id_to_symbol_info.find(vm_id) != std::cend(_vm_id_to_symbol_info); } void debugger::on_load(vm_tool_controller_t &controller_, std::size_t tool_id) { _tool_id = tool_id; controller = &controller_; _event_cookies.emplace(controller->subscribe_event(vm_event_t::thread_begin, [](vm_event_t, vm_event_context_t &cxt) { auto t = cxt.value1.thread; auto ss = std::stringstream{}; ss << "Thread " << t->get_thread_id() << " started in " << t->get_registers().module_ref->module->module_name->str() << " @ " << t->get_registers().pc; debug_print_info(ss.str()); })); _event_cookies.emplace(controller->subscribe_event(vm_event_t::thread_end, [](vm_event_t, vm_event_context_t &cxt) { auto ss = std::stringstream{}; ss << "Thread " << cxt.value1.thread->get_thread_id() << " ended."; debug_print_info(ss.str()); })); _event_cookies.emplace(controller->subscribe_event(vm_event_t::exception_raised, [&](vm_event_t, vm_event_context_t &cxt) { auto ss = std::stringstream{}; ss << "Exception '" << cxt.value2.str->str() << "' thrown."; debug_print_info(ss.str()); if (util::has_flag(_options, debugger_options::break_on_exception)) prompt(*this, *cxt.value1.registers); })); _event_cookies.emplace(controller->subscribe_event(vm_event_t::exception_unhandled, [&](vm_event_t, vm_event_context_t &cxt) { auto ss = std::stringstream{}; ss << "Unhandled exception '" << cxt.value2.str->str() << "'"; debug_print_error(ss.str()); prompt(*this, *cxt.value1.registers); })); _event_cookies.emplace(controller->subscribe_event(vm_event_t::module_vm_load, [&](vm_event_t, vm_event_context_t &cxt) { auto loaded_mod = cxt.value1.loaded_mod; assert(loaded_mod != nullptr); load_symbols(*loaded_mod); })); _event_cookies.emplace(controller->subscribe_event(vm_event_t::module_thread_load, [&](vm_event_t, vm_event_context_t &cxt) { auto m = (*cxt.value2.module); auto ss = std::stringstream{}; ss << "Module " << m->module_name->str() << " loaded"; if (util::has_flag(m->header.runtime_flag, runtime_flags_t::builtin)) ss << " (built-in)"; debug_print_info(ss.str()); // If the break on enter flag was set, it will be true // and the first module load will be the user entry module. if (util::has_flag(_options, debugger_options::break_on_enter)) { // Reset the break on enter flag and set a breakpoint // on the entry PC for the module - 'break on enter' _options ^= debugger_options::break_on_enter; controller->set_breakpoint(m, m->header.entry_pc); } if (util::has_flag(_options, debugger_options::break_on_module_load)) prompt(*this, *cxt.value1.registers); })); _event_cookies.emplace(controller->subscribe_event(vm_event_t::breakpoint, [&](vm_event_t, vm_event_context_t &cxt) { auto ss = std::stringstream{}; ss << "Breakpoint hit"; if (cxt.value2.cookie != 0) ss << " [" << cxt.value2.cookie << "]"; debug_print_info(ss.str()); auto reg_str = registers_to_string(*cxt.value1.registers); debug_print_info(reg_str); prompt(*this, *cxt.value1.registers); })); } void debugger::on_unload() { assert(controller != nullptr); for (auto ec : _event_cookies) controller->unsubscribe_event(ec); controller = nullptr; } void debugger::load_symbols(const disvm::loaded_vm_module_t &loaded_mod) { auto m = loaded_mod.module.lock(); assert(m != nullptr && "Loaded module event should have valid module reference"); auto symbol_extension = ".sbl"; std::string symbol_path_maybe{ loaded_mod.origin->str() }; const auto ext_index = symbol_path_maybe.find_last_of('.'); if (ext_index == std::string::npos) { // Module doesn't have an extension so just append the symbol extension. symbol_path_maybe.append(symbol_extension); } else { // Replace the module extension with the symbol extension. symbol_path_maybe.replace(ext_index, std::string::npos, symbol_extension); } std::ifstream sbl_file{ symbol_path_maybe, std::ifstream::in }; if (!sbl_file.is_open()) return; std::unique_ptr<symbol::symbol_data_t> symbol_data; try { symbol_data = symbol::read(sbl_file); } catch (const std::runtime_error &e) { // File with assumed symbol name/extension is not the correct format std::stringstream msg; msg << "Assumed symbol file '" << symbol_path_maybe << "' has invalid symbol format. (" << e.what() << ")"; debug_print_error(msg.str()); return; } // Check if the symbol data matches the loaded module if (0 != symbol_data->get_module_name().compare(m->module_name->str()) || symbol_data->get_instruction_count() != m->code_section.size()) { // Symbol file does not match the loaded modules - stale file? std::stringstream msg; msg << "Symbol file '" << symbol_path_maybe << "' does not match loaded module '" << loaded_mod.origin->str() << "'."; debug_print_error(msg.str()); return; } const auto vm_id = loaded_mod.vm_id; assert(_vm_id_to_symbol_info.find(vm_id) == std::end(_vm_id_to_symbol_info) && "Module VM ID should be unique"); auto symbol_iter = symbol_data->get_pc_iter(); _vm_id_to_symbol_info[vm_id] = { std::move(symbol_data), std::move(symbol_iter) }; std::stringstream msg; msg << "Symbol file '" << symbol_path_maybe << "' loaded for '" << loaded_mod.origin->str() << "'."; debug_print_info(msg.str()); }