StackwalkerAPI support for reading local variables in a stack
[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    if (pid_) {
88       setPid(pid_);
89    }
90 }
91
92 void ProcessState::setPid(Dyninst::PID pid_)
93 {
94    pid = pid_;
95    if (pid) {
96       proc_map[pid] = this;
97    }
98 }
99
100 Dyninst::PID ProcessState::getProcessId() 
101 {
102    return pid;
103 }
104
105 void ProcessState::preStackwalk(Dyninst::THR_ID)
106 {
107 }
108
109 void ProcessState::postStackwalk(Dyninst::THR_ID)
110 {
111 }
112
113 void ProcessState::setDefaultLibraryTracker()
114 {
115   if (library_tracker) return;
116 #if defined(cap_stackwalker_use_symtab)
117     library_tracker = new SymtabLibState(this);
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    if (pid)
128       proc_map.erase(pid);
129 }
130
131 int ProcDebug::pipe_in = -1;
132 int ProcDebug::pipe_out = -1;
133
134 ProcDebug::ProcDebug(PID p) : 
135   ProcessState(p),
136   initial_thread(NULL),
137   active_thread(NULL)
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, 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, 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, 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, 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 bool ProcDebug::debug_wait_and_handle(bool block, bool &handled)
555 {
556   bool result;
557   DebugEvent ev = debug_get_event(block);
558
559   if (ev.dbg == dbg_noevent)
560   {
561     sw_printf("[%s:%u] - Returning from debug_wait_and_handle with nothing to do\n",
562               __FILE__, __LINE__);
563     handled = false;
564     return true;
565   }
566   if (ev.dbg == dbg_err)
567   {
568     sw_printf("[%s:%u] - Returning from debug_wait_and_handle with error\n",
569               __FILE__, __LINE__);
570     handled = false;
571     return false;
572   }
573
574   sw_printf("[%s:%u] - Handling event on for pid %d: dbg %d, data %d\n", 
575             __FILE__, __LINE__, ev.proc->pid, ev.dbg, ev.data.idata);
576   result = ev.proc->debug_handle_event(ev);
577
578   if (!result) {
579     sw_printf("[%s:%u] - debug_handle_event returned error for ev.dbg = %d, " \
580               "ev.proc = %d\n", __FILE__, __LINE__, ev.dbg, ev.proc->pid);
581     handled = false;
582     return false;
583   }
584   
585   sw_printf("[%s:%u] - Event %d on pid %d successfully handled\n", 
586             __FILE__, __LINE__, ev.dbg, ev.proc->pid);
587   handled = true;
588   return true;
589
590
591 ProcDebug::~ProcDebug()
592 {
593 }
594
595 unsigned ProcSelf::getAddressWidth()
596 {
597    return sizeof(void *);
598 }
599
600 bool ProcSelf::isFirstParty()
601 {
602   return true;
603 }
604
605 ProcSelf::~ProcSelf()
606 {
607 }
608
609 bool ProcDebug::handleDebugEvent(bool block)
610 {
611   bool result;
612   bool handled;
613   
614   result = debug_wait_and_handle(block, handled);
615   if (!result) {
616     sw_printf("[%s:%u] - Error waiting for event in handleDebugEvent\n",
617               __FILE__, __LINE__);
618     return false;
619   }
620
621   return true;
622 }
623
624 void ProcDebug::preStackwalk(Dyninst::THR_ID tid)
625 {
626    if (tid == NULL_THR_ID)
627       tid = initial_thread->getTid();
628
629    thread_map_t::iterator i = threads.find(tid);
630    if (i == threads.end())
631       return;
632    
633    active_thread = (*i).second;
634    if (!active_thread->userIsStopped()) {
635       active_thread->setShouldResume(true);
636    }
637    if (!active_thread->isStopped())
638       pause_thread(active_thread);
639 }
640
641 void ProcDebug::postStackwalk(Dyninst::THR_ID tid)
642 {
643    if (tid == NULL_THR_ID)
644       tid = initial_thread->getTid();
645
646    thread_map_t::iterator i = threads.find(tid);
647    if (i == threads.end())
648       return;
649    
650    assert(active_thread == (*i).second);
651    if (active_thread->shouldResume()) {
652       resume_thread(active_thread);
653       active_thread->setShouldResume(false);      
654    }
655 }
656
657 bool ProcDebug::isTerminated()
658 {
659    return (state() == ps_exited || state() == ps_errorstate);
660 }
661
662 bool ProcDebug::isFirstParty()
663 {
664   return false;
665 }
666
667 LibraryState::LibraryState(ProcessState *parent) :
668    procstate(parent)
669 {
670 }
671
672 LibraryState::~LibraryState()
673 {
674 }
675
676 #if !defined(os_bluegene)
677 bool ProcDebug::newProcDebugSet(const vector<Dyninst::PID> &pids,
678                                 vector<ProcDebug *> &out_set)
679 {
680    vector<Dyninst::PID>::const_iterator i;
681    for (i=pids.begin(); i!=pids.end(); i++)
682    {
683       Dyninst::PID pid = *i;
684       ProcDebug *new_pd = ProcDebug::newProcDebug(pid);
685       if (!new_pd) {
686          fprintf(stderr, "[%s:%u] - Unable to allocate new ProcDebugBG\n",
687                  __FILE__, __LINE__);
688          return false;
689    }
690       out_set.push_back(new_pd);
691    }
692    return true;
693 }
694 #endif
695
696 LibraryState *ProcessState::getLibraryTracker()
697 {
698    return library_tracker;
699 }
700
701 proc_state ProcDebug::state()
702 {
703    assert(initial_thread);
704    return initial_thread->state();
705 }
706
707 void ProcDebug::setState(proc_state p)
708 {
709    assert(initial_thread);
710    sw_printf("[%s:%u] - Setting initial thread for %d to %d\n",
711              __FILE__, __LINE__, pid, p);
712    initial_thread->setState(p);
713 }
714
715 ThreadState::ThreadState(ProcDebug *p, Dyninst::THR_ID id) :
716    is_stopped(true),
717    user_stopped(true),
718    should_resume(false),
719    tid(id),
720    thr_state(ps_neonatal),
721    parent(p)
722 {
723 }
724
725 bool ThreadState::isStopped()
726 {
727    return is_stopped;
728 }
729
730 void ThreadState::setStopped(bool s)
731 {
732    is_stopped = s;
733 }
734
735 bool ThreadState::userIsStopped()
736 {
737    return user_stopped;
738 }
739
740 void ThreadState::setUserStopped(bool u)
741 {
742    user_stopped = u;
743 }
744
745 bool ThreadState::shouldResume()
746 {
747    return should_resume;
748 }
749
750 void ThreadState::setShouldResume(bool r)
751 {
752    should_resume = r;
753 }
754
755 Dyninst::THR_ID ThreadState::getTid()
756 {
757    return tid;
758 }
759
760 proc_state ThreadState::state()
761 {
762    return thr_state;
763 }
764
765 void ThreadState::setState(proc_state s)
766 {
767    sw_printf("[%s:%u] - Setting thread %d to state %d\n",
768              __FILE__, __LINE__, tid, s);
769    thr_state = s;
770 }
771
772 ProcDebug* ThreadState::proc() 
773 {
774    return parent;
775 }
776
777 ThreadState::~ThreadState()
778 {
779 }