stacktrace.cc revision 1977
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 29#include <string> 30 31#include "arch/alpha/isa_traits.hh" 32#include "arch/alpha/stacktrace.hh" 33#include "arch/alpha/vtophys.hh" 34#include "base/bitfield.hh" 35#include "base/trace.hh" 36#include "cpu/base.hh" 37#include "cpu/exec_context.hh" 38 39using namespace std; 40 41ProcessInfo::ProcessInfo(ExecContext *_xc) 42 : xc(_xc) 43{ 44 Addr addr = 0; 45 46 if (!xc->system->kernelSymtab->findAddress("thread_info_size", addr)) 47 panic("thread info not compiled into kernel\n"); 48 thread_info_size = *(int32_t *)vtomem(xc, addr, sizeof(int32_t)); 49 50 if (!xc->system->kernelSymtab->findAddress("task_struct_size", addr)) 51 panic("thread info not compiled into kernel\n"); 52 task_struct_size = *(int32_t *)vtomem(xc, addr, sizeof(int32_t)); 53 54 if (!xc->system->kernelSymtab->findAddress("thread_info_task", addr)) 55 panic("thread info not compiled into kernel\n"); 56 task_off = *(int32_t *)vtomem(xc, addr, sizeof(int32_t)); 57 58 if (!xc->system->kernelSymtab->findAddress("task_struct_pid", addr)) 59 panic("thread info not compiled into kernel\n"); 60 pid_off = *(int32_t *)vtomem(xc, addr, sizeof(int32_t)); 61 62 if (!xc->system->kernelSymtab->findAddress("task_struct_comm", addr)) 63 panic("thread info not compiled into kernel\n"); 64 name_off = *(int32_t *)vtomem(xc, addr, sizeof(int32_t)); 65} 66 67Addr 68ProcessInfo::task(Addr ksp) const 69{ 70 Addr base = ksp & ~0x3fff; 71 if (base == ULL(0xfffffc0000000000)) 72 return 0; 73 74 Addr task; 75 CopyOut(xc, &task, base + task_off, sizeof(task)); 76 return task; 77} 78 79int 80ProcessInfo::pid(Addr ksp) const 81{ 82 Addr task = this->task(ksp); 83 if (!task) 84 return -1; 85 86 uint16_t pid; 87 CopyOut(xc, &pid, task + pid_off, sizeof(pid)); 88 return pid; 89} 90 91string 92ProcessInfo::name(Addr ksp) const 93{ 94 Addr task = this->task(ksp); 95 if (!task) 96 return "console"; 97 98 char comm[256]; 99 CopyString(xc, comm, task + name_off, sizeof(comm)); 100 if (!comm[0]) 101 return "startup"; 102 103 return comm; 104} 105 106StackTrace::StackTrace() 107 : xc(0), stack(64) 108{ 109} 110 111StackTrace::StackTrace(ExecContext *_xc, StaticInstPtr<TheISA> inst) 112 : xc(0), stack(64) 113{ 114 trace(_xc, inst); 115} 116 117StackTrace::~StackTrace() 118{ 119} 120 121void 122StackTrace::trace(ExecContext *_xc, bool is_call) 123{ 124 xc = _xc; 125 126 bool usermode = (xc->regs.ipr[AlphaISA::IPR_DTB_CM] & 0x18) != 0; 127 128 Addr pc = xc->regs.npc; 129 bool kernel = xc->system->kernelStart <= pc && pc <= xc->system->kernelEnd; 130 131 if (usermode) { 132 stack.push_back(user); 133 return; 134 } 135 136 if (!kernel) { 137 stack.push_back(console); 138 return; 139 } 140 141 SymbolTable *symtab = xc->system->kernelSymtab; 142 Addr ksp = xc->regs.intRegFile[TheISA::StackPointerReg]; 143 Addr bottom = ksp & ~0x3fff; 144 Addr addr; 145 146 if (is_call) { 147 if (!symtab->findNearestAddr(pc, addr)) 148 panic("could not find address %#x", pc); 149 150 stack.push_back(addr); 151 pc = xc->regs.pc; 152 } 153 154 Addr ra; 155 int size; 156 157 while (ksp > bottom) { 158 if (!symtab->findNearestAddr(pc, addr)) 159 panic("could not find symbol for pc=%#x", pc); 160 assert(pc >= addr && "symbol botch: callpc < func"); 161 162 stack.push_back(addr); 163 164 if (isEntry(addr)) 165 return; 166 167 if (decodePrologue(ksp, pc, addr, size, ra)) { 168 if (!ra) 169 return; 170 171 if (size <= 0) { 172 stack.push_back(unknown); 173 return; 174 } 175 176 pc = ra; 177 ksp += size; 178 } else { 179 stack.push_back(unknown); 180 return; 181 } 182 183 bool kernel = xc->system->kernelStart <= pc && 184 pc <= xc->system->kernelEnd; 185 if (!kernel) 186 return; 187 188 if (stack.size() >= 1000) 189 panic("unwinding too far"); 190 } 191 192 panic("unwinding too far"); 193} 194 195bool 196StackTrace::isEntry(Addr addr) 197{ 198 if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp12]) 199 return true; 200 201 if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp7]) 202 return true; 203 204 if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp11]) 205 return true; 206 207 if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp21]) 208 return true; 209 210 if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp9]) 211 return true; 212 213 if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp2]) 214 return true; 215 216 return false; 217} 218 219bool 220StackTrace::decodeStack(MachInst inst, int &disp) 221{ 222 // lda $sp, -disp($sp) 223 // 224 // Opcode<31:26> == 0x08 225 // RA<25:21> == 30 226 // RB<20:16> == 30 227 // Disp<15:0> 228 const MachInst mem_mask = 0xffff0000; 229 const MachInst lda_pattern = 0x23de0000; 230 const MachInst lda_disp_mask = 0x0000ffff; 231 232 // subq $sp, disp, $sp 233 // addq $sp, disp, $sp 234 // 235 // Opcode<31:26> == 0x10 236 // RA<25:21> == 30 237 // Lit<20:13> 238 // One<12> = 1 239 // Func<11:5> == 0x20 (addq) 240 // Func<11:5> == 0x29 (subq) 241 // RC<4:0> == 30 242 const MachInst intop_mask = 0xffe01fff; 243 const MachInst addq_pattern = 0x43c0141e; 244 const MachInst subq_pattern = 0x43c0153e; 245 const MachInst intop_disp_mask = 0x001fe000; 246 const int intop_disp_shift = 13; 247 248 if ((inst & mem_mask) == lda_pattern) 249 disp = -sext<16>(inst & lda_disp_mask); 250 else if ((inst & intop_mask) == addq_pattern) 251 disp = -int((inst & intop_disp_mask) >> intop_disp_shift); 252 else if ((inst & intop_mask) == subq_pattern) 253 disp = int((inst & intop_disp_mask) >> intop_disp_shift); 254 else 255 return false; 256 257 return true; 258} 259 260bool 261StackTrace::decodeSave(MachInst inst, int ®, int &disp) 262{ 263 // lda $stq, disp($sp) 264 // 265 // Opcode<31:26> == 0x08 266 // RA<25:21> == ? 267 // RB<20:16> == 30 268 // Disp<15:0> 269 const MachInst stq_mask = 0xfc1f0000; 270 const MachInst stq_pattern = 0xb41e0000; 271 const MachInst stq_disp_mask = 0x0000ffff; 272 const MachInst reg_mask = 0x03e00000; 273 const int reg_shift = 21; 274 275 if ((inst & stq_mask) == stq_pattern) { 276 reg = (inst & reg_mask) >> reg_shift; 277 disp = sext<16>(inst & stq_disp_mask); 278 } else { 279 return false; 280 } 281 282 return true; 283} 284 285/* 286 * Decode the function prologue for the function we're in, and note 287 * which registers are stored where, and how large the stack frame is. 288 */ 289bool 290StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func, 291 int &size, Addr &ra) 292{ 293 size = 0; 294 ra = 0; 295 296 for (Addr pc = func; pc < callpc; pc += sizeof(MachInst)) { 297 MachInst inst; 298 CopyOut(xc, (uint8_t *)&inst, pc, sizeof(MachInst)); 299 300 int reg, disp; 301 if (decodeStack(inst, disp)) { 302 if (size) { 303 // panic("decoding frame size again"); 304 return true; 305 } 306 size += disp; 307 } else if (decodeSave(inst, reg, disp)) { 308 if (!ra && reg == ReturnAddressReg) { 309 CopyOut(xc, (uint8_t *)&ra, sp + disp, sizeof(Addr)); 310 if (!ra) { 311 // panic("no return address value pc=%#x\n", pc); 312 return false; 313 } 314 } 315 } 316 } 317 318 return true; 319} 320 321#if TRACING_ON 322void 323StackTrace::dump() 324{ 325 StringWrap name(xc->cpu->name()); 326 SymbolTable *symtab = xc->system->kernelSymtab; 327 328 DPRINTFN("------ Stack ------\n"); 329 330 string symbol; 331 for (int i = 0, size = stack.size(); i < size; ++i) { 332 Addr addr = stack[size - i - 1]; 333 if (addr == user) 334 symbol = "user"; 335 else if (addr == console) 336 symbol = "console"; 337 else if (addr == unknown) 338 symbol = "unknown"; 339 else 340 symtab->findSymbol(addr, symbol); 341 342 DPRINTFN("%#x: %s\n", addr, symbol); 343 } 344} 345#endif 346