stacktrace.cc revision 5222
12292SN/A/* 210333Smitch.hayenga@arm.com * Copyright .AN) 2007 MIPS Technologies, Inc. All Rights Reserved 310239Sbinhpham@cs.rutgers.edu * 48707Sandreas.hansson@arm.com * This software is part of the M5 simulator. 58707Sandreas.hansson@arm.com * 68707Sandreas.hansson@arm.com * THIS IS A LEGAL AGREEMENT. BY DOWNLOADING, USING, COPYING, CREATING 78707Sandreas.hansson@arm.com * DERIVATIVE WORKS, AND/OR DISTRIBUTING THIS SOFTWARE YOU ARE AGREEING 88707Sandreas.hansson@arm.com * TO THESE TERMS AND CONDITIONS. 98707Sandreas.hansson@arm.com * 108707Sandreas.hansson@arm.com * Permission is granted to use, copy, create derivative works and 118707Sandreas.hansson@arm.com * distribute this software and such derivative works for any purpose, 128707Sandreas.hansson@arm.com * so long as (1) the copyright notice above, this grant of permission, 138707Sandreas.hansson@arm.com * and the disclaimer below appear in all copies and derivative works 148707Sandreas.hansson@arm.com * made, (2) the copyright notice above is augmented as appropriate to 152727Sktlim@umich.edu * reflect the addition of any new copyrightable work in a derivative 162292SN/A * work (e.g., Copyright .AN) <Publication Year> Copyright Owner), and (3) 172292SN/A * the name of MIPS Technologies, Inc. ($B!H(BMIPS$B!I(B) is not used in any 182292SN/A * advertising or publicity pertaining to the use or distribution of 192292SN/A * this software without specific, written prior authorization. 202292SN/A * 212292SN/A * THIS SOFTWARE IS PROVIDED $B!H(BAS IS.$B!I(B MIPS MAKES NO WARRANTIES AND 222292SN/A * DISCLAIMS ALL WARRANTIES, WHETHER EXPRESS, STATUTORY, IMPLIED OR 232292SN/A * OTHERWISE, INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 242292SN/A * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND 252292SN/A * NON-INFRINGEMENT OF THIRD PARTY RIGHTS, REGARDING THIS SOFTWARE. 262292SN/A * IN NO EVENT SHALL MIPS BE LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, 272292SN/A * INDIRECT, INCIDENTAL, CONSEQUENTIAL, SPECIAL, OR PUNITIVE DAMAGES OF 282292SN/A * ANY KIND OR NATURE, ARISING OUT OF OR IN CONNECTION WITH THIS AGREEMENT, 292292SN/A * THIS SOFTWARE AND/OR THE USE OF THIS SOFTWARE, WHETHER SUCH LIABILITY 302292SN/A * IS ASSERTED ON THE BASIS OF CONTRACT, TORT (INCLUDING NEGLIGENCE OR 312292SN/A * STRICT LIABILITY), OR OTHERWISE, EVEN IF MIPS HAS BEEN WARNED OF THE 322292SN/A * POSSIBILITY OF ANY SUCH LOSS OR DAMAGE IN ADVANCE. 332292SN/A * 342292SN/A * Authors: Nathan L. Binkert 352292SN/A */ 362292SN/A 372292SN/A#include <string> 382292SN/A 392292SN/A#include "arch/mips/isa_traits.hh" 402689Sktlim@umich.edu#include "arch/mips/stacktrace.hh" 412689Sktlim@umich.edu#include "arch/mips/vtophys.hh" 422292SN/A#include "base/bitfield.hh" 432292SN/A#include "base/trace.hh" 449944Smatt.horsnell@ARM.com#include "cpu/base.hh" 459944Smatt.horsnell@ARM.com#include "cpu/thread_context.hh" 469944Smatt.horsnell@ARM.com#include "sim/system.hh" 472329SN/A 482980Sgblack@eecs.umich.eduusing namespace std; 492329SN/Ausing namespace MipsISA; 502329SN/A 5113449Sgabeblack@google.comProcessInfo::ProcessInfo(ThreadContext *_tc) 522292SN/A : tc(_tc) 539444SAndreas.Sandberg@ARM.com{ 548232Snate@binkert.org// Addr addr = 0; 558232Snate@binkert.org 568232Snate@binkert.org VirtualPort *vp; 576221Snate@binkert.org 582292SN/A vp = tc->getVirtPort(); 596221Snate@binkert.org 605529Snate@binkert.org// if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_size", addr)) 612292SN/A// panic("thread info not compiled into kernel\n"); 625529Snate@binkert.org// thread_info_size = vp->readGtoH<int32_t>(addr); 638707Sandreas.hansson@arm.com 6413560Snikos.nikoleris@arm.com// if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_size", addr)) 654329Sktlim@umich.edu// panic("thread info not compiled into kernel\n"); 664329Sktlim@umich.edu// task_struct_size = vp->readGtoH<int32_t>(addr); 6713472Srekai.gonzalezalberquilla@arm.com 6813472Srekai.gonzalezalberquilla@arm.com// if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_task", addr)) 6913472Srekai.gonzalezalberquilla@arm.com// panic("thread info not compiled into kernel\n"); 7013472Srekai.gonzalezalberquilla@arm.com// task_off = vp->readGtoH<int32_t>(addr); 7110333Smitch.hayenga@arm.com 722292SN/A// if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_pid", addr)) 739868Sjthestness@gmail.com// panic("thread info not compiled into kernel\n"); 749868Sjthestness@gmail.com// pid_off = vp->readGtoH<int32_t>(addr); 752292SN/A 762292SN/A// if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_comm", addr)) 772292SN/A// panic("thread info not compiled into kernel\n"); 782292SN/A// name_off = vp->readGtoH<int32_t>(addr); 792292SN/A 8013560Snikos.nikoleris@arm.com tc->delVirtPort(vp); 812292SN/A} 8213560Snikos.nikoleris@arm.com 832292SN/AAddr 848346Sksewell@umich.eduProcessInfo::task(Addr ksp) const 852292SN/A{ 8613560Snikos.nikoleris@arm.com Addr base = ksp & ~0x3fff; 872292SN/A if (base == ULL(0xfffffc0000000000)) 882292SN/A return 0; 892292SN/A 902292SN/A Addr tsk; 912292SN/A 928346Sksewell@umich.edu VirtualPort *vp; 932292SN/A 942292SN/A vp = tc->getVirtPort(); 9513449Sgabeblack@google.com tsk = vp->readGtoH<Addr>(base + task_off); 9613449Sgabeblack@google.com tc->delVirtPort(vp); 972292SN/A 982292SN/A return tsk; 9913472Srekai.gonzalezalberquilla@arm.com} 1006221Snate@binkert.org 10113472Srekai.gonzalezalberquilla@arm.comint 10213472Srekai.gonzalezalberquilla@arm.comProcessInfo::pid(Addr ksp) const 1038850Sandreas.hansson@arm.com{ 1042292SN/A Addr task = this->task(ksp); 1052292SN/A if (!task) 1062292SN/A return -1; 1072292SN/A 1082292SN/A uint16_t pd; 1092292SN/A 1102292SN/A VirtualPort *vp; 1112292SN/A 1122292SN/A vp = tc->getVirtPort(); 1132292SN/A pd = vp->readGtoH<uint16_t>(task + pid_off); 1142292SN/A tc->delVirtPort(vp); 1152292SN/A 1162292SN/A return pd; 1172727Sktlim@umich.edu} 1182727Sktlim@umich.edu 1192727Sktlim@umich.edustring 1206221Snate@binkert.orgProcessInfo::name(Addr ksp) const 1212727Sktlim@umich.edu{ 1222727Sktlim@umich.edu Addr task = this->task(ksp); 1232727Sktlim@umich.edu if (!task) 1242727Sktlim@umich.edu return "console"; 1252727Sktlim@umich.edu 1262727Sktlim@umich.edu char comm[256]; 1276221Snate@binkert.org CopyStringOut(tc, comm, task + name_off, sizeof(comm)); 1282292SN/A if (!comm[0]) 1292292SN/A return "startup"; 1302292SN/A 1312292SN/A return comm; 1322292SN/A} 1332292SN/A 1342307SN/AStackTrace::StackTrace() 1359444SAndreas.Sandberg@ARM.com : tc(0), stack(64) 1362307SN/A{ 1379444SAndreas.Sandberg@ARM.com} 1389444SAndreas.Sandberg@ARM.com 1399444SAndreas.Sandberg@ARM.comStackTrace::StackTrace(ThreadContext *_tc, StaticInstPtr inst) 1409444SAndreas.Sandberg@ARM.com : tc(0), stack(64) 1419444SAndreas.Sandberg@ARM.com{ 1429444SAndreas.Sandberg@ARM.com trace(_tc, inst); 1439444SAndreas.Sandberg@ARM.com} 1449444SAndreas.Sandberg@ARM.com 1459444SAndreas.Sandberg@ARM.comStackTrace::~StackTrace() 1469444SAndreas.Sandberg@ARM.com{ 1479444SAndreas.Sandberg@ARM.com} 1489444SAndreas.Sandberg@ARM.com 1499444SAndreas.Sandberg@ARM.comvoid 1509444SAndreas.Sandberg@ARM.comStackTrace::trace(ThreadContext *_tc, bool is_call) 1519444SAndreas.Sandberg@ARM.com{ 1522307SN/A tc = _tc; 1539444SAndreas.Sandberg@ARM.com /* FIXME - Jaidev - What is IPR_DTB_CM in Alpha? */ 1549444SAndreas.Sandberg@ARM.com bool usermode = 0; 1559444SAndreas.Sandberg@ARM.com //(tc->readMiscReg(MipsISA::IPR_DTB_CM) & 0x18) != 0; 1569444SAndreas.Sandberg@ARM.com 1579444SAndreas.Sandberg@ARM.com// Addr pc = tc->readNextPC(); 1589444SAndreas.Sandberg@ARM.com// bool kernel = tc->getSystemPtr()->kernelStart <= pc && 1599444SAndreas.Sandberg@ARM.com// pc <= tc->getSystemPtr()->kernelEnd; 1602307SN/A 1612307SN/A if (usermode) { 1622307SN/A stack.push_back(user); 1632307SN/A return; 1642307SN/A } 1652307SN/A 1666221Snate@binkert.org// if (!kernel) { 1672307SN/A// stack.push_back(console); 1682307SN/A// return; 1692307SN/A// } 1702307SN/A 1712307SN/A// SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab; 1722292SN/A// Addr ksp = tc->readIntReg(TheISA::StackPointerReg); 1736221Snate@binkert.org// Addr bottom = ksp & ~0x3fff; 1742292SN/A// Addr addr; 17513560Snikos.nikoleris@arm.com 1762292SN/A// if (is_call) { 1772292SN/A// if (!symtab->findNearestAddr(pc, addr)) 1782292SN/A// panic("could not find address %#x", pc); 1792292SN/A 1802292SN/A// stack.push_back(addr); 1812292SN/A// pc = tc->readPC(); 1822292SN/A// } 1832292SN/A 1842292SN/A// Addr ra; 1852292SN/A// int size; 18613560Snikos.nikoleris@arm.com 1873867Sbinkertn@umich.edu// while (ksp > bottom) { 1882292SN/A// if (!symtab->findNearestAddr(pc, addr)) 1892292SN/A// panic("could not find symbol for pc=%#x", pc); 1902292SN/A// assert(pc >= addr && "symbol botch: callpc < func"); 19113560Snikos.nikoleris@arm.com 1922292SN/A// stack.push_back(addr); 19313560Snikos.nikoleris@arm.com 19413560Snikos.nikoleris@arm.com// if (isEntry(addr)) 1952292SN/A// return; 1962292SN/A 1972292SN/A// if (decodePrologue(ksp, pc, addr, size, ra)) { 1982292SN/A// if (!ra) 1992292SN/A// return; 2006221Snate@binkert.org 2016221Snate@binkert.org// if (size <= 0) { 2023867Sbinkertn@umich.edu// stack.push_back(unknown); 2033867Sbinkertn@umich.edu// return; 2046221Snate@binkert.org// } 2053867Sbinkertn@umich.edu 2063867Sbinkertn@umich.edu// pc = ra; 2072292SN/A// ksp += size; 2082292SN/A// } else { 2092292SN/A// stack.push_back(unknown); 2102292SN/A// return; 2112292SN/A// } 2122292SN/A 2136221Snate@binkert.org// bool kernel = tc->getSystemPtr()->kernelStart <= pc && 2142292SN/A// pc <= tc->getSystemPtr()->kernelEnd; 2152292SN/A// if (!kernel) 2162292SN/A// return; 2172292SN/A 2182292SN/A// if (stack.size() >= 1000) 2192292SN/A// panic("unwinding too far"); 2202292SN/A// } 2216221Snate@binkert.org 2222292SN/A// panic("unwinding too far"); 2232292SN/A} 2242292SN/A 2252292SN/Abool 2262292SN/AStackTrace::isEntry(Addr addr) 2272292SN/A{ 2282292SN/A /* if (addr == tc->readMiscReg(MipsISA::IPR_PALtemp2)) 2292292SN/A return true;*/ 2302292SN/A 2316221Snate@binkert.org return false; 2326221Snate@binkert.org} 2332292SN/A 2343867Sbinkertn@umich.edubool 2356221Snate@binkert.orgStackTrace::decodeStack(MachInst inst, int &disp) 2362292SN/A{ 2372292SN/A // lda $sp, -disp($sp) 2382292SN/A // 2392292SN/A // Opcode<31:26> == 0x08 2402292SN/A // RA<25:21> == 30 2412292SN/A // RB<20:16> == 30 2422292SN/A // Disp<15:0> 24313429Srekai.gonzalezalberquilla@arm.com const MachInst mem_mask = 0xffff0000; 2442292SN/A const MachInst lda_pattern = 0x23de0000; 2456221Snate@binkert.org const MachInst lda_disp_mask = 0x0000ffff; 2462292SN/A 2472292SN/A // subq $sp, disp, $sp 2482292SN/A // addq $sp, disp, $sp 2492292SN/A // 2502292SN/A // Opcode<31:26> == 0x10 2512292SN/A // RA<25:21> == 30 25213429Srekai.gonzalezalberquilla@arm.com // Lit<20:13> 2532292SN/A // One<12> = 1 2546221Snate@binkert.org // Func<11:5> == 0x20 (addq) 2552292SN/A // Func<11:5> == 0x29 (subq) 2562292SN/A // RC<4:0> == 30 2572292SN/A const MachInst intop_mask = 0xffe01fff; 2582292SN/A const MachInst addq_pattern = 0x43c0141e; 2592292SN/A const MachInst subq_pattern = 0x43c0153e; 2602292SN/A const MachInst intop_disp_mask = 0x001fe000; 26113429Srekai.gonzalezalberquilla@arm.com const int intop_disp_shift = 13; 2622292SN/A 2636221Snate@binkert.org if ((inst & mem_mask) == lda_pattern) 2642292SN/A disp = -sext<16>(inst & lda_disp_mask); 2652292SN/A else if ((inst & intop_mask) == addq_pattern) 2662292SN/A disp = -int((inst & intop_disp_mask) >> intop_disp_shift); 2672292SN/A else if ((inst & intop_mask) == subq_pattern) 2682292SN/A disp = int((inst & intop_disp_mask) >> intop_disp_shift); 2692292SN/A else 27013429Srekai.gonzalezalberquilla@arm.com return false; 2712292SN/A 2726221Snate@binkert.org return true; 2732292SN/A} 2742292SN/A 2752292SN/Abool 2762292SN/AStackTrace::decodeSave(MachInst inst, int ®, int &disp) 2772292SN/A{ 2782292SN/A // lda $stq, disp($sp) 2792292SN/A // 2802292SN/A // Opcode<31:26> == 0x08 2816221Snate@binkert.org // RA<25:21> == ? 2826221Snate@binkert.org // RB<20:16> == 30 2832292SN/A // Disp<15:0> 2843867Sbinkertn@umich.edu const MachInst stq_mask = 0xfc1f0000; 2856221Snate@binkert.org const MachInst stq_pattern = 0xb41e0000; 2862292SN/A const MachInst stq_disp_mask = 0x0000ffff; 2872292SN/A const MachInst reg_mask = 0x03e00000; 2882329SN/A const int reg_shift = 21; 2892329SN/A 2902292SN/A if ((inst & stq_mask) == stq_pattern) { 2912292SN/A reg = (inst & reg_mask) >> reg_shift; 2922292SN/A disp = sext<16>(inst & stq_disp_mask); 2932292SN/A } else { 2942292SN/A return false; 2952292SN/A } 2962292SN/A 2972292SN/A return true; 2982292SN/A} 2992292SN/A 3002292SN/A/* 3016221Snate@binkert.org * Decode the function prologue for the function we're in, and note 3026221Snate@binkert.org * which registers are stored where, and how large the stack frame is. 3032292SN/A */ 3043867Sbinkertn@umich.edubool 3056221Snate@binkert.orgStackTrace::decodePrologue(Addr sp, Addr callpc, Addr func, 3063867Sbinkertn@umich.edu int &size, Addr &ra) 3072292SN/A{ 3082292SN/A size = 0; 3092292SN/A ra = 0; 3102292SN/A 3112292SN/A for (Addr pc = func; pc < callpc; pc += sizeof(MachInst)) { 3122292SN/A MachInst inst; 3132292SN/A CopyOut(tc, (uint8_t *)&inst, pc, sizeof(MachInst)); 3148707Sandreas.hansson@arm.com 3158707Sandreas.hansson@arm.com int reg, disp; 31610713Sandreas.hansson@arm.com if (decodeStack(inst, disp)) { 3178707Sandreas.hansson@arm.com if (size) { 31810333Smitch.hayenga@arm.com // panic("decoding frame size again"); 31910333Smitch.hayenga@arm.com return true; 32010333Smitch.hayenga@arm.com } 32110333Smitch.hayenga@arm.com size += disp; 3228707Sandreas.hansson@arm.com } else if (decodeSave(inst, reg, disp)) { 3238707Sandreas.hansson@arm.com if (!ra && reg == ReturnAddressReg) { 3248707Sandreas.hansson@arm.com CopyOut(tc, (uint8_t *)&ra, sp + disp, sizeof(Addr)); 3258707Sandreas.hansson@arm.com if (!ra) { 3268707Sandreas.hansson@arm.com // panic("no return address value pc=%#x\n", pc); 3278975Sandreas.hansson@arm.com return false; 3288707Sandreas.hansson@arm.com } 3298707Sandreas.hansson@arm.com } 3308707Sandreas.hansson@arm.com } 3318707Sandreas.hansson@arm.com } 33210575SMarco.Elver@ARM.com 33311435Smitch.hayenga@arm.com return true; 33411435Smitch.hayenga@arm.com} 33510575SMarco.Elver@ARM.com 33610575SMarco.Elver@ARM.com#if TRACING_ON 33710575SMarco.Elver@ARM.comvoid 33810575SMarco.Elver@ARM.comStackTrace::dump() 33910575SMarco.Elver@ARM.com{ 34010575SMarco.Elver@ARM.com StringWrap name(tc->getCpuPtr()->name()); 34110575SMarco.Elver@ARM.com// SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab; 34210575SMarco.Elver@ARM.com 34310575SMarco.Elver@ARM.com DPRINTFN("------ Stack ------\n"); 34410575SMarco.Elver@ARM.com 34510575SMarco.Elver@ARM.com// string symbol; 34610575SMarco.Elver@ARM.com// for (int i = 0, size = stack.size(); i < size; ++i) { 34710575SMarco.Elver@ARM.com// Addr addr = stack[size - i - 1]; 34810575SMarco.Elver@ARM.com// if (addr == user) 34910575SMarco.Elver@ARM.com// symbol = "user"; 35010575SMarco.Elver@ARM.com// else if (addr == console) 35110575SMarco.Elver@ARM.com// symbol = "console"; 35210575SMarco.Elver@ARM.com// else if (addr == unknown) 35310575SMarco.Elver@ARM.com// symbol = "unknown"; 35410575SMarco.Elver@ARM.com// else 35510575SMarco.Elver@ARM.com// symtab->findSymbol(addr, symbol); 35610573Sstephan.diestelhorst@arm.com 3578948Sandreas.hansson@arm.com// DPRINTFN("%#x: %s\n", addr, symbol); 3588948Sandreas.hansson@arm.com// } 3598707Sandreas.hansson@arm.com} 3608948Sandreas.hansson@arm.com#endif 3618975Sandreas.hansson@arm.com