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