Updates for StackwalkerAPI
[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   LibraryState *getLibraryTracker();
86
87   //Allow initialization/uninitialization
88   virtual void preStackwalk(Dyninst::THR_ID tid);
89   virtual void postStackwalk(Dyninst::THR_ID tid);
90 };
91
92 class ProcSelf : public ProcessState {
93  public:
94   ProcSelf();
95   void initialize();
96
97   virtual bool getRegValue(Dyninst::MachRegister reg, Dyninst::THR_ID thread, Dyninst::MachRegisterVal &val);
98   virtual bool readMem(void *dest, Dyninst::Address source, size_t size);
99   virtual bool getThreadIds(std::vector<Dyninst::THR_ID> &threads);
100   virtual bool getDefaultThread(Dyninst::THR_ID &default_tid);
101   virtual unsigned getAddressWidth();
102   virtual ~ProcSelf();
103 };
104
105 typedef enum {
106   ps_neonatal,
107   ps_attached_intermediate,
108   ps_attached,
109   ps_running,
110   ps_exited,
111   ps_errorstate,
112 } proc_state;
113
114 typedef enum {
115    dbg_err,
116    dbg_exited,
117    dbg_crashed,
118    dbg_stopped,
119    dbg_other,
120    dbg_noevent,
121    dbg_libraryload,
122    //BGL
123    dbg_continued,
124    dbg_mem_ack,
125    dbg_reg_ack,
126    dbg_allregs_ack,
127    dbg_attached,
128 } dbg_t;
129
130 class ProcDebug;
131
132 struct DebugEvent {
133    dbg_t dbg;
134    union {
135       int idata;
136       void *pdata;
137    } data;
138    unsigned size;
139    ProcDebug *proc;
140    ThreadState *thr;
141
142    DebugEvent() : dbg(dbg_noevent), size(0), proc(NULL), thr(NULL) {}
143 };
144
145 struct procdebug_ltint
146 {
147    bool operator()(int a, int b) const;
148 };
149
150 class ProcDebug : public ProcessState {
151   friend class Walker;
152   friend class ThreadState;
153  protected:
154   ProcDebug(Dyninst::PID pid);
155   ProcDebug(const std::string &executable, 
156             const std::vector<std::string> &argv);
157   
158   /**
159    * attach() is the top-level command, and is implemented by debug_attach and
160    * debug_waitfor_attach. 
161    **/
162   virtual bool attach();
163   static bool multi_attach(std::vector<ProcDebug *> &pids);
164
165
166   virtual bool debug_attach(ThreadState *ts) = 0;
167   virtual bool debug_waitfor_attach(ThreadState *ts);
168   virtual bool debug_post_attach(ThreadState *ts);
169   virtual bool debug_post_create();
170
171   virtual bool create(const std::string &executable, 
172                       const std::vector<std::string> &argv);
173   virtual bool debug_create(const std::string &executable, 
174                             const std::vector<std::string> &argv) = 0;
175   virtual bool debug_waitfor_create();
176   
177   /**
178    * pause() is the top-level command (under the public section), and is 
179    * implemented by debug_pause() and debug_waitfor_pause()
180    **/
181   virtual bool pause_thread(ThreadState *thr);
182   virtual bool debug_pause(ThreadState *thr) = 0;
183   virtual bool debug_waitfor_pause(ThreadState *thr);
184
185   virtual bool resume_thread(ThreadState *thr);
186   virtual bool debug_continue(ThreadState *thr) = 0;
187   virtual bool debug_continue_with(ThreadState *thr, long sig) = 0;
188   virtual bool debug_waitfor_continue(ThreadState *thr);
189
190   virtual bool debug_handle_signal(DebugEvent *ev) = 0;
191   virtual bool debug_handle_event(DebugEvent ev) = 0;
192
193   static DebugEvent debug_get_event(bool block);
194   static bool debug_wait_and_handle(bool block, bool &handled);
195
196   proc_state state();
197   void setState(proc_state p);
198  public:
199   
200   static ProcDebug *newProcDebug(Dyninst::PID pid);
201   static bool newProcDebugSet(const std::vector<Dyninst::PID> &pids,
202                               std::vector<ProcDebug *> &out_set);
203   static ProcDebug *newProcDebug(const std::string &executable, 
204                                  const std::vector<std::string> &argv);
205   virtual ~ProcDebug();
206
207   virtual bool getRegValue(Dyninst::MachRegister reg, Dyninst::THR_ID thread, Dyninst::MachRegisterVal &val) = 0;
208   virtual bool readMem(void *dest, Dyninst::Address source, size_t size) = 0;
209   virtual bool getThreadIds(std::vector<Dyninst::THR_ID> &thrds) = 0;
210   virtual bool getDefaultThread(Dyninst::THR_ID &default_tid) = 0;
211   virtual unsigned getAddressWidth() = 0;
212
213   virtual void preStackwalk(Dyninst::THR_ID tid);
214   virtual void postStackwalk(Dyninst::THR_ID tid);
215
216   
217   virtual bool pause(Dyninst::THR_ID tid = NULL_THR_ID);
218   virtual bool resume(Dyninst::THR_ID tid = NULL_THR_ID);
219   virtual bool isTerminated();
220
221   static int getNotificationFD();
222   static bool handleDebugEvent(bool block = false);
223  protected:
224   ThreadState *initial_thread;
225   ThreadState *active_thread;
226   typedef std::map<Dyninst::THR_ID, ThreadState*> thread_map_t;
227   thread_map_t threads;
228  public:
229   static int pipe_in;
230   static int pipe_out;
231 };
232
233 //LibAddrPair.first = path to library, LibAddrPair.second = load address
234 typedef std::pair<std::string, Address> LibAddrPair;
235 typedef enum { library_load, library_unload} lib_change_t;
236 class LibraryState {
237  protected:
238    ProcessState *procstate;
239  public:
240    LibraryState(ProcessState *parent);
241    virtual bool getLibraryAtAddr(Address addr, LibAddrPair &lib) = 0;
242    virtual bool getLibraries(std::vector<LibAddrPair> &libs) = 0;
243    virtual void notifyOfUpdate() = 0;
244    virtual Address getLibTrapAddress() = 0;
245    virtual ~LibraryState();
246 };
247
248 class ThreadState {
249  public:
250    static ThreadState* createThreadState(ProcDebug *parent, 
251                                          Dyninst::THR_ID id = NULL_THR_ID,
252                                          bool alrady_attached = false);
253    virtual ~ThreadState();
254
255    bool isStopped();
256    void setStopped(bool s);
257    
258    bool userIsStopped();
259    void setUserStopped(bool u);
260
261    bool shouldResume();
262    void setShouldResume(bool r);
263
264    Dyninst::THR_ID getTid();
265
266    proc_state state();
267    void setState(proc_state s);
268    
269    ProcDebug *proc();
270  protected:
271    ThreadState(ProcDebug *p, Dyninst::THR_ID id);
272    bool is_stopped;
273    bool user_stopped;
274    bool should_resume;
275    Dyninst::THR_ID tid;
276    proc_state thr_state;
277    ProcDebug *parent;
278 };
279
280 }
281 }
282
283 #endif