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