Showing the changes to src/exec/debugger.cpp (1 of 1 file). Show all
Unified · Split
| @@ -51,7 +51,14 @@ namespace · 50 unmodified lines | |||
| 51 | #undef CSI | 51 | #undef CSI |
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | void debug_print_error(const std::string &str) | 54 | struct debug_cmd_error_t : std::runtime_error |
| 55 | { | ||
| 56 | debug_cmd_error_t(const char *message) | ||
| 57 | : std::runtime_error{ message } | ||
| 58 | { } | ||
| 59 | }; | ||
| 60 | |||
| 61 | void debug_print_error(const char *str) | ||
| 55 | { | 62 | { |
| 56 | std::cout | 63 | std::cout |
| 57 | << console_modifiers::red_font | 64 | << console_modifiers::red_font |
| @@ -62,6 +69,11 @@ namespace · 4 unmodified lines | |||
| 62 | << "\n"; | 69 | << "\n"; |
| 63 | } | 70 | } |
| 64 | 71 | ||
| 72 | void debug_print_error(const std::string &str) | ||
| 73 | { | ||
| 74 | debug_print_error(str.c_str()); | ||
| 75 | } | ||
| 76 | |||
| 65 | void debug_print_info(const std::string &str) | 77 | void debug_print_info(const std::string &str) |
| 66 | { | 78 | { |
| 67 | std::cout | 79 | std::cout |
| @@ -290,7 +302,7 @@ namespace · 222 unmodified lines | |||
| 290 | cxt.exit_break = true; | 302 | cxt.exit_break = true; |
| 291 | } | 303 | } |
| 292 | 304 | ||
| 293 | void cmd_term(const std::vector<std::string> &, dbg_cmd_cxt_t &cxt) | 305 | void cmd_term(const std::vector<std::string> &, dbg_cmd_cxt_t &) |
| 294 | { | 306 | { |
| 295 | throw vm_user_exception{ "Debugger signaled VM termination" }; | 307 | throw vm_user_exception{ "Debugger signaled VM termination" }; |
| 296 | } | 308 | } |
| @@ -332,10 +344,7 @@ namespace · 35 unmodified lines | |||
| 332 | void cmd_breakpoint_set(const std::vector<std::string> &a, dbg_cmd_cxt_t &cxt) | 344 | void cmd_breakpoint_set(const std::vector<std::string> &a, dbg_cmd_cxt_t &cxt) |
| 333 | { | 345 | { |
| 334 | if (a.size() < 3) | 346 | if (a.size() < 3) |
| 335 | { | 347 | throw debug_cmd_error_t{ "Must supply an IP and module ID" }; |
| 336 | debug_print_error("Must supply an IP and module ID"); | ||
| 337 | return; | ||
| 338 | } | ||
| 339 | 348 | ||
| 340 | vm_pc_t pc; | 349 | vm_pc_t pc; |
| 341 | try | 350 | try |
| @@ -344,8 +353,7 @@ namespace · 2 unmodified lines | |||
| 344 | } | 353 | } |
| 345 | catch (...) | 354 | catch (...) |
| 346 | { | 355 | { |
| 347 | debug_print_error("Invalid IP format"); | 356 | throw debug_cmd_error_t{ "Invalid IP format" }; |
| 348 | return; | ||
| 349 | } | 357 | } |
| 350 | 358 | ||
| 351 | uint32_t module_id; | 359 | uint32_t module_id; |
| @@ -355,8 +363,7 @@ namespace · 3 unmodified lines | |||
| 355 | } | 363 | } |
| 356 | catch (...) | 364 | catch (...) |
| 357 | { | 365 | { |
| 358 | debug_print_error("Invalid module ID format"); | 366 | throw debug_cmd_error_t{ "Invalid module ID format" }; |
| 359 | return; | ||
| 360 | } | 367 | } |
| 361 | 368 | ||
| 362 | auto module = std::shared_ptr<vm_module_t>{}; | 369 | auto module = std::shared_ptr<vm_module_t>{}; |
| @@ -372,20 +379,15 @@ namespace · 9 unmodified lines | |||
| 372 | 379 | ||
| 373 | if (module == nullptr) | 380 | if (module == nullptr) |
| 374 | { | 381 | { |
| 375 | debug_print_error("Invalid module ID"); | 382 | throw debug_cmd_error_t{ "Invalid module ID" }; |
| 376 | return; | ||
| 377 | } | 383 | } |
| 378 | else if (util::has_flag(module->header.runtime_flag, runtime_flags_t::builtin)) | 384 | else if (util::has_flag(module->header.runtime_flag, runtime_flags_t::builtin)) |
| 379 | { | 385 | { |
| 380 | debug_print_error("Unable to set breakpoint in built-in module"); | 386 | throw debug_cmd_error_t{ "Unable to set breakpoint in built-in module" }; |
| 381 | return; | ||
| 382 | } | 387 | } |
| 383 | 388 | ||
| 384 | 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)) |
| 385 | { | 390 | throw debug_cmd_error_t{ "Invalid IP for module" }; |
| 386 | debug_print_error("Invalid IP for module"); | ||
| 387 | return; | ||
| 388 | } | ||
| 389 | 391 | ||
| 390 | cxt.dbg.breakpoint_cookies.push_back(cxt.dbg.controller->set_breakpoint(module, pc)); | 392 | cxt.dbg.breakpoint_cookies.push_back(cxt.dbg.controller->set_breakpoint(module, pc)); |
| 391 | } | 393 | } |
| @@ -393,10 +395,7 @@ namespace · 1 unmodified line | |||
| 393 | 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) |
| 394 | { | 396 | { |
| 395 | if (a.size() == 1) | 397 | if (a.size() == 1) |
| 396 | { | 398 | throw debug_cmd_error_t{ "Must supply a breakpoint ID or wildcard" }; |
| 397 | debug_print_error("Must supply a breakpoint ID or wildcard"); | ||
| 398 | return; | ||
| 399 | } | ||
| 400 | 399 | ||
| 401 | auto controller = cxt.dbg.controller; | 400 | auto controller = cxt.dbg.controller; |
| 402 | if (a[1].compare("*") == 0) | 401 | if (a[1].compare("*") == 0) |
| @@ -417,8 +416,7 @@ namespace · 14 unmodified lines | |||
| 417 | } | 416 | } |
| 418 | catch (...) | 417 | catch (...) |
| 419 | { | 418 | { |
| 420 | debug_print_error("Invalid breakpoint ID format"); | 419 | throw debug_cmd_error_t{ "Invalid breakpoint ID format" }; |
| 421 | return; | ||
| 422 | } | 420 | } |
| 423 | 421 | ||
| 424 | auto cookie_iter = std::find_if( | 422 | auto cookie_iter = std::find_if( |
| @@ -426,10 +424,7 @@ namespace · 1 unmodified line | |||
| 426 | std::end(cxt.dbg.breakpoint_cookies), | 424 | std::end(cxt.dbg.breakpoint_cookies), |
| 427 | [breakpoint_cookie] (const cookie_t c) { return c == breakpoint_cookie; }); | 425 | [breakpoint_cookie] (const cookie_t c) { return c == breakpoint_cookie; }); |
| 428 | if (cookie_iter == cxt.dbg.breakpoint_cookies.end()) | 426 | if (cookie_iter == cxt.dbg.breakpoint_cookies.end()) |
| 429 | { | 427 | throw debug_cmd_error_t{ "Unknown breakpoint ID" }; |
| 430 | debug_print_error("Unknown breakpoint ID"); | ||
| 431 | return; | ||
| 432 | } | ||
| 433 | 428 | ||
| 434 | // Clear the breakpoint | 429 | // Clear the breakpoint |
| 435 | controller->clear_breakpoint(breakpoint_cookie); | 430 | controller->clear_breakpoint(breakpoint_cookie); |
| @@ -446,7 +441,7 @@ namespace · 10 unmodified lines | |||
| 446 | const auto details = cxt.dbg.controller->get_breakpoint_details(cookie); | 441 | const auto details = cxt.dbg.controller->get_breakpoint_details(cookie); |
| 447 | msg << std::setw(3) << cookie << ": " | 442 | msg << std::setw(3) << cookie << ": " |
| 448 | << std::setw(16) << details.module->module_name->str() | 443 | << std::setw(16) << details.module->module_name->str() |
| 449 | << std::setw(0) << " @ " << details.pc << "\n"; | 444 | << std::setw(0) << "@" << details.pc << "\n"; |
| 450 | } | 445 | } |
| 451 | 446 | ||
| 452 | debug_print_info(msg.str()); | 447 | debug_print_info(msg.str()); |
| @@ -474,8 +469,7 @@ namespace · 21 unmodified lines | |||
| 474 | } | 469 | } |
| 475 | catch (...) | 470 | catch (...) |
| 476 | { | 471 | { |
| 477 | debug_print_error("Invalid thread ID format"); | 472 | throw debug_cmd_error_t{ "Invalid thread ID format" }; |
| 478 | return; | ||
| 479 | } | 473 | } |
| 480 | } | 474 | } |
| 481 | 475 | ||
| @@ -496,10 +490,7 @@ namespace · 14 unmodified lines | |||
| 496 | } | 490 | } |
| 497 | 491 | ||
| 498 | if (thread_registers.empty()) | 492 | if (thread_registers.empty()) |
| 499 | { | 493 | throw debug_cmd_error_t{ "Unknown thread ID" }; |
| 500 | debug_print_error("Unknown thread ID"); | ||
| 501 | return; | ||
| 502 | } | ||
| 503 | 494 | ||
| 504 | auto msg = std::stringstream{}; | 495 | auto msg = std::stringstream{}; |
| 505 | for (auto t : thread_registers) | 496 | for (auto t : thread_registers) |
| @@ -515,10 +506,7 @@ namespace · 9 unmodified lines | |||
| 515 | void cmd_switchthread(const std::vector<std::string> &a, dbg_cmd_cxt_t &cxt) | 506 | void cmd_switchthread(const std::vector<std::string> &a, dbg_cmd_cxt_t &cxt) |
| 516 | { | 507 | { |
| 517 | if (a.size() == 1) | 508 | if (a.size() == 1) |
| 518 | { | 509 | throw debug_cmd_error_t{ "Must supply a target thread ID" }; |
| 519 | debug_print_error("Must supply a target thread ID"); | ||
| 520 | return; | ||
| 521 | } | ||
| 522 | 510 | ||
| 523 | uint32_t thread_id; | 511 | uint32_t thread_id; |
| 524 | try | 512 | try |
| @@ -527,8 +515,7 @@ namespace · 2 unmodified lines | |||
| 527 | } | 515 | } |
| 528 | catch (...) | 516 | catch (...) |
| 529 | { | 517 | { |
| 530 | debug_print_error("Invalid thread ID format"); | 518 | throw debug_cmd_error_t{ "Invalid thread ID format" }; |
| 531 | return; | ||
| 532 | } | 519 | } |
| 533 | 520 | ||
| 534 | auto all_threads = cxt.vm.get_scheduler_control().get_all_threads(); | 521 | auto all_threads = cxt.vm.get_scheduler_control().get_all_threads(); |
| @@ -544,7 +531,7 @@ namespace · 9 unmodified lines | |||
| 544 | } | 531 | } |
| 545 | } | 532 | } |
| 546 | 533 | ||
| 547 | debug_print_error("Unknown thread ID"); | 534 | throw debug_cmd_error_t{ "Unknown thread ID" }; |
| 548 | } | 535 | } |
| 549 | 536 | ||
| 550 | void cmd_disassemble(const std::vector<std::string> &a, dbg_cmd_cxt_t &cxt) | 537 | void cmd_disassemble(const std::vector<std::string> &a, dbg_cmd_cxt_t &cxt) |
| @@ -558,8 +545,7 @@ namespace · 7 unmodified lines | |||
| 558 | } | 545 | } |
| 559 | catch (...) | 546 | catch (...) |
| 560 | { | 547 | { |
| 561 | debug_print_error("Invalid disassemble count format"); | 548 | throw debug_cmd_error_t{ "Invalid disassemble count format" }; |
| 562 | return; | ||
| 563 | } | 549 | } |
| 564 | } | 550 | } |
| 565 | 551 | ||
| @@ -589,10 +575,7 @@ namespace · 23 unmodified lines | |||
| 589 | void cmd_examine(const std::vector<std::string> &a, dbg_cmd_cxt_t &cxt) | 575 | void cmd_examine(const std::vector<std::string> &a, dbg_cmd_cxt_t &cxt) |
| 590 | { | 576 | { |
| 591 | if (a.size() < 3) | 577 | if (a.size() < 3) |
| 592 | { | 578 | throw debug_cmd_error_t{ "Invalid number of arguments" }; |
| 593 | debug_print_error("Invalid number of arguments"); | ||
| 594 | return; | ||
| 595 | } | ||
| 596 | 579 | ||
| 597 | std::shared_ptr<const type_descriptor_t> base_type; | 580 | std::shared_ptr<const type_descriptor_t> base_type; |
| 598 | word_t *base_pointer; | 581 | word_t *base_pointer; |
| @@ -606,18 +589,14 @@ namespace · 7 unmodified lines | |||
| 606 | { | 589 | { |
| 607 | auto frame = cxt.current_register->stack.peek_frame(); | 590 | auto frame = cxt.current_register->stack.peek_frame(); |
| 608 | if (frame == nullptr) | 591 | if (frame == nullptr) |
| 609 | { | 592 | throw debug_cmd_error_t{ "Invalid frame pointer " }; |
| 610 | debug_print_error("Invalid frame pointer "); | ||
| 611 | return; | ||
| 612 | } | ||
| 613 | 593 | ||
| 614 | base_type = frame->frame_type; | 594 | base_type = frame->frame_type; |
| 615 | base_pointer = reinterpret_cast<word_t *>(frame->base()); | 595 | base_pointer = reinterpret_cast<word_t *>(frame->base()); |
| 616 | } | 596 | } |
| 617 | else | 597 | else |
| 618 | { | 598 | { |
| 619 | debug_print_error("Invalid memory base pointer"); | 599 | throw debug_cmd_error_t{ "Invalid memory base pointer" }; |
| 620 | return; | ||
| 621 | } | 600 | } |
| 622 | 601 | ||
| 623 | assert(base_type != nullptr && base_pointer != nullptr); | 602 | assert(base_type != nullptr && base_pointer != nullptr); |
| @@ -635,15 +614,11 @@ namespace · 11 unmodified lines | |||
| 635 | } | 614 | } |
| 636 | catch (...) | 615 | catch (...) |
| 637 | { | 616 | { |
| 638 | debug_print_error("Invalid memory offset format"); | 617 | throw debug_cmd_error_t{ "Invalid memory offset format" }; |
| 639 | return; | ||
| 640 | } | 618 | } |
| 641 | 619 | ||
| 642 | if (0 > byte_offset1 || byte_offset1 >= base_type->size_in_bytes) | 620 | if (0 > byte_offset1 || byte_offset1 >= base_type->size_in_bytes) |
| 643 | { | 621 | throw debug_cmd_error_t{ "First offset out of range" }; |
| 644 | debug_print_error("First offset out of range"); | ||
| 645 | return; | ||
| 646 | } | ||
| 647 | 622 | ||
| 648 | auto msg = std::stringstream{}; | 623 | auto msg = std::stringstream{}; |
| 649 | if (byte_offset2 != -1) | 624 | if (byte_offset2 != -1) |
| @@ -661,16 +636,10 @@ namespace · 11 unmodified lines | |||
| 661 | if (byte_offset2 != -1) | 636 | if (byte_offset2 != -1) |
| 662 | { | 637 | { |
| 663 | if (alloc_to_examine == nullptr) | 638 | if (alloc_to_examine == nullptr) |
| 664 | { | 639 | throw debug_cmd_error_t{ "First offset is nil" }; |
| 665 | debug_print_error("First offset is nil"); | ||
| 666 | return; | ||
| 667 | } | ||
| 668 | 640 | ||
| 669 | if (0 > byte_offset2 || byte_offset2 >= alloc_to_examine->alloc_type->size_in_bytes) | 641 | if (0 > byte_offset2 || byte_offset2 >= alloc_to_examine->alloc_type->size_in_bytes) |
| 670 | { | 642 | throw debug_cmd_error_t{ "Second offset out of range" }; |
| 671 | debug_print_error("Second offset out of range"); | ||
| 672 | return; | ||
| 673 | } | ||
| 674 | 643 | ||
| 675 | // Update data pointer for 2nd indirection | 644 | // Update data pointer for 2nd indirection |
| 676 | base_pointer = reinterpret_cast<word_t *>(alloc_to_examine->get_allocation()); | 645 | base_pointer = reinterpret_cast<word_t *>(alloc_to_examine->get_allocation()); |
| @@ -862,9 +831,16 @@ namespace · 185 unmodified lines | |||
| 862 | continue; | 831 | continue; |
| 863 | } | 832 | } |
| 864 | 833 | ||
| 865 | cmd_exec(cmd_tokens, cxt); | 834 | try |
| 866 | if (cxt.exit_break) | 835 | { |
| 867 | break; | 836 | cmd_exec(cmd_tokens, cxt); |
| 837 | if (cxt.exit_break) | ||
| 838 | break; | ||
| 839 | } | ||
| 840 | catch (const debug_cmd_error_t &e) | ||
| 841 | { | ||
| 842 | debug_print_error(e.what()); | ||
| 843 | } | ||
| 868 | } | 844 | } |
| 869 | } | 845 | } |
| 870 | } | 846 | } |