stacktrace.cc revision 2235
17753SWilliam.Wang@arm.com/* 29394Sandreas.hansson@arm.com * Copyright (c) 2005 The Regents of The University of Michigan 37753SWilliam.Wang@arm.com * All rights reserved. 47753SWilliam.Wang@arm.com * 57753SWilliam.Wang@arm.com * Redistribution and use in source and binary forms, with or without 67753SWilliam.Wang@arm.com * modification, are permitted provided that the following conditions are 77753SWilliam.Wang@arm.com * met: redistributions of source code must retain the above copyright 87753SWilliam.Wang@arm.com * notice, this list of conditions and the following disclaimer; 97753SWilliam.Wang@arm.com * redistributions in binary form must reproduce the above copyright 107753SWilliam.Wang@arm.com * notice, this list of conditions and the following disclaimer in the 117753SWilliam.Wang@arm.com * documentation and/or other materials provided with the distribution; 127753SWilliam.Wang@arm.com * neither the name of the copyright holders nor the names of its 137753SWilliam.Wang@arm.com * contributors may be used to endorse or promote products derived from 147753SWilliam.Wang@arm.com * this software without specific prior written permission. 157753SWilliam.Wang@arm.com * 167753SWilliam.Wang@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 177753SWilliam.Wang@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 187753SWilliam.Wang@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 197753SWilliam.Wang@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 207753SWilliam.Wang@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 217753SWilliam.Wang@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 227753SWilliam.Wang@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 237753SWilliam.Wang@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 247753SWilliam.Wang@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 257753SWilliam.Wang@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 267753SWilliam.Wang@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 277753SWilliam.Wang@arm.com */ 287753SWilliam.Wang@arm.com 297753SWilliam.Wang@arm.com#include <string> 307753SWilliam.Wang@arm.com 317753SWilliam.Wang@arm.com#include "arch/alpha/isa_traits.hh" 327753SWilliam.Wang@arm.com#include "arch/alpha/stacktrace.hh" 337753SWilliam.Wang@arm.com#include "arch/alpha/vtophys.hh" 347753SWilliam.Wang@arm.com#include "base/bitfield.hh" 357753SWilliam.Wang@arm.com#include "base/trace.hh" 367753SWilliam.Wang@arm.com#include "cpu/base.hh" 377753SWilliam.Wang@arm.com#include "cpu/exec_context.hh" 387950SAli.Saidi@ARM.com#include "sim/system.hh" 397753SWilliam.Wang@arm.com 407753SWilliam.Wang@arm.comusing namespace std; 419330Schander.sudanthi@arm.comusing namespace AlphaISA; 427950SAli.Saidi@ARM.com 437950SAli.Saidi@ARM.comProcessInfo::ProcessInfo(ExecContext *_xc) 447753SWilliam.Wang@arm.com : xc(_xc) 458245Snate@binkert.org{ 468245Snate@binkert.org Addr addr = 0; 477753SWilliam.Wang@arm.com 489525SAndreas.Sandberg@ARM.com if (!xc->getSystemPtr()->kernelSymtab->findAddress("thread_info_size", addr)) 497753SWilliam.Wang@arm.com panic("thread info not compiled into kernel\n"); 507753SWilliam.Wang@arm.com thread_info_size = *(int32_t *)vtomem(xc, addr, sizeof(int32_t)); 517753SWilliam.Wang@arm.com 529525SAndreas.Sandberg@ARM.com if (!xc->getSystemPtr()->kernelSymtab->findAddress("task_struct_size", addr)) 537753SWilliam.Wang@arm.com panic("thread info not compiled into kernel\n"); 548737Skoansin.tan@gmail.com task_struct_size = *(int32_t *)vtomem(xc, addr, sizeof(int32_t)); 558737Skoansin.tan@gmail.com 568737Skoansin.tan@gmail.com if (!xc->getSystemPtr()->kernelSymtab->findAddress("thread_info_task", addr)) 578737Skoansin.tan@gmail.com panic("thread info not compiled into kernel\n"); 587753SWilliam.Wang@arm.com task_off = *(int32_t *)vtomem(xc, addr, sizeof(int32_t)); 597753SWilliam.Wang@arm.com 607753SWilliam.Wang@arm.com if (!xc->getSystemPtr()->kernelSymtab->findAddress("task_struct_pid", addr)) 617753SWilliam.Wang@arm.com panic("thread info not compiled into kernel\n"); 627753SWilliam.Wang@arm.com pid_off = *(int32_t *)vtomem(xc, addr, sizeof(int32_t)); 637753SWilliam.Wang@arm.com 647950SAli.Saidi@ARM.com if (!xc->getSystemPtr()->kernelSymtab->findAddress("task_struct_comm", addr)) 657753SWilliam.Wang@arm.com panic("thread info not compiled into kernel\n"); 667753SWilliam.Wang@arm.com name_off = *(int32_t *)vtomem(xc, addr, sizeof(int32_t)); 679157Sandreas.hansson@arm.com} 689530SChris.Emmons@arm.com 699530SChris.Emmons@arm.comAddr 707950SAli.Saidi@ARM.comProcessInfo::task(Addr ksp) const 717753SWilliam.Wang@arm.com{ 729395SAndreas.Sandberg@ARM.com Addr base = ksp & ~0x3fff; 739395SAndreas.Sandberg@ARM.com if (base == ULL(0xfffffc0000000000)) 749395SAndreas.Sandberg@ARM.com return 0; 757753SWilliam.Wang@arm.com 767753SWilliam.Wang@arm.com Addr task; 777753SWilliam.Wang@arm.com CopyOut(xc, &task, base + task_off, sizeof(task)); 788737Skoansin.tan@gmail.com return task; 797950SAli.Saidi@ARM.com} 807753SWilliam.Wang@arm.com 817753SWilliam.Wang@arm.comint 828737Skoansin.tan@gmail.comProcessInfo::pid(Addr ksp) const 837950SAli.Saidi@ARM.com{ 849395SAndreas.Sandberg@ARM.com Addr task = this->task(ksp); 859395SAndreas.Sandberg@ARM.com if (!task) 869395SAndreas.Sandberg@ARM.com return -1; 879330Schander.sudanthi@arm.com 889330Schander.sudanthi@arm.com uint16_t pid; 897753SWilliam.Wang@arm.com CopyOut(xc, &pid, task + pid_off, sizeof(pid)); 907753SWilliam.Wang@arm.com return pid; 919086Sandreas.hansson@arm.com} 929086Sandreas.hansson@arm.com 939086Sandreas.hansson@arm.comstring 949086Sandreas.hansson@arm.comProcessInfo::name(Addr ksp) const 959086Sandreas.hansson@arm.com{ 967753SWilliam.Wang@arm.com Addr task = this->task(ksp); 977753SWilliam.Wang@arm.com if (!task) 987753SWilliam.Wang@arm.com return "console"; 997753SWilliam.Wang@arm.com 1007753SWilliam.Wang@arm.com char comm[256]; 1017753SWilliam.Wang@arm.com CopyString(xc, comm, task + name_off, sizeof(comm)); 1027753SWilliam.Wang@arm.com if (!comm[0]) 1037753SWilliam.Wang@arm.com return "startup"; 1047753SWilliam.Wang@arm.com 1057950SAli.Saidi@ARM.com return comm; 1067950SAli.Saidi@ARM.com} 1077753SWilliam.Wang@arm.com 1087950SAli.Saidi@ARM.comStackTrace::StackTrace() 1097950SAli.Saidi@ARM.com : xc(0), stack(64) 1107753SWilliam.Wang@arm.com{ 1117950SAli.Saidi@ARM.com} 1127753SWilliam.Wang@arm.com 1137950SAli.Saidi@ARM.comStackTrace::StackTrace(ExecContext *_xc, StaticInstPtr inst) 1147950SAli.Saidi@ARM.com : xc(0), stack(64) 1157950SAli.Saidi@ARM.com{ 1167950SAli.Saidi@ARM.com trace(_xc, inst); 1177950SAli.Saidi@ARM.com} 1187950SAli.Saidi@ARM.com 1197950SAli.Saidi@ARM.comStackTrace::~StackTrace() 1207950SAli.Saidi@ARM.com{ 1217950SAli.Saidi@ARM.com} 1227950SAli.Saidi@ARM.com 1237950SAli.Saidi@ARM.comvoid 1247950SAli.Saidi@ARM.comStackTrace::trace(ExecContext *_xc, bool is_call) 1257950SAli.Saidi@ARM.com{ 1267950SAli.Saidi@ARM.com xc = _xc; 1277950SAli.Saidi@ARM.com 1287950SAli.Saidi@ARM.com bool usermode = (xc->readMiscReg(AlphaISA::IPR_DTB_CM) & 0x18) != 0; 1297950SAli.Saidi@ARM.com 1307950SAli.Saidi@ARM.com Addr pc = xc->readNextPC(); 1317950SAli.Saidi@ARM.com bool kernel = xc->getSystemPtr()->kernelStart <= pc && 1327950SAli.Saidi@ARM.com pc <= xc->getSystemPtr()->kernelEnd; 1337950SAli.Saidi@ARM.com 1347950SAli.Saidi@ARM.com if (usermode) { 1357950SAli.Saidi@ARM.com stack.push_back(user); 1367950SAli.Saidi@ARM.com return; 1377950SAli.Saidi@ARM.com } 1387950SAli.Saidi@ARM.com 1397950SAli.Saidi@ARM.com if (!kernel) { 1407950SAli.Saidi@ARM.com stack.push_back(console); 1417950SAli.Saidi@ARM.com return; 1427950SAli.Saidi@ARM.com } 1437950SAli.Saidi@ARM.com 1447950SAli.Saidi@ARM.com SymbolTable *symtab = xc->getSystemPtr()->kernelSymtab; 1457950SAli.Saidi@ARM.com Addr ksp = xc->readIntReg(TheISA::StackPointerReg); 1467950SAli.Saidi@ARM.com Addr bottom = ksp & ~0x3fff; 1477950SAli.Saidi@ARM.com Addr addr; 1487950SAli.Saidi@ARM.com 1497950SAli.Saidi@ARM.com if (is_call) { 1507950SAli.Saidi@ARM.com if (!symtab->findNearestAddr(pc, addr)) 1517950SAli.Saidi@ARM.com panic("could not find address %#x", pc); 1527950SAli.Saidi@ARM.com 1537950SAli.Saidi@ARM.com stack.push_back(addr); 1547950SAli.Saidi@ARM.com pc = xc->readPC(); 1557950SAli.Saidi@ARM.com } 1567950SAli.Saidi@ARM.com 1577950SAli.Saidi@ARM.com Addr ra; 1587950SAli.Saidi@ARM.com int size; 1597950SAli.Saidi@ARM.com 1607950SAli.Saidi@ARM.com while (ksp > bottom) { 1617950SAli.Saidi@ARM.com if (!symtab->findNearestAddr(pc, addr)) 1627950SAli.Saidi@ARM.com panic("could not find symbol for pc=%#x", pc); 1637950SAli.Saidi@ARM.com assert(pc >= addr && "symbol botch: callpc < func"); 1647950SAli.Saidi@ARM.com 1657950SAli.Saidi@ARM.com stack.push_back(addr); 1667950SAli.Saidi@ARM.com 1677950SAli.Saidi@ARM.com if (isEntry(addr)) 1687950SAli.Saidi@ARM.com return; 1697950SAli.Saidi@ARM.com 1707950SAli.Saidi@ARM.com if (decodePrologue(ksp, pc, addr, size, ra)) { 1717950SAli.Saidi@ARM.com if (!ra) 1727950SAli.Saidi@ARM.com return; 1737950SAli.Saidi@ARM.com 1747950SAli.Saidi@ARM.com if (size <= 0) { 1757950SAli.Saidi@ARM.com stack.push_back(unknown); 1767950SAli.Saidi@ARM.com return; 1777950SAli.Saidi@ARM.com } 1787950SAli.Saidi@ARM.com 1797950SAli.Saidi@ARM.com pc = ra; 1807950SAli.Saidi@ARM.com ksp += size; 1817950SAli.Saidi@ARM.com } else { 1827950SAli.Saidi@ARM.com stack.push_back(unknown); 1837950SAli.Saidi@ARM.com return; 1847950SAli.Saidi@ARM.com } 1857950SAli.Saidi@ARM.com 1867950SAli.Saidi@ARM.com bool kernel = xc->getSystemPtr()->kernelStart <= pc && 1877753SWilliam.Wang@arm.com pc <= xc->getSystemPtr()->kernelEnd; 1887950SAli.Saidi@ARM.com if (!kernel) 1897950SAli.Saidi@ARM.com return; 1907950SAli.Saidi@ARM.com 1917950SAli.Saidi@ARM.com if (stack.size() >= 1000) 1927950SAli.Saidi@ARM.com panic("unwinding too far"); 1937753SWilliam.Wang@arm.com } 1947950SAli.Saidi@ARM.com 1957950SAli.Saidi@ARM.com panic("unwinding too far"); 1967950SAli.Saidi@ARM.com} 1977950SAli.Saidi@ARM.com 1987950SAli.Saidi@ARM.combool 1997753SWilliam.Wang@arm.comStackTrace::isEntry(Addr addr) 2007950SAli.Saidi@ARM.com{ 2017950SAli.Saidi@ARM.com if (addr == xc->readMiscReg(AlphaISA::IPR_PALtemp12)) 2027950SAli.Saidi@ARM.com return true; 2037753SWilliam.Wang@arm.com 2047753SWilliam.Wang@arm.com if (addr == xc->readMiscReg(AlphaISA::IPR_PALtemp7)) 2057753SWilliam.Wang@arm.com return true; 2067753SWilliam.Wang@arm.com 2077753SWilliam.Wang@arm.com if (addr == xc->readMiscReg(AlphaISA::IPR_PALtemp11)) 2087753SWilliam.Wang@arm.com return true; 2097753SWilliam.Wang@arm.com 2107753SWilliam.Wang@arm.com if (addr == xc->readMiscReg(AlphaISA::IPR_PALtemp21)) 2117753SWilliam.Wang@arm.com return true; 2127753SWilliam.Wang@arm.com 2137753SWilliam.Wang@arm.com if (addr == xc->readMiscReg(AlphaISA::IPR_PALtemp9)) 2147753SWilliam.Wang@arm.com return true; 2157753SWilliam.Wang@arm.com 2167753SWilliam.Wang@arm.com if (addr == xc->readMiscReg(AlphaISA::IPR_PALtemp2)) 2177753SWilliam.Wang@arm.com return true; 2187753SWilliam.Wang@arm.com 2197753SWilliam.Wang@arm.com return false; 2207753SWilliam.Wang@arm.com} 2217753SWilliam.Wang@arm.com 2227753SWilliam.Wang@arm.combool 2237753SWilliam.Wang@arm.comStackTrace::decodeStack(MachInst inst, int &disp) 2247753SWilliam.Wang@arm.com{ 2257753SWilliam.Wang@arm.com // lda $sp, -disp($sp) 2267753SWilliam.Wang@arm.com // 2277753SWilliam.Wang@arm.com // Opcode<31:26> == 0x08 2287753SWilliam.Wang@arm.com // RA<25:21> == 30 2297753SWilliam.Wang@arm.com // RB<20:16> == 30 2307753SWilliam.Wang@arm.com // Disp<15:0> 2317753SWilliam.Wang@arm.com const MachInst mem_mask = 0xffff0000; 2327753SWilliam.Wang@arm.com const MachInst lda_pattern = 0x23de0000; 2337753SWilliam.Wang@arm.com const MachInst lda_disp_mask = 0x0000ffff; 2347753SWilliam.Wang@arm.com 2357753SWilliam.Wang@arm.com // subq $sp, disp, $sp 2367753SWilliam.Wang@arm.com // addq $sp, disp, $sp 2377753SWilliam.Wang@arm.com // 2387753SWilliam.Wang@arm.com // Opcode<31:26> == 0x10 2397753SWilliam.Wang@arm.com // RA<25:21> == 30 2407753SWilliam.Wang@arm.com // Lit<20:13> 2417753SWilliam.Wang@arm.com // One<12> = 1 2427753SWilliam.Wang@arm.com // Func<11:5> == 0x20 (addq) 2437753SWilliam.Wang@arm.com // Func<11:5> == 0x29 (subq) 2447753SWilliam.Wang@arm.com // RC<4:0> == 30 2457753SWilliam.Wang@arm.com const MachInst intop_mask = 0xffe01fff; 2467753SWilliam.Wang@arm.com const MachInst addq_pattern = 0x43c0141e; 2477753SWilliam.Wang@arm.com const MachInst subq_pattern = 0x43c0153e; 2487753SWilliam.Wang@arm.com const MachInst intop_disp_mask = 0x001fe000; 2497753SWilliam.Wang@arm.com const int intop_disp_shift = 13; 2507950SAli.Saidi@ARM.com 2517950SAli.Saidi@ARM.com if ((inst & mem_mask) == lda_pattern) 2527753SWilliam.Wang@arm.com disp = -sext<16>(inst & lda_disp_mask); 2537950SAli.Saidi@ARM.com else if ((inst & intop_mask) == addq_pattern) 2547753SWilliam.Wang@arm.com disp = -int((inst & intop_disp_mask) >> intop_disp_shift); 2557950SAli.Saidi@ARM.com else if ((inst & intop_mask) == subq_pattern) 2567950SAli.Saidi@ARM.com disp = int((inst & intop_disp_mask) >> intop_disp_shift); 2577753SWilliam.Wang@arm.com else 2587950SAli.Saidi@ARM.com return false; 2597950SAli.Saidi@ARM.com 2607950SAli.Saidi@ARM.com return true; 2617950SAli.Saidi@ARM.com} 2627950SAli.Saidi@ARM.com 2637950SAli.Saidi@ARM.combool 2647950SAli.Saidi@ARM.comStackTrace::decodeSave(MachInst inst, int ®, int &disp) 2657950SAli.Saidi@ARM.com{ 2667950SAli.Saidi@ARM.com // lda $stq, disp($sp) 2677950SAli.Saidi@ARM.com // 2687950SAli.Saidi@ARM.com // Opcode<31:26> == 0x08 2697950SAli.Saidi@ARM.com // RA<25:21> == ? 2707950SAli.Saidi@ARM.com // RB<20:16> == 30 2717950SAli.Saidi@ARM.com // Disp<15:0> 2727950SAli.Saidi@ARM.com const MachInst stq_mask = 0xfc1f0000; 2737950SAli.Saidi@ARM.com const MachInst stq_pattern = 0xb41e0000; 2747950SAli.Saidi@ARM.com const MachInst stq_disp_mask = 0x0000ffff; 2757950SAli.Saidi@ARM.com const MachInst reg_mask = 0x03e00000; 2767950SAli.Saidi@ARM.com const int reg_shift = 21; 2777950SAli.Saidi@ARM.com 2787950SAli.Saidi@ARM.com if ((inst & stq_mask) == stq_pattern) { 2797950SAli.Saidi@ARM.com reg = (inst & reg_mask) >> reg_shift; 2808508SAli.Saidi@ARM.com disp = sext<16>(inst & stq_disp_mask); 2817950SAli.Saidi@ARM.com } else { 2827950SAli.Saidi@ARM.com return false; 2837950SAli.Saidi@ARM.com } 2847950SAli.Saidi@ARM.com 2857950SAli.Saidi@ARM.com return true; 2867950SAli.Saidi@ARM.com} 2877950SAli.Saidi@ARM.com 2887753SWilliam.Wang@arm.com/* 2897950SAli.Saidi@ARM.com * Decode the function prologue for the function we're in, and note 2907950SAli.Saidi@ARM.com * which registers are stored where, and how large the stack frame is. 2917950SAli.Saidi@ARM.com */ 2927950SAli.Saidi@ARM.combool 2937950SAli.Saidi@ARM.comStackTrace::decodePrologue(Addr sp, Addr callpc, Addr func, 2947950SAli.Saidi@ARM.com int &size, Addr &ra) 2957950SAli.Saidi@ARM.com{ 2967950SAli.Saidi@ARM.com size = 0; 2977950SAli.Saidi@ARM.com ra = 0; 2987950SAli.Saidi@ARM.com 2997950SAli.Saidi@ARM.com for (Addr pc = func; pc < callpc; pc += sizeof(MachInst)) { 3007950SAli.Saidi@ARM.com MachInst inst; 3017950SAli.Saidi@ARM.com CopyOut(xc, (uint8_t *)&inst, pc, sizeof(MachInst)); 3027950SAli.Saidi@ARM.com 3037950SAli.Saidi@ARM.com int reg, disp; 3047950SAli.Saidi@ARM.com if (decodeStack(inst, disp)) { 3057950SAli.Saidi@ARM.com if (size) { 3067950SAli.Saidi@ARM.com // panic("decoding frame size again"); 3077950SAli.Saidi@ARM.com return true; 3087950SAli.Saidi@ARM.com } 3097950SAli.Saidi@ARM.com size += disp; 3107950SAli.Saidi@ARM.com } else if (decodeSave(inst, reg, disp)) { 3117950SAli.Saidi@ARM.com if (!ra && reg == ReturnAddressReg) { 3127950SAli.Saidi@ARM.com CopyOut(xc, (uint8_t *)&ra, sp + disp, sizeof(Addr)); 3137950SAli.Saidi@ARM.com if (!ra) { 3147950SAli.Saidi@ARM.com // panic("no return address value pc=%#x\n", pc); 3157950SAli.Saidi@ARM.com return false; 3167950SAli.Saidi@ARM.com } 3177950SAli.Saidi@ARM.com } 3187950SAli.Saidi@ARM.com } 3197950SAli.Saidi@ARM.com } 3207950SAli.Saidi@ARM.com 3217950SAli.Saidi@ARM.com return true; 3227950SAli.Saidi@ARM.com} 3237950SAli.Saidi@ARM.com 3247950SAli.Saidi@ARM.com#if TRACING_ON 3257950SAli.Saidi@ARM.comvoid 3267950SAli.Saidi@ARM.comStackTrace::dump() 3277950SAli.Saidi@ARM.com{ 3287950SAli.Saidi@ARM.com StringWrap name(xc->getCpuPtr()->name()); 3297950SAli.Saidi@ARM.com SymbolTable *symtab = xc->getSystemPtr()->kernelSymtab; 3307950SAli.Saidi@ARM.com 3317950SAli.Saidi@ARM.com DPRINTFN("------ Stack ------\n"); 3327950SAli.Saidi@ARM.com 3337950SAli.Saidi@ARM.com string symbol; 3347950SAli.Saidi@ARM.com for (int i = 0, size = stack.size(); i < size; ++i) { 3357950SAli.Saidi@ARM.com Addr addr = stack[size - i - 1]; 3367950SAli.Saidi@ARM.com if (addr == user) 3377950SAli.Saidi@ARM.com symbol = "user"; 3387950SAli.Saidi@ARM.com else if (addr == console) 3397950SAli.Saidi@ARM.com symbol = "console"; 3407950SAli.Saidi@ARM.com else if (addr == unknown) 3417950SAli.Saidi@ARM.com symbol = "unknown"; 3427950SAli.Saidi@ARM.com else 3437950SAli.Saidi@ARM.com symtab->findSymbol(addr, symbol); 3447950SAli.Saidi@ARM.com 3457950SAli.Saidi@ARM.com DPRINTFN("%#x: %s\n", addr, symbol); 3467950SAli.Saidi@ARM.com } 3477950SAli.Saidi@ARM.com} 3487950SAli.Saidi@ARM.com#endif 3497950SAli.Saidi@ARM.com