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