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