* bsd-uthread.h: New file.
[external/binutils.git] / gdb / bsd-uthread.c
1 /* BSD user-level threads support.
2
3    Copyright 2005 Free Software Foundation, Inc.
4
5    This file is part of GDB.
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 59 Temple Place - Suite 330,
20    Boston, MA 02111-1307, USA.  */
21
22 #include "defs.h"
23 #include "gdbcore.h"
24 #include "gdbthread.h"
25 #include "inferior.h"
26 #include "objfiles.h"
27 #include "observer.h"
28 #include "regcache.h"
29 #include "solist.h"
30 #include "symfile.h"
31 #include "target.h"
32
33 #include "gdb_assert.h"
34 #include "gdb_obstack.h"
35
36 #include "bsd-uthread.h"
37
38 /* HACK: Save the bsd_uthreads ops returned by bsd_uthread_target.  */
39 static struct target_ops *bsd_uthread_ops_hack;
40 \f
41
42 /* Architecture-specific operations.  */
43
44 /* Per-architecture data key.  */
45 static struct gdbarch_data *bsd_uthread_data;
46
47 struct bsd_uthread_ops
48 {
49   /* Supply registers for an inactive thread to a register cache.  */
50   void (*supply_uthread)(struct regcache *, int, CORE_ADDR);
51
52   /* Collect registers for an inactive thread from a register cache.  */
53   void (*collect_uthread)(const struct regcache *, int, CORE_ADDR);
54 };
55
56 static void *
57 bsd_uthread_init (struct obstack *obstack)
58 {
59   struct bsd_uthread_ops *ops;
60
61   ops = OBSTACK_ZALLOC (obstack, struct bsd_uthread_ops);
62   return ops;
63 }
64
65 /* Set the function that supplies registers from an inactive thread
66    for architecture GDBARCH to SUPPLY_UTHREAD.  */
67
68 void
69 bsd_uthread_set_supply_uthread (struct gdbarch *gdbarch,
70                                 void (*supply_uthread) (struct regcache *,
71                                                         int, CORE_ADDR))
72 {
73   struct bsd_uthread_ops *ops = gdbarch_data (gdbarch, bsd_uthread_data);
74   ops->supply_uthread = supply_uthread;
75 }
76
77 /* Set the function that collects registers for an inactive thread for
78    architecture GDBARCH to SUPPLY_UTHREAD.  */
79
80 void
81 bsd_uthread_set_collect_uthread (struct gdbarch *gdbarch,
82                          void (*collect_uthread) (const struct regcache *,
83                                                   int, CORE_ADDR))
84 {
85   struct bsd_uthread_ops *ops = gdbarch_data (gdbarch, bsd_uthread_data);
86   ops->collect_uthread = collect_uthread;
87 }
88
89 /* Magic number to help recognize a valid thread structure.  */
90 #define BSD_UTHREAD_PTHREAD_MAGIC       0xd09ba115
91
92 /* Check whether the thread structure at ADDR is valid.  */
93
94 static void
95 bsd_uthread_check_magic (CORE_ADDR addr)
96 {
97   ULONGEST magic = read_memory_unsigned_integer (addr, 4);
98
99   if (magic != BSD_UTHREAD_PTHREAD_MAGIC)
100     error ("Bad magic");
101 }
102
103 /* Thread states.  */
104 #define BSD_UTHREAD_PS_RUNNING  0
105 #define BSD_UTHREAD_PS_DEAD     18
106
107 /* Address of the pointer to the the thread structure for the running
108    thread.  */
109 static CORE_ADDR bsd_uthread_thread_run_addr;
110
111 /* Address of the list of all threads.  */
112 static CORE_ADDR bsd_uthread_thread_list_addr;
113
114 /* Offsets of various "interesting" bits in the thread structure.  */
115 static int bsd_uthread_thread_state_offset = -1;
116 static int bsd_uthread_thread_next_offset = -1;
117 static int bsd_uthread_thread_ctx_offset;
118
119 /* Name of shared threads library.  */
120 static const char *bsd_uthread_solib_name;
121
122 /* Non-zero if the thread startum implemented by this module is active.  */
123 static int bsd_uthread_active;
124
125 static CORE_ADDR
126 bsd_uthread_lookup_address (const char *name, struct objfile *objfile)
127 {
128   struct minimal_symbol *sym;
129
130   sym = lookup_minimal_symbol (name, NULL, objfile);
131   if (sym)
132     return SYMBOL_VALUE_ADDRESS (sym);
133
134   return 0;
135 }
136
137 static int
138 bsd_uthread_lookup_offset (const char *name, struct objfile *objfile)
139 {
140   CORE_ADDR addr;
141
142   addr = bsd_uthread_lookup_address (name, objfile);
143   if (addr == 0)
144     return 0;
145
146   return read_memory_unsigned_integer (addr, 4);
147 }
148
149 /* If OBJFILE contains the symbols corresponding to one of the
150    supported user-level threads libraries, activate the thread stratum
151    implemented by this module.  */
152
153 static int
154 bsd_uthread_activate (struct objfile *objfile)
155 {
156   struct gdbarch *gdbarch = current_gdbarch;
157   struct bsd_uthread_ops *ops = gdbarch_data (gdbarch, bsd_uthread_data);
158
159   /* Skip if the thread stratum has already been activated.  */
160   if (bsd_uthread_active)
161     return 0;
162
163   /* There's no point in enabling this module if no
164      architecture-specific operations are provided.  */
165   if (!ops->supply_uthread)
166     return 0;
167
168   bsd_uthread_thread_run_addr =
169     bsd_uthread_lookup_address ("_thread_run", objfile);
170   if (bsd_uthread_thread_run_addr == 0)
171     return 0;
172
173   bsd_uthread_thread_list_addr =
174     bsd_uthread_lookup_address ("_thread_list", objfile);
175   if (bsd_uthread_thread_list_addr == 0)
176     return 0;
177
178   bsd_uthread_thread_state_offset =
179     bsd_uthread_lookup_offset ("_thread_state_offset", objfile);
180   if (bsd_uthread_thread_state_offset == 0)
181     return 0;
182
183   bsd_uthread_thread_next_offset =
184     bsd_uthread_lookup_offset ("_thread_next_offset", objfile);
185   if (bsd_uthread_thread_next_offset == 0)
186     return 0;
187
188   bsd_uthread_thread_ctx_offset =
189     bsd_uthread_lookup_offset ("_thread_ctx_offset", objfile);
190
191   push_target (bsd_uthread_ops_hack);
192   bsd_uthread_active = 1;
193   return 1;
194 }
195
196 /* Deactivate the thread stratum implemented by this module.  */
197
198 static void
199 bsd_uthread_deactivate (void)
200 {
201   /* Skip if the thread stratum has already been deactivated.  */
202   if (!bsd_uthread_active)
203     return;
204
205   bsd_uthread_active = 0;
206   unpush_target (bsd_uthread_ops_hack);
207
208   bsd_uthread_thread_run_addr = 0;
209   bsd_uthread_thread_list_addr = 0;
210   bsd_uthread_thread_state_offset = 0;
211   bsd_uthread_thread_next_offset = 0;
212   bsd_uthread_thread_ctx_offset = 0;
213   bsd_uthread_solib_name = NULL;
214 }
215
216 void
217 bsd_uthread_inferior_created (struct target_ops *ops, int from_tty)
218 {
219   bsd_uthread_activate (NULL);
220 }
221
222 /* Likely candidates for the threads library.  */
223 static const char *bsd_uthread_solib_names[] =
224 {
225   "/usr/lib/libc_r.so",         /* FreeBSD */
226   "/usr/lib/libpthread.so",     /* OpenBSD */
227   NULL
228 };
229
230 void
231 bsd_uthread_solib_loaded (struct so_list *so)
232 {
233   const char **names = bsd_uthread_solib_names;
234
235   for (names = bsd_uthread_solib_names; *names; names++)
236     {
237       if (strncmp (so->so_original_name, *names, strlen (*names)) == 0)
238         {
239           solib_read_symbols (so, so->from_tty);
240
241           if (bsd_uthread_activate (so->objfile))
242             {
243               bsd_uthread_solib_name == so->so_original_name;
244               return;
245             }
246         }
247     }
248 }
249
250 void
251 bsd_uthread_solib_unloaded (struct so_list *so)
252 {
253   if (!bsd_uthread_solib_name)
254     return;
255
256   if (strcmp (so->so_original_name, bsd_uthread_solib_name) == 0)
257     bsd_uthread_deactivate ();
258 }
259
260 static void
261 bsd_uthread_mourn_inferior (void)
262 {
263   find_target_beneath (bsd_uthread_ops_hack)->to_mourn_inferior ();
264   bsd_uthread_deactivate ();
265 }
266
267 static void
268 bsd_uthread_fetch_registers (int regnum)
269 {
270   struct gdbarch *gdbarch = current_gdbarch;
271   struct bsd_uthread_ops *ops = gdbarch_data (gdbarch, bsd_uthread_data);
272   CORE_ADDR addr = ptid_get_tid (inferior_ptid);
273   CORE_ADDR active_addr;
274
275   /* Always fetch the appropriate registers from the layer beneath.  */
276   find_target_beneath (bsd_uthread_ops_hack)->to_fetch_registers (regnum);
277
278   /* FIXME: That might have gotten us more than we asked for.  Make
279      sure we overwrite all relevant registers with values from the
280      thread structure.  This can go once we fix the underlying target.  */
281   regnum = -1;
282
283   active_addr = read_memory_typed_address (bsd_uthread_thread_run_addr,
284                                            builtin_type_void_data_ptr);
285   if (addr != 0 && addr != active_addr)
286     {
287       bsd_uthread_check_magic (addr);
288       ops->supply_uthread (current_regcache, regnum,
289                            addr + bsd_uthread_thread_ctx_offset);
290     }
291 }
292
293 static void
294 bsd_uthread_store_registers (int regnum)
295 {
296   struct gdbarch *gdbarch = current_gdbarch;
297   struct bsd_uthread_ops *ops = gdbarch_data (gdbarch, bsd_uthread_data);
298   CORE_ADDR addr = ptid_get_tid (inferior_ptid);
299   CORE_ADDR active_addr;
300
301   active_addr = read_memory_typed_address (bsd_uthread_thread_run_addr,
302                                            builtin_type_void_data_ptr);
303   if (addr != 0 && addr != active_addr)
304     {
305       bsd_uthread_check_magic (addr);
306       ops->collect_uthread (current_regcache, regnum,
307                             addr + bsd_uthread_thread_ctx_offset);
308     }
309   else
310     {
311       /* Updating the thread that is currently running; pass the
312          request to the layer beneath.  */
313       find_target_beneath (bsd_uthread_ops_hack)->to_store_registers (regnum);
314     }
315 }
316
317 /* FIXME: This function is only there because otherwise GDB tries to
318    invoke deprecate_xfer_memory.  */
319
320 static LONGEST
321 bsd_uthread_xfer_partial (struct target_ops *ops, enum target_object object,
322                           const char *annex, void *readbuf,
323                           const void *writebuf, ULONGEST offset, LONGEST len)
324 {
325   gdb_assert (ops->beneath->to_xfer_partial);
326   return ops->beneath->to_xfer_partial (ops->beneath, object, annex, readbuf,
327                                         writebuf, offset, len);
328 }
329
330 static ptid_t
331 bsd_uthread_wait (ptid_t ptid, struct target_waitstatus *status)
332 {
333   CORE_ADDR addr;
334
335   /* Pass the request to the layer beneath.  */
336   ptid = find_target_beneath (bsd_uthread_ops_hack)->to_wait (ptid, status);
337
338   /* Fetch the corresponding thread ID, and augment the returned
339      process ID with it.  */
340   addr = read_memory_typed_address (bsd_uthread_thread_run_addr,
341                                     builtin_type_void_data_ptr);
342   if (addr != 0)
343     {
344       char buf[4];
345
346       /* FIXME: For executables linked statically with the threads
347          library, we end up here before the program has actually been
348          executed.  In that case ADDR will be garbage since it has
349          been read from the wrong virtual memory image.  */
350       if (target_read_memory (addr, buf, 4) == 0)
351         {
352           ULONGEST magic = extract_unsigned_integer (buf, 4);
353           if (magic == BSD_UTHREAD_PTHREAD_MAGIC)
354             ptid = ptid_build (ptid_get_pid (ptid), 0, addr);
355         }
356     }
357
358   /* HACK: Twiddle INFERIOR_PTID such that the initial thread of a
359      process isn't recognized as a new thread.  */
360   if (ptid_get_tid (ptid) != 0 && !in_thread_list (ptid)
361       && ptid_get_tid (inferior_ptid) == 0)
362     {
363       add_thread (ptid);
364       inferior_ptid = ptid;
365     }
366
367   return ptid;
368 }
369
370 static void
371 bsd_uthread_resume (ptid_t ptid, int step, enum target_signal sig)
372 {
373   /* Pass the request to the layer beneath.  */
374   find_target_beneath (bsd_uthread_ops_hack)->to_resume (ptid, step, sig);
375 }
376
377 static int
378 bsd_uthread_thread_alive (ptid_t ptid)
379 {
380   CORE_ADDR addr = ptid_get_tid (inferior_ptid);
381
382   if (addr != 0)
383     {
384       int offset = bsd_uthread_thread_state_offset;
385       ULONGEST state;
386
387       bsd_uthread_check_magic (addr);
388
389       state = read_memory_unsigned_integer (addr + offset, 4);
390       if (state == BSD_UTHREAD_PS_DEAD)
391         return 0;
392     }
393
394   return find_target_beneath (bsd_uthread_ops_hack)->to_thread_alive (ptid);
395 }
396
397 static void
398 bsd_uthread_find_new_threads (void)
399 {
400   pid_t pid = ptid_get_pid (inferior_ptid);
401   int offset = bsd_uthread_thread_next_offset;
402   CORE_ADDR addr;
403
404   addr = read_memory_typed_address (bsd_uthread_thread_list_addr,
405                                     builtin_type_void_data_ptr);
406   while (addr != 0)
407     {
408       ptid_t ptid = ptid_build (pid, 0, addr);
409
410       if (!in_thread_list (ptid))
411         add_thread (ptid);
412
413       addr = read_memory_typed_address (addr + offset,
414                                         builtin_type_void_data_ptr);
415     }
416 }
417
418 /* Possible states a thread can be in.  */
419 static char *bsd_uthread_state[] =
420 {
421   "RUNNING",
422   "SIGTHREAD",
423   "MUTEX_WAIT",
424   "COND_WAIT",
425   "FDLR_WAIT",
426   "FDLW_WAIT",
427   "FDR_WAIT",
428   "FDW_WAIT",
429   "FILE_WAIT",
430   "POLL_WAIT",
431   "SELECT_WAIT",
432   "SLEEP_WAIT",
433   "WAIT_WAIT",
434   "SIGSUSPEND",
435   "SIGWAIT",
436   "SPINBLOCK",
437   "JOIN",
438   "SUSPENDED",
439   "DEAD",
440   "DEADLOCK"
441 };
442
443 /* Return a string describing th state of the thread specified by
444    INFO.  */
445
446 static char *
447 bsd_uthread_extra_thread_info (struct thread_info *info)
448 {
449   CORE_ADDR addr = ptid_get_tid (info->ptid);
450
451   if (addr != 0)
452     {
453       int offset = bsd_uthread_thread_state_offset;
454       ULONGEST state;
455
456       state = read_memory_unsigned_integer (addr + offset, 4);
457       if (state < ARRAY_SIZE (bsd_uthread_state))
458         return bsd_uthread_state[state];
459     }
460
461   return NULL;
462 }
463
464 static char *
465 bsd_uthread_pid_to_str (ptid_t ptid)
466 {
467   if (ptid_get_tid (ptid) != 0)
468     {
469       static char buf[64];
470       int size;
471
472       size = snprintf (buf, sizeof buf, "process %d, thread 0x%lx",
473                        ptid_get_pid (ptid), ptid_get_tid (ptid));
474       gdb_assert (size < sizeof buf);
475       return buf;
476     }
477
478   return normal_pid_to_str (ptid);
479 }
480
481 struct target_ops *
482 bsd_uthread_target (void)
483 {
484   struct target_ops *t = XZALLOC (struct target_ops);
485
486   t->to_shortname = "bsd-uthreads";
487   t->to_longname = "BSD user-level threads";
488   t->to_doc = "BSD user-level threads";
489   t->to_mourn_inferior = bsd_uthread_mourn_inferior;
490   t->to_fetch_registers = bsd_uthread_fetch_registers;
491   t->to_store_registers = bsd_uthread_store_registers;
492   t->to_xfer_partial = bsd_uthread_xfer_partial;
493   t->to_wait = bsd_uthread_wait;
494   t->to_resume = bsd_uthread_resume;
495   t->to_thread_alive = bsd_uthread_thread_alive;
496   t->to_find_new_threads = bsd_uthread_find_new_threads;
497   t->to_extra_thread_info = bsd_uthread_extra_thread_info;
498   t->to_pid_to_str = bsd_uthread_pid_to_str;
499   t->to_stratum = thread_stratum;
500   t->to_magic = OPS_MAGIC;
501   bsd_uthread_ops_hack = t;
502
503   return t;
504 }
505
506 void
507 _initialize_bsd_uthread (void)
508 {
509   add_target (bsd_uthread_target ());
510
511   bsd_uthread_data = gdbarch_data_register_pre_init (bsd_uthread_init);
512
513   observer_attach_inferior_created (bsd_uthread_inferior_created);
514   observer_attach_solib_loaded (bsd_uthread_solib_loaded);
515   observer_attach_solib_unloaded (bsd_uthread_solib_unloaded);
516 }