Fix ARM stack walking (#559)
[dyninst.git] / stackwalk / src / walker.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/walker.h"
32 #include "stackwalk/h/frame.h"
33 #include "stackwalk/h/swk_errors.h"
34 #include "stackwalk/h/procstate.h"
35 #include "stackwalk/h/symlookup.h"
36 #include "stackwalk/h/framestepper.h"
37 #include "stackwalk/h/steppergroup.h"
38 #include "stackwalk/src/sw.h"
39 #include "stackwalk/src/libstate.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    if (Walker::symrfact) {
291       return Walker::symrfact;
292    }
293
294    SymbolReaderFactory *fact = ProcControlAPI::Process::getDefaultSymbolReader();
295    if (fact) {
296       Walker::symrfact = fact;
297       return fact;
298    }
299
300    fact = Stackwalker::getDefaultSymbolReader();
301    if (fact) {
302       Walker::symrfact = fact;
303       return fact;
304    }
305    return NULL;
306 }
307
308 void Walker::setSymbolReader(SymbolReaderFactory *srf)
309 {
310    symrfact = srf;
311    ProcControlAPI::Process::setDefaultSymbolReader(srf);
312 }
313
314 /**
315  * What is happening here, you may ask?
316  *
317  * getInitialFrame returns the active frame on the stack.  However,
318  * this is a problem if we want to do a first party stackwalk, because
319  * getInitialFrame will return a copy of its own frame and then deconstruct
320  * the frame, leaving us with an invalid stack frame.
321  *
322  * Instead we put the implementation of getInitialFrame into a macro, which
323  * means it's inlined into any function that uses it.  Thus, we can do a
324  * first party stackwalk by embedding this into the walkStack call, which will
325  * get its own frame, then generate a stack frame without destroying the
326  * initial frame.
327  *
328  * This is used in two places, so I figure it's better to use a
329  * #define rather than make two copies of this code.  Also, this is only
330  * legal to call from a Walker object.
331  **/
332 #define getInitialFrameImpl(frame, thread) \
333 { \
334   result = true; \
335   Dyninst::MachRegister pc_reg, frm_reg, stk_reg; \
336   Dyninst::MachRegisterVal pc, sp, fp; \
337   location_t loc; \
338   if (thread == NULL_THR_ID) { \
339     result = proc->getDefaultThread(thread); \
340     if (!result) { \
341       sw_printf("getDefaultThread returned an error\n"); \
342       result = false; \
343       goto done_gifi; \
344     } \
345   } \
346   result = proc->getRegValue(Dyninst::ReturnAddr, thread, pc); \
347   result = result && proc->getRegValue(Dyninst::StackTop, thread, sp); \
348   result = result && proc->getRegValue(Dyninst::FrameBase, thread, fp); \
349   if (!result) { \
350     sw_printf("Failed to get registers from process\n"); \
351     result = false; \
352     goto done_gifi; \
353   } \
354   frame.setRA(pc); \
355   frame.setFP(fp); \
356   frame.setSP(sp); \
357   loc.location = loc_register; \
358   loc.val.reg = Dyninst::ReturnAddr; \
359   frame.setRALocation(loc); \
360   loc.val.reg = Dyninst::StackTop; \
361   frame.setSPLocation(loc); \
362   loc.val.reg = Dyninst::FrameBase; \
363   frame.setFPLocation(loc); \
364   frame.setThread(thread); \
365   frame.markTopFrame(); \
366   done_gifi: ; \
367 }
368
369 bool Walker::walkStack(std::vector<Frame> &stackwalk, THR_ID thread)
370 {
371    bool result;
372    Frame initialFrame(this);
373
374    if (thread == NULL_THR_ID) {
375       result = proc->getDefaultThread(thread);
376       if (!result) {
377          sw_printf("[%s:%u] - Couldn't get initial thread on %d\n",
378                    FILE__, __LINE__, proc->getProcessId());
379          return false;
380       }
381    }
382
383    result = callPreStackwalk(thread);
384    if (!result) {
385       sw_printf("[%s:%u] - Call to preStackwalk failed, exiting from stackwalk\n",
386                 FILE__, __LINE__);
387       return false;
388    }
389
390    sw_printf("[%s:%u] - Starting stackwalk on thread %d\n",
391              FILE__, __LINE__, (int) thread);
392
393    getInitialFrameImpl(initialFrame, thread);
394    if (!result) {
395       sw_printf("[%s:%u] - Failed to get registers from process\n",
396                 FILE__, __LINE__, (int) thread);
397       goto done;
398    }
399
400    result = walkStackFromFrame(stackwalk, initialFrame);
401    if (!result) {
402       sw_printf("[%s:%u] - walkStackFromFrame failed\n",
403                 FILE__, __LINE__, (int) thread);
404       goto done;
405    }
406
407  done:
408    bool postresult = callPostStackwalk(thread);
409    if (!postresult) {
410       sw_printf("[%s:%u] - Call to postStackwalk failed\n", FILE__, __LINE__);
411       return false;
412    }
413    return result;
414 }
415
416 bool Walker::walkStackFromFrame(std::vector<Frame> &stackwalk,
417                                 const Frame &frame)
418 {
419    bool result;
420
421    stackwalk.clear();
422    stackwalk.push_back(frame);
423
424    sw_printf("[%s:%u] - walkStackFromFrame called with frame at %lx\n",
425              FILE__, __LINE__, stackwalk.back().getRA());
426
427    result = callPreStackwalk();
428    if (!result) {
429       sw_printf("[%s:%u] - Call to preStackwalk failed, exiting from stackwalk\n",
430                 FILE__, __LINE__);
431       return false;
432    }
433
434
435    for (;;) {
436      Frame cur_frame(this);
437      sw_printf("[%s:%u] - Walking single frame from %lx\n", FILE__, __LINE__,
438                stackwalk.back().getRA());
439
440      result = walkSingleFrame(stackwalk.back(), cur_frame);
441      if (!result) {
442         if (getLastError() == err_stackbottom) {
443            sw_printf("[%s:%u] - Reached bottom of stack\n", FILE__, __LINE__);
444            clearLastError();
445            result = true;
446            goto done;
447         }
448         sw_printf("[%s:%u] - Error walking through stack frame %s\n",
449                   FILE__, __LINE__, getLastErrorMsg());
450         result = false;
451         goto done;
452      }
453      stackwalk.back().next_stepper = cur_frame.getStepper();
454      int cur_capa = stackwalk.capacity();
455      stackwalk.push_back(cur_frame);     
456      if (cur_capa != stackwalk.capacity()) {
457          // If the stackwalk vector reallocates memory,
458          // all prev_frame points become invalid.
459          // So, we need to update them.
460          for (int i = 1; i < stackwalk.size(); ++i) {
461              stackwalk[i].prev_frame = &(stackwalk[i - 1]);
462          }
463      }
464    }
465
466  done:
467    bool postresult = callPostStackwalk();
468    if (!postresult) {
469       sw_printf("[%s:%u] - Call to postStackwalk failed\n", FILE__, __LINE__);
470       return false;
471    }
472
473    for (std::vector<Frame>::iterator swi = stackwalk.begin();
474         swi != stackwalk.end();
475         ++swi)
476    {
477      swi->prev_frame = NULL;
478    }
479
480    sw_printf("[%s:%u] - Finished walking callstack from frame, result = %s\n",
481              FILE__, __LINE__, result ? "true" : "false");
482
483    return result;
484 }
485
486 bool Walker::walkSingleFrame(const Frame &in, Frame &out)
487 {
488    gcframe_ret_t gcf_result;
489    bool result;
490    Frame last_frame = in;
491
492    sw_printf("[%s:%u] - Attempting to walk through frame with RA 0x%lx\n",
493              FILE__, __LINE__, last_frame.getRA());
494
495    result = callPreStackwalk();
496    if (!result) {
497       sw_printf("[%s:%u] - Call to preStackwalk failed, exiting from stackwalk\n",
498                 FILE__, __LINE__);
499       return false;
500    }
501
502    if (!group) {
503       setLastError(err_nogroup, "Attempt to walk a stack without a StepperGroup");
504       return false;
505    }
506
507    out.prev_frame = &in;
508
509    FrameStepper *last_stepper = NULL;
510    for (;;)
511    {
512      FrameStepper *cur_stepper = NULL;
513      bool res = group->findStepperForAddr(last_frame.getRA(), cur_stepper,
514                                           last_stepper);
515      if (!res) {
516         sw_printf("[%s:%u] - Unable to find a framestepper for %lx\n",
517                   FILE__, __LINE__, last_frame.getRA());
518         result = false;
519         goto done;
520      }
521      sw_printf("[%s:%u] - Attempting to use stepper %s\n",
522                FILE__, __LINE__, cur_stepper->getName());
523      gcf_result = cur_stepper->getCallerFrame(in, out);
524      if (gcf_result == gcf_success) {
525        sw_printf("[%s:%u] - Success using stepper %s on 0x%lx\n",
526                  FILE__, __LINE__, cur_stepper->getName(), in.getRA());
527        if (!checkValidFrame(in, out)) {
528           sw_printf("[%s:%u] - Resulting frame is not valid\n", FILE__, __LINE__);
529           result = false;
530           goto done;
531        }
532        sw_printf("[%s:%u] - Returning frame with RA %lx, SP %lx, FP %lx\n",
533                  FILE__, __LINE__, out.getRA(), out.getSP(), out.getFP());
534        out.setStepper(cur_stepper);
535        result = true;
536        goto done;
537      }
538      else if (gcf_result == gcf_not_me) {
539        last_stepper = cur_stepper;
540        sw_printf("[%s:%u] - Stepper %s declined address 0x%lx\n",
541                  FILE__, __LINE__, cur_stepper->getName(), in.getRA());
542        continue;
543      }
544      else if (gcf_result == gcf_stackbottom) {
545         sw_printf("[%s:%u] - Stepper %s bottomed out on 0x%lx\n",
546                   FILE__, __LINE__, cur_stepper->getName(), in.getRA());
547        setLastError(err_stackbottom, "walkSingleFrame reached bottom of stack");
548        result = false;
549        goto done;
550      }
551      else if (gcf_result == gcf_error) {
552         sw_printf("[%s:%u] - A stepper reported error %d on frame at %lx\n",
553                   FILE__, __LINE__, cur_stepper, in.getRA());
554        result = false;
555        goto done;
556      }
557    }
558
559  done:
560    out.setThread(in.getThread());
561    bool postresult = callPostStackwalk();
562    if (!postresult) {
563       sw_printf("[%s:%u] - Call to postStackwalk failed\n", FILE__, __LINE__);
564       return false;
565    }
566
567    return result;
568 }
569
570 bool Walker::getInitialFrame(Frame &frame, THR_ID thread) {
571    bool result;
572    frame.walker = this;
573    result = callPreStackwalk(thread);
574    if (!result) {
575       sw_printf("[%s:%u] - Call to preStackwalk failed, exiting from stackwalk\n",
576                 FILE__, __LINE__);
577       return false;
578    }
579
580    getInitialFrameImpl(frame, thread);
581    if (!result) {
582       sw_printf("[%s:%u] - getInitialFrameImpl failed\n",
583                 FILE__, __LINE__, (int) thread);
584    }
585    bool postresult = callPostStackwalk(thread);
586    if (!postresult) {
587       sw_printf("[%s:%u] - Call to postStackwalk failed\n", FILE__, __LINE__);
588       return false;
589    }
590
591    return result;
592 }
593
594
595 bool Walker::getAvailableThreads(std::vector<THR_ID> &threads) const {
596    threads.clear();
597    bool result = proc->getThreadIds(threads);
598    if (dyn_debug_stackwalk) {
599       if (!result) {
600          sw_printf("[%s:%u] - getThreadIds error\n", FILE__, __LINE__);
601       }
602       else {
603          sw_printf("[%s:%u] - getThreadIds returning %d values:\t\n",
604                    FILE__, __LINE__, threads.size());
605          for (unsigned i=0; i<threads.size(); i++) {
606             sw_printf("%d ", (int) threads[i]);
607          }
608          sw_printf("\n ");
609       }
610    }
611    return result;
612 }
613
614 ProcessState *Walker::getProcessState() const {
615    return proc;
616 }
617
618 SymbolLookup *Walker::getSymbolLookup() const {
619    return lookup;
620 }
621
622 ProcessState *Walker::createDefaultProcess(std::string exec_name)
623 {
624    ProcSelf *pself = new ProcSelf(exec_name);
625    pself->initialize();
626    return pself;
627 }
628
629 ProcessState *Walker::createDefaultProcess(PID pid, std::string executable)
630 {
631    ProcDebug *pdebug = ProcDebug::newProcDebug(pid, executable);
632    return pdebug;
633 }
634
635 ProcessState *Walker::createDefaultProcess(Dyninst::ProcControlAPI::Process::ptr proc)
636 {
637    ProcDebug *pdebug = ProcDebug::newProcDebug(proc);
638    return pdebug;
639 }
640
641 bool Walker::createDefaultProcess(const vector<Dyninst::PID> &pids,
642                                   vector<ProcDebug *> &pds)
643 {
644    return ProcDebug::newProcDebugSet(pids, pds);
645 }
646
647 ProcessState *Walker::createDefaultProcess(std::string exec_name,
648                                            const std::vector<std::string> &argv)
649 {
650    ProcDebug *pdebug = ProcDebug::newProcDebug(exec_name, argv);
651    return pdebug;
652 }
653
654 bool Walker::addStepper(FrameStepper *s)
655 {
656    assert(group);
657    sw_printf("[%s:%u] - Registering stepper %s with group %p\n",
658              FILE__, __LINE__, s->getName(), group);
659    group->registerStepper(s);
660    return true;
661 }
662
663 bool Walker::callPreStackwalk(Dyninst::THR_ID tid)
664 {
665    call_count++;
666    if (call_count != 1)
667       return true;
668
669    return getProcessState()->preStackwalk(tid);
670 }
671
672 bool Walker::callPostStackwalk(Dyninst::THR_ID tid)
673 {
674    call_count--;
675
676    if (call_count != 0)
677       return true;
678
679    return getProcessState()->postStackwalk(tid);
680 }
681
682 StepperGroup *Walker::createDefaultStepperGroup()
683 {
684    return new AddrRangeGroup(this);
685 }
686
687 StepperGroup *Walker::getStepperGroup() const
688 {
689    return group;
690 }
691
692 int_walkerSet::int_walkerSet() :
693    non_pd_walkers(0)
694 {
695    initProcSet();
696 }
697
698 int_walkerSet::~int_walkerSet()
699 {
700    clearProcSet();
701 }
702
703 pair<set<Walker *>::iterator, bool> int_walkerSet::insert(Walker *w)
704 {
705    ProcDebug *pd = dynamic_cast<ProcDebug *>(w->getProcessState());
706    if (!pd) {
707       non_pd_walkers++;
708    }
709    else {
710       addToProcSet(pd);
711    }
712
713    return walkers.insert(w);
714 }
715
716 void int_walkerSet::erase(set<Walker *>::iterator i)
717 {
718    ProcDebug *pd = dynamic_cast<ProcDebug *>((*i)->getProcessState());
719    if (!pd) {
720       non_pd_walkers--;
721    }
722    else {
723       eraseFromProcSet(pd);
724    }
725
726    walkers.erase(i);
727 }
728
729 WalkerSet *WalkerSet::newWalkerSet()
730 {
731    return new WalkerSet();
732 }
733
734 WalkerSet::WalkerSet() :
735    iwalkerset(new int_walkerSet())
736 {
737 }
738
739 WalkerSet::~WalkerSet()
740 {
741    delete iwalkerset;
742 }
743
744 WalkerSet::iterator WalkerSet::begin() {
745    return iwalkerset->walkers.begin();
746 }
747
748 WalkerSet::iterator WalkerSet::end() {
749    return iwalkerset->walkers.end();
750 }
751
752 WalkerSet::iterator WalkerSet::find(Walker *w) {
753    return iwalkerset->walkers.find(w);
754 }
755
756 WalkerSet::const_iterator WalkerSet::begin() const {
757    return ((const int_walkerSet *) iwalkerset)->walkers.begin();
758 }
759
760 WalkerSet::const_iterator WalkerSet::end() const {
761    return ((const int_walkerSet *) iwalkerset)->walkers.end();
762 }
763
764 WalkerSet::const_iterator WalkerSet::find(Walker *w) const {
765    return ((const int_walkerSet *) iwalkerset)->walkers.find(w);
766 }
767
768 pair<WalkerSet::iterator, bool> WalkerSet::insert(Walker *walker) {
769    return iwalkerset->insert(walker);
770 }
771
772 void WalkerSet::erase(WalkerSet::iterator i) {
773    iwalkerset->erase(i);
774 }
775
776 bool WalkerSet::empty() const {
777    return iwalkerset->walkers.empty();
778 }
779
780 size_t WalkerSet::size() const {
781    return iwalkerset->walkers.size();
782 }
783
784 bool WalkerSet::walkStacks(CallTree &tree, bool walk_initial_only) const {
785    if (empty()) {
786       sw_printf("[%s:%u] - Attempt to walk stacks of empty process set\n", FILE__, __LINE__);
787       return false;
788    }
789    if (!iwalkerset->non_pd_walkers) {
790       bool bad_plat = false;
791       bool result = iwalkerset->walkStacksProcSet(tree, bad_plat, walk_initial_only);
792       if (result) {
793          //Success
794          return true;
795       }
796       if (!bad_plat) {
797          //Error
798          return false;
799       }
800       sw_printf("[%s:%u] - Platform does not have OS supported unwinding\n", FILE__, __LINE__);
801    }
802
803    bool had_error = false;
804    for (const_iterator i = begin(); i != end(); i++) {
805       vector<THR_ID> threads;
806       Walker *walker = *i;
807       bool result = walker->getAvailableThreads(threads);
808       if (!result) {
809          sw_printf("[%s:%u] - Error getting threads for process %d\n", FILE__, __LINE__,
810                    walker->getProcessState()->getProcessId());
811          had_error = true;
812          continue;
813       }
814
815       for (vector<THR_ID>::iterator j = threads.begin(); j != threads.end(); j++) {
816          std::vector<Frame> swalk;
817          THR_ID thr = *j;
818
819          bool result = walker->walkStack(swalk, thr);
820          if (!result && swalk.empty()) {
821             sw_printf("[%s:%u] - Error walking stack for %d/%d\n", FILE__, __LINE__,
822                       walker->getProcessState()->getProcessId(), thr);
823             had_error = true;
824             continue;
825          }
826          tree.addCallStack(swalk, thr, walker, !result);
827
828          if (walk_initial_only) break;
829       }
830    }
831    return !had_error;
832 }