2005-05-01 Paul Brook <paul@codesourcery.com>
[deliverable/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"
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. */
39static struct target_ops *bsd_uthread_ops_hack;
40\f
41
42/* Architecture-specific operations. */
43
44/* Per-architecture data key. */
45static struct gdbarch_data *bsd_uthread_data;
46
47struct 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
56static void *
57bsd_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
68void
69bsd_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
80void
81bsd_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
94static void
95bsd_uthread_check_magic (CORE_ADDR addr)
96{
97 ULONGEST magic = read_memory_unsigned_integer (addr, 4);
98
99 if (magic != BSD_UTHREAD_PTHREAD_MAGIC)
8a3fe4f8 100 error (_("Bad magic"));
82f5c14f
MK
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. */
109static CORE_ADDR bsd_uthread_thread_run_addr;
110
111/* Address of the list of all threads. */
112static CORE_ADDR bsd_uthread_thread_list_addr;
113
114/* Offsets of various "interesting" bits in the thread structure. */
115static int bsd_uthread_thread_state_offset = -1;
116static int bsd_uthread_thread_next_offset = -1;
117static int bsd_uthread_thread_ctx_offset;
118
119/* Name of shared threads library. */
120static const char *bsd_uthread_solib_name;
121
122/* Non-zero if the thread startum implemented by this module is active. */
123static int bsd_uthread_active;
124
125static CORE_ADDR
126bsd_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
137static int
138bsd_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
153static int
154bsd_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
198static void
199bsd_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
216void
217bsd_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. */
223static const char *bsd_uthread_solib_names[] =
224{
225 "/usr/lib/libc_r.so", /* FreeBSD */
226 "/usr/lib/libpthread.so", /* OpenBSD */
227 NULL
228};
229
230void
231bsd_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
250void
251bsd_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
260static void
261bsd_uthread_mourn_inferior (void)
262{
263 find_target_beneath (bsd_uthread_ops_hack)->to_mourn_inferior ();
264 bsd_uthread_deactivate ();
265}
266
267static void
268bsd_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
293static void
294bsd_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
320static LONGEST
321bsd_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
330static ptid_t
331bsd_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
370static void
371bsd_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
377static int
378bsd_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
397static void
398bsd_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. */
419static 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
446static char *
447bsd_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
464static char *
465bsd_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
481struct target_ops *
482bsd_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
506void
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}
This page took 0.073099 seconds and 4 git commands to generate.