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
50 {50 {
51 // [TODO] For debug builds, it might be useful to wrap the controller in a proxy that records51 // [TODO] For debug builds, it might be useful to wrap the controller in a proxy that records
52 // the subscribed callbacks and asserts they are all properly unsubscribed during agent unload.52 // 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);
54 }54 }
55 catch (...)55 catch (...)
56 {56 {
@@ -91,12 +91,12 @@ std::size_t vm_tool_dispatch_t::unload_tool(std::size_t tool_id) · 34 unmodified lines
91opcode_t vm_tool_dispatch_t::on_breakpoint(vm_registers_t &r)91opcode_t vm_tool_dispatch_t::on_breakpoint(vm_registers_t &r)
92{92{
93 opcode_t original_op;93 opcode_t original_op;
94 std::size_t cookie_id;94 cookie_t cookie_id;
95 std::tie(original_op, cookie_id) = get_original_opcode(r);95 std::tie(original_op, cookie_id) = get_original_opcode_and_cookie(r);
96 96
97 vm_event_context_t cxt{};97 vm_event_context_t cxt{};
98 cxt.value1.registers = &r;98 cxt.value1.registers = &r;
99 cxt.value2.i = cookie_id;99 cxt.value2.cookie = cookie_id;
100 100
101 _events.fire_event_callbacks(vm_event_t::breakpoint, cxt);101 _events.fire_event_callbacks(vm_event_t::breakpoint, cxt);
102 102
@@ -123,7 +123,7 @@ void vm_tool_dispatch_t::on_exception_unhandled(vm_registers_t &r, const vm_stri · 20 unmodified lines
123 _events.fire_event_callbacks(vm_event_t::exception_unhandled, cxt);123 _events.fire_event_callbacks(vm_event_t::exception_unhandled, cxt);
124}124}
125 125
126void vm_tool_dispatch_t::on_module_load(std::shared_ptr<vm_module_t> &m, const vm_string_t &path)126void vm_tool_dispatch_t::on_module_vm_load(std::shared_ptr<vm_module_t> &m, const vm_string_t &path)
127{127{
128 assert(m != nullptr);128 assert(m != nullptr);
129 129
@@ -131,7 +131,18 @@ void vm_tool_dispatch_t::on_module_load(std::shared_ptr<vm_module_t> &m, const v · 1 unmodified line
131 cxt.value1.module = &m;131 cxt.value1.module = &m;
132 cxt.value2.str = &path;132 cxt.value2.str = &path;
133 133
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
137void 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);
135}146}
136 147
137void vm_tool_dispatch_t::on_thread_begin(vm_thread_t &t)148void 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
150 _events.fire_event_callbacks(vm_event_t::thread_end, cxt);161 _events.fire_event_callbacks(vm_event_t::thread_end, cxt);
151}162}
152 163
153std::size_t vm_tool_dispatch_t::subscribe_event(vm_event_t evt, vm_event_callback_t cb)164vm_t& vm_tool_dispatch_t::get_vm_instance() const
165{
166 return _vm;
167}
168
169cookie_t vm_tool_dispatch_t::subscribe_event(vm_event_t evt, vm_event_callback_t cb)
154{170{
155 if (!cb)171 if (!cb)
156 throw vm_system_exception{ "Invalid callback for event" };172 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
172 return cookie_id;188 return cookie_id;
173}189}
174 190
175void vm_tool_dispatch_t::unsubscribe_event(std::size_t cookie_id)191void vm_tool_dispatch_t::unsubscribe_event(cookie_t cookie_id)
176{192{
177 std::lock_guard<std::mutex> lock{ _events.lock };193 std::lock_guard<std::mutex> lock{ _events.lock };
178 194
@@ -190,7 +206,7 @@ void vm_tool_dispatch_t::unsubscribe_event(std::size_t cookie_id) · 11 unmodified lines
190 debug::log_msg(debug::component_trace_t::tool, debug::log_level_t::debug, "unsubscribe: event: %d %d", evt, cookie_id);206 debug::log_msg(debug::component_trace_t::tool, debug::log_level_t::debug, "unsubscribe: event: %d %d", evt, cookie_id);
191}207}
192 208
193std::size_t vm_tool_dispatch_t::set_breakpoint(std::shared_ptr<vm_module_t> module, vm_pc_t pc)209cookie_t vm_tool_dispatch_t::set_breakpoint(std::shared_ptr<vm_module_t> module, vm_pc_t pc)
194{210{
195 if (module == nullptr || util::has_flag(module->header.runtime_flag, runtime_flags_t::builtin))211 if (module == nullptr || util::has_flag(module->header.runtime_flag, runtime_flags_t::builtin))
196 throw vm_system_exception{ "Unable to set breakpoint in supplied module" };212 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
209 const auto cookie_id = _breakpoints.cookie_counter++;225 const auto cookie_id = _breakpoints.cookie_counter++;
210 226
211 // Map the cookie to the module/pc pair.227 // 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 };
213 229
214 // Record the original opcode230 // Record the original opcode
215 auto &pc_map = _breakpoints.original_opcodes[reinterpret_cast<std::uintptr_t>(module.get())];231 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
225 }241 }
226}242}
227 243
228void vm_tool_dispatch_t::clear_breakpoint(std::size_t cookie_id)244breakpoint_details_t vm_tool_dispatch_t::get_breakpoint_details(cookie_t cookie_id) const
229{245{
230 std::lock_guard<std::mutex> lock{ _breakpoints.lock };246 std::lock_guard<std::mutex> lock{ _breakpoints.lock };
231 247
232 // Resolve the cookie to the module/pc pair248 auto iter_cookie = _breakpoints.cookie_to_details.find(cookie_id);
233 auto iter_cookie = _breakpoints.cookie_to_modulepc.find(cookie_id);249 if (iter_cookie == _breakpoints.cookie_to_details.cend())
234 if (iter_cookie == _breakpoints.cookie_to_modulepc.cend())250 throw vm_system_exception{ "Unknown breakpoint cookie" };
235 return;251
252 return iter_cookie->second;
253}
254
255void 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" };
236 262
237 auto mod_pc_pair = iter_cookie->second;263 auto details = iter_cookie->second;
238 const auto target_pc = mod_pc_pair.second;264 const auto target_pc = details.pc;
239 265
240 // Determine the original opcode266 // 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()));
242 assert(iter_orig != _breakpoints.original_opcodes.cend());268 assert(iter_orig != _breakpoints.original_opcodes.cend());
243 269
244 auto &pc_map = iter_orig->second;270 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
248 auto original_opcode = iter_pc->second.first;274 auto original_opcode = iter_pc->second.first;
249 275
250 // Replace the breakpoint opcode with the original276 // 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);
252 assert(code_section[target_pc].op.opcode == opcode_t::brkpt);278 assert(code_section[target_pc].op.opcode == opcode_t::brkpt);
253 code_section[target_pc].op.opcode = original_opcode;279 code_section[target_pc].op.opcode = original_opcode;
254 280
255 if (debug::is_component_tracing_enabled<debug::component_trace_t::tool>())281 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());
257 283
258 // Clean-up the PC mapping to opcode284 // Clean-up the PC mapping to opcode
259 pc_map.erase(iter_pc);285 pc_map.erase(iter_pc);
@@ -263,10 +289,10 @@ void vm_tool_dispatch_t::clear_breakpoint(std::size_t cookie_id) · 3 unmodified lines
263 _breakpoints.original_opcodes.erase(iter_orig);289 _breakpoints.original_opcodes.erase(iter_orig);
264 290
265 // Remove the cookie map291 // Remove the cookie map
266 _breakpoints.cookie_to_modulepc.erase(iter_cookie);292 _breakpoints.cookie_to_details.erase(iter_cookie);
267}293}
268 294
269std::tuple<opcode_t, std::size_t> vm_tool_dispatch_t::get_original_opcode(const vm_registers_t &r)295std::tuple<opcode_t, cookie_t> vm_tool_dispatch_t::get_original_opcode_and_cookie(const vm_registers_t &r)
270{296{
271 const auto module = r.module_ref->module.get();297 const auto module = r.module_ref->module.get();
272 const auto current_pc = r.pc - 1;298 const auto current_pc = r.pc - 1;