Update copyright to LGPL on all files
[dyninst.git] / stackwalk / src / frame.C
1 /*
2  * Copyright (c) 1996-2009 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/frame.h"
33 #include "stackwalk/h/walker.h"
34 #include "stackwalk/h/swk_errors.h"
35 #include "stackwalk/h/symlookup.h"
36 #include "stackwalk/h/procstate.h"
37
38 #include "stackwalk/src/symtab-swk.h"
39
40 #include <assert.h>
41
42 using namespace Dyninst;
43 using namespace Dyninst::Stackwalker;
44
45 Frame::Frame(Walker *parent_walker) :
46   ra(0x0),
47   fp(0x0),
48   sp(0x0),
49   sym_value(NULL),
50   name_val_set(nv_unset),
51   bottom_frame(false),
52   frame_complete(false),
53   stepper(NULL),
54   walker(parent_walker),
55   originating_thread(NULL_THR_ID)
56 {
57   assert(walker);
58   ra_loc.location = loc_unknown;
59   ra_loc.val.addr = 0x0;
60   fp_loc.location = loc_unknown;
61   fp_loc.val.addr = 0x0;
62   sp_loc.location = loc_unknown;
63   sp_loc.val.addr = 0x0;
64   
65   sw_printf("[%s:%u] - Created frame at %p\n", __FILE__, __LINE__, this);
66 }
67
68 Frame *Frame::newFrame(Dyninst::MachRegisterVal pc, Dyninst::MachRegisterVal sp, Dyninst::MachRegisterVal fp, Walker *walker) {
69   sw_printf("[%s:%u] - Manually creating frame with %lx, %lx, %lx, %p\n",
70             __FILE__, __LINE__, pc, sp, fp, walker);
71   if (!walker) {
72     sw_printf("[%s:%u] - Trying to create Frame with NULL Walker\n",
73               __FILE__, __LINE__);
74     setLastError(err_badparam, "Walker parameter cannot be NULL when creating frame");
75   }
76   
77   Frame *newframe = new Frame(walker);
78   
79   newframe->setRA(pc);
80   newframe->setSP(sp);
81   newframe->setFP(fp);
82   
83   return newframe;
84 }
85
86 void Frame::setStepper(FrameStepper *newstep) {
87   sw_printf("[%s:%u] - Setting frame %p's stepper to %p\n", 
88             __FILE__, __LINE__, this, newstep);
89   stepper = newstep;
90 }
91
92 void Frame::markBottomFrame() {
93   sw_printf("[%s:%u] - Marking frame %p as bottom\n", 
94             __FILE__, __LINE__, this);
95   bottom_frame = true;
96 }
97
98 Dyninst::MachRegisterVal Frame::getRA() const {
99   return ra;
100 }
101
102 Dyninst::MachRegisterVal Frame::getSP() const {
103   return sp;
104 }
105
106 Dyninst::MachRegisterVal Frame::getFP() const {
107   return fp;
108 }
109
110 location_t Frame::getRALocation() const {
111   return ra_loc;
112 }
113
114 location_t Frame::getSPLocation() const {
115   return sp_loc;
116 }
117
118 location_t Frame::getFPLocation() const {
119   return fp_loc;
120 }
121
122 void Frame::setRA(Dyninst::MachRegisterVal newval) {
123   sw_printf("[%s:%u] - Setting ra of frame %p to %lx\n",
124             __FILE__, __LINE__, this, newval);
125   ra = newval;
126   frame_complete = true;
127 }
128
129 void Frame::setFP(Dyninst::MachRegisterVal newval) {
130   sw_printf("[%s:%u] - Setting fp of frame %p to %lx\n",
131                           __FILE__, __LINE__, this, newval);
132   fp = newval;
133 }
134
135 void Frame::setSP(Dyninst::MachRegisterVal newval) {
136   sw_printf("[%s:%u] - Setting sp of frame %p to %lx\n",
137             __FILE__, __LINE__, this, newval);
138   sp = newval;
139 }
140
141 static void debug_print_location(const char *s, Frame *f, location_t val) {
142   if (val.location == loc_address)
143     sw_printf("[%s:%u] - Setting frame %p %s location to address %lx\n",
144               __FILE__, __LINE__, f, s, val.val.addr);
145   else if (val.location == loc_register)
146     sw_printf("[%s:%u] - Setting frame %p %s location to register %lx\n",
147               __FILE__, __LINE__, f, s, val.val.reg);
148   else if (val.location == loc_unknown)
149     sw_printf("[%s:%u] - Setting frame %p %s location to unknown\n",
150               __FILE__, __LINE__, f, s);
151 }
152
153 void Frame::setRALocation(location_t newval) {
154   if (dyn_debug_stackwalk) {
155     debug_print_location("RA", this, newval);
156   }
157   ra_loc = newval;
158 }
159
160 void Frame::setSPLocation(location_t newval) {
161   if (dyn_debug_stackwalk) {
162     debug_print_location("SP", this, newval);
163   }
164   sp_loc = newval;
165 }
166
167 void Frame::setFPLocation(location_t newval) {
168   if (dyn_debug_stackwalk) {
169     debug_print_location("FP", this, newval);
170   }
171   fp_loc = newval;
172 }
173
174 void Frame::setNameValue() const {
175   if (name_val_set == nv_set || name_val_set == nv_err)
176     return;
177   
178   if (!walker) {
179     setLastError(err_nosymlookup, "No Walker object was associated with this frame");
180     sw_printf("[%s:%u] - Error, No walker found.\n", __FILE__, __LINE__);
181     name_val_set = nv_err;
182     return;
183   }
184   
185   SymbolLookup *lookup = walker->getSymbolLookup();
186   if (!lookup) {
187     setLastError(err_nosymlookup, "No SymbolLookup object was associated with the Walker");
188     sw_printf("[%s:%u] - Error, No symbol lookup found.\n", __FILE__, __LINE__);
189     name_val_set = nv_err;
190     return;
191   }
192   
193   bool result = lookup->lookupAtAddr(getRA(), sym_name, sym_value);
194   if (!result) {
195     sw_printf("[%s:%u] - Error, returned by lookupAtAddr().\n", __FILE__, __LINE__);
196     name_val_set = nv_err;
197   }
198   
199   sw_printf("[%s:%u] - Successfully looked up symbol for frame %p\n",
200             __FILE__, __LINE__, this);
201   
202   name_val_set = nv_set;
203 }
204
205 bool Frame::getName(std::string &str) const {
206   setNameValue();
207   if (name_val_set == nv_set) {
208     str = sym_name;
209     sw_printf("[%s:%u] - Frame::getName (frame %p) returning %s\n",
210               __FILE__, __LINE__, this, str.c_str());
211     return true;
212   }
213   else {
214     sw_printf("[%s:%u] - Frame::getName (frame %p) returning error\n",
215               __FILE__, __LINE__, this);
216     return false;
217   }
218 }
219
220 bool Frame::getObject(void* &obj) const {
221   setNameValue();
222   if (name_val_set == nv_set) {
223     obj = sym_value;
224     sw_printf("[%s:%u] - Frame::getObject (frame %p) returning %p\n",
225               __FILE__, __LINE__, this, obj);
226     return true;
227   }
228   else {
229     sw_printf("[%s:%u] - Frame::getObject (frame %p) returning error\n",
230               __FILE__, __LINE__, this);
231     return false;
232   }
233 }
234
235 bool Frame::isBottomFrame() const {
236   return bottom_frame;
237 }
238         
239 FrameStepper *Frame::getStepper() const {
240   return stepper;
241 }
242
243 Walker *Frame::getWalker() const {
244   return walker;
245 }
246
247 bool Frame::isFrameComplete() const {
248   return frame_complete;
249 }
250
251 Frame::~Frame() {
252   sw_printf("[%s:%u] - Destroying frame %p\n", __FILE__, __LINE__, this);
253 }
254
255 #ifdef cap_stackwalker_use_symtab
256 bool Frame::getLibOffset(std::string &lib, Dyninst::Offset &offset, void*& symtab)
257 #else
258 bool Frame::getLibOffset(std::string &lib, Dyninst::Offset &offset, void*&)
259 #endif
260 {
261   LibraryState *libstate = getWalker()->getProcessState()->getLibraryTracker();
262   if (!libstate) {
263     sw_printf("[%s:%u] - getLibraryAtAddr, had no library tracker\n",
264               __FILE__, __LINE__);
265     setLastError(err_unsupported, "No valid library tracker registered");
266     return false;
267   }
268
269   LibAddrPair la;
270   bool result = libstate->getLibraryAtAddr(getRA(), la);
271   if (!result) {
272     sw_printf("[%s:%u] - getLibraryAtAddr returned false for %x\n",
273               __FILE__, __LINE__, getRA());
274     return false;
275   }
276
277   lib = la.first;
278   offset = getRA() - la.second;
279
280 #if defined(cap_stackwalker_use_symtab)
281   symtab = static_cast<void *>(SymtabWrapper::getSymtab(lib));
282 #endif
283
284   return true;
285 }
286
287 THR_ID Frame::getThread() const
288 {
289    return originating_thread;
290 }
291
292 void Frame::setThread(THR_ID t)
293 {
294    originating_thread = t;
295 }