stacktrace.cc revision 3570
15217Ssaidi@eecs.umich.edu/* 213610Sgiacomo.gabrielli@arm.com * Copyright (c) 2005 The Regents of The University of Michigan 39920Syasuko.eckert@amd.com * All rights reserved. 49428SAndreas.Sandberg@ARM.com * 59428SAndreas.Sandberg@ARM.com * Redistribution and use in source and binary forms, with or without 69428SAndreas.Sandberg@ARM.com * modification, are permitted provided that the following conditions are 79428SAndreas.Sandberg@ARM.com * met: redistributions of source code must retain the above copyright 89428SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer; 99428SAndreas.Sandberg@ARM.com * redistributions in binary form must reproduce the above copyright 109428SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer in the 119428SAndreas.Sandberg@ARM.com * documentation and/or other materials provided with the distribution; 129428SAndreas.Sandberg@ARM.com * neither the name of the copyright holders nor the names of its 139428SAndreas.Sandberg@ARM.com * contributors may be used to endorse or promote products derived from 149428SAndreas.Sandberg@ARM.com * this software without specific prior written permission. 155217Ssaidi@eecs.umich.edu * 165217Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 175217Ssaidi@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 185217Ssaidi@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 195217Ssaidi@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 205217Ssaidi@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 215217Ssaidi@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 225217Ssaidi@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 235217Ssaidi@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 245217Ssaidi@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 255217Ssaidi@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 265217Ssaidi@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 275217Ssaidi@eecs.umich.edu * 285217Ssaidi@eecs.umich.edu * Authors: Nathan Binkert 295217Ssaidi@eecs.umich.edu */ 305217Ssaidi@eecs.umich.edu 315217Ssaidi@eecs.umich.edu#include <string> 325217Ssaidi@eecs.umich.edu 335217Ssaidi@eecs.umich.edu#include "arch/sparc/isa_traits.hh" 345217Ssaidi@eecs.umich.edu#include "arch/sparc/stacktrace.hh" 355217Ssaidi@eecs.umich.edu#include "arch/sparc/vtophys.hh" 365217Ssaidi@eecs.umich.edu#include "base/bitfield.hh" 375217Ssaidi@eecs.umich.edu#include "base/trace.hh" 385217Ssaidi@eecs.umich.edu#include "cpu/base.hh" 395217Ssaidi@eecs.umich.edu#include "cpu/thread_context.hh" 405217Ssaidi@eecs.umich.edu#include "sim/system.hh" 415217Ssaidi@eecs.umich.edu 425217Ssaidi@eecs.umich.eduusing namespace std; 435217Ssaidi@eecs.umich.edunamespace SparcISA 4411793Sbrandon.potter@amd.com{ 4511793Sbrandon.potter@amd.com ProcessInfo::ProcessInfo(ThreadContext *_tc) 4613610Sgiacomo.gabrielli@arm.com : tc(_tc) 4712334Sgabeblack@google.com { 485217Ssaidi@eecs.umich.edu Addr addr = 0; 496658Snate@binkert.org 509441SAndreas.Sandberg@ARM.com VirtualPort *vp; 519441SAndreas.Sandberg@ARM.com 528232Snate@binkert.org vp = tc->getVirtPort(); 5311627Smichael.lebeane@amd.com 5413905Sgabeblack@google.com if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_size", addr)) 5511627Smichael.lebeane@amd.com panic("thread info not compiled into kernel\n"); 569441SAndreas.Sandberg@ARM.com thread_info_size = vp->readGtoH<int32_t>(addr); 575217Ssaidi@eecs.umich.edu 585217Ssaidi@eecs.umich.edu if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_size", addr)) 595217Ssaidi@eecs.umich.edu panic("thread info not compiled into kernel\n"); 605217Ssaidi@eecs.umich.edu task_struct_size = vp->readGtoH<int32_t>(addr); 615217Ssaidi@eecs.umich.edu 625217Ssaidi@eecs.umich.edu if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_task", addr)) 635217Ssaidi@eecs.umich.edu panic("thread info not compiled into kernel\n"); 645217Ssaidi@eecs.umich.edu task_off = vp->readGtoH<int32_t>(addr); 6513557Sgabeblack@google.com 6613557Sgabeblack@google.com if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_pid", addr)) 675217Ssaidi@eecs.umich.edu panic("thread info not compiled into kernel\n"); 685217Ssaidi@eecs.umich.edu pid_off = vp->readGtoH<int32_t>(addr); 695217Ssaidi@eecs.umich.edu 705217Ssaidi@eecs.umich.edu if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_comm", addr)) 715217Ssaidi@eecs.umich.edu panic("thread info not compiled into kernel\n"); 725217Ssaidi@eecs.umich.edu name_off = vp->readGtoH<int32_t>(addr); 735217Ssaidi@eecs.umich.edu 7413611Sgabeblack@google.com tc->delVirtPort(vp); 7513611Sgabeblack@google.com } 765217Ssaidi@eecs.umich.edu 775217Ssaidi@eecs.umich.edu Addr 785217Ssaidi@eecs.umich.edu ProcessInfo::task(Addr ksp) const 795217Ssaidi@eecs.umich.edu { 8012109SRekai.GonzalezAlberquilla@arm.com Addr base = ksp & ~0x3fff; 8112109SRekai.GonzalezAlberquilla@arm.com if (base == ULL(0xfffffc0000000000)) 8212109SRekai.GonzalezAlberquilla@arm.com return 0; 8312109SRekai.GonzalezAlberquilla@arm.com 8412109SRekai.GonzalezAlberquilla@arm.com Addr tsk; 8512109SRekai.GonzalezAlberquilla@arm.com 8612109SRekai.GonzalezAlberquilla@arm.com VirtualPort *vp; 8712109SRekai.GonzalezAlberquilla@arm.com 8812109SRekai.GonzalezAlberquilla@arm.com vp = tc->getVirtPort(); 8912109SRekai.GonzalezAlberquilla@arm.com tsk = vp->readGtoH<Addr>(base + task_off); 9013610Sgiacomo.gabrielli@arm.com tc->delVirtPort(vp); 9113610Sgiacomo.gabrielli@arm.com 9213610Sgiacomo.gabrielli@arm.com return tsk; 9313610Sgiacomo.gabrielli@arm.com } 9413610Sgiacomo.gabrielli@arm.com 9513610Sgiacomo.gabrielli@arm.com int 9613610Sgiacomo.gabrielli@arm.com ProcessInfo::pid(Addr ksp) const 9713610Sgiacomo.gabrielli@arm.com { 9813610Sgiacomo.gabrielli@arm.com Addr task = this->task(ksp); 9913610Sgiacomo.gabrielli@arm.com if (!task) 10013610Sgiacomo.gabrielli@arm.com return -1; 1015217Ssaidi@eecs.umich.edu 10213557Sgabeblack@google.com uint16_t pd; 10313557Sgabeblack@google.com 1045217Ssaidi@eecs.umich.edu VirtualPort *vp; 1055217Ssaidi@eecs.umich.edu 1065217Ssaidi@eecs.umich.edu vp = tc->getVirtPort(); 1075217Ssaidi@eecs.umich.edu pd = vp->readGtoH<uint16_t>(task + pid_off); 1085217Ssaidi@eecs.umich.edu tc->delVirtPort(vp); 1099920Syasuko.eckert@amd.com 1109920Syasuko.eckert@amd.com return pd; 11113622Sgabeblack@google.com } 11213622Sgabeblack@google.com 1139920Syasuko.eckert@amd.com string 1149920Syasuko.eckert@amd.com ProcessInfo::name(Addr ksp) const 1159920Syasuko.eckert@amd.com { 1169920Syasuko.eckert@amd.com Addr task = this->task(ksp); 1177720Sgblack@eecs.umich.edu if (!task) 1187720Sgblack@eecs.umich.edu return "console"; 1195712Shsul@eecs.umich.edu 1205712Shsul@eecs.umich.edu char comm[256]; 1215217Ssaidi@eecs.umich.edu CopyStringOut(tc, comm, task + name_off, sizeof(comm)); 1225217Ssaidi@eecs.umich.edu if (!comm[0]) 1235714Shsul@eecs.umich.edu return "startup"; 12411005Sandreas.sandberg@arm.com 12511005Sandreas.sandberg@arm.com return comm; 12611005Sandreas.sandberg@arm.com } 1275714Shsul@eecs.umich.edu 1285714Shsul@eecs.umich.edu StackTrace::StackTrace() 1295714Shsul@eecs.umich.edu : tc(0), stack(64) 1305217Ssaidi@eecs.umich.edu { 1319428SAndreas.Sandberg@ARM.com } 1329428SAndreas.Sandberg@ARM.com 13311627Smichael.lebeane@amd.com StackTrace::StackTrace(ThreadContext *_tc, StaticInstPtr inst) 13411627Smichael.lebeane@amd.com : tc(0), stack(64) 13511627Smichael.lebeane@amd.com { 13611627Smichael.lebeane@amd.com trace(_tc, inst); 13711627Smichael.lebeane@amd.com } 13811627Smichael.lebeane@amd.com 13911627Smichael.lebeane@amd.com StackTrace::~StackTrace() 14011627Smichael.lebeane@amd.com { 14111627Smichael.lebeane@amd.com } 14213905Sgabeblack@google.com 14311627Smichael.lebeane@amd.com void 14411627Smichael.lebeane@amd.com StackTrace::trace(ThreadContext *_tc, bool is_call) 14511627Smichael.lebeane@amd.com { 14611627Smichael.lebeane@amd.com#if 0 14711627Smichael.lebeane@amd.com tc = _tc; 14811627Smichael.lebeane@amd.com 14911627Smichael.lebeane@amd.com bool usermode = (tc->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0; 15011627Smichael.lebeane@amd.com 15111627Smichael.lebeane@amd.com Addr pc = tc->readNextPC(); 15211627Smichael.lebeane@amd.com bool kernel = tc->getSystemPtr()->kernelStart <= pc && 15311627Smichael.lebeane@amd.com pc <= tc->getSystemPtr()->kernelEnd; 15411627Smichael.lebeane@amd.com 15511627Smichael.lebeane@amd.com if (usermode) { 15611627Smichael.lebeane@amd.com stack.push_back(user); 15711627Smichael.lebeane@amd.com return; 15811627Smichael.lebeane@amd.com } 15911627Smichael.lebeane@amd.com 16011627Smichael.lebeane@amd.com if (!kernel) { 16111627Smichael.lebeane@amd.com stack.push_back(console); 16211627Smichael.lebeane@amd.com return; 16311627Smichael.lebeane@amd.com } 16411627Smichael.lebeane@amd.com 16511627Smichael.lebeane@amd.com SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab; 16613865Sgabeblack@google.com Addr ksp = tc->readIntReg(TheISA::StackPointerReg); 1679428SAndreas.Sandberg@ARM.com Addr bottom = ksp & ~0x3fff; 1689428SAndreas.Sandberg@ARM.com Addr addr; 1699428SAndreas.Sandberg@ARM.com 17013557Sgabeblack@google.com if (is_call) { 1719428SAndreas.Sandberg@ARM.com if (!symtab->findNearestAddr(pc, addr)) 17213611Sgabeblack@google.com panic("could not find address %#x", pc); 1739428SAndreas.Sandberg@ARM.com 1749428SAndreas.Sandberg@ARM.com stack.push_back(addr); 17510905Sandreas.sandberg@arm.com pc = tc->readPC(); 1769428SAndreas.Sandberg@ARM.com } 17712109SRekai.GonzalezAlberquilla@arm.com 17812109SRekai.GonzalezAlberquilla@arm.com Addr ra; 17912109SRekai.GonzalezAlberquilla@arm.com int size; 18012109SRekai.GonzalezAlberquilla@arm.com 18112109SRekai.GonzalezAlberquilla@arm.com while (ksp > bottom) { 18212109SRekai.GonzalezAlberquilla@arm.com if (!symtab->findNearestAddr(pc, addr)) 18313610Sgiacomo.gabrielli@arm.com panic("could not find symbol for pc=%#x", pc); 18413610Sgiacomo.gabrielli@arm.com assert(pc >= addr && "symbol botch: callpc < func"); 18513610Sgiacomo.gabrielli@arm.com 18613610Sgiacomo.gabrielli@arm.com stack.push_back(addr); 18713610Sgiacomo.gabrielli@arm.com 18813610Sgiacomo.gabrielli@arm.com if (isEntry(addr)) 18913557Sgabeblack@google.com return; 1909428SAndreas.Sandberg@ARM.com 1919428SAndreas.Sandberg@ARM.com if (decodePrologue(ksp, pc, addr, size, ra)) { 1929428SAndreas.Sandberg@ARM.com if (!ra) 1939428SAndreas.Sandberg@ARM.com return; 1949920Syasuko.eckert@amd.com 19513622Sgabeblack@google.com if (size <= 0) { 1969920Syasuko.eckert@amd.com stack.push_back(unknown); 1979920Syasuko.eckert@amd.com return; 1989920Syasuko.eckert@amd.com } 1999920Syasuko.eckert@amd.com 2009920Syasuko.eckert@amd.com pc = ra; 20110905Sandreas.sandberg@arm.com ksp += size; 2029428SAndreas.Sandberg@ARM.com } else { 2039428SAndreas.Sandberg@ARM.com stack.push_back(unknown); 2049428SAndreas.Sandberg@ARM.com return; 2059428SAndreas.Sandberg@ARM.com } 2069428SAndreas.Sandberg@ARM.com 20710905Sandreas.sandberg@arm.com bool kernel = tc->getSystemPtr()->kernelStart <= pc && 2089428SAndreas.Sandberg@ARM.com pc <= tc->getSystemPtr()->kernelEnd; 2099428SAndreas.Sandberg@ARM.com if (!kernel) 2109428SAndreas.Sandberg@ARM.com return; 21113557Sgabeblack@google.com 2129428SAndreas.Sandberg@ARM.com if (stack.size() >= 1000) 2139428SAndreas.Sandberg@ARM.com panic("unwinding too far"); 21410905Sandreas.sandberg@arm.com } 2159428SAndreas.Sandberg@ARM.com 21613611Sgabeblack@google.com panic("unwinding too far"); 2179428SAndreas.Sandberg@ARM.com#endif 21812109SRekai.GonzalezAlberquilla@arm.com } 21912109SRekai.GonzalezAlberquilla@arm.com 22012109SRekai.GonzalezAlberquilla@arm.com bool 22112109SRekai.GonzalezAlberquilla@arm.com StackTrace::isEntry(Addr addr) 22212109SRekai.GonzalezAlberquilla@arm.com { 22312109SRekai.GonzalezAlberquilla@arm.com#if 0 22413610Sgiacomo.gabrielli@arm.com if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp12)) 22513610Sgiacomo.gabrielli@arm.com return true; 22613610Sgiacomo.gabrielli@arm.com 22713610Sgiacomo.gabrielli@arm.com if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp7)) 22813610Sgiacomo.gabrielli@arm.com return true; 22913610Sgiacomo.gabrielli@arm.com 23013557Sgabeblack@google.com if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp11)) 2319428SAndreas.Sandberg@ARM.com return true; 2329428SAndreas.Sandberg@ARM.com 2339428SAndreas.Sandberg@ARM.com if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp21)) 2349428SAndreas.Sandberg@ARM.com return true; 2359920Syasuko.eckert@amd.com 23613622Sgabeblack@google.com if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp9)) 2379920Syasuko.eckert@amd.com return true; 2389920Syasuko.eckert@amd.com 2399920Syasuko.eckert@amd.com if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp2)) 2409920Syasuko.eckert@amd.com return true; 2419920Syasuko.eckert@amd.com#endif 2429428SAndreas.Sandberg@ARM.com return false; 24310905Sandreas.sandberg@arm.com } 2449428SAndreas.Sandberg@ARM.com 2459428SAndreas.Sandberg@ARM.com bool 2469428SAndreas.Sandberg@ARM.com StackTrace::decodeStack(MachInst inst, int &disp) 2479428SAndreas.Sandberg@ARM.com { 2489441SAndreas.Sandberg@ARM.com // lda $sp, -disp($sp) 2499441SAndreas.Sandberg@ARM.com // 2509441SAndreas.Sandberg@ARM.com // Opcode<31:26> == 0x08 2519441SAndreas.Sandberg@ARM.com // RA<25:21> == 30 2529441SAndreas.Sandberg@ARM.com // RB<20:16> == 30 2539441SAndreas.Sandberg@ARM.com // Disp<15:0> 2549441SAndreas.Sandberg@ARM.com const MachInst mem_mask = 0xffff0000; 2559441SAndreas.Sandberg@ARM.com const MachInst lda_pattern = 0x23de0000; 2569441SAndreas.Sandberg@ARM.com const MachInst lda_disp_mask = 0x0000ffff; 2579441SAndreas.Sandberg@ARM.com 2589441SAndreas.Sandberg@ARM.com // subq $sp, disp, $sp 2599441SAndreas.Sandberg@ARM.com // addq $sp, disp, $sp 2609441SAndreas.Sandberg@ARM.com // 2619441SAndreas.Sandberg@ARM.com // Opcode<31:26> == 0x10 2629441SAndreas.Sandberg@ARM.com // RA<25:21> == 30 2639441SAndreas.Sandberg@ARM.com // Lit<20:13> 2649441SAndreas.Sandberg@ARM.com // One<12> = 1 2659441SAndreas.Sandberg@ARM.com // Func<11:5> == 0x20 (addq) 2669441SAndreas.Sandberg@ARM.com // Func<11:5> == 0x29 (subq) 2679441SAndreas.Sandberg@ARM.com // RC<4:0> == 30 2689441SAndreas.Sandberg@ARM.com const MachInst intop_mask = 0xffe01fff; 2699441SAndreas.Sandberg@ARM.com const MachInst addq_pattern = 0x43c0141e; 2709441SAndreas.Sandberg@ARM.com const MachInst subq_pattern = 0x43c0153e; 2719441SAndreas.Sandberg@ARM.com const MachInst intop_disp_mask = 0x001fe000; 2729441SAndreas.Sandberg@ARM.com const int intop_disp_shift = 13; 2739441SAndreas.Sandberg@ARM.com 2749441SAndreas.Sandberg@ARM.com if ((inst & mem_mask) == lda_pattern) 2759441SAndreas.Sandberg@ARM.com disp = -sext<16>(inst & lda_disp_mask); 2769441SAndreas.Sandberg@ARM.com else if ((inst & intop_mask) == addq_pattern) 2779441SAndreas.Sandberg@ARM.com disp = -int((inst & intop_disp_mask) >> intop_disp_shift); 2789441SAndreas.Sandberg@ARM.com else if ((inst & intop_mask) == subq_pattern) 2799441SAndreas.Sandberg@ARM.com disp = int((inst & intop_disp_mask) >> intop_disp_shift); 2809441SAndreas.Sandberg@ARM.com else 2819441SAndreas.Sandberg@ARM.com return false; 282 283 return true; 284 } 285 286 bool 287 StackTrace::decodeSave(MachInst inst, int ®, int &disp) 288 { 289 // lda $stq, disp($sp) 290 // 291 // Opcode<31:26> == 0x08 292 // RA<25:21> == ? 293 // RB<20:16> == 30 294 // Disp<15:0> 295 const MachInst stq_mask = 0xfc1f0000; 296 const MachInst stq_pattern = 0xb41e0000; 297 const MachInst stq_disp_mask = 0x0000ffff; 298 const MachInst reg_mask = 0x03e00000; 299 const int reg_shift = 21; 300 301 if ((inst & stq_mask) == stq_pattern) { 302 reg = (inst & reg_mask) >> reg_shift; 303 disp = sext<16>(inst & stq_disp_mask); 304 } else { 305 return false; 306 } 307 308 return true; 309 } 310 311 /* 312 * Decode the function prologue for the function we're in, and note 313 * which registers are stored where, and how large the stack frame is. 314 */ 315 bool 316 StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func, 317 int &size, Addr &ra) 318 { 319 size = 0; 320 ra = 0; 321 322 for (Addr pc = func; pc < callpc; pc += sizeof(MachInst)) { 323 MachInst inst; 324 CopyOut(tc, (uint8_t *)&inst, pc, sizeof(MachInst)); 325 326 int reg, disp; 327 if (decodeStack(inst, disp)) { 328 if (size) { 329 // panic("decoding frame size again"); 330 return true; 331 } 332 size += disp; 333 } else if (decodeSave(inst, reg, disp)) { 334 if (!ra && reg == ReturnAddressReg) { 335 CopyOut(tc, (uint8_t *)&ra, sp + disp, sizeof(Addr)); 336 if (!ra) { 337 // panic("no return address value pc=%#x\n", pc); 338 return false; 339 } 340 } 341 } 342 } 343 344 return true; 345 } 346 347#if TRACING_ON 348 void 349 StackTrace::dump() 350 { 351 StringWrap name(tc->getCpuPtr()->name()); 352 SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab; 353 354 DPRINTFN("------ Stack ------\n"); 355 356 string symbol; 357 for (int i = 0, size = stack.size(); i < size; ++i) { 358 Addr addr = stack[size - i - 1]; 359 if (addr == user) 360 symbol = "user"; 361 else if (addr == console) 362 symbol = "console"; 363 else if (addr == unknown) 364 symbol = "unknown"; 365 else 366 symtab->findSymbol(addr, symbol); 367 368 DPRINTFN("%#x: %s\n", addr, symbol); 369 } 370 } 371#endif 372} 373