Updates for StackwalkerAPI
[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       bool result = resume_thread(thr);
344       if (result) {
345          thr->setUserStopped(false);
346       }
347    }
348    
349    //Handle the case where we're continuing all threads
350    thread_map_t::iterator i;
351    bool had_error = false;
352    for (i= threads.begin(); i != threads.end(); i++) {
353       thr = (*i).second;
354       assert(thr);
355       if (thr->state() == ps_exited) {
356          sw_printf("[%s:%u] - thread %d on process %d already exited\n",
357                 __FILE__, __LINE__, tid, pid);
358          continue;
359       }
360       sw_printf("[%s:%u] - Continuing thread %d on process %d\n",
361                 __FILE__, __LINE__, tid, pid);
362       bool result = resume_thread(thr);
363    if (!result) {
364          sw_printf("[%s:%u] - Error resumeing thread %d on process %d\n",
365                 __FILE__, __LINE__, tid, pid);
366          had_error = true;
367       }
368       else {
369          thr->setUserStopped(false);
370       }
371    }
372    return !had_error;
373 }
374
375 bool ProcDebug::resume_thread(ThreadState *thr)
376 {
377    Dyninst::THR_ID tid = thr->getTid();
378    sw_printf("[%s:%u] - Top level resume for %d/%d\n",
379              __FILE__, __LINE__, pid, tid);
380    bool result = debug_continue(thr);
381    if (!result) {
382       sw_printf("[%s:%u] - Could not resume debugee %d, thread %d\n",
383                 __FILE__, __LINE__, pid, tid);
384       return false;
385    }
386
387    result = debug_waitfor_continue(thr);
388    if (state() == ps_exited) {
389       setLastError(err_procexit, "Process exited unexpectedly during continue");
390       return false; 
391    }
392    if (!result) {
393       sw_printf("[%s:%u] - Error during process resume for %d\n",
394                 __FILE__, __LINE__, pid);
395       return false;
396    }
397    
398    return true;
399 }
400
401 bool ProcDebug::debug_waitfor_continue(ThreadState *thr)
402 {
403   sw_printf("[%s:%u] - At debug_waitfor_continue, isStopped = %d\n",
404             __FILE__, __LINE__, (int) thr->isStopped());
405   while (thr->isStopped()) {
406     bool handled, result;
407     
408     result = debug_wait_and_handle(true, handled);
409     if (!result || state() == ps_errorstate) {
410       sw_printf("[%s:%u] - Error.  Process %d errored during continue\n",
411                 __FILE__, __LINE__, pid);
412       return false;
413     }
414     if (state() == ps_exited || thr->state() == ps_exited) {
415       sw_printf("[%s:%u] - Error.  Process %d exited during continue\n",
416                 __FILE__, __LINE__, pid);
417       return false;
418     }
419   }
420   sw_printf("[%s:%u] - Successfully continued %d/%d\n",
421             __FILE__, __LINE__, pid, thr->getTid());
422   return true;
423 }
424
425 bool ProcDebug::pause(Dyninst::THR_ID tid)
426 {
427    sw_printf("[%s:%u] - User is stopping process %d, thread %d\n",
428              __FILE__, __LINE__, pid, tid);
429    
430    ThreadState *thr = NULL;
431    if (tid != NULL_THR_ID) {
432       //Handle the case where we're being asked to stop one thread.
433       thread_map_t::iterator i = threads.find(tid);
434       if (i == threads.end()) {
435          sw_printf("[%s:%u] - Thread %d in process %d was not valid\n",
436                    __FILE__, __LINE__, tid, pid);
437          setLastError(err_badparam, "No such thread");
438          return false;
439       }
440       thr = (*i).second;
441       assert(thr);
442       if (thr->state() == ps_exited) {
443          sw_printf("[%s:%u] - Attempt to resume thread %d in proc %d that "
444                    "already exited\n", __FILE__, __LINE__, tid, pid);
445          setLastError(err_procexit, "Thread already exited");
446          return false;
447       }
448       bool result = pause_thread(thr);
449       if (result) {
450          thr->setUserStopped(true);         
451       }
452       return result;
453    }
454    
455    //Handle the case where we're stopping all threads
456    thread_map_t::iterator i;
457    bool had_error = false;
458    for (i = threads.begin(); i != threads.end(); i++) {
459       thr = (*i).second;
460       assert(thr);
461       if (thr->state() == ps_exited) {
462          sw_printf("[%s:%u] - thread %d on process %d already exited\n",
463                 __FILE__, __LINE__, tid, pid);
464          continue;
465       }
466       sw_printf("[%s:%u] - Pausing thread %d on process %d\n",
467                 __FILE__, __LINE__, tid, pid);
468       bool result = pause_thread(thr);
469   if (!result) {
470          sw_printf("[%s:%u] - Error pausing thread %d on process %d\n",
471                 __FILE__, __LINE__, tid, pid);
472          had_error = true;
473       }
474       else {
475          thr->setUserStopped(true);         
476       }
477    }
478    return !had_error;   
479 }
480
481 bool ProcDebug::pause_thread(ThreadState *thr)
482 {
483    Dyninst::THR_ID tid = thr->getTid();
484    sw_printf("[%s:%u] - Top level thread pause for %d/%d\n",
485              __FILE__, __LINE__, pid, tid);
486    bool result = debug_pause(thr);
487    if (!result) {
488       sw_printf("[%s:%u] - Could not pause debuggee %d, thr %d\n",
489                 __FILE__, __LINE__, pid, tid);
490     return false;
491   }
492   
493    result = debug_waitfor_pause(thr);
494    if (thr->state() == ps_exited) {
495     setLastError(err_procexit, "Process exited unexpectedly during pause");
496     return false; 
497   }
498   if (!result) {
499       sw_printf("[%s:%u] - Error during process pause for %d, thr %d\n",
500                 __FILE__, __LINE__, pid, tid);
501     return false;
502   }
503
504    assert(thr->isStopped());
505   return true;
506 }
507
508 bool ProcDebug::debug_waitfor_pause(ThreadState *thr)
509 {
510    Dyninst::THR_ID tid = thr->getTid();
511    sw_printf("[%s:%u] - Waiting for %d, %d to stop\n", __FILE__, __LINE__, pid, tid);
512    while (!thr->isStopped()) {
513     bool handled, result;
514     
515     result = debug_wait_and_handle(true, handled);
516       if (!result || thr->state() == ps_errorstate) {
517          sw_printf("[%s:%u] - Error.  Process %d, %d errored during pause\n",
518                    __FILE__, __LINE__, pid, tid);
519       return false;
520     }
521       if (thr->state() == ps_exited) {
522          sw_printf("[%s:%u] - Error.  Process %d, %d exited during pause\n",
523                    __FILE__, __LINE__, pid, tid);
524       return false;
525     }
526   }
527    sw_printf("[%s:%u] - Successfully stopped %d, %d\n", 
528              __FILE__, __LINE__, pid, tid);
529   return true;
530 }
531
532 bool ProcDebug::debug_wait_and_handle(bool block, bool &handled)
533 {
534   bool result;
535   DebugEvent ev = debug_get_event(block);
536
537   if (ev.dbg == dbg_noevent)
538   {
539     sw_printf("[%s:%u] - Returning from debug_wait_and_handle with nothing to do\n",
540               __FILE__, __LINE__);
541     handled = false;
542     return true;
543   }
544   if (ev.dbg == dbg_err)
545   {
546     sw_printf("[%s:%u] - Returning from debug_wait_and_handle with error\n",
547               __FILE__, __LINE__);
548     handled = false;
549     return false;
550   }
551
552   sw_printf("[%s:%u] - Handling event on for pid %d: dbg %d, data %d\n", 
553             __FILE__, __LINE__, ev.proc->pid, ev.dbg, ev.data.idata);
554   result = ev.proc->debug_handle_event(ev);
555
556   if (!result) {
557     sw_printf("[%s:%u] - debug_handle_event returned error for ev.dbg = %d, " \
558               "ev.proc = %d\n", __FILE__, __LINE__, ev.dbg, ev.proc->pid);
559     handled = false;
560     return false;
561   }
562   
563   sw_printf("[%s:%u] - Event %d on pid %d successfully handled\n", 
564             __FILE__, __LINE__, ev.dbg, ev.proc->pid);
565   handled = true;
566   return true;
567
568
569 ProcDebug::~ProcDebug()
570 {
571 }
572
573 unsigned ProcSelf::getAddressWidth()
574 {
575    return sizeof(void *);
576 }
577
578 ProcSelf::~ProcSelf()
579 {
580 }
581
582 bool ProcDebug::handleDebugEvent(bool block)
583 {
584   bool result;
585   bool handled;
586   
587   result = debug_wait_and_handle(block, handled);
588   if (!result) {
589     sw_printf("[%s:%u] - Error waiting for event in handleDebugEvent\n",
590               __FILE__, __LINE__);
591     return false;
592   }
593
594   return true;
595 }
596
597 void ProcDebug::preStackwalk(Dyninst::THR_ID tid)
598 {
599    if (tid == NULL_THR_ID)
600       tid = initial_thread->getTid();
601
602    thread_map_t::iterator i = threads.find(tid);
603    if (i == threads.end())
604       return;
605    
606    active_thread = (*i).second;
607    if (!active_thread->userIsStopped()) {
608       active_thread->setShouldResume(true);
609    }
610    if (!active_thread->isStopped())
611       pause_thread(active_thread);
612 }
613
614 void ProcDebug::postStackwalk(Dyninst::THR_ID tid)
615 {
616    if (tid == NULL_THR_ID)
617       tid = initial_thread->getTid();
618
619    thread_map_t::iterator i = threads.find(tid);
620    if (i == threads.end())
621       return;
622    
623    assert(active_thread == (*i).second);
624    if (active_thread->shouldResume()) {
625       resume_thread(active_thread);
626       active_thread->setShouldResume(false);      
627    }
628 }
629
630 bool ProcDebug::isTerminated()
631 {
632    return (state() == ps_exited || state() == ps_errorstate);
633 }
634
635 LibraryState::LibraryState(ProcessState *parent) :
636    procstate(parent)
637 {
638 }
639
640 LibraryState::~LibraryState()
641 {
642 }
643
644 #if !defined(os_bluegene)
645 bool ProcDebug::newProcDebugSet(const vector<Dyninst::PID> &pids,
646                                 vector<ProcDebug *> &out_set)
647 {
648    vector<Dyninst::PID>::const_iterator i;
649    for (i=pids.begin(); i!=pids.end(); i++)
650    {
651       Dyninst::PID pid = *i;
652       ProcDebug *new_pd = ProcDebug::newProcDebug(pid);
653       if (!new_pd) {
654          fprintf(stderr, "[%s:%u] - Unable to allocate new ProcDebugBG\n",
655                  __FILE__, __LINE__);
656          return false;
657    }
658       out_set.push_back(new_pd);
659    }
660    return true;
661 }
662 #endif
663
664 LibraryState *ProcessState::getLibraryTracker()
665 {
666    return library_tracker;
667 }
668
669 proc_state ProcDebug::state()
670 {
671    assert(initial_thread);
672    return initial_thread->state();
673 }
674
675 void ProcDebug::setState(proc_state p)
676 {
677    assert(initial_thread);
678    sw_printf("[%s:%u] - Setting initial thread for %d to %d\n",
679              __FILE__, __LINE__, pid, p);
680    initial_thread->setState(p);
681 }
682
683 ThreadState::ThreadState(ProcDebug *p, Dyninst::THR_ID id) :
684    is_stopped(true),
685    user_stopped(true),
686    should_resume(false),
687    tid(id),
688    thr_state(ps_neonatal),
689    parent(p)
690 {
691 }
692
693 bool ThreadState::isStopped()
694 {
695    return is_stopped;
696 }
697
698 void ThreadState::setStopped(bool s)
699 {
700    is_stopped = s;
701 }
702
703 bool ThreadState::userIsStopped()
704 {
705    return user_stopped;
706 }
707
708 void ThreadState::setUserStopped(bool u)
709 {
710    user_stopped = u;
711 }
712
713 bool ThreadState::shouldResume()
714 {
715    return should_resume;
716 }
717
718 void ThreadState::setShouldResume(bool r)
719 {
720    should_resume = r;
721 }
722
723 Dyninst::THR_ID ThreadState::getTid()
724 {
725    return tid;
726 }
727
728 proc_state ThreadState::state()
729 {
730    return thr_state;
731 }
732
733 void ThreadState::setState(proc_state s)
734 {
735    sw_printf("[%s:%u] - Setting thread %d to state %d\n",
736              __FILE__, __LINE__, tid, s);
737    thr_state = s;
738 }
739
740 ProcDebug* ThreadState::proc() 
741 {
742    return parent;
743 }
744
745 ThreadState::~ThreadState()
746 {
747 }