Add StackwalkerAPI frame stepper that walks through instrumentation.
[dyninst.git] / stackwalk / src / dbginfo-stepper.C
1 /*
2  * Copyright (c) 1996-2008 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
30  */
31
32 #include "stackwalk/h/framestepper.h"
33 #include "stackwalk/h/frame.h"
34 #include "stackwalk/h/procstate.h"
35 #include "stackwalk/h/swk_errors.h"
36 #include "stackwalk/h/steppergroup.h"
37 #include "stackwalk/h/walker.h"
38 #include "stackwalk/src/symtab-swk.h"
39 #include "stackwalk/src/dbgstepper-impl.h"
40
41 #include "dynutil/h/dyntypes.h"
42
43
44 using namespace Dyninst;
45 using namespace Stackwalker;
46 using namespace SymtabAPI;
47
48 #if defined(cap_stackwalker_use_symtab)
49
50 DebugStepperImpl::DebugStepperImpl(Walker *w, DebugStepper *parent) :
51    FrameStepper(w),
52    parent_stepper(parent),
53    cur_frame(NULL)
54 {
55 }
56
57 bool DebugStepperImpl::ReadMem(Address addr, void *buffer, unsigned size)
58 {
59    return getProcessState()->readMem(buffer, addr, size);
60 }
61
62 bool DebugStepperImpl::GetReg(MachRegister reg, MachRegisterVal &val)
63 {
64    if (isFrameRegister(reg)) {
65       val = static_cast<MachRegisterVal>(cur_frame->getFP());
66       return true;
67    }
68
69    if (isStackRegister(reg)) {
70       val = static_cast<MachRegisterVal>(cur_frame->getSP());
71       return true;
72    }
73    
74    if (reg == MachRegReturn) {
75       val = static_cast<MachRegisterVal>(cur_frame->getRA());
76       return true;
77    }
78
79    return false;
80 }
81
82 gcframe_ret_t DebugStepperImpl::getCallerFrame(const Frame &in, Frame &out)
83 {
84    LibAddrPair lib;
85    bool result;
86
87    result = getProcessState()->getLibraryTracker()->getLibraryAtAddr(in.getRA(), lib);
88    if (!result) {
89       sw_printf("[%s:%u] - Stackwalking through an invalid PC at %lx\n",
90                  __FILE__, __LINE__, in.getRA());
91       return gcf_stackbottom;
92    }
93
94    Symtab *symtab = SymtabWrapper::getSymtab(lib.first);
95    if (!symtab) {
96       sw_printf("[%s:%u] - Could not open file %s with SymtabAPI %s\n",
97                  __FILE__, __LINE__, lib.first.c_str());
98       setLastError(err_nofile, "Could not open file for Debugging stackwalker\n");
99       return gcf_error;
100    }
101    
102    if (!symtab->hasStackwalkDebugInfo())
103    {
104       sw_printf("[%s:%u] - Library %s does not have stackwalking debug info\n",
105                  __FILE__, __LINE__, lib.first.c_str());
106       return gcf_not_me;
107    }
108    
109    Address pc = in.getRA() - lib.second;
110
111    cur_frame = &in;
112    gcframe_ret_t gcresult =  getCallerFrameArch(pc, in, out, symtab);
113    cur_frame = NULL;
114    return gcresult;
115 }
116
117 void DebugStepperImpl::registerStepperGroup(StepperGroup *group)
118 {
119    unsigned addr_width = group->getWalker()->getProcessState()->getAddressWidth();
120    if (addr_width == 4)
121       group->addStepper(parent_stepper, 0, 0xffffffff);
122 #if defined(arch_64bit)
123    else if (addr_width == 8)
124       group->addStepper(parent_stepper, 0, 0xffffffffffffffff);
125 #endif
126    else
127       assert(0 && "Unknown architecture word size");
128 }
129
130 unsigned DebugStepperImpl::getPriority() const
131 {
132    return 0x10010;
133 }
134
135 DebugStepperImpl::~DebugStepperImpl()
136 {
137 }
138
139 #endif
140
141