Rename the symbol reader getRegions to getSegments, since the desired return is an...
[dyninst.git] / stackwalk / src / sw_pcontrol.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/procstate.h"
32 #include "stackwalk/h/swk_errors.h"
33 #include "stackwalk/h/walker.h"
34 #include "stackwalk/h/steppergroup.h"
35
36 #include "proccontrol/h/PCProcess.h"
37 #include "proccontrol/h/ProcessSet.h"
38 #include "proccontrol/h/PlatFeatures.h"
39 #include "proccontrol/h/PCErrors.h"
40
41 #include "dynutil/h/dyn_regs.h"
42 #include "dynutil/h/SymReader.h"
43
44 #include "stackwalk/src/libstate.h"
45 #include "stackwalk/src/sw.h"
46
47 #include <vector>
48
49 using namespace Dyninst;
50 using namespace ProcControlAPI;
51 using namespace Stackwalker;
52 using namespace std;
53
54 class PCLibraryState : public LibraryState {
55 private:
56    ProcDebug *pdebug;
57 public:
58    PCLibraryState(ProcessState *pd);
59    ~PCLibraryState();
60
61    bool checkLibraryContains(Address addr, Library::ptr lib);
62    virtual bool getLibraryAtAddr(Address addr, LibAddrPair &lib);
63    virtual bool getLibraries(std::vector<LibAddrPair> &libs);
64    virtual void notifyOfUpdate();
65    virtual Address getLibTrapAddress();
66    virtual bool getAOut(LibAddrPair &ao);
67
68    void checkForNewLib(Library::ptr lib);
69 };
70
71 ProcDebug::ProcDebug(Process::ptr p) :
72    ProcessState(p->getPid()),
73    proc(p)
74 {
75 }
76
77 ProcDebug *ProcDebug::newProcDebug(PID pid, std::string executable)
78 {
79    Process::ptr proc = Process::attachProcess(pid, executable);
80    if (!proc) {
81       Stackwalker::setLastError(err_proccontrol, ProcControlAPI::getLastErrorMsg());
82       sw_printf("[%s:%u] - ProcControl error creating process\n", __FILE__, __LINE__);
83       return NULL;
84    }
85    
86    return newProcDebug(proc);
87 }
88
89 ProcDebug *ProcDebug::newProcDebug(Dyninst::ProcControlAPI::Process::ptr proc)
90 {
91    ProcDebug *pd = new ProcDebug(proc);
92    pd->library_tracker = new PCLibraryState(pd);
93
94    return pd;
95 }
96
97 bool ProcDebug::newProcDebugSet(const std::vector<PID> &pids,
98                                 std::vector<ProcDebug *> & out_set)
99 {
100    for (vector<PID>::const_iterator i = pids.begin(); i != pids.end(); i++) {
101       ProcDebug *pd = ProcDebug::newProcDebug(*i);
102       if (!pd)
103          return false;
104       out_set.push_back(pd);
105    }
106    return true;
107 }
108
109 ProcDebug *ProcDebug::newProcDebug(std::string executable, 
110                                    const std::vector<std::string> &argv)
111 {
112    Process::ptr proc = Process::createProcess(executable, argv);
113    if (!proc) {
114       Stackwalker::setLastError(err_proccontrol, ProcControlAPI::getLastErrorMsg());
115       sw_printf("[%s:%u] - ProcControl error creating process\n", __FILE__, __LINE__);
116       return NULL;
117    }
118
119    ProcDebug *pd = new ProcDebug(proc);
120    pd->library_tracker = new PCLibraryState(pd);
121    
122    return pd;
123 }
124
125 ProcDebug::~ProcDebug()
126 {
127    if (library_tracker)
128       delete library_tracker;
129    library_tracker = NULL;
130 }
131
132 #define CHECK_PROC_LIVE \
133    do { \
134    if (!proc || proc->isTerminated()) { \
135      sw_printf("[%s:%u] - operation on exited process\n", __FILE__, __LINE__); \
136      Stackwalker::setLastError(err_procexit, "Process has exited or been detached"); \
137      return false; \
138    } \
139    } while (0)
140
141 bool ProcDebug::getRegValue(MachRegister reg, THR_ID thread, 
142                             MachRegisterVal &val)
143 {
144    CHECK_PROC_LIVE;
145    if (reg == FrameBase) {
146       reg = MachRegister::getFramePointer(getArchitecture());
147    }
148    else if (reg == ReturnAddr) {
149       reg = MachRegister::getPC(getArchitecture());
150    }
151    else if (reg == StackTop) {
152       reg = MachRegister::getStackPointer(getArchitecture());
153    }
154    ThreadPool::iterator thrd_i = proc->threads().find(thread);
155    if (thrd_i == proc->threads().end()) {
156       sw_printf("[%s:%u] - Invalid thread ID to getRegValue\n", __FILE__, __LINE__);
157       Stackwalker::setLastError(err_badparam, "Invalid thread ID\n");
158       return false;
159    }
160    Thread::ptr thrd = *thrd_i;
161    bool result = thrd->getRegister(reg, val);
162    if (!result) {
163       sw_printf("[%s:%u] - ProcControlAPI error reading register\n", __FILE__, __LINE__);
164       Stackwalker::setLastError(err_proccontrol, ProcControlAPI::getLastErrorMsg());
165    }
166    return result;
167 }
168
169 bool ProcDebug::readMem(void *dest, Address source, size_t size)
170 {
171    CHECK_PROC_LIVE;
172    bool result = proc->readMemory(dest, source, size);
173    if (!result) {
174      sw_printf("[%s:%u] - ProcControlAPI error reading memory at 0x%lx\n", __FILE__, __LINE__, source);
175       Stackwalker::setLastError(err_proccontrol, ProcControlAPI::getLastErrorMsg());
176    }
177    return result;
178 }
179
180 bool ProcDebug::getThreadIds(std::vector<THR_ID> &thrds)
181 {
182    CHECK_PROC_LIVE;
183    ThreadPool::iterator i = proc->threads().begin();
184    for (; i != proc->threads().end(); i++) {
185       thrds.push_back((*i)->getLWP());
186    }
187    return true;
188 }
189
190 bool ProcDebug::getDefaultThread(THR_ID &default_tid)
191 {
192    CHECK_PROC_LIVE;
193    default_tid = proc->threads().getInitialThread()->getLWP();
194    return true;
195 }
196
197 unsigned ProcDebug::getAddressWidth() 
198 {
199    CHECK_PROC_LIVE;
200    return getArchAddressWidth(proc->getArchitecture());
201 }
202
203 bool ProcDebug::preStackwalk(THR_ID tid)
204 {
205    CHECK_PROC_LIVE;
206    if (tid == NULL_THR_ID)
207       getDefaultThread(tid);
208    sw_printf("[%s:%u] - Calling preStackwalk for thread %d\n", __FILE__, __LINE__, tid);
209    
210    ThreadPool::iterator thread_iter = proc->threads().find(tid);
211    if (thread_iter == proc->threads().end()) {
212       sw_printf("[%s:%u] - Stackwalk on non-existant thread\n", __FILE__, __LINE__);
213       Stackwalker::setLastError(err_badparam, "Invalid thread ID\n");
214       return false;     
215    }
216    Thread::ptr active_thread = *thread_iter;
217
218    if (active_thread->isRunning()) {
219       sw_printf("[%s:%u] - Stopping running thread %d\n", __FILE__, __LINE__, tid);
220       bool result = active_thread->stopThread();
221       if (!result) {
222          sw_printf("[%s:%u] - Error stopping thread\n", __FILE__, __LINE__);
223          Stackwalker::setLastError(err_proccontrol, "Could not stop thread for stackwalk\n");
224          return false;
225       }
226       needs_resume.insert(active_thread);
227    }
228    return true;
229 }   
230
231 bool ProcDebug::postStackwalk(THR_ID tid)
232 {
233    CHECK_PROC_LIVE;
234    if (tid == NULL_THR_ID)
235       getDefaultThread(tid);
236    sw_printf("[%s:%u] - Calling postStackwalk for thread %d\n", __FILE__, __LINE__, tid);
237    
238    ThreadPool::iterator thread_iter = proc->threads().find(tid);
239    if (thread_iter == proc->threads().end()) {
240       sw_printf("[%s:%u] - Stackwalk on non-existant thread\n", __FILE__, __LINE__);
241       Stackwalker::setLastError(err_badparam, "Invalid thread ID\n");
242       return false;     
243    }
244    Thread::ptr active_thread = *thread_iter;
245    
246    set<Thread::ptr>::iterator i = needs_resume.find(active_thread);
247    if (i != needs_resume.end()) {
248       sw_printf("[%s:%u] - Resuming thread %d after stackwalk\n", __FILE__, __LINE__, tid);
249       bool result = active_thread->continueThread();
250       if (!result) {
251          sw_printf("[%s:%u] - Error resuming stopped thread %d\n", __FILE__, __LINE__, tid);
252          Stackwalker::setLastError(err_proccontrol, ProcControlAPI::getLastErrorMsg());
253          return false;
254       }
255       needs_resume.erase(i);
256    }
257    return true;
258 }
259   
260 bool ProcDebug::pause(THR_ID tid)
261 {
262    CHECK_PROC_LIVE;
263    if (tid == NULL_THR_ID) {
264       sw_printf("[%s:%u] - Stopping process %d\n", __FILE__, __LINE__, proc->getPid());
265
266       bool result = proc->stopProc();
267       if (!result) {
268          sw_printf("[%s:%u] - Error stopping process %d\n", 
269                    __FILE__, __LINE__, proc->getPid());
270          Stackwalker::setLastError(err_proccontrol, ProcControlAPI::getLastErrorMsg());
271          return false;
272       }
273       return true;
274    }
275
276    ThreadPool::iterator thread_iter = proc->threads().find(tid);
277    if (thread_iter == proc->threads().end()) {
278       sw_printf("[%s:%u] - stop on non-existant thread\n", __FILE__, __LINE__);
279       Stackwalker::setLastError(err_badparam, "Invalid thread ID\n");
280       return false;     
281    }
282    Thread::ptr thread = *thread_iter;
283    sw_printf("[%s:%u] - Stopping thread %d\n", __FILE__, __LINE__, tid);
284
285    if (thread->isStopped()) {
286       sw_printf("[%s:%u] - Thread %d is already stopped\n", __FILE__, __LINE__, tid);
287       return true;
288    }
289
290    bool result = thread->stopThread();
291    if (!result) {
292       sw_printf("[%s:%u] - Error stopping thread %d\n", __FILE__, __LINE__, tid);
293       Stackwalker::setLastError(err_proccontrol, ProcControlAPI::getLastErrorMsg());
294       return false;
295    }
296    
297    return true;
298 }
299
300 bool ProcDebug::resume(THR_ID tid)
301 {
302    CHECK_PROC_LIVE;
303    if (tid == NULL_THR_ID) {
304       sw_printf("[%s:%u] - Running process %d\n", __FILE__, __LINE__, proc->getPid());
305
306       bool result = proc->continueProc();
307       if (!result) {
308          sw_printf("[%s:%u] - Error running process %d\n", 
309                    __FILE__, __LINE__, proc->getPid());
310          Stackwalker::setLastError(err_proccontrol, ProcControlAPI::getLastErrorMsg());
311          return false;
312       }
313       return true;
314    }
315
316    ThreadPool::iterator thread_iter = proc->threads().find(tid);
317    if (thread_iter == proc->threads().end()) {
318       sw_printf("[%s:%u] - continue on non-existant thread\n", __FILE__, __LINE__);
319       Stackwalker::setLastError(err_badparam, "Invalid thread ID\n");
320       return false;     
321    }
322    Thread::ptr thread = *thread_iter;
323    sw_printf("[%s:%u] - Running thread %d\n", __FILE__, __LINE__, tid);
324
325    if (thread->isRunning()) {
326       sw_printf("[%s:%u] - Thread %d is already running\n", __FILE__, __LINE__, tid);
327       return true;
328    }
329
330    bool result = thread->continueThread();
331    if (!result) {
332       sw_printf("[%s:%u] - Error running thread %d\n", __FILE__, __LINE__, tid);
333       Stackwalker::setLastError(err_proccontrol, ProcControlAPI::getLastErrorMsg());
334       return false;
335    }
336    
337    return true;
338 }
339
340 bool ProcDebug::isTerminated()
341 {
342    return (!proc || proc->isTerminated());
343 }
344
345 bool ProcDebug::detach(bool)
346 {
347    CHECK_PROC_LIVE;   
348    bool result = proc->detach();
349    if (!result) {
350       sw_printf("[%s:%u] - Error detaching from process %d\n", __FILE__, __LINE__, 
351                 proc->getPid());
352       Stackwalker::setLastError(err_proccontrol, ProcControlAPI::getLastErrorMsg());
353       return false;
354    }
355    return true;
356 }
357
358 int ProcDebug::getNotificationFD()
359 {
360    return -1;
361 }
362
363 std::string ProcDebug::getExecutablePath()
364 {
365    CHECK_PROC_LIVE;
366    return proc->libraries().getExecutable()->getName();
367 }
368
369 bool ProcDebug::handleDebugEvent(bool block)
370 {
371    bool result = Process::handleEvents(block);
372    if (!result) {
373       sw_printf("[%s:%u] - Error handling debug events\n", __FILE__, __LINE__);
374       Stackwalker::setLastError(err_proccontrol, ProcControlAPI::getLastErrorMsg());
375       return false;
376    }
377    return true;
378 }
379
380 bool ProcDebug::isFirstParty()
381 {
382    return false;
383 }
384
385 Architecture ProcDebug::getArchitecture()
386 {
387    return proc->getArchitecture();
388 }
389
390 Process::ptr ProcDebug::getProc()
391 {
392    return proc;
393 }
394
395 PCLibraryState::PCLibraryState(ProcessState *pd) :
396    LibraryState(pd)
397 {
398    pdebug = static_cast<ProcDebug *>(pd);
399 }
400    
401 PCLibraryState::~PCLibraryState()
402 {
403 }
404  
405 bool PCLibraryState::checkLibraryContains(Address addr, Library::ptr lib)
406 {
407    std::string filename = lib->getName();
408    Address base = lib->getLoadAddress();
409
410    SymbolReaderFactory *fact = Walker::getSymbolReader();
411    SymReader *reader = fact->openSymbolReader(filename);
412    if (!reader) {
413       sw_printf("[%s:%u] - Error could not open expected file %s\n", 
414                 __FILE__, __LINE__, filename.c_str());
415       return false;
416    }
417
418    int num_regions = reader->numSegments();
419    for (int i=0; i<num_regions; i++) {
420       SymSegment region;
421       reader->getSegment(i, region);
422       Address region_start = region.mem_addr + base;
423       Address region_end = region_start + region.mem_size;
424       if (region_start <= addr && region_end > addr) 
425          return true;
426    }
427    return false;
428 }
429
430 void PCLibraryState::checkForNewLib(Library::ptr lib)
431 {
432    
433    if (lib->getData())
434       return;
435    sw_printf("[%s:%u] - Detected new library %s at %lx, notifying\n",
436              __FILE__, __LINE__, lib->getName().c_str(), lib->getLoadAddress());
437    
438    lib->setData((void *) 0x1);
439    StepperGroup *group = pdebug->getWalker()->getStepperGroup();
440    LibAddrPair la(lib->getName(), lib->getLoadAddress());
441    group->newLibraryNotification(&la, library_load);
442 }
443 /*
444 For a given address, 'addr', PCLibraryState::getLibraryAtAddr returns
445 the name and load address of the library/executable that loaded over
446 'addr'.
447
448 Traditionally when searching for the library that contains an address,
449 we would sequentially open each library, read its program headers and
450 see if that library contained the address.  This caused at-scale
451 performance problems on apps with lots of libraries, as we turned up
452 opening a lot of unnecessary files.
453
454 This function tries to be smarter.  It identifies the libraries that
455 most likely to contain our address, and then targets opens at them.
456 We do this by getting the dynamic address for each library (a pointer
457 given by the link map).  The dynamic address points to the library's
458 DYNAMIC section, which must be loaded into memory as specified by the
459 System V ABI.  We expect that the library containing addr will have a
460 nearby DYNAMIC pointer, and we check the two libraries with a DYNAMIC
461 pointer above and below addr.  One of these libraries should contain
462 addr.
463
464 If, for some reason, we fail to get a DYNAMIC section then we'll stash
465 that library away in 'zero_dynamic_libs' and check it when done.
466 */ 
467 bool PCLibraryState::getLibraryAtAddr(Address addr, LibAddrPair &lib)
468 {
469    Process::ptr proc = pdebug->getProc();
470    CHECK_PROC_LIVE;
471    
472    LibraryPool::iterator i;
473    Library::ptr nearest_predecessor = Library::ptr();
474    signed int pred_distance = 0;
475    Library::ptr nearest_successor = Library::ptr();
476    signed int succ_distance = 0;
477
478    vector<pair<LibAddrPair, unsigned int> > arch_libs;
479    updateLibsArch(arch_libs);
480    vector<pair<LibAddrPair, unsigned int> >::iterator j;
481    for (j = arch_libs.begin(); j != arch_libs.end(); j++) {
482       string name = (*j).first.first;
483       Address start = (*j).first.second;
484       Address size = (*j).second;
485       if (addr >= start && addr < start + size) {
486          lib.first = name;
487          lib.second = start;
488          return true;
489       }
490    }
491
492    std::vector<Library::ptr> zero_dynamic_libs;
493    for (i = proc->libraries().begin(); i != proc->libraries().end(); i++)
494    {
495       Library::ptr slib = *i;
496       checkForNewLib(slib);
497
498       Address dyn_addr = slib->getDynamicAddress();
499       if (!dyn_addr) {
500          zero_dynamic_libs.push_back(slib);
501          continue;
502       }
503
504       signed int distance = addr - dyn_addr;
505       if (distance == 0) {
506          lib.first = slib->getName();
507          lib.second = slib->getLoadAddress();
508          sw_printf("[%s:%u] - Found library %s contains address %lx\n",
509                    __FILE__, __LINE__, lib.first.c_str(), addr);
510          return true;
511       }
512       else if (distance < 0) {
513          if (!pred_distance || pred_distance < distance) {
514             nearest_predecessor = slib;
515             pred_distance = distance;
516          }
517       }
518       else if (distance > 0) {
519          if (!succ_distance || succ_distance > distance) {
520             nearest_successor = slib;
521             succ_distance = distance;
522          }
523       }
524    }
525
526    if (!nearest_predecessor && !nearest_successor) {
527       //Likely a static binary, set nearest_predecessor so that
528       // the following check will test it.
529       nearest_predecessor = proc->libraries().getExecutable();
530    }
531
532    if (nearest_predecessor && checkLibraryContains(addr, nearest_predecessor)) {
533       lib.first = nearest_predecessor->getName();
534       lib.second = nearest_predecessor->getLoadAddress();
535       sw_printf("[%s:%u] - Found library %s contains address %lx\n",
536                 __FILE__, __LINE__, lib.first.c_str(), addr);
537       return true;
538    }
539    if (nearest_successor && checkLibraryContains(addr, nearest_successor)) {
540       lib.first = nearest_successor->getName();
541       lib.second = nearest_successor->getLoadAddress();
542       sw_printf("[%s:%u] - Found library %s contains address %lx\n",
543                 __FILE__, __LINE__, lib.first.c_str(), addr);
544       return true;
545    }
546
547    std::vector<Library::ptr>::iterator k = zero_dynamic_libs.begin();
548    for (; k != zero_dynamic_libs.end(); k++) {
549       if (checkLibraryContains(addr, *k)) {
550          lib.first = (*k)->getName();
551          lib.second = (*k)->getLoadAddress();
552          return true;
553       }
554    }
555    if(checkLibraryContains(addr, proc->libraries().getExecutable()))
556    {
557      
558      lib.first = proc->libraries().getExecutable()->getName();
559      lib.second = proc->libraries().getExecutable()->getLoadAddress();
560      sw_printf("[%s:%u] - Found executable %s contains address %lx\n", __FILE__,
561                __LINE__, lib.first.c_str(), addr);
562      return true;
563    }
564    
565    sw_printf("[%s:%u] - Could not find library for addr %lx\n", 
566              __FILE__, __LINE__, addr);
567    return false;
568 }
569
570 bool PCLibraryState::getLibraries(std::vector<LibAddrPair> &libs)
571 {
572    Process::ptr proc = pdebug->getProc();
573    CHECK_PROC_LIVE;
574
575    LibraryPool::iterator i;   
576    for (i = proc->libraries().begin(); i != proc->libraries().end(); i++)
577    {
578       checkForNewLib(*i);
579       libs.push_back(LibAddrPair((*i)->getName(), (*i)->getLoadAddress()));
580    }
581
582    vector<pair<LibAddrPair, unsigned int> > arch_libs;
583    vector<pair<LibAddrPair, unsigned int> >::iterator j;
584    updateLibsArch(arch_libs);
585    for (j = arch_libs.begin(); j != arch_libs.end(); j++) {
586       libs.push_back(j->first);
587    }
588
589    return true;
590 }
591
592 void PCLibraryState::notifyOfUpdate()
593 {
594 }
595
596 Address PCLibraryState::getLibTrapAddress()
597 {
598    return 0;
599 }
600
601 bool PCLibraryState::getAOut(LibAddrPair &ao)
602 {
603    Process::ptr proc = pdebug->getProc();
604    CHECK_PROC_LIVE;
605
606    Library::ptr lib = proc->libraries().getExecutable();
607    if (!lib) {
608       sw_printf("[%s:%u] - Could not get executable\n", __FILE__, __LINE__);
609       return false;
610    }
611    ao = LibAddrPair(lib->getName(), lib->getLoadAddress());
612    return true;
613 }
614
615 void int_walkerSet::addToProcSet(ProcDebug *pd)
616 {
617    ProcessSet::ptr &pset = *((ProcessSet::ptr *) procset);
618    Process::ptr proc = pd->getProc();
619    pset->insert(proc);
620 }
621
622 void int_walkerSet::eraseFromProcSet(ProcDebug *pd)
623 {
624    ProcessSet::ptr &pset = *((ProcessSet::ptr *) procset);
625    Process::ptr proc = pd->getProc();
626
627    ProcessSet::iterator i = pset->find(proc);
628    assert(i != pset->end());
629    pset->erase(i);
630 }
631
632 void int_walkerSet::clearProcSet()
633 {
634    ProcessSet::ptr *pset = (ProcessSet::ptr *) procset;
635    (*pset)->clear();
636    delete pset;
637    procset = NULL;
638 }
639
640 void int_walkerSet::initProcSet()
641 {
642    ProcessSet::ptr *p = new ProcessSet::ptr();
643    *p = ProcessSet::newProcessSet();
644    procset = (void *) p;
645 }
646
647 class StackCallback : public Dyninst::ProcControlAPI::CallStackCallback
648 {
649 private:
650    CallTree &tree;
651    FrameNode *cur;
652    Walker *cur_walker;
653 public:
654    StackCallback(CallTree &t);
655    virtual ~StackCallback();
656    
657    virtual bool beginStackWalk(Thread::ptr thr);
658    virtual bool addStackFrame(Thread::ptr thr, Dyninst::Address ra, Dyninst::Address sp, Dyninst::Address fp);
659    virtual void endStackWalk(Thread::ptr thr);
660 };
661
662 StackCallback::StackCallback(CallTree &t) :
663    tree(t),
664    cur(NULL)
665 {
666    top_first = true;
667 }
668
669 StackCallback::~StackCallback()
670 {
671 }
672
673 bool StackCallback::beginStackWalk(Thread::ptr thr)
674 {
675    assert(!cur);
676    Process::ptr proc = thr->getProcess();
677    ProcessState *pstate = ProcessState::getProcessStateByPid(proc->getPid());
678    if (!pstate) {
679       sw_printf("[%s:%u] - Error, unknown process state for %d while starting stackwalk\n", 
680                 __FILE__, __LINE__, proc->getPid());
681       return false;
682    }
683
684    cur_walker = pstate->getWalker();
685    cur = tree.getHead();
686
687    return true;
688 }
689
690 bool StackCallback::addStackFrame(Thread::ptr thr,
691                                   Dyninst::Address ra, Dyninst::Address sp, Dyninst::Address fp)
692 {
693    Frame f(cur_walker);
694    f.setRA(ra);
695    f.setSP(sp);
696    f.setFP(fp);
697    f.setThread(thr->getLWP());
698    
699    cur = tree.addFrame(f, cur);
700    return true;
701 }
702
703 void StackCallback::endStackWalk(Thread::ptr thr) {
704    THR_ID thrd_lwp = thr->getLWP();
705    Frame *last_frame = cur->getFrame();
706    if (last_frame) {
707       last_frame->markTopFrame();
708    }
709    tree.addThread(thrd_lwp, cur, cur_walker, false);
710    cur = NULL;
711    cur_walker = NULL;
712 }
713
714 bool int_walkerSet::walkStacksProcSet(CallTree &tree, bool &bad_plat)
715 {
716    ProcessSet::ptr &pset = *((ProcessSet::ptr *) procset);
717    ThreadSet::ptr all_threads = ThreadSet::newThreadSet(pset);
718    StackCallback cbs(tree);
719
720    if (!all_threads->getCallStackUnwinding()) {
721       bad_plat = true;
722       return false;
723    }
724    return all_threads->getCallStackUnwinding()->walkStack(&cbs);
725 }