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