stacktrace.cc revision 2107
12810SN/A/* 210693SMarco.Balboni@ARM.com * Copyright (c) 2005 The Regents of The University of Michigan 38856Sandreas.hansson@arm.com * All rights reserved. 48856Sandreas.hansson@arm.com * 58856Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without 68856Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are 78856Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright 88856Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer; 98856Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright 108856Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the 118856Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution; 128856Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its 138856Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from 142810SN/A * this software without specific prior written permission. 152810SN/A * 162810SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172810SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182810SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192810SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202810SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212810SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222810SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232810SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242810SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252810SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262810SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272810SN/A */ 282810SN/A 292810SN/A#include <string> 302810SN/A 312810SN/A#include "arch/alpha/isa_traits.hh" 322810SN/A#include "arch/alpha/stacktrace.hh" 332810SN/A#include "arch/alpha/vtophys.hh" 342810SN/A#include "base/bitfield.hh" 352810SN/A#include "base/trace.hh" 362810SN/A#include "cpu/base.hh" 372810SN/A#include "cpu/exec_context.hh" 382810SN/A 392810SN/Ausing namespace std; 402810SN/Ausing namespace AlphaISA; 414458SN/A 424458SN/AProcessInfo::ProcessInfo(ExecContext *_xc) 432810SN/A : xc(_xc) 442810SN/A{ 452810SN/A Addr addr = 0; 462810SN/A 472810SN/A if (!xc->system->kernelSymtab->findAddress("thread_info_size", addr)) 482810SN/A panic("thread info not compiled into kernel\n"); 492810SN/A thread_info_size = *(int32_t *)vtomem(xc, addr, sizeof(int32_t)); 5011051Sandreas.hansson@arm.com 5111051Sandreas.hansson@arm.com if (!xc->system->kernelSymtab->findAddress("task_struct_size", addr)) 522810SN/A panic("thread info not compiled into kernel\n"); 537676Snate@binkert.org task_struct_size = *(int32_t *)vtomem(xc, addr, sizeof(int32_t)); 547676Snate@binkert.org 557676Snate@binkert.org if (!xc->system->kernelSymtab->findAddress("thread_info_task", addr)) 562810SN/A panic("thread info not compiled into kernel\n"); 572810SN/A task_off = *(int32_t *)vtomem(xc, addr, sizeof(int32_t)); 582825SN/A 592810SN/A if (!xc->system->kernelSymtab->findAddress("task_struct_pid", addr)) 602810SN/A panic("thread info not compiled into kernel\n"); 616215Snate@binkert.org pid_off = *(int32_t *)vtomem(xc, addr, sizeof(int32_t)); 628232Snate@binkert.org 638232Snate@binkert.org if (!xc->system->kernelSymtab->findAddress("task_struct_comm", addr)) 645338Sstever@gmail.com panic("thread info not compiled into kernel\n"); 652810SN/A name_off = *(int32_t *)vtomem(xc, addr, sizeof(int32_t)); 662810SN/A} 678914Sandreas.hansson@arm.com 688229Snate@binkert.orgAddr 695034SN/AProcessInfo::task(Addr ksp) const 702811SN/A{ 718786Sgblack@eecs.umich.edu Addr base = ksp & ~0x3fff; 724626SN/A if (base == ULL(0xfffffc0000000000)) 738833Sdam.sunwoo@arm.com return 0; 742810SN/A 753194SN/A Addr task; 762810SN/A CopyOut(xc, &task, base + task_off, sizeof(task)); 772810SN/A return task; 782810SN/A} 792810SN/A 802810SN/Aint 814628SN/AProcessInfo::pid(Addr ksp) const 824628SN/A{ 834628SN/A Addr task = this->task(ksp); 844628SN/A if (!task) 854628SN/A return -1; 864628SN/A 874628SN/A uint16_t pid; 884628SN/A CopyOut(xc, &pid, task + pid_off, sizeof(pid)); 898737Skoansin.tan@gmail.com return pid; 904628SN/A} 914628SN/A 924628SN/Astring 934628SN/AProcessInfo::name(Addr ksp) const 944628SN/A{ 954628SN/A Addr task = this->task(ksp); 964628SN/A if (!task) 974628SN/A return "console"; 984628SN/A 994628SN/A char comm[256]; 1008737Skoansin.tan@gmail.com CopyString(xc, comm, task + name_off, sizeof(comm)); 1014628SN/A if (!comm[0]) 1028856Sandreas.hansson@arm.com return "startup"; 1038856Sandreas.hansson@arm.com 1048856Sandreas.hansson@arm.com return comm; 1058856Sandreas.hansson@arm.com} 1068856Sandreas.hansson@arm.com 10710942Sandreas.hansson@arm.comStackTrace::StackTrace() 1088856Sandreas.hansson@arm.com : xc(0), stack(64) 1098856Sandreas.hansson@arm.com{ 1108856Sandreas.hansson@arm.com} 1118922Swilliam.wang@arm.com 1122810SN/AStackTrace::StackTrace(ExecContext *_xc, StaticInstPtr inst) 1138856Sandreas.hansson@arm.com : xc(0), stack(64) 1142844SN/A{ 1158856Sandreas.hansson@arm.com trace(_xc, inst); 1168856Sandreas.hansson@arm.com} 1178856Sandreas.hansson@arm.com 11810713Sandreas.hansson@arm.comStackTrace::~StackTrace() 1198856Sandreas.hansson@arm.com{ 12010942Sandreas.hansson@arm.com} 1218856Sandreas.hansson@arm.com 12210942Sandreas.hansson@arm.comvoid 12310713Sandreas.hansson@arm.comStackTrace::trace(ExecContext *_xc, bool is_call) 1248856Sandreas.hansson@arm.com{ 1258856Sandreas.hansson@arm.com xc = _xc; 1263738SN/A 1274458SN/A bool usermode = (xc->regs.ipr[AlphaISA::IPR_DTB_CM] & 0x18) != 0; 1288856Sandreas.hansson@arm.com 12910713Sandreas.hansson@arm.com Addr pc = xc->regs.npc; 13010713Sandreas.hansson@arm.com bool kernel = xc->system->kernelStart <= pc && pc <= xc->system->kernelEnd; 13110713Sandreas.hansson@arm.com 1328914Sandreas.hansson@arm.com if (usermode) { 1332810SN/A stack.push_back(user); 1348856Sandreas.hansson@arm.com return; 1358856Sandreas.hansson@arm.com } 1368856Sandreas.hansson@arm.com 1378914Sandreas.hansson@arm.com if (!kernel) { 1388856Sandreas.hansson@arm.com stack.push_back(console); 1398922Swilliam.wang@arm.com return; 1408856Sandreas.hansson@arm.com } 1413013SN/A 1428856Sandreas.hansson@arm.com SymbolTable *symtab = xc->system->kernelSymtab; 1438856Sandreas.hansson@arm.com Addr ksp = xc->regs.intRegFile[TheISA::StackPointerReg]; 1448856Sandreas.hansson@arm.com Addr bottom = ksp & ~0x3fff; 1458856Sandreas.hansson@arm.com Addr addr; 1468856Sandreas.hansson@arm.com 1478856Sandreas.hansson@arm.com if (is_call) { 1488856Sandreas.hansson@arm.com if (!symtab->findNearestAddr(pc, addr)) 1498856Sandreas.hansson@arm.com panic("could not find address %#x", pc); 1508922Swilliam.wang@arm.com 1518856Sandreas.hansson@arm.com stack.push_back(addr); 1525314SN/A pc = xc->regs.pc; 1532811SN/A } 1548856Sandreas.hansson@arm.com 1558856Sandreas.hansson@arm.com Addr ra; 1562810SN/A int size; 1572810SN/A 1588856Sandreas.hansson@arm.com while (ksp > bottom) { 1592810SN/A if (!symtab->findNearestAddr(pc, addr)) 1602810SN/A panic("could not find symbol for pc=%#x", pc); 16110345SCurtis.Dunham@arm.com assert(pc >= addr && "symbol botch: callpc < func"); 16210345SCurtis.Dunham@arm.com 1638856Sandreas.hansson@arm.com stack.push_back(addr); 1648856Sandreas.hansson@arm.com 1658856Sandreas.hansson@arm.com if (isEntry(addr)) 1668856Sandreas.hansson@arm.com return; 1673606SN/A 1688914Sandreas.hansson@arm.com if (decodePrologue(ksp, pc, addr, size, ra)) { 16910713Sandreas.hansson@arm.com if (!ra) 1708914Sandreas.hansson@arm.com return; 1712810SN/A 1722810SN/A if (size <= 0) { 1732897SN/A stack.push_back(unknown); 1742897SN/A return; 1758856Sandreas.hansson@arm.com } 1764458SN/A 17710344Sandreas.hansson@arm.com pc = ra; 17810344Sandreas.hansson@arm.com ksp += size; 17910344Sandreas.hansson@arm.com } else { 18010344Sandreas.hansson@arm.com stack.push_back(unknown); 1818856Sandreas.hansson@arm.com return; 1822811SN/A } 1832810SN/A 1848856Sandreas.hansson@arm.com bool kernel = xc->system->kernelStart <= pc && 1858856Sandreas.hansson@arm.com pc <= xc->system->kernelEnd; 1863338SN/A if (!kernel) 1874626SN/A return; 1884626SN/A 1894626SN/A if (stack.size() >= 1000) 1904626SN/A panic("unwinding too far"); 1914626SN/A } 1924626SN/A 1934626SN/A panic("unwinding too far"); 1944626SN/A} 19510693SMarco.Balboni@ARM.com 19610693SMarco.Balboni@ARM.combool 19710693SMarco.Balboni@ARM.comStackTrace::isEntry(Addr addr) 19810693SMarco.Balboni@ARM.com{ 19910693SMarco.Balboni@ARM.com if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp12]) 20010693SMarco.Balboni@ARM.com return true; 20110693SMarco.Balboni@ARM.com 20210767Sandreas.hansson@arm.com if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp7]) 20310693SMarco.Balboni@ARM.com return true; 2044628SN/A 20510942Sandreas.hansson@arm.com if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp11]) 20610942Sandreas.hansson@arm.com return true; 2074628SN/A 20810764Sandreas.hansson@arm.com if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp21]) 20910764Sandreas.hansson@arm.com return true; 21010764Sandreas.hansson@arm.com 21110764Sandreas.hansson@arm.com if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp9]) 21210764Sandreas.hansson@arm.com return true; 2134666SN/A 2144628SN/A if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp2]) 2154628SN/A return true; 2164628SN/A 2174628SN/A return false; 2184628SN/A} 21910942Sandreas.hansson@arm.com 22010942Sandreas.hansson@arm.combool 22110942Sandreas.hansson@arm.comStackTrace::decodeStack(MachInst inst, int &disp) 2224628SN/A{ 2234628SN/A // lda $sp, -disp($sp) 2244628SN/A // 2254628SN/A // Opcode<31:26> == 0x08 22610679Sandreas.hansson@arm.com // RA<25:21> == 30 2274628SN/A // RB<20:16> == 30 2284628SN/A // Disp<15:0> 2294628SN/A const MachInst mem_mask = 0xffff0000; 23010679Sandreas.hansson@arm.com const MachInst lda_pattern = 0x23de0000; 2314628SN/A const MachInst lda_disp_mask = 0x0000ffff; 2324628SN/A 2334628SN/A // subq $sp, disp, $sp 2344628SN/A // addq $sp, disp, $sp 2354628SN/A // 2369347SAndreas.Sandberg@arm.com // Opcode<31:26> == 0x10 2379347SAndreas.Sandberg@arm.com // RA<25:21> == 30 2389347SAndreas.Sandberg@arm.com // Lit<20:13> 2399347SAndreas.Sandberg@arm.com // One<12> = 1 2409347SAndreas.Sandberg@arm.com // Func<11:5> == 0x20 (addq) 2419347SAndreas.Sandberg@arm.com // Func<11:5> == 0x29 (subq) 2429347SAndreas.Sandberg@arm.com // RC<4:0> == 30 2439347SAndreas.Sandberg@arm.com const MachInst intop_mask = 0xffe01fff; 2449347SAndreas.Sandberg@arm.com const MachInst addq_pattern = 0x43c0141e; 2459347SAndreas.Sandberg@arm.com const MachInst subq_pattern = 0x43c0153e; 2469347SAndreas.Sandberg@arm.com const MachInst intop_disp_mask = 0x001fe000; 2479347SAndreas.Sandberg@arm.com const int intop_disp_shift = 13; 2489347SAndreas.Sandberg@arm.com 2499347SAndreas.Sandberg@arm.com if ((inst & mem_mask) == lda_pattern) 2509347SAndreas.Sandberg@arm.com disp = -sext<16>(inst & lda_disp_mask); 2519347SAndreas.Sandberg@arm.com else if ((inst & intop_mask) == addq_pattern) 2529347SAndreas.Sandberg@arm.com disp = -int((inst & intop_disp_mask) >> intop_disp_shift); 2539347SAndreas.Sandberg@arm.com else if ((inst & intop_mask) == subq_pattern) 2549347SAndreas.Sandberg@arm.com disp = int((inst & intop_disp_mask) >> intop_disp_shift); 25510821Sandreas.hansson@arm.com else 25610821Sandreas.hansson@arm.com return false; 25710821Sandreas.hansson@arm.com 25810821Sandreas.hansson@arm.com return true; 25910821Sandreas.hansson@arm.com} 26010821Sandreas.hansson@arm.com 26110821Sandreas.hansson@arm.combool 26210821Sandreas.hansson@arm.comStackTrace::decodeSave(MachInst inst, int ®, int &disp) 26310821Sandreas.hansson@arm.com{ 26410821Sandreas.hansson@arm.com // lda $stq, disp($sp) 2654626SN/A // 2666227Snate@binkert.org // Opcode<31:26> == 0x08 2674626SN/A // RA<25:21> == ? 2684630SN/A // RB<20:16> == 30 26910693SMarco.Balboni@ARM.com // Disp<15:0> 27010693SMarco.Balboni@ARM.com const MachInst stq_mask = 0xfc1f0000; 2714630SN/A const MachInst stq_pattern = 0xb41e0000; 27210693SMarco.Balboni@ARM.com const MachInst stq_disp_mask = 0x0000ffff; 2739263Smrinmoy.ghosh@arm.com const MachInst reg_mask = 0x03e00000; 2749263Smrinmoy.ghosh@arm.com const int reg_shift = 21; 27510693SMarco.Balboni@ARM.com 27610693SMarco.Balboni@ARM.com if ((inst & stq_mask) == stq_pattern) { 27710693SMarco.Balboni@ARM.com reg = (inst & reg_mask) >> reg_shift; 27810693SMarco.Balboni@ARM.com disp = sext<16>(inst & stq_disp_mask); 27910693SMarco.Balboni@ARM.com } else { 28010693SMarco.Balboni@ARM.com return false; 28110693SMarco.Balboni@ARM.com } 28210693SMarco.Balboni@ARM.com 28310693SMarco.Balboni@ARM.com return true; 28410693SMarco.Balboni@ARM.com} 28510693SMarco.Balboni@ARM.com 28610693SMarco.Balboni@ARM.com/* 28710693SMarco.Balboni@ARM.com * Decode the function prologue for the function we're in, and note 2889263Smrinmoy.ghosh@arm.com * which registers are stored where, and how large the stack frame is. 2899288Sandreas.hansson@arm.com */ 2904630SN/Abool 2914626SN/AStackTrace::decodePrologue(Addr sp, Addr callpc, Addr func, 2924626SN/A int &size, Addr &ra) 2934626SN/A{ 2946122SSteve.Reinhardt@amd.com size = 0; 2959529Sandreas.hansson@arm.com ra = 0; 2964626SN/A 2972810SN/A for (Addr pc = func; pc < callpc; pc += sizeof(MachInst)) { 29810884Sandreas.hansson@arm.com MachInst inst; 29910884Sandreas.hansson@arm.com CopyOut(xc, (uint8_t *)&inst, pc, sizeof(MachInst)); 30010884Sandreas.hansson@arm.com 30110884Sandreas.hansson@arm.com int reg, disp; 30210884Sandreas.hansson@arm.com if (decodeStack(inst, disp)) { 30310884Sandreas.hansson@arm.com if (size) { 30410884Sandreas.hansson@arm.com // panic("decoding frame size again"); 30510884Sandreas.hansson@arm.com return true; 3062810SN/A } 3072810SN/A size += disp; 3082810SN/A } else if (decodeSave(inst, reg, disp)) { 3092810SN/A if (!ra && reg == ReturnAddressReg) { 3102810SN/A CopyOut(xc, (uint8_t *)&ra, sp + disp, sizeof(Addr)); 3116122SSteve.Reinhardt@amd.com if (!ra) { 3126122SSteve.Reinhardt@amd.com // panic("no return address value pc=%#x\n", pc); 3136122SSteve.Reinhardt@amd.com return false; 3142810SN/A } 3159288Sandreas.hansson@arm.com } 3162810SN/A } 3174626SN/A } 3184626SN/A 3192810SN/A return true; 3202810SN/A} 3212810SN/A 3222810SN/A#if TRACING_ON 3236122SSteve.Reinhardt@amd.comvoid 3246122SSteve.Reinhardt@amd.comStackTrace::dump() 3256122SSteve.Reinhardt@amd.com{ 3269529Sandreas.hansson@arm.com StringWrap name(xc->cpu->name()); 3276122SSteve.Reinhardt@amd.com SymbolTable *symtab = xc->system->kernelSymtab; 3288833Sdam.sunwoo@arm.com 3298833Sdam.sunwoo@arm.com DPRINTFN("------ Stack ------\n"); 3308833Sdam.sunwoo@arm.com 3316978SLisa.Hsu@amd.com string symbol; 3322810SN/A for (int i = 0, size = stack.size(); i < size; ++i) { 3332810SN/A Addr addr = stack[size - i - 1]; 3342810SN/A if (addr == user) 3352810SN/A symbol = "user"; 3362810SN/A else if (addr == console) 3372810SN/A symbol = "console"; 3382810SN/A else if (addr == unknown) 3395999Snate@binkert.org symbol = "unknown"; 3402810SN/A else 3412810SN/A symtab->findSymbol(addr, symbol); 3422810SN/A 3432810SN/A DPRINTFN("%#x: %s\n", addr, symbol); 3442810SN/A } 3452810SN/A} 3465999Snate@binkert.org#endif 3472810SN/A