Make stackwalker optimizations BG/Q friendly by avoiding unnecessary file opens.
[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 #include "common/h/IntervalTree.h"
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
58    typedef std::pair<LibAddrPair, Library::ptr> cache_t;
59
60    IntervalTree<Address, cache_t> loadedLibs;
61
62    cache_t makeCache(LibAddrPair a, Library::ptr b) { return std::make_pair(a, b); }
63    bool findInCache(Process::ptr proc, Address addr, LibAddrPair &lib);
64    void removeLibFromCache(cache_t element);
65
66 public:
67    PCLibraryState(ProcessState *pd);
68    ~PCLibraryState();
69
70    bool checkLibraryContains(Address addr, Library::ptr lib);
71    virtual bool getLibraryAtAddr(Address addr, LibAddrPair &lib);
72    virtual bool getLibraries(std::vector<LibAddrPair> &libs);
73    virtual void notifyOfUpdate();
74    virtual Address getLibTrapAddress();
75    virtual bool getAOut(LibAddrPair &ao);
76   
77    bool updateLibraries();
78    bool cacheLibraryRanges(Library::ptr lib);
79    bool memoryScan(Process::ptr proc, Address addr, LibAddrPair &lib);
80
81    void checkForNewLib(Library::ptr lib);
82 };
83
84 ProcDebug::ProcDebug(Process::ptr p) :
85    ProcessState(p->getPid()),
86    proc(p)
87 {
88 }
89
90 ProcDebug *ProcDebug::newProcDebug(PID pid, std::string executable)
91 {
92    Process::ptr proc = Process::attachProcess(pid, executable);
93    if (!proc) {
94       Stackwalker::setLastError(err_proccontrol, ProcControlAPI::getLastErrorMsg());
95       sw_printf("[%s:%u] - ProcControl error creating process\n", __FILE__, __LINE__);
96       return NULL;
97    }
98    
99    return newProcDebug(proc);
100 }
101
102 ProcDebug *ProcDebug::newProcDebug(Dyninst::ProcControlAPI::Process::ptr proc)
103 {
104    ProcDebug *pd = new ProcDebug(proc);
105    pd->library_tracker = new PCLibraryState(pd);
106
107    return pd;
108 }
109
110 bool ProcDebug::newProcDebugSet(const std::vector<PID> &pids,
111                                 std::vector<ProcDebug *> & out_set)
112 {
113    for (vector<PID>::const_iterator i = pids.begin(); i != pids.end(); i++) {
114       ProcDebug *pd = ProcDebug::newProcDebug(*i);
115       if (!pd)
116          return false;
117       out_set.push_back(pd);
118    }
119    return true;
120 }
121
122 ProcDebug *ProcDebug::newProcDebug(std::string executable, 
123                                    const std::vector<std::string> &argv)
124 {
125    Process::ptr proc = Process::createProcess(executable, argv);
126    if (!proc) {
127       Stackwalker::setLastError(err_proccontrol, ProcControlAPI::getLastErrorMsg());
128       sw_printf("[%s:%u] - ProcControl error creating process\n", __FILE__, __LINE__);
129       return NULL;
130    }
131
132    ProcDebug *pd = new ProcDebug(proc);
133    pd->library_tracker = new PCLibraryState(pd);
134    
135    return pd;
136 }
137
138 ProcDebug::~ProcDebug()
139 {
140    if (library_tracker)
141       delete library_tracker;
142    library_tracker = NULL;
143 }
144
145 #define CHECK_PROC_LIVE \
146    do { \
147    if (!proc || proc->isTerminated()) { \
148      sw_printf("[%s:%u] - operation on exited process\n", __FILE__, __LINE__); \
149      Stackwalker::setLastError(err_procexit, "Process has exited or been detached"); \
150      return false; \
151    } \
152    } while (0)
153
154 bool ProcDebug::getRegValue(MachRegister reg, THR_ID thread, 
155                             MachRegisterVal &val)
156 {
157    CHECK_PROC_LIVE;
158    if (reg == FrameBase) {
159       reg = MachRegister::getFramePointer(getArchitecture());
160    }
161    else if (reg == ReturnAddr) {
162       reg = MachRegister::getPC(getArchitecture());
163    }
164    else if (reg == StackTop) {
165       reg = MachRegister::getStackPointer(getArchitecture());
166    }
167    ThreadPool::iterator thrd_i = proc->threads().find(thread);
168    if (thrd_i == proc->threads().end()) {
169       sw_printf("[%s:%u] - Invalid thread ID to getRegValue\n", __FILE__, __LINE__);
170       Stackwalker::setLastError(err_badparam, "Invalid thread ID\n");
171       return false;
172    }
173    Thread::ptr thrd = *thrd_i;
174    bool result = thrd->getRegister(reg, val);
175    if (!result) {
176       sw_printf("[%s:%u] - ProcControlAPI error reading register\n", __FILE__, __LINE__);
177       Stackwalker::setLastError(err_proccontrol, ProcControlAPI::getLastErrorMsg());
178    }
179    return result;
180 }
181
182 bool ProcDebug::readMem(void *dest, Address source, size_t size)
183 {
184    CHECK_PROC_LIVE;
185    bool result = proc->readMemory(dest, source, size);
186    if (!result) {
187      sw_printf("[%s:%u] - ProcControlAPI error reading memory at 0x%lx\n", __FILE__, __LINE__, source);
188       Stackwalker::setLastError(err_proccontrol, ProcControlAPI::getLastErrorMsg());
189    }
190    return result;
191 }
192
193 bool ProcDebug::getThreadIds(std::vector<THR_ID> &thrds)
194 {
195    CHECK_PROC_LIVE;
196    ThreadPool::iterator i = proc->threads().begin();
197    for (; i != proc->threads().end(); i++) {
198       thrds.push_back((*i)->getLWP());
199    }
200    return true;
201 }
202
203 bool ProcDebug::getDefaultThread(THR_ID &default_tid)
204 {
205    CHECK_PROC_LIVE;
206    default_tid = proc->threads().getInitialThread()->getLWP();
207    return true;
208 }
209
210 unsigned ProcDebug::getAddressWidth() 
211 {
212    CHECK_PROC_LIVE;
213    return getArchAddressWidth(proc->getArchitecture());
214 }
215
216 bool ProcDebug::preStackwalk(THR_ID tid)
217 {
218    CHECK_PROC_LIVE;
219    if (tid == NULL_THR_ID)
220       getDefaultThread(tid);
221    sw_printf("[%s:%u] - Calling preStackwalk for thread %d\n", __FILE__, __LINE__, tid);
222    
223    ThreadPool::iterator thread_iter = proc->threads().find(tid);
224    if (thread_iter == proc->threads().end()) {
225       sw_printf("[%s:%u] - Stackwalk on non-existant thread\n", __FILE__, __LINE__);
226       Stackwalker::setLastError(err_badparam, "Invalid thread ID\n");
227       return false;     
228    }
229    Thread::ptr active_thread = *thread_iter;
230
231    if (active_thread->isRunning()) {
232       sw_printf("[%s:%u] - Stopping running thread %d\n", __FILE__, __LINE__, tid);
233       bool result = active_thread->stopThread();
234       if (!result) {
235          sw_printf("[%s:%u] - Error stopping thread\n", __FILE__, __LINE__);
236          Stackwalker::setLastError(err_proccontrol, "Could not stop thread for stackwalk\n");
237          return false;
238       }
239       needs_resume.insert(active_thread);
240    }
241    return true;
242 }   
243
244 bool ProcDebug::postStackwalk(THR_ID tid)
245 {
246    CHECK_PROC_LIVE;
247    if (tid == NULL_THR_ID)
248       getDefaultThread(tid);
249    sw_printf("[%s:%u] - Calling postStackwalk for thread %d\n", __FILE__, __LINE__, tid);
250    
251    ThreadPool::iterator thread_iter = proc->threads().find(tid);
252    if (thread_iter == proc->threads().end()) {
253       sw_printf("[%s:%u] - Stackwalk on non-existant thread\n", __FILE__, __LINE__);
254       Stackwalker::setLastError(err_badparam, "Invalid thread ID\n");
255       return false;     
256    }
257    Thread::ptr active_thread = *thread_iter;
258    
259    set<Thread::ptr>::iterator i = needs_resume.find(active_thread);
260    if (i != needs_resume.end()) {
261       sw_printf("[%s:%u] - Resuming thread %d after stackwalk\n", __FILE__, __LINE__, tid);
262       bool result = active_thread->continueThread();
263       if (!result) {
264          sw_printf("[%s:%u] - Error resuming stopped thread %d\n", __FILE__, __LINE__, tid);
265          Stackwalker::setLastError(err_proccontrol, ProcControlAPI::getLastErrorMsg());
266          return false;
267       }
268       needs_resume.erase(i);
269    }
270    return true;
271 }
272   
273 bool ProcDebug::pause(THR_ID tid)
274 {
275    CHECK_PROC_LIVE;
276    if (tid == NULL_THR_ID) {
277       sw_printf("[%s:%u] - Stopping process %d\n", __FILE__, __LINE__, proc->getPid());
278
279       bool result = proc->stopProc();
280       if (!result) {
281          sw_printf("[%s:%u] - Error stopping process %d\n", 
282                    __FILE__, __LINE__, proc->getPid());
283          Stackwalker::setLastError(err_proccontrol, ProcControlAPI::getLastErrorMsg());
284          return false;
285       }
286       return true;
287    }
288
289    ThreadPool::iterator thread_iter = proc->threads().find(tid);
290    if (thread_iter == proc->threads().end()) {
291       sw_printf("[%s:%u] - stop on non-existant thread\n", __FILE__, __LINE__);
292       Stackwalker::setLastError(err_badparam, "Invalid thread ID\n");
293       return false;     
294    }
295    Thread::ptr thread = *thread_iter;
296    sw_printf("[%s:%u] - Stopping thread %d\n", __FILE__, __LINE__, tid);
297
298    if (thread->isStopped()) {
299       sw_printf("[%s:%u] - Thread %d is already stopped\n", __FILE__, __LINE__, tid);
300       return true;
301    }
302
303    bool result = thread->stopThread();
304    if (!result) {
305       sw_printf("[%s:%u] - Error stopping thread %d\n", __FILE__, __LINE__, tid);
306       Stackwalker::setLastError(err_proccontrol, ProcControlAPI::getLastErrorMsg());
307       return false;
308    }
309    
310    return true;
311 }
312
313 bool ProcDebug::resume(THR_ID tid)
314 {
315    CHECK_PROC_LIVE;
316    if (tid == NULL_THR_ID) {
317       sw_printf("[%s:%u] - Running process %d\n", __FILE__, __LINE__, proc->getPid());
318
319       bool result = proc->continueProc();
320       if (!result) {
321          sw_printf("[%s:%u] - Error running process %d\n", 
322                    __FILE__, __LINE__, proc->getPid());
323          Stackwalker::setLastError(err_proccontrol, ProcControlAPI::getLastErrorMsg());
324          return false;
325       }
326       return true;
327    }
328
329    ThreadPool::iterator thread_iter = proc->threads().find(tid);
330    if (thread_iter == proc->threads().end()) {
331       sw_printf("[%s:%u] - continue on non-existant thread\n", __FILE__, __LINE__);
332       Stackwalker::setLastError(err_badparam, "Invalid thread ID\n");
333       return false;     
334    }
335    Thread::ptr thread = *thread_iter;
336    sw_printf("[%s:%u] - Running thread %d\n", __FILE__, __LINE__, tid);
337
338    if (thread->isRunning()) {
339       sw_printf("[%s:%u] - Thread %d is already running\n", __FILE__, __LINE__, tid);
340       return true;
341    }
342
343    bool result = thread->continueThread();
344    if (!result) {
345       sw_printf("[%s:%u] - Error running thread %d\n", __FILE__, __LINE__, tid);
346       Stackwalker::setLastError(err_proccontrol, ProcControlAPI::getLastErrorMsg());
347       return false;
348    }
349    
350    return true;
351 }
352
353 bool ProcDebug::isTerminated()
354 {
355    return (!proc || proc->isTerminated());
356 }
357
358 bool ProcDebug::detach(bool leave_stopped)
359 {
360    CHECK_PROC_LIVE;   
361    bool result = proc->detach(leave_stopped);
362    if (!result) {
363       sw_printf("[%s:%u] - Error detaching from process %d\n", __FILE__, __LINE__, 
364                 proc->getPid());
365       Stackwalker::setLastError(err_proccontrol, ProcControlAPI::getLastErrorMsg());
366       return false;
367    }
368    return true;
369 }
370
371 int ProcDebug::getNotificationFD()
372 {
373    return -1;
374 }
375
376 std::string ProcDebug::getExecutablePath()
377 {
378    CHECK_PROC_LIVE;
379    return proc->libraries().getExecutable()->getName();
380 }
381
382 bool ProcDebug::handleDebugEvent(bool block)
383 {
384    bool result = Process::handleEvents(block);
385    if (!result) {
386       sw_printf("[%s:%u] - Error handling debug events\n", __FILE__, __LINE__);
387       Stackwalker::setLastError(err_proccontrol, ProcControlAPI::getLastErrorMsg());
388       return false;
389    }
390    return true;
391 }
392
393 bool ProcDebug::isFirstParty()
394 {
395    return false;
396 }
397
398 Architecture ProcDebug::getArchitecture()
399 {
400    return proc->getArchitecture();
401 }
402
403 Process::ptr ProcDebug::getProc()
404 {
405    return proc;
406 }
407
408 PCLibraryState::PCLibraryState(ProcessState *pd) :
409    LibraryState(pd)
410 {
411    pdebug = static_cast<ProcDebug *>(pd);
412 }
413    
414 PCLibraryState::~PCLibraryState()
415 {
416 }
417  
418 bool PCLibraryState::cacheLibraryRanges(Library::ptr lib)
419 {
420    std::string filename = lib->getName();
421    Address base = lib->getLoadAddress();
422
423    SymbolReaderFactory *fact = getDefaultSymbolReader();
424    SymReader *reader = fact->openSymbolReader(filename);
425    if (!reader) {
426       sw_printf("[%s:%u] - Error could not open expected file %s\n", 
427                 __FILE__, __LINE__, filename.c_str());
428       return false;
429    }
430
431    int num_segments = reader->numSegments();
432    for (int i=0; i<num_segments; i++) {
433       SymSegment segment;
434       reader->getSegment(i, segment);
435       if (segment.type != 1) continue;
436       Address segment_start = segment.mem_addr + base;
437       Address segment_end = segment_start + segment.mem_size;
438
439       loadedLibs.insert(segment_start, segment_end, 
440                         makeCache(LibAddrPair(lib->getName(), 
441                                               lib->getLoadAddress()), 
442                                   lib));
443    }
444    return true;
445 }
446
447 bool PCLibraryState::findInCache(Process::ptr proc, Address addr, LibAddrPair &lib) {
448    cache_t tmp;
449
450    if (!loadedLibs.find(addr, tmp)) { 
451       return false;
452    }   
453
454    Library::ptr lib_ptr = tmp.second;
455    if (proc->libraries().find(lib_ptr) != proc->libraries().end()) {
456       lib = tmp.first;
457       return true;
458    }
459    removeLibFromCache(tmp);
460    
461    return false;
462 }
463
464 void PCLibraryState::removeLibFromCache(cache_t element) {
465    IntervalTree<Address, cache_t>::iterator iter = loadedLibs.begin();
466
467    while(iter != loadedLibs.end()) {
468       // Can't use a for loop because I need to fiddle with
469       // increments manually.
470       cache_t found = iter->second.second;
471       if (found == element) {
472          IntervalTree<Address, cache_t>::iterator toDelete = iter;
473          ++iter;
474          loadedLibs.erase(toDelete->first);
475       }
476       else {
477          ++iter;
478       }
479    }
480 }
481
482 bool PCLibraryState::checkLibraryContains(Address addr, Library::ptr lib)
483 {
484    cacheLibraryRanges(lib);
485
486    cache_t tmp;
487
488    bool ret = loadedLibs.find(addr, tmp);
489    if (ret && tmp.second == lib)
490       return true;
491    return false;
492 }
493
494 void PCLibraryState::checkForNewLib(Library::ptr lib)
495 {
496    
497    if (lib->getData())
498       return;
499    sw_printf("[%s:%u] - Detected new library %s at %lx, notifying\n",
500              __FILE__, __LINE__, lib->getName().c_str(), lib->getLoadAddress());
501    
502    lib->setData((void *) 0x1);
503
504    StepperGroup *group = pdebug->getWalker()->getStepperGroup();
505    LibAddrPair la(lib->getName(), lib->getLoadAddress());
506
507    cacheLibraryRanges(lib);
508
509    group->newLibraryNotification(&la, library_load);
510 }
511
512 /*
513 For a given address, 'addr', PCLibraryState::getLibraryAtAddr returns
514 the name and load address of the library/executable that loaded over
515 'addr'.
516
517 Traditionally when searching for the library that contains an address,
518 we would sequentially open each library, read its program headers and
519 see if that library contained the address.  This caused at-scale
520 performance problems on apps with lots of libraries, as we turned up
521 opening a lot of unnecessary files.
522
523 This function tries to be smarter.  It identifies the libraries that
524 most likely to contain our address, and then targets opens at them.
525 We do this by getting the dynamic address for each library (a pointer
526 given by the link map).  The dynamic address points to the library's
527 DYNAMIC section, which must be loaded into memory as specified by the
528 System V ABI.  We expect that the library containing addr will have a
529 nearby DYNAMIC pointer, and we check the two libraries with a DYNAMIC
530 pointer above and below addr.  One of these libraries should contain
531 addr.
532
533 If, for some reason, we fail to get a DYNAMIC section then we'll stash
534 that library away in 'zero_dynamic_libs' and check it when done.
535 */ 
536
537 bool PCLibraryState::getLibraryAtAddr(Address addr, LibAddrPair &lib)
538 {
539    Process::ptr proc = pdebug->getProc();
540    CHECK_PROC_LIVE;
541
542    /**
543     * An OS can have a list of platform-special libs (currently only the
544     * vsyscall DSO on Linux).  Those don't appear in the normal link_map
545     * and thus won't have dynamic addresses.  Check their library range 
546     * manually.
547     **/
548
549    vector<pair<LibAddrPair, unsigned int> > arch_libs;
550    updateLibsArch(arch_libs);
551    vector<pair<LibAddrPair, unsigned int> >::iterator j;
552    for (j = arch_libs.begin(); j != arch_libs.end(); j++) {
553       string name = (*j).first.first;
554       Address start = (*j).first.second;
555       Address size = (*j).second;
556       if (addr >= start && addr < start + size) {
557          lib.first = name;
558          lib.second = start;
559          return true;
560       }
561    }
562
563    /**
564     * Look up the address in our cache of libraries
565     **/
566
567    bool ret = findInCache(proc, addr, lib);
568    if (ret) {
569       return true;
570    }
571
572    /**
573     * Cache lookup failed. Instead of iterating over every library,
574     * look at the link map in memory. This allows us to avoid opening
575     * files.
576     **/
577
578    // Do a fast in-memory scan
579    ret = memoryScan(proc, addr, lib);
580    if (ret) {
581       return true;
582    }
583
584    return false;
585 }
586
587 bool PCLibraryState::memoryScan(Process::ptr proc, Address addr, LibAddrPair &lib) {
588    
589    LibraryPool::iterator i;
590    Library::ptr nearest_predecessor = Library::ptr();
591    signed int pred_distance = 0;
592    Library::ptr nearest_successor = Library::ptr();
593    signed int succ_distance = 0;
594
595
596    /**
597     * Search the entire library list for the dynamic sections that come
598     * directly before and after our target address (nearest_predecessor
599     * and nearest_successor).
600     *
601     * They dynamic linker (and who-knows-what on future systems) can have a 
602     * dynamic address of zero.  Remember any library with a zero dynamic
603     * address with zero_dynamic_libs, and manually check those if the
604     * nearest_successor and nearest_predecessor.
605     **/
606    std::vector<Library::ptr> zero_dynamic_libs;
607    for (i = proc->libraries().begin(); i != proc->libraries().end(); i++)
608    {
609       Library::ptr slib = *i;
610       checkForNewLib(slib);
611
612       Address dyn_addr = slib->getDynamicAddress();
613       if (!dyn_addr) {
614          zero_dynamic_libs.push_back(slib);
615          continue;
616       }
617
618       signed int distance = addr - dyn_addr;
619       if (distance == 0) {
620          lib.first = slib->getName();
621          lib.second = slib->getLoadAddress();
622          sw_printf("[%s:%u] - Found library %s contains address %lx\n",
623                    __FILE__, __LINE__, lib.first.c_str(), addr);
624          return true;
625       }
626       else if (distance < 0) {
627          if (!pred_distance || pred_distance < distance) {
628             nearest_predecessor = slib;
629             pred_distance = distance;
630          }
631       }
632       else if (distance > 0) {
633          if (!succ_distance || succ_distance > distance) {
634             nearest_successor = slib;
635             succ_distance = distance;
636          }
637       }
638    }
639
640    /**
641     * Likely a static binary, set nearest_predecessor so that
642     * the following check will test it.
643     **/
644    if (!nearest_predecessor && !nearest_successor) {
645       nearest_predecessor = proc->libraries().getExecutable();
646    }
647
648    /**
649     * Check if predessor contains our address first--this should be the typical case 
650     **/
651    if (nearest_predecessor && checkLibraryContains(addr, nearest_predecessor)) {
652       lib.first = nearest_predecessor->getName();
653       lib.second = nearest_predecessor->getLoadAddress();
654       sw_printf("[%s:%u] - Found library %s contains address %lx\n",
655                 __FILE__, __LINE__, lib.first.c_str(), addr);
656       return true;
657    }
658    /**
659     * Check successor
660     **/
661    if (nearest_successor && checkLibraryContains(addr, nearest_successor)) {
662       lib.first = nearest_successor->getName();
663       lib.second = nearest_successor->getLoadAddress();
664       sw_printf("[%s:%u] - Found library %s contains address %lx\n",
665                 __FILE__, __LINE__, lib.first.c_str(), addr);
666       return true;
667    }
668
669    /**
670     * The address wasn't located by the dynamic section tests.  Check
671     * any libraries without dynamic pointers, plus the executable.
672     **/
673    std::vector<Library::ptr>::iterator k = zero_dynamic_libs.begin();
674    for (; k != zero_dynamic_libs.end(); k++) {
675       if (checkLibraryContains(addr, *k)) {
676          lib.first = (*k)->getName();
677          lib.second = (*k)->getLoadAddress();
678          return true;
679       }
680    }
681    if(checkLibraryContains(addr, proc->libraries().getExecutable()))
682    {
683      
684      lib.first = proc->libraries().getExecutable()->getName();
685      lib.second = proc->libraries().getExecutable()->getLoadAddress();
686      sw_printf("[%s:%u] - Found executable %s contains address %lx\n", __FILE__,
687                __LINE__, lib.first.c_str(), addr);
688      return true;
689    }
690    
691    sw_printf("[%s:%u] - Could not find library for addr %lx\n", 
692              __FILE__, __LINE__, addr);
693    return false;
694 }
695
696 bool PCLibraryState::getLibraries(std::vector<LibAddrPair> &libs)
697 {
698    Process::ptr proc = pdebug->getProc();
699    CHECK_PROC_LIVE;
700
701    LibraryPool::iterator i;   
702    for (i = proc->libraries().begin(); i != proc->libraries().end(); i++)
703    {
704       checkForNewLib(*i);
705       libs.push_back(LibAddrPair((*i)->getName(), (*i)->getLoadAddress()));
706    }
707
708    vector<pair<LibAddrPair, unsigned int> > arch_libs;
709    vector<pair<LibAddrPair, unsigned int> >::iterator j;
710    updateLibsArch(arch_libs);
711    for (j = arch_libs.begin(); j != arch_libs.end(); j++) {
712       libs.push_back(j->first);
713    }
714
715    return true;
716 }
717
718 bool PCLibraryState::updateLibraries()
719 {
720    Process::ptr proc = pdebug->getProc();
721    CHECK_PROC_LIVE;
722
723
724    static bool exec = false;
725
726    if (!exec) {
727      cacheLibraryRanges(proc->libraries().getExecutable());
728      exec = true;
729    }
730
731
732    LibraryPool::iterator i;   
733    for (i = proc->libraries().begin(); i != proc->libraries().end(); i++)
734    {
735       checkForNewLib(*i);
736    }
737
738    vector<pair<LibAddrPair, unsigned int> > arch_libs;
739    vector<pair<LibAddrPair, unsigned int> >::iterator j;
740    updateLibsArch(arch_libs);
741
742    return true;
743 }
744
745 void PCLibraryState::notifyOfUpdate()
746 {
747 }
748
749 Address PCLibraryState::getLibTrapAddress()
750 {
751    return 0;
752 }
753
754 bool PCLibraryState::getAOut(LibAddrPair &ao)
755 {
756    Process::ptr proc = pdebug->getProc();
757    CHECK_PROC_LIVE;
758
759    Library::ptr lib = proc->libraries().getExecutable();
760    if (!lib) {
761       sw_printf("[%s:%u] - Could not get executable\n", __FILE__, __LINE__);
762       return false;
763    }
764    ao = LibAddrPair(lib->getName(), lib->getLoadAddress());
765    return true;
766 }
767
768 void int_walkerSet::addToProcSet(ProcDebug *pd)
769 {
770    ProcessSet::ptr &pset = *((ProcessSet::ptr *) procset);
771    Process::ptr proc = pd->getProc();
772    pset->insert(proc);
773 }
774
775 void int_walkerSet::eraseFromProcSet(ProcDebug *pd)
776 {
777    ProcessSet::ptr &pset = *((ProcessSet::ptr *) procset);
778    Process::ptr proc = pd->getProc();
779
780    ProcessSet::iterator i = pset->find(proc);
781    assert(i != pset->end());
782    pset->erase(i);
783 }
784
785 void int_walkerSet::clearProcSet()
786 {
787    ProcessSet::ptr *pset = (ProcessSet::ptr *) procset;
788    (*pset)->clear();
789    delete pset;
790    procset = NULL;
791 }
792
793 void int_walkerSet::initProcSet()
794 {
795    ProcessSet::ptr *p = new ProcessSet::ptr();
796    *p = ProcessSet::newProcessSet();
797    procset = (void *) p;
798 }
799
800 class StackCallback : public Dyninst::ProcControlAPI::CallStackCallback
801 {
802 private:
803    CallTree &tree;
804    FrameNode *cur;
805    Walker *cur_walker;
806 public:
807    StackCallback(CallTree &t);
808    virtual ~StackCallback();
809    
810    virtual bool beginStackWalk(Thread::ptr thr);
811    virtual bool addStackFrame(Thread::ptr thr, Dyninst::Address ra, Dyninst::Address sp, Dyninst::Address fp);
812    virtual void endStackWalk(Thread::ptr thr);
813 };
814
815 StackCallback::StackCallback(CallTree &t) :
816    tree(t),
817    cur(NULL)
818 {
819    top_first = true;
820 }
821
822 StackCallback::~StackCallback()
823 {
824 }
825
826 bool StackCallback::beginStackWalk(Thread::ptr thr)
827 {
828    assert(!cur);
829    Process::ptr proc = thr->getProcess();
830    ProcessState *pstate = ProcessState::getProcessStateByPid(proc->getPid());
831    if (!pstate) {
832       sw_printf("[%s:%u] - Error, unknown process state for %d while starting stackwalk\n", 
833                 __FILE__, __LINE__, proc->getPid());
834       return false;
835    }
836
837    cur_walker = pstate->getWalker();
838    cur = tree.getHead();
839
840    return true;
841 }
842
843 bool StackCallback::addStackFrame(Thread::ptr thr,
844                                   Dyninst::Address ra, Dyninst::Address sp, Dyninst::Address fp)
845 {
846    Frame f(cur_walker);
847    f.setRA(ra);
848    f.setSP(sp);
849    f.setFP(fp);
850    f.setThread(thr->getLWP());
851    
852    cur = tree.addFrame(f, cur);
853    return true;
854 }
855
856 void StackCallback::endStackWalk(Thread::ptr thr) {
857    THR_ID thrd_lwp = thr->getLWP();
858    Frame *last_frame = cur->getFrame();
859    if (last_frame) {
860       last_frame->markTopFrame();
861    }
862    tree.addThread(thrd_lwp, cur, cur_walker, false);
863    cur = NULL;
864    cur_walker = NULL;
865 }
866
867 bool int_walkerSet::walkStacksProcSet(CallTree &tree, bool &bad_plat, bool walk_initial_only)
868 {
869    ProcessSet::ptr &pset = *((ProcessSet::ptr *) procset);
870    ThreadSet::ptr all_threads = ThreadSet::newThreadSet(pset, walk_initial_only);
871    StackCallback cbs(tree);
872
873    if (!all_threads->getCallStackUnwinding()) {
874       bad_plat = true;
875       return false;
876    }
877    return all_threads->getCallStackUnwinding()->walkStack(&cbs);
878 }