Remove tabs from all logging
Unified · Split
| @@ -13,6 +13,7 @@ · 12 unmodified lines | |||
| 13 | #include <utils.h> | 13 | #include <utils.h> |
| 14 | #include <vm_memory.h> | 14 | #include <vm_memory.h> |
| 15 | #include <vm_asm.h> | 15 | #include <vm_asm.h> |
| 16 | #include <exceptions.h> | ||
| 16 | #include "exec.h" | 17 | #include "exec.h" |
| 17 | 18 | ||
| 18 | using namespace disvm; | 19 | using namespace disvm; |
| @@ -289,6 +290,11 @@ namespace · 270 unmodified lines | |||
| 289 | cxt.exit_break = true; | 290 | cxt.exit_break = true; |
| 290 | } | 291 | } |
| 291 | 292 | ||
| 293 | void cmd_term(const std::vector<std::string> &, dbg_cmd_cxt_t &cxt) | ||
| 294 | { | ||
| 295 | throw vm_user_exception{ "Debugger signaled VM termination" }; | ||
| 296 | } | ||
| 297 | |||
| 292 | void cmd_print_registers(const std::vector<std::string> &, dbg_cmd_cxt_t &cxt) | 298 | void cmd_print_registers(const std::vector<std::string> &, dbg_cmd_cxt_t &cxt) |
| 293 | { | 299 | { |
| 294 | auto s = registers_to_string(*cxt.current_register); | 300 | auto s = registers_to_string(*cxt.current_register); |
| @@ -740,6 +746,7 @@ namespace · 445 unmodified lines | |||
| 740 | const dbg_cmd_t cmds[] = | 746 | const dbg_cmd_t cmds[] = |
| 741 | { | 747 | { |
| 742 | { "c", "Continue", nullptr, nullptr, cmd_continue }, | 748 | { "c", "Continue", nullptr, nullptr, cmd_continue }, |
| 749 | { "term", "Terminate the VM instance", nullptr, nullptr, cmd_term }, | ||
| 743 | 750 | ||
| 744 | { "r", "Print registers", nullptr, nullptr, cmd_print_registers }, | 751 | { "r", "Print registers", nullptr, nullptr, cmd_print_registers }, |
| 745 | { "t", "Print all threads", nullptr, nullptr, cmd_print_threads }, | 752 | { "t", "Print all threads", nullptr, nullptr, cmd_print_threads }, |
| @@ -862,8 +869,18 @@ namespace · 116 unmodified lines | |||
| 862 | } | 869 | } |
| 863 | } | 870 | } |
| 864 | 871 | ||
| 865 | debugger::debugger() | 872 | std::ostream& operator<<(std::ostream &ss, const debugger_options o) |
| 866 | : _tool_id{ 0 } | 873 | { |
| 874 | ss << "Break on enter: " << std::boolalpha << o.break_on_enter << "\n" | ||
| 875 | << "Break on module load: " << std::boolalpha << o.break_on_module_load << "\n" | ||
| 876 | << "Break on exception: " << std::boolalpha << o.break_on_exception << "\n"; | ||
| 877 | |||
| 878 | return ss; | ||
| 879 | } | ||
| 880 | |||
| 881 | debugger::debugger(const debugger_options &opt) | ||
| 882 | : _options{ opt } | ||
| 883 | , _tool_id{ 0 } | ||
| 867 | , controller{ nullptr } | 884 | , controller{ nullptr } |
| 868 | { } | 885 | { } |
| 869 | 886 | ||
| @@ -896,7 +913,7 @@ void debugger::on_load(vm_tool_controller_t &controller_, std::size_t tool_id) · 26 unmodified lines | |||
| 896 | debug_print_info(ss.str()); | 913 | debug_print_info(ss.str()); |
| 897 | })); | 914 | })); |
| 898 | 915 | ||
| 899 | _event_cookies.push_back(controller->subscribe_event(vm_event_t::exception_raised, [](vm_event_t, vm_event_context_t &cxt) | 916 | _event_cookies.push_back(controller->subscribe_event(vm_event_t::exception_raised, [&](vm_event_t, vm_event_context_t &cxt) |
| 900 | { | 917 | { |
| 901 | auto ss = std::stringstream{}; | 918 | auto ss = std::stringstream{}; |
| 902 | ss << "Exception '" | 919 | ss << "Exception '" |
| @@ -904,6 +921,9 @@ void debugger::on_load(vm_tool_controller_t &controller_, std::size_t tool_id) · 1 unmodified line | |||
| 904 | << "' thrown."; | 921 | << "' thrown."; |
| 905 | 922 | ||
| 906 | debug_print_info(ss.str()); | 923 | debug_print_info(ss.str()); |
| 924 | |||
| 925 | if (_options.break_on_exception) | ||
| 926 | prompt(*this, *cxt.value1.registers); | ||
| 907 | })); | 927 | })); |
| 908 | 928 | ||
| 909 | _event_cookies.push_back(controller->subscribe_event(vm_event_t::exception_unhandled, [&](vm_event_t, vm_event_context_t &cxt) | 929 | _event_cookies.push_back(controller->subscribe_event(vm_event_t::exception_unhandled, [&](vm_event_t, vm_event_context_t &cxt) |
| @@ -928,8 +948,20 @@ void debugger::on_load(vm_tool_controller_t &controller_, std::size_t tool_id) · 18 unmodified lines | |||
| 928 | if (util::has_flag(m->header.runtime_flag, runtime_flags_t::builtin)) | 948 | if (util::has_flag(m->header.runtime_flag, runtime_flags_t::builtin)) |
| 929 | ss << " (built-in)"; | 949 | ss << " (built-in)"; |
| 930 | 950 | ||
| 931 | |||
| 932 | debug_print_info(ss.str()); | 951 | debug_print_info(ss.str()); |
| 952 | |||
| 953 | // If the break on enter flag was set, it will be true | ||
| 954 | // and the first module load will be the user entry module. | ||
| 955 | if (_options.break_on_enter) | ||
| 956 | { | ||
| 957 | // Reset the break on enter flag and set a breakpoint | ||
| 958 | // on the entry PC for the module - 'break on enter' | ||
| 959 | _options.break_on_enter = false; | ||
| 960 | controller->set_breakpoint(m, m->header.entry_pc); | ||
| 961 | } | ||
| 962 | |||
| 963 | if (_options.break_on_module_load) | ||
| 964 | prompt(*this, *cxt.value1.registers); | ||
| 933 | })); | 965 | })); |
| 934 | 966 | ||
| 935 | _event_cookies.push_back(controller->subscribe_event(vm_event_t::breakpoint, [&](vm_event_t, vm_event_context_t &cxt) | 967 | _event_cookies.push_back(controller->subscribe_event(vm_event_t::breakpoint, [&](vm_event_t, vm_event_context_t &cxt) |
| @@ -12,13 +12,22 @@ · 11 unmodified lines | |||
| 12 | #include <disvm.h> | 12 | #include <disvm.h> |
| 13 | #include <vm_tools.h> | 13 | #include <vm_tools.h> |
| 14 | 14 | ||
| 15 | struct debugger_options | ||
| 16 | { | ||
| 17 | bool break_on_enter; | ||
| 18 | bool break_on_module_load; | ||
| 19 | bool break_on_exception; | ||
| 20 | }; | ||
| 21 | |||
| 22 | std::ostream& operator<<(std::ostream &ss, const debugger_options o); | ||
| 23 | |||
| 15 | class debugger final : public disvm::runtime::vm_tool_t | 24 | class debugger final : public disvm::runtime::vm_tool_t |
| 16 | { | 25 | { |
| 17 | public: | 26 | public: |
| 18 | debugger(); | 27 | debugger(const debugger_options &); |
| 19 | 28 | ||
| 20 | public: // vm_tool_t | 29 | public: // vm_tool_t |
| 21 | void on_load(disvm::runtime::vm_tool_controller_t &controller, std::size_t tool_id) override; | 30 | void on_load(disvm::runtime::vm_tool_controller_t &, std::size_t tool_id) override; |
| 22 | 31 | ||
| 23 | void on_unload() override; | 32 | void on_unload() override; |
| 24 | 33 | ||
| @@ -27,6 +36,7 @@ public: · 2 unmodified lines | |||
| 27 | std::vector<disvm::runtime::cookie_t> breakpoint_cookies; | 36 | std::vector<disvm::runtime::cookie_t> breakpoint_cookies; |
| 28 | 37 | ||
| 29 | private: | 38 | private: |
| 39 | debugger_options _options; | ||
| 30 | std::size_t _tool_id; | 40 | std::size_t _tool_id; |
| 31 | std::vector<disvm::runtime::cookie_t> _event_cookies; | 41 | std::vector<disvm::runtime::cookie_t> _event_cookies; |
| 32 | }; | 42 | }; |
| @@ -30,10 +30,14 @@ namespace · 29 unmodified lines | |||
| 30 | 30 | ||
| 31 | std::shared_ptr<const vm_module_t> command_module; | 31 | std::shared_ptr<const vm_module_t> command_module; |
| 32 | 32 | ||
| 33 | std::unique_ptr<vm_module_t> create_entry_module(vm_t &vm, int argc, char* argv[]) | 33 | std::unique_ptr<vm_module_t> create_entry_module(vm_t &vm, const std::vector<char *> &vm_args) |
| 34 | { | 34 | { |
| 35 | if (vm_args.size() == 0) | ||
| 36 | throw vm_user_exception{ "Entry module not supplied" }; | ||
| 37 | |||
| 35 | // First argument is the module to load | 38 | // First argument is the module to load |
| 36 | auto command_module_path = new vm_string_t{ std::strlen(argv[0]), reinterpret_cast<uint8_t *>(argv[0]) }; | 39 | auto entry_module_path = vm_args[0]; |
| 40 | auto command_module_path = new vm_string_t{ std::strlen(entry_module_path), reinterpret_cast<uint8_t *>(entry_module_path) }; | ||
| 37 | 41 | ||
| 38 | // Pre-load the command module in the VM. | 42 | // Pre-load the command module in the VM. |
| 39 | command_module = vm.load_module(command_module_path->str()); | 43 | command_module = vm.load_module(command_module_path->str()); |
| @@ -41,9 +45,9 @@ namespace · 1 unmodified line | |||
| 41 | // Convert arguments to a list | 45 | // Convert arguments to a list |
| 42 | vm_list_t *args = nullptr; | 46 | vm_list_t *args = nullptr; |
| 43 | vm_list_t *last = nullptr; | 47 | vm_list_t *last = nullptr; |
| 44 | for (auto i = 1; i < argc; ++i) | 48 | for (auto i = std::size_t{ 1 }; i < vm_args.size(); ++i) |
| 45 | { | 49 | { |
| 46 | auto tmp = argv[i]; | 50 | auto tmp = vm_args[i]; |
| 47 | auto arg = new vm_string_t{ std::strlen(tmp), reinterpret_cast<uint8_t *>(tmp) }; | 51 | auto arg = new vm_string_t{ std::strlen(tmp), reinterpret_cast<uint8_t *>(tmp) }; |
| 48 | if (args == nullptr) | 52 | if (args == nullptr) |
| 49 | { | 53 | { |
| @@ -165,39 +169,160 @@ namespace · 115 unmodified lines | |||
| 165 | } | 169 | } |
| 166 | } | 170 | } |
| 167 | 171 | ||
| 172 | struct arg_exception_t : std::runtime_error | ||
| 173 | { | ||
| 174 | arg_exception_t(const char *m, const char *arg) | ||
| 175 | : std::runtime_error{ m } | ||
| 176 | , arg{ arg } | ||
| 177 | { } | ||
| 178 | |||
| 179 | const char * const arg; | ||
| 180 | }; | ||
| 181 | |||
| 182 | struct exec_options | ||
| 183 | { | ||
| 184 | std::vector<char *> vm_args; | ||
| 185 | |||
| 186 | bool print_help; | ||
| 187 | bool quiet_start; | ||
| 188 | bool enabled_debugger; | ||
| 189 | debugger_options debugger; | ||
| 190 | }; | ||
| 191 | |||
| 192 | void print_banner(const exec_options &options) | ||
| 193 | { | ||
| 194 | std::cout | ||
| 195 | << "DisVM\n" | ||
| 196 | << "----------------\n" | ||
| 197 | << "Debugger enabled: " << std::boolalpha << options.enabled_debugger << "\n"; | ||
| 198 | |||
| 199 | if (options.enabled_debugger) | ||
| 200 | std::cout << options.debugger << "\n"; | ||
| 201 | |||
| 202 | std::cout << std::endl; | ||
| 203 | } | ||
| 204 | |||
| 205 | void print_help() | ||
| 206 | { | ||
| 207 | std::cout | ||
| 208 | << "Usage: disvm-exec [-d[e|m|x]*] [-q] [-?] <entry module> <args>*\n" | ||
| 209 | << " d - Enable debugger\n" | ||
| 210 | << " e - Break on entry\n" | ||
| 211 | << " m - Break on module load\n" | ||
| 212 | << " x - Break on exception (first chance)\n" | ||
| 213 | << " q - Suppress banner and configuration\n" | ||
| 214 | << " ? - Print help\n"; | ||
| 215 | } | ||
| 216 | |||
| 217 | void process_arg(char* arg, std::function<char *()> next, exec_options &options) | ||
| 218 | { | ||
| 219 | assert(arg != nullptr && next != nullptr); | ||
| 220 | if (arg[0] != '-') | ||
| 221 | { | ||
| 222 | for (; arg != nullptr; arg = next()) | ||
| 223 | options.vm_args.push_back(arg); | ||
| 224 | |||
| 225 | return; | ||
| 226 | } | ||
| 227 | |||
| 228 | auto arg_len = std::strlen(arg); | ||
| 229 | if (arg_len < 2) | ||
| 230 | throw arg_exception_t{ "Invalid flag format", arg }; | ||
| 231 | |||
| 232 | switch (arg[1]) | ||
| 233 | { | ||
| 234 | case 'd': | ||
| 235 | options.enabled_debugger = true; | ||
| 236 | for (auto i = std::size_t{ 2 }; i < arg_len; ++i) | ||
| 237 | { | ||
| 238 | switch (arg[i]) | ||
| 239 | { | ||
| 240 | case 'e': options.debugger.break_on_enter = true; | ||
| 241 | break; | ||
| 242 | case 'm': options.debugger.break_on_module_load = true; | ||
| 243 | break; | ||
| 244 | case 'x': options.debugger.break_on_exception = true; | ||
| 245 | break; | ||
| 246 | } | ||
| 247 | } | ||
| 248 | |||
| 249 | break; | ||
| 250 | |||
| 251 | case 'q': | ||
| 252 | options.quiet_start = true; | ||
| 253 | break; | ||
| 254 | |||
| 255 | case '?': | ||
| 256 | options.print_help = true; | ||
| 257 | break; | ||
| 258 | |||
| 259 | default: | ||
| 260 | throw arg_exception_t{ "Unknown flag", arg }; | ||
| 261 | } | ||
| 262 | } | ||
| 263 | |||
| 168 | int main(int argc, char* argv[]) | 264 | int main(int argc, char* argv[]) |
| 169 | { | 265 | { |
| 170 | // [TODO] Handle command line arguments | 266 | exec_options options = {}; |
| 171 | assert(argc > 1); | 267 | |
| 268 | try | ||
| 269 | { | ||
| 270 | // Ignore the process name | ||
| 271 | auto arg_idx = int{ 1 }; | ||
| 272 | auto next_arg = [&]() | ||
| 273 | { | ||
| 274 | return arg_idx < argc ? argv[arg_idx++] : nullptr; | ||
| 275 | }; | ||
| 276 | |||
| 277 | for (auto curr_arg = next_arg(); curr_arg != nullptr; curr_arg = next_arg()) | ||
| 278 | process_arg(curr_arg, next_arg, options); | ||
| 279 | } | ||
| 280 | catch (const arg_exception_t &ae) | ||
| 281 | { | ||
| 282 | std::cerr << ae.what(); | ||
| 283 | if (ae.arg != nullptr) | ||
| 284 | std::cerr << ": " << ae.arg << std::endl; | ||
| 285 | |||
| 286 | return EXIT_FAILURE; | ||
| 287 | } | ||
| 288 | |||
| 289 | if (!options.quiet_start) | ||
| 290 | print_banner(options); | ||
| 291 | |||
| 292 | if (options.print_help) | ||
| 293 | { | ||
| 294 | print_help(); | ||
| 295 | return EXIT_SUCCESS; | ||
| 296 | } | ||
| 172 | 297 | ||
| 173 | vm_t vm; | 298 | vm_t vm; |
| 174 | 299 | ||
| 175 | //vm.load_tool(std::make_shared<debugger>()); | 300 | if (options.enabled_debugger) |
| 301 | vm.load_tool(std::make_shared<debugger>(options.debugger)); | ||
| 176 | 302 | ||
| 177 | try | 303 | try |
| 178 | { | 304 | { |
| 179 | // Ignore the process name | 305 | auto entry = create_entry_module(vm, options.vm_args); |
| 180 | auto entry = create_entry_module(vm, argc - 1, argv + 1); | ||
| 181 | 306 | ||
| 182 | vm.exec(std::move(entry)); | 307 | vm.exec(std::move(entry)); |
| 183 | 308 | ||
| 184 | vm.spin_sleep_till_idle(std::chrono::milliseconds(100)); | 309 | vm.spin_sleep_till_idle(std::chrono::milliseconds(100)); |
| 185 | } | 310 | } |
| 186 | catch (vm_user_exception &ue) | 311 | catch (const vm_user_exception &ue) |
| 187 | { | 312 | { |
| 188 | std::cout << ue.what() << std::endl; | 313 | std::cerr << ue.what() << std::endl; |
| 189 | 314 | ||
| 190 | return EXIT_FAILURE; | 315 | return EXIT_FAILURE; |
| 191 | } | 316 | } |
| 192 | catch (vm_system_exception &se) | 317 | catch (const vm_system_exception &se) |
| 193 | { | 318 | { |
| 194 | std::cout | 319 | std::cerr |
| 195 | << "Internal exception:\n\t" | 320 | << "Internal exception:\n " |
| 196 | << se.what() | 321 | << se.what() |
| 197 | << std::endl; | 322 | << std::endl; |
| 198 | 323 | ||
| 199 | return EXIT_FAILURE; | 324 | return EXIT_FAILURE; |
| 200 | } | 325 | } |
| 201 | 326 | ||
| 202 | return 0; | 327 | return EXIT_SUCCESS; |
| 203 | } | 328 | } |
| @@ -158,7 +158,7 @@ namespace · 157 unmodified lines | |||
| 158 | add_pointer_to_queue = std::function<void(pointer_t p, std::size_t)>{ [&allocs](pointer_t p, std::size_t) -> void | 158 | add_pointer_to_queue = std::function<void(pointer_t p, std::size_t)>{ [&allocs](pointer_t p, std::size_t) -> void |
| 159 | { | 159 | { |
| 160 | auto a = vm_alloc_t::from_allocation(p); | 160 | auto a = vm_alloc_t::from_allocation(p); |
| 161 | debug::log_msg(debug::component_trace_t::garbage_collector, debug::log_level_t::debug, "\tref: %#" PRIxPTR "\n", a); | 161 | debug::log_msg(debug::component_trace_t::garbage_collector, debug::log_level_t::debug, " ref: %#" PRIxPTR "\n", a); |
| 162 | allocs.push(a); | 162 | allocs.push(a); |
| 163 | } }; | 163 | } }; |
| 164 | } | 164 | } |
| @@ -58,7 +58,7 @@ void default_scheduler_t::worker_main(default_scheduler_t &instance) · 57 unmodified lines | |||
| 58 | if (module_ref.module->module_name != nullptr) | 58 | if (module_ref.module->module_name != nullptr) |
| 59 | module_name = module_ref.module->module_name->str(); | 59 | module_name = module_ref.module->module_name->str(); |
| 60 | 60 | ||
| 61 | err_msg << "\t" << module_name << "@" << pc << "\n"; | 61 | err_msg << " " << module_name << "@" << pc << "\n"; |
| 62 | return true; | 62 | return true; |
| 63 | }); | 63 | }); |
| 64 | } | 64 | } |