Initial commit of StackwalkerAPI
[dyninst.git] / stackwalk / src / frame.C
1 /*
2  * Copyright (c) 1996-2007 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
37 #include <assert.h>
38
39 using namespace Dyninst;
40 using namespace Dyninst::Stackwalker;
41
42 Frame::Frame(Walker *parent_walker) :
43   ra(0x0),
44   fp(0x0),
45   sp(0x0),
46   sym_value(NULL),
47   name_val_set(nv_unset),
48   bottom_frame(false),
49   frame_complete(false),
50   stepper(NULL),
51   walker(parent_walker)
52 {
53   assert(walker);
54   ra_loc.location = loc_unknown;
55   ra_loc.val.addr = 0x0;
56   fp_loc.location = loc_unknown;
57   fp_loc.val.addr = 0x0;
58   sp_loc.location = loc_unknown;
59   sp_loc.val.addr = 0x0;
60   
61   sw_printf("[%s:%u] - Created frame at %p\n", __FILE__, __LINE__, this);
62 }
63
64 Frame *Frame::newFrame(regval_t pc, regval_t sp, regval_t fp, Walker *walker) {
65   sw_printf("[%s:%u] - Manually creating frame with %lx, %lx, %lx, %p\n",
66             __FILE__, __LINE__, pc, sp, fp, walker);
67   if (!walker) {
68     sw_printf("[%s:%u] - Trying to create Frame with NULL Walker\n",
69               __FILE__, __LINE__);
70     setLastError(err_badparam, "Walker parameter cannot be NULL when creating frame");
71   }
72   
73   Frame *newframe = new Frame(walker);
74   
75   newframe->setRA(pc);
76   newframe->setSP(sp);
77   newframe->setFP(fp);
78   
79   return newframe;
80 }
81
82 void Frame::setStepper(FrameStepper *newstep) {
83   sw_printf("[%s:%u] - Setting frame %p's stepper to %p\n", 
84             __FILE__, __LINE__, this, newstep);
85   stepper = newstep;
86 }
87
88 void Frame::markBottomFrame() {
89   sw_printf("[%s:%u] - Marking frame %p as bottom\n", 
90             __FILE__, __LINE__, this);
91   bottom_frame = true;
92 }
93
94 regval_t Frame::getRA() const {
95   return ra;
96 }
97
98 regval_t Frame::getSP() const {
99   return sp;
100 }
101
102 regval_t Frame::getFP() const {
103   return fp;
104 }
105
106 location_t Frame::getRALocation() const {
107   return ra_loc;
108 }
109
110 location_t Frame::getSPLocation() const {
111   return sp_loc;
112 }
113
114 location_t Frame::getFPLocation() const {
115   return fp_loc;
116 }
117
118 void Frame::setRA(regval_t newval) {
119   sw_printf("[%s:%u] - Setting ra of frame %p to %x\n",
120             __FILE__, __LINE__, this, newval);
121   ra = newval;
122   frame_complete = true;
123 }
124
125 void Frame::setFP(regval_t newval) {
126   sw_printf("[%s:%u] - Setting fp of frame %p to %x\n",
127                           __FILE__, __LINE__, this, newval);
128   fp = newval;
129 }
130
131 void Frame::setSP(regval_t newval) {
132   sw_printf("[%s:%u] - Setting sp of frame %p to %x\n",
133             __FILE__, __LINE__, this, newval);
134   sp = newval;
135 }
136
137 static void debug_print_location(const char *s, Frame *f, location_t val) {
138   if (val.location == loc_address)
139     sw_printf("[%s:%u] - Setting frame %p %s location to address %lx\n",
140               __FILE__, __LINE__, f, s, val.val.addr);
141   else if (val.location == loc_register)
142     sw_printf("[%s:%u] - Setting frame %p %s location to register %lx\n",
143               __FILE__, __LINE__, f, s, val.val.reg);
144   else if (val.location == loc_unknown)
145     sw_printf("[%s:%u] - Setting frame %p %s location to unknown\n",
146               __FILE__, __LINE__, f, s);
147 }
148
149 void Frame::setRALocation(location_t newval) {
150   if (dyn_debug_stackwalk) {
151     debug_print_location("RA", this, newval);
152   }
153   ra_loc = newval;
154 }
155
156 void Frame::setSPLocation(location_t newval) {
157   if (dyn_debug_stackwalk) {
158     debug_print_location("SP", this, newval);
159   }
160   sp_loc = newval;
161 }
162
163 void Frame::setFPLocation(location_t newval) {
164   if (dyn_debug_stackwalk) {
165     debug_print_location("FP", this, newval);
166   }
167   fp_loc = newval;
168 }
169
170 void Frame::setNameValue() {
171   if (name_val_set == nv_set || name_val_set == nv_err)
172     return;
173   
174   if (!walker) {
175     setLastError(err_nosymlookup, "No Walker object was associated with this frame");
176     sw_printf("[%s:%u] - Error, No walker found.\n", __FILE__, __LINE__);
177     name_val_set = nv_err;
178     return;
179   }
180   
181   SymbolLookup *lookup = walker->getSymbolLookup();
182   if (!lookup) {
183     setLastError(err_nosymlookup, "No SymbolLookup object was associated with the Walker");
184     sw_printf("[%s:%u] - Error, No symbol lookup found.\n", __FILE__, __LINE__);
185     name_val_set = nv_err;
186     return;
187   }
188   
189   bool result = lookup->lookupAtAddr(getRA(), sym_name, sym_value);
190   if (!result) {
191     sw_printf("[%s:%u] - Error, returned by lookupAddr.\n", __FILE__, __LINE__);
192     name_val_set = nv_err;
193   }
194   
195   sw_printf("[%s:%u] - Successfully looked up symbol for frame %p\n",
196             __FILE__, __LINE__, this);
197   
198   name_val_set = nv_set;
199 }
200
201 bool Frame::getName(std::string &str) {
202   setNameValue();
203   if (name_val_set == nv_set) {
204     str = sym_name;
205     sw_printf("[%s:%u] - Frame::getName (frame %p) returning %s\n",
206               __FILE__, __LINE__, this, str.c_str());
207     return true;
208   }
209   else {
210     sw_printf("[%s:%u] - Frame::getName (frame %p) returning error\n",
211               __FILE__, __LINE__, this);
212     return false;
213   }
214 }
215
216 bool Frame::getObject(void* &obj) {
217   setNameValue();
218   if (name_val_set == nv_set) {
219     obj = sym_value;
220     sw_printf("[%s:%u] - Frame::getObject (frame %p) returning %p\n",
221               __FILE__, __LINE__, this, obj);
222     return true;
223   }
224   else {
225     sw_printf("[%s:%u] - Frame::getObject (frame %p) returning error\n",
226               __FILE__, __LINE__, this);
227     return false;
228   }
229 }
230
231 bool Frame::isBottomFrame() const {
232   return bottom_frame;
233 }
234         
235 FrameStepper *Frame::getStepper() const {
236   return stepper;
237 }
238
239 Walker *Frame::getWalker() const {
240   return walker;
241 }
242
243 bool Frame::isFrameComplete() const {
244   return frame_complete;
245 }
246
247 Frame::~Frame() {
248   sw_printf("[%s:%u] - Destroying frame %p\n", __FILE__, __LINE__, this);
249 }
250