History

Debugger supports breakpoints (set/clear/list) Clean up usage of final and override on various classes Distinguish tool events for vm loading module and thread loading module

arr committed 10 years ago

Commit e2f8e251 parent d8c9a3314 files · +382 −177Browse files

Showing the changes to src/vm/tool_dispatch.cpp (1 of 14 files). Show all

Unified · Split

src/vm/tool_dispatch.cpp+48−22
@@ -50,7 +50,7 @@ std::size_t vm_tool_dispatch_t::load_tool(std::shared_ptr<runtime::vm_tool_t> to · 49 unmodified lines
5050 {
5151 // [TODO] For debug builds, it might be useful to wrap the controller in a proxy that records
5252 // the subscribed callbacks and asserts they are all properly unsubscribed during agent unload.
53− tool->on_load(_vm, *this, current_id);
53+ tool->on_load(*this, current_id);
5454 }
5555 catch (...)
5656 {
@@ -91,12 +91,12 @@ std::size_t vm_tool_dispatch_t::unload_tool(std::size_t tool_id) · 34 unmodified lines
9191 opcode_t vm_tool_dispatch_t::on_breakpoint(vm_registers_t &r)
9292 {
9393 opcode_t original_op;
94− std::size_t cookie_id;
95− std::tie(original_op, cookie_id) = get_original_opcode(r);
94+ cookie_t cookie_id;
95+ std::tie(original_op, cookie_id) = get_original_opcode_and_cookie(r);
9696
9797 vm_event_context_t cxt{};
9898 cxt.value1.registers = &r;
99− cxt.value2.i = cookie_id;
99+ cxt.value2.cookie = cookie_id;
100100
101101 _events.fire_event_callbacks(vm_event_t::breakpoint, cxt);
102102
@@ -123,7 +123,7 @@ void vm_tool_dispatch_t::on_exception_unhandled(vm_registers_t &r, const vm_stri · 20 unmodified lines
123123 _events.fire_event_callbacks(vm_event_t::exception_unhandled, cxt);
124124 }
125125
126−void vm_tool_dispatch_t::on_module_load(std::shared_ptr<vm_module_t> &m, const vm_string_t &path)
126+void vm_tool_dispatch_t::on_module_vm_load(std::shared_ptr<vm_module_t> &m, const vm_string_t &path)
127127 {
128128 assert(m != nullptr);
129129
@@ -131,7 +131,18 @@ void vm_tool_dispatch_t::on_module_load(std::shared_ptr<vm_module_t> &m, const v · 1 unmodified line
131131 cxt.value1.module = &m;
132132 cxt.value2.str = &path;
133133
134− _events.fire_event_callbacks(vm_event_t::module_load, cxt);
134+ _events.fire_event_callbacks(vm_event_t::module_vm_load, cxt);
135+}
136+
137+void vm_tool_dispatch_t::on_module_thread_load(vm_registers_t &r, std::shared_ptr<vm_module_t> &m)
138+{
139+ assert(m != nullptr);
140+
141+ vm_event_context_t cxt{};
142+ cxt.value1.registers = &r;
143+ cxt.value2.module = &m;
144+
145+ _events.fire_event_callbacks(vm_event_t::module_thread_load, cxt);
135146 }
136147
137148 void vm_tool_dispatch_t::on_thread_begin(vm_thread_t &t)
@@ -150,7 +161,12 @@ void vm_tool_dispatch_t::on_thread_end(vm_thread_t &t) · 12 unmodified lines
150161 _events.fire_event_callbacks(vm_event_t::thread_end, cxt);
151162 }
152163
153−std::size_t vm_tool_dispatch_t::subscribe_event(vm_event_t evt, vm_event_callback_t cb)
164+vm_t& vm_tool_dispatch_t::get_vm_instance() const
165+{
166+ return _vm;
167+}
168+
169+cookie_t vm_tool_dispatch_t::subscribe_event(vm_event_t evt, vm_event_callback_t cb)
154170 {
155171 if (!cb)
156172 throw vm_system_exception{ "Invalid callback for event" };
@@ -172,7 +188,7 @@ std::size_t vm_tool_dispatch_t::subscribe_event(vm_event_t evt, vm_event_callbac · 15 unmodified lines
172188 return cookie_id;
173189 }
174190
175−void vm_tool_dispatch_t::unsubscribe_event(std::size_t cookie_id)
191+void vm_tool_dispatch_t::unsubscribe_event(cookie_t cookie_id)
176192 {
177193 std::lock_guard<std::mutex> lock{ _events.lock };
178194
@@ -190,7 +206,7 @@ void vm_tool_dispatch_t::unsubscribe_event(std::size_t cookie_id) · 11 unmodified lines
190206 debug::log_msg(debug::component_trace_t::tool, debug::log_level_t::debug, "unsubscribe: event: %d %d", evt, cookie_id);
191207 }
192208
193−std::size_t vm_tool_dispatch_t::set_breakpoint(std::shared_ptr<vm_module_t> module, vm_pc_t pc)
209+cookie_t vm_tool_dispatch_t::set_breakpoint(std::shared_ptr<vm_module_t> module, vm_pc_t pc)
194210 {
195211 if (module == nullptr || util::has_flag(module->header.runtime_flag, runtime_flags_t::builtin))
196212 throw vm_system_exception{ "Unable to set breakpoint in supplied module" };
@@ -209,7 +225,7 @@ std::size_t vm_tool_dispatch_t::set_breakpoint(std::shared_ptr<vm_module_t> modu · 12 unmodified lines
209225 const auto cookie_id = _breakpoints.cookie_counter++;
210226
211227 // Map the cookie to the module/pc pair.
212− _breakpoints.cookie_to_modulepc[cookie_id] = std::make_pair(module, pc);
228+ _breakpoints.cookie_to_details[cookie_id] = { module, pc };
213229
214230 // Record the original opcode
215231 auto &pc_map = _breakpoints.original_opcodes[reinterpret_cast<std::uintptr_t>(module.get())];
@@ -225,20 +241,30 @@ std::size_t vm_tool_dispatch_t::set_breakpoint(std::shared_ptr<vm_module_t> modu · 9 unmodified lines
225241 }
226242 }
227243
228−void vm_tool_dispatch_t::clear_breakpoint(std::size_t cookie_id)
244+breakpoint_details_t vm_tool_dispatch_t::get_breakpoint_details(cookie_t cookie_id) const
229245 {
230246 std::lock_guard<std::mutex> lock{ _breakpoints.lock };
231247
232− // Resolve the cookie to the module/pc pair
233− auto iter_cookie = _breakpoints.cookie_to_modulepc.find(cookie_id);
234− if (iter_cookie == _breakpoints.cookie_to_modulepc.cend())
235− return;
248+ auto iter_cookie = _breakpoints.cookie_to_details.find(cookie_id);
249+ if (iter_cookie == _breakpoints.cookie_to_details.cend())
250+ throw vm_system_exception{ "Unknown breakpoint cookie" };
251+
252+ return iter_cookie->second;
253+}
254+
255+void vm_tool_dispatch_t::clear_breakpoint(cookie_t cookie_id)
256+{
257+ std::lock_guard<std::mutex> lock{ _breakpoints.lock };
258+
259+ auto iter_cookie = _breakpoints.cookie_to_details.find(cookie_id);
260+ if (iter_cookie == _breakpoints.cookie_to_details.cend())
261+ throw vm_system_exception{ "Unknown breakpoint cookie" };
236262
237− auto mod_pc_pair = iter_cookie->second;
238− const auto target_pc = mod_pc_pair.second;
263+ auto details = iter_cookie->second;
264+ const auto target_pc = details.pc;
239265
240266 // Determine the original opcode
241− auto iter_orig = _breakpoints.original_opcodes.find(reinterpret_cast<std::uintptr_t>(mod_pc_pair.first.get()));
267+ auto iter_orig = _breakpoints.original_opcodes.find(reinterpret_cast<std::uintptr_t>(details.module.get()));
242268 assert(iter_orig != _breakpoints.original_opcodes.cend());
243269
244270 auto &pc_map = iter_orig->second;
@@ -248,12 +274,12 @@ void vm_tool_dispatch_t::clear_breakpoint(std::size_t cookie_id) · 3 unmodified lines
248274 auto original_opcode = iter_pc->second.first;
249275
250276 // Replace the breakpoint opcode with the original
251− auto &code_section = const_cast<code_section_t &>(mod_pc_pair.first->code_section);
277+ auto &code_section = const_cast<code_section_t &>(details.module->code_section);
252278 assert(code_section[target_pc].op.opcode == opcode_t::brkpt);
253279 code_section[target_pc].op.opcode = original_opcode;
254280
255281 if (debug::is_component_tracing_enabled<debug::component_trace_t::tool>())
256− debug::log_msg(debug::component_trace_t::tool, debug::log_level_t::debug, "breakpoint: unset: %d %d >>%s<<", cookie_id, target_pc, mod_pc_pair.first->module_name->str());
282+ debug::log_msg(debug::component_trace_t::tool, debug::log_level_t::debug, "breakpoint: unset: %d %d >>%s<<", cookie_id, target_pc, details.module->module_name->str());
257283
258284 // Clean-up the PC mapping to opcode
259285 pc_map.erase(iter_pc);
@@ -263,10 +289,10 @@ void vm_tool_dispatch_t::clear_breakpoint(std::size_t cookie_id) · 3 unmodified lines
263289 _breakpoints.original_opcodes.erase(iter_orig);
264290
265291 // Remove the cookie map
266− _breakpoints.cookie_to_modulepc.erase(iter_cookie);
292+ _breakpoints.cookie_to_details.erase(iter_cookie);
267293 }
268294
269−std::tuple<opcode_t, std::size_t> vm_tool_dispatch_t::get_original_opcode(const vm_registers_t &r)
295+std::tuple<opcode_t, cookie_t> vm_tool_dispatch_t::get_original_opcode_and_cookie(const vm_registers_t &r)
270296 {
271297 const auto module = r.module_ref->module.get();
272298 const auto current_pc = r.pc - 1;