stacktrace.cc revision 10417
11917SN/A/*
21917SN/A * Copyright (c) 2005 The Regents of The University of Michigan
31917SN/A * All rights reserved.
41917SN/A *
51917SN/A * Redistribution and use in source and binary forms, with or without
61917SN/A * modification, are permitted provided that the following conditions are
71917SN/A * met: redistributions of source code must retain the above copyright
81917SN/A * notice, this list of conditions and the following disclaimer;
91917SN/A * redistributions in binary form must reproduce the above copyright
101917SN/A * notice, this list of conditions and the following disclaimer in the
111917SN/A * documentation and/or other materials provided with the distribution;
121917SN/A * neither the name of the copyright holders nor the names of its
131917SN/A * contributors may be used to endorse or promote products derived from
141917SN/A * this software without specific prior written permission.
151917SN/A *
161917SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
171917SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
181917SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
191917SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
201917SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
211917SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
221917SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
231917SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
241917SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
251917SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
261917SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665Ssaidi@eecs.umich.edu *
282665Ssaidi@eecs.umich.edu * Authors: Nathan Binkert
291917SN/A */
301917SN/A
311917SN/A#include <string>
321917SN/A
331917SN/A#include "arch/alpha/isa_traits.hh"
341917SN/A#include "arch/alpha/stacktrace.hh"
351917SN/A#include "arch/alpha/vtophys.hh"
361917SN/A#include "base/bitfield.hh"
371917SN/A#include "base/trace.hh"
381917SN/A#include "cpu/base.hh"
392680Sktlim@umich.edu#include "cpu/thread_context.hh"
408706Sandreas.hansson@arm.com#include "mem/fs_translating_port_proxy.hh"
412235SN/A#include "sim/system.hh"
421917SN/A
431917SN/Ausing namespace std;
441917SN/A
455569Snate@binkert.orgnamespace AlphaISA {
465569Snate@binkert.org
475569Snate@binkert.orgProcessInfo::ProcessInfo(ThreadContext *_tc)
485569Snate@binkert.org    : tc(_tc)
491917SN/A{
505569Snate@binkert.org    Addr addr = 0;
518852Sandreas.hansson@arm.com    FSTranslatingPortProxy &vp = tc->getVirtProxy();
525569Snate@binkert.org    SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab;
531917SN/A
545569Snate@binkert.org    if (!symtab->findAddress("thread_info_size", addr))
555569Snate@binkert.org        panic("thread info not compiled into kernel\n");
568852Sandreas.hansson@arm.com    thread_info_size = vp.readGtoH<int32_t>(addr);
572684Ssaidi@eecs.umich.edu
585569Snate@binkert.org    if (!symtab->findAddress("task_struct_size", addr))
595569Snate@binkert.org        panic("thread info not compiled into kernel\n");
608852Sandreas.hansson@arm.com    task_struct_size = vp.readGtoH<int32_t>(addr);
612684Ssaidi@eecs.umich.edu
625569Snate@binkert.org    if (!symtab->findAddress("thread_info_task", addr))
635569Snate@binkert.org        panic("thread info not compiled into kernel\n");
648852Sandreas.hansson@arm.com    task_off = vp.readGtoH<int32_t>(addr);
651917SN/A
665569Snate@binkert.org    if (!symtab->findAddress("task_struct_pid", addr))
675569Snate@binkert.org        panic("thread info not compiled into kernel\n");
688852Sandreas.hansson@arm.com    pid_off = vp.readGtoH<int32_t>(addr);
691917SN/A
705569Snate@binkert.org    if (!symtab->findAddress("task_struct_comm", addr))
715569Snate@binkert.org        panic("thread info not compiled into kernel\n");
728852Sandreas.hansson@arm.com    name_off = vp.readGtoH<int32_t>(addr);
735569Snate@binkert.org}
741917SN/A
755569Snate@binkert.orgAddr
765569Snate@binkert.orgProcessInfo::task(Addr ksp) const
775569Snate@binkert.org{
785569Snate@binkert.org    Addr base = ksp & ~0x3fff;
795569Snate@binkert.org    if (base == ULL(0xfffffc0000000000))
805569Snate@binkert.org        return 0;
811917SN/A
825569Snate@binkert.org    Addr tsk;
835569Snate@binkert.org
848852Sandreas.hansson@arm.com    FSTranslatingPortProxy &vp = tc->getVirtProxy();
858852Sandreas.hansson@arm.com    tsk = vp.readGtoH<Addr>(base + task_off);
865569Snate@binkert.org
875569Snate@binkert.org    return tsk;
885569Snate@binkert.org}
895569Snate@binkert.org
905569Snate@binkert.orgint
915569Snate@binkert.orgProcessInfo::pid(Addr ksp) const
925569Snate@binkert.org{
935569Snate@binkert.org    Addr task = this->task(ksp);
945569Snate@binkert.org    if (!task)
955569Snate@binkert.org        return -1;
965569Snate@binkert.org
975569Snate@binkert.org    uint16_t pd;
985569Snate@binkert.org
998852Sandreas.hansson@arm.com    FSTranslatingPortProxy &vp = tc->getVirtProxy();
1008852Sandreas.hansson@arm.com    pd = vp.readGtoH<uint16_t>(task + pid_off);
1015569Snate@binkert.org
1025569Snate@binkert.org    return pd;
1035569Snate@binkert.org}
1045569Snate@binkert.org
1055569Snate@binkert.orgstring
1065569Snate@binkert.orgProcessInfo::name(Addr ksp) const
1075569Snate@binkert.org{
1085569Snate@binkert.org    Addr task = this->task(ksp);
1095569Snate@binkert.org    if (!task)
1105569Snate@binkert.org        return "console";
1115569Snate@binkert.org
1125569Snate@binkert.org    char comm[256];
1135569Snate@binkert.org    CopyStringOut(tc, comm, task + name_off, sizeof(comm));
1145569Snate@binkert.org    if (!comm[0])
1155569Snate@binkert.org        return "startup";
1165569Snate@binkert.org
1175569Snate@binkert.org    return comm;
1185569Snate@binkert.org}
1195569Snate@binkert.org
1205569Snate@binkert.orgStackTrace::StackTrace()
1215569Snate@binkert.org    : tc(0), stack(64)
1225569Snate@binkert.org{
1235569Snate@binkert.org}
1245569Snate@binkert.org
12510417Sandreas.hansson@arm.comStackTrace::StackTrace(ThreadContext *_tc, const StaticInstPtr &inst)
1265569Snate@binkert.org    : tc(0), stack(64)
1275569Snate@binkert.org{
1285569Snate@binkert.org    trace(_tc, inst);
1295569Snate@binkert.org}
1305569Snate@binkert.org
1315569Snate@binkert.orgStackTrace::~StackTrace()
1325569Snate@binkert.org{
1335569Snate@binkert.org}
1345569Snate@binkert.org
1355569Snate@binkert.orgvoid
1365569Snate@binkert.orgStackTrace::trace(ThreadContext *_tc, bool is_call)
1375569Snate@binkert.org{
1385569Snate@binkert.org    tc = _tc;
1395569Snate@binkert.org
1405569Snate@binkert.org    System *sys = tc->getSystemPtr();
1415569Snate@binkert.org
1425569Snate@binkert.org    bool usermode =
1435569Snate@binkert.org        (tc->readMiscRegNoEffect(IPR_DTB_CM) & 0x18) != 0;
1445569Snate@binkert.org
1457720Sgblack@eecs.umich.edu    Addr pc = tc->pcState().pc();
1465569Snate@binkert.org    bool kernel = sys->kernelStart <= pc && pc <= sys->kernelEnd;
1475569Snate@binkert.org
1485569Snate@binkert.org    if (usermode) {
1495569Snate@binkert.org        stack.push_back(user);
1505569Snate@binkert.org        return;
1511917SN/A    }
1521917SN/A
1535569Snate@binkert.org    if (!kernel) {
1545569Snate@binkert.org        stack.push_back(console);
1555569Snate@binkert.org        return;
1561917SN/A    }
1571917SN/A
1585569Snate@binkert.org    SymbolTable *symtab = sys->kernelSymtab;
1595569Snate@binkert.org    Addr ksp = tc->readIntReg(StackPointerReg);
1605569Snate@binkert.org    Addr bottom = ksp & ~0x3fff;
1611917SN/A
1625569Snate@binkert.org    if (is_call) {
1635569Snate@binkert.org        Addr addr;
1645569Snate@binkert.org        if (!symtab->findNearestAddr(pc, addr))
1655569Snate@binkert.org            panic("could not find address %#x", pc);
1661917SN/A
1675569Snate@binkert.org        stack.push_back(addr);
1687720Sgblack@eecs.umich.edu        pc = tc->pcState().pc();
1691917SN/A    }
1701917SN/A
1715569Snate@binkert.org    while (ksp > bottom) {
1725569Snate@binkert.org        Addr addr;
1735569Snate@binkert.org        if (!symtab->findNearestAddr(pc, addr))
1745569Snate@binkert.org            panic("could not find symbol for pc=%#x", pc);
1755569Snate@binkert.org        assert(pc >= addr && "symbol botch: callpc < func");
1761917SN/A
1775569Snate@binkert.org        stack.push_back(addr);
1781917SN/A
1795569Snate@binkert.org        if (isEntry(addr))
1801917SN/A            return;
1813570Sgblack@eecs.umich.edu
1823570Sgblack@eecs.umich.edu        Addr ra;
1833570Sgblack@eecs.umich.edu        int size;
1845569Snate@binkert.org        if (decodePrologue(ksp, pc, addr, size, ra)) {
1855569Snate@binkert.org            if (!ra)
1861917SN/A                return;
1871917SN/A
1885569Snate@binkert.org            if (size <= 0) {
1891977SN/A                stack.push_back(unknown);
1901977SN/A                return;
1911977SN/A            }
1921977SN/A
1935569Snate@binkert.org            pc = ra;
1945569Snate@binkert.org            ksp += size;
1955569Snate@binkert.org        } else {
1965569Snate@binkert.org            stack.push_back(unknown);
1975569Snate@binkert.org            return;
1981917SN/A        }
1991917SN/A
2009550Sandreas.hansson@arm.com        kernel = sys->kernelStart <= pc && pc <= sys->kernelEnd;
2015569Snate@binkert.org        if (!kernel)
2025569Snate@binkert.org            return;
2035569Snate@binkert.org
2045569Snate@binkert.org        if (stack.size() >= 1000)
2055569Snate@binkert.org            panic("unwinding too far");
2061917SN/A    }
2071917SN/A
2085569Snate@binkert.org    panic("unwinding too far");
2095569Snate@binkert.org}
2101917SN/A
2115569Snate@binkert.orgbool
2125569Snate@binkert.orgStackTrace::isEntry(Addr addr)
2135569Snate@binkert.org{
2145569Snate@binkert.org    if (addr == tc->readMiscRegNoEffect(IPR_PALtemp12))
2155569Snate@binkert.org        return true;
2161917SN/A
2175569Snate@binkert.org    if (addr == tc->readMiscRegNoEffect(IPR_PALtemp7))
2185569Snate@binkert.org        return true;
2191917SN/A
2205569Snate@binkert.org    if (addr == tc->readMiscRegNoEffect(IPR_PALtemp11))
2215569Snate@binkert.org        return true;
2221917SN/A
2235569Snate@binkert.org    if (addr == tc->readMiscRegNoEffect(IPR_PALtemp21))
2245569Snate@binkert.org        return true;
2251917SN/A
2265569Snate@binkert.org    if (addr == tc->readMiscRegNoEffect(IPR_PALtemp9))
2275569Snate@binkert.org        return true;
2281917SN/A
2295569Snate@binkert.org    if (addr == tc->readMiscRegNoEffect(IPR_PALtemp2))
2305569Snate@binkert.org        return true;
2315569Snate@binkert.org
2325569Snate@binkert.org    return false;
2335569Snate@binkert.org}
2345569Snate@binkert.org
2355569Snate@binkert.orgbool
2365569Snate@binkert.orgStackTrace::decodeStack(MachInst inst, int &disp)
2375569Snate@binkert.org{
2385569Snate@binkert.org    // lda $sp, -disp($sp)
2395569Snate@binkert.org    //
2405569Snate@binkert.org    // Opcode<31:26> == 0x08
2415569Snate@binkert.org    // RA<25:21> == 30
2425569Snate@binkert.org    // RB<20:16> == 30
2435569Snate@binkert.org    // Disp<15:0>
2445569Snate@binkert.org    const MachInst mem_mask = 0xffff0000;
2455569Snate@binkert.org    const MachInst lda_pattern = 0x23de0000;
2465569Snate@binkert.org    const MachInst lda_disp_mask = 0x0000ffff;
2475569Snate@binkert.org
2485569Snate@binkert.org    // subq $sp, disp, $sp
2495569Snate@binkert.org    // addq $sp, disp, $sp
2505569Snate@binkert.org    //
2515569Snate@binkert.org    // Opcode<31:26> == 0x10
2525569Snate@binkert.org    // RA<25:21> == 30
2535569Snate@binkert.org    // Lit<20:13>
2545569Snate@binkert.org    // One<12> = 1
2555569Snate@binkert.org    // Func<11:5> == 0x20 (addq)
2565569Snate@binkert.org    // Func<11:5> == 0x29 (subq)
2575569Snate@binkert.org    // RC<4:0> == 30
2585569Snate@binkert.org    const MachInst intop_mask = 0xffe01fff;
2595569Snate@binkert.org    const MachInst addq_pattern = 0x43c0141e;
2605569Snate@binkert.org    const MachInst subq_pattern = 0x43c0153e;
2615569Snate@binkert.org    const MachInst intop_disp_mask = 0x001fe000;
2625569Snate@binkert.org    const int intop_disp_shift = 13;
2635569Snate@binkert.org
2645569Snate@binkert.org    if ((inst & mem_mask) == lda_pattern)
2655569Snate@binkert.org        disp = -sext<16>(inst & lda_disp_mask);
2665569Snate@binkert.org    else if ((inst & intop_mask) == addq_pattern)
2675569Snate@binkert.org        disp = -int((inst & intop_disp_mask) >> intop_disp_shift);
2685569Snate@binkert.org    else if ((inst & intop_mask) == subq_pattern)
2695569Snate@binkert.org        disp = int((inst & intop_disp_mask) >> intop_disp_shift);
2705569Snate@binkert.org    else
2715569Snate@binkert.org        return false;
2725569Snate@binkert.org
2735569Snate@binkert.org    return true;
2745569Snate@binkert.org}
2755569Snate@binkert.org
2765569Snate@binkert.orgbool
2775569Snate@binkert.orgStackTrace::decodeSave(MachInst inst, int &reg, int &disp)
2785569Snate@binkert.org{
2795569Snate@binkert.org    // lda $stq, disp($sp)
2805569Snate@binkert.org    //
2815569Snate@binkert.org    // Opcode<31:26> == 0x08
2825569Snate@binkert.org    // RA<25:21> == ?
2835569Snate@binkert.org    // RB<20:16> == 30
2845569Snate@binkert.org    // Disp<15:0>
2855569Snate@binkert.org    const MachInst stq_mask = 0xfc1f0000;
2865569Snate@binkert.org    const MachInst stq_pattern = 0xb41e0000;
2875569Snate@binkert.org    const MachInst stq_disp_mask = 0x0000ffff;
2885569Snate@binkert.org    const MachInst reg_mask = 0x03e00000;
2895569Snate@binkert.org    const int reg_shift = 21;
2905569Snate@binkert.org
2915569Snate@binkert.org    if ((inst & stq_mask) == stq_pattern) {
2925569Snate@binkert.org        reg = (inst & reg_mask) >> reg_shift;
2935569Snate@binkert.org        disp = sext<16>(inst & stq_disp_mask);
2945569Snate@binkert.org    } else {
2951917SN/A        return false;
2961917SN/A    }
2971917SN/A
2985569Snate@binkert.org    return true;
2995569Snate@binkert.org}
3001917SN/A
3015569Snate@binkert.org/*
3025569Snate@binkert.org * Decode the function prologue for the function we're in, and note
3035569Snate@binkert.org * which registers are stored where, and how large the stack frame is.
3045569Snate@binkert.org */
3055569Snate@binkert.orgbool
3065569Snate@binkert.orgStackTrace::decodePrologue(Addr sp, Addr callpc, Addr func, int &size,
3075569Snate@binkert.org                           Addr &ra)
3085569Snate@binkert.org{
3095569Snate@binkert.org    size = 0;
3105569Snate@binkert.org    ra = 0;
3111917SN/A
3125569Snate@binkert.org    for (Addr pc = func; pc < callpc; pc += sizeof(MachInst)) {
3135569Snate@binkert.org        MachInst inst;
3145569Snate@binkert.org        CopyOut(tc, (uint8_t *)&inst, pc, sizeof(MachInst));
3151917SN/A
3165569Snate@binkert.org        int reg, disp;
3175569Snate@binkert.org        if (decodeStack(inst, disp)) {
3185569Snate@binkert.org            if (size) {
3195569Snate@binkert.org                // panic("decoding frame size again");
3205569Snate@binkert.org                return true;
3215569Snate@binkert.org            }
3225569Snate@binkert.org            size += disp;
3235569Snate@binkert.org        } else if (decodeSave(inst, reg, disp)) {
3245569Snate@binkert.org            if (!ra && reg == ReturnAddressReg) {
3255569Snate@binkert.org                CopyOut(tc, (uint8_t *)&ra, sp + disp, sizeof(Addr));
3265569Snate@binkert.org                if (!ra) {
3275569Snate@binkert.org                    // panic("no return address value pc=%#x\n", pc);
3285569Snate@binkert.org                    return false;
3291917SN/A                }
3301917SN/A            }
3311917SN/A        }
3321917SN/A    }
3331917SN/A
3345569Snate@binkert.org    return true;
3355569Snate@binkert.org}
3365569Snate@binkert.org
3373570Sgblack@eecs.umich.edu#if TRACING_ON
3385569Snate@binkert.orgvoid
3395569Snate@binkert.orgStackTrace::dump()
3405569Snate@binkert.org{
3415569Snate@binkert.org    StringWrap name(tc->getCpuPtr()->name());
3425569Snate@binkert.org    SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab;
3433570Sgblack@eecs.umich.edu
3445569Snate@binkert.org    DPRINTFN("------ Stack ------\n");
3453570Sgblack@eecs.umich.edu
3465569Snate@binkert.org    string symbol;
3475569Snate@binkert.org    for (int i = 0, size = stack.size(); i < size; ++i) {
3485569Snate@binkert.org        Addr addr = stack[size - i - 1];
3495569Snate@binkert.org        if (addr == user)
3505569Snate@binkert.org            symbol = "user";
3515569Snate@binkert.org        else if (addr == console)
3525569Snate@binkert.org            symbol = "console";
3535569Snate@binkert.org        else if (addr == unknown)
3545569Snate@binkert.org            symbol = "unknown";
3555569Snate@binkert.org        else
3565569Snate@binkert.org            symtab->findSymbol(addr, symbol);
3573570Sgblack@eecs.umich.edu
3585569Snate@binkert.org        DPRINTFN("%#x: %s\n", addr, symbol);
3593570Sgblack@eecs.umich.edu    }
3605569Snate@binkert.org}
3613570Sgblack@eecs.umich.edu#endif
3625569Snate@binkert.org
3635569Snate@binkert.org} // namespace AlphaISA
364