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