History

Change debugger options to enumeration. Alter how the debugger displays the registers. Adding a breakpoint that is already set is a no-op and simply returns the current cookie value. Fix bug in print for the Sys module - don't ignore format modifiers.

arr committed 10 years ago

Commit db76c0c1 parent f29cf0d6 files · +45 −41Browse files

Unified · Split

6 files
  1. src/exec/debugger.cpp +16 −23
  2. src/exec/exec.h +12 −8
  3. src/exec/main.cpp +5 −5
  4. src/vm/sys/print.cpp +1 −0
  5. src/vm/sys/sys_utils.h +3 −3
  6. src/vm/tool_dispatch.cpp +8 −2
src/exec/debugger.cpp+16−23
@@ -139,7 +139,7 @@ namespace · 138 unmodified lines
139139
140140 register_string
141141 << " Thread ID: " << r.thread.get_thread_id() << "\n"
142− << " Module: " << r.module_ref->module->module_name->str() << " PC: " << r.pc << "\n"
142+ << " PC: " << r.pc << " Module: " << r.module_ref->module->module_name->str() << "\n"
143143 << " Opcode: " << r.module_ref->code_section[r.pc].op << "\n";
144144
145145 return register_string.str();
@@ -389,14 +389,7 @@ namespace · 243 unmodified lines
389389 if (pc < 0 || module->code_section.size() <= static_cast<std::size_t>(pc))
390390 throw debug_cmd_error_t{ "Invalid IP for module" };
391391
392− try
393− {
394− cxt.dbg.breakpoint_cookies.push_back(cxt.dbg.controller->set_breakpoint(module, pc));
395− }
396− catch (const vm_system_exception& e)
397− {
398− throw debug_cmd_error_t{ e.what() };
399− }
392+ cxt.dbg.breakpoint_cookies.emplace(cxt.dbg.controller->set_breakpoint(module, pc));
400393 }
401394
402395 void cmd_breakpoint_clear(const std::vector<std::string> &a, dbg_cmd_cxt_t &cxt)
@@ -880,14 +873,14 @@ namespace · 477 unmodified lines
880873
881874 std::ostream& operator<<(std::ostream &ss, const debugger_options o)
882875 {
883− ss << "Break on enter: " << std::boolalpha << o.break_on_enter << "\n"
884− << "Break on module load: " << std::boolalpha << o.break_on_module_load << "\n"
885− << "Break on exception: " << std::boolalpha << o.break_on_exception << "\n";
876+ ss << "Break on enter: " << std::boolalpha << util::has_flag(o, debugger_options::break_on_enter) << "\n"
877+ << "Break on module load: " << std::boolalpha << util::has_flag(o, debugger_options::break_on_module_load) << "\n"
878+ << "Break on exception: " << std::boolalpha << util::has_flag(o, debugger_options::break_on_exception) << "\n";
886879
887880 return ss;
888881 }
889882
890−debugger::debugger(const debugger_options &opt)
883+debugger::debugger(const debugger_options opt)
891884 : _options{ opt }
892885 , _tool_id{ 0 }
893886 , controller{ nullptr }
@@ -898,7 +891,7 @@ void debugger::on_load(vm_tool_controller_t &controller_, std::size_t tool_id) · 4 unmodified lines
898891 _tool_id = tool_id;
899892 controller = &controller_;
900893
901− _event_cookies.push_back(controller->subscribe_event(vm_event_t::thread_begin, [](vm_event_t, vm_event_context_t &cxt)
894+ _event_cookies.emplace(controller->subscribe_event(vm_event_t::thread_begin, [](vm_event_t, vm_event_context_t &cxt)
902895 {
903896 auto t = cxt.value1.thread;
904897 auto ss = std::stringstream{};
@@ -912,7 +905,7 @@ void debugger::on_load(vm_tool_controller_t &controller_, std::size_t tool_id) · 7 unmodified lines
912905 debug_print_info(ss.str());
913906 }));
914907
915− _event_cookies.push_back(controller->subscribe_event(vm_event_t::thread_end, [](vm_event_t, vm_event_context_t &cxt)
908+ _event_cookies.emplace(controller->subscribe_event(vm_event_t::thread_end, [](vm_event_t, vm_event_context_t &cxt)
916909 {
917910 auto ss = std::stringstream{};
918911 ss << "Thread "
@@ -922,7 +915,7 @@ void debugger::on_load(vm_tool_controller_t &controller_, std::size_t tool_id) · 3 unmodified lines
922915 debug_print_info(ss.str());
923916 }));
924917
925− _event_cookies.push_back(controller->subscribe_event(vm_event_t::exception_raised, [&](vm_event_t, vm_event_context_t &cxt)
918+ _event_cookies.emplace(controller->subscribe_event(vm_event_t::exception_raised, [&](vm_event_t, vm_event_context_t &cxt)
926919 {
927920 auto ss = std::stringstream{};
928921 ss << "Exception '"
@@ -931,11 +924,11 @@ void debugger::on_load(vm_tool_controller_t &controller_, std::size_t tool_id) · 2 unmodified lines
931924
932925 debug_print_info(ss.str());
933926
934− if (_options.break_on_exception)
927+ if (util::has_flag(_options, debugger_options::break_on_exception))
935928 prompt(*this, *cxt.value1.registers);
936929 }));
937930
938− _event_cookies.push_back(controller->subscribe_event(vm_event_t::exception_unhandled, [&](vm_event_t, vm_event_context_t &cxt)
931+ _event_cookies.emplace(controller->subscribe_event(vm_event_t::exception_unhandled, [&](vm_event_t, vm_event_context_t &cxt)
939932 {
940933 auto ss = std::stringstream{};
941934 ss << "Unhandled exception '"
@@ -946,7 +939,7 @@ void debugger::on_load(vm_tool_controller_t &controller_, std::size_t tool_id) · 4 unmodified lines
946939 prompt(*this, *cxt.value1.registers);
947940 }));
948941
949− _event_cookies.push_back(controller->subscribe_event(vm_event_t::module_thread_load, [&](vm_event_t, vm_event_context_t &cxt)
942+ _event_cookies.emplace(controller->subscribe_event(vm_event_t::module_thread_load, [&](vm_event_t, vm_event_context_t &cxt)
950943 {
951944 auto m = (*cxt.value2.module);
952945 auto ss = std::stringstream{};
@@ -961,19 +954,19 @@ void debugger::on_load(vm_tool_controller_t &controller_, std::size_t tool_id) · 8 unmodified lines
961954
962955 // If the break on enter flag was set, it will be true
963956 // and the first module load will be the user entry module.
964− if (_options.break_on_enter)
957+ if (util::has_flag(_options, debugger_options::break_on_enter))
965958 {
966959 // Reset the break on enter flag and set a breakpoint
967960 // on the entry PC for the module - 'break on enter'
968− _options.break_on_enter = false;
961+ _options ^= debugger_options::break_on_enter;
969962 controller->set_breakpoint(m, m->header.entry_pc);
970963 }
971964
972− if (_options.break_on_module_load)
965+ if (util::has_flag(_options, debugger_options::break_on_module_load))
973966 prompt(*this, *cxt.value1.registers);
974967 }));
975968
976− _event_cookies.push_back(controller->subscribe_event(vm_event_t::breakpoint, [&](vm_event_t, vm_event_context_t &cxt)
969+ _event_cookies.emplace(controller->subscribe_event(vm_event_t::breakpoint, [&](vm_event_t, vm_event_context_t &cxt)
977970 {
978971 auto ss = std::stringstream{};
979972 ss << "Breakpoint hit";
src/exec/exec.h+12−8
@@ -8,23 +8,27 @@ · 7 unmodified lines
88 #define _DISVM_SRC_EXEC_EXEC_H_
99
1010 #include <cstdint>
11−#include <vector>
11+#include <unordered_set>
1212 #include <disvm.h>
1313 #include <vm_tools.h>
14+#include <utils.h>
1415
15−struct debugger_options
16+enum class debugger_options
1617 {
17− bool break_on_enter;
18− bool break_on_module_load;
19− bool break_on_exception;
18+ none = 0,
19+ break_on_enter = 1,
20+ break_on_module_load = 2,
21+ break_on_exception = 4,
2022 };
2123
24+DEFINE_ENUM_FLAG_OPERATORS(debugger_options);
25+
2226 std::ostream& operator<<(std::ostream &ss, const debugger_options o);
2327
2428 class debugger final : public disvm::runtime::vm_tool_t
2529 {
2630 public:
27− debugger(const debugger_options &);
31+ debugger(const debugger_options);
2832
2933 public: // vm_tool_t
3034 void on_load(disvm::runtime::vm_tool_controller_t &, std::size_t tool_id) override;
@@ -33,12 +37,12 @@ public: // vm_tool_t · 2 unmodified lines
3337
3438 public:
3539 disvm::runtime::vm_tool_controller_t *controller;
36− std::vector<disvm::runtime::cookie_t> breakpoint_cookies;
40+ std::unordered_set<disvm::runtime::cookie_t> breakpoint_cookies;
3741
3842 private:
3943 debugger_options _options;
4044 std::size_t _tool_id;
41− std::vector<disvm::runtime::cookie_t> _event_cookies;
45+ std::unordered_set<disvm::runtime::cookie_t> _event_cookies;
4246 };
4347
4448 #endif // _DISVM_SRC_EXEC_EXEC_H_
src/exec/main.cpp+5−5
@@ -195,7 +195,7 @@ struct arg_exception_t : std::runtime_error · 194 unmodified lines
195195 struct exec_options
196196 {
197197 exec_options()
198− : debugger{}
198+ : debugger{ debugger_options::none }
199199 , enabled_debugger{ false }
200200 , quiet_start{ false }
201201 , print_help{ false }
@@ -227,7 +227,7 @@ void print_banner(const exec_options &options) · 25 unmodified lines
227227 << "System thread usage: " << options.sys_thread_count << "\n";
228228
229229 if (options.enabled_debugger)
230− std::cout << options.debugger << "\n";
230+ std::cout << "\n" << options.debugger << "\n";
231231
232232 std::cout << std::endl;
233233 }
@@ -268,11 +268,11 @@ void process_arg(char* arg, std::function<char *()> next, exec_options &options) · 34 unmodified lines
268268 {
269269 switch (arg[i])
270270 {
271− case 'e': options.debugger.break_on_enter = true;
271+ case 'e': options.debugger |= debugger_options::break_on_enter;
272272 break;
273− case 'm': options.debugger.break_on_module_load = true;
273+ case 'm': options.debugger |= debugger_options::break_on_module_load;
274274 break;
275− case 'x': options.debugger.break_on_exception = true;
275+ case 'x': options.debugger |= debugger_options::break_on_exception;
276276 break;
277277 }
278278 }
src/vm/sys/print.cpp+1−0
@@ -71,6 +71,7 @@ word_t disvm::runtime::sys::printf_to_buffer( · 70 unmodified lines
7171 {
7272 // Format flags
7373 default:
74+ format.push_back(static_cast<char>(c));
7475 continue;
7576 case 'b': // Print big type (64-bit)
7677 format.push_back('l');
src/vm/sys/sys_utils.h+3−3
@@ -38,9 +38,9 @@ namespace disvm · 37 unmodified lines
3838
3939 enum class cfs_flags_t
4040 {
41− none,
42− atomic,
43− ensure_create,
41+ none = 0,
42+ atomic = 1,
43+ ensure_create = 2,
4444 };
4545
4646 DEFINE_ENUM_FLAG_OPERATORS(cfs_flags_t);
src/vm/tool_dispatch.cpp+8−2
@@ -245,8 +245,15 @@ cookie_t vm_tool_dispatch_t::set_breakpoint(std::shared_ptr<vm_module_t> module, · 244 unmodified lines
245245
246246 {
247247 std::lock_guard<std::mutex> lock{ _breakpoints.lock };
248+ auto &pc_map = _breakpoints.original_opcodes[reinterpret_cast<std::uintptr_t>(module.get())];
249+
250+ // If the real opcode is already a breakpoint and it is known, return the current cookie.
248251 if (real_opcode == opcode_t::brkpt)
249− throw vm_system_exception{ "Breakpoint already set at PC" };
252+ {
253+ auto iter = pc_map.find(pc);
254+ if (iter != pc_map.cend())
255+ return iter->second.second;
256+ }
250257
251258 const auto cookie_id = _breakpoints.cookie_counter++;
252259
@@ -254,7 +261,6 @@ cookie_t vm_tool_dispatch_t::set_breakpoint(std::shared_ptr<vm_module_t> module, · 1 unmodified line
254261 _breakpoints.cookie_to_details[cookie_id] = { module, pc, real_opcode };
255262
256263 // Record the original opcode
257− auto &pc_map = _breakpoints.original_opcodes[reinterpret_cast<std::uintptr_t>(module.get())];
258264 pc_map[pc] = std::make_pair(real_opcode, cookie_id);
259265
260266 // Replace the current opcode with breakpoint