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