]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/gdb/gdb/gdbserver/thread-db.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / gdb / gdb / gdbserver / thread-db.c
1 /* Thread management interface, for the remote server for GDB.
2    Copyright 2002
3    Free Software Foundation, Inc.
4
5    Contributed by MontaVista Software.
6
7    This file is part of GDB.
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 59 Temple Place - Suite 330,
22    Boston, MA 02111-1307, USA.  */
23
24 #include "server.h"
25
26 #include "linux-low.h"
27
28 extern int debug_threads;
29
30 #ifdef HAVE_THREAD_DB_H
31 #include <thread_db.h>
32 #endif
33
34 /* Correct for all GNU/Linux targets (for quite some time).  */
35 #define GDB_GREGSET_T elf_gregset_t
36 #define GDB_FPREGSET_T elf_fpregset_t
37
38 #ifndef HAVE_ELF_FPREGSET_T
39 /* Make sure we have said types.  Not all platforms bring in <linux/elf.h>
40    via <sys/procfs.h>.  */
41 #ifdef HAVE_LINUX_ELF_H
42 #include <linux/elf.h>
43 #endif
44 #endif
45
46 #include "../gdb_proc_service.h"
47
48 /* Structure that identifies the child process for the
49    <proc_service.h> interface.  */
50 static struct ps_prochandle proc_handle;
51
52 /* Connection to the libthread_db library.  */
53 static td_thragent_t *thread_agent;
54
55 static int find_new_threads_callback (const td_thrhandle_t *th_p, void *data);
56
57 static char *
58 thread_db_err_str (td_err_e err)
59 {
60   static char buf[64];
61
62   switch (err)
63     {
64     case TD_OK:
65       return "generic 'call succeeded'";
66     case TD_ERR:
67       return "generic error";
68     case TD_NOTHR:
69       return "no thread to satisfy query";
70     case TD_NOSV:
71       return "no sync handle to satisfy query";
72     case TD_NOLWP:
73       return "no LWP to satisfy query";
74     case TD_BADPH:
75       return "invalid process handle";
76     case TD_BADTH:
77       return "invalid thread handle";
78     case TD_BADSH:
79       return "invalid synchronization handle";
80     case TD_BADTA:
81       return "invalid thread agent";
82     case TD_BADKEY:
83       return "invalid key";
84     case TD_NOMSG:
85       return "no event message for getmsg";
86     case TD_NOFPREGS:
87       return "FPU register set not available";
88     case TD_NOLIBTHREAD:
89       return "application not linked with libthread";
90     case TD_NOEVENT:
91       return "requested event is not supported";
92     case TD_NOCAPAB:
93       return "capability not available";
94     case TD_DBERR:
95       return "debugger service failed";
96     case TD_NOAPLIC:
97       return "operation not applicable to";
98     case TD_NOTSD:
99       return "no thread-specific data for this thread";
100     case TD_MALLOC:
101       return "malloc failed";
102     case TD_PARTIALREG:
103       return "only part of register set was written/read";
104     case TD_NOXREGS:
105       return "X register set not available for this thread";
106     default:
107       snprintf (buf, sizeof (buf), "unknown thread_db error '%d'", err);
108       return buf;
109     }
110 }
111
112 #if 0
113 static char *
114 thread_db_state_str (td_thr_state_e state)
115 {
116   static char buf[64];
117
118   switch (state)
119     {
120     case TD_THR_STOPPED:
121       return "stopped by debugger";
122     case TD_THR_RUN:
123       return "runnable";
124     case TD_THR_ACTIVE:
125       return "active";
126     case TD_THR_ZOMBIE:
127       return "zombie";
128     case TD_THR_SLEEP:
129       return "sleeping";
130     case TD_THR_STOPPED_ASLEEP:
131       return "stopped by debugger AND blocked";
132     default:
133       snprintf (buf, sizeof (buf), "unknown thread_db state %d", state);
134       return buf;
135     }
136 }
137 #endif
138
139 static void
140 thread_db_create_event (CORE_ADDR where)
141 {
142   td_event_msg_t msg;
143   td_err_e err;
144   struct inferior_linux_data *tdata;
145
146   if (debug_threads)
147     fprintf (stderr, "Thread creation event.\n");
148
149   tdata = inferior_target_data (current_inferior);
150
151   /* FIXME: This assumes we don't get another event.
152      In the LinuxThreads implementation, this is safe,
153      because all events come from the manager thread
154      (except for its own creation, of course).  */
155   err = td_ta_event_getmsg (thread_agent, &msg);
156   if (err != TD_OK)
157     fprintf (stderr, "thread getmsg err: %s\n",
158              thread_db_err_str (err));
159
160   /* msg.event == TD_EVENT_CREATE */
161
162   find_new_threads_callback (msg.th_p, NULL);
163 }
164
165 #if 0
166 static void
167 thread_db_death_event (CORE_ADDR where)
168 {
169   if (debug_threads)
170     fprintf (stderr, "Thread death event.\n");
171 }
172 #endif
173
174 static int
175 thread_db_enable_reporting ()
176 {
177   td_thr_events_t events;
178   td_notify_t notify;
179   td_err_e err;
180
181   /* Set the process wide mask saying which events we're interested in.  */
182   td_event_emptyset (&events);
183   td_event_addset (&events, TD_CREATE);
184
185 #if 0
186   /* This is reported to be broken in glibc 2.1.3.  A different approach
187      will be necessary to support that.  */
188   td_event_addset (&events, TD_DEATH);
189 #endif
190
191   err = td_ta_set_event (thread_agent, &events);
192   if (err != TD_OK)
193     {
194       warning ("Unable to set global thread event mask: %s",
195                thread_db_err_str (err));
196       return 0;
197     }
198
199   /* Get address for thread creation breakpoint.  */
200   err = td_ta_event_addr (thread_agent, TD_CREATE, &notify);
201   if (err != TD_OK)
202     {
203       warning ("Unable to get location for thread creation breakpoint: %s",
204                thread_db_err_str (err));
205       return 0;
206     }
207   set_breakpoint_at ((CORE_ADDR) (unsigned long) notify.u.bptaddr,
208                      thread_db_create_event);
209
210 #if 0
211   /* Don't concern ourselves with reported thread deaths, only
212      with actual thread deaths (via wait).  */
213
214   /* Get address for thread death breakpoint.  */
215   err = td_ta_event_addr (thread_agent, TD_DEATH, &notify);
216   if (err != TD_OK)
217     {
218       warning ("Unable to get location for thread death breakpoint: %s",
219                thread_db_err_str (err));
220       return;
221     }
222   set_breakpoint_at ((CORE_ADDR) (unsigned long) notify.u.bptaddr,
223                      thread_db_death_event);
224 #endif
225
226   return 1;
227 }
228
229 static void
230 maybe_attach_thread (const td_thrhandle_t *th_p, td_thrinfo_t *ti_p)
231 {
232   td_err_e err;
233   struct thread_info *inferior;
234   struct process_info *process;
235
236   /* If we are attaching to our first thread, things are a little
237      different.  */
238   if (all_threads.head == all_threads.tail)
239     {
240       inferior = (struct thread_info *) all_threads.head;
241       process = get_thread_process (inferior);
242       if (process->thread_known == 0)
243         {
244           /* Switch to indexing the threads list by TID.  */
245           change_inferior_id (&all_threads, ti_p->ti_tid);
246           goto found;
247         }
248     }
249   
250   inferior = (struct thread_info *) find_inferior_id (&all_threads,
251                                                       ti_p->ti_tid);
252   if (inferior != NULL)
253     return;
254
255   if (debug_threads)
256     fprintf (stderr, "Attaching to thread %ld (LWP %d)\n",
257              ti_p->ti_tid, ti_p->ti_lid);
258   linux_attach_lwp (ti_p->ti_lid, ti_p->ti_tid);
259   inferior = (struct thread_info *) find_inferior_id (&all_threads,
260                                                       ti_p->ti_tid);
261   if (inferior == NULL)
262     {
263       warning ("Could not attach to thread %ld (LWP %d)\n",
264                ti_p->ti_tid, ti_p->ti_lid);
265       return;
266     }
267
268   process = inferior_target_data (inferior);
269
270 found:
271   new_thread_notify (ti_p->ti_tid);
272
273   process->tid = ti_p->ti_tid;
274   process->lwpid = ti_p->ti_lid;
275
276   process->thread_known = 1;
277   err = td_thr_event_enable (th_p, 1);
278   if (err != TD_OK)
279     error ("Cannot enable thread event reporting for %d: %s",
280            ti_p->ti_lid, thread_db_err_str (err));
281 }
282
283 static int
284 find_new_threads_callback (const td_thrhandle_t *th_p, void *data)
285 {
286   td_thrinfo_t ti;
287   td_err_e err;
288
289   err = td_thr_get_info (th_p, &ti);
290   if (err != TD_OK)
291     error ("Cannot get thread info: %s", thread_db_err_str (err));
292
293   /* Check for zombies.  */
294   if (ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE)
295     return 0;
296
297   maybe_attach_thread (th_p, &ti);
298
299   return 0;
300 }
301
302 static void
303 thread_db_find_new_threads (void)
304 {
305   td_err_e err;
306
307   /* Iterate over all user-space threads to discover new threads.  */
308   err = td_ta_thr_iter (thread_agent, find_new_threads_callback, NULL,
309                         TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
310                         TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
311   if (err != TD_OK)
312     error ("Cannot find new threads: %s", thread_db_err_str (err));
313 }
314
315 int
316 thread_db_init ()
317 {
318   int err;
319
320   proc_handle.pid = ((struct inferior_list_entry *)current_inferior)->id;
321
322   err = td_ta_new (&proc_handle, &thread_agent);
323   switch (err)
324     {
325     case TD_NOLIBTHREAD:
326       /* No thread library was detected.  */
327       return 0;
328
329     case TD_OK:
330       /* The thread library was detected.  */
331
332       if (thread_db_enable_reporting () == 0)
333         return 0;
334       thread_db_find_new_threads ();
335       return 1;
336
337     default:
338       warning ("error initializing thread_db library.");
339     }
340
341   return 0;
342 }