ProcControlAPI on BlueGene Fixes
[dyninst.git] / proccontrol / src / int_thread_db.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 #if !defined(INT_THREAD_DB_H_)
32 #define INT_THREAD_DB_H
33
34 #include "proccontrol/src/int_process.h"
35
36 #if defined(cap_thread_db)
37
38 #include "proccontrol/h/Generator.h"
39 #include "proccontrol/h/Event.h"
40 #include "proccontrol/h/Decoder.h"
41 #include "proccontrol/h/Handler.h"
42 #include "proccontrol/src/int_handler.h"
43
44 extern "C" {
45
46 #if !defined(THREAD_DB_INC)
47 #include <thread_db.h>
48 #else
49 #include THREAD_DB_INC
50 #endif
51
52 #include "proc_service_wrapper.h"
53 }
54
55 #include <map>
56 using std::map;
57 using std::pair;
58
59 #include <vector>
60 using std::vector;
61
62 #include <string>
63 using std::string;
64
65 using namespace Dyninst;
66 using namespace ProcControlAPI;
67
68 class thread_db_thread;
69
70 class thread_db_process : virtual public int_process
71 {
72    friend class thread_db_thread;
73    friend ps_err_e ps_pread(struct ps_prochandle *, psaddr_t, void *, size_t);
74    friend ps_err_e ps_pwrite(struct ps_prochandle *, psaddr_t, const void *, size_t);
75
76 public:
77     thread_db_process(Dyninst::PID p, std::string e, std::vector<std::string> a, std::vector<std::string> envp, std::map<int, int> f);
78     thread_db_process(Dyninst::PID pid_, int_process *p);
79     virtual ~thread_db_process();
80
81     async_ret_t decodeTdbBreakpoint(EventBreakpoint::ptr bp);
82     bool decodeTdbLWPExit(EventLWPDestroy::ptr lwp_ev);
83     async_ret_t decodeTdbLibLoad(EventLibrary::ptr lib_ev);
84
85     /* helper functions for thread_db interactions */
86
87     td_thragent_t *getThreadDBAgent();
88     ps_err_e getSymbolAddr(const char *objName, const char *symName, 
89                            psaddr_t *symbolAddr);
90
91     async_ret_t initThreadDB();
92     void freeThreadDBAgent();
93     bool getPostDestroyEvents(vector<Event::ptr> &events);
94     static void addThreadDBHandlers(HandlerPool *hpool);
95
96     /*
97      * When creating a static executable or attaching to a new process,
98      * thread_db initialization needs to occur immediately after
99      * attach or create.
100      *
101      * When creating dynamic executables, initialization needs to happen
102      * when the thread library is loaded.
103      */
104     virtual bool post_attach();
105     virtual bool post_create();
106
107     virtual bool plat_supportThreadEvents();
108
109     // Platform-dependent functionality (derived classes override)
110     virtual bool plat_getLWPInfo(lwpid_t lwp, void *lwpInfo);
111     virtual const char *getThreadLibName(const char *symName);
112     virtual bool isSupportedThreadLib(string libName);
113     int_thread *triggerThread() const;
114
115     async_ret_t initThreadWithHandle(td_thrhandle_t *thr, td_thrinfo_t *info);
116     
117     async_ret_t updateTidInfo(vector<Event::ptr> &threadEvents);
118     bool needsTidUpdate();
119
120     //The types for thread_db functions we will call
121     typedef td_err_e (*td_init_t)(void);
122     typedef td_err_e (*td_ta_new_t)(struct ps_prochandle *, td_thragent_t **);
123     typedef td_err_e (*td_ta_delete_t)(td_thragent_t *);
124     typedef td_err_e (*td_ta_event_addr_t)(const td_thragent_t *, td_event_e, td_notify_t *);
125     typedef td_err_e (*td_ta_set_event_t)(const td_thragent_t *, td_thr_events_t *);
126     typedef td_err_e (*td_ta_event_getmsg_t)(const td_thragent_t *, td_event_msg_t *);
127     typedef td_err_e (*td_ta_map_lwp2thr_t)(const td_thragent_t *, lwpid_t, td_thrhandle_t *);
128     typedef td_err_e (*td_thr_get_info_t)(const td_thrhandle_t *, td_thrinfo_t *);
129     typedef td_err_e (*td_thr_event_enable_t)(const td_thrhandle_t *, int);
130     typedef td_err_e (*td_thr_set_event_t)(const td_thrhandle_t *, td_thr_events_t *);
131     typedef td_err_e (*td_thr_event_getmsg_t)(const td_thrhandle_t *, td_event_msg_t *);
132     typedef td_err_e (*td_thr_dbsuspend_t)(const td_thrhandle_t *);
133     typedef td_err_e (*td_thr_dbresume_t)(const td_thrhandle_t *);
134
135     //Function pointers to the thread_db functions
136     static bool loadedThreadDBLibrary();
137     static td_init_t p_td_init;
138     static td_ta_new_t p_td_ta_new;
139     static td_ta_delete_t p_td_ta_delete;
140     static td_ta_event_addr_t p_td_ta_event_addr;
141     static td_ta_set_event_t p_td_ta_set_event;
142     static td_ta_event_getmsg_t p_td_ta_event_getmsg;
143     static td_ta_map_lwp2thr_t p_td_ta_map_lwp2thr;
144     static td_thr_get_info_t p_td_thr_get_info;
145     static td_thr_event_enable_t p_td_thr_event_enable;
146     static td_thr_set_event_t p_td_thr_set_event;
147     static td_thr_event_getmsg_t p_td_thr_event_getmsg;
148     static td_thr_dbsuspend_t p_td_thr_dbsuspend;
149     static td_thr_dbresume_t p_td_thr_dbresume;
150
151 protected:
152     Event::ptr decodeThreadEvent(td_event_msg_t *eventMsg, bool &async);
153     async_ret_t handleThreadAttach(td_thrhandle_t *thr);
154     virtual bool plat_convertToBreakpointAddress(psaddr_t &addr);
155
156     static volatile bool thread_db_initialized;
157     bool thread_db_proc_initialized;
158     static Mutex thread_db_init_lock;
159
160     map<Dyninst::Address, pair<int_breakpoint *, EventType> > addr2Event;
161     td_thragent_t *threadAgent;
162     bool createdThreadAgent;
163
164     struct ps_prochandle *self;
165     int_thread *trigger_thread;
166
167     bool needs_tid_update;
168
169     std::set<mem_response::ptr> resps;
170     std::set<result_response::ptr> res_resps;
171     bool hasAsyncPending;
172     
173 private:
174     static bool tdb_loaded;
175     static bool tdb_loaded_result;
176
177     async_ret_t ll_fetchThreadInfo(td_thrhandle_t *th, td_thrinfo_t *info);
178 };
179
180 /*
181  * libthread_db defines this as opaque. We need to implement it.
182  */
183 struct ps_prochandle {
184     thread_db_process *thread_db_proc;
185 };
186
187 class thread_db_thread : public int_thread
188 {
189     friend class ThreadDBCreateHandler;
190     friend class thread_db_process;
191 public:
192     thread_db_thread(int_process *p, Dyninst::THR_ID t, Dyninst::LWP l);
193     virtual ~thread_db_thread();
194
195     async_ret_t setEventReporting(bool on);
196     bool fetchThreadInfo();
197
198     bool plat_resume();
199     bool plat_suspend();
200     void markDestroyed();
201     bool isDestroyed();
202
203     // Platform-dependent functionality
204     virtual bool thrdb_getThreadArea(int val, Dyninst::Address &addr);
205     virtual bool plat_convertToSystemRegs(const int_registerPool &pool, unsigned char *regs);
206
207     virtual bool haveUserThreadInfo();
208     virtual bool getTID(Dyninst::THR_ID &tid);
209     virtual bool getStartFuncAddress(Dyninst::Address &addr);
210     virtual bool getStackBase(Dyninst::Address &addr);
211     virtual bool getStackSize(unsigned long &size);
212     virtual bool getTLSPtr(Dyninst::Address &addr);
213 protected:
214     // Initialization of the thread handle cannot be performed until 
215     // thread_db is loaded and initialized. When creating a process,
216     // we need to be able to create an instance of thread_db_thread
217     // before thread_db is initialized so we lazily initialize the
218     // thread handle
219     bool initThreadHandle();
220     
221     td_thrhandle_t *threadHandle;
222     td_thrinfo_t tinfo;
223
224     // Since a thread destroy event happens at a breakpoint, the 
225     // breakpoint needs to be cleaned up before the thread can be 
226     // removed from the threadPool and deleted.
227     bool destroyed;
228     bool tinfo_initialized;
229     bool thread_initialized;
230     bool threadHandle_alloced;
231 };
232
233 class ThreadDBCreateHandler : public Handler
234 {
235 public:
236     ThreadDBCreateHandler();
237     virtual ~ThreadDBCreateHandler();
238     virtual Handler::handler_ret_t handleEvent(Event::ptr ev);
239     virtual int getPriority() const;
240     void getEventTypesHandled(vector<EventType> &etypes);
241 };
242
243 class ThreadDBLibHandler : public Handler
244 {
245 public:
246     ThreadDBLibHandler();
247     virtual ~ThreadDBLibHandler();
248     virtual Handler::handler_ret_t handleEvent(Event::ptr ev);
249     virtual int getPriority() const;
250     void getEventTypesHandled(std::vector<EventType> &etypes);
251 };
252
253 class ThreadDBDestroyHandler : public Handler
254 {
255 public:
256     ThreadDBDestroyHandler();
257     virtual ~ThreadDBDestroyHandler();
258     virtual Handler::handler_ret_t handleEvent(Event::ptr ev);
259     virtual int getPriority() const;
260     void getEventTypesHandled(std::vector<EventType> &etypes);
261 };
262
263 typedef struct new_thread_data {
264   td_thrhandle_t *thr_handle;
265   td_thrinfo_t thr_info;
266 } new_thread_data_t;
267
268 #else
269
270 class thread_db_thread : public int_thread
271 {
272   public:
273     thread_db_thread(int_process *p, Dyninst::THR_ID t, Dyninst::LWP l);
274     virtual ~thread_db_thread();
275
276     virtual bool thrdb_getThreadArea(int val, Dyninst::Address &addr);
277     virtual bool haveUserThreadInfo();
278     virtual bool getTID(Dyninst::THR_ID &tid);
279     virtual bool getStartFuncAddress(Dyninst::Address &addr);
280     virtual bool getStackBase(Dyninst::Address &addr);
281     virtual bool getStackSize(unsigned long &size);
282     virtual bool getTLSPtr(Dyninst::Address &addr);
283 };
284
285
286 class thread_db_process : virtual public int_process
287 {
288   public:
289     thread_db_process(Dyninst::PID p, std::string e, std::vector<std::string> a, std::vector<std::string> envp, std::map<int, int> f);
290     thread_db_process(Dyninst::PID pid_, int_process *p);
291     virtual ~thread_db_process();
292
293     bool decodeThreadBP(EventBreakpoint::ptr bp);
294     static void addThreadDBHandlers(HandlerPool *hpool);
295 };
296
297 #endif
298
299 #endif