Add callback interface to receive callbacks upon signals.
[dyninst.git] / stackwalk / src / linux-swk.C
1 /*
2  * Copyright (c) 1996-2009 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/swk_errors.h"
33 #include "stackwalk/h/symlookup.h"
34 #include "stackwalk/h/walker.h"
35 #include "stackwalk/h/steppergroup.h"
36 #include "stackwalk/h/procstate.h"
37 #include "stackwalk/h/frame.h"
38
39 #include "stackwalk/src/linux-swk.h"
40 #include "stackwalk/src/symtab-swk.h"
41
42 #include "common/h/linuxKludges.h"
43 #include "common/h/parseauxv.h"
44 #include "common/h/Types.h"
45
46 #include <string>
47 #include <sstream>
48
49 #include <string.h>
50 #include <sys/syscall.h>
51 #include <unistd.h>
52 #include <errno.h>
53 #include <assert.h>
54 #include <signal.h>
55 #include <sys/types.h>
56 #include <sys/wait.h>
57 #include <sys/mman.h>
58 #include <fcntl.h>
59 #include <poll.h>
60
61 using namespace Dyninst;
62 using namespace Dyninst::Stackwalker;
63
64 #ifndef SYS_tkill
65 #define SYS_tkill 238
66 #endif
67
68 //These should be defined on all modern linux's, turn these off
69 // if porting to some linux-like platform that doesn't support 
70 // them.
71 #include <sys/ptrace.h>
72 #include <linux/ptrace.h>
73 typedef enum __ptrace_request pt_req;
74 #define cap_ptrace_traceclone
75 #define cap_ptrace_setoptions
76
77 ProcDebug::thread_map_t ProcDebugLinux::all_threads;
78 std::map<pid_t, int> ProcDebugLinux::unknown_pid_events;
79
80 static int P_gettid()
81 {
82   static int gettid_not_valid = 0;
83   long int result;
84
85   if (gettid_not_valid)
86     return getpid();
87
88   result = syscall(SYS_gettid);
89   if (result == -1 && errno == ENOSYS)
90   {
91     gettid_not_valid = 1;
92     return getpid();
93   }
94   return (int) result;
95 }
96
97 static bool t_kill(int pid, int sig)
98 {
99   static bool has_tkill = true;
100   long int result = 0;
101   sw_printf("[%s:%u] - Sending %d to %d\n", __FILE__, __LINE__, sig, pid);
102   if (has_tkill) {
103      result = syscall(SYS_tkill, pid, sig);
104      if (result == -1 && errno == ENOSYS)
105      {
106         sw_printf("[%s:%d] - Using kill instead of tkill on this system\n", 
107                   __FILE__, __LINE__, sig, pid);
108         has_tkill = false;
109      }
110   }
111   if (!has_tkill) {
112      result = kill(pid, sig);
113   }
114
115   return (result == 0);
116 }
117
118 static void registerLibSpotterSelf(ProcSelf *pself);
119 ProcSelf::ProcSelf() :
120    ProcessState(getpid())
121 {
122 }
123
124 void ProcSelf::initialize()
125 {
126    setDefaultLibraryTracker();
127    assert(library_tracker);
128    registerLibSpotterSelf(this);
129 }
130
131 #if defined(cap_sw_catchfaults)
132
133 #include <setjmp.h>
134
135 static bool registered_handler = false;
136 static bool reading_memory = false;
137 sigjmp_buf readmem_jmp;
138
139 void handle_fault(int /*sig*/)
140 {
141    if (!reading_memory) {
142       //The instruction that caused this fault was not from
143       // ProcSelf::readMem.  Restore the SIGSEGV handler, and 
144       // the faulting instruction should restart after we return.
145       fprintf(stderr, "[%s:%u] - Caught segfault that didn't come " \
146               "from stackwalker memory read!", __FILE__, __LINE__);
147       signal(SIGSEGV, SIG_DFL);
148       return;
149    }
150    siglongjmp(readmem_jmp, 1);
151 }
152
153 bool ProcSelf::readMem(void *dest, Address source, size_t size)
154 {
155    if (!registered_handler) {
156       signal(SIGSEGV, handle_fault);
157       registered_handler = true;
158    }
159    reading_memory = true;
160    if (sigsetjmp(readmem_jmp, 1)) {
161       sw_printf("[%s:%u] - Caught fault while reading from %lx to %lx\n", 
162                 __FILE__, __LINE__, source, source + size);
163       setLastError(err_procread, "Could not read from process");
164       return false;
165    }
166    
167    memcpy(dest, (const void *) source, size);
168    reading_memory = false;
169    return true;
170 }
171 #else
172 bool ProcSelf::readMem(void *dest, Address source, size_t size)
173 {
174   memcpy(dest, (const void *) source, size);
175   return true;
176 }
177 #endif
178
179 bool ProcSelf::getThreadIds(std::vector<THR_ID> &threads)
180 {
181   bool result;
182   THR_ID tid;
183
184   result = getDefaultThread(tid);
185   if (!result) {
186     sw_printf("[%s:%u] - Could not read default thread\n",
187                __FILE__, __LINE__);
188     return false;
189   }
190   threads.clear();
191   threads.push_back(tid);
192   return true;
193 }
194
195 bool ProcDebugLinux::isLibraryTrap(Dyninst::THR_ID thrd)
196 {
197    LibraryState *ls = getLibraryTracker();
198    if (!ls)
199       return false;
200    Address lib_trap_addr = ls->getLibTrapAddress();
201    if (!lib_trap_addr)
202       return false;
203
204    Dyninst::MachRegisterVal cur_pc;
205    bool result = getRegValue(Dyninst::MachRegPC, thrd, cur_pc);
206    if (!result) {
207       sw_printf("[%s:%u] - Error getting PC value for thrd %d\n",
208                 __FILE__, __LINE__, (int) thrd);
209       return false;
210    }
211    if (cur_pc == lib_trap_addr || cur_pc-1 == lib_trap_addr)
212       return true;
213    return false;
214 }
215
216
217 bool ProcSelf::getDefaultThread(THR_ID &default_tid)
218 {
219   THR_ID tid = P_gettid();
220   if (tid == -1) {
221     const char *sys_err_msg = strerror(errno);
222     sw_printf("[%s:%u] - gettid syscall failed with %s\n",
223                __FILE__, __LINE__, sys_err_msg);
224     std::string errmsg("gettid syscall failed with ");
225     errmsg += sys_err_msg;
226     setLastError(err_internal, errmsg.c_str());
227     return false;
228   }
229
230   default_tid = tid;
231   return true;
232 }
233
234 static bool pipeHasData(int fd)
235 {
236    if (fd == -1)
237       return false;
238
239    struct pollfd pfd[1];
240    pfd[0].fd = fd;
241    pfd[0].events = POLLIN;
242    pfd[0].revents = 0;
243    int result = poll(pfd, 1, 0);
244    return (result == 1 && pfd[0].revents & POLLIN);
245 }
246
247 DebugEvent ProcDebug::debug_get_event(bool block)
248 {
249    int status = 0;
250    DebugEvent ev;
251    pid_t p;
252
253    bool dataOnPipe = pipeHasData(pipe_out);
254
255    int flags = __WALL;
256    if (!block)
257      flags |= WNOHANG;
258    sw_printf("[%s:%u] - Calling waitpid(-1, %p, %d)\n",
259              __FILE__, __LINE__, &status, flags);
260    p = waitpid(-1, &status, flags);
261    sw_printf("[%s:%u] - waitpid returned status = 0x%x, p = %d\n",
262              __FILE__, __LINE__, status, p);
263    if (p == -1) {
264       int errnum = errno;
265       sw_printf("[%s:%u] - Unable to wait for debug event: %s\n",
266                 __FILE__, __LINE__, strerror(errnum));
267       if (errnum == EINTR)
268          setLastError(err_interrupt, "System call interrupted");
269       else
270          setLastError(err_internal, "Error calling waitpid");
271       ev.dbg = dbg_err;
272       return ev;
273    }
274
275    //If we got an event, or if we didn't read a message and there
276    // is a byte on the pipe, then remove one byte from the pipe.
277    if (pipe_out != -1 && 
278        (p != 0 || dataOnPipe)) 
279    {
280       char c;
281       sw_printf("[%s:%u] - Removing data from pipe, %d, %s\n",
282                 __FILE__, __LINE__, p, dataOnPipe ? "true" : "false");
283       read(pipe_out, &c, 1);
284    }
285    
286    if (p == 0) {
287      sw_printf("[%s:%u] - No debug events available\n", __FILE__, __LINE__);
288      ev.dbg = dbg_noevent;
289      return ev;
290    }
291
292    thread_map_t::iterator i = ProcDebugLinux::all_threads.find(p);
293    if (i == ProcDebugLinux::all_threads.end())
294    {
295       sw_printf("[%s:%u] - Warning, recieved unknown pid %d from waitpid\n",
296                 __FILE__, __LINE__, p);
297       ProcDebugLinux::unknown_pid_events[p] = status;
298       ev.dbg = dbg_noevent;
299       return ev;
300    }
301    
302    ev.thr = i->second;
303    ev.proc = ev.thr->proc();
304
305    if (WIFEXITED(status)) 
306    {
307       ev.dbg = dbg_exited;
308       ev.data.idata = WEXITSTATUS(status);
309       sw_printf("[%s:%u] - Process %d exited with %d\n", 
310                 __FILE__, __LINE__, p, ev.dbg);
311    }
312    else if (WIFSIGNALED(status))
313    {
314       ev.dbg = dbg_crashed;
315       ev.data.idata = WTERMSIG(status);
316       sw_printf("[%s:%u] - Process %d crashed with %d\n", 
317                 __FILE__, __LINE__, p, ev.dbg);
318    }
319    else if (WIFSTOPPED(status))
320    {
321       ev.dbg = dbg_stopped;
322       ev.data.idata = WSTOPSIG(status);
323       
324       ProcDebugLinux *linux_proc = dynamic_cast<ProcDebugLinux*>(ev.proc);
325       assert(linux_proc);
326       if (ev.data.idata == SIGTRAP) {
327          if (linux_proc->state() == ps_running && 
328              linux_proc->isLibraryTrap((Dyninst::THR_ID) p)) 
329          {
330             sw_printf("[%s:%u] - Decoded library load event\n",
331                       __FILE__, __LINE__);
332             ev.dbg = dbg_libraryload;
333          }
334          else {
335             int extended_data = status >> 16;
336             if (extended_data)
337                ev.data.idata = (extended_data << 8) | SIGTRAP;
338          }
339       }
340       sw_printf("[%s:%u] - Process %d stopped with %d\n",
341                 __FILE__, __LINE__, p, ev.data);
342    }
343    else
344    {
345       sw_printf("[%s:%u] - Process %d had strange return value from waitpid\n",
346                 __FILE__, __LINE__, p);
347       setLastError(err_internal, "Error calling waitpid");
348       ev.dbg = dbg_err;
349    }
350    return ev;
351 }
352
353 bool ProcDebugLinux::debug_handle_event(DebugEvent ev)
354 {
355   bool result;
356   ThreadState *thr = ev.thr;
357
358   switch (ev.dbg)
359   {
360      case dbg_stopped:
361         thr->setStopped(true);
362         if (thr->state() == ps_attached_intermediate && 
363             (ev.data.idata == SIGSTOP || ev.data.idata == SIGTRAP)) {
364            sw_printf("[%s:%u] - Moving %d/%d to state running\n", 
365                      __FILE__, __LINE__, pid, thr->getTid());
366            thr->setState(ps_running);
367            return true;
368         }
369
370 #if defined(cap_ptrace_traceclone)
371         if (ev.data.idata == (SIGTRAP | (PTRACE_EVENT_CLONE << 8))) {
372            sw_printf("[%s:%u] - Discovered new thread in proc %d\n", 
373                      __FILE__, __LINE__, pid);
374            pid_t newtid = 0x0;
375            ThreadState *new_thread = NULL;
376            long iresult = ptrace((pt_req) PTRACE_GETEVENTMSG, thr->getTid(), 
377                                  NULL, &newtid);
378            if (iresult == -1) {
379               sw_printf("[%s:%u] - Unexpected error getting new tid on %d\n"
380                      __FILE__, __LINE__, pid);
381            }
382            else 
383            {
384               sw_printf("[%s:%u] - New thread %ld in proc %d\n",
385                         __FILE__, __LINE__, newtid, pid);
386               new_thread = ThreadState::createThreadState(this, (THR_ID) newtid, true);
387            }
388            if (!new_thread) {
389               sw_printf("[%s:%u] - Error creating thread %d in proc %d\n",
390                         __FILE__, __LINE__, newtid, pid);
391            }
392            result = debug_continue(thr);
393            if (!result) {
394               sw_printf("[%s:%u] - Debug continue failed on %d/%d\n",
395                         __FILE__, __LINE__, pid, thr->getTid());
396               return false;
397            }
398            return true;
399         }
400 #endif
401         
402         if (ev.data.idata != SIGSTOP) {
403            result = debug_handle_signal(&ev);
404            if (!result) {
405               sw_printf("[%s:%u] - Debug continue failed on %d/%d with %d\n", 
406                         __FILE__, __LINE__, pid, thr->getTid(), ev.data.idata);
407               return false;
408            }
409         }
410         return true;
411     case dbg_libraryload: 
412     {
413        sw_printf("[%s:%u] - Handling library load event on %d/%d\n",
414                  __FILE__, __LINE__, pid, thr->getTid());
415        thr->setStopped(true);
416        LibraryState *ls = getLibraryTracker();
417        assert(ls);
418        ls->notifyOfUpdate();
419        
420        result = debug_continue_with(thr, 0);
421        if (!result) {
422           sw_printf("[%s:%u] - Debug continue failed on %d/%d with %d\n", 
423                     __FILE__, __LINE__, pid, thr->getTid(), ev.data.idata);
424           return false;
425        }
426        return true;
427     }
428     case dbg_crashed:
429       sw_printf("[%s:%u] - Handling process crash on %d/%d\n",
430                 __FILE__, __LINE__, pid, thr->getTid());
431     case dbg_exited:
432       sw_printf("[%s:%u] - Handling process death on %d/%d\n",
433                 __FILE__, __LINE__, pid, thr->getTid());
434       thr->setState(ps_exited);
435       return true;
436     case dbg_err:
437     case dbg_noevent:
438     default:
439       sw_printf("[%s:%u] - Unexpectedly handling an error event %d on %d/%d\n", 
440                 __FILE__, __LINE__, ev.dbg, pid, thr->getTid());
441       setLastError(err_internal, "Told to handle an unexpected event.");
442       return false;
443   }
444 }
445
446 bool ProcDebugLinux::debug_handle_signal(DebugEvent *ev)
447 {
448    assert(ev->dbg == dbg_stopped);
449    if (sigfunc) {
450       bool user_stopped = ev->thr->userIsStopped();
451       ev->thr->setUserStopped(true);
452       sigfunc(ev->data.idata, ev->thr);
453       ev->thr->setUserStopped(user_stopped);
454    }
455    return debug_continue_with(ev->thr, ev->data.idata);
456 }
457
458 #if defined(cap_ptrace_setoptions)   
459 void ProcDebugLinux::setOptions(Dyninst::THR_ID tid)
460 {
461
462    long options = 0;
463 #if defined(cap_ptrace_traceclone)
464    options |= PTRACE_O_TRACECLONE;
465 #endif
466
467    if (options) {
468       int result = ptrace((pt_req) PTRACE_SETOPTIONS, tid, NULL, 
469                           (void *) options);
470       if (result == -1) {
471          sw_printf("[%s:%u] - Failed to set options for %d: %s\n", 
472                    __FILE__, __LINE__, tid, strerror(errno));
473       }
474    }   
475 }
476 #else
477 void ProcDebugLinux::setOptions(Dyninst::THR_ID)
478 {
479 }
480 #endif
481
482 bool ProcDebugLinux::debug_attach(ThreadState *ts)
483 {
484    long result;
485    pid_t tid = (pid_t) ts->getTid();
486    
487    sw_printf("[%s:%u] - Attaching to pid %d\n", __FILE__, __LINE__, tid);
488    result = ptrace((pt_req) PTRACE_ATTACH, tid, NULL, NULL);
489    if (result != 0) {
490       int errnum = errno;
491       sw_printf("[%s:%u] - Unable to attach to process %d: %s\n",
492                 __FILE__, __LINE__, tid, strerror(errnum));
493       if (errnum == EPERM)
494          setLastError(err_prem, "Do not have correct premissions to attach " \
495                       "to pid");
496       else if (errnum == ESRCH)
497          setLastError(err_noproc, "The specified process was not found");
498       else {
499          setLastError(err_internal, "DynStackwalker was unable to attach to " \
500                       "the specified process");
501       }
502       return false;
503    }
504    ts->setState(ps_attached_intermediate);   
505
506    return true;
507 }
508
509 bool ProcDebugLinux::debug_post_create()
510 {
511    sw_printf("[%s:%u] - Post create on %d\n", __FILE__, __LINE__, pid);
512    setOptions(pid);
513
514    setDefaultLibraryTracker();
515    assert(library_tracker);
516    registerLibSpotter();
517    return true;
518 }
519
520 bool ProcDebugLinux::debug_post_attach(ThreadState *thr)
521 {
522    sw_printf("[%s:%u] - Post attach on %d\n", __FILE__, __LINE__, thr->getTid());
523    THR_ID tid = thr->getTid();
524    setOptions(tid);
525
526    setDefaultLibraryTracker();
527    assert(library_tracker);
528    registerLibSpotter();
529
530    if (tid == pid) {
531       //We're attach to the initial process, also attach to all threads
532       pollForNewThreads();
533    }
534    return true;
535 }
536
537 bool ProcDebugLinux::debug_pause(ThreadState *thr)
538 {
539    bool result;
540
541    result = t_kill(thr->getTid(), SIGSTOP);
542    if (!result) {
543       if (errno == ESRCH) {
544          sw_printf("[%s:%u] - t_kill failed on %d, thread doesn't exist\n",
545                    __FILE__, __LINE__, thr->getTid());
546          setLastError(err_noproc, "Thread no longer exists");
547          return false;
548       }
549       sw_printf("[%s:%u] - t_kill failed on %d: %s\n", __FILE__, __LINE__,
550                 thr->getTid(), strerror(errno));
551       setLastError(err_internal, "Could not send signal to process while " \
552                    "stopping");
553       return false;
554    }
555    
556    return true;
557 }
558
559 bool ProcDebugLinux::debug_continue(ThreadState *thr)
560 {
561    return debug_continue_with(thr, 0);
562 }
563
564 bool ProcDebugLinux::debug_continue_with(ThreadState *thr, long sig)
565 {
566    long result;
567    assert(thr->isStopped());
568    Dyninst::THR_ID tid = thr->getTid();
569    sw_printf("[%s:%u] - Calling PTRACE_CONT with signal %d on %d\n",
570              __FILE__, __LINE__, sig, tid);
571    result = ptrace((pt_req) PTRACE_CONT, tid, NULL, (void *) sig);
572    if (result != 0)
573    {
574      int errnum = errno;
575       sw_printf("[%s:%u] - Error continuing %d with %d: %s\n",
576                 __FILE__, __LINE__, tid, sig, strerror(errnum));
577       setLastError(err_internal, "Could not continue process");
578       return false;
579    }
580
581    thr->setStopped(false);
582    return true;
583 }
584
585 bool ProcDebugLinux::readMem(void *dest, Address source, size_t size)
586 {
587    unsigned long nbytes = size;
588    const unsigned char *ap = (const unsigned char*) source;
589    unsigned char *dp = (unsigned char*) dest;
590    Address w = 0x0;               /* ptrace I/O buffer */
591    int len = sizeof(long);
592    unsigned long cnt;
593    
594    if (!nbytes) {
595       return true;
596    }
597    
598    ThreadState *thr = active_thread;
599    if (!thr) {
600       //Likely doing this read in response to some event, perhaps
601       // without an active thread.  The event should have stopped something,
602       // so find a stopped thread.
603       thread_map_t::iterator i;
604       for (i = threads.begin(); i != threads.end(); i++) {
605          ThreadState *t = (*i).second;
606          if (t->state() == ps_exited)
607             continue;
608          if (t->isStopped()) {
609             thr = t;
610             break;
611          }
612       }
613    }
614    assert(thr); //Something should be stopped if we're here.
615    pid_t tid = (pid_t) thr->getTid();
616
617    if ((cnt = (source % len))) {
618       /* Start of request is not aligned. */
619       unsigned char *p = (unsigned char*) &w;
620       
621       /* Read the segment containing the unaligned portion, and
622          copy what was requested to DP. */
623       errno = 0;
624       w = ptrace((pt_req) PTRACE_PEEKTEXT, tid, (Address) (ap-cnt), w);
625       if (errno) {
626          int errnum = errno;
627          sw_printf("[%s:%u] - PTRACE_PEEKTEXT returned error on %d: %s\n",
628                    __FILE__, __LINE__, pid, strerror(errnum));
629          setLastError(err_procread, "Could not read from process\n");
630          return false;
631       }
632
633       for (unsigned i = 0; i < len-cnt && i < nbytes; i++)
634          dp[i] = p[cnt+i];
635       
636       if (len-cnt >= nbytes) {
637          return true;
638       }
639       
640       dp += len-cnt;
641       ap += len-cnt;
642       nbytes -= len-cnt;
643    }
644    /* Copy aligned portion */
645    while (nbytes >= (u_int)len) {
646       errno = 0;
647       w = ptrace((pt_req) PTRACE_PEEKTEXT, tid, (Address) ap, 0);
648       if (errno) {
649          int errnum = errno;
650          sw_printf("[%s:%u] - PTRACE_PEEKTEXT returned error on %d: %s\n",
651                    __FILE__, __LINE__, pid, strerror(errnum));
652          setLastError(err_procread, "Could not read from process\n");
653          return false;
654       }
655       memcpy(dp, &w, len);
656       dp += len;
657       ap += len;
658       nbytes -= len;
659    }
660    
661    if (nbytes > 0) {
662       /* Some unaligned data remains */
663       unsigned char *p = (unsigned char *) &w;
664       
665       /* Read the segment containing the unaligned portion, and
666          copy what was requested to DP. */
667       errno = 0;
668       w = ptrace((pt_req) PTRACE_PEEKTEXT, tid, (Address) ap, 0);
669       if (errno) {
670          int errnum = errno;
671          sw_printf("[%s:%u] - PTRACE_PEEKTEXT returned error on %d: %s\n",
672                    __FILE__, __LINE__, pid, strerror(errnum));
673          setLastError(err_procread, "Could not read from process\n");
674          return false;
675       }
676       for (unsigned i = 0; i < nbytes; i++)
677          dp[i] = p[i];
678    }
679
680    return true;
681 }   
682
683 bool ProcDebugLinux::getThreadIds(std::vector<THR_ID> &thrds)
684 {
685 #if !defined(cap_ptrace_traceclone)
686    pollForNewThreads();
687 #endif
688    thread_map_t::iterator i;
689    for (i = threads.begin(); i != threads.end(); i++) {
690       ThreadState *ts = (*i).second;
691       if (ts->state() != ps_running) {
692          sw_printf("Skipping thread %d in state %d\n", 
693                    ts->getTid(), ts->state());
694          continue;
695       }
696               
697       thrds.push_back(ts->getTid());
698    }
699    return true;
700 }
701
702 bool ProcDebugLinux::pollForNewThreads()
703 {
704    std::vector<THR_ID> thrds;
705    bool result = findProcLWPs(pid, thrds);
706    if (!result) {
707       sw_printf("[%s:%u] - getThreadIds failed in libcommon's findProcLWPs "
708                 "for %d", __FILE__, __LINE__, pid);                
709       return false;
710    }
711
712    return add_new_threads(thrds.begin(), thrds.end());
713 }
714
715 bool ProcDebugLinux::getDefaultThread(THR_ID &default_tid)
716 {
717    default_tid = (THR_ID) pid;
718    return true;
719 }
720
721 ProcDebugLinux::ProcDebugLinux(PID pid)
722    : ProcDebug(pid),
723      cached_addr_width(0),
724      lib_load_trap(0x0),
725      trap_actual_len(0x0),
726      trap_install_error(false)
727 {
728 }
729
730 ProcDebugLinux::ProcDebugLinux(const std::string &executable, 
731                                const std::vector<std::string> &argv)
732    : ProcDebug(executable, argv),
733      cached_addr_width(0),
734      lib_load_trap(0x0),
735      trap_actual_len(0x0),
736      trap_install_error(false)
737 {
738 }
739
740 ProcDebugLinux::~ProcDebugLinux()
741 {
742 }
743    
744 ProcDebug *ProcDebug::newProcDebug(PID pid, std::string)
745 {
746    ProcDebugLinux *pd = new ProcDebugLinux(pid);
747    if (!pd)
748    {
749       sw_printf("[%s:%u] - Error creating new ProcDebug object\n",
750                 __FILE__, __LINE__);
751       return pd;
752    }
753
754    bool result = pd->attach();
755    if (!result || pd->state() != ps_running) {
756      pd->setState(ps_errorstate);
757      proc_map.erase(pid);
758      sw_printf("[%s:%u] - Error attaching to process %d\n",
759                __FILE__, __LINE__, pid);
760      delete pd;
761      return NULL;
762    }
763
764    return pd;
765 }
766
767 ProcDebug *ProcDebug::newProcDebug(const std::string &executable, 
768                                    const std::vector<std::string> &argv)
769 {
770    ProcDebugLinux *pd = new ProcDebugLinux(executable, argv);
771    if (!pd)
772    {
773       sw_printf("[%s:%u] - Error creating new ProcDebug object\n",
774                 __FILE__, __LINE__);
775       return NULL;
776    }
777
778    bool result = pd->create(executable, argv);
779    if (!result || pd->state() != ps_running)
780    {
781      pd->setState(ps_errorstate);
782      proc_map.erase(pd->pid);
783      sw_printf("[%s:%u] - Error attaching to process %d\n",
784                __FILE__, __LINE__, pd->pid);
785      delete pd;
786      return NULL;
787    }
788
789    return pd;   
790 }
791
792
793 void chld_handler(int)
794 {
795    write(ProcDebug::pipe_in, "s", 1);
796 }
797
798 int ProcDebug::getNotificationFD()
799 {
800    static bool registered_handler = false;
801    int filedes[2], result;
802    if (!registered_handler) 
803    {
804       signal(SIGCHLD, chld_handler);
805       result = pipe(filedes);
806       if (result == -1)
807       {
808          int errnum = errno;
809          sw_printf("[%s:%u] - Could not create pipe: %s\n",
810                    __FILE__, __LINE__, strerror(errnum));
811          setLastError(err_internal, "Could not create pipe for notificationFD");
812          return -1;
813       }
814       pipe_out = filedes[0];
815       pipe_in = filedes[1];
816
817       result = fcntl(pipe_out, F_GETFL);
818       if (result != -1)
819       {
820          result = fcntl(pipe_out, F_SETFL, result | O_NONBLOCK);
821       }
822       if (result == -1)
823       {
824          int errnum = errno;
825          sw_printf("[%s:%u] - Could not set fcntl flags: %s\n",
826                    __FILE__, __LINE__, strerror(errnum));
827          setLastError(err_internal, "Could not set pipe properties");
828          return -1;
829       }
830       registered_handler = true;
831    }
832    return pipe_out;
833 }
834
835 bool ProcDebugLinux::debug_create(const std::string &executable, 
836                                   const std::vector<std::string> &argv)
837 {
838    pid = fork();
839    if (pid == -1)
840    {
841       int errnum = errno;
842       sw_printf("[%s:%u] - Could not fork new process for %s: %s\n",
843                 __FILE__, __LINE__, executable.c_str(), strerror(errnum));
844       setLastError(err_internal, "Unable to fork new process");
845       return false;
846    }
847
848    if (pid)
849    {
850    }
851    else
852    {
853       //Child
854       long int result = ptrace((pt_req) PTRACE_TRACEME, 0, 0, 0);
855       unsigned i;
856       if (result == -1)
857       {
858          sw_printf("[%s:%u] - Failed to execute a PTRACE_TRACME.  Odd.\n",
859                    __FILE__, __LINE__);
860          setLastError(err_internal, "Unable to debug trace new process");
861          exit(-1);
862       }
863
864       typedef const char * const_str;
865       
866       const_str *new_argv = (const_str *) calloc(argv.size()+3, sizeof(char *));
867       new_argv[0] = executable.c_str();
868       for (i=1; i<argv.size()+1; i++) {
869          new_argv[i] = argv[i-1].c_str();
870       }
871       new_argv[i+1] = (char *) NULL;
872       
873       result = execv(executable.c_str(), const_cast<char * const*>(new_argv));
874       int errnum = errno;         
875       sw_printf("[%s:%u] - Failed to exec %s: %s\n", __FILE__, __LINE__, 
876                 executable.c_str(), strerror(errnum));
877       if (errnum == ENOENT)
878          setLastError(err_nofile, "No such file");
879       if (errnum == EPERM || errnum == EACCES)
880          setLastError(err_prem, "Premission denied");
881       else
882          setLastError(err_internal, "Unable to exec process");
883       exit(-1);
884    }
885    return true;
886 }
887
888 SigHandlerStepperImpl::SigHandlerStepperImpl(Walker *w, SigHandlerStepper *parent) :
889    FrameStepper(w),
890    parent_stepper(parent)
891 {
892 }
893
894 unsigned SigHandlerStepperImpl::getPriority() const
895 {
896    return 0x10005;
897 }
898
899 void SigHandlerStepperImpl::registerStepperGroupNoSymtab(StepperGroup *group)
900 {
901    /**
902     * We don't have symtabAPI loaded, and we want to figure out where 
903     * the SigHandler trampolines are.  If we're a first-party stackwalker
904     * we can just use the entire vsyscall page.  
905     *
906     * We're not in danger of confusing the location with a regular system call,
907     * as we're not running in a system call right now.  I can't
908     * make that guarentee for a third-party stackwalker.  
909     **/   
910    ProcessState *ps = getProcessState();
911    assert(ps);
912
913    if (!dynamic_cast<ProcSelf *>(ps)) {
914       //Not a first-party stackwalker
915       return;
916    }
917       
918    AuxvParser *parser = AuxvParser::createAuxvParser(ps->getProcessId(),
919                                                      ps->getAddressWidth());
920    if (!parser) {
921       sw_printf("[%s:%u] - Unable to parse auxv for %d\n", __FILE__, __LINE__,
922                 ps->getProcessId());
923       return;
924    }
925
926    Address start = parser->getVsyscallBase();
927    Address end = parser->getVsyscallEnd();
928    sw_printf("[%s:%u] - Registering signal handler stepper over range %lx to %lx\n",
929              __FILE__, __LINE__, start, end);
930    
931    parser->deleteAuxvParser();
932    
933    if (!start || !end)
934    {
935       sw_printf("[%s:%u] - Error collecting vsyscall base and end\n",
936                 __FILE__, __LINE__);
937       return;
938    }
939
940    group->addStepper(parent_stepper, start, end);
941 }
942
943 SigHandlerStepperImpl::~SigHandlerStepperImpl()
944 {
945 }
946
947 void ProcDebugLinux::registerLibSpotter()
948 {
949    bool result;
950
951    if (lib_load_trap)
952       return;
953
954    LibraryState *libs = getLibraryTracker();
955    if (!libs) {
956       sw_printf("[%s:%u] - Not using lib tracker, don't know how "
957                 "to get library load address\n", __FILE__, __LINE__);
958       return;
959    }
960    
961    lib_load_trap = libs->getLibTrapAddress();
962    if (!lib_load_trap) {
963       sw_printf("[%s:%u] - Couldn't get trap addr, couldn't set up "
964                 "library loading notification.\n", __FILE__, __LINE__);
965       trap_install_error = true;
966       return;
967    }
968
969    char trap_buffer[MAX_TRAP_LEN];
970    getTrapInstruction(trap_buffer, MAX_TRAP_LEN, trap_actual_len, true);
971
972    result = PtraceBulkRead(lib_load_trap, trap_actual_len, trap_overwrite_buffer, pid);
973    if (!result) {
974       sw_printf("[%s:%u] - Error reading trap bytes from %lx\n", 
975                 __FILE__, __LINE__, lib_load_trap);
976       trap_install_error = true;
977       return;
978    }
979    result = PtraceBulkWrite(lib_load_trap, trap_actual_len, trap_buffer, pid);
980    if (!result) {
981       sw_printf("[%s:%u] - Error writing trap to %lx, couldn't set up library "
982                 "load address\n", __FILE__, __LINE__, lib_load_trap);
983       trap_install_error = true;
984       return;
985    }
986    sw_printf("[%s:%u] - Successfully installed library trap at %lx\n",
987              __FILE__, __LINE__, lib_load_trap);
988 }
989
990 bool ProcDebugLinux::detach_thread(int tid, bool leave_stopped)
991 {
992    sw_printf("[%s:%u] - Detaching from tid %d\n", __FILE__, __LINE__, tid);
993    long int iresult = ptrace((pt_req) PTRACE_DETACH, tid, NULL, NULL);
994    if (iresult == -1) {
995       int error = errno;
996       sw_printf("[%s:%u] - Error.  Couldn't detach from %d: %s\n",
997                 __FILE__, __LINE__, tid, strerror(error));
998       if (error != ESRCH) {
999          setLastError(err_internal, "Could not detach from thread\n");
1000          return false;
1001       }
1002    }
1003
1004    thread_map_t::iterator j = all_threads.find(tid);
1005    if (j == all_threads.end()) {
1006       sw_printf("[%s:%u] - Error.  Expected to find %d in all threads\n",
1007                 __FILE__, __LINE__, tid);
1008       setLastError(err_internal, "Couldn't find thread in internal data structures");
1009       return false;
1010    }
1011
1012    if (!leave_stopped) {
1013       t_kill(tid, SIGCONT);
1014    }
1015
1016    all_threads.erase(j);
1017    return true;
1018 }
1019
1020 bool ProcDebugLinux::detach(bool leave_stopped)
1021 {
1022    bool result;
1023    bool error = false;
1024    sw_printf("[%s:%u] - Detaching from process %d\n", 
1025              __FILE__, __LINE__, getProcessId());
1026    result = pause();
1027    if (!result) {
1028       sw_printf("[%s:%u] - Error pausing process before detach\n",
1029                 __FILE__, __LINE__);
1030       return false;
1031    }
1032
1033    if (lib_load_trap && !trap_install_error)
1034    {
1035       result = PtraceBulkWrite(lib_load_trap, trap_actual_len, 
1036                                trap_overwrite_buffer, pid);
1037       if (!result) {
1038          sw_printf("[%s:%u] - Error.  Couldn't restore load trap bytes at %lx\n",
1039                    __FILE__, __LINE__, lib_load_trap);
1040          setLastError(err_internal, "Could not remove library trap");
1041          return false;
1042       }
1043       lib_load_trap = 0x0;
1044    }
1045    
1046    for (thread_map_t::iterator i = threads.begin(); i != threads.end(); i++)
1047    {
1048       Dyninst::THR_ID tid = (*i).first;
1049       ThreadState *thread_state = (*i).second;
1050       if (tid == getProcessId())
1051          continue;
1052       result = detach_thread(tid, leave_stopped);
1053       if (!result)
1054          error = true;
1055
1056       delete thread_state;
1057    }
1058    threads.clear();
1059
1060    result = detach_thread(getProcessId(), leave_stopped);
1061    if (!result)
1062       error = true;
1063
1064    detach_arch_cleanup();
1065
1066    return !error;
1067 }
1068
1069
1070 static LibraryState *local_lib_state = NULL;
1071 extern "C" {
1072    static void lib_trap_handler(int sig);
1073 }
1074 static void lib_trap_handler(int /*sig*/)
1075 {
1076    local_lib_state->notifyOfUpdate();
1077 }
1078
1079 static Address lib_trap_addr_self = 0x0;
1080 static bool lib_trap_addr_self_err = false;
1081 static void registerLibSpotterSelf(ProcSelf *pself)
1082 {
1083    if (lib_trap_addr_self)
1084       return;
1085    if (lib_trap_addr_self_err)
1086       return;
1087
1088    //Get the address to install a trap to
1089    LibraryState *libs = pself->getLibraryTracker();
1090    if (!libs) {
1091       sw_printf("[%s:%u] - Not using lib tracker, don't know how "
1092                 "to get library load address\n", __FILE__, __LINE__);
1093       lib_trap_addr_self_err = true;
1094       return;
1095    }   
1096    lib_trap_addr_self = libs->getLibTrapAddress();
1097    if (!lib_trap_addr_self) {
1098       sw_printf("[%s:%u] - Error getting trap address, can't install lib tracker",
1099                 __FILE__, __LINE__);
1100       lib_trap_addr_self_err = true;
1101       return;
1102    }
1103
1104    //Use /proc/PID/maps to make sure that this address is valid and writable
1105    unsigned maps_size;
1106    map_entries *maps = getLinuxMaps(getpid(), maps_size);
1107    if (!maps) {
1108       sw_printf("[%s:%u] - Error reading proc/%d/maps.  Can't install lib tracker",
1109                 __FILE__, __LINE__, getpid());
1110       lib_trap_addr_self_err = true;
1111       return;
1112    }
1113
1114    bool found = false;
1115    for (unsigned i=0; i<maps_size; i++) {
1116       if (maps[i].start <= lib_trap_addr_self && 
1117           maps[i].end > lib_trap_addr_self)
1118       {
1119          found = true;
1120          if (maps[i].prems & PREMS_WRITE) {
1121             break;
1122          }
1123          int pgsize = getpagesize();
1124          Address first_page = (lib_trap_addr_self / pgsize) * pgsize;
1125          unsigned size = pgsize;
1126          if (first_page + size < lib_trap_addr_self+MAX_TRAP_LEN)
1127             size += pgsize;
1128          int result = mprotect((void*) first_page,
1129                                size, 
1130                                PROT_READ|PROT_WRITE|PROT_EXEC);
1131          if (result == -1) {
1132             int errnum = errno;
1133             sw_printf("[%s:%u] - Error setting premissions for page containing %lx. "
1134                       "Can't install lib tracker: %s\n", __FILE__, __LINE__, 
1135                       lib_trap_addr_self, strerror(errnum));
1136             free(maps);
1137             lib_trap_addr_self_err = true;
1138             return;
1139          }
1140       }
1141    }
1142    free(maps);
1143    if (!found) {
1144       sw_printf("[%s:%u] - Couldn't find page containing %lx.  Can't install lib "
1145                 "tracker.", __FILE__, __LINE__, lib_trap_addr_self);
1146       lib_trap_addr_self_err = true;
1147       return;
1148    }
1149
1150    char trap_buffer[MAX_TRAP_LEN];
1151    unsigned actual_len;
1152    getTrapInstruction(trap_buffer, MAX_TRAP_LEN, actual_len, true);
1153
1154    local_lib_state = libs;
1155    signal(SIGTRAP, lib_trap_handler);
1156
1157    memcpy((void*) lib_trap_addr_self, trap_buffer, actual_len);   
1158    sw_printf("[%s:%u] - Successfully install lib tracker at 0x%lx\n",
1159             __FILE__, __LINE__, lib_trap_addr_self);
1160 }
1161
1162 #if defined(cap_stackwalker_use_symtab)
1163
1164 #include "common/h/parseauxv.h"
1165 #include "symtabAPI/h/Symtab.h"
1166 #include "symtabAPI/h/Symbol.h"
1167
1168 using namespace Dyninst::SymtabAPI;
1169
1170 bool SymtabLibState::updateLibsArch()
1171 {
1172    if (vsyscall_page_set == vsys_set)
1173    {
1174       return true;
1175    }
1176    else if (vsyscall_page_set == vsys_error)
1177    {
1178       return false;
1179    }
1180    else if (vsyscall_page_set == vsys_none)
1181    {
1182       return true;
1183    }
1184    assert(vsyscall_page_set == vsys_unset);
1185
1186 #if !defined(arch_x86)
1187    vsyscall_page_set = vsys_none;
1188    return true;
1189 #endif
1190       
1191    AuxvParser *parser = AuxvParser::createAuxvParser(procstate->getProcessId(), 
1192                                                      procstate->getAddressWidth());
1193    if (!parser) {
1194       sw_printf("[%s:%u] - Unable to parse auxv", __FILE__, __LINE__);
1195       vsyscall_page_set = vsys_error;
1196       return false;
1197    }
1198
1199    Address start = parser->getVsyscallBase();
1200    Address end = parser->getVsyscallEnd();
1201
1202    vsyscall_mem = malloc(end - start);
1203    bool result = procstate->readMem(vsyscall_mem, start, end - start);
1204    if (!result) {
1205       sw_printf("[%s:%u] - Error reading from vsyscall page\n");
1206       vsyscall_page_set = vsys_error;
1207       return false;
1208    }
1209
1210    std::stringstream ss;
1211    ss << "[vsyscall-" << procstate->getProcessId() << "]";
1212    LibAddrPair vsyscall_page;
1213    vsyscall_page.first = ss.str();
1214    vsyscall_page.second = start;
1215    
1216    result = Symtab::openFile(vsyscall_symtab, (char *) vsyscall_mem, end - start);
1217    if (!result || !vsyscall_symtab) {
1218       //TODO
1219       vsyscall_page_set = vsys_error;
1220       return false;
1221    }
1222
1223    SymtabWrapper::notifyOfSymtab(vsyscall_symtab, vsyscall_page.first);
1224    parser->deleteAuxvParser();
1225
1226    std::pair<LibAddrPair, unsigned int> vsyscall_lib_pair;
1227    vsyscall_lib_pair.first = vsyscall_page;
1228    vsyscall_lib_pair.second = static_cast<unsigned int>(end - start);
1229
1230    arch_libs.push_back(vsyscall_lib_pair);
1231    vsyscall_page_set = vsys_set;
1232
1233    return true;
1234 }
1235
1236 Symtab *SymtabLibState::getVsyscallSymtab()
1237 {
1238    refresh();
1239    if (vsyscall_page_set == vsys_set)
1240       return vsyscall_symtab;
1241    return NULL;
1242 }
1243
1244 #define NUM_VSYS_SIGRETURNS 3
1245 static const char* vsys_sigreturns[] = {
1246    "_sigreturn",
1247    "__kernel_sigreturn",
1248    "__kernel_rt_sigreturn"
1249 };
1250
1251 void SigHandlerStepperImpl::registerStepperGroup(StepperGroup *group)
1252 {
1253    LibraryState *libs = getProcessState()->getLibraryTracker();
1254    SymtabLibState *symtab_libs = dynamic_cast<SymtabLibState *>(libs);
1255    bool result;
1256    if (!symtab_libs) {
1257       sw_printf("[%s:%u] - Custom library tracker.  Don't know how to"
1258                 " to get vsyscall page\n", __FILE__, __LINE__);
1259       registerStepperGroupNoSymtab(group);
1260       return;
1261    }
1262    Symtab *vsyscall = symtab_libs->getVsyscallSymtab();
1263    if (!vsyscall)
1264    {
1265       sw_printf("[%s:%u] - Odd.  Couldn't find vsyscall page. Signal handler"
1266                 " stepping may not work\n", __FILE__, __LINE__);
1267       registerStepperGroupNoSymtab(group);
1268       return;
1269    }
1270
1271    for (unsigned i=0; i<NUM_VSYS_SIGRETURNS; i++)
1272    {
1273       std::vector<SymtabAPI::Symbol *> syms;
1274       result = vsyscall->findSymbolByType(syms, vsys_sigreturns[i], 
1275                                           SymtabAPI::Symbol::ST_FUNCTION,
1276                                           false, false, false);
1277       if (!result || !syms.size()) {
1278          continue;
1279       }
1280       Address addr = syms[0]->getAddr();
1281       unsigned long size = syms[0]->getSize();
1282       sw_printf("[%s:%u] - Registering signal handler stepper %s to run between"
1283                 " %lx and %lx\n", __FILE__, __LINE__, vsys_sigreturns[i], 
1284                 addr, addr+size);
1285       if (!size)
1286          size = getProcessState()->getAddressWidth();
1287       group->addStepper(parent_stepper, addr, addr + size);
1288    }
1289 }
1290
1291 #else
1292 void SigHandlerStepperImpl::registerStepperGroup(StepperGroup *group)
1293 {
1294    registerStepperGroupNoSymtab(group);
1295 }
1296 #endif
1297
1298 ThreadState* ThreadState::createThreadState(ProcDebug *parent,
1299                                             Dyninst::THR_ID id,
1300                                             bool already_attached)
1301 {
1302    assert(parent);
1303    Dyninst::THR_ID tid = id;
1304    if (id == NULL_THR_ID) {
1305       tid = (Dyninst::THR_ID) parent->getProcessId();
1306    }
1307    else {
1308       tid = id;
1309    }
1310    
1311    ThreadState *newts = new ThreadState(parent, tid);
1312    sw_printf("[%s:%u] - Creating new ThreadState %p for %d/%d\n",
1313              __FILE__, __LINE__, newts, parent->getProcessId(), tid);
1314    if (!newts || newts->state() == ps_errorstate) {
1315       sw_printf("[%s:%u] - Error creating new thread\n",
1316                 __FILE__, __LINE__);
1317       return NULL;
1318    }
1319    if (already_attached) {
1320       newts->setState(ps_attached_intermediate);
1321    }
1322
1323    std::map<pid_t, int>::iterator previous_event;
1324    previous_event = ProcDebugLinux::unknown_pid_events.find(tid);
1325    if (previous_event != ProcDebugLinux::unknown_pid_events.end()) {
1326       int status = (*previous_event).second;
1327       sw_printf("[%s:%u] - Matched new thread %d with old events with statis %lx\n",
1328                 __FILE__, __LINE__, tid, status);
1329       if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP) {
1330          newts->setState(ps_running);
1331       }
1332       ProcDebugLinux::unknown_pid_events.erase(previous_event);
1333    }
1334
1335    ProcDebug::thread_map_t::iterator i = ProcDebugLinux::all_threads.find(tid);
1336    assert(i == ProcDebugLinux::all_threads.end() || 
1337           (*i).second->state() == ps_exited);
1338    ProcDebugLinux::all_threads[tid] = newts;
1339    parent->threads[tid] = newts;
1340
1341    if (id == NULL_THR_ID) {
1342       //Done with work for initial thread
1343       return newts;
1344    }
1345
1346    bool result;
1347
1348    if (newts->state() == ps_neonatal) {
1349       result = parent->debug_attach(newts);
1350       if (!result && getLastError() == err_procexit) {
1351          sw_printf("[%s:%u] - Thread %d exited before attach\n", 
1352                    __FILE__, __LINE__, tid);
1353          newts->setState(ps_exited);
1354          return NULL;
1355       }
1356       else if (!result) {
1357          sw_printf("[%s:%u] - Unknown error attaching to thread %d\n",
1358                    __FILE__, __LINE__, tid);
1359          newts->setState(ps_errorstate);
1360          return NULL;
1361       }
1362    }
1363    result = parent->debug_waitfor_attach(newts);
1364    if (!result) {
1365       sw_printf("[%s:%u] - Error waiting for attach on %d\n", 
1366                 __FILE__, __LINE__, tid);
1367       return NULL;
1368    }
1369
1370    result = parent->debug_post_attach(newts);
1371    if (!result) {
1372       sw_printf("[%s:%u] - Error in post attach on %d\n",
1373                 __FILE__, __LINE__, tid);
1374       return NULL;
1375    }
1376
1377    result = parent->resume_thread(newts);
1378    if (!result) {
1379       sw_printf("[%s:%u] - Error resuming thread %d\n",
1380                 __FILE__, __LINE__, tid);
1381    }
1382    
1383    return newts;
1384 }
1385
1386 BottomOfStackStepperImpl::BottomOfStackStepperImpl(Walker *w, BottomOfStackStepper *p) :
1387    FrameStepper(w),
1388    parent(p),
1389    initialized(false)
1390 {
1391    sw_printf("[%s:%u] - Constructing BottomOfStackStepperImpl at %p\n",
1392              __FILE__, __LINE__, this);
1393 }
1394
1395 gcframe_ret_t BottomOfStackStepperImpl::getCallerFrame(const Frame &in, Frame & /*out*/)
1396 {
1397    /**
1398     * This stepper never actually returns an 'out' frame.  It simply 
1399     * tries to tell if we've reached the top of a stack and returns 
1400     * either gcf_stackbottom or gcf_not_me.
1401     **/
1402    if (!initialized)
1403       initialize();
1404
1405    std::vector<std::pair<Address, Address> >::iterator i;
1406    for (i = ra_stack_tops.begin(); i != ra_stack_tops.end(); i++)
1407    {
1408       if (in.getRA() >= (*i).first && in.getRA() <= (*i).second)
1409          return gcf_stackbottom;
1410    }
1411
1412    for (i = sp_stack_tops.begin(); i != sp_stack_tops.end(); i++)
1413    {
1414       if (in.getSP() >= (*i).first && in.getSP() < (*i).second)
1415          return gcf_stackbottom;
1416    }
1417
1418    /*   if (archIsBottom(in)) {
1419       return gcf_stackbottom;
1420       }*/
1421    return gcf_not_me;
1422 }
1423
1424 unsigned BottomOfStackStepperImpl::getPriority() const
1425 {
1426    //Highest priority, test for top of stack first.
1427    return 0x10000;
1428 }
1429
1430 void BottomOfStackStepperImpl::registerStepperGroup(StepperGroup *group)
1431 {
1432    unsigned addr_width = group->getWalker()->getProcessState()->getAddressWidth();
1433    if (addr_width == 4)
1434       group->addStepper(parent, 0, 0xffffffff);
1435 #if defined(arch_64bit)
1436    else if (addr_width == 8)
1437       group->addStepper(parent, 0, 0xffffffffffffffff);
1438 #endif
1439    else
1440       assert(0 && "Unknown architecture word size");
1441 }
1442
1443 void BottomOfStackStepperImpl::initialize()
1444 {
1445 #if defined(cap_stackwalker_use_symtab)
1446    std::vector<LibAddrPair> libs;
1447    ProcessState *proc = walker->getProcessState();
1448    assert(proc);
1449
1450    sw_printf("[%s:%u] - Initializing BottomOfStackStepper\n", __FILE__, __LINE__);
1451    initialized = true;
1452    
1453    LibraryState *ls = proc->getLibraryTracker();
1454    if (!ls) {
1455       sw_printf("[%s:%u] - Error initing StackBottom.  No library state for process.\n",
1456                 __FILE__, __LINE__);
1457       return;
1458    }
1459    SymtabLibState *symtab_ls = dynamic_cast<SymtabLibState *>(ls);
1460    if (!symtab_ls) {
1461       sw_printf("[%s:%u] - Error initing StackBottom. Unknown library state.\n",
1462                 __FILE__, __LINE__);
1463    }
1464    bool result = false;
1465    std::vector<Function *> funcs;
1466    std::vector<Function *>::iterator i;
1467
1468    //Find _start in a.out
1469    LibAddrPair aout_libaddr = symtab_ls->getAOut();
1470    Symtab *aout = SymtabWrapper::getSymtab(aout_libaddr.first);
1471    if (!aout) {
1472       sw_printf("[%s:%u] - Error. Could not locate a.out\n", __FILE__, __LINE__);
1473    }
1474    else {
1475       result = aout->findFunctionsByName(funcs, "_start");
1476       if (!result || !funcs.size()) {
1477          sw_printf("[%s:%u] - Error. Could not locate _start\n", __FILE__, __LINE__);
1478       }
1479    }
1480    for (i = funcs.begin(); i != funcs.end(); i++) {
1481       Address start = (*i)->getOffset() + aout_libaddr.second;
1482       Address end = start + (*i)->getSize();
1483       sw_printf("[%s:%u] - Adding _start stack bottom [0x%lx, 0x%lx]\n",
1484                 __FILE__, __LINE__, start, end);
1485       ra_stack_tops.push_back(std::pair<Address, Address>(start, end));
1486    }
1487
1488    //Find clone in libc.
1489    LibAddrPair clone_libaddr;
1490    Symtab *clone_symtab = NULL;
1491
1492    LibAddrPair start_thread_libaddr;
1493    Symtab *start_thread_symtab = NULL;
1494
1495    LibAddrPair ld_libaddr;
1496    Symtab *ld_symtab = NULL;
1497    
1498    //Find __clone function in libc
1499    libs.clear();
1500    result = symtab_ls->getLibraries(libs);
1501    if (!result) {
1502       sw_printf("[%s:%u] - Error. Failed to get libraries.\n", 
1503                 __FILE__, __LINE__);
1504       return;
1505    }
1506    
1507    if (libs.size() == 1) {
1508       //Static binary
1509       sw_printf("[%s:%u] - Think binary is static\n", __FILE__, __LINE__);
1510       clone_libaddr = aout_libaddr;
1511       clone_symtab = aout;
1512       start_thread_libaddr = aout_libaddr;
1513       start_thread_symtab = aout;
1514    }
1515    else {
1516       std::vector<LibAddrPair>::iterator i;
1517       for (i = libs.begin(); i != libs.end(); i++) {
1518          if (strstr((*i).first.c_str(), "libc.so") ||
1519              strstr((*i).first.c_str(), "libc-"))
1520          {
1521             clone_libaddr = (*i);
1522             sw_printf("[%s:%u] - Looking for clone in %s\n", 
1523                       __FILE__, __LINE__, clone_libaddr.first.c_str());
1524             clone_symtab = SymtabWrapper::getSymtab(clone_libaddr.first);
1525          }
1526          if (strstr((*i).first.c_str(), "libpthread"))
1527          {
1528             start_thread_libaddr = (*i);
1529             sw_printf("[%s:%u] - Looking for start_thread in %s\n", 
1530                       __FILE__, __LINE__, start_thread_libaddr.first.c_str());
1531             start_thread_symtab = SymtabWrapper::getSymtab(start_thread_libaddr.first);
1532          }
1533          if (strstr((*i).first.c_str(), "ld-"))
1534          {
1535             ld_libaddr = (*i);
1536             sw_printf("[%s:%u] - Looking for _start in %s\n", 
1537                       __FILE__, __LINE__, ld_libaddr.first.c_str());
1538             ld_symtab = SymtabWrapper::getSymtab(ld_libaddr.first);
1539          }
1540       }
1541       if (!clone_symtab) {
1542          sw_printf("[%s:%u] - Looking for clone in a.out\n", __FILE__, __LINE__);
1543          clone_symtab = aout;
1544          clone_libaddr = aout_libaddr;
1545       }
1546       if (!start_thread_symtab) {
1547          sw_printf("[%s:%u] - Looking for start_thread in a.out\n",  __FILE__, __LINE__);
1548          start_thread_symtab = aout;
1549          start_thread_libaddr = aout_libaddr;
1550       }
1551    }
1552
1553    if (ld_symtab) {
1554       std::vector<Symbol *> syms;
1555       std::vector<Symbol *>::iterator si;
1556       result = ld_symtab->findSymbol(syms, "_start");
1557       if (result) {
1558         for (si = syms.begin(); si != syms.end(); si++)
1559         {
1560           Address start = (*si)->getOffset() + ld_libaddr.second;
1561           // TODO There should be a better way of getting the size.
1562           Address end = start + 8;
1563           sw_printf("[%s:%u] - Adding ld _start stack bottom [0x%lx, 0x%lx]\n",
1564                     __FILE__, __LINE__, start, end);
1565           ra_stack_tops.push_back(std::pair<Address, Address>(start, end));
1566         }
1567       }
1568    }
1569
1570    if (clone_symtab) {
1571       funcs.clear();
1572       result = clone_symtab->findFunctionsByName(funcs, "__clone");
1573       if (!result)
1574          return;
1575       for (i = funcs.begin(); i != funcs.end(); i++) {
1576          Address start = (*i)->getOffset() + clone_libaddr.second;
1577          Address end = start + (*i)->getSize();
1578          sw_printf("[%s:%u] - Adding __clone stack bottom [0x%lx, 0x%lx]\n",
1579                    __FILE__, __LINE__, start, end);
1580          ra_stack_tops.push_back(std::pair<Address, Address>(start, end));
1581       }
1582    }
1583
1584    if (start_thread_symtab) {
1585       funcs.clear();
1586       result = start_thread_symtab->findFunctionsByName(funcs, "start_thread");
1587       if (!result)
1588          return;
1589       for (i = funcs.begin(); i != funcs.end(); i++) {
1590          Address start = (*i)->getOffset() + start_thread_libaddr.second;
1591          Address end = start + (*i)->getSize();
1592          sw_printf("[%s:%u] - Adding start_thread stack bottom [0x%lx, 0x%lx]\n",
1593                    __FILE__, __LINE__, start, end);
1594          ra_stack_tops.push_back(std::pair<Address, Address>(start, end));
1595       }
1596    }
1597 #endif
1598 }
1599
1600 BottomOfStackStepperImpl::~BottomOfStackStepperImpl()
1601 {
1602 }
1603