stacktrace.cc revision 11793
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
3111793Sbrandon.potter@amd.com#include "arch/x86/stacktrace.hh"
3211793Sbrandon.potter@amd.com
335086Sgblack@eecs.umich.edu#include <string>
345086Sgblack@eecs.umich.edu
355086Sgblack@eecs.umich.edu#include "arch/x86/isa_traits.hh"
365086Sgblack@eecs.umich.edu#include "arch/x86/vtophys.hh"
375086Sgblack@eecs.umich.edu#include "base/bitfield.hh"
385086Sgblack@eecs.umich.edu#include "base/trace.hh"
395086Sgblack@eecs.umich.edu#include "cpu/base.hh"
405086Sgblack@eecs.umich.edu#include "cpu/thread_context.hh"
418706Sandreas.hansson@arm.com#include "mem/fs_translating_port_proxy.hh"
425086Sgblack@eecs.umich.edu#include "sim/system.hh"
435086Sgblack@eecs.umich.edu
445086Sgblack@eecs.umich.eduusing namespace std;
455086Sgblack@eecs.umich.edunamespace X86ISA
465086Sgblack@eecs.umich.edu{
475086Sgblack@eecs.umich.edu    ProcessInfo::ProcessInfo(ThreadContext *_tc)
485086Sgblack@eecs.umich.edu        : tc(_tc)
495086Sgblack@eecs.umich.edu    {
505086Sgblack@eecs.umich.edu        Addr addr = 0;
515086Sgblack@eecs.umich.edu
528852Sandreas.hansson@arm.com        FSTranslatingPortProxy &vp = tc->getVirtProxy();
535086Sgblack@eecs.umich.edu
545086Sgblack@eecs.umich.edu        if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_size", addr))
555086Sgblack@eecs.umich.edu            panic("thread info not compiled into kernel\n");
568852Sandreas.hansson@arm.com        thread_info_size = vp.readGtoH<int32_t>(addr);
575086Sgblack@eecs.umich.edu
585086Sgblack@eecs.umich.edu        if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_size", addr))
595086Sgblack@eecs.umich.edu            panic("thread info not compiled into kernel\n");
608852Sandreas.hansson@arm.com        task_struct_size = vp.readGtoH<int32_t>(addr);
615086Sgblack@eecs.umich.edu
625086Sgblack@eecs.umich.edu        if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_task", addr))
635086Sgblack@eecs.umich.edu            panic("thread info not compiled into kernel\n");
648852Sandreas.hansson@arm.com        task_off = vp.readGtoH<int32_t>(addr);
655086Sgblack@eecs.umich.edu
665086Sgblack@eecs.umich.edu        if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_pid", addr))
675086Sgblack@eecs.umich.edu            panic("thread info not compiled into kernel\n");
688852Sandreas.hansson@arm.com        pid_off = vp.readGtoH<int32_t>(addr);
695086Sgblack@eecs.umich.edu
705086Sgblack@eecs.umich.edu        if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_comm", addr))
715086Sgblack@eecs.umich.edu            panic("thread info not compiled into kernel\n");
728852Sandreas.hansson@arm.com        name_off = vp.readGtoH<int32_t>(addr);
735086Sgblack@eecs.umich.edu    }
745086Sgblack@eecs.umich.edu
755086Sgblack@eecs.umich.edu    Addr
765086Sgblack@eecs.umich.edu    ProcessInfo::task(Addr ksp) const
775086Sgblack@eecs.umich.edu    {
785086Sgblack@eecs.umich.edu        Addr base = ksp & ~0x3fff;
795086Sgblack@eecs.umich.edu        if (base == ULL(0xfffffc0000000000))
805086Sgblack@eecs.umich.edu            return 0;
815086Sgblack@eecs.umich.edu
825086Sgblack@eecs.umich.edu        Addr tsk;
835086Sgblack@eecs.umich.edu
848852Sandreas.hansson@arm.com        FSTranslatingPortProxy &vp = tc->getVirtProxy();
858852Sandreas.hansson@arm.com        tsk = vp.readGtoH<Addr>(base + task_off);
865086Sgblack@eecs.umich.edu
875086Sgblack@eecs.umich.edu        return tsk;
885086Sgblack@eecs.umich.edu    }
895086Sgblack@eecs.umich.edu
905086Sgblack@eecs.umich.edu    int
915086Sgblack@eecs.umich.edu    ProcessInfo::pid(Addr ksp) const
925086Sgblack@eecs.umich.edu    {
935086Sgblack@eecs.umich.edu        Addr task = this->task(ksp);
945086Sgblack@eecs.umich.edu        if (!task)
955086Sgblack@eecs.umich.edu            return -1;
965086Sgblack@eecs.umich.edu
975086Sgblack@eecs.umich.edu        uint16_t pd;
985086Sgblack@eecs.umich.edu
998852Sandreas.hansson@arm.com        FSTranslatingPortProxy &vp = tc->getVirtProxy();
1008852Sandreas.hansson@arm.com        pd = vp.readGtoH<uint16_t>(task + pid_off);
1015086Sgblack@eecs.umich.edu
1025086Sgblack@eecs.umich.edu        return pd;
1035086Sgblack@eecs.umich.edu    }
1045086Sgblack@eecs.umich.edu
1055086Sgblack@eecs.umich.edu    string
1065086Sgblack@eecs.umich.edu    ProcessInfo::name(Addr ksp) const
1075086Sgblack@eecs.umich.edu    {
1085086Sgblack@eecs.umich.edu        Addr task = this->task(ksp);
1095086Sgblack@eecs.umich.edu        if (!task)
1105086Sgblack@eecs.umich.edu            return "console";
1115086Sgblack@eecs.umich.edu
1125086Sgblack@eecs.umich.edu        char comm[256];
1135086Sgblack@eecs.umich.edu        CopyStringOut(tc, comm, task + name_off, sizeof(comm));
1145086Sgblack@eecs.umich.edu        if (!comm[0])
1155086Sgblack@eecs.umich.edu            return "startup";
1165086Sgblack@eecs.umich.edu
1175086Sgblack@eecs.umich.edu        return comm;
1185086Sgblack@eecs.umich.edu    }
1195086Sgblack@eecs.umich.edu
1205086Sgblack@eecs.umich.edu    StackTrace::StackTrace()
1215086Sgblack@eecs.umich.edu        : tc(0), stack(64)
1225086Sgblack@eecs.umich.edu    {
1235086Sgblack@eecs.umich.edu    }
1245086Sgblack@eecs.umich.edu
12510417Sandreas.hansson@arm.com    StackTrace::StackTrace(ThreadContext *_tc, const StaticInstPtr &inst)
1265086Sgblack@eecs.umich.edu        : tc(0), stack(64)
1275086Sgblack@eecs.umich.edu    {
1285086Sgblack@eecs.umich.edu        trace(_tc, inst);
1295086Sgblack@eecs.umich.edu    }
1305086Sgblack@eecs.umich.edu
1315086Sgblack@eecs.umich.edu    StackTrace::~StackTrace()
1325086Sgblack@eecs.umich.edu    {
1335086Sgblack@eecs.umich.edu    }
1345086Sgblack@eecs.umich.edu
1355086Sgblack@eecs.umich.edu    void
1365086Sgblack@eecs.umich.edu    StackTrace::trace(ThreadContext *_tc, bool is_call)
1375086Sgblack@eecs.umich.edu    {
1385086Sgblack@eecs.umich.edu    }
1395086Sgblack@eecs.umich.edu
1405086Sgblack@eecs.umich.edu    bool
1415086Sgblack@eecs.umich.edu    StackTrace::isEntry(Addr addr)
1425086Sgblack@eecs.umich.edu    {
1435086Sgblack@eecs.umich.edu        return false;
1445086Sgblack@eecs.umich.edu    }
1455086Sgblack@eecs.umich.edu
1465086Sgblack@eecs.umich.edu    bool
1475086Sgblack@eecs.umich.edu    StackTrace::decodeStack(MachInst inst, int &disp)
1485086Sgblack@eecs.umich.edu    {
1495087Sgblack@eecs.umich.edu        disp = 0;
1505086Sgblack@eecs.umich.edu        return true;
1515086Sgblack@eecs.umich.edu    }
1525086Sgblack@eecs.umich.edu
1535086Sgblack@eecs.umich.edu    bool
1545086Sgblack@eecs.umich.edu    StackTrace::decodeSave(MachInst inst, int &reg, int &disp)
1555086Sgblack@eecs.umich.edu    {
1565087Sgblack@eecs.umich.edu        reg = 0;
1575087Sgblack@eecs.umich.edu        disp = 0;
1585086Sgblack@eecs.umich.edu        return true;
1595086Sgblack@eecs.umich.edu    }
1605086Sgblack@eecs.umich.edu
1615086Sgblack@eecs.umich.edu    /*
1625086Sgblack@eecs.umich.edu     * Decode the function prologue for the function we're in, and note
1635086Sgblack@eecs.umich.edu     * which registers are stored where, and how large the stack frame is.
1645086Sgblack@eecs.umich.edu     */
1655086Sgblack@eecs.umich.edu    bool
1665086Sgblack@eecs.umich.edu    StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func,
1675086Sgblack@eecs.umich.edu                               int &size, Addr &ra)
1685086Sgblack@eecs.umich.edu    {
1695086Sgblack@eecs.umich.edu        size = 0;
1705086Sgblack@eecs.umich.edu        ra = 0;
1715086Sgblack@eecs.umich.edu
1725086Sgblack@eecs.umich.edu        for (Addr pc = func; pc < callpc; pc += sizeof(MachInst)) {
1735086Sgblack@eecs.umich.edu            MachInst inst;
1745086Sgblack@eecs.umich.edu            CopyOut(tc, (uint8_t *)&inst, pc, sizeof(MachInst));
1755086Sgblack@eecs.umich.edu
1765086Sgblack@eecs.umich.edu            int reg, disp;
1775086Sgblack@eecs.umich.edu            if (decodeStack(inst, disp)) {
1785086Sgblack@eecs.umich.edu                if (size) {
1795086Sgblack@eecs.umich.edu                    // panic("decoding frame size again");
1805086Sgblack@eecs.umich.edu                    return true;
1815086Sgblack@eecs.umich.edu                }
1825086Sgblack@eecs.umich.edu                size += disp;
1835086Sgblack@eecs.umich.edu            } else if (decodeSave(inst, reg, disp)) {
1845086Sgblack@eecs.umich.edu                if (!ra && reg == ReturnAddressReg) {
1855086Sgblack@eecs.umich.edu                    CopyOut(tc, (uint8_t *)&ra, sp + disp, sizeof(Addr));
1865086Sgblack@eecs.umich.edu                    if (!ra) {
1875086Sgblack@eecs.umich.edu                        // panic("no return address value pc=%#x\n", pc);
1885086Sgblack@eecs.umich.edu                        return false;
1895086Sgblack@eecs.umich.edu                    }
1905086Sgblack@eecs.umich.edu                }
1915086Sgblack@eecs.umich.edu            }
1925086Sgblack@eecs.umich.edu        }
1935086Sgblack@eecs.umich.edu
1945086Sgblack@eecs.umich.edu        return true;
1955086Sgblack@eecs.umich.edu    }
1965086Sgblack@eecs.umich.edu
1975086Sgblack@eecs.umich.edu#if TRACING_ON
1985086Sgblack@eecs.umich.edu    void
1995086Sgblack@eecs.umich.edu    StackTrace::dump()
2005086Sgblack@eecs.umich.edu    {
2015086Sgblack@eecs.umich.edu        StringWrap name(tc->getCpuPtr()->name());
2025086Sgblack@eecs.umich.edu        SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab;
2035086Sgblack@eecs.umich.edu
2045086Sgblack@eecs.umich.edu        DPRINTFN("------ Stack ------\n");
2055086Sgblack@eecs.umich.edu
2065086Sgblack@eecs.umich.edu        string symbol;
2075086Sgblack@eecs.umich.edu        for (int i = 0, size = stack.size(); i < size; ++i) {
2085086Sgblack@eecs.umich.edu            Addr addr = stack[size - i - 1];
2095086Sgblack@eecs.umich.edu            if (addr == user)
2105086Sgblack@eecs.umich.edu                symbol = "user";
2115086Sgblack@eecs.umich.edu            else if (addr == console)
2125086Sgblack@eecs.umich.edu                symbol = "console";
2135086Sgblack@eecs.umich.edu            else if (addr == unknown)
2145086Sgblack@eecs.umich.edu                symbol = "unknown";
2155086Sgblack@eecs.umich.edu            else
2165086Sgblack@eecs.umich.edu                symtab->findSymbol(addr, symbol);
2175086Sgblack@eecs.umich.edu
2185086Sgblack@eecs.umich.edu            DPRINTFN("%#x: %s\n", addr, symbol);
2195086Sgblack@eecs.umich.edu        }
2205086Sgblack@eecs.umich.edu    }
2215086Sgblack@eecs.umich.edu#endif
2225086Sgblack@eecs.umich.edu}
223