Index: lldb/source/Plugins/Process/OpenBSD/NativeRegisterContextOpenBSD_arm64.cpp
--- lldb/source/Plugins/Process/OpenBSD/NativeRegisterContextOpenBSD_arm64.cpp.orig
+++ lldb/source/Plugins/Process/OpenBSD/NativeRegisterContextOpenBSD_arm64.cpp
@@ -0,0 +1,561 @@
+//===-- NativeRegisterContextOpenBSD_arm64.cpp ---------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(__arm64__) || defined(__aarch64__)
+
+#include <elf.h>
+#include <err.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "NativeRegisterContextOpenBSD_arm64.h"
+
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/Status.h"
+#include "llvm/ADT/APInt.h"
+
+#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
+#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
+
+// clang-format off
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+#include <machine/cpu.h>
+// clang-format on
+
+using namespace lldb_private;
+using namespace lldb_private::process_openbsd;
+
+#define REG_CONTEXT_SIZE (GetGPRSize() + GetFPRSize())
+
+// ARM64 general purpose registers.
+static const uint32_t g_gpr_regnums_arm64[] = {
+    gpr_x0_arm64,       gpr_x1_arm64,   gpr_x2_arm64,  gpr_x3_arm64,
+    gpr_x4_arm64,       gpr_x5_arm64,   gpr_x6_arm64,  gpr_x7_arm64,
+    gpr_x8_arm64,       gpr_x9_arm64,   gpr_x10_arm64, gpr_x11_arm64,
+    gpr_x12_arm64,      gpr_x13_arm64,  gpr_x14_arm64, gpr_x15_arm64,
+    gpr_x16_arm64,      gpr_x17_arm64,  gpr_x18_arm64, gpr_x19_arm64,
+    gpr_x20_arm64,      gpr_x21_arm64,  gpr_x22_arm64, gpr_x23_arm64,
+    gpr_x24_arm64,      gpr_x25_arm64,  gpr_x26_arm64, gpr_x27_arm64,
+    gpr_x28_arm64,      gpr_fp_arm64,   gpr_lr_arm64,  gpr_sp_arm64,
+    gpr_pc_arm64,       gpr_cpsr_arm64, gpr_w0_arm64,  gpr_w1_arm64,
+    gpr_w2_arm64,       gpr_w3_arm64,   gpr_w4_arm64,  gpr_w5_arm64,
+    gpr_w6_arm64,       gpr_w7_arm64,   gpr_w8_arm64,  gpr_w9_arm64,
+    gpr_w10_arm64,      gpr_w11_arm64,  gpr_w12_arm64, gpr_w13_arm64,
+    gpr_w14_arm64,      gpr_w15_arm64,  gpr_w16_arm64, gpr_w17_arm64,
+    gpr_w18_arm64,      gpr_w19_arm64,  gpr_w20_arm64, gpr_w21_arm64,
+    gpr_w22_arm64,      gpr_w23_arm64,  gpr_w24_arm64, gpr_w25_arm64,
+    gpr_w26_arm64,      gpr_w27_arm64,  gpr_w28_arm64,
+    LLDB_INVALID_REGNUM // register sets need to end with this flag
+};
+static_assert(((sizeof g_gpr_regnums_arm64 / sizeof g_gpr_regnums_arm64[0]) -
+               1) == k_num_gpr_registers_arm64,
+              "g_gpr_regnums_arm64 has wrong number of register infos");
+
+// ARM64 floating point registers.
+static const uint32_t g_fpu_regnums_arm64[] = {
+    fpu_v0_arm64,       fpu_v1_arm64,   fpu_v2_arm64,  fpu_v3_arm64,
+    fpu_v4_arm64,       fpu_v5_arm64,   fpu_v6_arm64,  fpu_v7_arm64,
+    fpu_v8_arm64,       fpu_v9_arm64,   fpu_v10_arm64, fpu_v11_arm64,
+    fpu_v12_arm64,      fpu_v13_arm64,  fpu_v14_arm64, fpu_v15_arm64,
+    fpu_v16_arm64,      fpu_v17_arm64,  fpu_v18_arm64, fpu_v19_arm64,
+    fpu_v20_arm64,      fpu_v21_arm64,  fpu_v22_arm64, fpu_v23_arm64,
+    fpu_v24_arm64,      fpu_v25_arm64,  fpu_v26_arm64, fpu_v27_arm64,
+    fpu_v28_arm64,      fpu_v29_arm64,  fpu_v30_arm64, fpu_v31_arm64,
+
+    fpu_s0_arm64,       fpu_s1_arm64,   fpu_s2_arm64,  fpu_s3_arm64,
+    fpu_s4_arm64,       fpu_s5_arm64,   fpu_s6_arm64,  fpu_s7_arm64,
+    fpu_s8_arm64,       fpu_s9_arm64,   fpu_s10_arm64, fpu_s11_arm64,
+    fpu_s12_arm64,      fpu_s13_arm64,  fpu_s14_arm64, fpu_s15_arm64,
+    fpu_s16_arm64,      fpu_s17_arm64,  fpu_s18_arm64, fpu_s19_arm64,
+    fpu_s20_arm64,      fpu_s21_arm64,  fpu_s22_arm64, fpu_s23_arm64,
+    fpu_s24_arm64,      fpu_s25_arm64,  fpu_s26_arm64, fpu_s27_arm64,
+    fpu_s28_arm64,      fpu_s29_arm64,  fpu_s30_arm64, fpu_s31_arm64,
+
+    fpu_d0_arm64,       fpu_d1_arm64,   fpu_d2_arm64,  fpu_d3_arm64,
+    fpu_d4_arm64,       fpu_d5_arm64,   fpu_d6_arm64,  fpu_d7_arm64,
+    fpu_d8_arm64,       fpu_d9_arm64,   fpu_d10_arm64, fpu_d11_arm64,
+    fpu_d12_arm64,      fpu_d13_arm64,  fpu_d14_arm64, fpu_d15_arm64,
+    fpu_d16_arm64,      fpu_d17_arm64,  fpu_d18_arm64, fpu_d19_arm64,
+    fpu_d20_arm64,      fpu_d21_arm64,  fpu_d22_arm64, fpu_d23_arm64,
+    fpu_d24_arm64,      fpu_d25_arm64,  fpu_d26_arm64, fpu_d27_arm64,
+    fpu_d28_arm64,      fpu_d29_arm64,  fpu_d30_arm64, fpu_d31_arm64,
+    fpu_fpsr_arm64,     fpu_fpcr_arm64,
+    LLDB_INVALID_REGNUM // register sets need to end with this flag
+};
+static_assert(((sizeof g_fpu_regnums_arm64 / sizeof g_fpu_regnums_arm64[0]) -
+               1) == k_num_fpr_registers_arm64,
+              "g_fpu_regnums_arm64 has wrong number of register infos");
+
+namespace {
+// Number of register sets provided by this context.
+enum { k_num_register_sets = 2 };
+}
+
+// Register sets for ARM64.
+static const RegisterSet g_reg_sets_arm64[k_num_register_sets] = {
+    {"General Purpose Registers", "gpr", k_num_gpr_registers_arm64,
+     g_gpr_regnums_arm64},
+    {"Floating Point Registers", "fpu", k_num_fpr_registers_arm64,
+     g_fpu_regnums_arm64}};
+
+std::unique_ptr<NativeRegisterContextOpenBSD>
+NativeRegisterContextOpenBSD::CreateHostNativeRegisterContextOpenBSD(
+    const ArchSpec &target_arch, NativeThreadProtocol &native_thread) {
+  return std::make_unique<NativeRegisterContextOpenBSD_arm64>(target_arch, native_thread);
+}
+
+// ----------------------------------------------------------------------------
+// NativeRegisterContextOpenBSD_arm64 members.
+// ----------------------------------------------------------------------------
+
+static RegisterInfoInterface *
+CreateRegisterInfoInterface(const ArchSpec &target_arch) {
+  assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
+         "Register setting path assumes this is a 64-bit host");
+  return new RegisterInfoPOSIX_arm64(target_arch, 0);
+}
+
+static llvm::APInt uint128ToAPInt(__uint128_t in) {
+  uint64_t *pair = (uint64_t *)&in;
+  llvm::APInt out(128, 2, pair);
+  return out;
+}
+
+static __uint128_t APIntTouint128(llvm::APInt in) {
+  assert(in.getBitWidth() == 128);
+  __uint128_t out = 0;
+  const uint64_t *data = in.getRawData();
+  ::memcpy((uint64_t *)&out, data, sizeof(__uint128_t));
+  return out;
+}
+
+NativeRegisterContextOpenBSD_arm64::NativeRegisterContextOpenBSD_arm64(
+    const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
+    : NativeRegisterContextOpenBSD(native_thread,
+                                  CreateRegisterInfoInterface(target_arch)),
+      m_gpr(), m_fpr() {}
+
+uint32_t NativeRegisterContextOpenBSD_arm64::GetUserRegisterCount() const {
+  uint32_t count = 0;
+  for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index)
+    count += g_reg_sets_arm64[set_index].num_registers;
+  return count;
+}
+
+uint32_t NativeRegisterContextOpenBSD_arm64::GetRegisterSetCount() const {
+  return k_num_register_sets;
+}
+
+const RegisterSet *
+NativeRegisterContextOpenBSD_arm64::GetRegisterSet(uint32_t set_index) const {
+	if (set_index < k_num_register_sets)
+    return &g_reg_sets_arm64[set_index];
+
+  return nullptr;
+}
+
+Status
+NativeRegisterContextOpenBSD_arm64::ReadRegister(const RegisterInfo *reg_info,
+                                                 RegisterValue &reg_value) {
+  Status error;
+  Log *log = GetLog(POSIXLog::Registers);
+
+  if (!reg_info) {
+    error.SetErrorString("reg_info NULL");
+    return error;
+  }
+
+  const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+  if (reg == LLDB_INVALID_REGNUM) {
+    // This is likely an internal register for lldb use only and should not be
+    // directly queried.
+    error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb "
+                                   "register, cannot read directly",
+                                   reg_info->name);
+    return error;
+  }
+
+  int set = GetSetForNativeRegNum(reg);
+  if (set == -1) {
+    // This is likely an internal register for lldb use only and should not be
+    // directly queried.
+    error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set",
+                                   reg_info->name);
+    return error;
+  }
+
+  if (ReadRegisterSet(set) != 0) {
+    // This is likely an internal register for lldb use only and should not be
+    // directly queried.
+    error.SetErrorStringWithFormat(
+        "reading register set for register \"%s\" failed", reg_info->name);
+    return error;
+  }
+
+  switch (reg) {
+  case gpr_x0_arm64:
+  case gpr_x1_arm64:
+  case gpr_x2_arm64:
+  case gpr_x3_arm64:
+  case gpr_x4_arm64:
+  case gpr_x5_arm64:
+  case gpr_x6_arm64:
+  case gpr_x7_arm64:
+  case gpr_x8_arm64:
+  case gpr_x9_arm64:
+  case gpr_x10_arm64:
+  case gpr_x11_arm64:
+  case gpr_x12_arm64:
+  case gpr_x13_arm64:
+  case gpr_x14_arm64:
+  case gpr_x15_arm64:
+  case gpr_x16_arm64:
+  case gpr_x17_arm64:
+  case gpr_x18_arm64:
+  case gpr_x19_arm64:
+  case gpr_x20_arm64:
+  case gpr_x21_arm64:
+  case gpr_x22_arm64:
+  case gpr_x23_arm64:
+  case gpr_x24_arm64:
+  case gpr_x25_arm64:
+  case gpr_x26_arm64:
+  case gpr_x27_arm64:
+  case gpr_x28_arm64:
+    reg_value = (uint64_t)m_gpr.r_reg[reg - gpr_x0_arm64];
+    break;
+  case gpr_fp_arm64:
+    reg_value = (uint64_t)m_gpr.r_reg[29];
+    break;
+  case gpr_lr_arm64:
+    reg_value = (uint64_t)m_gpr.r_lr;
+    break;
+  case gpr_sp_arm64:
+    reg_value = (uint64_t)m_gpr.r_sp;
+    break;
+  case gpr_pc_arm64:
+    reg_value = (uint64_t)m_gpr.r_pc;
+    break;
+  case gpr_cpsr_arm64:
+    reg_value = (uint64_t)m_gpr.r_spsr;
+    break;
+  case fpu_v0_arm64:
+  case fpu_v1_arm64:
+  case fpu_v2_arm64:
+  case fpu_v3_arm64:
+  case fpu_v4_arm64:
+  case fpu_v5_arm64:
+  case fpu_v6_arm64:
+  case fpu_v7_arm64:
+  case fpu_v8_arm64:
+  case fpu_v9_arm64:
+  case fpu_v10_arm64:
+  case fpu_v11_arm64:
+  case fpu_v12_arm64:
+  case fpu_v13_arm64:
+  case fpu_v14_arm64:
+  case fpu_v15_arm64:
+  case fpu_v16_arm64:
+  case fpu_v17_arm64:
+  case fpu_v18_arm64:
+  case fpu_v19_arm64:
+  case fpu_v20_arm64:
+  case fpu_v21_arm64:
+  case fpu_v22_arm64:
+  case fpu_v23_arm64:
+  case fpu_v24_arm64:
+  case fpu_v25_arm64:
+  case fpu_v26_arm64:
+  case fpu_v27_arm64:
+  case fpu_v28_arm64:
+  case fpu_v29_arm64:
+  case fpu_v30_arm64:
+  case fpu_v31_arm64:
+    reg_value = uint128ToAPInt(m_fpr.fp_reg[reg - fpu_v0_arm64]);
+    break;
+  case fpu_fpsr_arm64:
+    reg_value = (uint32_t)m_fpr.fp_sr;
+    break;
+  case fpu_fpcr_arm64:
+    reg_value = (uint32_t)m_fpr.fp_cr;
+    break;
+  default:
+    log->Printf("Requested read to unhandled reg: %u", reg);
+    break;
+  }
+
+  if (reg_value.GetByteSize() > reg_info->byte_size) {
+    reg_value.SetType(*reg_info);
+  }
+
+  return error;
+}
+
+Status NativeRegisterContextOpenBSD_arm64::WriteRegister(
+    const RegisterInfo *reg_info, const RegisterValue &reg_value) {
+
+  Status error;
+  Log *log = GetLog(POSIXLog::Registers);
+
+  if (!reg_info) {
+    error.SetErrorString("reg_info NULL");
+    return error;
+  }
+
+  const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+  if (reg == LLDB_INVALID_REGNUM) {
+    // This is likely an internal register for lldb use only and should not be
+    // directly queried.
+    error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb "
+                                   "register, cannot read directly",
+                                   reg_info->name);
+    return error;
+  }
+
+  int set = GetSetForNativeRegNum(reg);
+  if (set == -1) {
+    // This is likely an internal register for lldb use only and should not be
+    // directly queried.
+    error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set",
+                                   reg_info->name);
+    return error;
+  }
+
+  if (ReadRegisterSet(set) != 0) {
+    // This is likely an internal register for lldb use only and should not be
+    // directly queried.
+    error.SetErrorStringWithFormat(
+        "reading register set for register \"%s\" failed", reg_info->name);
+    return error;
+  }
+
+  switch (reg) {
+  case gpr_x0_arm64:
+  case gpr_x1_arm64:
+  case gpr_x2_arm64:
+  case gpr_x3_arm64:
+  case gpr_x4_arm64:
+  case gpr_x5_arm64:
+  case gpr_x6_arm64:
+  case gpr_x7_arm64:
+  case gpr_x8_arm64:
+  case gpr_x9_arm64:
+  case gpr_x10_arm64:
+  case gpr_x11_arm64:
+  case gpr_x12_arm64:
+  case gpr_x13_arm64:
+  case gpr_x14_arm64:
+  case gpr_x15_arm64:
+  case gpr_x16_arm64:
+  case gpr_x17_arm64:
+  case gpr_x18_arm64:
+  case gpr_x19_arm64:
+  case gpr_x20_arm64:
+  case gpr_x21_arm64:
+  case gpr_x22_arm64:
+  case gpr_x23_arm64:
+  case gpr_x24_arm64:
+  case gpr_x25_arm64:
+  case gpr_x26_arm64:
+  case gpr_x27_arm64:
+  case gpr_x28_arm64:
+    m_gpr.r_reg[reg - gpr_x0_arm64] = reg_value.GetAsUInt64();
+    break;
+  case gpr_fp_arm64:
+    m_gpr.r_reg[29] = reg_value.GetAsUInt64();
+    break;
+  case gpr_lr_arm64:
+    m_gpr.r_lr = reg_value.GetAsUInt64();
+    break;
+  case gpr_sp_arm64:
+    m_gpr.r_sp = reg_value.GetAsUInt64();
+    break;
+  case gpr_pc_arm64:
+    m_gpr.r_pc = reg_value.GetAsUInt64();
+    break;
+  case gpr_cpsr_arm64:
+    m_gpr.r_spsr = reg_value.GetAsUInt64();
+    break;
+  case fpu_v0_arm64:
+  case fpu_v1_arm64:
+  case fpu_v2_arm64:
+  case fpu_v3_arm64:
+  case fpu_v4_arm64:
+  case fpu_v5_arm64:
+  case fpu_v6_arm64:
+  case fpu_v7_arm64:
+  case fpu_v8_arm64:
+  case fpu_v9_arm64:
+  case fpu_v10_arm64:
+  case fpu_v11_arm64:
+  case fpu_v12_arm64:
+  case fpu_v13_arm64:
+  case fpu_v14_arm64:
+  case fpu_v15_arm64:
+  case fpu_v16_arm64:
+  case fpu_v17_arm64:
+  case fpu_v18_arm64:
+  case fpu_v19_arm64:
+  case fpu_v20_arm64:
+  case fpu_v21_arm64:
+  case fpu_v22_arm64:
+  case fpu_v23_arm64:
+  case fpu_v24_arm64:
+  case fpu_v25_arm64:
+  case fpu_v26_arm64:
+  case fpu_v27_arm64:
+  case fpu_v28_arm64:
+  case fpu_v29_arm64:
+  case fpu_v30_arm64:
+  case fpu_v31_arm64:
+    m_fpr.fp_reg[reg - fpu_v0_arm64] =
+      APIntTouint128(reg_value.GetAsUInt128(llvm::APInt(128, 0, false)));
+    break;
+  case fpu_fpsr_arm64:
+    m_fpr.fp_sr = reg_value.GetAsUInt32();
+    break;
+  case fpu_fpcr_arm64:
+    m_fpr.fp_cr = reg_value.GetAsUInt32();
+    break;
+  default:
+    log->Printf("Requested write of unhandled reg: %u", reg);
+    break;
+  }
+
+  if (WriteRegisterSet(set) != 0)
+    error.SetErrorStringWithFormat("failed to write register set");
+
+  return error;
+}
+
+Status NativeRegisterContextOpenBSD_arm64::ReadAllRegisterValues(
+    lldb::WritableDataBufferSP &data_sp) {
+  Status error;
+
+  data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
+  if (!data_sp) {
+    error.SetErrorStringWithFormat(
+        "failed to allocate DataBufferHeap instance of size %zu",
+        REG_CONTEXT_SIZE);
+    return error;
+  }
+
+  error = ReadGPR();
+  if (error.Fail())
+    return error;
+
+  error = ReadFPR();
+  if (error.Fail())
+    return error;
+
+  uint8_t *dst = data_sp->GetBytes();
+  if (dst == nullptr) {
+    error.SetErrorStringWithFormat("DataBufferHeap instance of size %zu"
+                                   " returned a null pointer",
+                                   REG_CONTEXT_SIZE);
+    return error;
+  }
+
+  ::memcpy(dst, &m_gpr, GetGPRSize());
+  dst += GetGPRSize();
+
+  ::memcpy(dst, &m_fpr, GetFPRSize());
+  dst += GetFPRSize();
+
+  return error;
+}
+
+Status NativeRegisterContextOpenBSD_arm64::WriteAllRegisterValues(
+    const lldb::DataBufferSP &data_sp) {
+  Status error;
+
+  if (!data_sp) {
+    error.SetErrorStringWithFormat(
+        "NativeRegisterContextOpenBSD_arm64::%s invalid data_sp provided",
+        __FUNCTION__);
+    return error;
+  }
+
+  if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) {
+    error.SetErrorStringWithFormat(
+        "NativeRegisterContextOpenBSD_arm64::%s data_sp contained mismatched "
+        "data size, expected %zu, actual %llu",
+        __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize());
+    return error;
+  }
+
+  const uint8_t *src = data_sp->GetBytes();
+  if (src == nullptr) {
+    error.SetErrorStringWithFormat("NativeRegisterContextOpenBSD_arm64::%s "
+                                   "DataBuffer::GetBytes() returned a null "
+                                   "pointer",
+                                   __FUNCTION__);
+    return error;
+  }
+  // TODO ?
+  // Do we need to make a custom RegisterInfoOpenBSD_arm64
+  // because the RegisterInfoPOSIX_arm64 doesn't quite match
+  // our machine/reg.h?
+  ::memcpy(&m_gpr, src, GetGPRSize());
+  error = WriteGPR();
+  if (error.Fail())
+    return error;
+  src += GetGPRSize();
+
+  ::memcpy(&m_fpr, src, GetFPRSize());
+  error = WriteFPR();
+  if (error.Fail())
+    return error;
+  src += GetFPRSize();
+
+  return error;
+}
+
+int NativeRegisterContextOpenBSD_arm64::GetSetForNativeRegNum(
+    int reg_num) const {
+  if (reg_num >= k_first_gpr_arm64 && reg_num <= k_last_gpr_arm64)
+    return GPRegSet;
+  else if (reg_num >= k_first_fpr_arm64 && reg_num <= k_last_fpr_arm64)
+    return FPRegSet;
+  else
+    return -1;
+}
+
+int NativeRegisterContextOpenBSD_arm64::ReadRegisterSet(uint32_t set) {
+  switch (set) {
+  case GPRegSet:
+    ReadGPR();
+    return 0;
+  case FPRegSet:
+    ReadFPR();
+    return 0;
+  default:
+    break;
+  }
+  return -1;
+}
+
+int NativeRegisterContextOpenBSD_arm64::WriteRegisterSet(uint32_t set) {
+  switch (set) {
+  case GPRegSet:
+    WriteGPR();
+    return 0;
+  case FPRegSet:
+    WriteFPR();
+    return 0;
+  default:
+    break;
+  }
+  return -1;
+}
+#endif
