GDB (xrefs)
Loading...
Searching...
No Matches
bsd-uthread.c
Go to the documentation of this file.
1/* BSD user-level threads support.
2
3 Copyright (C) 2005-2023 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 3 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, see <http://www.gnu.org/licenses/>. */
19
20#include "defs.h"
21#include "gdbcore.h"
22#include "gdbthread.h"
23#include "inferior.h"
24#include "objfiles.h"
25#include "observable.h"
26#include "regcache.h"
27#include "solib.h"
28#include "solist.h"
29#include "symfile.h"
30#include "target.h"
31
32#include "gdbsupport/gdb_obstack.h"
33
34#include "bsd-uthread.h"
35
37 "bsd-uthreads",
38 N_("BSD user-level threads"),
39 N_("BSD user-level threads")
40};
41
42struct bsd_uthread_target final : public target_ops
43{
44 const target_info &info () const override
45 { return bsd_uthread_target_info; }
46
47 strata stratum () const override { return thread_stratum; }
48
49 void close () override;
50
51 void mourn_inferior () override;
52
53 void fetch_registers (struct regcache *, int) override;
54 void store_registers (struct regcache *, int) override;
55
56 ptid_t wait (ptid_t, struct target_waitstatus *, target_wait_flags) override;
57 void resume (ptid_t, int, enum gdb_signal) override;
58
59 bool thread_alive (ptid_t ptid) override;
60
61 void update_thread_list () override;
62
63 const char *extra_thread_info (struct thread_info *) override;
64
65 std::string pid_to_str (ptid_t) override;
66};
67
69
70
71/* Architecture-specific operations. */
72
74{
75 /* Supply registers for an inactive thread to a register cache. */
76 void (*supply_uthread)(struct regcache *, int, CORE_ADDR) = nullptr;
77
78 /* Collect registers for an inactive thread from a register cache. */
79 void (*collect_uthread)(const struct regcache *, int, CORE_ADDR) = nullptr;
80};
81
82/* Per-architecture data key. */
84
85static struct bsd_uthread_ops *
87{
89 if (ops == nullptr)
90 ops = bsd_uthread_data.emplace (gdbarch);
91 return ops;
92}
93
94/* Set the function that supplies registers from an inactive thread
95 for architecture GDBARCH to SUPPLY_UTHREAD. */
96
97void
99 void (*supply_uthread) (struct regcache *,
100 int, CORE_ADDR))
101{
103
105}
106
107/* Set the function that collects registers for an inactive thread for
108 architecture GDBARCH to SUPPLY_UTHREAD. */
109
110void
112 void (*collect_uthread) (const struct regcache *,
113 int, CORE_ADDR))
114{
116
118}
119
120/* Magic number to help recognize a valid thread structure. */
121#define BSD_UTHREAD_PTHREAD_MAGIC 0xd09ba115
122
123/* Check whether the thread structure at ADDR is valid. */
124
125static void
127{
128 enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
129 ULONGEST magic = read_memory_unsigned_integer (addr, 4, byte_order);
130
131 if (magic != BSD_UTHREAD_PTHREAD_MAGIC)
132 error (_("Bad magic"));
133}
134
135/* Thread states. */
136#define BSD_UTHREAD_PS_RUNNING 0
137#define BSD_UTHREAD_PS_DEAD 18
138
139/* Address of the pointer to the thread structure for the running
140 thread. */
142
143/* Address of the list of all threads. */
145
146/* Offsets of various "interesting" bits in the thread structure. */
150
151/* Name of shared threads library. */
152static const char *bsd_uthread_solib_name;
153
154/* Non-zero if the thread stratum implemented by this module is active. */
156
157static CORE_ADDR
159{
160 struct bound_minimal_symbol sym;
161
162 sym = lookup_minimal_symbol (name, NULL, objfile);
163 if (sym.minsym)
164 return sym.value_address ();
165
166 return 0;
167}
168
169static int
171{
172 enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
173 CORE_ADDR addr;
174
176 if (addr == 0)
177 return 0;
178
179 return read_memory_unsigned_integer (addr, 4, byte_order);
180}
181
182static CORE_ADDR
184{
185 struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
186 return read_memory_typed_address (addr, ptr_type);
187}
188
189/* If OBJFILE contains the symbols corresponding to one of the
190 supported user-level threads libraries, activate the thread stratum
191 implemented by this module. */
192
193static int
195{
196 struct gdbarch *gdbarch = target_gdbarch ();
198
199 /* Skip if the thread stratum has already been activated. */
201 return 0;
202
203 /* There's no point in enabling this module if no
204 architecture-specific operations are provided. */
205 if (!ops->supply_uthread)
206 return 0;
207
209 bsd_uthread_lookup_address ("_thread_run", objfile);
211 return 0;
212
214 bsd_uthread_lookup_address ("_thread_list", objfile);
216 return 0;
217
219 bsd_uthread_lookup_offset ("_thread_state_offset", objfile);
221 return 0;
222
224 bsd_uthread_lookup_offset ("_thread_next_offset", objfile);
226 return 0;
227
229 bsd_uthread_lookup_offset ("_thread_ctx_offset", objfile);
230
233 return 1;
234}
235
236/* Cleanup due to deactivation. */
237
238void
249
250/* Deactivate the thread stratum implemented by this module. */
251
252static void
254{
255 /* Skip if the thread stratum has already been deactivated. */
257 return;
258
260}
261
262static void
267
268/* Likely candidates for the threads library. */
269static const char * const bsd_uthread_solib_names[] =
270{
271 "/usr/lib/libc_r.so", /* FreeBSD */
272 "/usr/lib/libpthread.so", /* OpenBSD */
273 NULL
274};
275
276static void
278{
279 const char * const *names = bsd_uthread_solib_names;
280
281 for (names = bsd_uthread_solib_names; *names; names++)
282 {
283 if (startswith (so->so_original_name, *names))
284 {
285 solib_read_symbols (so, 0);
286
288 {
290 return;
291 }
292 }
293 }
294}
295
296static void
298{
300 return;
301
302 if (strcmp (so->so_original_name, bsd_uthread_solib_name) == 0)
304}
305
306void
312
313void
315{
316 struct gdbarch *gdbarch = regcache->arch ();
317 struct bsd_uthread_ops *uthread_ops = get_bsd_uthread (gdbarch);
318 ptid_t ptid = regcache->ptid ();
319 CORE_ADDR addr = ptid.tid ();
320 CORE_ADDR active_addr;
321 scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
322
323 /* We are doing operations (e.g. reading memory) that rely on
324 inferior_ptid. */
325 inferior_ptid = ptid;
326
327 /* Always fetch the appropriate registers from the layer beneath. */
329
330 /* FIXME: That might have gotten us more than we asked for. Make
331 sure we overwrite all relevant registers with values from the
332 thread structure. This can go once we fix the underlying target. */
333 regnum = -1;
334
336 if (addr != 0 && addr != active_addr)
337 {
339 uthread_ops->supply_uthread (regcache, regnum,
341 }
342}
343
344void
346{
347 struct gdbarch *gdbarch = regcache->arch ();
348 struct bsd_uthread_ops *uthread_ops = get_bsd_uthread (gdbarch);
349 ptid_t ptid = regcache->ptid ();
350 CORE_ADDR addr = ptid.tid ();
351 CORE_ADDR active_addr;
352 scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
353
354 /* We are doing operations (e.g. reading memory) that rely on
355 inferior_ptid. */
356 inferior_ptid = ptid;
357
359 if (addr != 0 && addr != active_addr)
360 {
362 uthread_ops->collect_uthread (regcache, regnum,
364 }
365 else
366 {
367 /* Updating the thread that is currently running; pass the
368 request to the layer beneath. */
370 }
371}
372
373ptid_t
375 target_wait_flags options)
376{
377 enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
378 CORE_ADDR addr;
380 = as_process_stratum_target (this->beneath ());
381
382 /* Pass the request to the layer beneath. */
383 ptid = beneath->wait (ptid, status, options);
384
385 /* If the process is no longer alive, there's no point in figuring
386 out the thread ID. It will fail anyway. */
387 if (status->kind () == TARGET_WAITKIND_SIGNALLED
388 || status->kind () == TARGET_WAITKIND_EXITED)
389 return ptid;
390
391 /* Fetch the corresponding thread ID, and augment the returned
392 process ID with it. */
394 if (addr != 0)
395 {
396 gdb_byte buf[4];
397
398 /* FIXME: For executables linked statically with the threads
399 library, we end up here before the program has actually been
400 executed. In that case ADDR will be garbage since it has
401 been read from the wrong virtual memory image. */
402 if (target_read_memory (addr, buf, 4) == 0)
403 {
404 ULONGEST magic = extract_unsigned_integer (buf, 4, byte_order);
405 if (magic == BSD_UTHREAD_PTHREAD_MAGIC)
406 ptid = ptid_t (ptid.pid (), 0, addr);
407 }
408 }
409
410 /* If INFERIOR_PTID doesn't have a tid member yet, and we now have a
411 ptid with tid set, then ptid is still the initial thread of
412 the process. Notify GDB core about it. */
413 if (inferior_ptid.tid () == 0
414 && ptid.tid () != 0 && !in_thread_list (beneath, ptid))
416
417 /* Don't let the core see a ptid without a corresponding thread. */
418 thread_info *thread = beneath->find_thread (ptid);
419 if (thread == NULL || thread->state == THREAD_EXITED)
420 add_thread (beneath, ptid);
421
422 return ptid;
423}
424
425void
426bsd_uthread_target::resume (ptid_t ptid, int step, enum gdb_signal sig)
427{
428 /* Pass the request to the layer beneath. */
429 beneath ()->resume (ptid, step, sig);
430}
431
432bool
434{
435 enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
436 CORE_ADDR addr = ptid.tid ();
437
438 if (addr != 0)
439 {
441 ULONGEST state;
442
444
445 state = read_memory_unsigned_integer (addr + offset, 4, byte_order);
446 if (state == BSD_UTHREAD_PS_DEAD)
447 return false;
448 }
449
450 return beneath ()->thread_alive (ptid);
451}
452
453void
455{
456 pid_t pid = inferior_ptid.pid ();
458 CORE_ADDR addr;
459
460 prune_threads ();
461
463 while (addr != 0)
464 {
465 ptid_t ptid = ptid_t (pid, 0, addr);
466
467 process_stratum_target *proc_target
469 thread_info *thread = proc_target->find_thread (ptid);
470 if (thread == nullptr || thread->state == THREAD_EXITED)
471 {
472 /* If INFERIOR_PTID doesn't have a tid member yet, then ptid
473 is still the initial thread of the process. Notify GDB
474 core about it. */
475 if (inferior_ptid.tid () == 0)
476 thread_change_ptid (proc_target, inferior_ptid, ptid);
477 else
478 add_thread (proc_target, ptid);
479 }
480
481 addr = bsd_uthread_read_memory_address (addr + offset);
482 }
483}
484
485/* Possible states a thread can be in. */
486static const char * const bsd_uthread_state[] =
487{
488 "RUNNING",
489 "SIGTHREAD",
490 "MUTEX_WAIT",
491 "COND_WAIT",
492 "FDLR_WAIT",
493 "FDLW_WAIT",
494 "FDR_WAIT",
495 "FDW_WAIT",
496 "FILE_WAIT",
497 "POLL_WAIT",
498 "SELECT_WAIT",
499 "SLEEP_WAIT",
500 "WAIT_WAIT",
501 "SIGSUSPEND",
502 "SIGWAIT",
503 "SPINBLOCK",
504 "JOIN",
505 "SUSPENDED",
506 "DEAD",
507 "DEADLOCK"
508};
509
510/* Return a string describing th state of the thread specified by
511 INFO. */
512
513const char *
515{
516 enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
517 CORE_ADDR addr = info->ptid.tid ();
518
519 if (addr != 0)
520 {
522 ULONGEST state;
523
524 state = read_memory_unsigned_integer (addr + offset, 4, byte_order);
525 if (state < ARRAY_SIZE (bsd_uthread_state))
526 return bsd_uthread_state[state];
527 }
528
529 return NULL;
530}
531
532std::string
534{
535 if (ptid.tid () != 0)
536 return string_printf ("process %d, thread 0x%s",
537 ptid.pid (),
538 phex_nz (ptid.tid (), sizeof (ULONGEST)));
539
540 return normal_pid_to_str (ptid);
541}
542
544void
int regnum
const char *const name
struct gdbarch * target_gdbarch(void)
static const char *const bsd_uthread_state[]
static void bsd_uthread_inferior_created(inferior *inf)
static void bsd_uthread_solib_loaded(struct so_list *so)
static void bsd_uthread_solib_unloaded(program_space *pspace, so_list *so)
static void bsd_uthread_deactivate(void)
void _initialize_bsd_uthread()
void bsd_uthread_set_collect_uthread(struct gdbarch *gdbarch, void(*collect_uthread)(const struct regcache *, int, CORE_ADDR))
static const char * bsd_uthread_solib_name
static void bsd_uthread_check_magic(CORE_ADDR addr)
static CORE_ADDR bsd_uthread_thread_list_addr
static int bsd_uthread_thread_state_offset
#define BSD_UTHREAD_PTHREAD_MAGIC
#define BSD_UTHREAD_PS_DEAD
static const char *const bsd_uthread_solib_names[]
static CORE_ADDR bsd_uthread_thread_run_addr
static int bsd_uthread_thread_next_offset
static int bsd_uthread_lookup_offset(const char *name, struct objfile *objfile)
static CORE_ADDR bsd_uthread_lookup_address(const char *name, struct objfile *objfile)
static int bsd_uthread_active
static const target_info bsd_uthread_target_info
Definition bsd-uthread.c:36
static const registry< gdbarch >::key< struct bsd_uthread_ops > bsd_uthread_data
Definition bsd-uthread.c:83
static struct bsd_uthread_ops * get_bsd_uthread(struct gdbarch *gdbarch)
Definition bsd-uthread.c:86
static CORE_ADDR bsd_uthread_read_memory_address(CORE_ADDR addr)
static int bsd_uthread_thread_ctx_offset
static int bsd_uthread_activate(struct objfile *objfile)
static bsd_uthread_target bsd_uthread_ops
Definition bsd-uthread.c:68
void bsd_uthread_set_supply_uthread(struct gdbarch *gdbarch, void(*supply_uthread)(struct regcache *, int, CORE_ADDR))
Definition bsd-uthread.c:98
int unpush_target(struct target_ops *t)
Definition inferior.c:96
void push_target(struct target_ops *t)
Definition inferior.h:406
thread_info * find_thread(ptid_t ptid)
gdbarch * arch() const
Definition regcache.c:231
ptid_t ptid() const
Definition regcache.h:408
void * get(unsigned key)
Definition registry.h:211
enum thread_state state
Definition gdbthread.h:339
CORE_ADDR read_memory_typed_address(CORE_ADDR addr, struct type *type)
Definition corefile.c:336
ULONGEST read_memory_unsigned_integer(CORE_ADDR memaddr, int len, enum bfd_endian byte_order)
Definition corefile.c:306
static ULONGEST extract_unsigned_integer(gdb::array_view< const gdb_byte > buf, enum bfd_endian byte_order)
Definition defs.h:480
enum bfd_endian gdbarch_byte_order(struct gdbarch *gdbarch)
Definition gdbarch.c:1396
struct thread_info * add_thread(process_stratum_target *targ, ptid_t ptid)
Definition thread.c:336
@ THREAD_EXITED
Definition gdbthread.h:79
void thread_change_ptid(process_stratum_target *targ, ptid_t old_ptid, ptid_t new_ptid)
Definition thread.c:811
void prune_threads(void)
Definition thread.c:737
bool in_thread_list(process_stratum_target *targ, ptid_t ptid)
Definition thread.c:631
const struct builtin_type * builtin_type(struct gdbarch *gdbarch)
Definition gdbtypes.c:6168
mach_port_t mach_port_t name mach_port_t mach_port_t name kern_return_t int int rusage_t pid_t pid
Definition gnu-nat.c:1791
mach_port_t mach_port_t name mach_port_t mach_port_t name kern_return_t int status
Definition gnu-nat.c:1790
ptid_t inferior_ptid
Definition infcmd.c:74
struct inferior * current_inferior(void)
Definition inferior.c:55
struct bound_minimal_symbol lookup_minimal_symbol(const char *name, const char *sfile, struct objfile *objf)
Definition minsyms.c:363
observable< struct so_list * > solib_loaded
observable< inferior * > inferior_created
observable< struct program_space *, struct so_list * > solib_unloaded
static process_stratum_target * as_process_stratum_target(target_ops *target)
bool solib_read_symbols(struct so_list *so, symfile_add_flags flags)
Definition solib.c:686
CORE_ADDR value_address() const
Definition minsyms.h:41
struct minimal_symbol * minsym
Definition minsyms.h:49
void(* collect_uthread)(const struct regcache *, int, CORE_ADDR)
Definition bsd-uthread.c:79
void(* supply_uthread)(struct regcache *, int, CORE_ADDR)
Definition bsd-uthread.c:76
void update_thread_list() override
ptid_t wait(ptid_t, struct target_waitstatus *, target_wait_flags) override
void store_registers(struct regcache *, int) override
bool thread_alive(ptid_t ptid) override
void fetch_registers(struct regcache *, int) override
void resume(ptid_t, int, enum gdb_signal) override
const char * extra_thread_info(struct thread_info *) override
const target_info & info() const override
Definition bsd-uthread.c:44
std::string pid_to_str(ptid_t) override
void close() override
void mourn_inferior() override
strata stratum() const override
Definition bsd-uthread.c:47
struct type * builtin_data_ptr
Definition gdbtypes.h:2135
Definition gnu-nat.c:153
char so_original_name[SO_NAME_MAX_PATH_SIZE]
Definition solist.h:53
struct objfile * objfile
Definition solist.h:70
virtual ptid_t wait(ptid_t, struct target_waitstatus *, target_wait_flags options) TARGET_DEFAULT_FUNC(default_target_wait)
virtual void fetch_registers(struct regcache *, int) TARGET_DEFAULT_IGNORE()
target_ops * beneath() const
Definition target.c:3041
virtual void store_registers(struct regcache *, int) TARGET_DEFAULT_NORETURN(noprocess())
virtual void resume(ptid_t, int TARGET_DEBUG_PRINTER(target_debug_print_step), enum gdb_signal) TARGET_DEFAULT_NORETURN(noprocess())
virtual void mourn_inferior() TARGET_DEFAULT_FUNC(default_mourn_inferior)
virtual bool thread_alive(ptid_t ptid) TARGET_DEFAULT_RETURN(false)
std::string normal_pid_to_str(ptid_t ptid)
Definition target.c:3693
int target_read_memory(CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len)
Definition target.c:1785
strata
Definition target.h:94
@ thread_stratum
Definition target.h:98
@ TARGET_WAITKIND_SIGNALLED
Definition waitstatus.h:40
@ TARGET_WAITKIND_EXITED
Definition waitstatus.h:32