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