Index: ChangeLog from Benoît Perrot benoit@lrde.epita.fr
Add the backtrace command to the shell. * src/vm/cpu.hh, src/vm/virtual_machine.hh: Add an accessor to call stack. * src/shell/cmd.hh, src/shell/shell.hh, src/shell/shell.cc: Parse and execute backtrace command.
2004-07-18 Benoît Perrot benoit@lrde.epita.fr
Index: src/vm/cpu.hh --- src/vm/cpu.hh (revision 114) +++ src/vm/cpu.hh (working copy) @@ -271,7 +271,7 @@ if (check_callee_save_p_) for (int i = Cpu::s0; i <= Cpu::s7; ++i) set_unlimited(-i, get_register((Cpu::kind_type) i)); - call_stack_.push(get_pc ()); + call_stack_.push_back(get_pc ());
unlimited_.begin_scope(); } @@ -286,14 +286,20 @@ std::cerr << "Warning: callee save register `$s" << i - Cpu::s0 << "' was not preserved across last call to 0x" - << std::hex << call_stack_.top() << std::dec << std::endl; + << std::hex << *call_stack_.rbegin() << std::dec << std::endl; set_register((Cpu::kind_type) i, get_unlimited(-i)); exit_set(exit_runtime); } - call_stack_.pop(); + call_stack_.pop_back(); } + public: + const std::vector<register_type> & get_call_stack() const + { + return call_stack_; + } + protected: - std::stack<register_type> call_stack_; + std::vector<register_type> call_stack_; bool check_callee_save_p_;
Index: src/vm/virtual_machine.hh --- src/vm/virtual_machine.hh (revision 116) +++ src/vm/virtual_machine.hh (working copy) @@ -115,6 +115,12 @@ /// Add a breakpoint void add_breakpoint(const std::string& label);
+ /// Return CPU's call stack + const std::vector<register_type> & get_call_stack() const + { + return cpu_.get_call_stack(); + } + protected: /// The list of breakpoints std::list<int> breakpoints_; Index: src/shell/cmd.hh --- src/shell/cmd.hh (revision 119) +++ src/shell/cmd.hh (working copy) @@ -48,6 +48,7 @@ cmd_undisplay, cmd_dump, cmd_mem, + cmd_backtrace, cmd_nop_after_branch, cmd_help }; Index: src/shell/shell.hh --- src/shell/shell.hh (revision 119) +++ src/shell/shell.hh (working copy) @@ -60,7 +60,8 @@ DUMP = 210, MEM = 211, NOP_AFTER_BRANCH = 212, - HELP = 213 + HELP = 213, + BACKTRACE };
/// Shell Class. @@ -209,6 +210,7 @@ void do_dump(); void do_print(const Cmd &cmd); void do_mem(); + void do_backtrace() const;
void do_nop_after_branch();
Index: src/shell/shell.cc --- src/shell/shell.cc (revision 119) +++ src/shell/shell.cc (working copy) @@ -17,6 +17,8 @@ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA //
+#include <iomanip> + #include "misc/readline.hh"
#include "parse/libparse.hh" @@ -50,6 +52,8 @@ map_token_["l"] = LOAD; map_token_["mem"] = MEM; map_token_["m"] = MEM; + map_token_["backtrace"] = BACKTRACE; + map_token_["bt"] = BACKTRACE; map_token_["next"] = NEXT; map_token_["n"] = NEXT; map_token_["print"] = PRINT; @@ -237,6 +241,8 @@ command->push_arg(tmp); return command; } + case BACKTRACE: + return new Cmd(Cmd::cmd_backtrace); case NOP_AFTER_BRANCH: return new Cmd(Cmd::cmd_nop_after_branch); case HELP: @@ -372,6 +378,28 @@ }
void + Shell::do_backtrace() const + { + const std::vectorvm::register_type &call_stack = vm_.get_call_stack(); + + if (call_stack.empty()) + std::cout << "No stack." << std::endl; + else + { + unsigned level = 0; + for (std::vectorvm::register_type::const_reverse_iterator + it = call_stack.rbegin(); it != call_stack.rend(); ++it) + { + std::cout + << "#" << level << " 0x" + << std::hex << std::setfill('0') << std::setw(8) << (*it) + << std::endl; + ++level; + } + } + } + + void Shell::do_error() const { std::cerr << "Command error" << std::endl; @@ -405,6 +433,8 @@ << "\tdump all the register value" << std::endl << "mem <addr>" << std::endl << "\tprint a the value of a memory region" << std::endl + << "backtrace" << std::endl + << "\tPrint backtrace of stack frame" << std::endl << "nop-after-branch" << std::endl << "\tenable Fill delay slot of branch instructions " << "with NOP" << std::endl; @@ -448,6 +478,9 @@ case Cmd::cmd_mem: do_mem(); break; + case Cmd::cmd_backtrace: + do_backtrace(); + break; case Cmd::cmd_break: do_break(cmd); break;