diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/alpha/stacktrace.cc | 49 | ||||
-rw-r--r-- | arch/alpha/stacktrace.hh | 32 |
2 files changed, 60 insertions, 21 deletions
diff --git a/arch/alpha/stacktrace.cc b/arch/alpha/stacktrace.cc index fdad9d673..5a8df3d35 100644 --- a/arch/alpha/stacktrace.cc +++ b/arch/alpha/stacktrace.cc @@ -103,25 +103,42 @@ ProcessInfo::name(Addr ksp) const return comm; } -StackTrace::StackTrace(ExecContext *_xc, bool is_call) - : xc(_xc) +StackTrace::StackTrace() + : xc(0), stack(64) +{ +} + +StackTrace::StackTrace(ExecContext *_xc, StaticInstPtr<TheISA> inst) + : xc(0), stack(64) { + trace(_xc, inst); +} + +StackTrace::~StackTrace() +{ +} + +void +StackTrace::trace(ExecContext *_xc, bool is_call) +{ + xc = _xc; + bool usermode = (xc->regs.ipr[AlphaISA::IPR_DTB_CM] & 0x18) != 0; Addr pc = xc->regs.npc; bool kernel = xc->system->kernelStart <= pc && pc <= xc->system->kernelEnd; if (usermode) { - stack.push_back(1); + stack.push_back(user); return; } if (!kernel) { - stack.push_back(2); + stack.push_back(console); return; } - SymbolTable *symtab = xc->system->allSymtab; + SymbolTable *symtab = xc->system->kernelSymtab; Addr ksp = xc->regs.intRegFile[TheISA::StackPointerReg]; Addr bottom = ksp & ~0x3fff; Addr addr; @@ -151,10 +168,15 @@ StackTrace::StackTrace(ExecContext *_xc, bool is_call) if (!ra) return; + if (size <= 0) { + stack.push_back(unknown); + return; + } + pc = ra; ksp += size; } else { - stack.push_back(3); + stack.push_back(unknown); return; } @@ -162,15 +184,14 @@ StackTrace::StackTrace(ExecContext *_xc, bool is_call) pc <= xc->system->kernelEnd; if (!kernel) return; + + if (stack.size() >= 1000) + panic("unwinding too far"); } panic("unwinding too far"); } -StackTrace::~StackTrace() -{ -} - bool StackTrace::isEntry(Addr addr) { @@ -302,18 +323,18 @@ void StackTrace::dump() { StringWrap name(xc->cpu->name()); - SymbolTable *symtab = xc->system->allSymtab; + SymbolTable *symtab = xc->system->kernelSymtab; DPRINTFN("------ Stack ------\n"); string symbol; for (int i = 0, size = stack.size(); i < size; ++i) { Addr addr = stack[size - i - 1]; - if (addr == 1) + if (addr == user) symbol = "user"; - else if (addr == 2) + else if (addr == console) symbol = "console"; - else if (addr == 3) + else if (addr == unknown) symbol = "unknown"; else symtab->findSymbol(addr, symbol); diff --git a/arch/alpha/stacktrace.hh b/arch/alpha/stacktrace.hh index 5a4741eba..244e574b6 100644 --- a/arch/alpha/stacktrace.hh +++ b/arch/alpha/stacktrace.hh @@ -34,7 +34,6 @@ class ExecContext; class StackTrace; -class SymbolTable; class ProcessInfo { @@ -67,13 +66,28 @@ class StackTrace bool decodeSave(MachInst inst, int ®, int &disp); bool decodeStack(MachInst inst, int &disp); + void trace(ExecContext *xc, bool is_call); + public: - StackTrace(ExecContext *xc, bool is_call); + StackTrace(); + StackTrace(ExecContext *xc, StaticInstPtr<TheISA> inst); ~StackTrace(); + void clear() + { + xc = 0; + stack.clear(); + } + + bool valid() const { return xc != NULL; } + bool trace(ExecContext *xc, StaticInstPtr<TheISA> inst); + public: const std::vector<Addr> &getstack() const { return stack; } - static StackTrace *create(ExecContext *xc, StaticInstPtr<TheISA> inst); + + static const int user = 1; + static const int console = 2; + static const int unknown = 3; #if TRACING_ON private: @@ -87,13 +101,17 @@ class StackTrace #endif }; -inline StackTrace * -StackTrace::create(ExecContext *xc, StaticInstPtr<TheISA> inst) +inline bool +StackTrace::trace(ExecContext *xc, StaticInstPtr<TheISA> inst) { if (!inst->isCall() && !inst->isReturn()) - return NULL; + return false; + + if (valid()) + clear(); - return new StackTrace(xc, !inst->isReturn()); + trace(xc, !inst->isReturn()); + return true; } #endif // __ARCH_ALPHA_STACKTRACE_HH__ |