Fix Stackwalker Linux issues with inconsistent SIGCHLD delivery
[dyninst.git] / stackwalk / src / procstate.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/procstate.h"
34 #include "common/h/headers.h"
35 #include <assert.h>
36 #include <string>
37 #include <vector>
38 #if defined(cap_stackwalker_use_symtab)
39 #include "stackwalk/src/symtab-swk.h"
40 #endif
41
42 using namespace Dyninst;
43 using namespace Dyninst::Stackwalker;
44 using namespace std;
45
46 class DefaultLibState : public LibraryState
47 {
48 public:
49    DefaultLibState(ProcessState *parent) : 
50       LibraryState(parent) 
51    {
52    }
53
54    virtual bool getLibraryAtAddr(Address, LibAddrPair &) {
55       return false;
56    }
57
58    virtual bool getLibraries(std::vector<LibAddrPair> &) {
59       return false;
60    }
61
62    virtual void notifyOfUpdate() {
63    }
64
65    virtual Address getLibTrapAddress() {
66       return 0x0;
67    }
68
69    ~DefaultLibState() { 
70    }
71 };
72
73 std::map<Dyninst::PID, ProcessState *> ProcessState::proc_map;
74
75 ProcessState::ProcessState(Dyninst::PID pid_) :
76    library_tracker(NULL)
77 {
78    std::map<PID, ProcessState *>::iterator i = proc_map.find(pid_);
79    if (i != proc_map.end())
80    {
81       sw_printf("[%s:%u] - Already attached to debuggee %d\n",
82                 __FILE__, __LINE__, pid_);
83       setLastError(err_badparam, "Attach requested to already " \
84                    "attached process");
85       return;
86    }
87    setPid(pid_);
88 }
89
90 void ProcessState::setPid(Dyninst::PID pid_)
91 {
92    pid = pid_;
93    proc_map[pid] = this;
94 }
95
96 Dyninst::PID ProcessState::getProcessId() 
97 {
98    return pid;
99 }
100
101 void ProcessState::preStackwalk(Dyninst::THR_ID)
102 {
103 }
104
105 void ProcessState::postStackwalk(Dyninst::THR_ID)
106 {
107 }
108
109 void ProcessState::setDefaultLibraryTracker()
110 {
111   if (library_tracker) return;
112 #if defined(cap_stackwalker_use_symtab)
113   std::string execp("");
114   ProcDebug *pd = dynamic_cast<ProcDebug *>(this);
115   if (pd) 
116      execp = pd->getExecutablePath();
117   library_tracker = new SymtabLibState(this, execp);
118 #else
119   library_tracker = new DefaultLibState(this);
120 #endif
121 }
122
123 ProcessState::~ProcessState()
124 {
125    if (library_tracker)
126       delete library_tracker;
127    proc_map.erase(pid);
128 }
129
130 int ProcDebug::pipe_in = -1;
131 int ProcDebug::pipe_out = -1;
132
133 ProcDebug::ProcDebug(PID p, string exe) : 
134   ProcessState(p),
135   initial_thread(NULL),
136   active_thread(NULL),
137   executable_path(exe)
138 {
139    initial_thread = ThreadState::createThreadState(this);
140    threads[initial_thread->getTid()] = initial_thread;   
141 }
142
143 ProcDebug::ProcDebug(const std::string & /*executable*/, 
144                      const std::vector<std::string> & /*argv*/) : 
145    ProcessState(0),
146    initial_thread(NULL),
147    active_thread(NULL)
148 {
149 }
150
151 bool ProcDebug::create(const string &executable, 
152                        const vector<string> &argv)
153 {
154   bool result = debug_create(executable, argv);
155   if (!result) {
156     sw_printf("[%s:%u] - Could not create debuggee, %s\n",
157               __FILE__, __LINE__, executable.c_str());
158     return false;
159   }
160
161   setPid(pid);
162   initial_thread = ThreadState::createThreadState(this, NULL_THR_ID, true);
163
164   threads[initial_thread->getTid()] = initial_thread;   
165
166   sw_printf("[%s:%u] - Created debugged %s on pid %d\n",
167             __FILE__, __LINE__, executable.c_str(), pid);
168   result = debug_waitfor_create();
169   if (state() == ps_exited) {
170      sw_printf("[%s:%u] - Process %s exited during create\n", 
171                __FILE__, __LINE__, executable.c_str());
172     return false; 
173   }
174   if (!result) {
175     sw_printf("[%s:%u] - Error during process create for %d\n",
176               __FILE__, __LINE__, pid);
177     return false;
178   }
179   result = debug_post_create();
180     if (!result) {
181     sw_printf("[%s:%u] - Error during post create for %d\n",
182                 __FILE__, __LINE__, pid);
183       return false;
184     }
185      
186   assert(state() == ps_running);
187   
188   return true;
189 }
190
191 bool ProcDebug::debug_waitfor_create()
192 {
193   for (;;) {
194     bool handled, result;
195     
196     result = debug_wait_and_handle(true, false, handled);
197     if (!result || state() == ps_errorstate) {
198       sw_printf("[%s:%u] - Error.  Process %d errored during create\n",
199                 __FILE__, __LINE__, pid);
200       return false;
201     }
202     if (state() == ps_exited) {
203       sw_printf("[%s:%u] - Error.  Process %d exited during create\n",
204                 __FILE__, __LINE__, pid);
205       return false;
206     }
207     if (state() == ps_running) {
208       sw_printf("[%s:%u] - Successfully completed create on %d\n",
209                 __FILE__, __LINE__, pid);
210       return true;
211     }
212   }
213 }
214
215 bool ProcDebug::multi_attach(vector<ProcDebug *> &pids)
216 {
217    bool result;
218    bool had_error = false;
219    vector<ProcDebug *>::iterator i;
220
221 #define for_each_procdebug(func, cond, err_msg) \
222    for (i = pids.begin(); i != pids.end(); i++) { \
223       ProcDebug *pd = (*i); \
224       if (!pd) \
225         continue; \
226       if (!cond) \
227         continue; \
228       result = pd->func(pd->initial_thread); \
229       if (!result) { \
230          sw_printf("[%s:%u] - Could not %s to %d", __FILE__, __LINE__, err_msg, pd->pid); \
231          delete pd; \
232          *i = NULL; \
233          had_error = true; \
234       } \
235    }
236
237    for_each_procdebug(debug_attach, true, "attach");
238
239    for_each_procdebug(debug_waitfor_attach, true, "wait for attach");
240
241    for_each_procdebug(debug_post_attach, true, "post attach");
242
243    for_each_procdebug(debug_continue, (pd->state() != ps_running), "send continue");
244
245    return had_error;
246 }
247
248 bool ProcDebug::attach()
249 {
250   bool result = debug_attach(initial_thread);
251   if (!result) {
252     sw_printf("[%s:%u] - Could not attach to debuggee, %d\n",
253               __FILE__, __LINE__, pid);
254     return false;
255   }
256
257   result = debug_waitfor_attach(initial_thread);
258   if (!result) {
259      sw_printf("[%s:%u] - Error waiting for attach\n", __FILE__, __LINE__);
260      goto error;
261   }
262
263   result = debug_post_attach(initial_thread);
264   if (!result) {
265      sw_printf("[%s:%u] - Error on post attach for %d\n",
266                __FILE__, __LINE__, pid);
267      goto error;
268   }
269
270   if (state() != ps_running) {
271      result = debug_continue(initial_thread);
272      if (!result) {
273         sw_printf("[%s:%u] - Could not continue debuggee %d after attach\n",
274                   __FILE__, __LINE__, pid);
275         goto error;
276      }
277   }
278
279   return true;
280
281  error:
282   if (state() == ps_exited) {
283     setLastError(err_procexit, "Process exited unexpectedly during attach");
284   }
285   sw_printf("[%s:%u] - Error during process attach for %d\n",
286             __FILE__, __LINE__, pid);
287   return false;
288 }
289
290
291 bool ProcDebug::debug_waitfor_attach(ThreadState *ts)
292 {
293   Dyninst::THR_ID tid = ts->getTid();
294   for (;;) {
295     bool handled, result;
296
297     if (ts->state() == ps_exited) {
298       sw_printf("[%s:%u] - Error.  Thread %d/%d exited during attach\n",
299                 __FILE__, __LINE__, pid, tid);
300       return false;
301     }
302     if (ts->state() == ps_attached || ts->state() == ps_running)  {
303       sw_printf("[%s:%u] - Successfully completed attach on %d/%d\n",
304                 __FILE__, __LINE__, pid, tid);
305       return true;
306     }
307     
308     result = debug_wait_and_handle(true, false, handled);
309     if (!result || ts->state() == ps_errorstate) {
310       sw_printf("[%s:%u] - Error.  Thread %d/%d errored during attach\n",
311                 __FILE__, __LINE__, pid, tid);
312       return false;
313     }
314   }
315 }
316
317 bool ProcDebug::debug_post_attach(ThreadState *)
318 {
319    return true;
320 }
321
322 bool ProcDebug::debug_post_create()
323 {
324    return true;
325 }
326
327 bool ProcDebug::resume(Dyninst::THR_ID tid)
328 {
329    sw_printf("[%s:%u] - User is continuing process %d, thread %d\n",
330              __FILE__, __LINE__, pid, tid);
331    
332    ThreadState *thr = NULL;
333    if (tid != NULL_THR_ID) {
334       //Handle the case where we're being asked to continue one thread.
335       thread_map_t::iterator i = threads.find(tid);
336       if (i == threads.end()) {
337          sw_printf("[%s:%u] - Thread %d in process %d was not valid\n",
338                    __FILE__, __LINE__, tid, pid);
339          setLastError(err_badparam, "No such thread");
340          return false;
341       }
342       thr = (*i).second;
343       assert(thr);
344       if (thr->state() == ps_exited) {
345          sw_printf("[%s:%u] - Attempt to resume thread %d in proc %d that "
346                    "already exited\n", __FILE__, __LINE__, tid, pid);
347          setLastError(err_badparam, "Thread already exited");
348          return false;
349       }
350       if (!thr->isStopped()) {
351          sw_printf("[%s:%u] - thread %d is already running on process %d\n",
352                    __FILE__, __LINE__, tid, pid);
353          thr->setUserStopped(false);
354       }
355       else {
356          bool result = resume_thread(thr);
357          if (result) {
358             thr->setUserStopped(false);
359          }
360       }
361    }
362    
363    //Handle the case where we're continuing all threads
364    thread_map_t::iterator i;
365    bool had_error = false;
366    for (i = threads.begin(); i != threads.end(); i++) {
367       thr = (*i).second;
368       int thr_tid = thr->getTid();
369       assert(thr);
370       if (thr->state() == ps_exited) {
371          sw_printf("[%s:%u] - thread %d on process %d already exited\n",
372                 __FILE__, __LINE__, thr_tid, pid);
373          continue;
374       }
375       if (!thr->isStopped()) {
376          sw_printf("[%s:%u] - thread %d is already running on process %d\n",
377                    __FILE__, __LINE__, thr_tid, pid);
378          thr->setUserStopped(false);
379          continue;
380       }
381
382       sw_printf("[%s:%u] - Continuing thread %d on process %d\n",
383                 __FILE__, __LINE__, thr_tid, pid);
384       bool result = resume_thread(thr);
385       if (!result) {
386          sw_printf("[%s:%u] - Error resuming thread %d on process %d\n",
387                 __FILE__, __LINE__, thr_tid, pid);
388          had_error = true;
389       }
390       else {
391          thr->setUserStopped(false);
392       }
393    }
394    return !had_error;
395 }
396
397 bool ProcDebug::resume_thread(ThreadState *thr)
398 {
399    Dyninst::THR_ID tid = thr->getTid();
400    sw_printf("[%s:%u] - Top level resume for %d/%d\n",
401              __FILE__, __LINE__, pid, tid);
402    bool result = debug_continue(thr);
403    if (!result) {
404       sw_printf("[%s:%u] - Could not resume debugee %d, thread %d\n",
405                 __FILE__, __LINE__, pid, tid);
406       return false;
407    }
408
409    result = debug_waitfor_continue(thr);
410    if (state() == ps_exited) {
411       setLastError(err_procexit, "Process exited unexpectedly during continue");
412       return false; 
413    }
414    if (!result) {
415       sw_printf("[%s:%u] - Error during process resume for %d\n",
416                 __FILE__, __LINE__, pid);
417       return false;
418    }
419    
420    return true;
421 }
422
423 bool ProcDebug::debug_waitfor_continue(ThreadState *thr)
424 {
425   sw_printf("[%s:%u] - At debug_waitfor_continue, isStopped = %d\n",
426             __FILE__, __LINE__, (int) thr->isStopped());
427   while (thr->isStopped()) {
428     bool handled, result;
429     
430     result = debug_wait_and_handle(true, false, handled);
431     if (!result || state() == ps_errorstate) {
432       sw_printf("[%s:%u] - Error.  Process %d errored during continue\n",
433                 __FILE__, __LINE__, pid);
434       return false;
435     }
436     if (state() == ps_exited || thr->state() == ps_exited) {
437       sw_printf("[%s:%u] - Error.  Process %d exited during continue\n",
438                 __FILE__, __LINE__, pid);
439       return false;
440     }
441   }
442   sw_printf("[%s:%u] - Successfully continued %d/%d\n",
443             __FILE__, __LINE__, pid, thr->getTid());
444   return true;
445 }
446
447 bool ProcDebug::pause(Dyninst::THR_ID tid)
448 {
449    sw_printf("[%s:%u] - User is stopping process %d, thread %d\n",
450              __FILE__, __LINE__, pid, tid);
451    
452    ThreadState *thr = NULL;
453    if (tid != NULL_THR_ID) {
454       //Handle the case where we're being asked to stop one thread.
455       thread_map_t::iterator i = threads.find(tid);
456       if (i == threads.end()) {
457          sw_printf("[%s:%u] - Thread %d in process %d was not valid\n",
458                    __FILE__, __LINE__, tid, pid);
459          setLastError(err_badparam, "No such thread");
460          return false;
461       }
462       thr = (*i).second;
463       assert(thr);
464       if (thr->state() == ps_exited) {
465          sw_printf("[%s:%u] - Attempt to resume thread %d in proc %d that "
466                    "already exited\n", __FILE__, __LINE__, tid, pid);
467          setLastError(err_procexit, "Thread already exited");
468          return false;
469       }
470       bool result = pause_thread(thr);
471       if (result) {
472          thr->setUserStopped(true);         
473       }
474       return result;
475    }
476    
477    //Handle the case where we're stopping all threads
478    thread_map_t::iterator i;
479    bool had_error = false;
480    for (i = threads.begin(); i != threads.end(); i++) {
481       thr = (*i).second;
482       assert(thr);
483       if (thr->state() == ps_exited) {
484          sw_printf("[%s:%u] - thread %d on process %d already exited\n",
485                 __FILE__, __LINE__, tid, pid);
486          continue;
487       }
488       sw_printf("[%s:%u] - Pausing thread %d on process %d\n",
489                 __FILE__, __LINE__, tid, pid);
490       bool result = pause_thread(thr);
491       if (!result) {
492          sw_printf("[%s:%u] - Error pausing thread %d on process %d\n",
493                 __FILE__, __LINE__, tid, pid);
494          had_error = true;
495       }
496       else {
497          thr->setUserStopped(true);         
498       }
499    }
500    return !had_error;   
501 }
502
503 bool ProcDebug::pause_thread(ThreadState *thr)
504 {
505    Dyninst::THR_ID tid = thr->getTid();
506    sw_printf("[%s:%u] - Top level thread pause for %d/%d\n",
507              __FILE__, __LINE__, pid, tid);
508    bool result = debug_pause(thr);
509    if (!result) {
510       sw_printf("[%s:%u] - Could not pause debuggee %d, thr %d\n",
511                 __FILE__, __LINE__, pid, tid);
512     return false;
513   }
514   
515    result = debug_waitfor_pause(thr);
516    if (thr->state() == ps_exited) {
517     setLastError(err_procexit, "Process exited unexpectedly during pause");
518     return false; 
519   }
520   if (!result) {
521       sw_printf("[%s:%u] - Error during process pause for %d, thr %d\n",
522                 __FILE__, __LINE__, pid, tid);
523     return false;
524   }
525
526    assert(thr->isStopped());
527   return true;
528 }
529
530 bool ProcDebug::debug_waitfor_pause(ThreadState *thr)
531 {
532    Dyninst::THR_ID tid = thr->getTid();
533    sw_printf("[%s:%u] - Waiting for %d, %d to stop\n", __FILE__, __LINE__, pid, tid);
534    while (!thr->isStopped()) {
535       bool handled, result;
536       
537       result = debug_wait_and_handle(true, false, handled);
538       if (!result || thr->state() == ps_errorstate) {
539          sw_printf("[%s:%u] - Error.  Process %d, %d errored during pause\n",
540                    __FILE__, __LINE__, pid, tid);
541          return false;
542       }
543       if (thr->state() == ps_exited) {
544          sw_printf("[%s:%u] - Error.  Process %d, %d exited during pause\n",
545                    __FILE__, __LINE__, pid, tid);
546          return false;
547       }
548    }
549    sw_printf("[%s:%u] - Successfully stopped %d, %d\n", 
550              __FILE__, __LINE__, pid, tid);
551   return true;
552 }
553
554
555 bool ProcDebug::debug_waitfor(dbg_t event_type) {
556   bool handled;
557   dbg_t handled_type;
558   bool flush = false;
559 #if defined(os_linux)
560   flush = true;
561 #endif
562   while (debug_wait_and_handle(true, flush, handled, &handled_type)) {
563     if (handled_type == event_type) {
564       return true;
565     }
566   }
567   return false;
568 }
569
570
571 bool ProcDebug::debug_wait_and_handle(bool block, bool flush, bool &handled, 
572                                       dbg_t *event_type)
573 {
574   bool result;
575   handled = false;
576   
577   for (;;) {
578      DebugEvent ev = debug_get_event(block);
579
580      if (ev.dbg == dbg_noevent)
581      {
582         sw_printf("[%s:%u] - Returning from debug_wait_and_handle, %s.\n",
583                   __FILE__, __LINE__, handled ? "handled event" : "no event");
584         if (!handled && event_type) {
585            *event_type = dbg_noevent;
586         }
587         return true;
588      }
589      if (event_type) {
590         *event_type = ev.dbg;
591      }
592      if (ev.dbg == dbg_err)
593      {
594         sw_printf("[%s:%u] - Returning from debug_wait_and_handle with error\n",
595                   __FILE__, __LINE__);
596         return false;
597      }
598
599      sw_printf("[%s:%u] - Handling event for pid %d: dbg %d, data %d\n", 
600                __FILE__, __LINE__, ev.proc->pid, ev.dbg, ev.data.idata);
601      result = ev.proc->debug_handle_event(ev);
602      if (!result) {
603         sw_printf("[%s:%u] - debug_handle_event returned error for ev.dbg = %d, " \
604                   "ev.proc = %d\n", __FILE__, __LINE__, ev.dbg, ev.proc->pid);
605         handled = false;
606         return false;
607      }
608      
609      sw_printf("[%s:%u] - Event %d on pid %d successfully handled\n", 
610                __FILE__, __LINE__, ev.dbg, ev.proc->pid);
611      handled = true;
612
613      if (!flush)
614         break;
615      block = false;
616   }
617   return true;
618
619
620
621 bool ProcDebug::add_new_thread(THR_ID tid) {
622   if (threads.count(tid)) return true;
623
624   sw_printf("[%s:%u] - Adding new thread %d, in proc %d\n",
625             __FILE__, __LINE__, tid, pid);
626
627   ThreadState *new_thread = ThreadState::createThreadState(this, tid);
628   threads[tid] = new_thread;
629   
630   if (!new_thread && getLastError() == err_noproc) {
631     //Race condition, get thread ID or running thread, which then 
632     // exits.  Should be rare...
633     sw_printf("[%s:%u] - Error creating thread %d, does not exist\n",
634               __FILE__, __LINE__, tid);
635     clearLastError();
636     return false;
637
638   } else if (!new_thread) {
639     sw_printf("[%s:%u] - Unexpected error creating thread %d\n",
640               __FILE__, __LINE__, tid);
641     return false;
642   }
643
644   return true;
645 }
646
647
648 ProcDebug::~ProcDebug()
649 {
650 }
651
652 unsigned ProcSelf::getAddressWidth()
653 {
654    return sizeof(void *);
655 }
656
657 bool ProcSelf::isFirstParty()
658 {
659   return true;
660 }
661
662 ProcSelf::~ProcSelf()
663 {
664 }
665
666 bool ProcDebug::handleDebugEvent(bool block)
667 {
668   bool result;
669   bool handled;
670   
671   result = debug_wait_and_handle(block, true, handled);
672   if (!result) {
673     sw_printf("[%s:%u] - Error waiting for event in handleDebugEvent\n",
674               __FILE__, __LINE__);
675     return false;
676   }
677
678   return true;
679 }
680
681 void ProcDebug::preStackwalk(Dyninst::THR_ID tid)
682 {
683    if (tid == NULL_THR_ID)
684       tid = initial_thread->getTid();
685
686    sw_printf("[%s:%u] - Calling preStackwalk for thread %d\n", __FILE__, __LINE__, tid);
687
688    thread_map_t::iterator i = threads.find(tid);
689    if (i == threads.end()) {
690       sw_printf("[%s:%u] - Couldn't find thread %d!\n", __FILE__, __LINE__, tid);
691       return;
692    }
693    
694    active_thread = (*i).second;
695    if (!active_thread->userIsStopped()) {
696       active_thread->setShouldResume(true);
697    }
698    if (!active_thread->isStopped())
699       pause_thread(active_thread);
700 }
701
702 void ProcDebug::postStackwalk(Dyninst::THR_ID tid)
703 {
704    if (tid == NULL_THR_ID)
705       tid = initial_thread->getTid();
706
707    sw_printf("[%s:%u] - Calling preStackwalk for thread %d\n", __FILE__, __LINE__, tid);
708
709    thread_map_t::iterator i = threads.find(tid);
710    if (i == threads.end()) {
711       sw_printf("[%s:%u] - Couldn't find thread %d!\n", __FILE__, __LINE__, tid);
712       return;
713    }
714
715    assert(active_thread == (*i).second);
716    if (active_thread->shouldResume()) {
717       resume_thread(active_thread);
718       active_thread->setShouldResume(false);      
719    }
720 }
721
722 bool ProcDebug::isTerminated()
723 {
724    return (state() == ps_exited || state() == ps_errorstate);
725 }
726
727 bool ProcDebug::isFirstParty()
728 {
729   return false;
730 }
731
732 LibraryState::LibraryState(ProcessState *parent) :
733    procstate(parent)
734 {
735 }
736
737 LibraryState::~LibraryState()
738 {
739 }
740
741 #ifndef os_bg_ion
742 bool ProcDebug::newProcDebugSet(const vector<Dyninst::PID> &pids,
743                                 vector<ProcDebug *> &out_set)
744 {
745    vector<Dyninst::PID>::const_iterator i;
746    for (i=pids.begin(); i!=pids.end(); i++)
747    {
748       Dyninst::PID pid = *i;
749       ProcDebug *new_pd = ProcDebug::newProcDebug(pid);
750       if (!new_pd) {
751          fprintf(stderr, "[%s:%u] - Unable to allocate new ProcDebugBG\n",
752                  __FILE__, __LINE__);
753          return false;
754    }
755       out_set.push_back(new_pd);
756    }
757    return true;
758 }
759 #endif // !os_bg_ion
760
761 LibraryState *ProcessState::getLibraryTracker()
762 {
763    return library_tracker;
764 }
765
766 proc_state ProcDebug::state()
767 {
768    assert(initial_thread);
769    return initial_thread->state();
770 }
771
772 void ProcDebug::setState(proc_state p)
773 {
774    assert(initial_thread);
775    sw_printf("[%s:%u] - Setting initial thread for %d to state %d\n",
776              __FILE__, __LINE__, pid, p);
777    initial_thread->setState(p);
778 }
779
780 const string& ProcDebug::getExecutablePath() {
781   return executable_path;
782 }
783
784 ThreadState::ThreadState(ProcDebug *p, Dyninst::THR_ID id) :
785    is_stopped(true),
786    user_stopped(true),
787    should_resume(false),
788    tid(id),
789    thr_state(ps_neonatal),
790    parent(p)
791 {
792 }
793
794 bool ThreadState::isStopped()
795 {
796    return is_stopped;
797 }
798
799 void ThreadState::setStopped(bool s)
800 {
801    is_stopped = s;
802 }
803
804 bool ThreadState::userIsStopped()
805 {
806    return user_stopped;
807 }
808
809 void ThreadState::setUserStopped(bool u)
810 {
811    user_stopped = u;
812 }
813
814 bool ThreadState::shouldResume()
815 {
816    return should_resume;
817 }
818
819 void ThreadState::setShouldResume(bool r)
820 {
821    should_resume = r;
822 }
823
824 Dyninst::THR_ID ThreadState::getTid()
825 {
826    return tid;
827 }
828
829 proc_state ThreadState::state()
830 {
831    return thr_state;
832 }
833
834 void ThreadState::setState(proc_state s)
835 {
836    sw_printf("[%s:%u] - Setting thread %d to state %d\n",
837              __FILE__, __LINE__, tid, s);
838    thr_state = s;
839 }
840
841 ProcDebug* ThreadState::proc() 
842 {
843    return parent;
844 }
845
846 ThreadState::~ThreadState()
847 {
848 }