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