stacktrace.cc revision 1977
13116SN/A/*
23116SN/A * Copyright (c) 2005 The Regents of The University of Michigan
33116SN/A * All rights reserved.
43116SN/A *
53116SN/A * Redistribution and use in source and binary forms, with or without
63116SN/A * modification, are permitted provided that the following conditions are
73116SN/A * met: redistributions of source code must retain the above copyright
83116SN/A * notice, this list of conditions and the following disclaimer;
93116SN/A * redistributions in binary form must reproduce the above copyright
103116SN/A * notice, this list of conditions and the following disclaimer in the
113116SN/A * documentation and/or other materials provided with the distribution;
123116SN/A * neither the name of the copyright holders nor the names of its
133116SN/A * contributors may be used to endorse or promote products derived from
143116SN/A * this software without specific prior written permission.
153116SN/A *
163116SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
173116SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
183116SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
193116SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
203116SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
213116SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
223116SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
233116SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
243116SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
253116SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
263116SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
273116SN/A */
283116SN/A
293116SN/A#include <string>
303116SN/A
313116SN/A#include "arch/alpha/isa_traits.hh"
323116SN/A#include "arch/alpha/stacktrace.hh"
333318SN/A#include "arch/alpha/vtophys.hh"
343318SN/A#include "base/bitfield.hh"
353318SN/A#include "base/trace.hh"
363116SN/A#include "cpu/base.hh"
373116SN/A#include "cpu/exec_context.hh"
3811263Sandreas.sandberg@arm.com
394263SN/Ausing namespace std;
404263SN/A
414263SN/AProcessInfo::ProcessInfo(ExecContext *_xc)
424263SN/A    : xc(_xc)
434263SN/A{
444762SN/A    Addr addr = 0;
4510469SN/A
464762SN/A    if (!xc->system->kernelSymtab->findAddress("thread_info_size", addr))
473116SN/A        panic("thread info not compiled into kernel\n");
484263SN/A    thread_info_size = *(int32_t *)vtomem(xc, addr, sizeof(int32_t));
499152SN/A
508232SN/A    if (!xc->system->kernelSymtab->findAddress("task_struct_size", addr))
513116SN/A        panic("thread info not compiled into kernel\n");
523405SN/A    task_struct_size = *(int32_t *)vtomem(xc, addr, sizeof(int32_t));
534762SN/A
543116SN/A    if (!xc->system->kernelSymtab->findAddress("thread_info_task", addr))
553116SN/A        panic("thread info not compiled into kernel\n");
563116SN/A    task_off = *(int32_t *)vtomem(xc, addr, sizeof(int32_t));
573318SN/A
584263SN/A    if (!xc->system->kernelSymtab->findAddress("task_struct_pid", addr))
593318SN/A        panic("thread info not compiled into kernel\n");
604981SN/A    pid_off = *(int32_t *)vtomem(xc, addr, sizeof(int32_t));
6110913SN/A
624263SN/A    if (!xc->system->kernelSymtab->findAddress("task_struct_comm", addr))
635783SN/A        panic("thread info not compiled into kernel\n");
645535SN/A    name_off = *(int32_t *)vtomem(xc, addr, sizeof(int32_t));
655535SN/A}
665535SN/A
675535SN/AAddr
684291SN/AProcessInfo::task(Addr ksp) const
694283SN/A{
705500SN/A    Addr base = ksp & ~0x3fff;
719157SN/A    if (base == ULL(0xfffffc0000000000))
723116SN/A        return 0;
734981SN/A
744981SN/A    Addr task;
753318SN/A    CopyOut(xc, &task, base + task_off, sizeof(task));
764263SN/A    return task;
774218SN/A}
784218SN/A
794218SN/Aint
804218SN/AProcessInfo::pid(Addr ksp) const
814218SN/A{
824218SN/A    Addr task = this->task(ksp);
834283SN/A    if (!task)
844218SN/A        return -1;
854218SN/A
864263SN/A    uint16_t pid;
874263SN/A    CopyOut(xc, &pid, task + pid_off, sizeof(pid));
884263SN/A    return pid;
894263SN/A}
904218SN/A
915763SN/Astring
925763SN/AProcessInfo::name(Addr ksp) const
935763SN/A{
943116SN/A    Addr task = this->task(ksp);
954218SN/A    if (!task)
964218SN/A        return "console";
973405SN/A
983318SN/A    char comm[256];
993318SN/A    CopyString(xc, comm, task + name_off, sizeof(comm));
1003318SN/A    if (!comm[0])
1013318SN/A        return "startup";
1023318SN/A
1033405SN/A    return comm;
1043405SN/A}
1053405SN/A
1064283SN/AStackTrace::StackTrace()
1074283SN/A    : xc(0), stack(64)
1084283SN/A{
1094283SN/A}
1104218SN/A
1114218SN/AStackTrace::StackTrace(ExecContext *_xc, StaticInstPtr<TheISA> inst)
1124218SN/A    : xc(0), stack(64)
1134283SN/A{
1144283SN/A    trace(_xc, inst);
1154218SN/A}
1163318SN/A
1174218SN/AStackTrace::~StackTrace()
1184263SN/A{
1195954SN/A}
1205954SN/A
1215954SN/Avoid
1224263SN/AStackTrace::trace(ExecContext *_xc, bool is_call)
1234263SN/A{
1243116SN/A    xc = _xc;
1253116SN/A
1269086SN/A    bool usermode = (xc->regs.ipr[AlphaISA::IPR_DTB_CM] & 0x18) != 0;
1279086SN/A
1289086SN/A    Addr pc = xc->regs.npc;
1299086SN/A    bool kernel = xc->system->kernelStart <= pc && pc <= xc->system->kernelEnd;
1309086SN/A
1315954SN/A    if (usermode) {
1325954SN/A        stack.push_back(user);
1335954SN/A        return;
1345954SN/A    }
1359807SN/A
1365954SN/A    if (!kernel) {
1375954SN/A        stack.push_back(console);
1384981SN/A        return;
1394981SN/A    }
1404981SN/A
1414981SN/A    SymbolTable *symtab = xc->system->kernelSymtab;
1424987SN/A    Addr ksp = xc->regs.intRegFile[TheISA::StackPointerReg];
1434981SN/A    Addr bottom = ksp & ~0x3fff;
1444981SN/A    Addr addr;
1454981SN/A
1464981SN/A    if (is_call) {
1474981SN/A        if (!symtab->findNearestAddr(pc, addr))
1484981SN/A            panic("could not find address %#x", pc);
1493116SN/A
1503116SN/A        stack.push_back(addr);
1513349SN/A        pc = xc->regs.pc;
1523116SN/A    }
1533116SN/A
1543116SN/A    Addr ra;
1559807SN/A    int size;
1563116SN/A
1573116SN/A    while (ksp > bottom) {
1583116SN/A        if (!symtab->findNearestAddr(pc, addr))
1596124SN/A            panic("could not find symbol for pc=%#x", pc);
1606124SN/A        assert(pc >= addr && "symbol botch: callpc < func");
1616124SN/A
1623116SN/A        stack.push_back(addr);
1639198SN/A
1643116SN/A        if (isEntry(addr))
1653116SN/A            return;
1666124SN/A
1676124SN/A        if (decodePrologue(ksp, pc, addr, size, ra)) {
1686124SN/A            if (!ra)
1693116SN/A                return;
1703349SN/A
1713116SN/A            if (size <= 0) {
1723116SN/A                stack.push_back(unknown);
1733116SN/A                return;
1743116SN/A            }
1753116SN/A
1763116SN/A            pc = ra;
1773116SN/A            ksp += size;
1783116SN/A        } else {
1793116SN/A            stack.push_back(unknown);
1803116SN/A            return;
1813318SN/A        }
1823318SN/A
1833318SN/A        bool kernel = xc->system->kernelStart <= pc &&
1844283SN/A            pc <= xc->system->kernelEnd;
1853116SN/A        if (!kernel)
1866124SN/A            return;
1876124SN/A
1886124SN/A        if (stack.size() >= 1000)
1893116SN/A            panic("unwinding too far");
1903405SN/A    }
1913318SN/A
1924218SN/A    panic("unwinding too far");
1934218SN/A}
1944218SN/A
1954218SN/Abool
1964218SN/AStackTrace::isEntry(Addr addr)
1974218SN/A{
1984218SN/A    if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp12])
1994218SN/A        return true;
2004218SN/A
2014218SN/A    if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp7])
2024218SN/A        return true;
2034218SN/A
2044218SN/A    if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp11])
2054218SN/A        return true;
2064218SN/A
2074218SN/A    if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp21])
2084218SN/A        return true;
2094218SN/A
2104218SN/A    if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp9])
2116124SN/A        return true;
2126124SN/A
2134218SN/A    if (addr == xc->regs.ipr[AlphaISA::IPR_PALtemp2])
2144283SN/A        return true;
2154283SN/A
2164283SN/A    return false;
2174263SN/A}
2184283SN/A
2194283SN/Abool
2204283SN/AStackTrace::decodeStack(MachInst inst, int &disp)
2214218SN/A{
2225763SN/A    // lda $sp, -disp($sp)
2235763SN/A    //
2245763SN/A    // Opcode<31:26> == 0x08
2255763SN/A    // RA<25:21> == 30
2265763SN/A    // RB<20:16> == 30
2274218SN/A    // Disp<15:0>
2284218SN/A    const MachInst mem_mask = 0xffff0000;
2294218SN/A    const MachInst lda_pattern = 0x23de0000;
2304218SN/A    const MachInst lda_disp_mask = 0x0000ffff;
2314218SN/A
2324218SN/A    // subq $sp, disp, $sp
2334218SN/A    // addq $sp, disp, $sp
2344218SN/A    //
2354218SN/A    // Opcode<31:26> == 0x10
2364218SN/A    // RA<25:21> == 30
2374218SN/A    // Lit<20:13>
2384218SN/A    // One<12> = 1
2394218SN/A    // Func<11:5> == 0x20 (addq)
2404218SN/A    // Func<11:5> == 0x29 (subq)
2414218SN/A    // RC<4:0> == 30
2424218SN/A    const MachInst intop_mask = 0xffe01fff;
2434218SN/A    const MachInst addq_pattern = 0x43c0141e;
2444218SN/A    const MachInst subq_pattern = 0x43c0153e;
2454218SN/A    const MachInst intop_disp_mask = 0x001fe000;
2464218SN/A    const int intop_disp_shift = 13;
2474218SN/A
2484218SN/A    if ((inst & mem_mask) == lda_pattern)
2494218SN/A        disp = -sext<16>(inst & lda_disp_mask);
2504218SN/A    else if ((inst & intop_mask) == addq_pattern)
2514218SN/A        disp = -int((inst & intop_disp_mask) >> intop_disp_shift);
2524218SN/A    else if ((inst & intop_mask) == subq_pattern)
2534218SN/A        disp = int((inst & intop_disp_mask) >> intop_disp_shift);
2544218SN/A    else
2554218SN/A        return false;
2564218SN/A
2574218SN/A    return true;
2584218SN/A}
2594218SN/A
2604218SN/Abool
2615763SN/AStackTrace::decodeSave(MachInst inst, int &reg, int &disp)
2625763SN/A{
2635763SN/A    // lda $stq, disp($sp)
2644218SN/A    //
2654218SN/A    // Opcode<31:26> == 0x08
2664218SN/A    // RA<25:21> == ?
2674218SN/A    // RB<20:16> == 30
2684218SN/A    // Disp<15:0>
2694218SN/A    const MachInst stq_mask = 0xfc1f0000;
2704218SN/A    const MachInst stq_pattern = 0xb41e0000;
2714218SN/A    const MachInst stq_disp_mask = 0x0000ffff;
2724263SN/A    const MachInst reg_mask = 0x03e00000;
2734263SN/A    const int reg_shift = 21;
2746124SN/A
2756124SN/A    if ((inst & stq_mask) == stq_pattern) {
2764263SN/A        reg = (inst & reg_mask) >> reg_shift;
2774263SN/A        disp = sext<16>(inst & stq_disp_mask);
2784263SN/A    } else {
2794218SN/A        return false;
2805763SN/A    }
2815763SN/A
2825763SN/A    return true;
2834218SN/A}
2844218SN/A
2854218SN/A/*
2864218SN/A * Decode the function prologue for the function we're in, and note
2874218SN/A * which registers are stored where, and how large the stack frame is.
2884218SN/A */
2894218SN/Abool
2904218SN/AStackTrace::decodePrologue(Addr sp, Addr callpc, Addr func,
2914218SN/A                           int &size, Addr &ra)
2924218SN/A{
2934218SN/A    size = 0;
2944218SN/A    ra = 0;
2954218SN/A
2964218SN/A    for (Addr pc = func; pc < callpc; pc += sizeof(MachInst)) {
2974218SN/A        MachInst inst;
2985763SN/A        CopyOut(xc, (uint8_t *)&inst, pc, sizeof(MachInst));
2995763SN/A
3005763SN/A        int reg, disp;
3014218SN/A        if (decodeStack(inst, disp)) {
3024218SN/A            if (size) {
3034218SN/A                // panic("decoding frame size again");
3044218SN/A                return true;
3054218SN/A            }
3064218SN/A            size += disp;
3074218SN/A        } else if (decodeSave(inst, reg, disp)) {
3084218SN/A            if (!ra && reg == ReturnAddressReg) {
3094218SN/A                CopyOut(xc, (uint8_t *)&ra, sp + disp, sizeof(Addr));
3104218SN/A                if (!ra) {
3114218SN/A                    // panic("no return address value pc=%#x\n", pc);
3124218SN/A                    return false;
3135763SN/A                }
3145763SN/A            }
3155763SN/A        }
3165763SN/A    }
3175763SN/A
3185763SN/A    return true;
3194218SN/A}
3204218SN/A
3214218SN/A#if TRACING_ON
3225763SN/Avoid
3235763SN/AStackTrace::dump()
3245763SN/A{
3255763SN/A    StringWrap name(xc->cpu->name());
3265763SN/A    SymbolTable *symtab = xc->system->kernelSymtab;
3275763SN/A
3284218SN/A    DPRINTFN("------ Stack ------\n");
3294218SN/A
3304218SN/A    string symbol;
3315763SN/A    for (int i = 0, size = stack.size(); i < size; ++i) {
3325763SN/A        Addr addr = stack[size - i - 1];
3335763SN/A        if (addr == user)
3345763SN/A            symbol = "user";
3355763SN/A        else if (addr == console)
3365763SN/A            symbol = "console";
3375763SN/A        else if (addr == unknown)
3385763SN/A            symbol = "unknown";
3395763SN/A        else
3405763SN/A            symtab->findSymbol(addr, symbol);
3413318SN/A
3426124SN/A        DPRINTFN("%#x: %s\n", addr, symbol);
3436124SN/A    }
3446124SN/A}
3456124SN/A#endif
3464218SN/A