helpful analyzing coredumps and inspecting running processes. From a diff provided by drahn@. ok jca@, phessler@
211 lines
6.5 KiB
Plaintext
211 lines
6.5 KiB
Plaintext
$OpenBSD: patch-gdb_aarch64obsd-nat_c,v 1.1 2018/07/10 11:03:46 kettenis Exp $
|
||
Index: gdb/aarch64obsd-nat.c
|
||
--- gdb/aarch64obsd-nat.c.orig
|
||
+++ gdb/aarch64obsd-nat.c
|
||
@@ -0,0 +1,205 @@
|
||
+/* Native-dependent code for OpenBSD/arm64 (AArch64)
|
||
+
|
||
+ Copyright (C) 2011-2017 Free Software Foundation, Inc.
|
||
+
|
||
+ This file is part of GDB.
|
||
+
|
||
+ This program is free software; you can redistribute it and/or modify
|
||
+ it under the terms of the GNU General Public License as published by
|
||
+ the Free Software Foundation; either version 3 of the License, or
|
||
+ (at your option) any later version.
|
||
+
|
||
+ This program is distributed in the hope that it will be useful,
|
||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
+ GNU General Public License for more details.
|
||
+
|
||
+ You should have received a copy of the GNU General Public License
|
||
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include "defs.h"
|
||
+#include "gdbcore.h"
|
||
+#include "inferior.h"
|
||
+#include "regcache.h"
|
||
+#include <sys/types.h>
|
||
+#include <sys/ptrace.h>
|
||
+#include <machine/reg.h>
|
||
+
|
||
+#include "aarch64-tdep.h"
|
||
+#include "inf-ptrace.h"
|
||
+
|
||
+/* Fill GDB's register array with the general-purpose register values
|
||
+ from the current thread. */
|
||
+
|
||
+static void
|
||
+fetch_gregs_from_thread (struct regcache *regcache)
|
||
+{
|
||
+ struct reg regs;
|
||
+ pid_t pid;
|
||
+ int regno;
|
||
+ int ret;
|
||
+
|
||
+ pid = ptid_get_pid (inferior_ptid);
|
||
+
|
||
+ ret = ptrace(PT_GETREGS, pid, (caddr_t)®s, 0);
|
||
+ if (ret < 0)
|
||
+ perror_with_name (_("Unable to fetch general registers."));
|
||
+
|
||
+ for (regno = AARCH64_X0_REGNUM; regno <= AARCH64_FP_REGNUM; regno++)
|
||
+ regcache_raw_supply (regcache, regno, ®s.r_reg[regno]);
|
||
+ regcache_raw_supply (regcache, AARCH64_LR_REGNUM, ®s.r_lr);
|
||
+ regcache_raw_supply (regcache, AARCH64_SP_REGNUM, ®s.r_sp);
|
||
+ regcache_raw_supply (regcache, AARCH64_PC_REGNUM, ®s.r_pc);
|
||
+ regcache_raw_supply (regcache, AARCH64_CPSR_REGNUM, ®s.r_spsr);
|
||
+}
|
||
+
|
||
+/* Store to the current thread the valid general-purpose register
|
||
+ values in the GDB's register array. */
|
||
+
|
||
+static void
|
||
+store_gregs_to_thread (const struct regcache *regcache)
|
||
+{
|
||
+ struct reg regs;
|
||
+ pid_t pid;
|
||
+ int regno;
|
||
+ int ret;
|
||
+
|
||
+ pid = ptid_get_pid (inferior_ptid);
|
||
+
|
||
+ // fetch old values as only 'valid' entries will be replaced.
|
||
+ ret = ptrace(PT_GETREGS, pid, (caddr_t)®s, 0);
|
||
+ if (ret < 0) {
|
||
+ perror_with_name (_("Unable to store general registers."));
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ for (regno = AARCH64_X0_REGNUM; regno <= AARCH64_FP_REGNUM; regno++)
|
||
+ if (REG_VALID == regcache_register_status (regcache, regno))
|
||
+ regcache_raw_collect (regcache, regno, ®s.r_reg[regno]);
|
||
+ if (REG_VALID == regcache_register_status (regcache, AARCH64_LR_REGNUM))
|
||
+ regcache_raw_collect (regcache, AARCH64_LR_REGNUM, ®s.r_lr);
|
||
+ if (REG_VALID == regcache_register_status (regcache, AARCH64_SP_REGNUM))
|
||
+ regcache_raw_collect (regcache, AARCH64_SP_REGNUM, ®s.r_sp);
|
||
+ if (REG_VALID == regcache_register_status (regcache, AARCH64_PC_REGNUM))
|
||
+ regcache_raw_collect (regcache, AARCH64_PC_REGNUM, ®s.r_pc);
|
||
+ if (REG_VALID == regcache_register_status (regcache, AARCH64_CPSR_REGNUM))
|
||
+ regcache_raw_collect (regcache, AARCH64_CPSR_REGNUM, ®s.r_spsr);
|
||
+
|
||
+ ret = ptrace(PT_SETREGS, pid, (caddr_t)®s, 0);
|
||
+ if (ret < 0)
|
||
+ perror_with_name (_("Unable to store general registers."));
|
||
+}
|
||
+
|
||
+/* Fill GDB's register array with the fp/simd register values
|
||
+ from the current thread. */
|
||
+
|
||
+static void
|
||
+fetch_fpregs_from_thread (struct regcache *regcache)
|
||
+{
|
||
+ int ret;
|
||
+ pid_t pid;
|
||
+ int regno;
|
||
+ struct fpreg fpregs;
|
||
+
|
||
+ pid = ptid_get_pid (inferior_ptid);
|
||
+
|
||
+ ret = ptrace(PT_GETFPREGS, pid, (caddr_t)&fpregs, 0);
|
||
+ if (ret < 0) {
|
||
+ perror_with_name (_("Unable to fetch general registers."));
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ for (regno = AARCH64_V0_REGNUM; regno <= AARCH64_V31_REGNUM; regno++)
|
||
+ regcache_raw_supply (regcache, regno, &fpregs.fp_reg[regno]);
|
||
+
|
||
+ regcache_raw_supply (regcache, AARCH64_FPSR_REGNUM, &fpregs.fp_sr);
|
||
+ regcache_raw_supply (regcache, AARCH64_FPCR_REGNUM, &fpregs.fp_cr);
|
||
+}
|
||
+
|
||
+/* Store to the current thread the valid fp/simd register
|
||
+ values in the GDB's register array. */
|
||
+
|
||
+static void
|
||
+store_fpregs_to_thread (const struct regcache *regcache)
|
||
+{
|
||
+ int ret;
|
||
+ pid_t pid;
|
||
+ int regno;
|
||
+ struct fpreg fpregs;
|
||
+
|
||
+ pid = ptid_get_pid (inferior_ptid);
|
||
+
|
||
+ ret = ptrace(PT_GETFPREGS, pid, (caddr_t)&fpregs, 0);
|
||
+ if (ret < 0) {
|
||
+ perror_with_name (_("Unable to store general registers."));
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ for (regno = AARCH64_V0_REGNUM; regno <= AARCH64_V31_REGNUM; regno++)
|
||
+ if (REG_VALID == regcache_register_status (regcache, regno))
|
||
+ regcache_raw_collect (regcache, regno, &fpregs.fp_reg[regno]);
|
||
+
|
||
+ if (REG_VALID == regcache_register_status (regcache, AARCH64_FPSR_REGNUM))
|
||
+ regcache_raw_collect (regcache, AARCH64_FPSR_REGNUM, &fpregs.fp_sr);
|
||
+ if (REG_VALID == regcache_register_status (regcache, AARCH64_FPCR_REGNUM))
|
||
+ regcache_raw_collect (regcache, AARCH64_FPCR_REGNUM, &fpregs.fp_cr);
|
||
+
|
||
+ ret = ptrace(PT_SETFPREGS, pid, (caddr_t)&fpregs, 0);
|
||
+ if (ret < 0)
|
||
+ perror_with_name (_("Unable to store general registers."));
|
||
+}
|
||
+
|
||
+/* Implement the "to_fetch_register" target_ops method. */
|
||
+
|
||
+static void
|
||
+aarch64_obsd_fetch_inferior_registers (struct target_ops *ops,
|
||
+ struct regcache *regcache,
|
||
+ int regno)
|
||
+{
|
||
+ if (regno == -1)
|
||
+ {
|
||
+ fetch_gregs_from_thread (regcache);
|
||
+ fetch_fpregs_from_thread (regcache);
|
||
+ }
|
||
+ else if (regno < AARCH64_V0_REGNUM)
|
||
+ fetch_gregs_from_thread (regcache);
|
||
+ else
|
||
+ fetch_fpregs_from_thread (regcache);
|
||
+}
|
||
+
|
||
+/* Implement the "to_store_register" target_ops method. */
|
||
+
|
||
+static void
|
||
+aarch64_obsd_store_inferior_registers (struct target_ops *ops,
|
||
+ struct regcache *regcache,
|
||
+ int regno)
|
||
+{
|
||
+ if (regno == -1)
|
||
+ {
|
||
+ store_gregs_to_thread (regcache);
|
||
+ store_fpregs_to_thread (regcache);
|
||
+ }
|
||
+ else if (regno < AARCH64_V0_REGNUM)
|
||
+ store_gregs_to_thread (regcache);
|
||
+ else
|
||
+ store_fpregs_to_thread (regcache);
|
||
+}
|
||
+
|
||
+
|
||
+/* -Wmissing-prototypes. */
|
||
+void _initialize_aarch64_obsd_nat (void);
|
||
+
|
||
+void
|
||
+_initialize_aarch64_obsd_nat (void)
|
||
+{
|
||
+ struct target_ops *t;
|
||
+
|
||
+ t = inf_ptrace_target ();
|
||
+
|
||
+ /* Add our register access methods. */
|
||
+ t->to_fetch_registers = aarch64_obsd_fetch_inferior_registers;
|
||
+ t->to_store_registers = aarch64_obsd_store_inferior_registers;
|
||
+
|
||
+ /* Register the target. */
|
||
+ add_target (t);
|
||
+}
|