gem5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
stacktrace.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2005 The Regents of The University of Michigan
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met: redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer;
9  * redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution;
12  * neither the name of the copyright holders nor the names of its
13  * contributors may be used to endorse or promote products derived from
14  * this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  * Authors: Nathan Binkert
29  */
30 
31 #include "arch/alpha/stacktrace.hh"
32 
33 #include <string>
34 
35 #include "arch/alpha/isa_traits.hh"
36 #include "arch/alpha/vtophys.hh"
37 #include "base/bitfield.hh"
38 #include "base/trace.hh"
39 #include "cpu/base.hh"
40 #include "cpu/thread_context.hh"
42 #include "sim/system.hh"
43 
44 using namespace std;
45 
46 namespace AlphaISA {
47 
48 ProcessInfo::ProcessInfo(ThreadContext *_tc)
49  : tc(_tc)
50 {
51  Addr addr = 0;
54 
55  if (!symtab->findAddress("thread_info_size", addr))
56  panic("thread info not compiled into kernel\n");
57  thread_info_size = vp.readGtoH<int32_t>(addr);
58 
59  if (!symtab->findAddress("task_struct_size", addr))
60  panic("thread info not compiled into kernel\n");
61  task_struct_size = vp.readGtoH<int32_t>(addr);
62 
63  if (!symtab->findAddress("thread_info_task", addr))
64  panic("thread info not compiled into kernel\n");
65  task_off = vp.readGtoH<int32_t>(addr);
66 
67  if (!symtab->findAddress("task_struct_pid", addr))
68  panic("thread info not compiled into kernel\n");
69  pid_off = vp.readGtoH<int32_t>(addr);
70 
71  if (!symtab->findAddress("task_struct_comm", addr))
72  panic("thread info not compiled into kernel\n");
73  name_off = vp.readGtoH<int32_t>(addr);
74 }
75 
76 Addr
78 {
79  Addr base = ksp & ~0x3fff;
80  if (base == ULL(0xfffffc0000000000))
81  return 0;
82 
83  Addr tsk;
84 
86  tsk = vp.readGtoH<Addr>(base + task_off);
87 
88  return tsk;
89 }
90 
91 int
93 {
94  Addr task = this->task(ksp);
95  if (!task)
96  return -1;
97 
98  uint16_t pd;
99 
101  pd = vp.readGtoH<uint16_t>(task + pid_off);
102 
103  return pd;
104 }
105 
106 string
108 {
109  Addr task = this->task(ksp);
110  if (!task)
111  return "console";
112 
113  char comm[256];
114  CopyStringOut(tc, comm, task + name_off, sizeof(comm));
115  if (!comm[0])
116  return "startup";
117 
118  return comm;
119 }
120 
122  : tc(0), stack(64)
123 {
124 }
125 
127  : tc(0), stack(64)
128 {
129  trace(_tc, inst);
130 }
131 
133 {
134 }
135 
136 void
137 StackTrace::trace(ThreadContext *_tc, bool is_call)
138 {
139  tc = _tc;
140 
141  System *sys = tc->getSystemPtr();
142 
143  bool usermode =
144  (tc->readMiscRegNoEffect(IPR_DTB_CM) & 0x18) != 0;
145 
146  Addr pc = tc->pcState().pc();
147  bool kernel = sys->kernelStart <= pc && pc <= sys->kernelEnd;
148 
149  if (usermode) {
150  stack.push_back(user);
151  return;
152  }
153 
154  if (!kernel) {
155  stack.push_back(console);
156  return;
157  }
158 
159  SymbolTable *symtab = sys->kernelSymtab;
161  Addr bottom = ksp & ~0x3fff;
162 
163  if (is_call) {
164  Addr addr;
165  if (!symtab->findNearestAddr(pc, addr))
166  panic("could not find address %#x", pc);
167 
168  stack.push_back(addr);
169  pc = tc->pcState().pc();
170  }
171 
172  while (ksp > bottom) {
173  Addr addr;
174  if (!symtab->findNearestAddr(pc, addr))
175  panic("could not find symbol for pc=%#x", pc);
176  assert(pc >= addr && "symbol botch: callpc < func");
177 
178  stack.push_back(addr);
179 
180  if (isEntry(addr))
181  return;
182 
183  Addr ra;
184  int size;
185  if (decodePrologue(ksp, pc, addr, size, ra)) {
186  if (!ra)
187  return;
188 
189  if (size <= 0) {
190  stack.push_back(unknown);
191  return;
192  }
193 
194  pc = ra;
195  ksp += size;
196  } else {
197  stack.push_back(unknown);
198  return;
199  }
200 
201  kernel = sys->kernelStart <= pc && pc <= sys->kernelEnd;
202  if (!kernel)
203  return;
204 
205  if (stack.size() >= 1000)
206  panic("unwinding too far");
207  }
208 
209  panic("unwinding too far");
210 }
211 
212 bool
214 {
215  if (addr == tc->readMiscRegNoEffect(IPR_PALtemp12))
216  return true;
217 
218  if (addr == tc->readMiscRegNoEffect(IPR_PALtemp7))
219  return true;
220 
221  if (addr == tc->readMiscRegNoEffect(IPR_PALtemp11))
222  return true;
223 
224  if (addr == tc->readMiscRegNoEffect(IPR_PALtemp21))
225  return true;
226 
227  if (addr == tc->readMiscRegNoEffect(IPR_PALtemp9))
228  return true;
229 
230  if (addr == tc->readMiscRegNoEffect(IPR_PALtemp2))
231  return true;
232 
233  return false;
234 }
235 
236 bool
238 {
239  // lda $sp, -disp($sp)
240  //
241  // Opcode<31:26> == 0x08
242  // RA<25:21> == 30
243  // RB<20:16> == 30
244  // Disp<15:0>
245  const MachInst mem_mask = 0xffff0000;
246  const MachInst lda_pattern = 0x23de0000;
247  const MachInst lda_disp_mask = 0x0000ffff;
248 
249  // subq $sp, disp, $sp
250  // addq $sp, disp, $sp
251  //
252  // Opcode<31:26> == 0x10
253  // RA<25:21> == 30
254  // Lit<20:13>
255  // One<12> = 1
256  // Func<11:5> == 0x20 (addq)
257  // Func<11:5> == 0x29 (subq)
258  // RC<4:0> == 30
259  const MachInst intop_mask = 0xffe01fff;
260  const MachInst addq_pattern = 0x43c0141e;
261  const MachInst subq_pattern = 0x43c0153e;
262  const MachInst intop_disp_mask = 0x001fe000;
263  const int intop_disp_shift = 13;
264 
265  if ((inst & mem_mask) == lda_pattern)
266  disp = -sext<16>(inst & lda_disp_mask);
267  else if ((inst & intop_mask) == addq_pattern)
268  disp = -int((inst & intop_disp_mask) >> intop_disp_shift);
269  else if ((inst & intop_mask) == subq_pattern)
270  disp = int((inst & intop_disp_mask) >> intop_disp_shift);
271  else
272  return false;
273 
274  return true;
275 }
276 
277 bool
278 StackTrace::decodeSave(MachInst inst, int &reg, int &disp)
279 {
280  // lda $stq, disp($sp)
281  //
282  // Opcode<31:26> == 0x08
283  // RA<25:21> == ?
284  // RB<20:16> == 30
285  // Disp<15:0>
286  const MachInst stq_mask = 0xfc1f0000;
287  const MachInst stq_pattern = 0xb41e0000;
288  const MachInst stq_disp_mask = 0x0000ffff;
289  const MachInst reg_mask = 0x03e00000;
290  const int reg_shift = 21;
291 
292  if ((inst & stq_mask) == stq_pattern) {
293  reg = (inst & reg_mask) >> reg_shift;
294  disp = sext<16>(inst & stq_disp_mask);
295  } else {
296  return false;
297  }
298 
299  return true;
300 }
301 
302 /*
303  * Decode the function prologue for the function we're in, and note
304  * which registers are stored where, and how large the stack frame is.
305  */
306 bool
308  Addr &ra)
309 {
310  size = 0;
311  ra = 0;
312 
313  for (Addr pc = func; pc < callpc; pc += sizeof(MachInst)) {
314  MachInst inst;
315  CopyOut(tc, (uint8_t *)&inst, pc, sizeof(MachInst));
316 
317  int reg, disp;
318  if (decodeStack(inst, disp)) {
319  if (size) {
320  // panic("decoding frame size again");
321  return true;
322  }
323  size += disp;
324  } else if (decodeSave(inst, reg, disp)) {
325  if (!ra && reg == ReturnAddressReg) {
326  CopyOut(tc, (uint8_t *)&ra, sp + disp, sizeof(Addr));
327  if (!ra) {
328  // panic("no return address value pc=%#x\n", pc);
329  return false;
330  }
331  }
332  }
333  }
334 
335  return true;
336 }
337 
338 #if TRACING_ON
339 void
341 {
342  StringWrap name(tc->getCpuPtr()->name());
343  SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab;
344 
345  DPRINTFN("------ Stack ------\n");
346 
347  string symbol;
348  for (int i = 0, size = stack.size(); i < size; ++i) {
349  Addr addr = stack[size - i - 1];
350  if (addr == user)
351  symbol = "user";
352  else if (addr == console)
353  symbol = "console";
354  else if (addr == unknown)
355  symbol = "unknown";
356  else
357  symtab->findSymbol(addr, symbol);
358 
359  DPRINTFN("%#x: %s\n", addr, symbol);
360  }
361 }
362 #endif
363 
364 } // namespace AlphaISA
A TranslatingPortProxy in FS mode translates a virtual address to a physical address and then calls t...
void trace(ThreadContext *tc, bool is_call)
Definition: stacktrace.cc:137
virtual System * getSystemPtr()=0
Bitfield< 5, 3 > reg
Definition: types.hh:89
const std::string & name()
Definition: trace.cc:49
Bitfield< 7 > i
Definition: miscregs.hh:1378
#define panic(...)
Definition: misc.hh:153
bool decodeStack(MachInst inst, int &disp)
Definition: stacktrace.cc:237
Addr task(Addr ksp) const
Definition: stacktrace.cc:77
ip6_addr_t addr
Definition: inet.hh:335
std::vector< Addr > stack
Definition: stacktrace.hh:67
virtual MiscReg readMiscRegNoEffect(int misc_reg) const =0
Bitfield< 0 > sp
Definition: miscregs.hh:1386
bool isEntry(Addr addr)
Definition: stacktrace.cc:213
Definition: system.hh:83
virtual BaseCPU * getCpuPtr()=0
bool findAddress(const std::string &symbol, Addr &address) const
Definition: symtab.hh:97
bool decodePrologue(Addr sp, Addr callpc, Addr func, int &size, Addr &ra)
Definition: stacktrace.cc:307
virtual TheISA::PCState pcState()=0
void CopyOut(ThreadContext *tc, void *dest, Addr src, size_t cplen)
ThreadContext is the external interface to all thread state for anything outside of the CPU...
#define DPRINTFN(...)
Definition: trace.hh:216
std::string name(Addr ksp) const
Definition: stacktrace.cc:107
const RegIndex ReturnAddressReg
Definition: registers.hh:82
uint32_t MachInst
Definition: types.hh:40
Addr kernelStart
Beginning of kernel code.
Definition: system.hh:233
virtual uint64_t readIntReg(int reg_idx)=0
bool decodeSave(MachInst inst, int &reg, int &disp)
Definition: stacktrace.cc:278
void CopyStringOut(ThreadContext *tc, char *dst, Addr vaddr, size_t maxlen)
Bitfield< 51, 12 > base
Definition: pagetable.hh:85
const RegIndex StackPointerReg
Definition: registers.hh:79
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
#define ULL(N)
uint64_t constant
Definition: types.hh:50
SymbolTable * kernelSymtab
kernel symbol table
Definition: system.hh:227
Bitfield< 20, 16 > ra
Definition: types.hh:47
Bitfield< 17, 16 > stack
Definition: misc.hh:588
ThreadContext * tc
Definition: stacktrace.hh:66
virtual FSTranslatingPortProxy & getVirtProxy()=0
int size()
Definition: pagetable.hh:146
ThreadContext * tc
Definition: stacktrace.hh:47
TranslatingPortProxy Object Declaration for FS.
int pid(Addr ksp) const
Definition: stacktrace.cc:92
IntReg pc
Definition: remote_gdb.hh:91
void dump()
Dump all statistics data to the registered outputs.
Definition: statistics.cc:517
bool findNearestAddr(Addr addr, Addr &symaddr, Addr &nextaddr) const
Definition: symtab.hh:147
Addr kernelEnd
End of kernel code.
Definition: system.hh:236

Generated on Fri Jun 9 2017 13:03:36 for gem5 by doxygen 1.8.6