$OpenBSD: patch-gdb_aarch64obsd-nat_c,v 1.2 2019/10/17 17:10:26 kurt Exp $
Index: gdb/aarch64obsd-nat.c
--- gdb/aarch64obsd-nat.c.orig
+++ gdb/aarch64obsd-nat.c
@@ -0,0 +1,206 @@
+/* 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"
+#include "obsd-nat.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 = get_ptrace_pid (inferior_ptid);
+
+  ret = ptrace(PT_GETREGS, pid, (caddr_t)&regs, 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, &regs.r_reg[regno]);
+  regcache_raw_supply (regcache, AARCH64_LR_REGNUM, &regs.r_lr);
+  regcache_raw_supply (regcache, AARCH64_SP_REGNUM, &regs.r_sp);
+  regcache_raw_supply (regcache, AARCH64_PC_REGNUM, &regs.r_pc);
+  regcache_raw_supply (regcache, AARCH64_CPSR_REGNUM, &regs.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 = get_ptrace_pid (inferior_ptid);
+
+  // fetch old values as only 'valid' entries will be replaced.
+  ret = ptrace(PT_GETREGS, pid, (caddr_t)&regs, 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, &regs.r_reg[regno]);
+  if (REG_VALID == regcache_register_status (regcache, AARCH64_LR_REGNUM))
+    regcache_raw_collect (regcache, AARCH64_LR_REGNUM, &regs.r_lr);
+  if (REG_VALID == regcache_register_status (regcache, AARCH64_SP_REGNUM))
+    regcache_raw_collect (regcache, AARCH64_SP_REGNUM, &regs.r_sp);
+  if (REG_VALID == regcache_register_status (regcache, AARCH64_PC_REGNUM))
+    regcache_raw_collect (regcache, AARCH64_PC_REGNUM, &regs.r_pc);
+  if (REG_VALID == regcache_register_status (regcache, AARCH64_CPSR_REGNUM))
+    regcache_raw_collect (regcache, AARCH64_CPSR_REGNUM, &regs.r_spsr);
+
+  ret = ptrace(PT_SETREGS, pid, (caddr_t)&regs, 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 = get_ptrace_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 = get_ptrace_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.  */
+  obsd_add_target (t);
+}
