summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorNathan Binkert <binkertn@umich.edu>2005-10-18 19:07:42 -0400
committerNathan Binkert <binkertn@umich.edu>2005-10-18 19:07:42 -0400
commita81c03737addc8e9a9b00cde0354e6c0ab4561af (patch)
treee7415ec9c2a97cf676d5599a1cec2c1fd775ace2 /arch
parent357ee7a845eac0bd903ed31e31eec993d54a698c (diff)
downloadgem5-a81c03737addc8e9a9b00cde0354e6c0ab4561af.tar.xz
Add new function profiling stuff, wrap the pc_sample stuff into it.
SConscript: Get rid of the pc_sample stuff and move to the new profiling stuff base/traceflags.py: DPRINTF Stack stuff cpu/base.cc: cpu/base.hh: cpu/exec_context.cc: cpu/exec_context.hh: cpu/simple/cpu.cc: Add profiling stuff kern/kernel_stats.hh: Use a smart pointer sim/system.cc: sim/system.hh: Create a new symbol table that has all of the symbols for a particular system util/stats/categories.py: change around the categories, add categories for function profiling stuff util/stats/profile.py: No profile parsing and display code to deal with function profiling stuff, graph, dot, and text outputs. --HG-- extra : convert_revision : b3de0cdc8bd468e42647966e2640ae009bda9eb8
Diffstat (limited to 'arch')
-rw-r--r--arch/alpha/stacktrace.cc324
-rw-r--r--arch/alpha/stacktrace.hh99
2 files changed, 423 insertions, 0 deletions
diff --git a/arch/alpha/stacktrace.cc b/arch/alpha/stacktrace.cc
new file mode 100644
index 000000000..fdad9d673
--- /dev/null
+++ b/arch/alpha/stacktrace.cc
@@ -0,0 +1,324 @@
+/*
+ * Copyright (c) 2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <string>
+
+#include "arch/alpha/isa_traits.hh"
+#include "arch/alpha/stacktrace.hh"
+#include "arch/alpha/vtophys.hh"
+#include "base/bitfield.hh"
+#include "base/trace.hh"
+#include "cpu/base.hh"
+#include "cpu/exec_context.hh"
+
+using namespace std;
+
+ProcessInfo::ProcessInfo(ExecContext *_xc)
+ : xc(_xc)
+{
+ Addr addr = 0;
+
+ if (!xc->system->kernelSymtab->findAddress("thread_info_size", addr))
+ panic("thread info not compiled into kernel\n");
+ thread_info_size = *(int32_t *)vtomem(xc, addr, sizeof(int32_t));
+
+ if (!xc->system->kernelSymtab->findAddress("task_struct_size", addr))
+ panic("thread info not compiled into kernel\n");
+ task_struct_size = *(int32_t *)vtomem(xc, addr, sizeof(int32_t));
+
+ if (!xc->system->kernelSymtab->findAddress("thread_info_task", addr))
+ panic("thread info not compiled into kernel\n");
+ task_off = *(int32_t *)vtomem(xc, addr, sizeof(int32_t));
+
+ if (!xc->system->kernelSymtab->findAddress("task_struct_pid", addr))
+ panic("thread info not compiled into kernel\n");
+ pid_off = *(int32_t *)vtomem(xc, addr, sizeof(int32_t));
+
+ if (!xc->system->kernelSymtab->findAddress("task_struct_comm", addr))
+ panic("thread info not compiled into kernel\n");
+ name_off = *(int32_t *)vtomem(xc, addr, sizeof(int32_t));
+}
+
+Addr
+ProcessInfo::task(Addr ksp) const
+{
+ Addr base = ksp & ~0x3fff;
+ if (base == ULL(0xfffffc0000000000))
+ return 0;
+
+ Addr task;
+ CopyOut(xc, &task, base + task_off, sizeof(task));
+ return task;
+}
+
+int
+ProcessInfo::pid(Addr ksp) const
+{
+ Addr task = this->task(ksp);
+ if (!task)
+ return -1;
+
+ uint16_t pid;
+ CopyOut(xc, &pid, task + pid_off, sizeof(pid));
+ return pid;
+}
+
+string
+ProcessInfo::name(Addr ksp) const
+{
+ Addr task = this->task(ksp);
+ if (!task)
+ return "console";
+
+ char comm[256];
+ CopyString(xc, comm, task + name_off, sizeof(comm));
+ if (!comm[0])
+ return "startup";
+
+ return comm;
+}
+
+StackTrace::StackTrace(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);
+ return;
+ }
+
+ if (!kernel) {
+ stack.push_back(2);
+ return;
+ }
+
+ SymbolTable *symtab = xc->system->allSymtab;
+ Addr ksp = xc->regs.intRegFile[TheISA::StackPointerReg];
+ Addr bottom = ksp & ~0x3fff;
+ Addr addr;
+
+ if (is_call) {
+ if (!symtab->findNearestAddr(pc, addr))
+ panic("could not find address %#x", pc);
+
+ stack.push_back(addr);
+ pc = xc->regs.pc;
+ }
+
+ Addr ra;
+ int size;
+
+ while (ksp > bottom) {
+ if (!symtab->findNearestAddr(pc, addr))
+ panic("could not find symbol for pc=%#x", pc);
+ assert(pc >= addr && "symbol botch: callpc < func");
+
+ stack.push_back(addr);
+
+ if (isEntry(addr))
+ return;
+
+ if (decodePrologue(ksp, pc, addr, size, ra)) {
+ if (!ra)
+ return;
+
+ pc = ra;
+ ksp += size;
+ } else {
+ stack.push_back(3);
+ return;
+ }
+
+ bool kernel = xc->system->kernelStart <= pc &&
+ pc <= xc->system->kernelEnd;
+ if (!kernel)
+ return;
+ }
+
+ panic("unwinding too far");
+}
+
+StackTrace::~StackTrace()
+{
+}
+
+bool
+StackTrace::isEntry(Addr addr)
+{
+ if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp12])
+ return true;
+
+ if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp7])
+ return true;
+
+ if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp11])
+ return true;
+
+ if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp21])
+ return true;
+
+ if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp9])
+ return true;
+
+ if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp2])
+ return true;
+
+ return false;
+}
+
+bool
+StackTrace::decodeStack(MachInst inst, int &disp)
+{
+ // lda $sp, -disp($sp)
+ //
+ // Opcode<31:26> == 0x08
+ // RA<25:21> == 30
+ // RB<20:16> == 30
+ // Disp<15:0>
+ const MachInst mem_mask = 0xffff0000;
+ const MachInst lda_pattern = 0x23de0000;
+ const MachInst lda_disp_mask = 0x0000ffff;
+
+ // subq $sp, disp, $sp
+ // addq $sp, disp, $sp
+ //
+ // Opcode<31:26> == 0x10
+ // RA<25:21> == 30
+ // Lit<20:13>
+ // One<12> = 1
+ // Func<11:5> == 0x20 (addq)
+ // Func<11:5> == 0x29 (subq)
+ // RC<4:0> == 30
+ const MachInst intop_mask = 0xffe01fff;
+ const MachInst addq_pattern = 0x43c0141e;
+ const MachInst subq_pattern = 0x43c0153e;
+ const MachInst intop_disp_mask = 0x001fe000;
+ const int intop_disp_shift = 13;
+
+ if ((inst & mem_mask) == lda_pattern)
+ disp = -sext<16>(inst & lda_disp_mask);
+ else if ((inst & intop_mask) == addq_pattern)
+ disp = -int((inst & intop_disp_mask) >> intop_disp_shift);
+ else if ((inst & intop_mask) == subq_pattern)
+ disp = int((inst & intop_disp_mask) >> intop_disp_shift);
+ else
+ return false;
+
+ return true;
+}
+
+bool
+StackTrace::decodeSave(MachInst inst, int &reg, int &disp)
+{
+ // lda $stq, disp($sp)
+ //
+ // Opcode<31:26> == 0x08
+ // RA<25:21> == ?
+ // RB<20:16> == 30
+ // Disp<15:0>
+ const MachInst stq_mask = 0xfc1f0000;
+ const MachInst stq_pattern = 0xb41e0000;
+ const MachInst stq_disp_mask = 0x0000ffff;
+ const MachInst reg_mask = 0x03e00000;
+ const int reg_shift = 21;
+
+ if ((inst & stq_mask) == stq_pattern) {
+ reg = (inst & reg_mask) >> reg_shift;
+ disp = sext<16>(inst & stq_disp_mask);
+ } else {
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ * Decode the function prologue for the function we're in, and note
+ * which registers are stored where, and how large the stack frame is.
+ */
+bool
+StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func,
+ int &size, Addr &ra)
+{
+ size = 0;
+ ra = 0;
+
+ for (Addr pc = func; pc < callpc; pc += sizeof(MachInst)) {
+ MachInst inst;
+ CopyOut(xc, (uint8_t *)&inst, pc, sizeof(MachInst));
+
+ int reg, disp;
+ if (decodeStack(inst, disp)) {
+ if (size) {
+ // panic("decoding frame size again");
+ return true;
+ }
+ size += disp;
+ } else if (decodeSave(inst, reg, disp)) {
+ if (!ra && reg == ReturnAddressReg) {
+ CopyOut(xc, (uint8_t *)&ra, sp + disp, sizeof(Addr));
+ if (!ra) {
+ // panic("no return address value pc=%#x\n", pc);
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+#if TRACING_ON
+void
+StackTrace::dump()
+{
+ StringWrap name(xc->cpu->name());
+ SymbolTable *symtab = xc->system->allSymtab;
+
+ DPRINTFN("------ Stack ------\n");
+
+ string symbol;
+ for (int i = 0, size = stack.size(); i < size; ++i) {
+ Addr addr = stack[size - i - 1];
+ if (addr == 1)
+ symbol = "user";
+ else if (addr == 2)
+ symbol = "console";
+ else if (addr == 3)
+ symbol = "unknown";
+ else
+ symtab->findSymbol(addr, symbol);
+
+ DPRINTFN("%#x: %s\n", addr, symbol);
+ }
+}
+#endif
diff --git a/arch/alpha/stacktrace.hh b/arch/alpha/stacktrace.hh
new file mode 100644
index 000000000..5a4741eba
--- /dev/null
+++ b/arch/alpha/stacktrace.hh
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __ARCH_ALPHA_STACKTRACE_HH__
+#define __ARCH_ALPHA_STACKTRACE_HH__
+
+#include "base/trace.hh"
+#include "cpu/static_inst.hh"
+
+class ExecContext;
+class StackTrace;
+class SymbolTable;
+
+class ProcessInfo
+{
+ private:
+ ExecContext *xc;
+
+ int thread_info_size;
+ int task_struct_size;
+ int task_off;
+ int pid_off;
+ int name_off;
+
+ public:
+ ProcessInfo(ExecContext *_xc);
+
+ Addr task(Addr ksp) const;
+ int pid(Addr ksp) const;
+ std::string name(Addr ksp) const;
+};
+
+class StackTrace
+{
+ private:
+ ExecContext *xc;
+ std::vector<Addr> stack;
+
+ private:
+ bool isEntry(Addr addr);
+ bool decodePrologue(Addr sp, Addr callpc, Addr func, int &size, Addr &ra);
+ bool decodeSave(MachInst inst, int &reg, int &disp);
+ bool decodeStack(MachInst inst, int &disp);
+
+ public:
+ StackTrace(ExecContext *xc, bool is_call);
+ ~StackTrace();
+
+ public:
+ const std::vector<Addr> &getstack() const { return stack; }
+ static StackTrace *create(ExecContext *xc, StaticInstPtr<TheISA> inst);
+
+#if TRACING_ON
+ private:
+ void dump();
+
+ public:
+ void dprintf() { if (DTRACE(Stack)) dump(); }
+#else
+ public:
+ void dprintf() {}
+#endif
+};
+
+inline StackTrace *
+StackTrace::create(ExecContext *xc, StaticInstPtr<TheISA> inst)
+{
+ if (!inst->isCall() && !inst->isReturn())
+ return NULL;
+
+ return new StackTrace(xc, !inst->isReturn());
+}
+
+#endif // __ARCH_ALPHA_STACKTRACE_HH__