X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Faarch64-linux-nat.c;h=77d5863a56aa2bd78779827fe58a1d4ba28fb577;hb=refs%2Fheads%2Fconcurrent-displaced-stepping-2020-04-01;hp=6d43eb7070f17768f324fe950bc7a0f278d190d8;hpb=4de283e4b5f21207fe12f99913d1f28d4f07843c;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c index 6d43eb7070..77d5863a56 100644 --- a/gdb/aarch64-linux-nat.c +++ b/gdb/aarch64-linux-nat.c @@ -1,6 +1,6 @@ /* Native-dependent code for GNU/Linux AArch64. - Copyright (C) 2011-2019 Free Software Foundation, Inc. + Copyright (C) 2011-2020 Free Software Foundation, Inc. Contributed by ARM Ltd. This file is part of GDB. @@ -30,6 +30,8 @@ #include "aarch64-tdep.h" #include "aarch64-linux-tdep.h" #include "aarch32-linux-nat.h" +#include "aarch32-tdep.h" +#include "arch/arm.h" #include "nat/aarch64-linux.h" #include "nat/aarch64-linux-hw-point.h" #include "nat/aarch64-sve-linux-ptrace.h" @@ -46,6 +48,7 @@ /* Defines ps_err_e, struct ps_prochandle. */ #include "gdb_proc_service.h" +#include "arch-utils.h" #ifndef TRAP_HWBKPT #define TRAP_HWBKPT 0x0004 @@ -95,6 +98,8 @@ public: /* Add our siginfo layout converter. */ bool low_siginfo_fixup (siginfo_t *ptrace, gdb_byte *inf, int direction) override; + + struct gdbarch *thread_architecture (ptid_t) override; }; static aarch64_linux_nat_target the_aarch64_linux_nat_target; @@ -291,7 +296,7 @@ fetch_fpregs_from_thread (struct regcache *regcache) /* Make sure REGS can hold all VFP registers contents on both aarch64 and arm. */ - gdb_static_assert (sizeof regs >= VFP_REGS_SIZE); + gdb_static_assert (sizeof regs >= ARM_VFP3_REGS_SIZE); tid = regcache->ptid ().lwp (); @@ -299,7 +304,7 @@ fetch_fpregs_from_thread (struct regcache *regcache) if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 32) { - iovec.iov_len = VFP_REGS_SIZE; + iovec.iov_len = ARM_VFP3_REGS_SIZE; ret = ptrace (PTRACE_GETREGSET, tid, NT_ARM_VFP, &iovec); if (ret < 0) @@ -338,14 +343,14 @@ store_fpregs_to_thread (const struct regcache *regcache) /* Make sure REGS can hold all VFP registers contents on both aarch64 and arm. */ - gdb_static_assert (sizeof regs >= VFP_REGS_SIZE); + gdb_static_assert (sizeof regs >= ARM_VFP3_REGS_SIZE); tid = regcache->ptid ().lwp (); iovec.iov_base = ®s; if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 32) { - iovec.iov_len = VFP_REGS_SIZE; + iovec.iov_len = ARM_VFP3_REGS_SIZE; ret = ptrace (PTRACE_GETREGSET, tid, NT_ARM_VFP, &iovec); if (ret < 0) @@ -409,6 +414,11 @@ store_sveregs_to_thread (struct regcache *regcache) struct iovec iovec; int tid = regcache->ptid ().lwp (); + /* First store vector length to the thread. This is done first to ensure the + ptrace buffers read from the kernel are the correct size. */ + if (!aarch64_sve_set_vq (tid, regcache)) + perror_with_name (_("Unable to set VG register.")); + /* Obtain a dump of SVE registers from ptrace. */ std::unique_ptr base = aarch64_sve_get_sveregs (tid); @@ -622,25 +632,23 @@ aarch64_linux_nat_target::post_attach (int pid) linux_nat_target::post_attach (pid); } -extern struct target_desc *tdesc_arm_with_neon; - /* Implement the "read_description" target_ops method. */ const struct target_desc * aarch64_linux_nat_target::read_description () { int ret, tid; - gdb_byte regbuf[VFP_REGS_SIZE]; + gdb_byte regbuf[ARM_VFP3_REGS_SIZE]; struct iovec iovec; tid = inferior_ptid.lwp (); iovec.iov_base = regbuf; - iovec.iov_len = VFP_REGS_SIZE; + iovec.iov_len = ARM_VFP3_REGS_SIZE; ret = ptrace (PTRACE_GETREGSET, tid, NT_ARM_VFP, &iovec); if (ret == 0) - return tdesc_arm_with_neon; + return aarch32_read_description (); CORE_ADDR hwcap = linux_get_hwcap (this); @@ -939,6 +947,34 @@ aarch64_linux_nat_target::can_do_single_step () return 1; } +/* Implement the "thread_architecture" target_ops method. */ + +struct gdbarch * +aarch64_linux_nat_target::thread_architecture (ptid_t ptid) +{ + /* Return the gdbarch for the current thread. If the vector length has + changed since the last time this was called, then do a further lookup. */ + + uint64_t vq = aarch64_sve_get_vq (ptid.lwp ()); + + /* Find the current gdbarch the same way as process_stratum_target. Only + return it if the current vector length matches the one in the tdep. */ + inferior *inf = find_inferior_ptid (this, ptid); + gdb_assert (inf != NULL); + if (vq == gdbarch_tdep (inf->gdbarch)->vq) + return inf->gdbarch; + + /* We reach here if the vector length for the thread is different from its + value at process start. Lookup gdbarch via info (potentially creating a + new one), stashing the vector length inside id. Use -1 for when SVE + unavailable, to distinguish from an unset value of 0. */ + struct gdbarch_info info; + gdbarch_info_init (&info); + info.bfd_arch_info = bfd_lookup_arch (bfd_arch_aarch64, bfd_mach_aarch64); + info.id = (int *) (vq == 0 ? -1 : vq); + return gdbarch_find_by_info (info); +} + /* Define AArch64 maintenance commands. */ static void @@ -960,8 +996,9 @@ triggers a breakpoint or watchpoint."), &maintenance_show_cmdlist); } +void _initialize_aarch64_linux_nat (); void -_initialize_aarch64_linux_nat (void) +_initialize_aarch64_linux_nat () { add_show_debug_regs_command ();