Fix Stackwalker Linux issues with inconsistent SIGCHLD delivery
[dyninst.git] / stackwalk / h / procstate.h
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 //TODO: isRunning(), isStopped()...
33 //TODO: Bug if trying to stop an already stopped process
34
35 #ifndef PROCSTATE_H_
36 #define PROCSTATE_H_
37
38 #include "basetypes.h"
39
40 #include <vector>
41 #include <map>
42 #include <queue>
43
44 namespace Dyninst {
45 namespace Stackwalker {
46
47 class LibraryState;
48 class ThreadState;
49
50 class ProcessState {
51 protected:
52    Dyninst::PID pid;
53    LibraryState *library_tracker;
54    
55    static std::map<Dyninst::PID, ProcessState *> proc_map;
56
57    ProcessState(Dyninst::PID pid_ = 0);
58    void setPid(Dyninst::PID pid_);
59 public:
60
61   //look-up Process-State by pid
62   static ProcessState* getProcessStateByPid(Dyninst::PID pid);
63
64   //Read register in thread
65   virtual bool getRegValue(Dyninst::MachRegister reg, Dyninst::THR_ID thread, Dyninst::MachRegisterVal &val) = 0;
66   
67   //Read memory in process
68   virtual bool readMem(void *dest, Dyninst::Address source, size_t size) = 0;
69
70   //Return list of available threads
71   virtual bool getThreadIds(std::vector<Dyninst::THR_ID> &threads) = 0;
72   
73   //Return the default thread
74   virtual bool getDefaultThread(Dyninst::THR_ID &default_tid) = 0;
75
76   //Return PID
77   virtual Dyninst::PID getProcessId();
78
79   //Return the size of an address in process in bytes
80   virtual unsigned getAddressWidth() = 0;
81
82   virtual ~ProcessState();
83
84   void setLibraryTracker(LibraryState *);
85   void setDefaultLibraryTracker();
86   LibraryState *getLibraryTracker();
87
88   //Allow initialization/uninitialization
89   virtual void preStackwalk(Dyninst::THR_ID tid);
90   virtual void postStackwalk(Dyninst::THR_ID tid);
91
92   virtual bool isFirstParty() = 0;
93 };
94
95 class ProcSelf : public ProcessState {
96  public:
97   ProcSelf();
98   void initialize();
99
100   virtual bool getRegValue(Dyninst::MachRegister reg, Dyninst::THR_ID thread, Dyninst::MachRegisterVal &val);
101   virtual bool readMem(void *dest, Dyninst::Address source, size_t size);
102   virtual bool getThreadIds(std::vector<Dyninst::THR_ID> &threads);
103   virtual bool getDefaultThread(Dyninst::THR_ID &default_tid);
104   virtual unsigned getAddressWidth();
105   virtual bool isFirstParty();
106   virtual ~ProcSelf();
107 };
108
109 typedef enum {
110   ps_neonatal,                // 0
111   ps_attached_intermediate,
112   ps_attached,
113   ps_running,
114   ps_exited,
115   ps_errorstate,              // 5
116 } proc_state;
117
118 typedef enum {
119   dbg_err,           // 0
120   dbg_exited,
121   dbg_crashed,
122   dbg_stopped,
123   dbg_other,
124   dbg_noevent,      // 5
125   dbg_libraryload,
126   // BG events are below.
127   dbg_continued,
128   dbg_mem_ack,
129   dbg_setmem_ack,
130   dbg_reg_ack,      // 10
131   dbg_allregs_ack,
132   dbg_attached,
133   dbg_thread_info,
134 } dbg_t;
135
136 class ProcDebug;
137
138 struct DebugEvent {
139    dbg_t dbg;
140    union {
141       int idata;
142       void *pdata;
143    } data;
144    unsigned size;
145    ProcDebug *proc;
146    ThreadState *thr;
147
148    DebugEvent() : dbg(dbg_noevent), size(0), proc(NULL), thr(NULL) {}
149 };
150
151 struct procdebug_ltint
152 {
153    bool operator()(int a, int b) const;
154 };
155
156 class ProcDebug : public ProcessState {
157   friend class Walker;
158   friend class ThreadState;
159  protected:
160   ProcDebug(Dyninst::PID pid, std::string executable="");
161   ProcDebug(const std::string &executable, 
162             const std::vector<std::string> &argv);
163   
164   /**
165    * attach() is the top-level command, and is implemented by debug_attach and
166    * debug_waitfor_attach. 
167    **/
168   virtual bool attach();
169   static bool multi_attach(std::vector<ProcDebug *> &pids);
170
171
172   virtual bool debug_attach(ThreadState *ts) = 0;
173   virtual bool debug_waitfor_attach(ThreadState *ts);
174   virtual bool debug_post_attach(ThreadState *ts);
175   virtual bool debug_post_create();
176
177   virtual bool create(const std::string &executable, 
178                       const std::vector<std::string> &argv);
179   virtual bool debug_create(const std::string &executable, 
180                             const std::vector<std::string> &argv) = 0;
181   virtual bool debug_waitfor_create();
182   
183   /**
184    * pause() is the top-level command (under the public section), and is 
185    * implemented by debug_pause() and debug_waitfor_pause()
186    **/
187   virtual bool pause_thread(ThreadState *thr);
188   virtual bool debug_pause(ThreadState *thr) = 0;
189   virtual bool debug_waitfor_pause(ThreadState *thr);
190
191   virtual bool resume_thread(ThreadState *thr);
192   virtual bool debug_continue(ThreadState *thr) = 0;
193   virtual bool debug_continue_with(ThreadState *thr, long sig) = 0;
194   virtual bool debug_waitfor_continue(ThreadState *thr);
195
196   virtual bool debug_handle_signal(DebugEvent *ev) = 0;
197   virtual bool debug_handle_event(DebugEvent ev) = 0;
198
199   static DebugEvent debug_get_event(bool block);
200   static bool debug_wait_and_handle(bool block, bool flush, bool &handled, dbg_t *event_type = NULL);
201
202   static bool debug_waitfor(dbg_t event_type);
203
204   proc_state state();
205   void setState(proc_state p);
206  public:
207   
208   static ProcDebug *newProcDebug(Dyninst::PID pid, std::string executable="");
209   static bool newProcDebugSet(const std::vector<Dyninst::PID> &pids,
210                               std::vector<ProcDebug *> &out_set);
211   static ProcDebug *newProcDebug(const std::string &executable, 
212                                  const std::vector<std::string> &argv);
213   virtual ~ProcDebug();
214
215   virtual bool getRegValue(Dyninst::MachRegister reg, Dyninst::THR_ID thread, Dyninst::MachRegisterVal &val) = 0;
216   virtual bool readMem(void *dest, Dyninst::Address source, size_t size) = 0;
217   virtual bool getThreadIds(std::vector<Dyninst::THR_ID> &thrds) = 0;
218   virtual bool getDefaultThread(Dyninst::THR_ID &default_tid) = 0;
219   virtual unsigned getAddressWidth() = 0;
220
221   virtual void preStackwalk(Dyninst::THR_ID tid);
222   virtual void postStackwalk(Dyninst::THR_ID tid);
223
224   
225   virtual bool pause(Dyninst::THR_ID tid = NULL_THR_ID);
226   virtual bool resume(Dyninst::THR_ID tid = NULL_THR_ID);
227   virtual bool isTerminated();
228
229   virtual bool detach(bool leave_stopped = false) = 0;
230
231   static int getNotificationFD();
232   const std::string& getExecutablePath();
233
234   static bool handleDebugEvent(bool block = false);
235   virtual bool isFirstParty();
236  protected:
237   /**
238    * Helper for polling for new threads.  Sees if the thread exists, 
239    * creates a ThreadState if not, and handles errors.  Mechanism for 
240    * finding thread ids is left to derived class.
241    **/
242   virtual bool add_new_thread(Dyninst::THR_ID tid);
243
244   /**
245    * Syntactic sugar for add_new_thread.  Use for adding lots of 
246    * threads from your favorite iterable data structure.
247    **/
248   template <class Iterator>
249   bool add_new_threads(Iterator start, Iterator end) 
250   {
251      bool good = true;
252      for (Iterator i=start; i != end; i++) {
253         if (!add_new_thread(*i)) good = false;
254      }
255      return good;
256   }
257    
258   ThreadState *initial_thread;
259   ThreadState *active_thread;
260   typedef std::map<Dyninst::THR_ID, ThreadState*> thread_map_t;
261   thread_map_t threads;
262   std::string executable_path;
263  public:
264   static int pipe_in;
265   static int pipe_out;
266 };
267
268 //LibAddrPair.first = path to library, LibAddrPair.second = load address
269 typedef std::pair<std::string, Address> LibAddrPair;
270 typedef enum { library_load, library_unload} lib_change_t;
271 class LibraryState {
272  protected:
273    ProcessState *procstate;
274  public:
275    LibraryState(ProcessState *parent);
276    virtual bool getLibraryAtAddr(Address addr, LibAddrPair &lib) = 0;
277    virtual bool getLibraries(std::vector<LibAddrPair> &libs) = 0;
278    virtual void notifyOfUpdate() = 0;
279    virtual Address getLibTrapAddress() = 0;
280    virtual ~LibraryState();
281 };
282
283 class ThreadState {
284  public:
285    static ThreadState* createThreadState(ProcDebug *parent, 
286                                          Dyninst::THR_ID id = NULL_THR_ID,
287                                          bool alrady_attached = false);
288    virtual ~ThreadState();
289
290    bool isStopped();
291    void setStopped(bool s);
292    
293    bool userIsStopped();
294    void setUserStopped(bool u);
295
296    bool shouldResume();
297    void setShouldResume(bool r);
298
299    Dyninst::THR_ID getTid();
300
301    proc_state state();
302    void setState(proc_state s);
303    
304    ProcDebug *proc();
305  protected:
306    ThreadState(ProcDebug *p, Dyninst::THR_ID id);
307    bool is_stopped;
308    bool user_stopped;
309    bool should_resume;
310    Dyninst::THR_ID tid;
311    proc_state thr_state;
312    ProcDebug *parent;
313 };
314
315 // ----- Useful functors for dealing with ThreadStates. -----
316 // invokes setStopped on the thread.
317 struct set_stopped {
318   bool value;
319   set_stopped(bool v) : value(v) { }
320   void operator()(ThreadState *ts) { ts->setStopped(value); }
321 };
322
323 // Sets thread state.
324 struct set_state {
325   proc_state value;
326   set_state(proc_state v) : value(v) { }
327   void operator()(ThreadState *ts) { ts->setState(value); }
328 };
329
330 // Sets thread state.
331 struct set_should_resume {
332   bool value;
333   set_should_resume(bool v) : value(v) { }
334   void operator()(ThreadState *ts) { ts->setShouldResume(value); }
335 };
336
337 }
338 }
339
340 #endif