Index: ChangeLog
from Benoît Perrot <benoit(a)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(a)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::vector<vm::register_type> &call_stack = vm_.get_call_stack();
+
+ if (call_stack.empty())
+ std::cout << "No stack." << std::endl;
+ else
+ {
+ unsigned level = 0;
+ for (std::vector<vm::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;