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 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 inst); ~StackTrace(); + void clear() + { + xc = 0; + stack.clear(); + } + + bool valid() const { return xc != NULL; } + bool trace(ExecContext *xc, StaticInstPtr inst); + public: const std::vector &getstack() const { return stack; } - static StackTrace *create(ExecContext *xc, StaticInstPtr 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 inst) +inline bool +StackTrace::trace(ExecContext *xc, StaticInstPtr inst) { if (!inst->isCall() && !inst->isReturn()) - return NULL; + return false; - return new StackTrace(xc, !inst->isReturn()); + if (valid()) + clear(); + + trace(xc, !inst->isReturn()); + return true; } #endif // __ARCH_ALPHA_STACKTRACE_HH__ diff --git a/cpu/base.cc b/cpu/base.cc index a6e71c808..8b94b8533 100644 --- a/cpu/base.cc +++ b/cpu/base.cc @@ -36,6 +36,7 @@ #include "base/output.hh" #include "cpu/base.hh" #include "cpu/exec_context.hh" +#include "cpu/profile.hh" #include "cpu/sampler/sampler.hh" #include "sim/param.hh" #include "sim/sim_events.hh" @@ -254,7 +255,8 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU) intstatus = oldCPU->intstatus; for (int i = 0; i < execContexts.size(); ++i) - execContexts[i]->profile->clear(); + if (execContexts[i]->profile) + execContexts[i]->profile->clear(); if (profileEvent) profileEvent->schedule(curTick); diff --git a/cpu/base.hh b/cpu/base.hh index 914d06982..4a44ab804 100644 --- a/cpu/base.hh +++ b/cpu/base.hh @@ -33,7 +33,6 @@ #include "base/statistics.hh" #include "config/full_system.hh" -#include "cpu/profile.hh" #include "cpu/sampler/sampler.hh" #include "sim/eventq.hh" #include "sim/sim_object.hh" diff --git a/cpu/profile.cc b/cpu/profile.cc index b17a3c74e..f4aa81c2b 100644 --- a/cpu/profile.cc +++ b/cpu/profile.cc @@ -47,8 +47,8 @@ ProfileNode::dump(const string &symbol, uint64_t id, const SymbolTable *symtab, ccprintf(os, "%#x %s %d ", id, symbol, count); ChildList::const_iterator i, end = children.end(); for (i = children.begin(); i != end; ++i) { - const ProfileNode &node = i->second; - ccprintf(os, "%#x ", (intptr_t)&node); + const ProfileNode *node = i->second; + ccprintf(os, "%#x ", (intptr_t)node); } ccprintf(os, "\n"); @@ -65,8 +65,8 @@ ProfileNode::dump(const string &symbol, uint64_t id, const SymbolTable *symtab, else if (!symtab->findSymbol(addr, symbol)) panic("could not find symbol for address %#x\n", addr); - const ProfileNode &node = i->second; - node.dump(symbol, (intptr_t)&node, symtab, os); + const ProfileNode *node = i->second; + node->dump(symbol, (intptr_t)node, symtab, os); } } @@ -75,11 +75,8 @@ ProfileNode::clear() { count = 0; ChildList::iterator i, end = children.end(); - for (i = children.begin(); i != end; ++i) { - ProfileNode &node = i->second; - node.clear(); - } - + for (i = children.begin(); i != end; ++i) + i->second->clear(); } FunctionProfile::FunctionProfile(const SymbolTable *_symtab) @@ -92,12 +89,16 @@ FunctionProfile::~FunctionProfile() } ProfileNode * -FunctionProfile::consume(const StackTrace *trace) +FunctionProfile::consume(const vector &stack) { - const vector &stack = trace->getstack(); ProfileNode *current = ⊤ - for (int i = 0, size = stack.size(); i < size; ++i) - current = ¤t->children[stack[size - i - 1]]; + for (int i = 0, size = stack.size(); i < size; ++i) { + ProfileNode *&ptr = current->children[stack[size - i - 1]]; + if (ptr == NULL) + ptr = new ProfileNode; + + current = ptr; + } return current; } diff --git a/cpu/profile.hh b/cpu/profile.hh index 9da170eb4..c795b8f41 100644 --- a/cpu/profile.hh +++ b/cpu/profile.hh @@ -40,7 +40,7 @@ class ProfileNode private: friend class FunctionProfile; - typedef std::map ChildList; + typedef std::map ChildList; ChildList children; public: @@ -60,15 +60,26 @@ class FunctionProfile const SymbolTable *symtab; ProfileNode top; std::map pc_count; + StackTrace trace; public: FunctionProfile(const SymbolTable *symtab); ~FunctionProfile(); - ProfileNode *consume(const StackTrace *trace); + ProfileNode *consume(ExecContext *xc, StaticInstPtr inst); + ProfileNode *consume(const std::vector &stack); void clear(); void dump(ExecContext *xc, std::ostream &out) const; void sample(ProfileNode *node, Addr pc); }; +inline ProfileNode * +FunctionProfile::consume(ExecContext *xc, StaticInstPtr inst) +{ + if (!trace.trace(xc, inst)) + return NULL; + trace.dprintf(); + return consume(trace.getstack()); +} + #endif // __CPU_PROFILE_HH__ diff --git a/cpu/simple/cpu.cc b/cpu/simple/cpu.cc index 8f7534e16..862fe5b2c 100644 --- a/cpu/simple/cpu.cc +++ b/cpu/simple/cpu.cc @@ -46,6 +46,7 @@ #include "cpu/base.hh" #include "cpu/exec_context.hh" #include "cpu/exetrace.hh" +#include "cpu/profile.hh" #include "cpu/sampler/sampler.hh" #include "cpu/simple/cpu.hh" #include "cpu/smt.hh" @@ -763,12 +764,7 @@ SimpleCPU::tick() if (xc->profile) { bool usermode = (xc->regs.ipr[AlphaISA::IPR_DTB_CM] & 0x18) != 0; xc->profilePC = usermode ? 1 : xc->regs.pc; - StackTrace *trace = StackTrace::create(xc, inst); - if (trace) { - xc->profileNode = xc->profile->consume(trace); - trace->dprintf(); - delete trace; - } + xc->profileNode = xc->profile->consume(xc, inst); } #endif