stacktrace.cc revision 2665:a124942bacb8
12600SN/A/* 22600SN/A * Copyright (c) 2005 The Regents of The University of Michigan 32600SN/A * All rights reserved. 42600SN/A * 52600SN/A * Redistribution and use in source and binary forms, with or without 62600SN/A * modification, are permitted provided that the following conditions are 72600SN/A * met: redistributions of source code must retain the above copyright 82600SN/A * notice, this list of conditions and the following disclaimer; 92600SN/A * redistributions in binary form must reproduce the above copyright 102600SN/A * notice, this list of conditions and the following disclaimer in the 112600SN/A * documentation and/or other materials provided with the distribution; 122600SN/A * neither the name of the copyright holders nor the names of its 132600SN/A * contributors may be used to endorse or promote products derived from 142600SN/A * this software without specific prior written permission. 152600SN/A * 162600SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172600SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182600SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192600SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202600SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212600SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222600SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232600SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242600SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252600SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262600SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * Authors: Nathan Binkert 292600SN/A */ 302600SN/A 312600SN/A#include <string> 322600SN/A 332600SN/A#include "arch/alpha/isa_traits.hh" 342600SN/A#include "arch/alpha/stacktrace.hh" 352600SN/A#include "arch/alpha/vtophys.hh" 362680Sktlim@umich.edu#include "base/bitfield.hh" 372600SN/A#include "base/trace.hh" 382600SN/A#include "cpu/base.hh" 392600SN/A#include "cpu/exec_context.hh" 402600SN/A#include "sim/system.hh" 412600SN/A 422600SN/Ausing namespace std; 432600SN/Ausing namespace AlphaISA; 442600SN/A 452600SN/AProcessInfo::ProcessInfo(ExecContext *_xc) 462600SN/A : xc(_xc) 472600SN/A{ 483114Sgblack@eecs.umich.edu Addr addr = 0; 492680Sktlim@umich.edu 502600SN/A if (!xc->getSystemPtr()->kernelSymtab->findAddress("thread_info_size", addr)) 512680Sktlim@umich.edu panic("thread info not compiled into kernel\n"); 522600SN/A thread_info_size = gtoh(xc->getVirtPort()->read<int32_t>(addr)); 532600SN/A 542600SN/A if (!xc->getSystemPtr()->kernelSymtab->findAddress("task_struct_size", addr)) 552600SN/A panic("thread info not compiled into kernel\n"); 562600SN/A task_struct_size = gtoh(xc->getVirtPort()->read<int32_t>(addr)); 572600SN/A 582600SN/A if (!xc->getSystemPtr()->kernelSymtab->findAddress("thread_info_task", addr)) 592680Sktlim@umich.edu panic("thread info not compiled into kernel\n"); 602600SN/A task_off = gtoh(xc->getVirtPort()->read<int32_t>(addr)); 612600SN/A 622600SN/A if (!xc->getSystemPtr()->kernelSymtab->findAddress("task_struct_pid", addr)) 632600SN/A panic("thread info not compiled into kernel\n"); 642600SN/A pid_off = gtoh(xc->getVirtPort()->read<int32_t>(addr)); 652600SN/A 662600SN/A if (!xc->getSystemPtr()->kernelSymtab->findAddress("task_struct_comm", addr)) 672600SN/A panic("thread info not compiled into kernel\n"); 682600SN/A name_off = gtoh(xc->getVirtPort()->read<int32_t>(addr)); 692600SN/A} 702600SN/A 712600SN/AAddr 722600SN/AProcessInfo::task(Addr ksp) const 732600SN/A{ 742600SN/A Addr base = ksp & ~0x3fff; 752600SN/A if (base == ULL(0xfffffc0000000000)) 762600SN/A return 0; 772600SN/A 782600SN/A return gtoh(xc->getVirtPort()->read<Addr>(base + task_off)); 792600SN/A} 802600SN/A 812600SN/Aint 822600SN/AProcessInfo::pid(Addr ksp) const 835748SSteve.Reinhardt@amd.com{ 842600SN/A Addr task = this->task(ksp); 852600SN/A if (!task) 862600SN/A return -1; 872600SN/A 882600SN/A return gtoh(xc->getVirtPort()->read<uint16_t>(task + pid_off)); 892600SN/A} 902600SN/A 912600SN/Astring 922600SN/AProcessInfo::name(Addr ksp) const 932600SN/A{ 942600SN/A Addr task = this->task(ksp); 952600SN/A if (!task) 962600SN/A return "console"; 972600SN/A 982600SN/A char comm[256]; 992600SN/A CopyStringOut(xc, comm, task + name_off, sizeof(comm)); 1002600SN/A if (!comm[0]) 1012600SN/A return "startup"; 1022600SN/A 1032600SN/A return comm; 1042600SN/A} 1052600SN/A 1062600SN/AStackTrace::StackTrace() 1072600SN/A : xc(0), stack(64) 1082600SN/A{ 1092600SN/A} 1102600SN/A 1112600SN/AStackTrace::StackTrace(ExecContext *_xc, StaticInstPtr inst) 1122600SN/A : xc(0), stack(64) 1132600SN/A{ 1142600SN/A trace(_xc, inst); 1152600SN/A} 1162600SN/A 1172600SN/AStackTrace::~StackTrace() 1182600SN/A{ 1192600SN/A} 1202600SN/A 1212600SN/Avoid 1222600SN/AStackTrace::trace(ExecContext *_xc, bool is_call) 1232600SN/A{ 1242600SN/A xc = _xc; 1252600SN/A 1265513SMichael.Adler@intel.com bool usermode = (xc->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0; 1272600SN/A 1282600SN/A Addr pc = xc->readNextPC(); 1292600SN/A bool kernel = xc->getSystemPtr()->kernelStart <= pc && 1302600SN/A pc <= xc->getSystemPtr()->kernelEnd; 1312600SN/A 1322600SN/A if (usermode) { 1332600SN/A stack.push_back(user); 1342600SN/A return; 1352600SN/A } 1362600SN/A 1372600SN/A if (!kernel) { 1382600SN/A stack.push_back(console); 1392600SN/A return; 1402600SN/A } 1412600SN/A 1422600SN/A SymbolTable *symtab = xc->getSystemPtr()->kernelSymtab; 1432600SN/A Addr ksp = xc->readIntReg(TheISA::StackPointerReg); 1442600SN/A Addr bottom = ksp & ~0x3fff; 1452600SN/A Addr addr; 1462600SN/A 1472600SN/A if (is_call) { 1482600SN/A if (!symtab->findNearestAddr(pc, addr)) 1492600SN/A panic("could not find address %#x", pc); 1502600SN/A 1512600SN/A stack.push_back(addr); 1522600SN/A pc = xc->readPC(); 1532600SN/A } 1542600SN/A 1552600SN/A Addr ra; 1565513SMichael.Adler@intel.com int size; 1572600SN/A 1582600SN/A while (ksp > bottom) { 1592600SN/A if (!symtab->findNearestAddr(pc, addr)) 1602600SN/A panic("could not find symbol for pc=%#x", pc); 1612600SN/A assert(pc >= addr && "symbol botch: callpc < func"); 1622600SN/A 1632600SN/A stack.push_back(addr); 1642600SN/A 1652600SN/A if (isEntry(addr)) 1662600SN/A return; 1672600SN/A 1682600SN/A if (decodePrologue(ksp, pc, addr, size, ra)) { 1692600SN/A if (!ra) 1702600SN/A return; 1712600SN/A 1722600SN/A if (size <= 0) { 1732600SN/A stack.push_back(unknown); 1742600SN/A return; 1752600SN/A } 1762600SN/A 1772600SN/A pc = ra; 1782600SN/A ksp += size; 1792600SN/A } else { 1802600SN/A stack.push_back(unknown); 1812600SN/A return; 1822600SN/A } 1832600SN/A 1842600SN/A bool kernel = xc->getSystemPtr()->kernelStart <= pc && 1852600SN/A pc <= xc->getSystemPtr()->kernelEnd; 1862600SN/A if (!kernel) 1872600SN/A return; 1882600SN/A 1892600SN/A if (stack.size() >= 1000) 1902600SN/A panic("unwinding too far"); 1912600SN/A } 1922600SN/A 1932600SN/A panic("unwinding too far"); 1942600SN/A} 1952600SN/A 1962600SN/Abool 1972600SN/AStackTrace::isEntry(Addr addr) 1982600SN/A{ 1992600SN/A if (addr == xc->readMiscReg(AlphaISA::IPR_PALtemp12)) 2002600SN/A return true; 2012600SN/A 2022600SN/A if (addr == xc->readMiscReg(AlphaISA::IPR_PALtemp7)) 2032600SN/A return true; 2042600SN/A 2052600SN/A if (addr == xc->readMiscReg(AlphaISA::IPR_PALtemp11)) 2062600SN/A return true; 2072600SN/A 2082600SN/A if (addr == xc->readMiscReg(AlphaISA::IPR_PALtemp21)) 2092600SN/A return true; 2102600SN/A 2112600SN/A if (addr == xc->readMiscReg(AlphaISA::IPR_PALtemp9)) 2122600SN/A return true; 2132600SN/A 2142600SN/A if (addr == xc->readMiscReg(AlphaISA::IPR_PALtemp2)) 2152600SN/A return true; 2162600SN/A 2172600SN/A return false; 2182600SN/A} 2192600SN/A 2202600SN/Abool 2212600SN/AStackTrace::decodeStack(MachInst inst, int &disp) 2222600SN/A{ 2232600SN/A // lda $sp, -disp($sp) 2242600SN/A // 2252600SN/A // Opcode<31:26> == 0x08 2262600SN/A // RA<25:21> == 30 2272600SN/A // RB<20:16> == 30 2282600SN/A // Disp<15:0> 2292600SN/A const MachInst mem_mask = 0xffff0000; 2302600SN/A const MachInst lda_pattern = 0x23de0000; 2312600SN/A const MachInst lda_disp_mask = 0x0000ffff; 2322600SN/A 2332600SN/A // subq $sp, disp, $sp 2342600SN/A // addq $sp, disp, $sp 2352600SN/A // 2362600SN/A // Opcode<31:26> == 0x10 2372600SN/A // RA<25:21> == 30 2382600SN/A // Lit<20:13> 2392600SN/A // One<12> = 1 2402600SN/A // Func<11:5> == 0x20 (addq) 2412600SN/A // Func<11:5> == 0x29 (subq) 2422600SN/A // RC<4:0> == 30 2432600SN/A const MachInst intop_mask = 0xffe01fff; 2442600SN/A const MachInst addq_pattern = 0x43c0141e; 2452600SN/A const MachInst subq_pattern = 0x43c0153e; 2462600SN/A const MachInst intop_disp_mask = 0x001fe000; 2472600SN/A const int intop_disp_shift = 13; 2482600SN/A 2492600SN/A if ((inst & mem_mask) == lda_pattern) 2502600SN/A disp = -sext<16>(inst & lda_disp_mask); 2512600SN/A else if ((inst & intop_mask) == addq_pattern) 2522600SN/A disp = -int((inst & intop_disp_mask) >> intop_disp_shift); 2532600SN/A else if ((inst & intop_mask) == subq_pattern) 2542600SN/A disp = int((inst & intop_disp_mask) >> intop_disp_shift); 2552600SN/A else 2562600SN/A return false; 2572600SN/A 2582600SN/A return true; 2592600SN/A} 2602600SN/A 2612600SN/Abool 2622600SN/AStackTrace::decodeSave(MachInst inst, int ®, int &disp) 2632600SN/A{ 2642600SN/A // lda $stq, disp($sp) 2652600SN/A // 2662600SN/A // Opcode<31:26> == 0x08 2672600SN/A // RA<25:21> == ? 2682600SN/A // RB<20:16> == 30 2692600SN/A // Disp<15:0> 2702600SN/A const MachInst stq_mask = 0xfc1f0000; 2712600SN/A const MachInst stq_pattern = 0xb41e0000; 2722600SN/A const MachInst stq_disp_mask = 0x0000ffff; 2732600SN/A const MachInst reg_mask = 0x03e00000; 2742600SN/A const int reg_shift = 21; 2752600SN/A 2762600SN/A if ((inst & stq_mask) == stq_pattern) { 2772600SN/A reg = (inst & reg_mask) >> reg_shift; 2782600SN/A disp = sext<16>(inst & stq_disp_mask); 2792600SN/A } else { 2802600SN/A return false; 2812600SN/A } 2822600SN/A 2832600SN/A return true; 2842600SN/A} 2852600SN/A 2862600SN/A/* 2872600SN/A * Decode the function prologue for the function we're in, and note 2882600SN/A * which registers are stored where, and how large the stack frame is. 2892600SN/A */ 2902600SN/Abool 2912600SN/AStackTrace::decodePrologue(Addr sp, Addr callpc, Addr func, 2922600SN/A int &size, Addr &ra) 2932600SN/A{ 2942600SN/A size = 0; 2952600SN/A ra = 0; 2962600SN/A 2972600SN/A for (Addr pc = func; pc < callpc; pc += sizeof(MachInst)) { 2982600SN/A MachInst inst; 2992600SN/A CopyOut(xc, (uint8_t *)&inst, pc, sizeof(MachInst)); 3002600SN/A 3012600SN/A int reg, disp; 3022600SN/A if (decodeStack(inst, disp)) { 3032600SN/A if (size) { 3042600SN/A // panic("decoding frame size again"); 3052600SN/A return true; 3062600SN/A } 3072600SN/A size += disp; 3082600SN/A } else if (decodeSave(inst, reg, disp)) { 3092600SN/A if (!ra && reg == ReturnAddressReg) { 3102600SN/A CopyOut(xc, (uint8_t *)&ra, sp + disp, sizeof(Addr)); 3112600SN/A if (!ra) { 3122600SN/A // panic("no return address value pc=%#x\n", pc); 3132600SN/A return false; 3142600SN/A } 3152600SN/A } 3162600SN/A } 3172600SN/A } 3182600SN/A 3192600SN/A return true; 3202600SN/A} 3212600SN/A 3222600SN/A#if TRACING_ON 3232600SN/Avoid 3245154Sgblack@eecs.umich.eduStackTrace::dump() 3255154Sgblack@eecs.umich.edu{ 3265154Sgblack@eecs.umich.edu StringWrap name(xc->getCpuPtr()->name()); 3272600SN/A SymbolTable *symtab = xc->getSystemPtr()->kernelSymtab; 3282600SN/A 3292600SN/A DPRINTFN("------ Stack ------\n"); 3302600SN/A 3312600SN/A string symbol; 3322600SN/A for (int i = 0, size = stack.size(); i < size; ++i) { 3332600SN/A Addr addr = stack[size - i - 1]; 3342600SN/A if (addr == user) 3352600SN/A symbol = "user"; 3362600SN/A else if (addr == console) 3372600SN/A symbol = "console"; 3382600SN/A else if (addr == unknown) 3392600SN/A symbol = "unknown"; 3402600SN/A else 3412600SN/A symtab->findSymbol(addr, symbol); 3422600SN/A 343 DPRINTFN("%#x: %s\n", addr, symbol); 344 } 345} 346#endif 347