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