Fixes for trap handling on BG/P
[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 bool preStackwalk(Dyninst::THR_ID tid);
95   virtual bool 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_setreg_ack,
138   dbg_attached,
139   dbg_thread_info,
140   dbg_detached      // 15
141 } dbg_t;
142
143 class ProcDebug;
144
145 struct DebugEvent {
146    dbg_t dbg;
147    union {
148       int idata;
149       void *pdata;
150    } data;
151    unsigned size;
152    ProcDebug *proc;
153    ThreadState *thr;
154
155    DebugEvent() : dbg(dbg_noevent), size(0), proc(NULL), thr(NULL) {}
156 };
157
158 struct procdebug_ltint
159 {
160    bool operator()(int a, int b) const;
161 };
162
163 class ProcDebug : public ProcessState {
164   friend class Walker;
165   friend class ThreadState;
166  protected:
167   ProcDebug(Dyninst::PID pid, std::string executable="");
168   ProcDebug(const std::string &executable, 
169             const std::vector<std::string> &argv);
170   
171   /**
172    * attach() is the top-level command, and is implemented by debug_attach and
173    * debug_waitfor_attach. 
174    **/
175   virtual bool attach();
176   static bool multi_attach(std::vector<ProcDebug *> &pids);
177
178
179   virtual bool debug_attach(ThreadState *ts) = 0;
180   virtual bool debug_waitfor_attach(ThreadState *ts);
181   virtual bool debug_post_attach(ThreadState *ts);
182   virtual bool debug_post_create();
183
184   virtual bool create(const std::string &executable, 
185                       const std::vector<std::string> &argv);
186   virtual bool debug_create(const std::string &executable, 
187                             const std::vector<std::string> &argv) = 0;
188   virtual bool debug_waitfor_create();
189   
190   /**
191    * pause() is the top-level command (under the public section), and is 
192    * implemented by debug_pause() and debug_waitfor_pause()
193    **/
194   virtual bool pause_thread(ThreadState *thr);
195   virtual bool debug_pause(ThreadState *thr) = 0;
196   virtual bool debug_waitfor_pause(ThreadState *thr);
197
198   virtual bool resume_thread(ThreadState *thr);
199   virtual bool debug_continue(ThreadState *thr) = 0;
200   virtual bool debug_continue_with(ThreadState *thr, long sig) = 0;
201   virtual bool debug_waitfor_continue(ThreadState *thr);
202
203   virtual bool debug_handle_signal(DebugEvent *ev) = 0;
204   virtual bool debug_handle_event(DebugEvent ev) = 0;
205
206   static DebugEvent debug_get_event(bool block);
207   static bool debug_wait_and_handle(bool block, bool flush, bool &handled, dbg_t *event_type = NULL);
208
209   static bool debug_waitfor(dbg_t event_type);
210
211   proc_state state();
212   void setState(proc_state p);
213  public:
214   
215   static ProcDebug *newProcDebug(Dyninst::PID pid, std::string executable="");
216   static bool newProcDebugSet(const std::vector<Dyninst::PID> &pids,
217                               std::vector<ProcDebug *> &out_set);
218   static ProcDebug *newProcDebug(const std::string &executable, 
219                                  const std::vector<std::string> &argv);
220   virtual ~ProcDebug();
221
222   virtual bool getRegValue(Dyninst::MachRegister reg, Dyninst::THR_ID thread, Dyninst::MachRegisterVal &val) = 0;
223   virtual bool readMem(void *dest, Dyninst::Address source, size_t size) = 0;
224   virtual bool getThreadIds(std::vector<Dyninst::THR_ID> &thrds) = 0;
225   virtual bool getDefaultThread(Dyninst::THR_ID &default_tid) = 0;
226   virtual unsigned getAddressWidth() = 0;
227
228   virtual bool preStackwalk(Dyninst::THR_ID tid);
229   virtual bool postStackwalk(Dyninst::THR_ID tid);
230
231   
232   virtual bool pause(Dyninst::THR_ID tid = NULL_THR_ID);
233   virtual bool resume(Dyninst::THR_ID tid = NULL_THR_ID);
234   virtual bool isTerminated();
235
236   virtual bool detach(bool leave_stopped = false) = 0;
237
238   static int getNotificationFD();
239   const std::string& getExecutablePath();
240
241   static bool handleDebugEvent(bool block = false);
242   virtual bool isFirstParty();
243
244   typedef void (*sig_callback_func)(int &signum, ThreadState *thr);
245   void registerSignalCallback(sig_callback_func f);
246  protected:
247   /**
248    * Helper for polling for new threads.  Sees if the thread exists, 
249    * creates a ThreadState if not, and handles errors.  Mechanism for 
250    * finding thread ids is left to derived class.
251    **/
252   virtual bool add_new_thread(Dyninst::THR_ID tid);
253
254   /**
255    * Syntactic sugar for add_new_thread.  Use for adding lots of 
256    * threads from your favorite iterable data structure.
257    **/
258   template <class Iterator>
259   bool add_new_threads(Iterator start, Iterator end) 
260   {
261      bool good = true;
262      for (Iterator i=start; i != end; i++) {
263         if (!add_new_thread(*i)) good = false;
264      }
265      return good;
266   }
267    
268   ThreadState *initial_thread;
269   ThreadState *active_thread;
270   typedef std::map<Dyninst::THR_ID, ThreadState*> thread_map_t;
271   thread_map_t threads;
272   std::string executable_path;
273   sig_callback_func sigfunc;
274  public:
275   static int pipe_in;
276   static int pipe_out;
277 };
278
279 //LibAddrPair.first = path to library, LibAddrPair.second = load address
280 typedef std::pair<std::string, Address> LibAddrPair;
281 typedef enum { library_load, library_unload} lib_change_t;
282 class LibraryState {
283  protected:
284    ProcessState *procstate;
285  public:
286    LibraryState(ProcessState *parent);
287    virtual bool getLibraryAtAddr(Address addr, LibAddrPair &lib) = 0;
288    virtual bool getLibraries(std::vector<LibAddrPair> &libs) = 0;
289    virtual void notifyOfUpdate() = 0;
290    virtual Address getLibTrapAddress() = 0;
291    virtual ~LibraryState();
292 };
293
294 class ThreadState {
295  public:
296    static ThreadState* createThreadState(ProcDebug *parent, 
297                                          Dyninst::THR_ID id = NULL_THR_ID,
298                                          bool alrady_attached = false);
299    virtual ~ThreadState();
300
301    bool isStopped();
302    void setStopped(bool s);
303    
304    bool userIsStopped();
305    void setUserStopped(bool u);
306
307    bool shouldResume();
308    void setShouldResume(bool r);
309
310    Dyninst::THR_ID getTid();
311
312    proc_state state();
313    void setState(proc_state s);
314    
315    ProcDebug *proc();
316  protected:
317    ThreadState(ProcDebug *p, Dyninst::THR_ID id);
318    bool is_stopped;
319    bool user_stopped;
320    bool should_resume;
321    Dyninst::THR_ID tid;
322    proc_state thr_state;
323    ProcDebug *parent;
324 };
325
326 // ----- Useful functors for dealing with ThreadStates. -----
327 // invokes setStopped on the thread.
328 struct set_stopped {
329   bool value;
330   set_stopped(bool v) : value(v) { }
331   void operator()(ThreadState *ts) { ts->setStopped(value); }
332 };
333
334 // Sets thread state.
335 struct set_state {
336   proc_state value;
337   set_state(proc_state v) : value(v) { }
338   void operator()(ThreadState *ts) { ts->setState(value); }
339 };
340
341 // Sets thread state.
342 struct set_should_resume {
343   bool value;
344   set_should_resume(bool v) : value(v) { }
345   void operator()(ThreadState *ts) { ts->setShouldResume(value); }
346 };
347
348 }
349 }
350
351 #endif