Commiting Aishwarya's work in allowing StackwalkerAPI users to change the system...
[dyninst.git] / stackwalk / src / walker.C
1 /*
2  * Copyright (c) 1996-2011 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/walker.h"
33 #include "stackwalk/h/frame.h"
34 #include "stackwalk/h/swk_errors.h"
35 #include "stackwalk/h/procstate.h"
36 #include "stackwalk/h/symlookup.h"
37 #include "stackwalk/h/framestepper.h"
38 #include "stackwalk/h/steppergroup.h"
39 #include "stackwalk/src/sw.h"
40 #include <assert.h>
41
42 using namespace Dyninst;
43 using namespace Dyninst::Stackwalker;
44 using namespace std;
45
46 void Walker::version(int& major, int& minor, int& maintenance)
47 {
48     major = SW_MAJOR;
49     minor = SW_MINOR;
50     maintenance = SW_BETA;
51 }
52
53
54 Walker::Walker(ProcessState *p, 
55                StepperGroup *grp,
56                SymbolLookup *sym, 
57                bool default_steppers,
58                std::string exec_name) :
59    proc(NULL), 
60    lookup(NULL),
61    creation_error(false),
62    call_count(0)
63 {
64    bool result;
65    //Always start with a process object
66    assert(p);
67    proc = p;
68    proc->walker = this;
69    
70    sw_printf("[%s:%u] - Creating new Walker with proc=%p, sym=%p, step = %d\n",
71              __FILE__, __LINE__, proc, sym, (int) default_steppers);
72    group = grp ? grp : createDefaultStepperGroup();
73    if (default_steppers) {
74       result = createDefaultSteppers();
75       if (!result) {
76          sw_printf("[%s:%u] - Error creating default steppers\n",
77                    __FILE__, __LINE__);
78          creation_error = true;
79          return;
80       }
81    }
82
83    lookup = sym ? sym : createDefaultSymLookup(exec_name);
84    if (!lookup) {
85       sw_printf("[%s:%u] - WARNING, no symbol lookup available\n",
86                 __FILE__, __LINE__);
87    }
88 }
89
90 Walker* Walker::newWalker(std::string exec_name) 
91 {
92   sw_printf("[%s:%u] - Creating new stackwalker on current process\n",
93             __FILE__, __LINE__);
94    
95   ProcessState *newproc = createDefaultProcess(exec_name);
96   if (!newproc) {
97     sw_printf("[%s:%u] - Error creating default process\n",
98               __FILE__, __LINE__);
99     return NULL;
100   }
101   
102   Walker *newwalker = new Walker(newproc, NULL, NULL, true, exec_name);
103   if (!newwalker || newwalker->creation_error) {
104     sw_printf("[%s:%u] - Error creating new Walker object %p\n",
105               __FILE__, __LINE__, newwalker);
106     return NULL;
107   }
108   
109   sw_printf("[%s:%u] - Successfully created Walker %p\n", 
110             __FILE__, __LINE__, newwalker);
111   
112   return newwalker;
113 }
114
115 Walker *Walker::newWalker(Dyninst::PID pid,
116                           std::string executable)
117 {
118   sw_printf("[%s:%u] - Creating new stackwalker for process %d on %s\n",
119             __FILE__, __LINE__, (int) pid, executable.c_str());
120   
121   ProcessState *newproc = createDefaultProcess(pid, executable);
122   if (!newproc) {
123     sw_printf("[%s:%u] - Error creating default process\n",
124               __FILE__, __LINE__);
125     return NULL;
126   }
127
128   Walker *newwalker = new Walker(newproc, NULL, NULL, true, executable);
129   if (!newwalker || newwalker->creation_error) {
130     sw_printf("[%s:%u] - Error creating new Walker object %p\n",
131               __FILE__, __LINE__, newwalker);
132     return NULL;
133   }
134   
135   sw_printf("[%s:%u] - Successfully created Walker %p\n", 
136             __FILE__, __LINE__, newwalker);
137   
138   return newwalker;
139 }
140
141 Walker *Walker::newWalker(std::string exec_name, 
142                           const std::vector<std::string> &argv)
143 {
144    sw_printf("[%s:%u] - Creating new stackwalker with process %s\n",
145              __FILE__, __LINE__, exec_name.c_str());
146
147    ProcessState *newproc = createDefaultProcess(exec_name, argv);
148    if (!newproc) {
149       sw_printf("[%s:%u] - Error creating default process\n",
150                 __FILE__, __LINE__);
151       return NULL;
152    }
153
154    Walker *newwalker = new Walker(newproc, NULL, NULL, true, exec_name);
155    if (!newwalker || newwalker->creation_error) {
156       sw_printf("[%s:%u] - Error creating new Walker object %p\n",
157                 __FILE__, __LINE__, newwalker);
158       return NULL;
159    }
160
161    sw_printf("[%s:%u] - Successfully created Walker %p\n", 
162              __FILE__, __LINE__, newwalker);
163
164    return newwalker;
165 }
166
167 Walker *Walker::newWalker(ProcessState *proc, 
168                           StepperGroup *grp,
169                           SymbolLookup *lookup,
170                           bool default_steppers)
171 {
172    if (!proc) {
173       sw_printf("[%s:%u] - Error proc parameter to newWalker must not be NULL\n",
174                 __FILE__, __LINE__);
175       setLastError(err_badparam, "Tried to create a walker with a NULL " \
176                    "ProcessState param");
177       return NULL;
178    }
179    sw_printf("[%s:%u] - Creating custom Walker with proc = %p" \
180              "lookup = %p\n", __FILE__, __LINE__, proc, lookup);
181   
182    Walker *newwalker = new Walker(proc, grp, lookup, default_steppers, "");
183    if (!newwalker || newwalker->creation_error) {
184       sw_printf("[%s:%u] - Error creating new Walker object %p\n",
185                 __FILE__, __LINE__, newwalker);
186       return NULL;
187    }
188   
189    sw_printf("[%s:%u] - Successfully created Walker %p\n", 
190              __FILE__, __LINE__, newwalker);
191   
192    return newwalker;
193 }
194
195 Walker *Walker::newWalker(Dyninst::PID pid)
196 {
197    return newWalker(pid, "");
198 }
199
200 bool Walker::newWalker(const std::vector<Dyninst::PID> &pids,
201                        std::vector<Walker *> &walkers_out)
202 {
203    return newWalker(pids, walkers_out, "");
204 }
205
206 bool Walker::newWalker(const std::vector<Dyninst::PID> &pids,
207                        std::vector<Walker *> &walkers_out,
208                        std::string executable)
209 {
210   sw_printf("[%s:%u] - Creating multiple stackwalkers\n",
211             __FILE__, __LINE__);
212   unsigned num_errors = 0;
213   
214   vector<ProcDebug *> new_dbs;
215   bool pd_result = createDefaultProcess(pids, new_dbs);
216   if (!pd_result) {
217      sw_printf("[%s:%u] - Errors attaching to some processes\n",
218                __FILE__, __LINE__);
219   }
220
221   vector<ProcDebug *>::iterator i;
222   for (i = new_dbs.begin(); i != new_dbs.end(); i++) {
223      ProcDebug *pd = *i;
224      if (!pd) {
225         assert(!pd_result);
226         walkers_out.push_back(NULL);
227         num_errors++;
228         continue;
229      }
230
231      Walker *newwalker = new Walker((ProcessState *) pd, NULL, NULL, true, executable);
232      if (!newwalker || newwalker->creation_error) {
233         sw_printf("[%s:%u] - Error creating new Walker object %p\n",
234                   __FILE__, __LINE__, newwalker);
235         walkers_out.push_back(NULL);
236         num_errors++;
237         continue;
238      }
239
240      sw_printf("[%s:%u] - Successfully created walker for %d\n",
241                __FILE__, __LINE__, pd->getProcessId());
242      walkers_out.push_back(newwalker);
243   }
244
245   if (num_errors == pids.size())
246      return false;
247   return true;
248 }
249
250 Walker::~Walker() {
251    if (proc)
252       delete proc;
253    if (lookup)
254       delete lookup;
255    //TODO: Stepper cleanup
256 }
257
258
259 /**
260  * What is happening here, you may ask?  
261  *
262  * getInitialFrame returns the active frame on the stack.  However, 
263  * this is a problem if we want to do a first party stackwalk, because
264  * getInitialFrame will return a copy of its own frame and then deconstruct
265  * the frame, leaving us with an invalid stack frame.
266  *
267  * Instead we put the implementation of getInitialFrame into a macro, which
268  * means it's inlined into any function that uses it.  Thus, we can do a 
269  * first party stackwalk by embedding this into the walkStack call, which will
270  * get its own frame, then generate a stack frame without destroying the 
271  * initial frame.
272  *
273  * This is used in two places, so I figure it's better to use a 
274  * #define rather than make two copies of this code.  Also, this is only
275  * legal to call from a Walker object.
276  **/
277 #define getInitialFrameImpl(frame, thread) \
278 { \
279   result = true; \
280   Dyninst::MachRegister pc_reg, frm_reg, stk_reg; \
281   Dyninst::MachRegisterVal pc, sp, fp; \
282   if (thread == NULL_THR_ID) { \
283     result = proc->getDefaultThread(thread); \
284     if (!result) { \
285       sw_printf("getDefaultThread returned an error\n"); \
286       result = false; \
287       goto done_gifi; \
288     } \
289   } \
290   result = proc->getRegValue(Dyninst::ReturnAddr, thread, pc); \
291   result = !result || proc->getRegValue(Dyninst::StackTop, thread, sp); \
292   result = !result || proc->getRegValue(Dyninst::FrameBase, thread, fp); \
293   if (!result) { \
294     sw_printf("Failed to get registers from process\n"); \
295     result = false; \
296     goto done_gifi; \
297   } \
298   frame.setRA(pc); \
299   frame.setFP(fp); \
300   frame.setSP(sp); \
301   frame.setThread(thread); \
302   done_gifi: ; \
303 }
304
305 bool Walker::walkStack(std::vector<Frame> &stackwalk, THR_ID thread)
306 {
307    bool result;
308    Frame initialFrame(this);
309
310    if (thread == NULL_THR_ID) {
311       result = proc->getDefaultThread(thread);
312       if (!result) {
313          sw_printf("[%s:%u] - Couldn't get initial thread on %d\n",
314                    __FILE__, __LINE__, proc->getProcessId());
315          return false;
316       }
317    }
318
319    result = callPreStackwalk(thread);
320    if (!result) {
321       sw_printf("[%s:%u] - Call to preStackwalk failed, exiting from stackwalk\n",
322                 __FILE__, __LINE__);
323       return false;
324    }
325
326    sw_printf("[%s:%u] - Starting stackwalk on thread %d\n",
327              __FILE__, __LINE__, (int) thread);
328
329    getInitialFrameImpl(initialFrame, thread);
330    if (!result) {
331       sw_printf("[%s:%u] - Failed to get registers from process\n",
332                 __FILE__, __LINE__, (int) thread);
333       goto done;
334    }                       
335
336    result = walkStackFromFrame(stackwalk, initialFrame);
337    if (!result) {
338       sw_printf("[%s:%u] - walkStackFromFrame failed\n",
339                 __FILE__, __LINE__, (int) thread);
340       goto done;
341    }
342
343  done:
344    bool postresult = callPostStackwalk(thread);
345    if (!postresult) {
346       sw_printf("[%s:%u] - Call to postStackwalk failed\n", __FILE__, __LINE__);
347       return false;
348    }
349    return result;
350 }
351
352 bool Walker::walkStackFromFrame(std::vector<Frame> &stackwalk, 
353                                 const Frame &frame)
354 {
355    bool result;
356
357    stackwalk.clear();
358    stackwalk.push_back(frame);
359
360    sw_printf("[%s:%u] - walkStackFromFrame called with frame at %lx\n",
361              __FILE__, __LINE__, stackwalk.back().getRA());
362
363    result = callPreStackwalk();
364    if (!result) {
365       sw_printf("[%s:%u] - Call to preStackwalk failed, exiting from stackwalk\n",
366                 __FILE__, __LINE__);
367       return false;
368    }
369
370
371    for (;;) {
372      Frame cur_frame(this);
373      sw_printf("[%s:%u] - Walking single frame from %lx\n", __FILE__, __LINE__, 
374                stackwalk.back().getRA());
375
376      result = walkSingleFrame(stackwalk.back(), cur_frame);
377      if (!result) {
378         if (getLastError() == err_stackbottom) {
379            sw_printf("[%s:%u] - Reached bottom of stack\n", __FILE__, __LINE__);
380            clearLastError();
381            result = true;
382            goto done;
383         }
384         sw_printf("[%s:%u] - Error walking through stack frame %s\n", 
385                   __FILE__, __LINE__, getLastErrorMsg());
386         result = false;
387         goto done;
388      }
389      stackwalk.push_back(cur_frame);
390    }       
391
392  done:
393    bool postresult = callPostStackwalk();
394    if (!postresult) {
395       sw_printf("[%s:%u] - Call to postStackwalk failed\n", __FILE__, __LINE__);
396       return false;
397    }
398
399    sw_printf("[%s:%u] - Finished walking callstack from frame, result = %s\n",
400              __FILE__, __LINE__, result ? "true" : "false");
401    return result;
402 }
403
404 bool Walker::walkSingleFrame(const Frame &in, Frame &out)
405 {
406    gcframe_ret_t gcf_result;
407    bool result;
408    Frame last_frame = in;
409
410    sw_printf("[%s:%u] - Attempting to walk through frame with RA 0x%lx\n",
411              __FILE__, __LINE__, last_frame.getRA());
412
413    result = callPreStackwalk();
414    if (!result) {
415       sw_printf("[%s:%u] - Call to preStackwalk failed, exiting from stackwalk\n",
416                 __FILE__, __LINE__);
417       return false;
418    }   
419    
420    if (!group) {
421       setLastError(err_nogroup, "Attempt to walk a stack without a StepperGroup");
422       return false;
423    }
424
425    FrameStepper *last_stepper = NULL;
426    for (;;)
427    {
428      FrameStepper *cur_stepper = NULL;
429      bool res = group->findStepperForAddr(last_frame.getRA(), cur_stepper,
430                                           last_stepper);
431      if (!res) {
432         sw_printf("[%s:%u] - Unable to find a framestepper for %lx\n",
433                   __FILE__, __LINE__, last_frame.getRA());
434         result = false;
435         goto done;
436      }
437      sw_printf("[%s:%u] - Attempting to use stepper %s\n", 
438                __FILE__, __LINE__, cur_stepper->getName());
439      gcf_result = cur_stepper->getCallerFrame(in, out);
440      if (gcf_result == gcf_success) {
441        sw_printf("[%s:%u] - Success using stepper %s on 0x%lx\n", 
442                  __FILE__, __LINE__, cur_stepper->getName(), in.getRA());
443        if (!checkValidFrame(in, out)) {
444           sw_printf("[%s:%u] - Resulting frame is not valid\n", __FILE__, __LINE__);
445           result = false;
446           goto done;
447        }
448        sw_printf("[%s:%u] - Returning frame with RA %lx, SP %lx, FP %lx\n",
449                  __FILE__, __LINE__, out.getRA(), out.getSP(), out.getFP());
450        result = true;
451        goto done;
452      }
453      else if (gcf_result == gcf_not_me) {
454        last_stepper = cur_stepper;
455        sw_printf("[%s:%u] - Stepper %s declined address 0x%lx\n", 
456                  __FILE__, __LINE__, cur_stepper->getName(), in.getRA());
457        continue; 
458      }
459      else if (gcf_result == gcf_stackbottom) {
460         sw_printf("[%s:%u] - Stepper %s bottomed out on 0x%lx\n", 
461                   __FILE__, __LINE__, cur_stepper->getName(), in.getRA());
462        setLastError(err_stackbottom, "walkSingleFrame reached bottom of stack");
463        result = false;
464        goto done;
465      }
466      else if (gcf_result == gcf_error) {
467         sw_printf("[%s:%u] - A stepper reported error %d on frame at %lx\n", 
468                   __FILE__, __LINE__, cur_stepper, in.getRA());
469        result = false;
470        goto done;
471      }
472    }
473
474  done:
475    out.setThread(in.getThread());
476    bool postresult = callPostStackwalk();
477    if (!postresult) {
478       sw_printf("[%s:%u] - Call to postStackwalk failed\n", __FILE__, __LINE__);
479       return false;
480    }
481    sw_printf("[%s:%u] - Finished walking callstack, result = %s\n",
482              __FILE__, __LINE__, result ? "true" : "false");
483
484    return result;
485 }
486
487 bool Walker::getInitialFrame(Frame &frame, THR_ID thread) {
488    bool result;
489    result = callPreStackwalk(thread);
490    if (!result) {
491       sw_printf("[%s:%u] - Call to preStackwalk failed, exiting from stackwalk\n",
492                 __FILE__, __LINE__);
493       return false;
494    }
495
496    getInitialFrameImpl(frame, thread);
497    if (!result) {
498       sw_printf("[%s:%u] - getInitialFrameImpl failed\n",
499                 __FILE__, __LINE__, (int) thread);
500    }
501    bool postresult = callPostStackwalk(thread);
502    if (!postresult) {
503       sw_printf("[%s:%u] - Call to postStackwalk failed\n", __FILE__, __LINE__);
504       return false;
505    }
506
507    return result;
508 }
509
510
511 bool Walker::getAvailableThreads(std::vector<THR_ID> &threads) const {
512    threads.clear();
513    bool result = proc->getThreadIds(threads);
514    if (dyn_debug_stackwalk) {
515       if (!result) {
516          sw_printf("[%s:%u] - getThreadIds error\n", __FILE__, __LINE__);
517       }
518       else {
519          sw_printf("[%s:%u] - getThreadIds returning %d values:\t\n", 
520                    __FILE__, __LINE__, threads.size());
521          for (unsigned i=0; i<threads.size(); i++) {
522             sw_printf("%d ", (int) threads[i]);
523          }
524          sw_printf("\n ");
525       }
526    }
527    return result;
528 }
529
530 ProcessState *Walker::getProcessState() const {
531    return proc;
532 }
533
534 SymbolLookup *Walker::getSymbolLookup() const {
535    return lookup;
536 }
537
538 ProcessState *Walker::createDefaultProcess(std::string exec_name)
539 {
540    ProcSelf *pself = new ProcSelf(exec_name);
541    pself->initialize();
542    return pself;
543 }
544
545 ProcessState *Walker::createDefaultProcess(PID pid, std::string executable)
546 {
547    ProcDebug *pdebug = ProcDebug::newProcDebug(pid, executable);
548    return pdebug;
549 }
550
551 bool Walker::createDefaultProcess(const vector<Dyninst::PID> &pids,
552                                   vector<ProcDebug *> &pds)
553 {
554    return ProcDebug::newProcDebugSet(pids, pds);
555 }
556
557 ProcessState *Walker::createDefaultProcess(std::string exec_name, 
558                                            const std::vector<std::string> &argv)
559 {
560    ProcDebug *pdebug = ProcDebug::newProcDebug(exec_name, argv);
561    return pdebug;
562 }
563
564 bool Walker::addStepper(FrameStepper *s)
565 {
566    assert(group);
567    sw_printf("[%s:%u] - Registering stepper %s with group %p\n",
568              __FILE__, __LINE__, s->getName(), group);
569    group->registerStepper(s);
570    return true;
571 }
572
573 bool Walker::callPreStackwalk(Dyninst::THR_ID tid)
574 {
575    call_count++;
576    if (call_count != 1)
577       return true;
578    
579    return getProcessState()->preStackwalk(tid);
580 }
581
582 bool Walker::callPostStackwalk(Dyninst::THR_ID tid)
583 {
584    call_count--;
585
586    if (call_count != 0)
587       return true;
588
589    return getProcessState()->postStackwalk(tid);
590 }
591
592 StepperGroup *Walker::createDefaultStepperGroup()
593 {
594    return new AddrRangeGroup(this);
595 }
596
597 StepperGroup *Walker::getStepperGroup() const
598 {
599    return group;
600 }
601
602 SymbolReaderFactory *Walker::symrfact = NULL;
603 SymbolReaderFactory *Walker::getSymbolReader()
604 {
605    return Dyninst::Stackwalker::getDefaultSymbolReader();
606 }
607
608 void Walker::setSymbolReader(SymbolReaderFactory *val)
609 {
610    symrfact = val;
611 }
612