History

Update stack walk in debugger to show source file name. Format function name to include full type signature.

arr committed 9 years ago

Commit 2b710fc1 parent 72f24ec3 files · +173 −13Browse files

Unified · Split

3 files
  1. src/asm/sbl_reader.cpp +135 −8
  2. src/exec/debugger.cpp +23 −3
  3. src/include/vm_asm.h +15 −2
src/asm/sbl_reader.cpp+135−8
@@ -127,11 +127,21 @@ namespace · 126 unmodified lines
127 template<>127 template<>
128 const type_t &type_table_t::resolve_table_index<type_t>(int32_t idx) const128 const type_t &type_table_t::resolve_table_index<type_t>(int32_t idx) const
129 {129 {
130 const auto idx_local = idx & ~inner_type_table_mask;130 if ((static_cast<uint32_t>(idx) & inner_type_table_mask) != 0)
131 if (0 > idx_local || idx_local >= inner_type_table.size())131 {
132 throw std::out_of_range{ "Invalid inner type table index" };132 const auto idx_local = idx & ~inner_type_table_mask;
133 if (0 > idx_local || idx_local >= inner_type_table.size())
134 throw std::out_of_range{ "Invalid inner type table index" };
135
136 return inner_type_table[idx_local];
137 }
138 else
139 {
140 if (0 > idx || static_cast<uint32_t>(idx) >= types.size())
141 throw std::out_of_range{ "Invalid type table index" };
133 142
134 return inner_type_table[idx_local];143 return types[idx];
144 }
135 }145 }
136 146
137 template<>147 template<>
@@ -571,6 +581,114 @@ namespace · 433 unmodified lines
571 581
572namespace582namespace
573{583{
584 std::string to_string(const type_t &t, const type_table_t &tt)
585 {
586 switch (t.type_class)
587 {
588 case type_class_t::none: return "<none>";
589 case type_class_t::nil: return "nil";
590 case type_class_t::big: return "big";
591 case type_class_t::byte: return "byte";
592 case type_class_t::integer: return "int";
593 case type_class_t::real: return "real";
594 case type_class_t::string: return "string";
595
596 case type_class_t::poly:
597 assert(false && "Not fully implemented");
598 return "poly<T>";
599
600 case type_class_t::array:
601 return to_string(tt.resolve_table_index<type_t>(t.value_index_1), tt) + "[]";
602 case type_class_t::channel:
603 return "chan of " + to_string(tt.resolve_table_index<type_t>(t.value_index_1), tt);
604 case type_class_t::list:
605 return "list of " + to_string(tt.resolve_table_index<type_t>(t.value_index_1), tt);
606 case type_class_t::ref:
607 return "ref " + to_string(tt.resolve_table_index<type_t>(t.value_index_1), tt);
608 case type_class_t::type_index:
609 return to_string(tt.resolve_table_index<type_t>(t.value_index_1), tt);
610
611 case type_class_t::adt:
612 case type_class_t::adt_pick:
613 {
614 const auto &adt = tt.resolve_table_index<name_source_size_t>(t.value_index_1);
615 return adt.name;
616 }
617 case type_class_t::tuple:
618 {
619 const auto &tuple = tt.resolve_table_index<tuple_item_t>(t.value_index_1);
620
621 std::stringstream ss;
622 ss << '(';
623
624 auto first = true;
625 for (const auto &t_t : tuple.id_table)
626 {
627 if (!first)
628 ss << ',';
629
630 ss << to_string(t_t.type, tt);
631 first = false;
632 }
633
634 ss << ')';
635 return ss.str();
636 }
637 case type_class_t::module:
638 return tt.resolve_table_index<std::string>(t.value_index_1);
639
640 case type_class_t::function:
641 {
642 std::stringstream ss;
643 ss << tt.resolve_table_index<std::string>(t.value_index_1)
644 << ' '
645 << to_string(tt.resolve_table_index<type_t>(t.value_index_2), tt);
646
647 return ss.str();
648 }
649
650 default:
651 throw std::runtime_error{ "Invalid type value" };
652 }
653 }
654
655 std::string to_string(const func_item_t &f, const type_table_t &tt, function_name_format_t fmt)
656 {
657 std::stringstream ss;
658
659 if (util::has_flag(fmt, function_name_format_t::name))
660 ss << f.name;
661
662 auto has_argument = false;
663 if (util::has_flag(fmt, function_name_format_t::arguments))
664 {
665 has_argument = true;
666 ss << '(';
667
668 auto first = true;
669 for (const auto &at : f.args)
670 {
671 if (!first)
672 ss << ',';
673
674 ss << to_string(at.type, tt);
675 first = false;
676 }
677
678 ss << ')';
679 }
680
681 if (util::has_flag(fmt, function_name_format_t::return_type))
682 {
683 if (has_argument)
684 ss << ':';
685
686 ss << to_string(f.return_type, tt);
687 }
688
689 return ss.str();
690 }
691
574 class sbl_symbol_debug final : public symbol_debug_t692 class sbl_symbol_debug final : public symbol_debug_t
575 {693 {
576 public:694 public:
@@ -632,12 +750,21 @@ namespace · 55 unmodified lines
632 return true;750 return true;
633 }751 }
634 752
635 const std::string &current_function_name() const override753 std::string current_function_name(function_name_format_t f) const override
636 {754 {
637 for (auto &e : _file->func_table)755 try
756 {
757 for (auto &e : _file->func_table)
758 {
759 if (e.entry_pc <= _current_pc && _current_pc <= e.limit_pc)
760 return to_string(e, _file->type_table, f);
761 }
762 }
763 catch (const std::exception &e)
638 {764 {
639 if (e.entry_pc <= _current_pc && _current_pc <= e.limit_pc)765 // Avoid crashing during debugging
640 return e.name;766 assert(false && "The SBL file appears to be corrupt or inconsistent");
767 throw std::runtime_error{ e.what() };
641 }768 }
642 769
643 throw std::runtime_error{ "Unknown function" };770 throw std::runtime_error{ "Unknown function" };
src/exec/debugger.cpp+23−3
@@ -749,6 +749,20 @@ namespace · 748 unmodified lines
749 << console_modifiers::reset_all;749 << console_modifiers::reset_all;
750 }750 }
751 751
752 void set_value_cmd(const std::vector<std::string> &args, dbg_cmd_cxt_t &)
753 {
754 if (args.size() == 0)
755 {
756 // [TODO] Print all options current state
757 return;
758 }
759 else if (0 == args[0].compare("help"))
760 {
761 // [TODO] Print help for 'set' command
762 return;
763 }
764 }
765
752 const dbg_cmd_t cmds[] =766 const dbg_cmd_t cmds[] =
753 {767 {
754 { "c", "Continue", nullptr, nullptr, cmd_continue },768 { "c", "Continue", nullptr, nullptr, cmd_continue },
@@ -766,6 +780,8 @@ namespace · 11 unmodified lines
766 { "~", "Switch to thread", "~ [0-9]+", "~ 42", cmd_switchthread },780 { "~", "Switch to thread", "~ [0-9]+", "~ 42", cmd_switchthread },
767 { "d", "Disassemble the next/previous N instructions (default N = 4)", "d (-?[0-9]+)?", "d, d -4, d 5", cmd_disassemble },781 { "d", "Disassemble the next/previous N instructions (default N = 4)", "d (-?[0-9]+)?", "d, d -4, d 5", cmd_disassemble },
768 { "x", "Examine memory", "x [mp|fp] [0-9]+ ([0-9]+)?", "x mp 3, x fp 20 6", cmd_examine },782 { "x", "Examine memory", "x [mp|fp] [0-9]+ ([0-9]+)?", "x mp 3, x fp 20 6", cmd_examine },
783
784 //{ "set" , "Set a debugger option", "set [ _a-zA-Z0-9]*", "'set help' for available options", set_value_cmd },
769 { "?", "Print help", nullptr, nullptr, cmd_help },785 { "?", "Print help", nullptr, nullptr, cmd_help },
770 786
771 // Undocumented commands787 // Undocumented commands
@@ -882,11 +898,15 @@ std::string debugger::resolve_function_source_line(std::shared_ptr<const vm_modu · 110 unmodified lines
882 // Position the debug symbol iterator898 // Position the debug symbol iterator
883 d.set_current_pc(pc);899 d.set_current_pc(pc);
884 900
901 const auto src = d.current_source_location();
902
885 ss << m->module_name->str()903 ss << m->module_name->str()
886 << '!'904 << '!'
887 << d.current_function_name()905 << d.current_function_name(symbol::function_name_format_t::declaration)
888 << ' '906 << " at "
889 << d.current_source_location().begin_line;907 << d.get_source_by_id(src.source_id)
908 << ':'
909 << src.begin_line;
890 910
891 return ss.str();911 return ss.str();
892}912}
src/include/vm_asm.h+15−2
@@ -13,6 +13,7 @@ · 12 unmodified lines
13#include <cstdint>13#include <cstdint>
14#include "opcodes.h"14#include "opcodes.h"
15#include "runtime.h"15#include "runtime.h"
16#include "utils.h"
16 17
17namespace disvm18namespace disvm
18{19{
@@ -406,6 +407,17 @@ namespace disvm · 387 unmodified lines
406 int32_t end_column;407 int32_t end_column;
407 };408 };
408 409
410 enum class function_name_format_t
411 {
412 name = 1,
413 return_type = (1 << 1),
414 arguments = (1 << 2),
415
416 declaration = name | arguments | return_type,
417 };
418
419 DEFINE_ENUM_FLAG_OPERATORS(function_name_format_t);
420
409 class symbol_debug_t421 class symbol_debug_t
410 {422 {
411 public:423 public:
@@ -424,9 +436,10 @@ namespace disvm · 12 unmodified lines
424 // Returns 'true' if the function was successful, otherwise 'false'.436 // Returns 'true' if the function was successful, otherwise 'false'.
425 virtual bool try_advance_pc(advance_pc_t, disvm::runtime::vm_pc_t *pc_after_advance = nullptr) = 0;437 virtual bool try_advance_pc(advance_pc_t, disvm::runtime::vm_pc_t *pc_after_advance = nullptr) = 0;
426 438
427 // Return the name of the function encompassing the current pc.439 // Return the name of the function containing the current pc.
440 // Optionally format the returned string.
428 // This function will throw a 'std::runtime_error' if a function doesn't exist at the current pc.441 // This function will throw a 'std::runtime_error' if a function doesn't exist at the current pc.
429 virtual const std::string & current_function_name() const = 0;442 virtual std::string current_function_name(function_name_format_t f = function_name_format_t::name) const = 0;
430 443
431 // Return the source location for the current pc444 // Return the source location for the current pc
432 virtual source_ref_t current_source_location() const = 0;445 virtual source_ref_t current_source_location() const = 0;