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
127127 template<>
128128 const type_t &type_table_t::resolve_table_index<type_t>(int32_t idx) const
129129 {
130− const auto idx_local = idx & ~inner_type_table_mask;
131− if (0 > idx_local || idx_local >= inner_type_table.size())
132− throw std::out_of_range{ "Invalid inner type table index" };
130+ if ((static_cast<uint32_t>(idx) & inner_type_table_mask) != 0)
131+ {
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" };
133142
134− return inner_type_table[idx_local];
143+ return types[idx];
144+ }
135145 }
136146
137147 template<>
@@ -571,6 +581,114 @@ namespace · 433 unmodified lines
571581
572582 namespace
573583 {
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+
574692 class sbl_symbol_debug final : public symbol_debug_t
575693 {
576694 public:
@@ -632,12 +750,21 @@ namespace · 55 unmodified lines
632750 return true;
633751 }
634752
635− const std::string &current_function_name() const override
753+ std::string current_function_name(function_name_format_t f) const override
636754 {
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)
638764 {
639− if (e.entry_pc <= _current_pc && _current_pc <= e.limit_pc)
640− return e.name;
765+ // Avoid crashing during debugging
766+ assert(false && "The SBL file appears to be corrupt or inconsistent");
767+ throw std::runtime_error{ e.what() };
641768 }
642769
643770 throw std::runtime_error{ "Unknown function" };
src/exec/debugger.cpp+23−3
@@ -749,6 +749,20 @@ namespace · 748 unmodified lines
749749 << console_modifiers::reset_all;
750750 }
751751
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+
752766 const dbg_cmd_t cmds[] =
753767 {
754768 { "c", "Continue", nullptr, nullptr, cmd_continue },
@@ -766,6 +780,8 @@ namespace · 11 unmodified lines
766780 { "~", "Switch to thread", "~ [0-9]+", "~ 42", cmd_switchthread },
767781 { "d", "Disassemble the next/previous N instructions (default N = 4)", "d (-?[0-9]+)?", "d, d -4, d 5", cmd_disassemble },
768782 { "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 },
769785 { "?", "Print help", nullptr, nullptr, cmd_help },
770786
771787 // Undocumented commands
@@ -882,11 +898,15 @@ std::string debugger::resolve_function_source_line(std::shared_ptr<const vm_modu · 110 unmodified lines
882898 // Position the debug symbol iterator
883899 d.set_current_pc(pc);
884900
901+ const auto src = d.current_source_location();
902+
885903 ss << m->module_name->str()
886904 << '!'
887− << d.current_function_name()
888− << ' '
889− << d.current_source_location().begin_line;
905+ << d.current_function_name(symbol::function_name_format_t::declaration)
906+ << " at "
907+ << d.get_source_by_id(src.source_id)
908+ << ':'
909+ << src.begin_line;
890910
891911 return ss.str();
892912 }
src/include/vm_asm.h+15−2
@@ -13,6 +13,7 @@ · 12 unmodified lines
1313 #include <cstdint>
1414 #include "opcodes.h"
1515 #include "runtime.h"
16+#include "utils.h"
1617
1718 namespace disvm
1819 {
@@ -406,6 +407,17 @@ namespace disvm · 387 unmodified lines
406407 int32_t end_column;
407408 };
408409
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+
409421 class symbol_debug_t
410422 {
411423 public:
@@ -424,9 +436,10 @@ namespace disvm · 12 unmodified lines
424436 // Returns 'true' if the function was successful, otherwise 'false'.
425437 virtual bool try_advance_pc(advance_pc_t, disvm::runtime::vm_pc_t *pc_after_advance = nullptr) = 0;
426438
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.
428441 // 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;
430443
431444 // Return the source location for the current pc
432445 virtual source_ref_t current_source_location() const = 0;