stacktrace.cc revision 1977
13116SN/A/* 23116SN/A * Copyright (c) 2005 The Regents of The University of Michigan 33116SN/A * All rights reserved. 43116SN/A * 53116SN/A * Redistribution and use in source and binary forms, with or without 63116SN/A * modification, are permitted provided that the following conditions are 73116SN/A * met: redistributions of source code must retain the above copyright 83116SN/A * notice, this list of conditions and the following disclaimer; 93116SN/A * redistributions in binary form must reproduce the above copyright 103116SN/A * notice, this list of conditions and the following disclaimer in the 113116SN/A * documentation and/or other materials provided with the distribution; 123116SN/A * neither the name of the copyright holders nor the names of its 133116SN/A * contributors may be used to endorse or promote products derived from 143116SN/A * this software without specific prior written permission. 153116SN/A * 163116SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 173116SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 183116SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 193116SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 203116SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 213116SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 223116SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 233116SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 243116SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 253116SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 263116SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 273116SN/A */ 283116SN/A 293116SN/A#include <string> 303116SN/A 313116SN/A#include "arch/alpha/isa_traits.hh" 323116SN/A#include "arch/alpha/stacktrace.hh" 333318SN/A#include "arch/alpha/vtophys.hh" 343318SN/A#include "base/bitfield.hh" 353318SN/A#include "base/trace.hh" 363116SN/A#include "cpu/base.hh" 373116SN/A#include "cpu/exec_context.hh" 3811263Sandreas.sandberg@arm.com 394263SN/Ausing namespace std; 404263SN/A 414263SN/AProcessInfo::ProcessInfo(ExecContext *_xc) 424263SN/A : xc(_xc) 434263SN/A{ 444762SN/A Addr addr = 0; 4510469SN/A 464762SN/A if (!xc->system->kernelSymtab->findAddress("thread_info_size", addr)) 473116SN/A panic("thread info not compiled into kernel\n"); 484263SN/A thread_info_size = *(int32_t *)vtomem(xc, addr, sizeof(int32_t)); 499152SN/A 508232SN/A if (!xc->system->kernelSymtab->findAddress("task_struct_size", addr)) 513116SN/A panic("thread info not compiled into kernel\n"); 523405SN/A task_struct_size = *(int32_t *)vtomem(xc, addr, sizeof(int32_t)); 534762SN/A 543116SN/A if (!xc->system->kernelSymtab->findAddress("thread_info_task", addr)) 553116SN/A panic("thread info not compiled into kernel\n"); 563116SN/A task_off = *(int32_t *)vtomem(xc, addr, sizeof(int32_t)); 573318SN/A 584263SN/A if (!xc->system->kernelSymtab->findAddress("task_struct_pid", addr)) 593318SN/A panic("thread info not compiled into kernel\n"); 604981SN/A pid_off = *(int32_t *)vtomem(xc, addr, sizeof(int32_t)); 6110913SN/A 624263SN/A if (!xc->system->kernelSymtab->findAddress("task_struct_comm", addr)) 635783SN/A panic("thread info not compiled into kernel\n"); 645535SN/A name_off = *(int32_t *)vtomem(xc, addr, sizeof(int32_t)); 655535SN/A} 665535SN/A 675535SN/AAddr 684291SN/AProcessInfo::task(Addr ksp) const 694283SN/A{ 705500SN/A Addr base = ksp & ~0x3fff; 719157SN/A if (base == ULL(0xfffffc0000000000)) 723116SN/A return 0; 734981SN/A 744981SN/A Addr task; 753318SN/A CopyOut(xc, &task, base + task_off, sizeof(task)); 764263SN/A return task; 774218SN/A} 784218SN/A 794218SN/Aint 804218SN/AProcessInfo::pid(Addr ksp) const 814218SN/A{ 824218SN/A Addr task = this->task(ksp); 834283SN/A if (!task) 844218SN/A return -1; 854218SN/A 864263SN/A uint16_t pid; 874263SN/A CopyOut(xc, &pid, task + pid_off, sizeof(pid)); 884263SN/A return pid; 894263SN/A} 904218SN/A 915763SN/Astring 925763SN/AProcessInfo::name(Addr ksp) const 935763SN/A{ 943116SN/A Addr task = this->task(ksp); 954218SN/A if (!task) 964218SN/A return "console"; 973405SN/A 983318SN/A char comm[256]; 993318SN/A CopyString(xc, comm, task + name_off, sizeof(comm)); 1003318SN/A if (!comm[0]) 1013318SN/A return "startup"; 1023318SN/A 1033405SN/A return comm; 1043405SN/A} 1053405SN/A 1064283SN/AStackTrace::StackTrace() 1074283SN/A : xc(0), stack(64) 1084283SN/A{ 1094283SN/A} 1104218SN/A 1114218SN/AStackTrace::StackTrace(ExecContext *_xc, StaticInstPtr<TheISA> inst) 1124218SN/A : xc(0), stack(64) 1134283SN/A{ 1144283SN/A trace(_xc, inst); 1154218SN/A} 1163318SN/A 1174218SN/AStackTrace::~StackTrace() 1184263SN/A{ 1195954SN/A} 1205954SN/A 1215954SN/Avoid 1224263SN/AStackTrace::trace(ExecContext *_xc, bool is_call) 1234263SN/A{ 1243116SN/A xc = _xc; 1253116SN/A 1269086SN/A bool usermode = (xc->regs.ipr[AlphaISA::IPR_DTB_CM] & 0x18) != 0; 1279086SN/A 1289086SN/A Addr pc = xc->regs.npc; 1299086SN/A bool kernel = xc->system->kernelStart <= pc && pc <= xc->system->kernelEnd; 1309086SN/A 1315954SN/A if (usermode) { 1325954SN/A stack.push_back(user); 1335954SN/A return; 1345954SN/A } 1359807SN/A 1365954SN/A if (!kernel) { 1375954SN/A stack.push_back(console); 1384981SN/A return; 1394981SN/A } 1404981SN/A 1414981SN/A SymbolTable *symtab = xc->system->kernelSymtab; 1424987SN/A Addr ksp = xc->regs.intRegFile[TheISA::StackPointerReg]; 1434981SN/A Addr bottom = ksp & ~0x3fff; 1444981SN/A Addr addr; 1454981SN/A 1464981SN/A if (is_call) { 1474981SN/A if (!symtab->findNearestAddr(pc, addr)) 1484981SN/A panic("could not find address %#x", pc); 1493116SN/A 1503116SN/A stack.push_back(addr); 1513349SN/A pc = xc->regs.pc; 1523116SN/A } 1533116SN/A 1543116SN/A Addr ra; 1559807SN/A int size; 1563116SN/A 1573116SN/A while (ksp > bottom) { 1583116SN/A if (!symtab->findNearestAddr(pc, addr)) 1596124SN/A panic("could not find symbol for pc=%#x", pc); 1606124SN/A assert(pc >= addr && "symbol botch: callpc < func"); 1616124SN/A 1623116SN/A stack.push_back(addr); 1639198SN/A 1643116SN/A if (isEntry(addr)) 1653116SN/A return; 1666124SN/A 1676124SN/A if (decodePrologue(ksp, pc, addr, size, ra)) { 1686124SN/A if (!ra) 1693116SN/A return; 1703349SN/A 1713116SN/A if (size <= 0) { 1723116SN/A stack.push_back(unknown); 1733116SN/A return; 1743116SN/A } 1753116SN/A 1763116SN/A pc = ra; 1773116SN/A ksp += size; 1783116SN/A } else { 1793116SN/A stack.push_back(unknown); 1803116SN/A return; 1813318SN/A } 1823318SN/A 1833318SN/A bool kernel = xc->system->kernelStart <= pc && 1844283SN/A pc <= xc->system->kernelEnd; 1853116SN/A if (!kernel) 1866124SN/A return; 1876124SN/A 1886124SN/A if (stack.size() >= 1000) 1893116SN/A panic("unwinding too far"); 1903405SN/A } 1913318SN/A 1924218SN/A panic("unwinding too far"); 1934218SN/A} 1944218SN/A 1954218SN/Abool 1964218SN/AStackTrace::isEntry(Addr addr) 1974218SN/A{ 1984218SN/A if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp12]) 1994218SN/A return true; 2004218SN/A 2014218SN/A if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp7]) 2024218SN/A return true; 2034218SN/A 2044218SN/A if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp11]) 2054218SN/A return true; 2064218SN/A 2074218SN/A if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp21]) 2084218SN/A return true; 2094218SN/A 2104218SN/A if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp9]) 2116124SN/A return true; 2126124SN/A 2134218SN/A if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp2]) 2144283SN/A return true; 2154283SN/A 2164283SN/A return false; 2174263SN/A} 2184283SN/A 2194283SN/Abool 2204283SN/AStackTrace::decodeStack(MachInst inst, int &disp) 2214218SN/A{ 2225763SN/A // lda $sp, -disp($sp) 2235763SN/A // 2245763SN/A // Opcode<31:26> == 0x08 2255763SN/A // RA<25:21> == 30 2265763SN/A // RB<20:16> == 30 2274218SN/A // Disp<15:0> 2284218SN/A const MachInst mem_mask = 0xffff0000; 2294218SN/A const MachInst lda_pattern = 0x23de0000; 2304218SN/A const MachInst lda_disp_mask = 0x0000ffff; 2314218SN/A 2324218SN/A // subq $sp, disp, $sp 2334218SN/A // addq $sp, disp, $sp 2344218SN/A // 2354218SN/A // Opcode<31:26> == 0x10 2364218SN/A // RA<25:21> == 30 2374218SN/A // Lit<20:13> 2384218SN/A // One<12> = 1 2394218SN/A // Func<11:5> == 0x20 (addq) 2404218SN/A // Func<11:5> == 0x29 (subq) 2414218SN/A // RC<4:0> == 30 2424218SN/A const MachInst intop_mask = 0xffe01fff; 2434218SN/A const MachInst addq_pattern = 0x43c0141e; 2444218SN/A const MachInst subq_pattern = 0x43c0153e; 2454218SN/A const MachInst intop_disp_mask = 0x001fe000; 2464218SN/A const int intop_disp_shift = 13; 2474218SN/A 2484218SN/A if ((inst & mem_mask) == lda_pattern) 2494218SN/A disp = -sext<16>(inst & lda_disp_mask); 2504218SN/A else if ((inst & intop_mask) == addq_pattern) 2514218SN/A disp = -int((inst & intop_disp_mask) >> intop_disp_shift); 2524218SN/A else if ((inst & intop_mask) == subq_pattern) 2534218SN/A disp = int((inst & intop_disp_mask) >> intop_disp_shift); 2544218SN/A else 2554218SN/A return false; 2564218SN/A 2574218SN/A return true; 2584218SN/A} 2594218SN/A 2604218SN/Abool 2615763SN/AStackTrace::decodeSave(MachInst inst, int ®, int &disp) 2625763SN/A{ 2635763SN/A // lda $stq, disp($sp) 2644218SN/A // 2654218SN/A // Opcode<31:26> == 0x08 2664218SN/A // RA<25:21> == ? 2674218SN/A // RB<20:16> == 30 2684218SN/A // Disp<15:0> 2694218SN/A const MachInst stq_mask = 0xfc1f0000; 2704218SN/A const MachInst stq_pattern = 0xb41e0000; 2714218SN/A const MachInst stq_disp_mask = 0x0000ffff; 2724263SN/A const MachInst reg_mask = 0x03e00000; 2734263SN/A const int reg_shift = 21; 2746124SN/A 2756124SN/A if ((inst & stq_mask) == stq_pattern) { 2764263SN/A reg = (inst & reg_mask) >> reg_shift; 2774263SN/A disp = sext<16>(inst & stq_disp_mask); 2784263SN/A } else { 2794218SN/A return false; 2805763SN/A } 2815763SN/A 2825763SN/A return true; 2834218SN/A} 2844218SN/A 2854218SN/A/* 2864218SN/A * Decode the function prologue for the function we're in, and note 2874218SN/A * which registers are stored where, and how large the stack frame is. 2884218SN/A */ 2894218SN/Abool 2904218SN/AStackTrace::decodePrologue(Addr sp, Addr callpc, Addr func, 2914218SN/A int &size, Addr &ra) 2924218SN/A{ 2934218SN/A size = 0; 2944218SN/A ra = 0; 2954218SN/A 2964218SN/A for (Addr pc = func; pc < callpc; pc += sizeof(MachInst)) { 2974218SN/A MachInst inst; 2985763SN/A CopyOut(xc, (uint8_t *)&inst, pc, sizeof(MachInst)); 2995763SN/A 3005763SN/A int reg, disp; 3014218SN/A if (decodeStack(inst, disp)) { 3024218SN/A if (size) { 3034218SN/A // panic("decoding frame size again"); 3044218SN/A return true; 3054218SN/A } 3064218SN/A size += disp; 3074218SN/A } else if (decodeSave(inst, reg, disp)) { 3084218SN/A if (!ra && reg == ReturnAddressReg) { 3094218SN/A CopyOut(xc, (uint8_t *)&ra, sp + disp, sizeof(Addr)); 3104218SN/A if (!ra) { 3114218SN/A // panic("no return address value pc=%#x\n", pc); 3124218SN/A return false; 3135763SN/A } 3145763SN/A } 3155763SN/A } 3165763SN/A } 3175763SN/A 3185763SN/A return true; 3194218SN/A} 3204218SN/A 3214218SN/A#if TRACING_ON 3225763SN/Avoid 3235763SN/AStackTrace::dump() 3245763SN/A{ 3255763SN/A StringWrap name(xc->cpu->name()); 3265763SN/A SymbolTable *symtab = xc->system->kernelSymtab; 3275763SN/A 3284218SN/A DPRINTFN("------ Stack ------\n"); 3294218SN/A 3304218SN/A string symbol; 3315763SN/A for (int i = 0, size = stack.size(); i < size; ++i) { 3325763SN/A Addr addr = stack[size - i - 1]; 3335763SN/A if (addr == user) 3345763SN/A symbol = "user"; 3355763SN/A else if (addr == console) 3365763SN/A symbol = "console"; 3375763SN/A else if (addr == unknown) 3385763SN/A symbol = "unknown"; 3395763SN/A else 3405763SN/A symtab->findSymbol(addr, symbol); 3413318SN/A 3426124SN/A DPRINTFN("%#x: %s\n", addr, symbol); 3436124SN/A } 3446124SN/A} 3456124SN/A#endif 3464218SN/A