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 &reg, 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