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