* mips-linux-nat.c: Include "gdb_proc_service.h".
[deliverable/binutils-gdb.git] / gdb / gdbserver / thread-db.c
CommitLineData
0d62e5e8 1/* Thread management interface, for the remote server for GDB.
6f0f660e 2 Copyright (C) 2002, 2004, 2005
0d62e5e8
DJ
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
6f0f660e
EZ
21 Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 Boston, MA 02110-1301, USA. */
0d62e5e8
DJ
23
24#include "server.h"
25
26#include "linux-low.h"
27
28extern 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. */
50static struct ps_prochandle proc_handle;
51
52/* Connection to the libthread_db library. */
53static td_thragent_t *thread_agent;
54
55static int find_new_threads_callback (const td_thrhandle_t *th_p, void *data);
56
57static char *
58thread_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";
3db0444b
DJ
106#ifdef HAVE_TD_VERSION
107 case TD_VERSION:
108 return "version mismatch between libthread_db and libpthread";
109#endif
0d62e5e8
DJ
110 default:
111 snprintf (buf, sizeof (buf), "unknown thread_db error '%d'", err);
112 return buf;
113 }
114}
115
116#if 0
117static char *
118thread_db_state_str (td_thr_state_e state)
119{
120 static char buf[64];
121
122 switch (state)
123 {
124 case TD_THR_STOPPED:
125 return "stopped by debugger";
126 case TD_THR_RUN:
127 return "runnable";
128 case TD_THR_ACTIVE:
129 return "active";
130 case TD_THR_ZOMBIE:
131 return "zombie";
132 case TD_THR_SLEEP:
133 return "sleeping";
134 case TD_THR_STOPPED_ASLEEP:
135 return "stopped by debugger AND blocked";
136 default:
137 snprintf (buf, sizeof (buf), "unknown thread_db state %d", state);
138 return buf;
139 }
140}
141#endif
142
143static void
144thread_db_create_event (CORE_ADDR where)
145{
146 td_event_msg_t msg;
147 td_err_e err;
148 struct inferior_linux_data *tdata;
149
150 if (debug_threads)
151 fprintf (stderr, "Thread creation event.\n");
152
153 tdata = inferior_target_data (current_inferior);
154
155 /* FIXME: This assumes we don't get another event.
156 In the LinuxThreads implementation, this is safe,
157 because all events come from the manager thread
158 (except for its own creation, of course). */
159 err = td_ta_event_getmsg (thread_agent, &msg);
160 if (err != TD_OK)
161 fprintf (stderr, "thread getmsg err: %s\n",
162 thread_db_err_str (err));
163
164 /* msg.event == TD_EVENT_CREATE */
165
166 find_new_threads_callback (msg.th_p, NULL);
167}
168
169#if 0
170static void
171thread_db_death_event (CORE_ADDR where)
172{
173 if (debug_threads)
174 fprintf (stderr, "Thread death event.\n");
175}
176#endif
177
178static int
179thread_db_enable_reporting ()
180{
181 td_thr_events_t events;
182 td_notify_t notify;
183 td_err_e err;
184
185 /* Set the process wide mask saying which events we're interested in. */
186 td_event_emptyset (&events);
187 td_event_addset (&events, TD_CREATE);
188
189#if 0
190 /* This is reported to be broken in glibc 2.1.3. A different approach
191 will be necessary to support that. */
192 td_event_addset (&events, TD_DEATH);
193#endif
194
195 err = td_ta_set_event (thread_agent, &events);
196 if (err != TD_OK)
197 {
198 warning ("Unable to set global thread event mask: %s",
199 thread_db_err_str (err));
200 return 0;
201 }
202
203 /* Get address for thread creation breakpoint. */
204 err = td_ta_event_addr (thread_agent, TD_CREATE, &notify);
205 if (err != TD_OK)
206 {
207 warning ("Unable to get location for thread creation breakpoint: %s",
208 thread_db_err_str (err));
209 return 0;
210 }
211 set_breakpoint_at ((CORE_ADDR) (unsigned long) notify.u.bptaddr,
212 thread_db_create_event);
213
214#if 0
215 /* Don't concern ourselves with reported thread deaths, only
216 with actual thread deaths (via wait). */
217
218 /* Get address for thread death breakpoint. */
219 err = td_ta_event_addr (thread_agent, TD_DEATH, &notify);
220 if (err != TD_OK)
221 {
222 warning ("Unable to get location for thread death breakpoint: %s",
223 thread_db_err_str (err));
224 return;
225 }
226 set_breakpoint_at ((CORE_ADDR) (unsigned long) notify.u.bptaddr,
227 thread_db_death_event);
228#endif
229
230 return 1;
231}
232
233static void
234maybe_attach_thread (const td_thrhandle_t *th_p, td_thrinfo_t *ti_p)
235{
236 td_err_e err;
237 struct thread_info *inferior;
238 struct process_info *process;
239
240 /* If we are attaching to our first thread, things are a little
241 different. */
242 if (all_threads.head == all_threads.tail)
243 {
244 inferior = (struct thread_info *) all_threads.head;
245 process = get_thread_process (inferior);
246 if (process->thread_known == 0)
247 {
248 /* Switch to indexing the threads list by TID. */
249 change_inferior_id (&all_threads, ti_p->ti_tid);
250 goto found;
251 }
252 }
253
254 inferior = (struct thread_info *) find_inferior_id (&all_threads,
255 ti_p->ti_tid);
256 if (inferior != NULL)
257 return;
258
259 if (debug_threads)
260 fprintf (stderr, "Attaching to thread %ld (LWP %d)\n",
261 ti_p->ti_tid, ti_p->ti_lid);
262 linux_attach_lwp (ti_p->ti_lid, ti_p->ti_tid);
263 inferior = (struct thread_info *) find_inferior_id (&all_threads,
264 ti_p->ti_tid);
265 if (inferior == NULL)
266 {
267 warning ("Could not attach to thread %ld (LWP %d)\n",
268 ti_p->ti_tid, ti_p->ti_lid);
269 return;
270 }
271
272 process = inferior_target_data (inferior);
273
274found:
275 new_thread_notify (ti_p->ti_tid);
276
277 process->tid = ti_p->ti_tid;
278 process->lwpid = ti_p->ti_lid;
279
280 process->thread_known = 1;
281 err = td_thr_event_enable (th_p, 1);
282 if (err != TD_OK)
283 error ("Cannot enable thread event reporting for %d: %s",
284 ti_p->ti_lid, thread_db_err_str (err));
285}
286
287static int
288find_new_threads_callback (const td_thrhandle_t *th_p, void *data)
289{
290 td_thrinfo_t ti;
291 td_err_e err;
292
293 err = td_thr_get_info (th_p, &ti);
294 if (err != TD_OK)
295 error ("Cannot get thread info: %s", thread_db_err_str (err));
296
297 /* Check for zombies. */
298 if (ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE)
299 return 0;
300
301 maybe_attach_thread (th_p, &ti);
302
303 return 0;
304}
305
306static void
307thread_db_find_new_threads (void)
308{
309 td_err_e err;
310
311 /* Iterate over all user-space threads to discover new threads. */
312 err = td_ta_thr_iter (thread_agent, find_new_threads_callback, NULL,
313 TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
314 TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
315 if (err != TD_OK)
316 error ("Cannot find new threads: %s", thread_db_err_str (err));
317}
318
fd500816
DJ
319/* Cache all future symbols that thread_db might request. We can not
320 request symbols at arbitrary states in the remote protocol, only
321 when the client tells us that new symbols are available. So when
322 we load the thread library, make sure to check the entire list. */
323
324static void
325thread_db_look_up_symbols (void)
326{
327 const char **sym_list = td_symbol_list ();
328 CORE_ADDR unused;
329
330 for (sym_list = td_symbol_list (); *sym_list; sym_list++)
331 look_up_one_symbol (*sym_list, &unused);
332}
333
0d62e5e8
DJ
334int
335thread_db_init ()
336{
337 int err;
338
fd500816
DJ
339 /* FIXME drow/2004-10-16: This is the "overall process ID", which
340 GNU/Linux calls tgid, "thread group ID". When we support
341 attaching to threads, the original thread may not be the correct
342 thread. We would have to get the process ID from /proc for NPTL.
343 For LinuxThreads we could do something similar: follow the chain
344 of parent processes until we find the highest one we're attached
345 to, and use its tgid.
346
347 This isn't the only place in gdbserver that assumes that the first
348 process in the list is the thread group leader. */
0d62e5e8
DJ
349 proc_handle.pid = ((struct inferior_list_entry *)current_inferior)->id;
350
351 err = td_ta_new (&proc_handle, &thread_agent);
352 switch (err)
353 {
354 case TD_NOLIBTHREAD:
355 /* No thread library was detected. */
356 return 0;
357
358 case TD_OK:
359 /* The thread library was detected. */
360
361 if (thread_db_enable_reporting () == 0)
362 return 0;
363 thread_db_find_new_threads ();
fd500816 364 thread_db_look_up_symbols ();
0d62e5e8
DJ
365 return 1;
366
367 default:
3db0444b
DJ
368 warning ("error initializing thread_db library: %s",
369 thread_db_err_str (err));
0d62e5e8
DJ
370 }
371
372 return 0;
373}
This page took 0.293359 seconds and 4 git commands to generate.