stackwalk: Fix Coverity UNINIT_CTOR errors
[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(cap_stackwalker_use_symtab)
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    walker(NULL),
384    had_error(false),
385    ftstring(s)
386 {
387 }
388
389 FrameNode::FrameNode(const FrameNode &fn) :
390    children(fn.children.key_comp()),
391    parent(NULL),
392    frame_type(fn.frame_type),
393    frame(fn.frame),
394    thrd(fn.thrd),
395    walker(fn.walker),
396    had_error(fn.had_error),
397    ftstring(fn.ftstring)
398 {
399 }
400
401 FrameNode::~FrameNode()
402 {
403 }
404
405 inline bool frame_cmp_wrapper::operator()(const FrameNode *a, const FrameNode *b) { 
406    if (a->frame_type == FrameNode::FTThread && b->frame_type == FrameNode::FTThread) {
407       Dyninst::PID a_pid = a->getWalker()->getProcessState()->getProcessId();
408       Dyninst::PID b_pid = b->getWalker()->getProcessState()->getProcessId();
409       if (a_pid != b_pid)
410          return a_pid < b_pid;
411       return a->thrd < b->thrd;
412    }
413    else if (a->frame_type == FrameNode::FTThread)
414       return false;
415    else if (b->frame_type == FrameNode::FTThread)
416       return true;
417    else if (a->frame_type == FrameNode::FTString && b->frame_type == FrameNode::FTString)
418       return a->frameString() < b->frameString();
419    else if (a->frame_type == FrameNode::FTString)
420       return false;
421    else if (b->frame_type == FrameNode::FTString)
422       return true;
423    else
424       return f(a->frame, b->frame);
425 }
426
427 CallTree::CallTree(frame_cmp_t cmpf)
428 {
429    cmp_wrapper.f = cmpf;
430    head = new FrameNode(cmp_wrapper);
431    head->frame_type = FrameNode::FTHead;
432    head->parent = NULL;
433 }
434
435 frame_cmp_t CallTree::getComparator()
436 {
437    return cmp_wrapper.f;
438 }
439
440 frame_cmp_wrapper CallTree::getCompareWrapper()
441 {
442    return cmp_wrapper;
443 }
444
445 static void deleteTree(FrameNode *node) {
446    frame_set_t &children = node->getChildren();
447    for (frame_set_t::iterator i = children.begin(); i != children.end(); i++)
448       deleteTree(*i);
449    delete(node);
450 }
451
452 CallTree::~CallTree() 
453 {
454    deleteTree(head);
455    head = NULL;
456 }
457
458 FrameNode *CallTree::addFrame(const Frame &f, FrameNode *parent)
459 {
460    FrameNode search_node(cmp_wrapper);
461    search_node.frame_type = FrameNode::FTFrame;
462    search_node.frame = f;
463
464    pair<frame_set_t::iterator, frame_set_t::iterator> is = parent->children.equal_range(&search_node);
465    bool found = (is.first != is.second);
466    if (found) {
467       //Common case, already have this node in tree, don't create a new one.
468       FrameNode *n = *is.first;
469       return n;
470    }
471
472    //Create and insert a new node at position i
473    FrameNode *new_node = new FrameNode(cmp_wrapper);
474    new_node->frame_type = FrameNode::FTFrame;
475    new_node->frame = f;
476    new_node->walker = f.getWalker();
477    parent->children.insert(is.first, new_node);
478
479    return new_node;
480 }
481
482 FrameNode *CallTree::addThread(THR_ID thrd, FrameNode *parent, Walker *walker, bool err_stack)
483 {
484    FrameNode *new_node = new FrameNode(cmp_wrapper);
485    assert(walker);
486    new_node->frame_type = FrameNode::FTThread;
487    new_node->thrd = thrd;
488    new_node->walker = walker;
489    new_node->had_error = err_stack;
490
491    pair<frame_set_t::iterator, bool> i = parent->children.insert(new_node);
492    if (!i.second) {
493       //Element already existed.
494       delete new_node;
495       return *(i.first);
496    }
497
498    return new_node;
499 }
500
501 void CallTree::addCallStack(const vector<Frame> &stk, THR_ID thrd, Walker *walker, bool err_stack)
502 {
503    FrameNode *cur = head;
504    for (vector<Frame>::const_reverse_iterator i = stk.rbegin(); i != stk.rend(); i++) {
505       cur = addFrame(*i, cur);
506    }
507    addThread(thrd, cur, walker, err_stack);
508 }
509  
510 bool Dyninst::Stackwalker::frame_addr_cmp(const Frame &a, const Frame &b)
511 {
512    return a.getRA() < b.getRA();
513 }
514
515 bool Dyninst::Stackwalker::frame_lib_offset_cmp(const Frame &a, const Frame &b)
516 {
517    string a_lib, b_lib;
518    Offset a_off = 0, b_off = 0;
519    void *a_ignore, *b_ignore;
520    a.getLibOffset(a_lib, a_off, a_ignore);
521    b.getLibOffset(b_lib, b_off, b_ignore);
522    int str_cmp = a_lib.compare(b_lib);
523    if (str_cmp < 0)
524       return true;
525    else if (str_cmp > 0)
526       return false;
527    else
528       return a_off < b_off;
529 }
530
531 bool Dyninst::Stackwalker::frame_symname_cmp(const Frame &a, const Frame &b)
532 {
533    string a_name, b_name;
534    a.getName(a_name);
535    b.getName(b_name);
536    return a_name < b_name;
537 }
538
539 bool Dyninst::Stackwalker::frame_lineno_cmp(const Frame &, const Frame &)
540 {
541    assert(0 && "frame_lineno_cmp unimplemented");
542         return false;
543 }