stacktrace.cc revision 8852
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
518852Sandreas.hansson@arm.com        FSTranslatingPortProxy &vp = tc->getVirtProxy();
525086Sgblack@eecs.umich.edu
535086Sgblack@eecs.umich.edu        if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_size", addr))
545086Sgblack@eecs.umich.edu            panic("thread info not compiled into kernel\n");
558852Sandreas.hansson@arm.com        thread_info_size = vp.readGtoH<int32_t>(addr);
565086Sgblack@eecs.umich.edu
575086Sgblack@eecs.umich.edu        if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_size", addr))
585086Sgblack@eecs.umich.edu            panic("thread info not compiled into kernel\n");
598852Sandreas.hansson@arm.com        task_struct_size = vp.readGtoH<int32_t>(addr);
605086Sgblack@eecs.umich.edu
615086Sgblack@eecs.umich.edu        if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_task", addr))
625086Sgblack@eecs.umich.edu            panic("thread info not compiled into kernel\n");
638852Sandreas.hansson@arm.com        task_off = vp.readGtoH<int32_t>(addr);
645086Sgblack@eecs.umich.edu
655086Sgblack@eecs.umich.edu        if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_pid", addr))
665086Sgblack@eecs.umich.edu            panic("thread info not compiled into kernel\n");
678852Sandreas.hansson@arm.com        pid_off = vp.readGtoH<int32_t>(addr);
685086Sgblack@eecs.umich.edu
695086Sgblack@eecs.umich.edu        if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_comm", addr))
705086Sgblack@eecs.umich.edu            panic("thread info not compiled into kernel\n");
718852Sandreas.hansson@arm.com        name_off = vp.readGtoH<int32_t>(addr);
725086Sgblack@eecs.umich.edu    }
735086Sgblack@eecs.umich.edu
745086Sgblack@eecs.umich.edu    Addr
755086Sgblack@eecs.umich.edu    ProcessInfo::task(Addr ksp) const
765086Sgblack@eecs.umich.edu    {
775086Sgblack@eecs.umich.edu        Addr base = ksp & ~0x3fff;
785086Sgblack@eecs.umich.edu        if (base == ULL(0xfffffc0000000000))
795086Sgblack@eecs.umich.edu            return 0;
805086Sgblack@eecs.umich.edu
815086Sgblack@eecs.umich.edu        Addr tsk;
825086Sgblack@eecs.umich.edu
838852Sandreas.hansson@arm.com        FSTranslatingPortProxy &vp = tc->getVirtProxy();
848852Sandreas.hansson@arm.com        tsk = vp.readGtoH<Addr>(base + task_off);
855086Sgblack@eecs.umich.edu
865086Sgblack@eecs.umich.edu        return tsk;
875086Sgblack@eecs.umich.edu    }
885086Sgblack@eecs.umich.edu
895086Sgblack@eecs.umich.edu    int
905086Sgblack@eecs.umich.edu    ProcessInfo::pid(Addr ksp) const
915086Sgblack@eecs.umich.edu    {
925086Sgblack@eecs.umich.edu        Addr task = this->task(ksp);
935086Sgblack@eecs.umich.edu        if (!task)
945086Sgblack@eecs.umich.edu            return -1;
955086Sgblack@eecs.umich.edu
965086Sgblack@eecs.umich.edu        uint16_t pd;
975086Sgblack@eecs.umich.edu
988852Sandreas.hansson@arm.com        FSTranslatingPortProxy &vp = tc->getVirtProxy();
998852Sandreas.hansson@arm.com        pd = vp.readGtoH<uint16_t>(task + pid_off);
1005086Sgblack@eecs.umich.edu
1015086Sgblack@eecs.umich.edu        return pd;
1025086Sgblack@eecs.umich.edu    }
1035086Sgblack@eecs.umich.edu
1045086Sgblack@eecs.umich.edu    string
1055086Sgblack@eecs.umich.edu    ProcessInfo::name(Addr ksp) const
1065086Sgblack@eecs.umich.edu    {
1075086Sgblack@eecs.umich.edu        Addr task = this->task(ksp);
1085086Sgblack@eecs.umich.edu        if (!task)
1095086Sgblack@eecs.umich.edu            return "console";
1105086Sgblack@eecs.umich.edu
1115086Sgblack@eecs.umich.edu        char comm[256];
1125086Sgblack@eecs.umich.edu        CopyStringOut(tc, comm, task + name_off, sizeof(comm));
1135086Sgblack@eecs.umich.edu        if (!comm[0])
1145086Sgblack@eecs.umich.edu            return "startup";
1155086Sgblack@eecs.umich.edu
1165086Sgblack@eecs.umich.edu        return comm;
1175086Sgblack@eecs.umich.edu    }
1185086Sgblack@eecs.umich.edu
1195086Sgblack@eecs.umich.edu    StackTrace::StackTrace()
1205086Sgblack@eecs.umich.edu        : tc(0), stack(64)
1215086Sgblack@eecs.umich.edu    {
1225086Sgblack@eecs.umich.edu    }
1235086Sgblack@eecs.umich.edu
1245086Sgblack@eecs.umich.edu    StackTrace::StackTrace(ThreadContext *_tc, StaticInstPtr inst)
1255086Sgblack@eecs.umich.edu        : tc(0), stack(64)
1265086Sgblack@eecs.umich.edu    {
1275086Sgblack@eecs.umich.edu        trace(_tc, inst);
1285086Sgblack@eecs.umich.edu    }
1295086Sgblack@eecs.umich.edu
1305086Sgblack@eecs.umich.edu    StackTrace::~StackTrace()
1315086Sgblack@eecs.umich.edu    {
1325086Sgblack@eecs.umich.edu    }
1335086Sgblack@eecs.umich.edu
1345086Sgblack@eecs.umich.edu    void
1355086Sgblack@eecs.umich.edu    StackTrace::trace(ThreadContext *_tc, bool is_call)
1365086Sgblack@eecs.umich.edu    {
1375086Sgblack@eecs.umich.edu    }
1385086Sgblack@eecs.umich.edu
1395086Sgblack@eecs.umich.edu    bool
1405086Sgblack@eecs.umich.edu    StackTrace::isEntry(Addr addr)
1415086Sgblack@eecs.umich.edu    {
1425086Sgblack@eecs.umich.edu        return false;
1435086Sgblack@eecs.umich.edu    }
1445086Sgblack@eecs.umich.edu
1455086Sgblack@eecs.umich.edu    bool
1465086Sgblack@eecs.umich.edu    StackTrace::decodeStack(MachInst inst, int &disp)
1475086Sgblack@eecs.umich.edu    {
1485087Sgblack@eecs.umich.edu        disp = 0;
1495086Sgblack@eecs.umich.edu        return true;
1505086Sgblack@eecs.umich.edu    }
1515086Sgblack@eecs.umich.edu
1525086Sgblack@eecs.umich.edu    bool
1535086Sgblack@eecs.umich.edu    StackTrace::decodeSave(MachInst inst, int &reg, int &disp)
1545086Sgblack@eecs.umich.edu    {
1555087Sgblack@eecs.umich.edu        reg = 0;
1565087Sgblack@eecs.umich.edu        disp = 0;
1575086Sgblack@eecs.umich.edu        return true;
1585086Sgblack@eecs.umich.edu    }
1595086Sgblack@eecs.umich.edu
1605086Sgblack@eecs.umich.edu    /*
1615086Sgblack@eecs.umich.edu     * Decode the function prologue for the function we're in, and note
1625086Sgblack@eecs.umich.edu     * which registers are stored where, and how large the stack frame is.
1635086Sgblack@eecs.umich.edu     */
1645086Sgblack@eecs.umich.edu    bool
1655086Sgblack@eecs.umich.edu    StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func,
1665086Sgblack@eecs.umich.edu                               int &size, Addr &ra)
1675086Sgblack@eecs.umich.edu    {
1685086Sgblack@eecs.umich.edu        size = 0;
1695086Sgblack@eecs.umich.edu        ra = 0;
1705086Sgblack@eecs.umich.edu
1715086Sgblack@eecs.umich.edu        for (Addr pc = func; pc < callpc; pc += sizeof(MachInst)) {
1725086Sgblack@eecs.umich.edu            MachInst inst;
1735086Sgblack@eecs.umich.edu            CopyOut(tc, (uint8_t *)&inst, pc, sizeof(MachInst));
1745086Sgblack@eecs.umich.edu
1755086Sgblack@eecs.umich.edu            int reg, disp;
1765086Sgblack@eecs.umich.edu            if (decodeStack(inst, disp)) {
1775086Sgblack@eecs.umich.edu                if (size) {
1785086Sgblack@eecs.umich.edu                    // panic("decoding frame size again");
1795086Sgblack@eecs.umich.edu                    return true;
1805086Sgblack@eecs.umich.edu                }
1815086Sgblack@eecs.umich.edu                size += disp;
1825086Sgblack@eecs.umich.edu            } else if (decodeSave(inst, reg, disp)) {
1835086Sgblack@eecs.umich.edu                if (!ra && reg == ReturnAddressReg) {
1845086Sgblack@eecs.umich.edu                    CopyOut(tc, (uint8_t *)&ra, sp + disp, sizeof(Addr));
1855086Sgblack@eecs.umich.edu                    if (!ra) {
1865086Sgblack@eecs.umich.edu                        // panic("no return address value pc=%#x\n", pc);
1875086Sgblack@eecs.umich.edu                        return false;
1885086Sgblack@eecs.umich.edu                    }
1895086Sgblack@eecs.umich.edu                }
1905086Sgblack@eecs.umich.edu            }
1915086Sgblack@eecs.umich.edu        }
1925086Sgblack@eecs.umich.edu
1935086Sgblack@eecs.umich.edu        return true;
1945086Sgblack@eecs.umich.edu    }
1955086Sgblack@eecs.umich.edu
1965086Sgblack@eecs.umich.edu#if TRACING_ON
1975086Sgblack@eecs.umich.edu    void
1985086Sgblack@eecs.umich.edu    StackTrace::dump()
1995086Sgblack@eecs.umich.edu    {
2005086Sgblack@eecs.umich.edu        StringWrap name(tc->getCpuPtr()->name());
2015086Sgblack@eecs.umich.edu        SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab;
2025086Sgblack@eecs.umich.edu
2035086Sgblack@eecs.umich.edu        DPRINTFN("------ Stack ------\n");
2045086Sgblack@eecs.umich.edu
2055086Sgblack@eecs.umich.edu        string symbol;
2065086Sgblack@eecs.umich.edu        for (int i = 0, size = stack.size(); i < size; ++i) {
2075086Sgblack@eecs.umich.edu            Addr addr = stack[size - i - 1];
2085086Sgblack@eecs.umich.edu            if (addr == user)
2095086Sgblack@eecs.umich.edu                symbol = "user";
2105086Sgblack@eecs.umich.edu            else if (addr == console)
2115086Sgblack@eecs.umich.edu                symbol = "console";
2125086Sgblack@eecs.umich.edu            else if (addr == unknown)
2135086Sgblack@eecs.umich.edu                symbol = "unknown";
2145086Sgblack@eecs.umich.edu            else
2155086Sgblack@eecs.umich.edu                symtab->findSymbol(addr, symbol);
2165086Sgblack@eecs.umich.edu
2175086Sgblack@eecs.umich.edu            DPRINTFN("%#x: %s\n", addr, symbol);
2185086Sgblack@eecs.umich.edu        }
2195086Sgblack@eecs.umich.edu    }
2205086Sgblack@eecs.umich.edu#endif
2215086Sgblack@eecs.umich.edu}
222