aboutsummaryrefslogtreecommitdiff
path: root/gdb/aarch64-linux-tdep.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/aarch64-linux-tdep.c')
-rw-r--r--gdb/aarch64-linux-tdep.c103
1 files changed, 83 insertions, 20 deletions
diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
index 2d156ad..dd35eaf 100644
--- a/gdb/aarch64-linux-tdep.c
+++ b/gdb/aarch64-linux-tdep.c
@@ -1,6 +1,6 @@
/* Target-dependent code for GNU/Linux AArch64.
- Copyright (C) 2009-2024 Free Software Foundation, Inc.
+ Copyright (C) 2009-2025 Free Software Foundation, Inc.
Contributed by ARM Ltd.
This file is part of GDB.
@@ -23,7 +23,9 @@
#include "extract-store-integer.h"
#include "gdbarch.h"
#include "glibc-tdep.h"
+#include "solib-svr4-linux.h"
#include "linux-tdep.h"
+#include "svr4-tls-tdep.h"
#include "aarch64-tdep.h"
#include "aarch64-linux-tdep.h"
#include "osabi.h"
@@ -35,6 +37,7 @@
#include "target/target.h"
#include "expop.h"
#include "auxv.h"
+#include "inferior.h"
#include "regcache.h"
#include "regset.h"
@@ -2038,11 +2041,17 @@ enum aarch64_syscall {
static enum gdb_syscall
aarch64_canonicalize_syscall (enum aarch64_syscall syscall_number)
{
-#define SYSCALL_MAP(SYSCALL) case aarch64_sys_##SYSCALL: \
- return gdb_sys_##SYSCALL
+#define SYSCALL_MAP(SYSCALL) \
+ case aarch64_sys_ ## SYSCALL: \
+ return gdb_sys_ ## SYSCALL
-#define UNSUPPORTED_SYSCALL_MAP(SYSCALL) case aarch64_sys_##SYSCALL: \
- return gdb_sys_no_syscall
+#define SYSCALL_MAP_RENAME(SYSCALL, GDB_SYSCALL) \
+ case aarch64_sys_ ## SYSCALL: \
+ return GDB_SYSCALL;
+
+#define UNSUPPORTED_SYSCALL_MAP(SYSCALL) \
+ case aarch64_sys_ ## SYSCALL: \
+ return gdb_sys_no_syscall
switch (syscall_number)
{
@@ -2269,8 +2278,7 @@ aarch64_canonicalize_syscall (enum aarch64_syscall syscall_number)
SYSCALL_MAP (clone);
SYSCALL_MAP (execve);
- case aarch64_sys_mmap:
- return gdb_sys_mmap2;
+ SYSCALL_MAP_RENAME (mmap, gdb_sys_old_mmap);
SYSCALL_MAP (fadvise64);
SYSCALL_MAP (swapon);
@@ -2291,7 +2299,7 @@ aarch64_canonicalize_syscall (enum aarch64_syscall syscall_number)
SYSCALL_MAP (move_pages);
UNSUPPORTED_SYSCALL_MAP (rt_tgsigqueueinfo);
UNSUPPORTED_SYSCALL_MAP (perf_event_open);
- UNSUPPORTED_SYSCALL_MAP (accept4);
+ SYSCALL_MAP (accept4);
UNSUPPORTED_SYSCALL_MAP (recvmmsg);
SYSCALL_MAP (wait4);
@@ -2312,9 +2320,14 @@ aarch64_canonicalize_syscall (enum aarch64_syscall syscall_number)
UNSUPPORTED_SYSCALL_MAP (sched_setattr);
UNSUPPORTED_SYSCALL_MAP (sched_getattr);
SYSCALL_MAP (getrandom);
- default:
- return gdb_sys_no_syscall;
- }
+
+ default:
+ return gdb_sys_no_syscall;
+ }
+
+#undef SYSCALL_MAP
+#undef SYSCALL_MAP_RENAME
+#undef UNSUPPORTED_SYSCALL_MAP
}
/* Retrieve the syscall number at a ptrace syscall-stop, either on syscall entry
@@ -2587,8 +2600,8 @@ aarch64_linux_fill_memtag_section (struct gdbarch *gdbarch, asection *osec)
static_cast<int> (memtag_type::allocation)))
{
warning (_("Failed to read MTE tags from memory range [%s,%s)."),
- phex_nz (start_address, sizeof (start_address)),
- phex_nz (end_address, sizeof (end_address)));
+ phex_nz (start_address),
+ phex_nz (end_address));
return false;
}
@@ -2691,6 +2704,57 @@ aarch64_use_target_description_from_corefile_notes (gdbarch *gdbarch,
return true;
}
+/* Fetch and return the TLS DTV (dynamic thread vector) address for PTID.
+ Throw a suitable TLS error if something goes wrong. */
+
+static CORE_ADDR
+aarch64_linux_get_tls_dtv_addr (struct gdbarch *gdbarch, ptid_t ptid,
+ svr4_tls_libc libc)
+{
+ /* On aarch64, the thread pointer is found in the TPIDR register.
+ Note that this is the first register in the TLS feature - see
+ features/aarch64-tls.c - and it will always be present. */
+ regcache *regcache
+ = get_thread_arch_regcache (current_inferior (), ptid, gdbarch);
+ aarch64_gdbarch_tdep *tdep = gdbarch_tdep<aarch64_gdbarch_tdep> (gdbarch);
+ target_fetch_registers (regcache, tdep->tls_regnum_base);
+ ULONGEST thr_ptr;
+ if (regcache->cooked_read (tdep->tls_regnum_base, &thr_ptr) != REG_VALID)
+ throw_error (TLS_GENERIC_ERROR, _("Unable to fetch thread pointer"));
+
+ CORE_ADDR dtv_ptr_addr;
+ switch (libc)
+ {
+ case svr4_tls_libc_musl:
+ /* MUSL: The DTV pointer is found at the very end of the pthread
+ struct which is located *before* the thread pointer. I.e.
+ the thread pointer will be just beyond the end of the struct,
+ so the address of the DTV pointer is found one pointer-size
+ before the thread pointer. */
+ dtv_ptr_addr = thr_ptr - (gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT);
+ break;
+ case svr4_tls_libc_glibc:
+ /* GLIBC: The thread pointer (tpidr) points at the TCB (thread control
+ block). On aarch64, this struct (tcbhead_t) is defined to
+ contain two pointers. The first is a pointer to the DTV and
+ the second is a pointer to private data. So the DTV pointer
+ address is the same as the thread pointer. */
+ dtv_ptr_addr = thr_ptr;
+ break;
+ default:
+ throw_error (TLS_GENERIC_ERROR, _("Unknown aarch64 C library"));
+ break;
+ }
+ 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
aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
@@ -2705,13 +2769,14 @@ aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
tdep->lowest_pc = 0x8000;
linux_init_abi (info, gdbarch, 1);
-
- set_solib_svr4_fetch_link_map_offsets (gdbarch,
- linux_lp64_fetch_link_map_offsets);
+ set_solib_svr4_ops (gdbarch, make_linux_lp64_svr4_solib_ops);
/* 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, aarch64_linux_get_tls_dtv_addr);
/* Shared library handling. */
set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
@@ -2972,12 +3037,10 @@ aarch64_linux_ltag_tests (void)
}
}
-} // namespace selftests
+} /* namespace selftests */
#endif /* GDB_SELF_TEST */
-void _initialize_aarch64_linux_tdep ();
-void
-_initialize_aarch64_linux_tdep ()
+INIT_GDB_FILE (aarch64_linux_tdep)
{
gdbarch_register_osabi (bfd_arch_aarch64, 0, GDB_OSABI_LINUX,
aarch64_linux_init_abi);