summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/alpha/stacktrace.cc49
-rw-r--r--arch/alpha/stacktrace.hh32
-rw-r--r--cpu/base.cc4
-rw-r--r--cpu/base.hh1
-rw-r--r--cpu/profile.cc27
-rw-r--r--cpu/profile.hh15
-rw-r--r--cpu/simple/cpu.cc8
7 files changed, 92 insertions, 44 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 &reg, 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__
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<Addr> &stack)
{
- const vector<Addr> &stack = trace->getstack();
ProfileNode *current = &top;
- for (int i = 0, size = stack.size(); i < size; ++i)
- current = &current->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<Addr, ProfileNode> ChildList;
+ typedef std::map<Addr, ProfileNode *> ChildList;
ChildList children;
public:
@@ -60,15 +60,26 @@ class FunctionProfile
const SymbolTable *symtab;
ProfileNode top;
std::map<Addr, Counter> pc_count;
+ StackTrace trace;
public:
FunctionProfile(const SymbolTable *symtab);
~FunctionProfile();
- ProfileNode *consume(const StackTrace *trace);
+ ProfileNode *consume(ExecContext *xc, StaticInstPtr<TheISA> inst);
+ ProfileNode *consume(const std::vector<Addr> &stack);
void clear();
void dump(ExecContext *xc, std::ostream &out) const;
void sample(ProfileNode *node, Addr pc);
};
+inline ProfileNode *
+FunctionProfile::consume(ExecContext *xc, StaticInstPtr<TheISA> 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