Merge branch 'dyn_pc_integration' of ssh://wasabi.cs.wisc.edu/p/paradyn/development...
[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 #include <thread_db.h>
46 #include "proc_service_wrapper.h"
47 }
48
49 #include <map>
50 using std::map;
51 using std::pair;
52
53 #include <vector>
54 using std::vector;
55
56 #include <string>
57 using std::string;
58
59 using namespace Dyninst;
60 using namespace ProcControlAPI;
61
62 class thread_db_thread;
63
64 class thread_db_process : virtual public int_process
65 {
66    friend class thread_db_thread;
67 public:
68     thread_db_process(Dyninst::PID p, std::string e, std::vector<std::string> a, std::vector<std::string> envp, std::map<int, int> f);
69     thread_db_process(Dyninst::PID pid_, int_process *p);
70     virtual ~thread_db_process();
71
72     bool decodeTdbBreakpoint(EventBreakpoint::ptr bp);
73     bool decodeTdbLWPExit(EventLWPDestroy::ptr lwp_ev);
74     bool decodeTdbLibLoad(EventLibrary::ptr lib_ev);
75
76     /* helper functions for thread_db interactions */
77
78     td_thragent_t *getThreadDBAgent();
79     ps_err_e getSymbolAddr(const char *objName, const char *symName, 
80                            psaddr_t *symbolAddr);
81     virtual bool initThreadDB();
82     virtual void freeThreadDBAgent();
83     virtual bool getPostDestroyEvents(vector<Event::ptr> &events);
84     static void addThreadDBHandlers(HandlerPool *hpool);
85
86     /*
87      * When creating a static executable or attaching to a new process,
88      * thread_db initialization needs to occur immediately after
89      * attach or create.
90      *
91      * When creating dynamic executables, initialization needs to happen
92      * when the thread library is loaded.
93      */
94     virtual bool post_attach();
95     virtual bool post_create();
96
97     // Platform-dependent functionality (derived classes override)
98     virtual bool plat_getLWPInfo(lwpid_t lwp, void *lwpInfo);
99
100     virtual const char *getThreadLibName(const char *symName);
101     virtual bool isSupportedThreadLib(string libName);
102     int_thread *triggerThread() const;
103
104     thread_db_thread *initThreadWithHandle(td_thrhandle_t *thr, td_thrinfo_t *info);
105     
106     bool updateTidInfo(vector<Event::ptr> &threadEvents);
107     bool needsTidUpdate();
108     
109 protected:
110     Event::ptr decodeThreadEvent(td_event_msg_t *eventMsg);
111     bool handleThreadAttach(td_thrhandle_t *thr);
112     virtual bool plat_convertToBreakpointAddress(psaddr_t &addr);
113
114     static volatile bool thread_db_initialized;
115     bool thread_db_proc_initialized;
116     static Mutex thread_db_init_lock;
117
118     map<Dyninst::Address, pair<int_breakpoint *, EventType> > addr2Event;
119     td_thragent_t *threadAgent;
120
121     struct ps_prochandle *self;
122     int_thread *trigger_thread;
123
124     bool needs_tid_update;
125 };
126
127 /*
128  * libthread_db defines this as opaque. We need to implement it.
129  */
130 struct ps_prochandle {
131     thread_db_process *thread_db_proc;
132 };
133
134 class thread_db_thread : public int_thread
135 {
136     friend class ThreadDBCreateHandler;
137     friend class thread_db_process;
138 public:
139     thread_db_thread(int_process *p, Dyninst::THR_ID t, Dyninst::LWP l);
140     virtual ~thread_db_thread();
141
142     Event::ptr getThreadEvent();
143     bool setEventReporting(bool on);
144     bool fetchThreadInfo();
145
146     void markDestroyed();
147     bool isDestroyed();
148
149     // Platform-dependent functionality
150     virtual bool plat_getThreadArea(int val, Dyninst::Address &addr);
151     virtual bool plat_convertToSystemRegs(const int_registerPool &pool, unsigned char *regs);
152
153     virtual bool haveUserThreadInfo();
154     virtual bool getTID(Dyninst::THR_ID &tid);
155     virtual bool getStartFuncAddress(Dyninst::Address &addr);
156     virtual bool getStackBase(Dyninst::Address &addr);
157     virtual bool getStackSize(unsigned long &size);
158     virtual bool getTLSPtr(Dyninst::Address &addr);
159 protected:
160     // Initialization of the thread handle cannot be performed until 
161     // thread_db is loaded and initialized. When creating a process,
162     // we need to be able to create an instance of thread_db_thread
163     // before thread_db is initialized so we lazily initialize the
164     // thread handle
165     bool initThreadHandle();
166     
167     td_thrhandle_t *threadHandle;
168     td_thrinfo_t tinfo;
169
170     // Since a thread destroy event happens at a breakpoint, the 
171     // breakpoint needs to be cleaned up before the thread can be 
172     // removed from the threadPool and deleted.
173     bool destroyed;
174     bool tinfo_initialized;
175     bool thread_initialized;
176     bool threadHandle_alloced;
177 };
178
179 class ThreadDBCreateHandler : public Handler
180 {
181 public:
182     ThreadDBCreateHandler();
183     virtual ~ThreadDBCreateHandler();
184     virtual Handler::handler_ret_t handleEvent(Event::ptr ev);
185     virtual int getPriority() const;
186     void getEventTypesHandled(vector<EventType> &etypes);
187 };
188
189 class ThreadDBLibHandler : public Handler
190 {
191 public:
192     ThreadDBLibHandler();
193     virtual ~ThreadDBLibHandler();
194     virtual Handler::handler_ret_t handleEvent(Event::ptr ev);
195     virtual int getPriority() const;
196     void getEventTypesHandled(std::vector<EventType> &etypes);
197 };
198
199 class ThreadDBDestroyHandler : public Handler
200 {
201 public:
202     ThreadDBDestroyHandler();
203     virtual ~ThreadDBDestroyHandler();
204     virtual Handler::handler_ret_t handleEvent(Event::ptr ev);
205     virtual int getPriority() const;
206     void getEventTypesHandled(std::vector<EventType> &etypes);
207 };
208
209 typedef struct new_thread_data {
210   td_thrhandle_t *thr_handle;
211   td_thrinfo_t thr_info;
212   bool threadHandle_alloced;
213 } new_thread_data_t;
214
215 #else
216
217 class thread_db_thread : public int_thread
218 {
219   public:
220     thread_db_thread(int_process *p, Dyninst::THR_ID t, Dyninst::LWP l);
221     virtual ~thread_db_thread();
222
223     virtual bool plat_getThreadArea(int val, Dyninst::Address &addr);
224     virtual bool haveUserThreadInfo();
225     virtual bool getTID(Dyninst::THR_ID &tid);
226     virtual bool getStartFuncAddress(Dyninst::Address &addr);
227     virtual bool getStackBase(Dyninst::Address &addr);
228     virtual bool getStackSize(unsigned long &size);
229     virtual bool getTLSPtr(Dyninst::Address &addr);
230 };
231
232
233 class thread_db_process : virtual public int_process
234 {
235   public:
236     thread_db_process(Dyninst::PID p, std::string e, std::vector<std::string> a, std::vector<std::string> envp, std::map<int, int> f);
237     thread_db_process(Dyninst::PID pid_, int_process *p);
238     virtual ~thread_db_process();
239
240     bool decodeThreadBP(EventBreakpoint::ptr bp);
241     static void addThreadDBHandlers(HandlerPool *hpool);
242 };
243
244 #endif
245
246 #endif