stacktrace.cc revision 8706
15086Sgblack@eecs.umich.edu/*
25086Sgblack@eecs.umich.edu * Copyright (c) 2005 The Regents of The University of Michigan
35086Sgblack@eecs.umich.edu * All rights reserved.
45086Sgblack@eecs.umich.edu *
55086Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
65086Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
75086Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright
85086Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
95086Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
105086Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
115086Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
125086Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
135086Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
145086Sgblack@eecs.umich.edu * this software without specific prior written permission.
155086Sgblack@eecs.umich.edu *
165086Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
175086Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
185086Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
195086Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
205086Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
215086Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
225086Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
235086Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
245086Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
255086Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
265086Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
275086Sgblack@eecs.umich.edu *
285086Sgblack@eecs.umich.edu * Authors: Nathan Binkert
295086Sgblack@eecs.umich.edu */
305086Sgblack@eecs.umich.edu
315086Sgblack@eecs.umich.edu#include <string>
325086Sgblack@eecs.umich.edu
335086Sgblack@eecs.umich.edu#include "arch/x86/isa_traits.hh"
345086Sgblack@eecs.umich.edu#include "arch/x86/stacktrace.hh"
355086Sgblack@eecs.umich.edu#include "arch/x86/vtophys.hh"
365086Sgblack@eecs.umich.edu#include "base/bitfield.hh"
375086Sgblack@eecs.umich.edu#include "base/trace.hh"
385086Sgblack@eecs.umich.edu#include "cpu/base.hh"
395086Sgblack@eecs.umich.edu#include "cpu/thread_context.hh"
408706Sandreas.hansson@arm.com#include "mem/fs_translating_port_proxy.hh"
415086Sgblack@eecs.umich.edu#include "sim/system.hh"
425086Sgblack@eecs.umich.edu
435086Sgblack@eecs.umich.eduusing namespace std;
445086Sgblack@eecs.umich.edunamespace X86ISA
455086Sgblack@eecs.umich.edu{
465086Sgblack@eecs.umich.edu    ProcessInfo::ProcessInfo(ThreadContext *_tc)
475086Sgblack@eecs.umich.edu        : tc(_tc)
485086Sgblack@eecs.umich.edu    {
495086Sgblack@eecs.umich.edu        Addr addr = 0;
505086Sgblack@eecs.umich.edu
518706Sandreas.hansson@arm.com        FSTranslatingPortProxy* vp;
525086Sgblack@eecs.umich.edu
538706Sandreas.hansson@arm.com        vp = tc->getVirtProxy();
545086Sgblack@eecs.umich.edu
555086Sgblack@eecs.umich.edu        if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_size", addr))
565086Sgblack@eecs.umich.edu            panic("thread info not compiled into kernel\n");
575086Sgblack@eecs.umich.edu        thread_info_size = vp->readGtoH<int32_t>(addr);
585086Sgblack@eecs.umich.edu
595086Sgblack@eecs.umich.edu        if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_size", addr))
605086Sgblack@eecs.umich.edu            panic("thread info not compiled into kernel\n");
615086Sgblack@eecs.umich.edu        task_struct_size = vp->readGtoH<int32_t>(addr);
625086Sgblack@eecs.umich.edu
635086Sgblack@eecs.umich.edu        if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_task", addr))
645086Sgblack@eecs.umich.edu            panic("thread info not compiled into kernel\n");
655086Sgblack@eecs.umich.edu        task_off = vp->readGtoH<int32_t>(addr);
665086Sgblack@eecs.umich.edu
675086Sgblack@eecs.umich.edu        if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_pid", addr))
685086Sgblack@eecs.umich.edu            panic("thread info not compiled into kernel\n");
695086Sgblack@eecs.umich.edu        pid_off = vp->readGtoH<int32_t>(addr);
705086Sgblack@eecs.umich.edu
715086Sgblack@eecs.umich.edu        if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_comm", addr))
725086Sgblack@eecs.umich.edu            panic("thread info not compiled into kernel\n");
735086Sgblack@eecs.umich.edu        name_off = vp->readGtoH<int32_t>(addr);
745086Sgblack@eecs.umich.edu    }
755086Sgblack@eecs.umich.edu
765086Sgblack@eecs.umich.edu    Addr
775086Sgblack@eecs.umich.edu    ProcessInfo::task(Addr ksp) const
785086Sgblack@eecs.umich.edu    {
795086Sgblack@eecs.umich.edu        Addr base = ksp & ~0x3fff;
805086Sgblack@eecs.umich.edu        if (base == ULL(0xfffffc0000000000))
815086Sgblack@eecs.umich.edu            return 0;
825086Sgblack@eecs.umich.edu
835086Sgblack@eecs.umich.edu        Addr tsk;
845086Sgblack@eecs.umich.edu
858706Sandreas.hansson@arm.com        FSTranslatingPortProxy* vp;
865086Sgblack@eecs.umich.edu
878706Sandreas.hansson@arm.com        vp = tc->getVirtProxy();
885086Sgblack@eecs.umich.edu        tsk = vp->readGtoH<Addr>(base + task_off);
895086Sgblack@eecs.umich.edu
905086Sgblack@eecs.umich.edu        return tsk;
915086Sgblack@eecs.umich.edu    }
925086Sgblack@eecs.umich.edu
935086Sgblack@eecs.umich.edu    int
945086Sgblack@eecs.umich.edu    ProcessInfo::pid(Addr ksp) const
955086Sgblack@eecs.umich.edu    {
965086Sgblack@eecs.umich.edu        Addr task = this->task(ksp);
975086Sgblack@eecs.umich.edu        if (!task)
985086Sgblack@eecs.umich.edu            return -1;
995086Sgblack@eecs.umich.edu
1005086Sgblack@eecs.umich.edu        uint16_t pd;
1015086Sgblack@eecs.umich.edu
1028706Sandreas.hansson@arm.com        FSTranslatingPortProxy* vp;
1035086Sgblack@eecs.umich.edu
1048706Sandreas.hansson@arm.com        vp = tc->getVirtProxy();
1055086Sgblack@eecs.umich.edu        pd = vp->readGtoH<uint16_t>(task + pid_off);
1065086Sgblack@eecs.umich.edu
1075086Sgblack@eecs.umich.edu        return pd;
1085086Sgblack@eecs.umich.edu    }
1095086Sgblack@eecs.umich.edu
1105086Sgblack@eecs.umich.edu    string
1115086Sgblack@eecs.umich.edu    ProcessInfo::name(Addr ksp) const
1125086Sgblack@eecs.umich.edu    {
1135086Sgblack@eecs.umich.edu        Addr task = this->task(ksp);
1145086Sgblack@eecs.umich.edu        if (!task)
1155086Sgblack@eecs.umich.edu            return "console";
1165086Sgblack@eecs.umich.edu
1175086Sgblack@eecs.umich.edu        char comm[256];
1185086Sgblack@eecs.umich.edu        CopyStringOut(tc, comm, task + name_off, sizeof(comm));
1195086Sgblack@eecs.umich.edu        if (!comm[0])
1205086Sgblack@eecs.umich.edu            return "startup";
1215086Sgblack@eecs.umich.edu
1225086Sgblack@eecs.umich.edu        return comm;
1235086Sgblack@eecs.umich.edu    }
1245086Sgblack@eecs.umich.edu
1255086Sgblack@eecs.umich.edu    StackTrace::StackTrace()
1265086Sgblack@eecs.umich.edu        : tc(0), stack(64)
1275086Sgblack@eecs.umich.edu    {
1285086Sgblack@eecs.umich.edu    }
1295086Sgblack@eecs.umich.edu
1305086Sgblack@eecs.umich.edu    StackTrace::StackTrace(ThreadContext *_tc, StaticInstPtr inst)
1315086Sgblack@eecs.umich.edu        : tc(0), stack(64)
1325086Sgblack@eecs.umich.edu    {
1335086Sgblack@eecs.umich.edu        trace(_tc, inst);
1345086Sgblack@eecs.umich.edu    }
1355086Sgblack@eecs.umich.edu
1365086Sgblack@eecs.umich.edu    StackTrace::~StackTrace()
1375086Sgblack@eecs.umich.edu    {
1385086Sgblack@eecs.umich.edu    }
1395086Sgblack@eecs.umich.edu
1405086Sgblack@eecs.umich.edu    void
1415086Sgblack@eecs.umich.edu    StackTrace::trace(ThreadContext *_tc, bool is_call)
1425086Sgblack@eecs.umich.edu    {
1435086Sgblack@eecs.umich.edu    }
1445086Sgblack@eecs.umich.edu
1455086Sgblack@eecs.umich.edu    bool
1465086Sgblack@eecs.umich.edu    StackTrace::isEntry(Addr addr)
1475086Sgblack@eecs.umich.edu    {
1485086Sgblack@eecs.umich.edu        return false;
1495086Sgblack@eecs.umich.edu    }
1505086Sgblack@eecs.umich.edu
1515086Sgblack@eecs.umich.edu    bool
1525086Sgblack@eecs.umich.edu    StackTrace::decodeStack(MachInst inst, int &disp)
1535086Sgblack@eecs.umich.edu    {
1545087Sgblack@eecs.umich.edu        disp = 0;
1555086Sgblack@eecs.umich.edu        return true;
1565086Sgblack@eecs.umich.edu    }
1575086Sgblack@eecs.umich.edu
1585086Sgblack@eecs.umich.edu    bool
1595086Sgblack@eecs.umich.edu    StackTrace::decodeSave(MachInst inst, int &reg, int &disp)
1605086Sgblack@eecs.umich.edu    {
1615087Sgblack@eecs.umich.edu        reg = 0;
1625087Sgblack@eecs.umich.edu        disp = 0;
1635086Sgblack@eecs.umich.edu        return true;
1645086Sgblack@eecs.umich.edu    }
1655086Sgblack@eecs.umich.edu
1665086Sgblack@eecs.umich.edu    /*
1675086Sgblack@eecs.umich.edu     * Decode the function prologue for the function we're in, and note
1685086Sgblack@eecs.umich.edu     * which registers are stored where, and how large the stack frame is.
1695086Sgblack@eecs.umich.edu     */
1705086Sgblack@eecs.umich.edu    bool
1715086Sgblack@eecs.umich.edu    StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func,
1725086Sgblack@eecs.umich.edu                               int &size, Addr &ra)
1735086Sgblack@eecs.umich.edu    {
1745086Sgblack@eecs.umich.edu        size = 0;
1755086Sgblack@eecs.umich.edu        ra = 0;
1765086Sgblack@eecs.umich.edu
1775086Sgblack@eecs.umich.edu        for (Addr pc = func; pc < callpc; pc += sizeof(MachInst)) {
1785086Sgblack@eecs.umich.edu            MachInst inst;
1795086Sgblack@eecs.umich.edu            CopyOut(tc, (uint8_t *)&inst, pc, sizeof(MachInst));
1805086Sgblack@eecs.umich.edu
1815086Sgblack@eecs.umich.edu            int reg, disp;
1825086Sgblack@eecs.umich.edu            if (decodeStack(inst, disp)) {
1835086Sgblack@eecs.umich.edu                if (size) {
1845086Sgblack@eecs.umich.edu                    // panic("decoding frame size again");
1855086Sgblack@eecs.umich.edu                    return true;
1865086Sgblack@eecs.umich.edu                }
1875086Sgblack@eecs.umich.edu                size += disp;
1885086Sgblack@eecs.umich.edu            } else if (decodeSave(inst, reg, disp)) {
1895086Sgblack@eecs.umich.edu                if (!ra && reg == ReturnAddressReg) {
1905086Sgblack@eecs.umich.edu                    CopyOut(tc, (uint8_t *)&ra, sp + disp, sizeof(Addr));
1915086Sgblack@eecs.umich.edu                    if (!ra) {
1925086Sgblack@eecs.umich.edu                        // panic("no return address value pc=%#x\n", pc);
1935086Sgblack@eecs.umich.edu                        return false;
1945086Sgblack@eecs.umich.edu                    }
1955086Sgblack@eecs.umich.edu                }
1965086Sgblack@eecs.umich.edu            }
1975086Sgblack@eecs.umich.edu        }
1985086Sgblack@eecs.umich.edu
1995086Sgblack@eecs.umich.edu        return true;
2005086Sgblack@eecs.umich.edu    }
2015086Sgblack@eecs.umich.edu
2025086Sgblack@eecs.umich.edu#if TRACING_ON
2035086Sgblack@eecs.umich.edu    void
2045086Sgblack@eecs.umich.edu    StackTrace::dump()
2055086Sgblack@eecs.umich.edu    {
2065086Sgblack@eecs.umich.edu        StringWrap name(tc->getCpuPtr()->name());
2075086Sgblack@eecs.umich.edu        SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab;
2085086Sgblack@eecs.umich.edu
2095086Sgblack@eecs.umich.edu        DPRINTFN("------ Stack ------\n");
2105086Sgblack@eecs.umich.edu
2115086Sgblack@eecs.umich.edu        string symbol;
2125086Sgblack@eecs.umich.edu        for (int i = 0, size = stack.size(); i < size; ++i) {
2135086Sgblack@eecs.umich.edu            Addr addr = stack[size - i - 1];
2145086Sgblack@eecs.umich.edu            if (addr == user)
2155086Sgblack@eecs.umich.edu                symbol = "user";
2165086Sgblack@eecs.umich.edu            else if (addr == console)
2175086Sgblack@eecs.umich.edu                symbol = "console";
2185086Sgblack@eecs.umich.edu            else if (addr == unknown)
2195086Sgblack@eecs.umich.edu                symbol = "unknown";
2205086Sgblack@eecs.umich.edu            else
2215086Sgblack@eecs.umich.edu                symtab->findSymbol(addr, symbol);
2225086Sgblack@eecs.umich.edu
2235086Sgblack@eecs.umich.edu            DPRINTFN("%#x: %s\n", addr, symbol);
2245086Sgblack@eecs.umich.edu        }
2255086Sgblack@eecs.umich.edu    }
2265086Sgblack@eecs.umich.edu#endif
2275086Sgblack@eecs.umich.edu}
228