Merge branch 'master' into bgq_ramdisk_io
[dyninst.git] / proccontrol / src / int_thread_db.h
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  * 
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  * 
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  * 
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  * 
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  * 
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30 #if !defined(INT_THREAD_DB_H_)
31 #define INT_THREAD_DB_H_
32
33 #include "proccontrol/src/int_process.h"
34
35 #if defined(cap_thread_db)
36
37 #include "proccontrol/h/Generator.h"
38 #include "proccontrol/h/Event.h"
39 #include "proccontrol/h/Decoder.h"
40 #include "proccontrol/h/Handler.h"
41 #include "proccontrol/src/int_handler.h"
42 #include "proccontrol/src/processplat.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 #include <vector>
57 #include <string>
58 #include <deque>
59
60 using namespace Dyninst;
61 using namespace ProcControlAPI;
62
63 class thread_db_thread;
64
65 class thread_db_process : public int_threadTracking
66 {
67    friend class thread_db_thread;
68    friend class ThreadDBDispatchHandler;
69
70    friend ps_err_e ps_pread(struct ps_prochandle *, psaddr_t, void *, size_t);
71    friend ps_err_e ps_pwrite(struct ps_prochandle *, psaddr_t, const void *, size_t);
72
73 public:
74     thread_db_process(Dyninst::PID p, std::string e, std::vector<std::string> a, std::vector<std::string> envp, std::map<int, int> f);
75     thread_db_process(Dyninst::PID pid_, int_process *p);
76     virtual ~thread_db_process();
77
78     async_ret_t decodeTdbBreakpoint(EventBreakpoint::ptr bp);
79     bool decodeTdbLWPExit(EventLWPDestroy::ptr lwp_ev);
80
81     /* helper functions for thread_db interactions */
82
83     td_thragent_t *getThreadDBAgent();
84     ps_err_e getSymbolAddr(const char *objName, const char *symName, 
85                            psaddr_t *symbolAddr);
86     async_ret_t initThreadDB();
87
88     virtual void freeThreadDBAgent();
89     virtual async_ret_t getEventForThread(std::set<Event::ptr> &new_ev_set);
90     static void addThreadDBHandlers(HandlerPool *hpool);
91
92     /*
93      * When creating a static executable or attaching to a new process,
94      * thread_db initialization needs to occur immediately after
95      * attach or create.
96      *
97      * When creating dynamic executables, initialization needs to happen
98      * when the thread library is loaded.
99      */
100     virtual async_ret_t post_attach(bool wasDetached, std::set<response::ptr> &aresps);
101     virtual async_ret_t post_create(std::set<response::ptr> &async_responses);
102
103     virtual bool plat_supportThreadEvents();
104
105     // Platform-dependent functionality (derived classes override)
106     virtual bool plat_getLWPInfo(lwpid_t lwp, void *lwpInfo);
107     virtual const char *getThreadLibName(const char *symName);
108     virtual bool isSupportedThreadLib(std::string libName);
109     int_thread *triggerThread() const;
110     async_ret_t initThreadWithHandle(td_thrhandle_t *thr, td_thrinfo_t *info, Dyninst::LWP lwp);
111
112     virtual bool setTrackThreads(bool b, std::set<std::pair<int_breakpoint *, Address> > &bps,
113                                           bool &add_bp);
114     virtual bool isTrackingThreads();
115     virtual bool refreshThreads();
116     virtual int threaddb_getPid();
117     
118     //The types for thread_db functions we will call
119     typedef td_err_e (*td_init_t)(void);
120     typedef td_err_e (*td_ta_new_t)(struct ps_prochandle *, td_thragent_t **);
121     typedef td_err_e (*td_ta_delete_t)(td_thragent_t *);
122     typedef td_err_e (*td_ta_event_addr_t)(const td_thragent_t *, td_event_e, td_notify_t *);
123     typedef td_err_e (*td_ta_set_event_t)(const td_thragent_t *, td_thr_events_t *);
124     typedef td_err_e (*td_ta_event_getmsg_t)(const td_thragent_t *, td_event_msg_t *);
125     typedef td_err_e (*td_ta_map_lwp2thr_t)(const td_thragent_t *, lwpid_t, td_thrhandle_t *);
126     typedef td_err_e (*td_thr_get_info_t)(const td_thrhandle_t *, td_thrinfo_t *);
127     typedef td_err_e (*td_thr_event_enable_t)(const td_thrhandle_t *, int);
128     typedef td_err_e (*td_thr_set_event_t)(const td_thrhandle_t *, td_thr_events_t *);
129     typedef td_err_e (*td_thr_event_getmsg_t)(const td_thrhandle_t *, td_event_msg_t *);
130     typedef td_err_e (*td_thr_dbsuspend_t)(const td_thrhandle_t *);
131     typedef td_err_e (*td_thr_dbresume_t)(const td_thrhandle_t *);
132
133     //Function pointers to the thread_db functions
134     static bool loadedThreadDBLibrary();
135     static td_init_t p_td_init;
136     static td_ta_new_t p_td_ta_new;
137     static td_ta_delete_t p_td_ta_delete;
138     static td_ta_event_addr_t p_td_ta_event_addr;
139     static td_ta_set_event_t p_td_ta_set_event;
140     static td_ta_event_getmsg_t p_td_ta_event_getmsg;
141     static td_ta_map_lwp2thr_t p_td_ta_map_lwp2thr;
142     static td_thr_get_info_t p_td_thr_get_info;
143     static td_thr_event_enable_t p_td_thr_event_enable;
144     static td_thr_set_event_t p_td_thr_set_event;
145     static td_thr_event_getmsg_t p_td_thr_event_getmsg;
146     static td_thr_dbsuspend_t p_td_thr_dbsuspend;
147     static td_thr_dbresume_t p_td_thr_dbresume;
148
149 protected:
150     Event::ptr decodeThreadEvent(td_event_msg_t *eventMsg, bool &async);
151     async_ret_t handleThreadAttach(td_thrhandle_t *thr, Dyninst::LWP lwp);
152     // plat_convertToBreakpointAddress moved to int_process so we avoid
153     // diamond inheritance undefined behavior
154
155     static volatile bool thread_db_initialized;
156     bool thread_db_proc_initialized;
157     static Mutex thread_db_init_lock;
158
159     std::map<Dyninst::Address, std::pair<int_breakpoint *, EventType> > addr2Event;
160     td_thragent_t *threadAgent;
161     bool createdThreadAgent;
162
163     struct ps_prochandle *self;
164     int_thread *trigger_thread;
165
166     std::deque<Event::ptr> savedEvents;
167
168     std::set<mem_response::ptr> resps;
169     std::set<result_response::ptr> res_resps;
170     EventThreadDB::ptr dispatch_event;
171
172     bool hasAsyncPending;
173     bool initialThreadEventCreated;
174     bool setEventSet;
175     bool completed_post;
176     bool track_threads;
177 private:
178     static bool tdb_loaded;
179     static bool tdb_loaded_result;
180
181     async_ret_t ll_fetchThreadInfo(td_thrhandle_t *th, td_thrinfo_t *info);
182 };
183
184 /*
185  * libthread_db defines this as opaque. We need to implement it.
186  */
187 struct ps_prochandle {
188     thread_db_process *thread_db_proc;
189 };
190
191 class thread_db_thread : virtual public int_thread
192 {
193     friend class ThreadDBCreateHandler;
194     friend class ThreadDBDispatchHandler;
195     friend class thread_db_process;
196 public:
197     thread_db_thread(int_process *p, Dyninst::THR_ID t, Dyninst::LWP l);
198     virtual ~thread_db_thread();
199
200     async_ret_t setEventReporting(bool on);
201     bool fetchThreadInfo();
202
203     void markDestroyed();
204     bool isDestroyed();
205
206     // Platform-dependent functionality
207     virtual bool thrdb_getThreadArea(int val, Dyninst::Address &addr);
208     virtual bool plat_convertToSystemRegs(const int_registerPool &pool, unsigned char *regs, bool gprs_only = false);
209
210     virtual bool haveUserThreadInfo();
211     virtual bool getTID(Dyninst::THR_ID &tid);
212     virtual bool getStartFuncAddress(Dyninst::Address &addr);
213     virtual bool getStackBase(Dyninst::Address &addr);
214     virtual bool getStackSize(unsigned long &size);
215     virtual bool getTLSPtr(Dyninst::Address &addr);
216 protected:
217     // Initialization of the thread handle cannot be performed until 
218     // thread_db is loaded and initialized. When creating a process,
219     // we need to be able to create an instance of thread_db_thread
220     // before thread_db is initialized so we lazily initialize the
221     // thread handle
222     bool initThreadHandle();
223     
224     td_thrhandle_t *threadHandle;
225     td_thrinfo_t tinfo;
226
227     // Since a thread destroy event happens at a breakpoint, the 
228     // breakpoint needs to be cleaned up before the thread can be 
229     // removed from the threadPool and deleted.
230     bool destroyed;
231     bool tinfo_initialized;
232     bool thread_initialized;
233     bool threadHandle_alloced;
234     bool enabled_event_reporting;
235 };
236
237 class ThreadDBDispatchHandler : public Handler
238 {
239   public:
240    ThreadDBDispatchHandler();
241    virtual ~ThreadDBDispatchHandler();
242    virtual Handler::handler_ret_t handleEvent(Event::ptr ev);
243    void getEventTypesHandled(std::vector<EventType> &etypes);
244    virtual int getPriority() const;
245 };
246
247 class ThreadDBCreateHandler : public Handler
248 {
249 public:
250    ThreadDBCreateHandler();
251    virtual ~ThreadDBCreateHandler();
252    virtual Handler::handler_ret_t handleEvent(Event::ptr ev);
253    void getEventTypesHandled(std::vector<EventType> &etypes);
254    virtual int getPriority() const;
255 };
256
257 class ThreadDBLibHandler : public Handler
258 {
259 public:
260    ThreadDBLibHandler();
261    virtual ~ThreadDBLibHandler();
262    virtual Handler::handler_ret_t handleEvent(Event::ptr ev);
263    virtual int getPriority() const;
264    void getEventTypesHandled(std::vector<EventType> &etypes);
265 };
266
267 class ThreadDBDestroyHandler : public Handler
268 {
269 public:
270    ThreadDBDestroyHandler();
271    virtual ~ThreadDBDestroyHandler();
272    virtual Handler::handler_ret_t handleEvent(Event::ptr ev);
273    void getEventTypesHandled(std::vector<EventType> &etypes);
274    virtual int getPriority() const;
275 };
276
277 typedef struct new_thread_data {
278   td_thrhandle_t *thr_handle;
279   td_thrinfo_t thr_info;
280   bool threadHandle_alloced;
281 } new_thread_data_t;
282
283 #else
284
285 class thread_db_thread : public int_thread
286 {
287   public:
288     thread_db_thread(int_process *p, Dyninst::THR_ID t, Dyninst::LWP l);
289     virtual ~thread_db_thread();
290
291     virtual bool thrdb_getThreadArea(int val, Dyninst::Address &addr);
292     virtual bool haveUserThreadInfo();
293     virtual bool getTID(Dyninst::THR_ID &tid);
294     virtual bool getStartFuncAddress(Dyninst::Address &addr);
295     virtual bool getStackBase(Dyninst::Address &addr);
296     virtual bool getStackSize(unsigned long &size);
297     virtual bool getTLSPtr(Dyninst::Address &addr);
298 };
299
300
301 class thread_db_process : virtual public int_process
302 {
303   public:
304     thread_db_process(Dyninst::PID p, std::string e, std::vector<std::string> a, std::vector<std::string> envp, std::map<int, int> f);
305     thread_db_process(Dyninst::PID pid_, int_process *p);
306     virtual ~thread_db_process();
307
308     bool decodeTdbLWPExit(EventLWPDestroy::ptr lwp_ev);
309     async_ret_t decodeTdbBreakpoint(EventBreakpoint::ptr bp);
310
311     bool decodeThreadBP(EventBreakpoint::ptr bp);
312     static void addThreadDBHandlers(HandlerPool *hpool);
313 };
314
315 #endif
316
317 #endif