Internal TLS support for aarch64, x86_64, riscv, ppc64, and s390x

For each architecture, aarch64, x86_64, riscv, ppc64, and s390x,
this commit defines a suitable 'get_tls_dtv_addr' method and,
when necessary, a 'get_tls_dtp_offset' method.

It also registers svr4_tls_get_thread_local_address, defined in
svr4-tls-tdep.c (in an earlier commit), as the
get_thread_local_address gdbarch method.  It also registers its
architecture specific code using svr4_tls_register_tls_methods().

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=24548
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31563

Tested-By: Luis Machado <luis.machado@arm.com>
Approved-By: Luis Machado <luis.machado@arm.com>
This commit is contained in:
Kevin Buettner
2025-04-23 21:39:29 -07:00
parent 85e1d8f93d
commit c34309bea2
6 changed files with 286 additions and 5 deletions

View File

@@ -33,7 +33,9 @@
#include "amd64-linux-tdep.h"
#include "i386-linux-tdep.h"
#include "linux-tdep.h"
#include "svr4-tls-tdep.h"
#include "gdbsupport/x86-xstate.h"
#include "inferior.h"
#include "amd64-tdep.h"
#include "solib-svr4.h"
@@ -1832,6 +1834,39 @@ amd64_linux_remove_non_address_bits_watchpoint (gdbarch *gdbarch,
return (addr & amd64_linux_lam_untag_mask ());
}
/* Fetch and return the TLS DTV (dynamic thread vector) address for PTID.
Throw a suitable TLS error if something goes wrong. */
static CORE_ADDR
amd64_linux_get_tls_dtv_addr (struct gdbarch *gdbarch, ptid_t ptid,
enum svr4_tls_libc libc)
{
/* On x86-64, the thread pointer is found in the fsbase register. */
regcache *regcache
= get_thread_arch_regcache (current_inferior (), ptid, gdbarch);
target_fetch_registers (regcache, AMD64_FSBASE_REGNUM);
ULONGEST fsbase;
if (regcache->cooked_read (AMD64_FSBASE_REGNUM, &fsbase) != REG_VALID)
throw_error (TLS_GENERIC_ERROR, _("Unable to fetch thread pointer"));
/* The thread pointer (fsbase) points at the TCB (thread control
block). The first two members of this struct are both pointers,
where the first will be a pointer to the TCB (i.e. it points at
itself) and the second will be a pointer to the DTV (dynamic
thread vector). There are many other fields too, but the one
we care about here is the DTV pointer. Compute the address
of the DTV pointer, fetch it, and convert it to an address. */
CORE_ADDR dtv_ptr_addr = fsbase + gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT;
gdb::byte_vector buf (gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT);
if (target_read_memory (dtv_ptr_addr, buf.data (), buf.size ()) != 0)
throw_error (TLS_GENERIC_ERROR, _("Unable to fetch DTV address"));
const struct builtin_type *builtin = builtin_type (gdbarch);
CORE_ADDR dtv_addr = gdbarch_pointer_to_address
(gdbarch, builtin->builtin_data_ptr, buf.data ());
return dtv_addr;
}
static void
amd64_linux_init_abi_common(struct gdbarch_info info, struct gdbarch *gdbarch,
int num_disp_step_buffers)
@@ -1862,6 +1897,9 @@ amd64_linux_init_abi_common(struct gdbarch_info info, struct gdbarch *gdbarch,
/* Enable TLS support. */
set_gdbarch_fetch_tls_load_module_address (gdbarch,
svr4_fetch_objfile_link_map);
set_gdbarch_get_thread_local_address (gdbarch,
svr4_tls_get_thread_local_address);
svr4_tls_register_tls_methods (info, gdbarch, amd64_linux_get_tls_dtv_addr);
/* GNU/Linux uses SVR4-style shared libraries. */
set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);