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
139 139
140 register_string140 register_string
141 << " Thread ID: " << r.thread.get_thread_id() << "\n"141 << " 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"
143 << " Opcode: " << r.module_ref->code_section[r.pc].op << "\n";143 << " Opcode: " << r.module_ref->code_section[r.pc].op << "\n";
144 144
145 return register_string.str();145 return register_string.str();
@@ -389,14 +389,7 @@ namespace · 243 unmodified lines
389 if (pc < 0 || module->code_section.size() <= static_cast<std::size_t>(pc))389 if (pc < 0 || module->code_section.size() <= static_cast<std::size_t>(pc))
390 throw debug_cmd_error_t{ "Invalid IP for module" };390 throw debug_cmd_error_t{ "Invalid IP for module" };
391 391
392 try392 cxt.dbg.breakpoint_cookies.emplace(cxt.dbg.controller->set_breakpoint(module, pc));
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 }
400 }393 }
401 394
402 void cmd_breakpoint_clear(const std::vector<std::string> &a, dbg_cmd_cxt_t &cxt)395 void cmd_breakpoint_clear(const std::vector<std::string> &a, dbg_cmd_cxt_t &cxt)
@@ -880,14 +873,14 @@ namespace · 477 unmodified lines
880 873
881std::ostream& operator<<(std::ostream &ss, const debugger_options o)874std::ostream& operator<<(std::ostream &ss, const debugger_options o)
882{875{
883 ss << "Break on enter: " << std::boolalpha << o.break_on_enter << "\n"876 ss << "Break on enter: " << std::boolalpha << util::has_flag(o, debugger_options::break_on_enter) << "\n"
884 << "Break on module load: " << std::boolalpha << o.break_on_module_load << "\n"877 << "Break on module load: " << std::boolalpha << util::has_flag(o, debugger_options::break_on_module_load) << "\n"
885 << "Break on exception: " << std::boolalpha << o.break_on_exception << "\n";878 << "Break on exception: " << std::boolalpha << util::has_flag(o, debugger_options::break_on_exception) << "\n";
886 879
887 return ss;880 return ss;
888}881}
889 882
890debugger::debugger(const debugger_options &opt)883debugger::debugger(const debugger_options opt)
891 : _options{ opt }884 : _options{ opt }
892 , _tool_id{ 0 }885 , _tool_id{ 0 }
893 , controller{ nullptr }886 , controller{ nullptr }
@@ -898,7 +891,7 @@ void debugger::on_load(vm_tool_controller_t &controller_, std::size_t tool_id) · 4 unmodified lines
898 _tool_id = tool_id;891 _tool_id = tool_id;
899 controller = &controller_;892 controller = &controller_;
900 893
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)
902 {895 {
903 auto t = cxt.value1.thread;896 auto t = cxt.value1.thread;
904 auto ss = std::stringstream{};897 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
912 debug_print_info(ss.str());905 debug_print_info(ss.str());
913 }));906 }));
914 907
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)
916 {909 {
917 auto ss = std::stringstream{};910 auto ss = std::stringstream{};
918 ss << "Thread "911 ss << "Thread "
@@ -922,7 +915,7 @@ void debugger::on_load(vm_tool_controller_t &controller_, std::size_t tool_id) · 3 unmodified lines
922 debug_print_info(ss.str());915 debug_print_info(ss.str());
923 }));916 }));
924 917
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)
926 {919 {
927 auto ss = std::stringstream{};920 auto ss = std::stringstream{};
928 ss << "Exception '"921 ss << "Exception '"
@@ -931,11 +924,11 @@ void debugger::on_load(vm_tool_controller_t &controller_, std::size_t tool_id) · 2 unmodified lines
931 924
932 debug_print_info(ss.str());925 debug_print_info(ss.str());
933 926
934 if (_options.break_on_exception)927 if (util::has_flag(_options, debugger_options::break_on_exception))
935 prompt(*this, *cxt.value1.registers);928 prompt(*this, *cxt.value1.registers);
936 }));929 }));
937 930
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)
939 {932 {
940 auto ss = std::stringstream{};933 auto ss = std::stringstream{};
941 ss << "Unhandled exception '"934 ss << "Unhandled exception '"
@@ -946,7 +939,7 @@ void debugger::on_load(vm_tool_controller_t &controller_, std::size_t tool_id) · 4 unmodified lines
946 prompt(*this, *cxt.value1.registers);939 prompt(*this, *cxt.value1.registers);
947 }));940 }));
948 941
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)
950 {943 {
951 auto m = (*cxt.value2.module);944 auto m = (*cxt.value2.module);
952 auto ss = std::stringstream{};945 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
961 954
962 // If the break on enter flag was set, it will be true955 // If the break on enter flag was set, it will be true
963 // and the first module load will be the user entry module.956 // 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))
965 {958 {
966 // Reset the break on enter flag and set a breakpoint959 // Reset the break on enter flag and set a breakpoint
967 // on the entry PC for the module - 'break on enter'960 // on the entry PC for the module - 'break on enter'
968 _options.break_on_enter = false;961 _options ^= debugger_options::break_on_enter;
969 controller->set_breakpoint(m, m->header.entry_pc);962 controller->set_breakpoint(m, m->header.entry_pc);
970 }963 }
971 964
972 if (_options.break_on_module_load)965 if (util::has_flag(_options, debugger_options::break_on_module_load))
973 prompt(*this, *cxt.value1.registers);966 prompt(*this, *cxt.value1.registers);
974 }));967 }));
975 968
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)
977 {970 {
978 auto ss = std::stringstream{};971 auto ss = std::stringstream{};
979 ss << "Breakpoint hit";972 ss << "Breakpoint hit";
src/exec/exec.h+12−8
@@ -8,23 +8,27 @@ · 7 unmodified lines
8#define _DISVM_SRC_EXEC_EXEC_H_8#define _DISVM_SRC_EXEC_EXEC_H_
9 9
10#include <cstdint>10#include <cstdint>
11#include <vector>11#include <unordered_set>
12#include <disvm.h>12#include <disvm.h>
13#include <vm_tools.h>13#include <vm_tools.h>
14#include <utils.h>
14 15
15struct debugger_options16enum class debugger_options
16{17{
17 bool break_on_enter;18 none = 0,
18 bool break_on_module_load;19 break_on_enter = 1,
19 bool break_on_exception;20 break_on_module_load = 2,
21 break_on_exception = 4,
20};22};
21 23
24DEFINE_ENUM_FLAG_OPERATORS(debugger_options);
25
22std::ostream& operator<<(std::ostream &ss, const debugger_options o);26std::ostream& operator<<(std::ostream &ss, const debugger_options o);
23 27
24class debugger final : public disvm::runtime::vm_tool_t28class debugger final : public disvm::runtime::vm_tool_t
25{29{
26public:30public:
27 debugger(const debugger_options &);31 debugger(const debugger_options);
28 32
29public: // vm_tool_t33public: // vm_tool_t
30 void on_load(disvm::runtime::vm_tool_controller_t &, std::size_t tool_id) override;34 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
33 37
34public:38public:
35 disvm::runtime::vm_tool_controller_t *controller;39 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;
37 41
38private:42private:
39 debugger_options _options;43 debugger_options _options;
40 std::size_t _tool_id;44 std::size_t _tool_id;
41 std::vector<disvm::runtime::cookie_t> _event_cookies;45 std::unordered_set<disvm::runtime::cookie_t> _event_cookies;
42};46};
43 47
44#endif // _DISVM_SRC_EXEC_EXEC_H_48#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
195struct exec_options195struct exec_options
196{196{
197 exec_options()197 exec_options()
198 : debugger{}198 : debugger{ debugger_options::none }
199 , enabled_debugger{ false }199 , enabled_debugger{ false }
200 , quiet_start{ false }200 , quiet_start{ false }
201 , print_help{ false }201 , print_help{ false }
@@ -227,7 +227,7 @@ void print_banner(const exec_options &options) · 25 unmodified lines
227 << "System thread usage: " << options.sys_thread_count << "\n";227 << "System thread usage: " << options.sys_thread_count << "\n";
228 228
229 if (options.enabled_debugger)229 if (options.enabled_debugger)
230 std::cout << options.debugger << "\n";230 std::cout << "\n" << options.debugger << "\n";
231 231
232 std::cout << std::endl;232 std::cout << std::endl;
233}233}
@@ -268,11 +268,11 @@ void process_arg(char* arg, std::function<char *()> next, exec_options &options) · 34 unmodified lines
268 {268 {
269 switch (arg[i])269 switch (arg[i])
270 {270 {
271 case 'e': options.debugger.break_on_enter = true;271 case 'e': options.debugger |= debugger_options::break_on_enter;
272 break;272 break;
273 case 'm': options.debugger.break_on_module_load = true;273 case 'm': options.debugger |= debugger_options::break_on_module_load;
274 break;274 break;
275 case 'x': options.debugger.break_on_exception = true;275 case 'x': options.debugger |= debugger_options::break_on_exception;
276 break;276 break;
277 }277 }
278 }278 }
src/vm/sys/print.cpp+1−0
@@ -71,6 +71,7 @@ word_t disvm::runtime::sys::printf_to_buffer( · 70 unmodified lines
71 {71 {
72 // Format flags72 // Format flags
73 default:73 default:
74 format.push_back(static_cast<char>(c));
74 continue;75 continue;
75 case 'b': // Print big type (64-bit)76 case 'b': // Print big type (64-bit)
76 format.push_back('l');77 format.push_back('l');
src/vm/sys/sys_utils.h+3−3
@@ -38,9 +38,9 @@ namespace disvm · 37 unmodified lines
38 38
39 enum class cfs_flags_t39 enum class cfs_flags_t
40 {40 {
41 none,41 none = 0,
42 atomic,42 atomic = 1,
43 ensure_create,43 ensure_create = 2,
44 };44 };
45 45
46 DEFINE_ENUM_FLAG_OPERATORS(cfs_flags_t);46 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
245 245
246 {246 {
247 std::lock_guard<std::mutex> lock{ _breakpoints.lock };247 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.
248 if (real_opcode == opcode_t::brkpt)251 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 }
250 257
251 const auto cookie_id = _breakpoints.cookie_counter++;258 const auto cookie_id = _breakpoints.cookie_counter++;
252 259
@@ -254,7 +261,6 @@ cookie_t vm_tool_dispatch_t::set_breakpoint(std::shared_ptr<vm_module_t> module, · 1 unmodified line
254 _breakpoints.cookie_to_details[cookie_id] = { module, pc, real_opcode };261 _breakpoints.cookie_to_details[cookie_id] = { module, pc, real_opcode };
255 262
256 // Record the original opcode263 // Record the original opcode
257 auto &pc_map = _breakpoints.original_opcodes[reinterpret_cast<std::uintptr_t>(module.get())];
258 pc_map[pc] = std::make_pair(real_opcode, cookie_id);264 pc_map[pc] = std::make_pair(real_opcode, cookie_id);
259 265
260 // Replace the current opcode with breakpoint266 // Replace the current opcode with breakpoint