stacktrace.cc revision 5567:8fc3b004b0df
11689SN/A/*
21689SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan
31689SN/A * All rights reserved.
41689SN/A *
51689SN/A * Redistribution and use in source and binary forms, with or without
61689SN/A * modification, are permitted provided that the following conditions are
71689SN/A * met: redistributions of source code must retain the above copyright
81689SN/A * notice, this list of conditions and the following disclaimer;
91689SN/A * redistributions in binary form must reproduce the above copyright
101689SN/A * notice, this list of conditions and the following disclaimer in the
111689SN/A * documentation and/or other materials provided with the distribution;
121689SN/A * neither the name of the copyright holders nor the names of its
131689SN/A * contributors may be used to endorse or promote products derived from
141689SN/A * this software without specific prior written permission.
151689SN/A *
161689SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
171689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
181689SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
191689SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
201689SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
211689SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
221689SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
231689SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
241689SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
251689SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
261689SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665Ssaidi@eecs.umich.edu *
282665Ssaidi@eecs.umich.edu * Authors: Nathan Binkert
291689SN/A */
301689SN/A
311061SN/A#include <string>
321060SN/A
331060SN/A#include "arch/mips/isa_traits.hh"
341060SN/A#include "arch/mips/stacktrace.hh"
351060SN/A#include "arch/mips/vtophys.hh"
361060SN/A#include "base/bitfield.hh"
371060SN/A#include "base/trace.hh"
381060SN/A#include "cpu/base.hh"
391060SN/A#include "cpu/thread_context.hh"
401060SN/A#include "sim/system.hh"
411060SN/A
421060SN/Ausing namespace std;
431060SN/Ausing namespace MipsISA;
441060SN/A
451755SN/AProcessInfo::ProcessInfo(ThreadContext *_tc)
461755SN/A    : tc(_tc)
471060SN/A{
481461SN/A//     Addr addr = 0;
491060SN/A
501060SN/A    VirtualPort *vp;
511060SN/A
521060SN/A    vp = tc->getVirtPort();
531060SN/A
541060SN/A//     if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_size", addr))
551060SN/A//         panic("thread info not compiled into kernel\n");
561060SN/A//     thread_info_size = vp->readGtoH<int32_t>(addr);
571060SN/A
581061SN/A//     if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_size", addr))
591060SN/A//         panic("thread info not compiled into kernel\n");
601061SN/A//     task_struct_size = vp->readGtoH<int32_t>(addr);
611060SN/A
621061SN/A//     if (!tc->getSystemPtr()->kernelSymtab->findAddress("thread_info_task", addr))
631060SN/A//         panic("thread info not compiled into kernel\n");
641061SN/A//     task_off = vp->readGtoH<int32_t>(addr);
651061SN/A
661061SN/A//     if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_pid", addr))
671060SN/A//         panic("thread info not compiled into kernel\n");
681060SN/A//     pid_off = vp->readGtoH<int32_t>(addr);
691060SN/A
701060SN/A//     if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_comm", addr))
711060SN/A//         panic("thread info not compiled into kernel\n");
721060SN/A//     name_off = vp->readGtoH<int32_t>(addr);
731060SN/A}
741060SN/A
751060SN/AAddr
761060SN/AProcessInfo::task(Addr ksp) const
771060SN/A{
781060SN/A    Addr base = ksp & ~0x3fff;
791060SN/A    if (base == ULL(0xfffffc0000000000))
801060SN/A        return 0;
811060SN/A
821060SN/A    Addr tsk;
831060SN/A
841060SN/A    VirtualPort *vp;
851060SN/A
861060SN/A    vp = tc->getVirtPort();
871060SN/A    tsk = vp->readGtoH<Addr>(base + task_off);
881062SN/A
891062SN/A    return tsk;
901060SN/A}
911060SN/A
921060SN/Aint
931060SN/AProcessInfo::pid(Addr ksp) const
941060SN/A{
951060SN/A    Addr task = this->task(ksp);
961060SN/A    if (!task)
971060SN/A        return -1;
981060SN/A
991060SN/A    uint16_t pd;
1001060SN/A
1011060SN/A    VirtualPort *vp;
1021060SN/A
1031060SN/A    vp = tc->getVirtPort();
1041060SN/A    pd = vp->readGtoH<uint16_t>(task + pid_off);
1051060SN/A
1061060SN/A    return pd;
1071060SN/A}
1081061SN/A
1091060SN/Astring
1101060SN/AProcessInfo::name(Addr ksp) const
1111060SN/A{
1121060SN/A    Addr task = this->task(ksp);
1131060SN/A    if (!task)
1141684SN/A        return "console";
1151684SN/A
1161684SN/A    char comm[256];
1171684SN/A    CopyStringOut(tc, comm, task + name_off, sizeof(comm));
1181684SN/A    if (!comm[0])
1191684SN/A        return "startup";
1201060SN/A
1211060SN/A    return comm;
1221060SN/A}
1231060SN/A
1241060SN/AStackTrace::StackTrace()
1251060SN/A    : tc(0), stack(64)
1261060SN/A{
1271060SN/A}
1281060SN/A
1291060SN/AStackTrace::StackTrace(ThreadContext *_tc, StaticInstPtr inst)
1301060SN/A    : tc(0), stack(64)
1311060SN/A{
1321060SN/A    trace(_tc, inst);
1331060SN/A}
1341060SN/A
1351060SN/AStackTrace::~StackTrace()
1361060SN/A{
1371060SN/A}
1381060SN/A
1391060SN/Avoid
1401060SN/AStackTrace::trace(ThreadContext *_tc, bool is_call)
1411060SN/A{
1421060SN/A    tc = _tc;
1431060SN/A    /* FIXME - Jaidev - What is IPR_DTB_CM in Alpha? */
1441060SN/A    bool usermode = 0;
1451060SN/A      //(tc->readMiscReg(MipsISA::IPR_DTB_CM) & 0x18) != 0;
1461060SN/A
1471060SN/A//     Addr pc = tc->readNextPC();
1481060SN/A//     bool kernel = tc->getSystemPtr()->kernelStart <= pc &&
1491060SN/A//         pc <= tc->getSystemPtr()->kernelEnd;
1501060SN/A
1511060SN/A    if (usermode) {
1521060SN/A        stack.push_back(user);
1531060SN/A        return;
1541060SN/A    }
1551060SN/A
1561060SN/A//     if (!kernel) {
1571060SN/A//         stack.push_back(console);
1581060SN/A//         return;
1591060SN/A//     }
1601060SN/A
1611060SN/A//     SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab;
1621060SN/A//     Addr ksp = tc->readIntReg(MipsISA::StackPointerReg);
1631060SN/A//     Addr bottom = ksp & ~0x3fff;
1641060SN/A//     Addr addr;
1651060SN/A
1661060SN/A//     if (is_call) {
1671060SN/A//         if (!symtab->findNearestAddr(pc, addr))
1681060SN/A//             panic("could not find address %#x", pc);
1691062SN/A
1701062SN/A//         stack.push_back(addr);
1711062SN/A//         pc = tc->readPC();
1721062SN/A//     }
1731062SN/A
1741062SN/A//     Addr ra;
1751062SN/A//     int size;
1761062SN/A
1771062SN/A//     while (ksp > bottom) {
1781062SN/A//         if (!symtab->findNearestAddr(pc, addr))
1791062SN/A//             panic("could not find symbol for pc=%#x", pc);
1801060SN/A//         assert(pc >= addr && "symbol botch: callpc < func");
1811060SN/A
1821755SN/A//         stack.push_back(addr);
183
184//         if (isEntry(addr))
185//             return;
186
187//         if (decodePrologue(ksp, pc, addr, size, ra)) {
188//             if (!ra)
189//                 return;
190
191//             if (size <= 0) {
192//                 stack.push_back(unknown);
193//                 return;
194//             }
195
196//             pc = ra;
197//             ksp += size;
198//         } else {
199//             stack.push_back(unknown);
200//             return;
201//         }
202
203//         bool kernel = tc->getSystemPtr()->kernelStart <= pc &&
204//             pc <= tc->getSystemPtr()->kernelEnd;
205//         if (!kernel)
206//             return;
207
208//         if (stack.size() >= 1000)
209//             panic("unwinding too far");
210//     }
211
212//     panic("unwinding too far");
213}
214
215bool
216StackTrace::isEntry(Addr addr)
217{
218  /*    if (addr == tc->readMiscReg(MipsISA::IPR_PALtemp2))
219        return true;*/
220
221    return false;
222}
223
224bool
225StackTrace::decodeStack(MachInst inst, int &disp)
226{
227    // lda $sp, -disp($sp)
228    //
229    // Opcode<31:26> == 0x08
230    // RA<25:21> == 30
231    // RB<20:16> == 30
232    // Disp<15:0>
233    const MachInst mem_mask = 0xffff0000;
234    const MachInst lda_pattern = 0x23de0000;
235    const MachInst lda_disp_mask = 0x0000ffff;
236
237    // subq $sp, disp, $sp
238    // addq $sp, disp, $sp
239    //
240    // Opcode<31:26> == 0x10
241    // RA<25:21> == 30
242    // Lit<20:13>
243    // One<12> = 1
244    // Func<11:5> == 0x20 (addq)
245    // Func<11:5> == 0x29 (subq)
246    // RC<4:0> == 30
247    const MachInst intop_mask = 0xffe01fff;
248    const MachInst addq_pattern = 0x43c0141e;
249    const MachInst subq_pattern = 0x43c0153e;
250    const MachInst intop_disp_mask = 0x001fe000;
251    const int intop_disp_shift = 13;
252
253    if ((inst & mem_mask) == lda_pattern)
254        disp = -sext<16>(inst & lda_disp_mask);
255    else if ((inst & intop_mask) == addq_pattern)
256        disp = -int((inst & intop_disp_mask) >> intop_disp_shift);
257    else if ((inst & intop_mask) == subq_pattern)
258        disp = int((inst & intop_disp_mask) >> intop_disp_shift);
259    else
260        return false;
261
262    return true;
263}
264
265bool
266StackTrace::decodeSave(MachInst inst, int &reg, int &disp)
267{
268    // lda $stq, disp($sp)
269    //
270    // Opcode<31:26> == 0x08
271    // RA<25:21> == ?
272    // RB<20:16> == 30
273    // Disp<15:0>
274    const MachInst stq_mask = 0xfc1f0000;
275    const MachInst stq_pattern = 0xb41e0000;
276    const MachInst stq_disp_mask = 0x0000ffff;
277    const MachInst reg_mask = 0x03e00000;
278    const int reg_shift = 21;
279
280    if ((inst & stq_mask) == stq_pattern) {
281        reg = (inst & reg_mask) >> reg_shift;
282        disp = sext<16>(inst & stq_disp_mask);
283    } else {
284        return false;
285    }
286
287    return true;
288}
289
290/*
291 * Decode the function prologue for the function we're in, and note
292 * which registers are stored where, and how large the stack frame is.
293 */
294bool
295StackTrace::decodePrologue(Addr sp, Addr callpc, Addr func,
296                           int &size, Addr &ra)
297{
298    size = 0;
299    ra = 0;
300
301    for (Addr pc = func; pc < callpc; pc += sizeof(MachInst)) {
302        MachInst inst;
303        CopyOut(tc, (uint8_t *)&inst, pc, sizeof(MachInst));
304
305        int reg, disp;
306        if (decodeStack(inst, disp)) {
307            if (size) {
308                // panic("decoding frame size again");
309                return true;
310            }
311            size += disp;
312        } else if (decodeSave(inst, reg, disp)) {
313            if (!ra && reg == ReturnAddressReg) {
314                CopyOut(tc, (uint8_t *)&ra, sp + disp, sizeof(Addr));
315                if (!ra) {
316                    // panic("no return address value pc=%#x\n", pc);
317                    return false;
318                }
319            }
320        }
321    }
322
323    return true;
324}
325
326#if TRACING_ON
327void
328StackTrace::dump()
329{
330    StringWrap name(tc->getCpuPtr()->name());
331//     SymbolTable *symtab = tc->getSystemPtr()->kernelSymtab;
332
333    DPRINTFN("------ Stack ------\n");
334
335//     string symbol;
336//     for (int i = 0, size = stack.size(); i < size; ++i) {
337//         Addr addr = stack[size - i - 1];
338//         if (addr == user)
339//             symbol = "user";
340//         else if (addr == console)
341//             symbol = "console";
342//         else if (addr == unknown)
343//             symbol = "unknown";
344//         else
345//             symtab->findSymbol(addr, symbol);
346
347//         DPRINTFN("%#x: %s\n", addr, symbol);
348//     }
349}
350#endif
351