Updates for StackwalkerAPI
[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 DebugStepper::DebugStepper(Walker *w) :
49    FrameStepper(w)
50 {
51 #if defined(cap_stackwalker_use_symtab)
52    impl = new DebugStepperImpl(w, this);
53 #else
54    impl = NULL;
55 #endif
56 }
57
58 gcframe_ret_t DebugStepper::getCallerFrame(const Frame &in, Frame &out)
59 {
60    if (!impl)
61       return gcf_not_me;
62    return impl->getCallerFrame(in, out);
63 }
64
65 unsigned DebugStepper::getPriority() const {
66    if (!impl)
67       return 0;
68    return impl->getPriority();
69 }
70
71 void DebugStepper::registerStepperGroup(StepperGroup *group)
72 {
73    if (!impl)
74       return;
75    return impl->registerStepperGroup(group);
76 }
77
78 DebugStepper::~DebugStepper()
79 {
80    if (impl)
81       delete impl;
82 }
83
84 #if defined(cap_stackwalker_use_symtab)
85
86 DebugStepperImpl::DebugStepperImpl(Walker *w, DebugStepper *parent) :
87    FrameStepper(w),
88    parent_stepper(parent),
89    cur_frame(NULL)
90 {
91 }
92
93 bool DebugStepperImpl::ReadMem(Address addr, void *buffer, unsigned size)
94 {
95    return getProcessState()->readMem(buffer, addr, size);
96 }
97
98 bool DebugStepperImpl::GetReg(MachRegister reg, MachRegisterVal &val)
99 {
100    if (isFrameRegister(reg)) {
101       val = static_cast<MachRegisterVal>(cur_frame->getFP());
102       return true;
103    }
104
105    if (isStackRegister(reg)) {
106       val = static_cast<MachRegisterVal>(cur_frame->getSP());
107       return true;
108    }
109    
110    if (reg == MachRegReturn) {
111       val = static_cast<MachRegisterVal>(cur_frame->getRA());
112       return true;
113    }
114
115    return false;
116 }
117
118 gcframe_ret_t DebugStepperImpl::getCallerFrame(const Frame &in, Frame &out)
119 {
120    LibAddrPair lib;
121    bool result;
122
123    result = getProcessState()->getLibraryTracker()->getLibraryAtAddr(in.getRA(), lib);
124    if (!result) {
125       sw_printf("[%s:%u] - Stackwalking through an invalid PC at %lx\n",
126                  __FILE__, __LINE__, in.getRA());
127       return gcf_stackbottom;
128    }
129
130    Symtab *symtab = SymtabWrapper::getSymtab(lib.first);
131    if (!symtab) {
132       sw_printf("[%s:%u] - Could not open file %s with SymtabAPI %s\n",
133                  __FILE__, __LINE__, lib.first.c_str());
134       setLastError(err_nofile, "Could not open file for Debugging stackwalker\n");
135       return gcf_error;
136    }
137    
138    if (!symtab->hasStackwalkDebugInfo())
139    {
140       sw_printf("[%s:%u] - Library %s does not have stackwalking debug info\n",
141                  __FILE__, __LINE__, lib.first.c_str());
142       return gcf_not_me;
143    }
144    
145    Address pc = in.getRA() - lib.second;
146
147    cur_frame = &in;
148    gcframe_ret_t gcresult =  getCallerFrameArch(pc, in, out, symtab);
149    cur_frame = NULL;
150    return gcresult;
151 }
152
153 void DebugStepperImpl::registerStepperGroup(StepperGroup *group)
154 {
155    unsigned addr_width = group->getWalker()->getProcessState()->getAddressWidth();
156    if (addr_width == 4)
157       group->addStepper(parent_stepper, 0, 0xffffffff);
158 #if defined(arch_64bit)
159    else if (addr_width == 8)
160       group->addStepper(parent_stepper, 0, 0xffffffffffffffff);
161 #endif
162    else
163       assert(0 && "Unknown architecture word size");
164 }
165
166 unsigned DebugStepperImpl::getPriority() const
167 {
168    return 0x10010;
169 }
170
171 DebugStepperImpl::~DebugStepperImpl()
172 {
173 }
174
175 #endif
176
177