GCC 4.8 build fixes: ensure all extern template declarations are in fact extern'ed...
[dyninst.git] / stackwalk / src / frame.C
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  * 
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  * 
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  * 
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  * 
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  * 
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30
31 #include "stackwalk/h/frame.h"
32 #include "stackwalk/h/walker.h"
33 #include "stackwalk/h/swk_errors.h"
34 #include "stackwalk/h/symlookup.h"
35 #include "stackwalk/h/procstate.h"
36
37 #include "stackwalk/src/symtab-swk.h"
38
39 #include <assert.h>
40 #include <string>
41
42 using namespace std;
43 using namespace Dyninst;
44 using namespace Dyninst::Stackwalker;
45
46 Frame::Frame() :
47   ra(0x0),
48   fp(0x0),
49   sp(0x0),
50   sym_value(NULL),
51   name_val_set(nv_unset),
52   top_frame(false),
53   bottom_frame(false),
54   frame_complete(false),
55   non_call_frame(false),
56   prev_frame(NULL),
57   stepper(NULL),
58   next_stepper(NULL),
59   walker(NULL),
60   originating_thread(NULL_THR_ID)
61 {
62   ra_loc.location = loc_unknown;
63   ra_loc.val.addr = 0x0;
64   fp_loc.location = loc_unknown;
65   fp_loc.val.addr = 0x0;
66   sp_loc.location = loc_unknown;
67   sp_loc.val.addr = 0x0;
68   
69   sw_printf("[%s:%u] - Created null frame at %p\n", FILE__, __LINE__, this);
70 }
71
72 Frame::Frame(Walker *parent_walker) :
73   ra(0x0),
74   fp(0x0),
75   sp(0x0),
76   sym_value(NULL),
77   name_val_set(nv_unset),
78   top_frame(false),
79   bottom_frame(false),
80   frame_complete(false),
81   non_call_frame(false),
82   prev_frame(NULL),
83   stepper(NULL),
84   next_stepper(NULL),
85   walker(parent_walker),
86   originating_thread(NULL_THR_ID)
87 {
88   assert(walker);
89   ra_loc.location = loc_unknown;
90   ra_loc.val.addr = 0x0;
91   fp_loc.location = loc_unknown;
92   fp_loc.val.addr = 0x0;
93   sp_loc.location = loc_unknown;
94   sp_loc.val.addr = 0x0;
95   
96   sw_printf("[%s:%u] - Created frame at %p\n", FILE__, __LINE__, this);
97 }
98
99 Frame *Frame::newFrame(Dyninst::MachRegisterVal pc, Dyninst::MachRegisterVal sp, Dyninst::MachRegisterVal fp, Walker *walker) {
100   sw_printf("[%s:%u] - Manually creating frame with %lx, %lx, %lx, %p\n",
101             FILE__, __LINE__, pc, sp, fp, walker);
102   if (!walker) {
103     sw_printf("[%s:%u] - Trying to create Frame with NULL Walker\n",
104               FILE__, __LINE__);
105     setLastError(err_badparam, "Walker parameter cannot be NULL when creating frame");
106   }
107   
108   Frame *newframe = new Frame(walker);
109   
110   newframe->setRA(pc);
111   newframe->setSP(sp);
112   newframe->setFP(fp);
113   
114   return newframe;
115 }
116
117 bool Frame::operator==(const Frame &F) const
118 {
119   return ((ra == F.ra) &&
120           (fp == F.fp) &&
121           (sp == F.sp) &&
122           (ra_loc == F.ra_loc) &&
123           (fp_loc == F.fp_loc) &&
124           (sp_loc == F.sp_loc) &&
125           (sym_name == F.sym_name) &&
126           (frame_complete == F.frame_complete) &&
127           (stepper == F.stepper) &&
128           (walker == F.walker) &&
129           (originating_thread == F.originating_thread));
130 }
131
132 void Frame::setStepper(FrameStepper *newstep) {
133   sw_printf("[%s:%u] - Setting frame %p's stepper to %p\n", 
134             FILE__, __LINE__, this, newstep);
135   stepper = newstep;
136 }
137
138 void Frame::markTopFrame() {
139   sw_printf("[%s:%u] - Marking frame %p as top\n",
140             FILE__, __LINE__, this);
141   top_frame = true;
142 }
143
144 void Frame::markBottomFrame() {
145   sw_printf("[%s:%u] - Marking frame %p as bottom\n", 
146             FILE__, __LINE__, this);
147   bottom_frame = true;
148 }
149
150 Dyninst::MachRegisterVal Frame::getRA() const {
151   return ra;
152 }
153
154 Dyninst::MachRegisterVal Frame::getSP() const {
155   return sp;
156 }
157
158 Dyninst::MachRegisterVal Frame::getFP() const {
159   return fp;
160 }
161
162 location_t Frame::getRALocation() const {
163   return ra_loc;
164 }
165
166 location_t Frame::getSPLocation() const {
167   return sp_loc;
168 }
169
170 location_t Frame::getFPLocation() const {
171   return fp_loc;
172 }
173
174 void Frame::setRA(Dyninst::MachRegisterVal newval) {
175   sw_printf("[%s:%u] - Setting ra of frame %p to %lx\n",
176             FILE__, __LINE__, this, newval);
177   ra = newval;
178   frame_complete = true;
179 }
180
181 void Frame::setFP(Dyninst::MachRegisterVal newval) {
182   sw_printf("[%s:%u] - Setting fp of frame %p to %lx\n",
183                           FILE__, __LINE__, this, newval);
184   fp = newval;
185 }
186
187 void Frame::setSP(Dyninst::MachRegisterVal newval) {
188   sw_printf("[%s:%u] - Setting sp of frame %p to %lx\n",
189             FILE__, __LINE__, this, newval);
190   sp = newval;
191 }
192
193 static void debug_print_location(const char *s, Frame *f, location_t val) {
194   if (val.location == loc_address)
195     sw_printf("[%s:%u] - Setting frame %p %s location to address %lx\n",
196               FILE__, __LINE__, f, s, val.val.addr);
197   else if (val.location == loc_register)
198     sw_printf("[%s:%u] - Setting frame %p %s location to register %s\n",
199               FILE__, __LINE__, f, s, val.val.reg.name().c_str());
200   else if (val.location == loc_unknown)
201      sw_printf("[%s:%u] - Setting frame %p %s location to unknown\n",
202                FILE__, __LINE__, f, s);
203 }
204
205 void Frame::setRALocation(location_t newval) {
206   if (dyn_debug_stackwalk) {
207     debug_print_location("RA", this, newval);
208   }
209   ra_loc = newval;
210 }
211
212 void Frame::setSPLocation(location_t newval) {
213   if (dyn_debug_stackwalk) {
214     debug_print_location("SP", this, newval);
215   }
216   sp_loc = newval;
217 }
218
219 void Frame::setFPLocation(location_t newval) {
220   if (dyn_debug_stackwalk) {
221     debug_print_location("FP", this, newval);
222   }
223   fp_loc = newval;
224 }
225
226 void Frame::setNameValue() const {
227   if (name_val_set == nv_set || name_val_set == nv_err)
228     return;
229   
230   if (!walker) {
231     setLastError(err_nosymlookup, "No Walker object was associated with this frame");
232     sw_printf("[%s:%u] - Error, No walker found.\n", FILE__, __LINE__);
233     name_val_set = nv_err;
234     return;
235   }
236   
237   SymbolLookup *lookup = walker->getSymbolLookup();
238   if (!lookup) {
239     setLastError(err_nosymlookup, "No SymbolLookup object was associated with the Walker");
240     sw_printf("[%s:%u] - Error, No symbol lookup found.\n", FILE__, __LINE__);
241     name_val_set = nv_err;
242     return;
243   }
244   
245   bool result = lookup->lookupAtAddr(getRA(), sym_name, sym_value);
246   if (!result) {
247     sw_printf("[%s:%u] - Error, returned by lookupAtAddr().\n", FILE__, __LINE__);
248     name_val_set = nv_err;
249   }
250   
251   sw_printf("[%s:%u] - Successfully looked up symbol for frame %p\n",
252             FILE__, __LINE__, this);
253   
254   name_val_set = nv_set;
255 }
256
257 bool Frame::getName(std::string &str) const {
258   setNameValue();
259   if (name_val_set == nv_set) {
260     str = sym_name;
261     sw_printf("[%s:%u] - Frame::getName (frame %p) returning %s\n",
262               FILE__, __LINE__, this, str.c_str());
263     return true;
264   }
265   else {
266     sw_printf("[%s:%u] - Frame::getName (frame %p) returning error\n",
267               FILE__, __LINE__, this);
268     return false;
269   }
270 }
271
272 bool Frame::getObject(void* &obj) const {
273   setNameValue();
274   if (name_val_set == nv_set) {
275     obj = sym_value;
276     sw_printf("[%s:%u] - Frame::getObject (frame %p) returning %p\n",
277               FILE__, __LINE__, this, obj);
278     return true;
279   }
280   else {
281     sw_printf("[%s:%u] - Frame::getObject (frame %p) returning error\n",
282               FILE__, __LINE__, this);
283     return false;
284   }
285 }
286
287 bool Frame::isTopFrame() const {
288   return top_frame;
289 }
290
291 bool Frame::isBottomFrame() const {
292   return bottom_frame;
293 }
294
295 const Frame *Frame::getPrevFrame() const {
296   return prev_frame;
297 }
298
299 FrameStepper *Frame::getStepper() const {
300   return stepper;
301 }
302
303 FrameStepper *Frame::getNextStepper() const {
304   return next_stepper;
305 }
306
307 Walker *Frame::getWalker() const {
308   return walker;
309 }
310
311 bool Frame::isFrameComplete() const {
312   return frame_complete;
313 }
314
315 Frame::~Frame() {
316   sw_printf("[%s:%u] - Destroying frame %p\n", FILE__, __LINE__, this);
317 }
318
319 bool Frame::getLibOffset(std::string &lib, Dyninst::Offset &offset, void*& symtab) const
320 {
321   LibraryState *libstate = getWalker()->getProcessState()->getLibraryTracker();
322   if (!libstate) {
323     sw_printf("[%s:%u] - getLibraryAtAddr, had no library tracker\n",
324               FILE__, __LINE__);
325     setLastError(err_unsupported, "No valid library tracker registered");
326     return false;
327   }
328
329   LibAddrPair la;
330   bool result = libstate->getLibraryAtAddr(getRA(), la);
331   if (!result) {
332     sw_printf("[%s:%u] - getLibraryAtAddr returned false for %x\n",
333               FILE__, __LINE__, getRA());
334     return false;
335   }
336
337   lib = la.first;
338   offset = getRA() - la.second;
339
340 #if defined(WITH_SYMTAB_API)
341   symtab = static_cast<void *>(SymtabWrapper::getSymtab(lib));
342 #else
343   symtab = NULL;
344 #endif
345
346   return true;
347 }
348
349 THR_ID Frame::getThread() const
350 {
351    return originating_thread;
352 }
353
354 void Frame::setThread(THR_ID t)
355 {
356    originating_thread = t;
357 }
358
359 void Frame::setNonCall() 
360 {
361    non_call_frame = true;
362 }
363
364 bool Frame::nonCall() const
365
366    return non_call_frame;
367 }
368
369 FrameNode::FrameNode(frame_cmp_wrapper f) :
370    children(f),
371    parent(NULL),
372    frame_type(),
373    thrd(NULL_THR_ID),
374    walker(NULL),
375    had_error(false)
376 {
377 }
378
379 FrameNode::FrameNode(frame_cmp_wrapper f, string s) :
380    children(f),
381    parent(NULL),
382    frame_type(FTString),
383    thrd(NULL_THR_ID),
384    walker(NULL),
385    had_error(false),
386    ftstring(s)
387 {
388 }
389
390 FrameNode::FrameNode(const FrameNode &fn) :
391    children(fn.children.key_comp()),
392    parent(NULL),
393    frame_type(fn.frame_type),
394    frame(fn.frame),
395    thrd(fn.thrd),
396    walker(fn.walker),
397    had_error(fn.had_error),
398    ftstring(fn.ftstring)
399 {
400 }
401
402 FrameNode::~FrameNode()
403 {
404 }
405
406 inline bool frame_cmp_wrapper::operator()(const FrameNode *a, const FrameNode *b) { 
407    if (a->frame_type == FrameNode::FTThread && b->frame_type == FrameNode::FTThread) {
408       Dyninst::PID a_pid = a->getWalker()->getProcessState()->getProcessId();
409       Dyninst::PID b_pid = b->getWalker()->getProcessState()->getProcessId();
410       if (a_pid != b_pid)
411          return a_pid < b_pid;
412       return a->thrd < b->thrd;
413    }
414    else if (a->frame_type == FrameNode::FTThread)
415       return false;
416    else if (b->frame_type == FrameNode::FTThread)
417       return true;
418    else if (a->frame_type == FrameNode::FTString && b->frame_type == FrameNode::FTString)
419       return a->frameString() < b->frameString();
420    else if (a->frame_type == FrameNode::FTString)
421       return false;
422    else if (b->frame_type == FrameNode::FTString)
423       return true;
424    else
425       return f(a->frame, b->frame);
426 }
427
428 CallTree::CallTree(frame_cmp_t cmpf)
429 {
430    cmp_wrapper.f = cmpf;
431    head = new FrameNode(cmp_wrapper);
432    head->frame_type = FrameNode::FTHead;
433    head->parent = NULL;
434 }
435
436 frame_cmp_t CallTree::getComparator()
437 {
438    return cmp_wrapper.f;
439 }
440
441 frame_cmp_wrapper CallTree::getCompareWrapper()
442 {
443    return cmp_wrapper;
444 }
445
446 static void deleteTree(FrameNode *node) {
447    frame_set_t &children = node->getChildren();
448    for (frame_set_t::iterator i = children.begin(); i != children.end(); i++)
449       deleteTree(*i);
450    delete(node);
451 }
452
453 CallTree::~CallTree() 
454 {
455    deleteTree(head);
456    head = NULL;
457 }
458
459 FrameNode *CallTree::addFrame(const Frame &f, FrameNode *parent)
460 {
461    FrameNode search_node(cmp_wrapper);
462    search_node.frame_type = FrameNode::FTFrame;
463    search_node.frame = f;
464
465    pair<frame_set_t::iterator, frame_set_t::iterator> is = parent->children.equal_range(&search_node);
466    bool found = (is.first != is.second);
467    if (found) {
468       //Common case, already have this node in tree, don't create a new one.
469       FrameNode *n = *is.first;
470       return n;
471    }
472
473    //Create and insert a new node at position i
474    FrameNode *new_node = new FrameNode(cmp_wrapper);
475    new_node->frame_type = FrameNode::FTFrame;
476    new_node->frame = f;
477    new_node->walker = f.getWalker();
478    parent->children.insert(is.first, new_node);
479
480    return new_node;
481 }
482
483 FrameNode *CallTree::addThread(THR_ID thrd, FrameNode *parent, Walker *walker, bool err_stack)
484 {
485    FrameNode *new_node = new FrameNode(cmp_wrapper);
486    assert(walker);
487    new_node->frame_type = FrameNode::FTThread;
488    new_node->thrd = thrd;
489    new_node->walker = walker;
490    new_node->had_error = err_stack;
491
492    pair<frame_set_t::iterator, bool> i = parent->children.insert(new_node);
493    if (!i.second) {
494       //Element already existed.
495       delete new_node;
496       return *(i.first);
497    }
498
499    return new_node;
500 }
501
502 void CallTree::addCallStack(const vector<Frame> &stk, THR_ID thrd, Walker *walker, bool err_stack)
503 {
504    FrameNode *cur = head;
505    for (vector<Frame>::const_reverse_iterator i = stk.rbegin(); i != stk.rend(); i++) {
506       cur = addFrame(*i, cur);
507    }
508    addThread(thrd, cur, walker, err_stack);
509 }
510  
511 bool Dyninst::Stackwalker::frame_addr_cmp(const Frame &a, const Frame &b)
512 {
513    return a.getRA() < b.getRA();
514 }
515
516 bool Dyninst::Stackwalker::frame_lib_offset_cmp(const Frame &a, const Frame &b)
517 {
518    string a_lib, b_lib;
519    Offset a_off = 0, b_off = 0;
520    void *a_ignore, *b_ignore;
521    a.getLibOffset(a_lib, a_off, a_ignore);
522    b.getLibOffset(b_lib, b_off, b_ignore);
523    int str_cmp = a_lib.compare(b_lib);
524    if (str_cmp < 0)
525       return true;
526    else if (str_cmp > 0)
527       return false;
528    else
529       return a_off < b_off;
530 }
531
532 bool Dyninst::Stackwalker::frame_symname_cmp(const Frame &a, const Frame &b)
533 {
534    string a_name, b_name;
535    a.getName(a_name);
536    b.getName(b_name);
537    return a_name < b_name;
538 }
539
540 bool Dyninst::Stackwalker::frame_lineno_cmp(const Frame &, const Frame &)
541 {
542    assert(0 && "frame_lineno_cmp unimplemented");
543         return false;
544 }