stacktrace.cc revision 2684
11917SN/A/* 21917SN/A * Copyright (c) 2005 The Regents of The University of Michigan 31917SN/A * All rights reserved. 41917SN/A * 51917SN/A * Redistribution and use in source and binary forms, with or without 61917SN/A * modification, are permitted provided that the following conditions are 71917SN/A * met: redistributions of source code must retain the above copyright 81917SN/A * notice, this list of conditions and the following disclaimer; 91917SN/A * redistributions in binary form must reproduce the above copyright 101917SN/A * notice, this list of conditions and the following disclaimer in the 111917SN/A * documentation and/or other materials provided with the distribution; 121917SN/A * neither the name of the copyright holders nor the names of its 131917SN/A * contributors may be used to endorse or promote products derived from 141917SN/A * this software without specific prior written permission. 151917SN/A * 161917SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 171917SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 181917SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 191917SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 201917SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 211917SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 221917SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 231917SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 241917SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 251917SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 261917SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * Authors: Nathan Binkert 291917SN/A */ 301917SN/A 311917SN/A#include <string> 321917SN/A 331917SN/A#include "arch/alpha/isa_traits.hh" 341917SN/A#include "arch/alpha/stacktrace.hh" 351917SN/A#include "arch/alpha/vtophys.hh" 361917SN/A#include "base/bitfield.hh" 371917SN/A#include "base/trace.hh" 381917SN/A#include "cpu/base.hh" 392680Sktlim@umich.edu#include "cpu/thread_context.hh" 402235SN/A#include "sim/system.hh" 411917SN/A 421917SN/Ausing namespace std; 432107SN/Ausing namespace AlphaISA; 441917SN/A 452680Sktlim@umich.eduProcessInfo::ProcessInfo(ThreadContext *_tc) 462680Sktlim@umich.edu : tc(_tc) 471917SN/A{ 481917SN/A Addr addr = 0; 491917SN/A 502684Ssaidi@eecs.umich.edu VirtualPort *vp; 512684Ssaidi@eecs.umich.edu 522684Ssaidi@eecs.umich.edu vp = tc->getVirtPort(); 532684Ssaidi@eecs.umich.edu 542680Sktlim@umich.edu if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_size", addr)) 551917SN/A panic("thread info not compiled into kernel\n"); 562684Ssaidi@eecs.umich.edu thread_info_size = vp->readGtoH<int32_t>(addr); 571917SN/A 582680Sktlim@umich.edu if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_size", addr)) 591917SN/A panic("thread info not compiled into kernel\n"); 602684Ssaidi@eecs.umich.edu task_struct_size = vp->readGtoH<int32_t>(addr); 611917SN/A 622680Sktlim@umich.edu if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_task", addr)) 631917SN/A panic("thread info not compiled into kernel\n"); 642684Ssaidi@eecs.umich.edu task_off = vp->readGtoH<int32_t>(addr); 651917SN/A 662680Sktlim@umich.edu if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_pid", addr)) 671917SN/A panic("thread info not compiled into kernel\n"); 682684Ssaidi@eecs.umich.edu pid_off = vp->readGtoH<int32_t>(addr); 691917SN/A 702680Sktlim@umich.edu if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_comm", addr)) 711917SN/A panic("thread info not compiled into kernel\n"); 722684Ssaidi@eecs.umich.edu name_off = vp->readGtoH<int32_t>(addr); 732684Ssaidi@eecs.umich.edu 742684Ssaidi@eecs.umich.edu tc->delVirtPort(vp); 751917SN/A} 761917SN/A 771917SN/AAddr 781917SN/AProcessInfo::task(Addr ksp) const 791917SN/A{ 801917SN/A Addr base = ksp & ~0x3fff; 811917SN/A if (base == ULL(0xfffffc0000000000)) 821917SN/A return 0; 831917SN/A 842684Ssaidi@eecs.umich.edu Addr tsk; 852684Ssaidi@eecs.umich.edu 862684Ssaidi@eecs.umich.edu VirtualPort *vp; 872684Ssaidi@eecs.umich.edu 882684Ssaidi@eecs.umich.edu vp = tc->getVirtPort(); 892684Ssaidi@eecs.umich.edu tsk = vp->readGtoH<Addr>(base + task_off); 902684Ssaidi@eecs.umich.edu tc->delVirtPort(vp); 912684Ssaidi@eecs.umich.edu 922684Ssaidi@eecs.umich.edu return tsk; 931917SN/A} 941917SN/A 951917SN/Aint 961917SN/AProcessInfo::pid(Addr ksp) const 971917SN/A{ 981917SN/A Addr task = this->task(ksp); 991917SN/A if (!task) 1001917SN/A return -1; 1011917SN/A 1022684Ssaidi@eecs.umich.edu uint16_t pd; 1032684Ssaidi@eecs.umich.edu 1042684Ssaidi@eecs.umich.edu VirtualPort *vp; 1052684Ssaidi@eecs.umich.edu 1062684Ssaidi@eecs.umich.edu vp = tc->getVirtPort(); 1072684Ssaidi@eecs.umich.edu pd = vp->readGtoH<uint16_t>(task + pid_off); 1082684Ssaidi@eecs.umich.edu tc->delVirtPort(vp); 1092684Ssaidi@eecs.umich.edu 1102684Ssaidi@eecs.umich.edu return pd; 1111917SN/A} 1121917SN/A 1131917SN/Astring 1141917SN/AProcessInfo::name(Addr ksp) const 1151917SN/A{ 1161917SN/A Addr task = this->task(ksp); 1171917SN/A if (!task) 1181917SN/A return "console"; 1191917SN/A 1201917SN/A char comm[256]; 1212680Sktlim@umich.edu CopyStringOut(tc, comm, task + name_off, sizeof(comm)); 1221917SN/A if (!comm[0]) 1231917SN/A return "startup"; 1241917SN/A 1251917SN/A return comm; 1261917SN/A} 1271917SN/A 1281977SN/AStackTrace::StackTrace() 1292680Sktlim@umich.edu : tc(0), stack(64) 1301917SN/A{ 1311977SN/A} 1321977SN/A 1332680Sktlim@umich.eduStackTrace::StackTrace(ThreadContext *_tc, StaticInstPtr inst) 1342680Sktlim@umich.edu : tc(0), stack(64) 1351977SN/A{ 1362680Sktlim@umich.edu trace(_tc, inst); 1371977SN/A} 1381977SN/A 1391977SN/AStackTrace::~StackTrace() 1401977SN/A{ 1411977SN/A} 1421977SN/A 1431977SN/Avoid 1442680Sktlim@umich.eduStackTrace::trace(ThreadContext *_tc, bool is_call) 1451977SN/A{ 1462680Sktlim@umich.edu tc = _tc; 1471977SN/A 1482680Sktlim@umich.edu bool usermode = (tc->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0; 1491917SN/A 1502680Sktlim@umich.edu Addr pc = tc->readNextPC(); 1512680Sktlim@umich.edu bool kernel = tc->getSystemPtr()->kernelStart <= pc && 1522680Sktlim@umich.edu pc <= tc->getSystemPtr()->kernelEnd; 1531917SN/A 1541917SN/A if (usermode) { 1551977SN/A stack.push_back(user); 1561917SN/A return; 1571917SN/A } 1581917SN/A 1591917SN/A if (!kernel) { 1601977SN/A stack.push_back(console); 1611917SN/A return; 1621917SN/A } 1631917SN/A 1642680Sktlim@umich.edu SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab; 1652680Sktlim@umich.edu Addr ksp = tc->readIntReg(TheISA::StackPointerReg); 1661917SN/A Addr bottom = ksp & ~0x3fff; 1671917SN/A Addr addr; 1681917SN/A 1691917SN/A if (is_call) { 1701917SN/A if (!symtab->findNearestAddr(pc, addr)) 1711917SN/A panic("could not find address %#x", pc); 1721917SN/A 1731917SN/A stack.push_back(addr); 1742680Sktlim@umich.edu pc = tc->readPC(); 1751917SN/A } 1761917SN/A 1771917SN/A Addr ra; 1781917SN/A int size; 1791917SN/A 1801917SN/A while (ksp > bottom) { 1811917SN/A if (!symtab->findNearestAddr(pc, addr)) 1821917SN/A panic("could not find symbol for pc=%#x", pc); 1831917SN/A assert(pc >= addr && "symbol botch: callpc < func"); 1841917SN/A 1851917SN/A stack.push_back(addr); 1861917SN/A 1871917SN/A if (isEntry(addr)) 1881917SN/A return; 1891917SN/A 1901917SN/A if (decodePrologue(ksp, pc, addr, size, ra)) { 1911917SN/A if (!ra) 1921917SN/A return; 1931917SN/A 1941977SN/A if (size <= 0) { 1951977SN/A stack.push_back(unknown); 1961977SN/A return; 1971977SN/A } 1981977SN/A 1991917SN/A pc = ra; 2001917SN/A ksp += size; 2011917SN/A } else { 2021977SN/A stack.push_back(unknown); 2031917SN/A return; 2041917SN/A } 2051917SN/A 2062680Sktlim@umich.edu bool kernel = tc->getSystemPtr()->kernelStart <= pc && 2072680Sktlim@umich.edu pc <= tc->getSystemPtr()->kernelEnd; 2081917SN/A if (!kernel) 2091917SN/A return; 2101977SN/A 2111977SN/A if (stack.size() >= 1000) 2121977SN/A panic("unwinding too far"); 2131917SN/A } 2141917SN/A 2151917SN/A panic("unwinding too far"); 2161917SN/A} 2171917SN/A 2181917SN/Abool 2191917SN/AStackTrace::isEntry(Addr addr) 2201917SN/A{ 2212680Sktlim@umich.edu if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp12)) 2221917SN/A return true; 2231917SN/A 2242680Sktlim@umich.edu if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp7)) 2251917SN/A return true; 2261917SN/A 2272680Sktlim@umich.edu if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp11)) 2281917SN/A return true; 2291917SN/A 2302680Sktlim@umich.edu if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp21)) 2311917SN/A return true; 2321917SN/A 2332680Sktlim@umich.edu if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp9)) 2341917SN/A return true; 2351917SN/A 2362680Sktlim@umich.edu if (addr == tc->readMiscReg(AlphaISA::IPR_PALtemp2)) 2371917SN/A return true; 2381917SN/A 2391917SN/A return false; 2401917SN/A} 2411917SN/A 2421917SN/Abool 2431917SN/AStackTrace::decodeStack(MachInst inst, int &disp) 2441917SN/A{ 2451917SN/A // lda $sp, -disp($sp) 2461917SN/A // 2471917SN/A // Opcode<31:26> == 0x08 2481917SN/A // RA<25:21> == 30 2491917SN/A // RB<20:16> == 30 2501917SN/A // Disp<15:0> 2511917SN/A const MachInst mem_mask = 0xffff0000; 2521917SN/A const MachInst lda_pattern = 0x23de0000; 2531917SN/A const MachInst lda_disp_mask = 0x0000ffff; 2541917SN/A 2551917SN/A // subq $sp, disp, $sp 2561917SN/A // addq $sp, disp, $sp 2571917SN/A // 2581917SN/A // Opcode<31:26> == 0x10 2591917SN/A // RA<25:21> == 30 2601917SN/A // Lit<20:13> 2611917SN/A // One<12> = 1 2621917SN/A // Func<11:5> == 0x20 (addq) 2631917SN/A // Func<11:5> == 0x29 (subq) 2641917SN/A // RC<4:0> == 30 2651917SN/A const MachInst intop_mask = 0xffe01fff; 2661917SN/A const MachInst addq_pattern = 0x43c0141e; 2671917SN/A const MachInst subq_pattern = 0x43c0153e; 2681917SN/A const MachInst intop_disp_mask = 0x001fe000; 2691917SN/A const int intop_disp_shift = 13; 2701917SN/A 2711917SN/A if ((inst & mem_mask) == lda_pattern) 2721917SN/A disp = -sext<16>(inst & lda_disp_mask); 2731917SN/A else if ((inst & intop_mask) == addq_pattern) 2741917SN/A disp = -int((inst & intop_disp_mask) >> intop_disp_shift); 2751917SN/A else if ((inst & intop_mask) == subq_pattern) 2761917SN/A disp = int((inst & intop_disp_mask) >> intop_disp_shift); 2771917SN/A else 2781917SN/A return false; 2791917SN/A 2801917SN/A return true; 2811917SN/A} 2821917SN/A 2831917SN/Abool 2841917SN/AStackTrace::decodeSave(MachInst inst, int ®, int &disp) 2851917SN/A{ 2861917SN/A // lda $stq, disp($sp) 2871917SN/A // 2881917SN/A // Opcode<31:26> == 0x08 2891917SN/A // RA<25:21> == ? 2901917SN/A // RB<20:16> == 30 2911917SN/A // Disp<15:0> 2921917SN/A const MachInst stq_mask = 0xfc1f0000; 2931917SN/A const MachInst stq_pattern = 0xb41e0000; 2941917SN/A const MachInst stq_disp_mask = 0x0000ffff; 2951917SN/A const MachInst reg_mask = 0x03e00000; 2961917SN/A const int reg_shift = 21; 2971917SN/A 2981917SN/A if ((inst & stq_mask) == stq_pattern) { 2991917SN/A reg = (inst & reg_mask) >> reg_shift; 3001917SN/A disp = sext<16>(inst & stq_disp_mask); 3011917SN/A } else { 3021917SN/A return false; 3031917SN/A } 3041917SN/A 3051917SN/A return true; 3061917SN/A} 3071917SN/A 3081917SN/A/* 3091917SN/A * Decode the function prologue for the function we're in, and note 3101917SN/A * which registers are stored where, and how large the stack frame is. 3111917SN/A */ 3121917SN/Abool 3131917SN/AStackTrace::decodePrologue(Addr sp, Addr callpc, Addr func, 3141917SN/A int &size, Addr &ra) 3151917SN/A{ 3161917SN/A size = 0; 3171917SN/A ra = 0; 3181917SN/A 3191917SN/A for (Addr pc = func; pc < callpc; pc += sizeof(MachInst)) { 3201917SN/A MachInst inst; 3212680Sktlim@umich.edu CopyOut(tc, (uint8_t *)&inst, pc, sizeof(MachInst)); 3221917SN/A 3231917SN/A int reg, disp; 3241917SN/A if (decodeStack(inst, disp)) { 3251917SN/A if (size) { 3261917SN/A // panic("decoding frame size again"); 3271917SN/A return true; 3281917SN/A } 3291917SN/A size += disp; 3301917SN/A } else if (decodeSave(inst, reg, disp)) { 3311917SN/A if (!ra && reg == ReturnAddressReg) { 3322680Sktlim@umich.edu CopyOut(tc, (uint8_t *)&ra, sp + disp, sizeof(Addr)); 3331917SN/A if (!ra) { 3341917SN/A // panic("no return address value pc=%#x\n", pc); 3351917SN/A return false; 3361917SN/A } 3371917SN/A } 3381917SN/A } 3391917SN/A } 3401917SN/A 3411917SN/A return true; 3421917SN/A} 3431917SN/A 3441917SN/A#if TRACING_ON 3451917SN/Avoid 3461917SN/AStackTrace::dump() 3471917SN/A{ 3482680Sktlim@umich.edu StringWrap name(tc->getCpuPtr()->name()); 3492680Sktlim@umich.edu SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab; 3501917SN/A 3511917SN/A DPRINTFN("------ Stack ------\n"); 3521917SN/A 3531917SN/A string symbol; 3541917SN/A for (int i = 0, size = stack.size(); i < size; ++i) { 3551917SN/A Addr addr = stack[size - i - 1]; 3561977SN/A if (addr == user) 3571917SN/A symbol = "user"; 3581977SN/A else if (addr == console) 3591917SN/A symbol = "console"; 3601977SN/A else if (addr == unknown) 3611917SN/A symbol = "unknown"; 3621917SN/A else 3631917SN/A symtab->findSymbol(addr, symbol); 3641917SN/A 3651917SN/A DPRINTFN("%#x: %s\n", addr, symbol); 3661917SN/A } 3671917SN/A} 3681917SN/A#endif 369