Merge branch 'dyninst_proccontrol_bw'
[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 SymbolReaderFactory *Walker::symrfact = NULL;
47
48 void Walker::version(int& major, int& minor, int& maintenance)
49 {
50     major = SW_MAJOR;
51     minor = SW_MINOR;
52     maintenance = SW_BETA;
53 }
54
55
56 Walker::Walker(ProcessState *p, 
57                StepperGroup *grp,
58                SymbolLookup *sym, 
59                bool default_steppers,
60                std::string exec_name) :
61    proc(NULL), 
62    lookup(NULL),
63    creation_error(false),
64    call_count(0)
65 {
66    bool result;
67    //Always start with a process object
68    assert(p);
69    proc = p;
70    proc->walker = this;
71    
72    sw_printf("[%s:%u] - Creating new Walker with proc=%p, sym=%p, step = %d\n",
73              __FILE__, __LINE__, proc, sym, (int) default_steppers);
74    group = grp ? grp : createDefaultStepperGroup();
75    if (default_steppers) {
76       result = createDefaultSteppers();
77       if (!result) {
78          sw_printf("[%s:%u] - Error creating default steppers\n",
79                    __FILE__, __LINE__);
80          creation_error = true;
81          return;
82       }
83    }
84
85    lookup = sym ? sym : createDefaultSymLookup(exec_name);
86    if (lookup) {
87       lookup->walker = this;
88    }
89    else {
90       sw_printf("[%s:%u] - WARNING, no symbol lookup available\n",
91                 __FILE__, __LINE__);
92    }
93 }
94
95 Walker* Walker::newWalker(std::string exec_name) 
96 {
97   sw_printf("[%s:%u] - Creating new stackwalker on current process\n",
98             __FILE__, __LINE__);
99    
100   ProcessState *newproc = createDefaultProcess(exec_name);
101   if (!newproc) {
102     sw_printf("[%s:%u] - Error creating default process\n",
103               __FILE__, __LINE__);
104     return NULL;
105   }
106   
107   Walker *newwalker = new Walker(newproc, NULL, NULL, true, exec_name);
108   if (!newwalker || newwalker->creation_error) {
109     sw_printf("[%s:%u] - Error creating new Walker object %p\n",
110               __FILE__, __LINE__, newwalker);
111     return NULL;
112   }
113   
114   sw_printf("[%s:%u] - Successfully created Walker %p\n", 
115             __FILE__, __LINE__, newwalker);
116   
117   return newwalker;
118 }
119
120 Walker *Walker::newWalker(Dyninst::PID pid,
121                           std::string executable)
122 {
123   sw_printf("[%s:%u] - Creating new stackwalker for process %d on %s\n",
124             __FILE__, __LINE__, (int) pid, executable.c_str());
125   
126   ProcessState *newproc = createDefaultProcess(pid, executable);
127   if (!newproc) {
128     sw_printf("[%s:%u] - Error creating default process\n",
129               __FILE__, __LINE__);
130     return NULL;
131   }
132
133   Walker *newwalker = new Walker(newproc, NULL, NULL, true, executable);
134   if (!newwalker || newwalker->creation_error) {
135     sw_printf("[%s:%u] - Error creating new Walker object %p\n",
136               __FILE__, __LINE__, newwalker);
137     return NULL;
138   }
139   
140   sw_printf("[%s:%u] - Successfully created Walker %p\n", 
141             __FILE__, __LINE__, newwalker);
142   
143   return newwalker;
144 }
145
146 Walker *Walker::newWalker(std::string exec_name, 
147                           const std::vector<std::string> &argv)
148 {
149    sw_printf("[%s:%u] - Creating new stackwalker with process %s\n",
150              __FILE__, __LINE__, exec_name.c_str());
151
152    ProcessState *newproc = createDefaultProcess(exec_name, argv);
153    if (!newproc) {
154       sw_printf("[%s:%u] - Error creating default process\n",
155                 __FILE__, __LINE__);
156       return NULL;
157    }
158
159    Walker *newwalker = new Walker(newproc, NULL, NULL, true, exec_name);
160    if (!newwalker || newwalker->creation_error) {
161       sw_printf("[%s:%u] - Error creating new Walker object %p\n",
162                 __FILE__, __LINE__, newwalker);
163       return NULL;
164    }
165
166    sw_printf("[%s:%u] - Successfully created Walker %p\n", 
167              __FILE__, __LINE__, newwalker);
168
169    return newwalker;
170 }
171
172 Walker *Walker::newWalker(ProcessState *proc, 
173                           StepperGroup *grp,
174                           SymbolLookup *lookup,
175                           bool default_steppers)
176 {
177    if (!proc) {
178       sw_printf("[%s:%u] - Error proc parameter to newWalker must not be NULL\n",
179                 __FILE__, __LINE__);
180       setLastError(err_badparam, "Tried to create a walker with a NULL " \
181                    "ProcessState param");
182       return NULL;
183    }
184    sw_printf("[%s:%u] - Creating custom Walker with proc = %p" \
185              "lookup = %p\n", __FILE__, __LINE__, proc, lookup);
186   
187    Walker *newwalker = new Walker(proc, grp, lookup, default_steppers, "");
188    if (!newwalker || newwalker->creation_error) {
189       sw_printf("[%s:%u] - Error creating new Walker object %p\n",
190                 __FILE__, __LINE__, newwalker);
191       return NULL;
192    }
193   
194    sw_printf("[%s:%u] - Successfully created Walker %p\n", 
195              __FILE__, __LINE__, newwalker);
196   
197    return newwalker;
198 }
199
200 Walker *Walker::newWalker(Dyninst::PID pid)
201 {
202    return newWalker(pid, "");
203 }
204
205 Walker *Walker::newWalker(Dyninst::ProcControlAPI::Process::ptr proc)
206 {
207   sw_printf("[%s:%u] - Creating new stackwalker for ProcControl process %d\n",
208             __FILE__, __LINE__, (int) proc->getPid());
209   
210   ProcessState *newproc = createDefaultProcess(proc);
211   if (!newproc) {
212     sw_printf("[%s:%u] - Error creating default process\n",
213               __FILE__, __LINE__);
214     return NULL;
215   }
216
217   Walker *newwalker = new Walker(newproc, NULL, NULL, true, string());
218   if (!newwalker || newwalker->creation_error) {
219     sw_printf("[%s:%u] - Error creating new Walker object %p\n",
220               __FILE__, __LINE__, newwalker);
221     return NULL;
222   }
223   
224   sw_printf("[%s:%u] - Successfully created Walker %p\n", 
225             __FILE__, __LINE__, newwalker);
226   
227   return newwalker;
228 }
229
230 bool Walker::newWalker(const std::vector<Dyninst::PID> &pids,
231                        std::vector<Walker *> &walkers_out)
232 {
233    return newWalker(pids, walkers_out, "");
234 }
235
236 bool Walker::newWalker(const std::vector<Dyninst::PID> &pids,
237                        std::vector<Walker *> &walkers_out,
238                        std::string executable)
239 {
240   sw_printf("[%s:%u] - Creating multiple stackwalkers\n",
241             __FILE__, __LINE__);
242   unsigned num_errors = 0;
243   
244   vector<ProcDebug *> new_dbs;
245   bool pd_result = createDefaultProcess(pids, new_dbs);
246   if (!pd_result) {
247      sw_printf("[%s:%u] - Errors attaching to some processes\n",
248                __FILE__, __LINE__);
249   }
250
251   vector<ProcDebug *>::iterator i;
252   for (i = new_dbs.begin(); i != new_dbs.end(); i++) {
253      ProcDebug *pd = *i;
254      if (!pd) {
255         assert(!pd_result);
256         walkers_out.push_back(NULL);
257         num_errors++;
258         continue;
259      }
260
261      Walker *newwalker = new Walker((ProcessState *) pd, NULL, NULL, true, executable);
262      if (!newwalker || newwalker->creation_error) {
263         sw_printf("[%s:%u] - Error creating new Walker object %p\n",
264                   __FILE__, __LINE__, newwalker);
265         walkers_out.push_back(NULL);
266         num_errors++;
267         continue;
268      }
269
270      sw_printf("[%s:%u] - Successfully created walker for %d\n",
271                __FILE__, __LINE__, pd->getProcessId());
272      walkers_out.push_back(newwalker);
273   }
274
275   if (num_errors == pids.size())
276      return false;
277   return true;
278 }
279
280 Walker::~Walker() {
281    if (proc)
282       delete proc;
283    if (lookup)
284       delete lookup;
285    delete group;
286 }
287
288 SymbolReaderFactory *Walker::getSymbolReader()
289 {
290    return symrfact;
291 }
292
293 void Walker::setSymbolReader(SymbolReaderFactory *srf)
294 {
295    symrfact = srf;
296 }
297
298 /**
299  * What is happening here, you may ask?  
300  *
301  * getInitialFrame returns the active frame on the stack.  However, 
302  * this is a problem if we want to do a first party stackwalk, because
303  * getInitialFrame will return a copy of its own frame and then deconstruct
304  * the frame, leaving us with an invalid stack frame.
305  *
306  * Instead we put the implementation of getInitialFrame into a macro, which
307  * means it's inlined into any function that uses it.  Thus, we can do a 
308  * first party stackwalk by embedding this into the walkStack call, which will
309  * get its own frame, then generate a stack frame without destroying the 
310  * initial frame.
311  *
312  * This is used in two places, so I figure it's better to use a 
313  * #define rather than make two copies of this code.  Also, this is only
314  * legal to call from a Walker object.
315  **/
316 #define getInitialFrameImpl(frame, thread) \
317 { \
318   result = true; \
319   Dyninst::MachRegister pc_reg, frm_reg, stk_reg; \
320   Dyninst::MachRegisterVal pc, sp, fp; \
321   location_t loc; \
322   if (thread == NULL_THR_ID) { \
323     result = proc->getDefaultThread(thread); \
324     if (!result) { \
325       sw_printf("getDefaultThread returned an error\n"); \
326       result = false; \
327       goto done_gifi; \
328     } \
329   } \
330   result = proc->getRegValue(Dyninst::ReturnAddr, thread, pc); \
331   result = !result || proc->getRegValue(Dyninst::StackTop, thread, sp); \
332   result = !result || proc->getRegValue(Dyninst::FrameBase, thread, fp); \
333   if (!result) { \
334     sw_printf("Failed to get registers from process\n"); \
335     result = false; \
336     goto done_gifi; \
337   } \
338   frame.setRA(pc); \
339   frame.setFP(fp); \
340   frame.setSP(sp); \
341   loc.location = loc_register; \
342   loc.val.reg = Dyninst::ReturnAddr; \
343   frame.setRALocation(loc); \
344   loc.val.reg = Dyninst::StackTop; \
345   frame.setSPLocation(loc); \
346   loc.val.reg = Dyninst::FrameBase; \
347   frame.setFPLocation(loc); \
348   frame.setThread(thread); \
349   frame.markTopFrame(); \
350   done_gifi: ; \
351 }
352
353 bool Walker::walkStack(std::vector<Frame> &stackwalk, THR_ID thread)
354 {
355    bool result;
356    Frame initialFrame(this);
357
358    if (thread == NULL_THR_ID) {
359       result = proc->getDefaultThread(thread);
360       if (!result) {
361          sw_printf("[%s:%u] - Couldn't get initial thread on %d\n",
362                    __FILE__, __LINE__, proc->getProcessId());
363          return false;
364       }
365    }
366
367    result = callPreStackwalk(thread);
368    if (!result) {
369       sw_printf("[%s:%u] - Call to preStackwalk failed, exiting from stackwalk\n",
370                 __FILE__, __LINE__);
371       return false;
372    }
373
374    sw_printf("[%s:%u] - Starting stackwalk on thread %d\n",
375              __FILE__, __LINE__, (int) thread);
376
377    getInitialFrameImpl(initialFrame, thread);
378    if (!result) {
379       sw_printf("[%s:%u] - Failed to get registers from process\n",
380                 __FILE__, __LINE__, (int) thread);
381       goto done;
382    }                       
383
384    result = walkStackFromFrame(stackwalk, initialFrame);
385    if (!result) {
386       sw_printf("[%s:%u] - walkStackFromFrame failed\n",
387                 __FILE__, __LINE__, (int) thread);
388       goto done;
389    }
390
391  done:
392    bool postresult = callPostStackwalk(thread);
393    if (!postresult) {
394       sw_printf("[%s:%u] - Call to postStackwalk failed\n", __FILE__, __LINE__);
395       return false;
396    }
397    return result;
398 }
399
400 bool Walker::walkStackFromFrame(std::vector<Frame> &stackwalk, 
401                                 const Frame &frame)
402 {
403    bool result;
404
405    stackwalk.clear();
406    stackwalk.push_back(frame);
407
408    sw_printf("[%s:%u] - walkStackFromFrame called with frame at %lx\n",
409              __FILE__, __LINE__, stackwalk.back().getRA());
410
411    result = callPreStackwalk();
412    if (!result) {
413       sw_printf("[%s:%u] - Call to preStackwalk failed, exiting from stackwalk\n",
414                 __FILE__, __LINE__);
415       return false;
416    }
417
418
419    for (;;) {
420      Frame cur_frame(this);
421      sw_printf("[%s:%u] - Walking single frame from %lx\n", __FILE__, __LINE__, 
422                stackwalk.back().getRA());
423
424      result = walkSingleFrame(stackwalk.back(), cur_frame);
425      if (!result) {
426         if (getLastError() == err_stackbottom) {
427            sw_printf("[%s:%u] - Reached bottom of stack\n", __FILE__, __LINE__);
428            clearLastError();
429            result = true;
430            goto done;
431         }
432         sw_printf("[%s:%u] - Error walking through stack frame %s\n", 
433                   __FILE__, __LINE__, getLastErrorMsg());
434         result = false;
435         goto done;
436      }
437      stackwalk.back().next_stepper = cur_frame.getStepper();
438      stackwalk.push_back(cur_frame);
439    }       
440
441  done:
442    bool postresult = callPostStackwalk();
443    if (!postresult) {
444       sw_printf("[%s:%u] - Call to postStackwalk failed\n", __FILE__, __LINE__);
445       return false;
446    }
447
448    for (std::vector<Frame>::iterator swi = stackwalk.begin();
449         swi != stackwalk.end();
450         ++swi)
451    {
452      swi->prev_frame = NULL;
453    }
454
455    sw_printf("[%s:%u] - Finished walking callstack from frame, result = %s\n",
456              __FILE__, __LINE__, result ? "true" : "false");
457
458    return result;
459 }
460
461 bool Walker::walkSingleFrame(const Frame &in, Frame &out)
462 {
463    gcframe_ret_t gcf_result;
464    bool result;
465    Frame last_frame = in;
466
467    sw_printf("[%s:%u] - Attempting to walk through frame with RA 0x%lx\n",
468              __FILE__, __LINE__, last_frame.getRA());
469
470    result = callPreStackwalk();
471    if (!result) {
472       sw_printf("[%s:%u] - Call to preStackwalk failed, exiting from stackwalk\n",
473                 __FILE__, __LINE__);
474       return false;
475    }   
476    
477    if (!group) {
478       setLastError(err_nogroup, "Attempt to walk a stack without a StepperGroup");
479       return false;
480    }
481
482    out.prev_frame = &in;
483
484    FrameStepper *last_stepper = NULL;
485    for (;;)
486    {
487      FrameStepper *cur_stepper = NULL;
488      bool res = group->findStepperForAddr(last_frame.getRA(), cur_stepper,
489                                           last_stepper);
490      if (!res) {
491         sw_printf("[%s:%u] - Unable to find a framestepper for %lx\n",
492                   __FILE__, __LINE__, last_frame.getRA());
493         result = false;
494         goto done;
495      }
496      sw_printf("[%s:%u] - Attempting to use stepper %s\n", 
497                __FILE__, __LINE__, cur_stepper->getName());
498      gcf_result = cur_stepper->getCallerFrame(in, out);
499      if (gcf_result == gcf_success) {
500        sw_printf("[%s:%u] - Success using stepper %s on 0x%lx\n", 
501                  __FILE__, __LINE__, cur_stepper->getName(), in.getRA());
502        if (!checkValidFrame(in, out)) {
503           sw_printf("[%s:%u] - Resulting frame is not valid\n", __FILE__, __LINE__);
504           result = false;
505           goto done;
506        }
507        sw_printf("[%s:%u] - Returning frame with RA %lx, SP %lx, FP %lx\n",
508                  __FILE__, __LINE__, out.getRA(), out.getSP(), out.getFP());
509        out.setStepper(cur_stepper);
510        result = true;
511        goto done;
512      }
513      else if (gcf_result == gcf_not_me) {
514        last_stepper = cur_stepper;
515        sw_printf("[%s:%u] - Stepper %s declined address 0x%lx\n", 
516                  __FILE__, __LINE__, cur_stepper->getName(), in.getRA());
517        continue; 
518      }
519      else if (gcf_result == gcf_stackbottom) {
520         sw_printf("[%s:%u] - Stepper %s bottomed out on 0x%lx\n", 
521                   __FILE__, __LINE__, cur_stepper->getName(), in.getRA());
522        setLastError(err_stackbottom, "walkSingleFrame reached bottom of stack");
523        result = false;
524        goto done;
525      }
526      else if (gcf_result == gcf_error) {
527         sw_printf("[%s:%u] - A stepper reported error %d on frame at %lx\n", 
528                   __FILE__, __LINE__, cur_stepper, in.getRA());
529        result = false;
530        goto done;
531      }
532    }
533
534  done:
535    out.setThread(in.getThread());
536    bool postresult = callPostStackwalk();
537    if (!postresult) {
538       sw_printf("[%s:%u] - Call to postStackwalk failed\n", __FILE__, __LINE__);
539       return false;
540    }
541
542    return result;
543 }
544
545 bool Walker::getInitialFrame(Frame &frame, THR_ID thread) {
546    bool result;
547    result = callPreStackwalk(thread);
548    if (!result) {
549       sw_printf("[%s:%u] - Call to preStackwalk failed, exiting from stackwalk\n",
550                 __FILE__, __LINE__);
551       return false;
552    }
553
554    getInitialFrameImpl(frame, thread);
555    if (!result) {
556       sw_printf("[%s:%u] - getInitialFrameImpl failed\n",
557                 __FILE__, __LINE__, (int) thread);
558    }
559    bool postresult = callPostStackwalk(thread);
560    if (!postresult) {
561       sw_printf("[%s:%u] - Call to postStackwalk failed\n", __FILE__, __LINE__);
562       return false;
563    }
564
565    return result;
566 }
567
568
569 bool Walker::getAvailableThreads(std::vector<THR_ID> &threads) const {
570    threads.clear();
571    bool result = proc->getThreadIds(threads);
572    if (dyn_debug_stackwalk) {
573       if (!result) {
574          sw_printf("[%s:%u] - getThreadIds error\n", __FILE__, __LINE__);
575       }
576       else {
577          sw_printf("[%s:%u] - getThreadIds returning %d values:\t\n", 
578                    __FILE__, __LINE__, threads.size());
579          for (unsigned i=0; i<threads.size(); i++) {
580             sw_printf("%d ", (int) threads[i]);
581          }
582          sw_printf("\n ");
583       }
584    }
585    return result;
586 }
587
588 ProcessState *Walker::getProcessState() const {
589    return proc;
590 }
591
592 SymbolLookup *Walker::getSymbolLookup() const {
593    return lookup;
594 }
595
596 ProcessState *Walker::createDefaultProcess(std::string exec_name)
597 {
598    ProcSelf *pself = new ProcSelf(exec_name);
599    pself->initialize();
600    return pself;
601 }
602
603 ProcessState *Walker::createDefaultProcess(PID pid, std::string executable)
604 {
605    ProcDebug *pdebug = ProcDebug::newProcDebug(pid, executable);
606    return pdebug;
607 }
608
609 ProcessState *Walker::createDefaultProcess(Dyninst::ProcControlAPI::Process::ptr proc)
610 {
611    ProcDebug *pdebug = ProcDebug::newProcDebug(proc);
612    return pdebug;
613 }
614
615 bool Walker::createDefaultProcess(const vector<Dyninst::PID> &pids,
616                                   vector<ProcDebug *> &pds)
617 {
618    return ProcDebug::newProcDebugSet(pids, pds);
619 }
620
621 ProcessState *Walker::createDefaultProcess(std::string exec_name, 
622                                            const std::vector<std::string> &argv)
623 {
624    ProcDebug *pdebug = ProcDebug::newProcDebug(exec_name, argv);
625    return pdebug;
626 }
627
628 bool Walker::addStepper(FrameStepper *s)
629 {
630    assert(group);
631    sw_printf("[%s:%u] - Registering stepper %s with group %p\n",
632              __FILE__, __LINE__, s->getName(), group);
633    group->registerStepper(s);
634    return true;
635 }
636
637 bool Walker::callPreStackwalk(Dyninst::THR_ID tid)
638 {
639    call_count++;
640    if (call_count != 1)
641       return true;
642    
643    return getProcessState()->preStackwalk(tid);
644 }
645
646 bool Walker::callPostStackwalk(Dyninst::THR_ID tid)
647 {
648    call_count--;
649
650    if (call_count != 0)
651       return true;
652
653    return getProcessState()->postStackwalk(tid);
654 }
655
656 StepperGroup *Walker::createDefaultStepperGroup()
657 {
658    return new AddrRangeGroup(this);
659 }
660
661 StepperGroup *Walker::getStepperGroup() const
662 {
663    return group;
664 }
665
666 int_walkerSet::int_walkerSet() :
667    non_pd_walkers(0)
668 {
669    initProcSet();
670 }
671
672 int_walkerSet::~int_walkerSet()
673 {
674    clearProcSet();
675 }
676
677 pair<set<Walker *>::iterator, bool> int_walkerSet::insert(Walker *w)
678 {
679    ProcDebug *pd = dynamic_cast<ProcDebug *>(w->getProcessState());
680    if (!pd) {
681       non_pd_walkers++;
682    }
683    else {
684       addToProcSet(pd);
685    }
686
687    return walkers.insert(w);
688 }
689
690 void int_walkerSet::erase(set<Walker *>::iterator i)
691 {
692    ProcDebug *pd = dynamic_cast<ProcDebug *>((*i)->getProcessState());
693    if (!pd) {
694       non_pd_walkers--;
695    }
696    else {
697       eraseFromProcSet(pd);
698    }
699    
700    walkers.erase(i);
701 }
702
703 WalkerSet *WalkerSet::newWalkerSet()
704 {
705    return new WalkerSet();
706 }
707
708 WalkerSet::WalkerSet() :
709    iwalkerset(new int_walkerSet())
710 {
711 }
712
713 WalkerSet::~WalkerSet()
714 {
715    delete iwalkerset;
716 }
717
718 WalkerSet::iterator WalkerSet::begin() {
719    return iwalkerset->walkers.begin();
720 }
721
722 WalkerSet::iterator WalkerSet::end() {
723    return iwalkerset->walkers.end();
724 }
725
726 WalkerSet::iterator WalkerSet::find(Walker *w) {
727    return iwalkerset->walkers.find(w);
728 }
729
730 WalkerSet::const_iterator WalkerSet::begin() const {
731    return ((const int_walkerSet *) iwalkerset)->walkers.begin();
732 }
733
734 WalkerSet::const_iterator WalkerSet::end() const {
735    return ((const int_walkerSet *) iwalkerset)->walkers.end();
736 }
737
738 WalkerSet::const_iterator WalkerSet::find(Walker *w) const {
739    return ((const int_walkerSet *) iwalkerset)->walkers.find(w);
740 }
741
742 pair<WalkerSet::iterator, bool> WalkerSet::insert(Walker *walker) {
743    return iwalkerset->insert(walker);
744 }
745
746 void WalkerSet::erase(WalkerSet::iterator i) {
747    iwalkerset->erase(i);
748 }
749
750 bool WalkerSet::empty() const {
751    return iwalkerset->walkers.empty();
752 }
753
754 size_t WalkerSet::size() const {
755    return iwalkerset->walkers.size();
756 }
757
758 bool WalkerSet::walkStacks(CallTree &tree) const {
759    if (empty()) {
760       sw_printf("[%s:%u] - Attempt to walk stacks of empty process set\n", __FILE__, __LINE__);
761       return false;
762    }
763    if (!iwalkerset->non_pd_walkers) {
764       bool bad_plat = false;
765       bool result = iwalkerset->walkStacksProcSet(tree, bad_plat);
766       if (result) {
767          //Success
768          return true;
769       }
770       if (!bad_plat) {
771          //Error
772          return false;
773       }
774       sw_printf("[%s:%u] - Platform does not have OS supported unwinding\n", __FILE__, __LINE__);
775    }
776    
777    bool had_error = false;
778    for (const_iterator i = begin(); i != end(); i++) {
779       vector<THR_ID> threads;
780       Walker *walker = *i;
781       bool result = walker->getAvailableThreads(threads);
782       if (!result) {
783          sw_printf("[%s:%u] - Error getting threads for process %d\n", __FILE__, __LINE__, 
784                    walker->getProcessState()->getProcessId());
785          had_error = true;
786          continue;
787       }
788
789       for (vector<THR_ID>::iterator j = threads.begin(); j != threads.end(); j++) {
790          std::vector<Frame> swalk;
791          THR_ID thr = *j;
792
793          bool result = walker->walkStack(swalk, thr);
794          if (!result && swalk.empty()) {
795             sw_printf("[%s:%u] - Error walking stack for %d/%d\n", __FILE__, __LINE__,
796                       walker->getProcessState()->getProcessId(), thr);
797             had_error = true;
798             continue;
799          }
800          tree.addCallStack(swalk, thr, walker, !result);
801       }
802    }
803    return !had_error;
804 }