Add support for ARM and ARM64 breakpad generated minidump files (version 2).

In this patch I add support for ARM and ARM64 break pad files. There are two flavors of ARM: Apple where FP is R7, and non Apple where FP is R11. Added minimal tests that load up ARM64 and the two flavors or ARM core files with a single thread and known register values in each register. Each register is checked for the exact value.

This is a fixed version of: https://reviews.llvm.org/D49750

The changes from D49750 are:

Don't init the m_arch in the Initialize call as a system info isn't required. This keeps the thread list, module list and other tests from failing
Added -Wextended-offsetof to Xcode project so we catch use extended usages of offsetof before submission
Fixed any extended offset of warnings

Differential Revision: https://reviews.llvm.org/D50336

llvm-svn: 339032
diff --git a/lldb/source/Plugins/Process/minidump/CMakeLists.txt b/lldb/source/Plugins/Process/minidump/CMakeLists.txt
index b898ee1..4126a7e 100644
--- a/lldb/source/Plugins/Process/minidump/CMakeLists.txt
+++ b/lldb/source/Plugins/Process/minidump/CMakeLists.txt
@@ -1,6 +1,8 @@
 add_lldb_library(lldbPluginProcessMinidump PLUGIN
   MinidumpTypes.cpp
   MinidumpParser.cpp
+  RegisterContextMinidump_ARM.cpp
+  RegisterContextMinidump_ARM64.cpp
   RegisterContextMinidump_x86_32.cpp
   RegisterContextMinidump_x86_64.cpp
   ProcessMinidump.cpp
diff --git a/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp b/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp
index 9a97933..ce65fb9 100644
--- a/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp
+++ b/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp
@@ -146,11 +146,14 @@
 }
 
 ArchSpec MinidumpParser::GetArchitecture() {
-  ArchSpec arch_spec;
+  if (m_arch.IsValid())
+    return m_arch;
+
+  // Set the architecture in m_arch
   const MinidumpSystemInfo *system_info = GetSystemInfo();
 
   if (!system_info)
-    return arch_spec;
+    return m_arch;
 
   // TODO what to do about big endiand flavors of arm ?
   // TODO set the arm subarch stuff if the minidump has info about it
@@ -196,19 +199,28 @@
     break;
   case MinidumpOSPlatform::MacOSX:
     triple.setOS(llvm::Triple::OSType::MacOSX);
+    triple.setVendor(llvm::Triple::Apple);
+    break;
+  case MinidumpOSPlatform::IOS:
+    triple.setOS(llvm::Triple::OSType::IOS);
+    triple.setVendor(llvm::Triple::Apple);
     break;
   case MinidumpOSPlatform::Android:
     triple.setOS(llvm::Triple::OSType::Linux);
     triple.setEnvironment(llvm::Triple::EnvironmentType::Android);
     break;
-  default:
+  default: {
     triple.setOS(llvm::Triple::OSType::UnknownOS);
+    std::string csd_version;
+    if (auto s = GetMinidumpString(system_info->csd_version_rva))
+      csd_version = *s;
+    if (csd_version.find("Linux") != std::string::npos)
+      triple.setOS(llvm::Triple::OSType::Linux);
     break;
+    }
   }
-
-  arch_spec.SetTriple(triple);
-
-  return arch_spec;
+  m_arch.SetTriple(triple);
+  return m_arch;
 }
 
 const MinidumpMiscInfo *MinidumpParser::GetMiscInfo() {
diff --git a/lldb/source/Plugins/Process/minidump/MinidumpParser.h b/lldb/source/Plugins/Process/minidump/MinidumpParser.h
index 49b1eef..48c752b 100644
--- a/lldb/source/Plugins/Process/minidump/MinidumpParser.h
+++ b/lldb/source/Plugins/Process/minidump/MinidumpParser.h
@@ -98,6 +98,7 @@
 private:
   lldb::DataBufferSP m_data_sp;
   llvm::DenseMap<uint32_t, MinidumpLocationDescriptor> m_directory_map;
+  ArchSpec m_arch;
 };
 
 } // end namespace minidump
diff --git a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
index b43f223..7af6301 100644
--- a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
+++ b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
@@ -29,6 +29,7 @@
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Threading.h"
 
+#include "Plugins/Process/Utility/StopInfoMachException.h"
 // C includes
 // C++ includes
 
@@ -174,19 +175,21 @@
   switch (arch.GetMachine()) {
   case llvm::Triple::x86:
   case llvm::Triple::x86_64:
-    // supported
+  case llvm::Triple::arm:
+  case llvm::Triple::aarch64:
+    // Any supported architectures must be listed here and also supported in
+    // ThreadMinidump::CreateRegisterContextForFrame().
     break;
-
   default:
     error.SetErrorStringWithFormat("unsupported minidump architecture: %s",
                                    arch.GetArchitectureName());
     return error;
   }
+  GetTarget().SetArchitecture(arch, true /*set_platform*/);
 
   m_thread_list = m_minidump_parser.GetThreads();
   m_active_exception = m_minidump_parser.GetExceptionStream();
   ReadModuleList();
-  GetTarget().SetArchitecture(arch);
 
   llvm::Optional<lldb::pid_t> pid = m_minidump_parser.GetPid();
   if (!pid) {
@@ -229,6 +232,11 @@
   if (arch.GetTriple().getOS() == llvm::Triple::Linux) {
     stop_info = StopInfo::CreateStopReasonWithSignal(
         *stop_thread, m_active_exception->exception_record.exception_code);
+  } else if (arch.GetTriple().getVendor() == llvm::Triple::Apple) {
+    stop_info = StopInfoMachException::CreateStopReasonWithMachException(
+        *stop_thread, m_active_exception->exception_record.exception_code, 2,
+        m_active_exception->exception_record.exception_flags,
+        m_active_exception->exception_record.exception_address, 0);
   } else {
     std::string desc;
     llvm::raw_string_ostream desc_stream(desc);
diff --git a/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp b/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp
new file mode 100644
index 0000000..2d73da4
--- /dev/null
+++ b/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp
@@ -0,0 +1,532 @@
+//===-- RegisterContextMinidump_ARM.cpp -------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// Project includes
+#include "RegisterContextMinidump_ARM.h"
+
+// Other libraries and framework includes
+#include "Utility/ARM_DWARF_Registers.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/LLDBAssert.h"
+#include "lldb/lldb-enumerations.h"
+
+// C includes
+#include <assert.h>
+
+// C++ includes
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace minidump;
+
+#define INV LLDB_INVALID_REGNUM
+#define OFFSET(r) (offsetof(RegisterContextMinidump_ARM::Context, r))
+
+#define DEF_R(i)                                                               \
+  {                                                                            \
+    "r" #i, nullptr, 4, OFFSET(r[i]), eEncodingUint, eFormatHex,               \
+        {INV, dwarf_r##i, INV, INV, reg_r##i}, nullptr, nullptr, nullptr, 0    \
+  }
+
+#define DEF_R_ARG(i, n)                                                        \
+  {                                                                            \
+    "r" #i, "arg" #n, 4, OFFSET(r[i]), eEncodingUint, eFormatHex,              \
+        {INV, dwarf_r##i, LLDB_REGNUM_GENERIC_ARG1 + i, INV, reg_r##i},        \
+        nullptr, nullptr, nullptr, 0                                           \
+  }
+
+#define DEF_D(i)                                                               \
+  {                                                                            \
+    "d" #i, nullptr, 8, OFFSET(d[i]), eEncodingVector, eFormatVectorOfUInt8,   \
+        {INV, dwarf_d##i, INV, INV, reg_d##i}, nullptr, nullptr, nullptr, 0    \
+  }
+
+#define DEF_S(i)                                                               \
+  {                                                                            \
+    "s" #i, nullptr, 4, OFFSET(s[i]), eEncodingIEEE754, eFormatFloat,          \
+        {INV, dwarf_s##i, INV, INV, reg_s##i}, nullptr, nullptr, nullptr, 0    \
+  }
+
+#define DEF_Q(i)                                                               \
+  {                                                                            \
+    "q" #i, nullptr, 16, OFFSET(q[i]), eEncodingVector, eFormatVectorOfUInt8,  \
+        {INV, dwarf_q##i, INV, INV, reg_q##i}, nullptr, nullptr, nullptr, 0    \
+  }
+
+// Zero based LLDB register numbers for this register context
+enum {
+  // General Purpose Registers
+  reg_r0,
+  reg_r1,
+  reg_r2,
+  reg_r3,
+  reg_r4,
+  reg_r5,
+  reg_r6,
+  reg_r7,
+  reg_r8,
+  reg_r9,
+  reg_r10,
+  reg_r11,
+  reg_r12,
+  reg_sp,
+  reg_lr,
+  reg_pc,
+  reg_cpsr,
+  // Floating Point Registers
+  reg_fpscr,
+  reg_d0,
+  reg_d1,
+  reg_d2,
+  reg_d3,
+  reg_d4,
+  reg_d5,
+  reg_d6,
+  reg_d7,
+  reg_d8,
+  reg_d9,
+  reg_d10,
+  reg_d11,
+  reg_d12,
+  reg_d13,
+  reg_d14,
+  reg_d15,
+  reg_d16,
+  reg_d17,
+  reg_d18,
+  reg_d19,
+  reg_d20,
+  reg_d21,
+  reg_d22,
+  reg_d23,
+  reg_d24,
+  reg_d25,
+  reg_d26,
+  reg_d27,
+  reg_d28,
+  reg_d29,
+  reg_d30,
+  reg_d31,
+  reg_s0,
+  reg_s1,
+  reg_s2,
+  reg_s3,
+  reg_s4,
+  reg_s5,
+  reg_s6,
+  reg_s7,
+  reg_s8,
+  reg_s9,
+  reg_s10,
+  reg_s11,
+  reg_s12,
+  reg_s13,
+  reg_s14,
+  reg_s15,
+  reg_s16,
+  reg_s17,
+  reg_s18,
+  reg_s19,
+  reg_s20,
+  reg_s21,
+  reg_s22,
+  reg_s23,
+  reg_s24,
+  reg_s25,
+  reg_s26,
+  reg_s27,
+  reg_s28,
+  reg_s29,
+  reg_s30,
+  reg_s31,
+  reg_q0,
+  reg_q1,
+  reg_q2,
+  reg_q3,
+  reg_q4,
+  reg_q5,
+  reg_q6,
+  reg_q7,
+  reg_q8,
+  reg_q9,
+  reg_q10,
+  reg_q11,
+  reg_q12,
+  reg_q13,
+  reg_q14,
+  reg_q15,
+  k_num_regs
+};
+
+static RegisterInfo g_reg_info_apple_fp = {
+    "fp",
+    "r7",
+    4,
+    OFFSET(r[7]),
+    eEncodingUint,
+    eFormatHex,
+    {INV, dwarf_r7, LLDB_REGNUM_GENERIC_FP, INV, reg_r7},
+    nullptr,
+    nullptr,
+    nullptr,
+    0};
+
+static RegisterInfo g_reg_info_fp = {
+    "fp",
+    "r11",
+    4,
+    OFFSET(r[11]),
+    eEncodingUint,
+    eFormatHex,
+    {INV, dwarf_r11, LLDB_REGNUM_GENERIC_FP, INV, reg_r11},
+    nullptr,
+    nullptr,
+    nullptr,
+    0};
+
+// Register info definitions for this register context
+static RegisterInfo g_reg_infos[] = {
+    DEF_R_ARG(0, 1),
+    DEF_R_ARG(1, 2),
+    DEF_R_ARG(2, 3),
+    DEF_R_ARG(3, 4),
+    DEF_R(4),
+    DEF_R(5),
+    DEF_R(6),
+    DEF_R(7),
+    DEF_R(8),
+    DEF_R(9),
+    DEF_R(10),
+    DEF_R(11),
+    DEF_R(12),
+    {"sp",
+     "r13",
+     4,
+     OFFSET(r[13]),
+     eEncodingUint,
+     eFormatHex,
+     {INV, dwarf_sp, LLDB_REGNUM_GENERIC_SP, INV, reg_sp},
+     nullptr,
+     nullptr,
+     nullptr,
+     0},
+    {"lr",
+     "r14",
+     4,
+     OFFSET(r[14]),
+     eEncodingUint,
+     eFormatHex,
+     {INV, dwarf_lr, LLDB_REGNUM_GENERIC_RA, INV, reg_lr},
+     nullptr,
+     nullptr,
+     nullptr,
+     0},
+    {"pc",
+     "r15",
+     4,
+     OFFSET(r[15]),
+     eEncodingUint,
+     eFormatHex,
+     {INV, dwarf_pc, LLDB_REGNUM_GENERIC_PC, INV, reg_pc},
+     nullptr,
+     nullptr,
+     nullptr,
+     0},
+    {"cpsr",
+     "psr",
+     4,
+     OFFSET(cpsr),
+     eEncodingUint,
+     eFormatHex,
+     {INV, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, INV, reg_cpsr},
+     nullptr,
+     nullptr,
+     nullptr,
+     0},
+    {"fpscr",
+     nullptr,
+     8,
+     OFFSET(fpscr),
+     eEncodingUint,
+     eFormatHex,
+     {INV, INV, INV, INV, reg_fpscr},
+     nullptr,
+     nullptr,
+     nullptr,
+     0},
+    DEF_D(0),
+    DEF_D(1),
+    DEF_D(2),
+    DEF_D(3),
+    DEF_D(4),
+    DEF_D(5),
+    DEF_D(6),
+    DEF_D(7),
+    DEF_D(8),
+    DEF_D(9),
+    DEF_D(10),
+    DEF_D(11),
+    DEF_D(12),
+    DEF_D(13),
+    DEF_D(14),
+    DEF_D(15),
+    DEF_D(16),
+    DEF_D(17),
+    DEF_D(18),
+    DEF_D(19),
+    DEF_D(20),
+    DEF_D(21),
+    DEF_D(22),
+    DEF_D(23),
+    DEF_D(24),
+    DEF_D(25),
+    DEF_D(26),
+    DEF_D(27),
+    DEF_D(28),
+    DEF_D(29),
+    DEF_D(30),
+    DEF_D(31),
+    DEF_S(0),
+    DEF_S(1),
+    DEF_S(2),
+    DEF_S(3),
+    DEF_S(4),
+    DEF_S(5),
+    DEF_S(6),
+    DEF_S(7),
+    DEF_S(8),
+    DEF_S(9),
+    DEF_S(10),
+    DEF_S(11),
+    DEF_S(12),
+    DEF_S(13),
+    DEF_S(14),
+    DEF_S(15),
+    DEF_S(16),
+    DEF_S(17),
+    DEF_S(18),
+    DEF_S(19),
+    DEF_S(20),
+    DEF_S(21),
+    DEF_S(22),
+    DEF_S(23),
+    DEF_S(24),
+    DEF_S(25),
+    DEF_S(26),
+    DEF_S(27),
+    DEF_S(28),
+    DEF_S(29),
+    DEF_S(30),
+    DEF_S(31),
+    DEF_Q(0),
+    DEF_Q(1),
+    DEF_Q(2),
+    DEF_Q(3),
+    DEF_Q(4),
+    DEF_Q(5),
+    DEF_Q(6),
+    DEF_Q(7),
+    DEF_Q(8),
+    DEF_Q(9),
+    DEF_Q(10),
+    DEF_Q(11),
+    DEF_Q(12),
+    DEF_Q(13),
+    DEF_Q(14),
+    DEF_Q(15)};
+
+constexpr size_t k_num_reg_infos = llvm::array_lengthof(g_reg_infos);
+
+// ARM general purpose registers.
+const uint32_t g_gpr_regnums[] = {
+    reg_r0,
+    reg_r1,
+    reg_r2,
+    reg_r3,
+    reg_r4,
+    reg_r5,
+    reg_r6,
+    reg_r7,
+    reg_r8,
+    reg_r9,
+    reg_r10,
+    reg_r11,
+    reg_r12,
+    reg_sp,
+    reg_lr,
+    reg_pc,
+    reg_cpsr,
+    LLDB_INVALID_REGNUM // register sets need to end with this flag
+};
+const uint32_t g_fpu_regnums[] = {
+    reg_fpscr,
+    reg_d0,
+    reg_d1,
+    reg_d2,
+    reg_d3,
+    reg_d4,
+    reg_d5,
+    reg_d6,
+    reg_d7,
+    reg_d8,
+    reg_d9,
+    reg_d10,
+    reg_d11,
+    reg_d12,
+    reg_d13,
+    reg_d14,
+    reg_d15,
+    reg_d16,
+    reg_d17,
+    reg_d18,
+    reg_d19,
+    reg_d20,
+    reg_d21,
+    reg_d22,
+    reg_d23,
+    reg_d24,
+    reg_d25,
+    reg_d26,
+    reg_d27,
+    reg_d28,
+    reg_d29,
+    reg_d30,
+    reg_d31,
+    reg_s0,
+    reg_s1,
+    reg_s2,
+    reg_s3,
+    reg_s4,
+    reg_s5,
+    reg_s6,
+    reg_s7,
+    reg_s8,
+    reg_s9,
+    reg_s10,
+    reg_s11,
+    reg_s12,
+    reg_s13,
+    reg_s14,
+    reg_s15,
+    reg_s16,
+    reg_s17,
+    reg_s18,
+    reg_s19,
+    reg_s20,
+    reg_s21,
+    reg_s22,
+    reg_s23,
+    reg_s24,
+    reg_s25,
+    reg_s26,
+    reg_s27,
+    reg_s28,
+    reg_s29,
+    reg_s30,
+    reg_s31,
+    reg_q0,
+    reg_q1,
+    reg_q2,
+    reg_q3,
+    reg_q4,
+    reg_q5,
+    reg_q6,
+    reg_q7,
+    reg_q8,
+    reg_q9,
+    reg_q10,
+    reg_q11,
+    reg_q12,
+    reg_q13,
+    reg_q14,
+    reg_q15,
+    LLDB_INVALID_REGNUM // register sets need to end with this flag
+};
+
+// Skip the last LLDB_INVALID_REGNUM in each count below by subtracting 1
+constexpr size_t k_num_gpr_regs = llvm::array_lengthof(g_gpr_regnums) - 1;
+constexpr size_t k_num_fpu_regs = llvm::array_lengthof(g_fpu_regnums) - 1;
+
+static RegisterSet g_reg_sets[] = {
+    {"General Purpose Registers", "gpr", k_num_gpr_regs, g_gpr_regnums},
+    {"Floating Point Registers", "fpu", k_num_fpu_regs, g_fpu_regnums},
+};
+
+constexpr size_t k_num_reg_sets = llvm::array_lengthof(g_reg_sets);
+
+RegisterContextMinidump_ARM::RegisterContextMinidump_ARM(
+    Thread &thread, const DataExtractor &data, bool apple)
+    : RegisterContext(thread, 0), m_apple(apple) {
+  lldb::offset_t offset = 0;
+  m_regs.context_flags = data.GetU32(&offset);
+  for (unsigned i = 0; i < llvm::array_lengthof(m_regs.r); ++i)
+    m_regs.r[i] = data.GetU32(&offset);
+  m_regs.cpsr = data.GetU32(&offset);
+  m_regs.fpscr = data.GetU64(&offset);
+  for (unsigned i = 0; i < llvm::array_lengthof(m_regs.d); ++i)
+    m_regs.d[i] = data.GetU64(&offset);
+  lldbassert(k_num_regs == k_num_reg_infos);
+}
+
+size_t RegisterContextMinidump_ARM::GetRegisterCount() { return k_num_regs; }
+
+const RegisterInfo *
+RegisterContextMinidump_ARM::GetRegisterInfoAtIndex(size_t reg) {
+  if (reg < k_num_reg_infos) {
+    if (m_apple) {
+      if (reg == reg_r7)
+        return &g_reg_info_apple_fp;
+    } else {
+      if (reg == reg_r11)
+        return &g_reg_info_fp;
+    }
+    return &g_reg_infos[reg];
+  }
+  return nullptr;
+}
+
+size_t RegisterContextMinidump_ARM::GetRegisterSetCount() {
+  return k_num_reg_sets;
+}
+
+const RegisterSet *RegisterContextMinidump_ARM::GetRegisterSet(size_t set) {
+  if (set < k_num_reg_sets)
+    return &g_reg_sets[set];
+  return nullptr;
+}
+
+const char *RegisterContextMinidump_ARM::GetRegisterName(unsigned reg) {
+  if (reg < k_num_reg_infos)
+    return g_reg_infos[reg].name;
+  return nullptr;
+}
+
+bool RegisterContextMinidump_ARM::ReadRegister(const RegisterInfo *reg_info,
+                                               RegisterValue &reg_value) {
+  Status error;
+  reg_value.SetFromMemoryData(
+      reg_info, (const uint8_t *)&m_regs + reg_info->byte_offset,
+      reg_info->byte_size, lldb::eByteOrderLittle, error);
+  return error.Success();
+}
+
+bool RegisterContextMinidump_ARM::WriteRegister(const RegisterInfo *,
+                                                const RegisterValue &) {
+  return false;
+}
+
+uint32_t RegisterContextMinidump_ARM::ConvertRegisterKindToRegisterNumber(
+    lldb::RegisterKind kind, uint32_t num) {
+  for (size_t i = 0; i < k_num_regs; ++i) {
+    if (g_reg_infos[i].kinds[kind] == num)
+      return i;
+  }
+  return LLDB_INVALID_REGNUM;
+}
diff --git a/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.h b/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.h
new file mode 100644
index 0000000..c410df9
--- /dev/null
+++ b/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.h
@@ -0,0 +1,95 @@
+//===-- RegisterContextMinidump_ARM.h ---------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_RegisterContextMinidump_ARM_h_
+#define liblldb_RegisterContextMinidump_ARM_h_
+
+// Project includes
+#include "MinidumpTypes.h"
+
+// Other libraries and framework includes
+#include "Plugins/Process/Utility/RegisterInfoInterface.h"
+
+#include "lldb/Target/RegisterContext.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/BitmaskEnum.h"
+
+// C includes
+// C++ includes
+
+namespace lldb_private {
+
+namespace minidump {
+
+LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
+
+class RegisterContextMinidump_ARM : public lldb_private::RegisterContext {
+public:
+  RegisterContextMinidump_ARM(lldb_private::Thread &thread,
+                              const DataExtractor &data, bool apple);
+
+  ~RegisterContextMinidump_ARM() override = default;
+
+  void InvalidateAllRegisters() override {
+    // Do nothing... registers are always valid...
+  }
+
+  size_t GetRegisterCount() override;
+
+  const lldb_private::RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override;
+
+  size_t GetRegisterSetCount() override;
+
+  const lldb_private::RegisterSet *GetRegisterSet(size_t set) override;
+
+  const char *GetRegisterName(unsigned reg);
+
+  bool ReadRegister(const RegisterInfo *reg_info,
+                    RegisterValue &reg_value) override;
+
+  bool WriteRegister(const RegisterInfo *reg_info,
+                     const RegisterValue &reg_value) override;
+
+  uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,
+                                               uint32_t num) override;
+
+  // Reference: see breakpad/crashpad source
+  struct QRegValue {
+    uint64_t lo;
+    uint64_t hi;
+  };
+
+  struct Context {
+    uint32_t context_flags;
+    uint32_t r[16];
+    uint32_t cpsr;
+    uint64_t fpscr;
+    union {
+      uint64_t d[32];
+      uint32_t s[32];
+      QRegValue q[16];
+    };
+    uint32_t extra[8];
+  };
+
+protected:
+  enum class Flags : uint32_t {
+    ARM_Flag = 0x40000000,
+    Integer = ARM_Flag | 0x00000002,
+    FloatingPoint = ARM_Flag | 0x00000004,
+    LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ FloatingPoint)
+  };
+  Context m_regs;
+  const bool m_apple; // True if this is an Apple ARM where FP is R7
+};
+
+} // end namespace minidump
+} // end namespace lldb_private
+#endif // liblldb_RegisterContextMinidump_ARM_h_
diff --git a/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.cpp b/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.cpp
new file mode 100644
index 0000000..5ba58d1
--- /dev/null
+++ b/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.cpp
@@ -0,0 +1,836 @@
+//===-- RegisterContextMinidump_ARM64.cpp -----------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// Project includes
+#include "RegisterContextMinidump_ARM64.h"
+
+// Other libraries and framework includes
+#include "Utility/ARM64_DWARF_Registers.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Utility/DataExtractor.h"
+#include "lldb/lldb-enumerations.h"
+
+// C includes
+#include <assert.h>
+
+// C++ includes
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace minidump;
+
+#define INV LLDB_INVALID_REGNUM
+#define OFFSET(r) (offsetof(RegisterContextMinidump_ARM64::Context, r))
+
+#define DEF_X(i)                                                               \
+  {                                                                            \
+    "x" #i, nullptr, 8, OFFSET(x[i]), eEncodingUint, eFormatHex,               \
+        {INV, arm64_dwarf::x##i, INV, INV, reg_x##i}, nullptr, nullptr,        \
+        nullptr, 0                                                             \
+  }
+
+#define DEF_W(i)                                                               \
+  {                                                                            \
+    "w" #i, nullptr, 4, OFFSET(x[i]), eEncodingUint, eFormatHex,               \
+        {INV, INV, INV, INV, reg_w##i}, nullptr, nullptr, nullptr, 0           \
+  }
+
+#define DEF_X_ARG(i, n)                                                        \
+  {                                                                            \
+    "x" #i, "arg" #n, 8, OFFSET(x[i]), eEncodingUint, eFormatHex,              \
+        {INV, arm64_dwarf::x##i, LLDB_REGNUM_GENERIC_ARG1 + i, INV, reg_x##i}, \
+        nullptr, nullptr, nullptr, 0                                           \
+  }
+
+#define DEF_V(i)                                                               \
+  {                                                                            \
+    "v" #i, nullptr, 16, OFFSET(v[i * 16]), eEncodingVector,                   \
+        eFormatVectorOfUInt8, {INV, arm64_dwarf::v##i, INV, INV, reg_v##i},    \
+        nullptr, nullptr, nullptr, 0                                           \
+  }
+
+#define DEF_D(i)                                                               \
+  {                                                                            \
+    "d" #i, nullptr, 8, OFFSET(v[i * 16]), eEncodingVector,                    \
+        eFormatVectorOfUInt8, {INV, INV, INV, INV, reg_d##i}, nullptr,         \
+        nullptr, nullptr, 0                                                    \
+  }
+
+#define DEF_S(i)                                                               \
+  {                                                                            \
+    "s" #i, nullptr, 4, OFFSET(v[i * 16]), eEncodingVector,                    \
+        eFormatVectorOfUInt8, {INV, INV, INV, INV, reg_s##i}, nullptr,         \
+        nullptr, nullptr, 0                                                    \
+  }
+
+#define DEF_H(i)                                                               \
+  {                                                                            \
+    "h" #i, nullptr, 2, OFFSET(v[i * 16]), eEncodingVector,                    \
+        eFormatVectorOfUInt8, {INV, INV, INV, INV, reg_h##i}, nullptr,         \
+        nullptr, nullptr, 0                                                    \
+  }
+
+// Zero based LLDB register numbers for this register context
+enum {
+  // General Purpose Registers
+  reg_x0 = 0,
+  reg_x1,
+  reg_x2,
+  reg_x3,
+  reg_x4,
+  reg_x5,
+  reg_x6,
+  reg_x7,
+  reg_x8,
+  reg_x9,
+  reg_x10,
+  reg_x11,
+  reg_x12,
+  reg_x13,
+  reg_x14,
+  reg_x15,
+  reg_x16,
+  reg_x17,
+  reg_x18,
+  reg_x19,
+  reg_x20,
+  reg_x21,
+  reg_x22,
+  reg_x23,
+  reg_x24,
+  reg_x25,
+  reg_x26,
+  reg_x27,
+  reg_x28,
+  reg_fp,
+  reg_lr,
+  reg_sp,
+  reg_pc,
+  reg_w0,
+  reg_w1,
+  reg_w2,
+  reg_w3,
+  reg_w4,
+  reg_w5,
+  reg_w6,
+  reg_w7,
+  reg_w8,
+  reg_w9,
+  reg_w10,
+  reg_w11,
+  reg_w12,
+  reg_w13,
+  reg_w14,
+  reg_w15,
+  reg_w16,
+  reg_w17,
+  reg_w18,
+  reg_w19,
+  reg_w20,
+  reg_w21,
+  reg_w22,
+  reg_w23,
+  reg_w24,
+  reg_w25,
+  reg_w26,
+  reg_w27,
+  reg_w28,
+  reg_w29,
+  reg_w30,
+  reg_w31,
+  reg_cpsr,
+  // Floating Point Registers
+  reg_fpsr,
+  reg_fpcr,
+  reg_v0,
+  reg_v1,
+  reg_v2,
+  reg_v3,
+  reg_v4,
+  reg_v5,
+  reg_v6,
+  reg_v7,
+  reg_v8,
+  reg_v9,
+  reg_v10,
+  reg_v11,
+  reg_v12,
+  reg_v13,
+  reg_v14,
+  reg_v15,
+  reg_v16,
+  reg_v17,
+  reg_v18,
+  reg_v19,
+  reg_v20,
+  reg_v21,
+  reg_v22,
+  reg_v23,
+  reg_v24,
+  reg_v25,
+  reg_v26,
+  reg_v27,
+  reg_v28,
+  reg_v29,
+  reg_v30,
+  reg_v31,
+  reg_d0,
+  reg_d1,
+  reg_d2,
+  reg_d3,
+  reg_d4,
+  reg_d5,
+  reg_d6,
+  reg_d7,
+  reg_d8,
+  reg_d9,
+  reg_d10,
+  reg_d11,
+  reg_d12,
+  reg_d13,
+  reg_d14,
+  reg_d15,
+  reg_d16,
+  reg_d17,
+  reg_d18,
+  reg_d19,
+  reg_d20,
+  reg_d21,
+  reg_d22,
+  reg_d23,
+  reg_d24,
+  reg_d25,
+  reg_d26,
+  reg_d27,
+  reg_d28,
+  reg_d29,
+  reg_d30,
+  reg_d31,
+  reg_s0,
+  reg_s1,
+  reg_s2,
+  reg_s3,
+  reg_s4,
+  reg_s5,
+  reg_s6,
+  reg_s7,
+  reg_s8,
+  reg_s9,
+  reg_s10,
+  reg_s11,
+  reg_s12,
+  reg_s13,
+  reg_s14,
+  reg_s15,
+  reg_s16,
+  reg_s17,
+  reg_s18,
+  reg_s19,
+  reg_s20,
+  reg_s21,
+  reg_s22,
+  reg_s23,
+  reg_s24,
+  reg_s25,
+  reg_s26,
+  reg_s27,
+  reg_s28,
+  reg_s29,
+  reg_s30,
+  reg_s31,
+  reg_h0,
+  reg_h1,
+  reg_h2,
+  reg_h3,
+  reg_h4,
+  reg_h5,
+  reg_h6,
+  reg_h7,
+  reg_h8,
+  reg_h9,
+  reg_h10,
+  reg_h11,
+  reg_h12,
+  reg_h13,
+  reg_h14,
+  reg_h15,
+  reg_h16,
+  reg_h17,
+  reg_h18,
+  reg_h19,
+  reg_h20,
+  reg_h21,
+  reg_h22,
+  reg_h23,
+  reg_h24,
+  reg_h25,
+  reg_h26,
+  reg_h27,
+  reg_h28,
+  reg_h29,
+  reg_h30,
+  reg_h31,
+  k_num_regs
+};
+
+// Register info definitions for this register context
+static RegisterInfo g_reg_infos[] = {
+    DEF_X_ARG(0, 1),
+    DEF_X_ARG(1, 2),
+    DEF_X_ARG(2, 3),
+    DEF_X_ARG(3, 4),
+    DEF_X_ARG(4, 5),
+    DEF_X_ARG(5, 6),
+    DEF_X_ARG(6, 7),
+    DEF_X_ARG(7, 8),
+    DEF_X(8),
+    DEF_X(9),
+    DEF_X(10),
+    DEF_X(11),
+    DEF_X(12),
+    DEF_X(13),
+    DEF_X(14),
+    DEF_X(15),
+    DEF_X(16),
+    DEF_X(17),
+    DEF_X(18),
+    DEF_X(19),
+    DEF_X(20),
+    DEF_X(21),
+    DEF_X(22),
+    DEF_X(23),
+    DEF_X(24),
+    DEF_X(25),
+    DEF_X(26),
+    DEF_X(27),
+    DEF_X(28),
+    {"fp",
+     "x29",
+     8,
+     OFFSET(x[29]),
+     eEncodingUint,
+     eFormatHex,
+     {INV, arm64_dwarf::x29, LLDB_REGNUM_GENERIC_FP, INV, reg_fp},
+     nullptr,
+     nullptr,
+     nullptr,
+     0},
+    {"lr",
+     "x30",
+     8,
+     OFFSET(x[30]),
+     eEncodingUint,
+     eFormatHex,
+     {INV, arm64_dwarf::x30, LLDB_REGNUM_GENERIC_RA, INV, reg_lr},
+     nullptr,
+     nullptr,
+     nullptr,
+     0},
+    {"sp",
+     "x31",
+     8,
+     OFFSET(x[31]),
+     eEncodingUint,
+     eFormatHex,
+     {INV, arm64_dwarf::x31, LLDB_REGNUM_GENERIC_SP, INV, reg_sp},
+     nullptr,
+     nullptr,
+     nullptr,
+     0},
+    {"pc",
+     nullptr,
+     8,
+     OFFSET(pc),
+     eEncodingUint,
+     eFormatHex,
+     {INV, arm64_dwarf::pc, LLDB_REGNUM_GENERIC_PC, INV, reg_pc},
+     nullptr,
+     nullptr,
+     nullptr,
+     0},
+    // w0 - w31
+    DEF_W(0),
+    DEF_W(1),
+    DEF_W(2),
+    DEF_W(3),
+    DEF_W(4),
+    DEF_W(5),
+    DEF_W(6),
+    DEF_W(7),
+    DEF_W(8),
+    DEF_W(9),
+    DEF_W(10),
+    DEF_W(11),
+    DEF_W(12),
+    DEF_W(13),
+    DEF_W(14),
+    DEF_W(15),
+    DEF_W(16),
+    DEF_W(17),
+    DEF_W(18),
+    DEF_W(19),
+    DEF_W(20),
+    DEF_W(21),
+    DEF_W(22),
+    DEF_W(23),
+    DEF_W(24),
+    DEF_W(25),
+    DEF_W(26),
+    DEF_W(27),
+    DEF_W(28),
+    DEF_W(29),
+    DEF_W(30),
+    DEF_W(31),
+    {"cpsr",
+     "psr",
+     4,
+     OFFSET(cpsr),
+     eEncodingUint,
+     eFormatHex,
+     {INV, arm64_dwarf::cpsr, LLDB_REGNUM_GENERIC_FLAGS, INV, reg_cpsr},
+     nullptr,
+     nullptr,
+     nullptr,
+     0},
+    {"fpsr",
+     nullptr,
+     4,
+     OFFSET(fpsr),
+     eEncodingUint,
+     eFormatHex,
+     {INV, INV, INV, INV, reg_fpsr},
+     nullptr,
+     nullptr,
+     nullptr,
+     0},
+    {"fpcr",
+     nullptr,
+     4,
+     OFFSET(fpcr),
+     eEncodingUint,
+     eFormatHex,
+     {INV, INV, INV, INV, reg_fpcr},
+     nullptr,
+     nullptr,
+     nullptr,
+     0},
+    // v0 - v31
+    DEF_V(0),
+    DEF_V(1),
+    DEF_V(2),
+    DEF_V(3),
+    DEF_V(4),
+    DEF_V(5),
+    DEF_V(6),
+    DEF_V(7),
+    DEF_V(8),
+    DEF_V(9),
+    DEF_V(10),
+    DEF_V(11),
+    DEF_V(12),
+    DEF_V(13),
+    DEF_V(14),
+    DEF_V(15),
+    DEF_V(16),
+    DEF_V(17),
+    DEF_V(18),
+    DEF_V(19),
+    DEF_V(20),
+    DEF_V(21),
+    DEF_V(22),
+    DEF_V(23),
+    DEF_V(24),
+    DEF_V(25),
+    DEF_V(26),
+    DEF_V(27),
+    DEF_V(28),
+    DEF_V(29),
+    DEF_V(30),
+    DEF_V(31),
+    // d0 - d31
+    DEF_D(0),
+    DEF_D(1),
+    DEF_D(2),
+    DEF_D(3),
+    DEF_D(4),
+    DEF_D(5),
+    DEF_D(6),
+    DEF_D(7),
+    DEF_D(8),
+    DEF_D(9),
+    DEF_D(10),
+    DEF_D(11),
+    DEF_D(12),
+    DEF_D(13),
+    DEF_D(14),
+    DEF_D(15),
+    DEF_D(16),
+    DEF_D(17),
+    DEF_D(18),
+    DEF_D(19),
+    DEF_D(20),
+    DEF_D(21),
+    DEF_D(22),
+    DEF_D(23),
+    DEF_D(24),
+    DEF_D(25),
+    DEF_D(26),
+    DEF_D(27),
+    DEF_D(28),
+    DEF_D(29),
+    DEF_D(30),
+    DEF_D(31),
+    // s0 - s31
+    DEF_S(0),
+    DEF_S(1),
+    DEF_S(2),
+    DEF_S(3),
+    DEF_S(4),
+    DEF_S(5),
+    DEF_S(6),
+    DEF_S(7),
+    DEF_S(8),
+    DEF_S(9),
+    DEF_S(10),
+    DEF_S(11),
+    DEF_S(12),
+    DEF_S(13),
+    DEF_S(14),
+    DEF_S(15),
+    DEF_S(16),
+    DEF_S(17),
+    DEF_S(18),
+    DEF_S(19),
+    DEF_S(20),
+    DEF_S(21),
+    DEF_S(22),
+    DEF_S(23),
+    DEF_S(24),
+    DEF_S(25),
+    DEF_S(26),
+    DEF_S(27),
+    DEF_S(28),
+    DEF_S(29),
+    DEF_S(30),
+    DEF_S(31),
+    // h0 - h31
+    DEF_H(0),
+    DEF_H(1),
+    DEF_H(2),
+    DEF_H(3),
+    DEF_H(4),
+    DEF_H(5),
+    DEF_H(6),
+    DEF_H(7),
+    DEF_H(8),
+    DEF_H(9),
+    DEF_H(10),
+    DEF_H(11),
+    DEF_H(12),
+    DEF_H(13),
+    DEF_H(14),
+    DEF_H(15),
+    DEF_H(16),
+    DEF_H(17),
+    DEF_H(18),
+    DEF_H(19),
+    DEF_H(20),
+    DEF_H(21),
+    DEF_H(22),
+    DEF_H(23),
+    DEF_H(24),
+    DEF_H(25),
+    DEF_H(26),
+    DEF_H(27),
+    DEF_H(28),
+    DEF_H(29),
+    DEF_H(30),
+    DEF_H(31),
+};
+
+constexpr size_t k_num_reg_infos = llvm::array_lengthof(g_reg_infos);
+
+// ARM64 general purpose registers.
+const uint32_t g_gpr_regnums[] = {
+    reg_x0,
+    reg_x1,
+    reg_x2,
+    reg_x3,
+    reg_x4,
+    reg_x5,
+    reg_x6,
+    reg_x7,
+    reg_x8,
+    reg_x9,
+    reg_x10,
+    reg_x11,
+    reg_x12,
+    reg_x13,
+    reg_x14,
+    reg_x15,
+    reg_x16,
+    reg_x17,
+    reg_x18,
+    reg_x19,
+    reg_x20,
+    reg_x21,
+    reg_x22,
+    reg_x23,
+    reg_x24,
+    reg_x25,
+    reg_x26,
+    reg_x27,
+    reg_x28,
+    reg_fp,
+    reg_lr,
+    reg_sp,
+    reg_w0,
+    reg_w1,
+    reg_w2,
+    reg_w3,
+    reg_w4,
+    reg_w5,
+    reg_w6,
+    reg_w7,
+    reg_w8,
+    reg_w9,
+    reg_w10,
+    reg_w11,
+    reg_w12,
+    reg_w13,
+    reg_w14,
+    reg_w15,
+    reg_w16,
+    reg_w17,
+    reg_w18,
+    reg_w19,
+    reg_w20,
+    reg_w21,
+    reg_w22,
+    reg_w23,
+    reg_w24,
+    reg_w25,
+    reg_w26,
+    reg_w27,
+    reg_w28,
+    reg_w29,
+    reg_w30,
+    reg_w31,
+    reg_pc,
+    reg_cpsr,
+    LLDB_INVALID_REGNUM // register sets need to end with this flag
+};
+const uint32_t g_fpu_regnums[] = {
+    reg_v0,
+    reg_v1,
+    reg_v2,
+    reg_v3,
+    reg_v4,
+    reg_v5,
+    reg_v6,
+    reg_v7,
+    reg_v8,
+    reg_v9,
+    reg_v10,
+    reg_v11,
+    reg_v12,
+    reg_v13,
+    reg_v14,
+    reg_v15,
+    reg_v16,
+    reg_v17,
+    reg_v18,
+    reg_v19,
+    reg_v20,
+    reg_v21,
+    reg_v22,
+    reg_v23,
+    reg_v24,
+    reg_v25,
+    reg_v26,
+    reg_v27,
+    reg_v28,
+    reg_v29,
+    reg_v30,
+    reg_v31,
+    reg_d0,
+    reg_d1,
+    reg_d2,
+    reg_d3,
+    reg_d4,
+    reg_d5,
+    reg_d6,
+    reg_d7,
+    reg_d8,
+    reg_d9,
+    reg_d10,
+    reg_d11,
+    reg_d12,
+    reg_d13,
+    reg_d14,
+    reg_d15,
+    reg_d16,
+    reg_d17,
+    reg_d18,
+    reg_d19,
+    reg_d20,
+    reg_d21,
+    reg_d22,
+    reg_d23,
+    reg_d24,
+    reg_d25,
+    reg_d26,
+    reg_d27,
+    reg_d28,
+    reg_d29,
+    reg_d30,
+    reg_d31,
+    reg_s0,
+    reg_s1,
+    reg_s2,
+    reg_s3,
+    reg_s4,
+    reg_s5,
+    reg_s6,
+    reg_s7,
+    reg_s8,
+    reg_s9,
+    reg_s10,
+    reg_s11,
+    reg_s12,
+    reg_s13,
+    reg_s14,
+    reg_s15,
+    reg_s16,
+    reg_s17,
+    reg_s18,
+    reg_s19,
+    reg_s20,
+    reg_s21,
+    reg_s22,
+    reg_s23,
+    reg_s24,
+    reg_s25,
+    reg_s26,
+    reg_s27,
+    reg_s28,
+    reg_s29,
+    reg_s30,
+    reg_s31,
+    reg_h0,
+    reg_h1,
+    reg_h2,
+    reg_h3,
+    reg_h4,
+    reg_h5,
+    reg_h6,
+    reg_h7,
+    reg_h8,
+    reg_h9,
+    reg_h10,
+    reg_h11,
+    reg_h12,
+    reg_h13,
+    reg_h14,
+    reg_h15,
+    reg_h16,
+    reg_h17,
+    reg_h18,
+    reg_h19,
+    reg_h20,
+    reg_h21,
+    reg_h22,
+    reg_h23,
+    reg_h24,
+    reg_h25,
+    reg_h26,
+    reg_h27,
+    reg_h28,
+    reg_h29,
+    reg_h30,
+    reg_h31,
+    reg_fpsr,
+    reg_fpcr,
+    LLDB_INVALID_REGNUM // register sets need to end with this flag
+};
+
+// Skip the last LLDB_INVALID_REGNUM in each count below by subtracting 1
+constexpr size_t k_num_gpr_regs = llvm::array_lengthof(g_gpr_regnums) - 1;
+constexpr size_t k_num_fpu_regs = llvm::array_lengthof(g_fpu_regnums) - 1;
+
+static RegisterSet g_reg_sets[] = {
+    {"General Purpose Registers", "gpr", k_num_gpr_regs, g_gpr_regnums},
+    {"Floating Point Registers", "fpu", k_num_fpu_regs, g_fpu_regnums},
+};
+
+constexpr size_t k_num_reg_sets = llvm::array_lengthof(g_reg_sets);
+
+RegisterContextMinidump_ARM64::RegisterContextMinidump_ARM64(
+    Thread &thread, const DataExtractor &data)
+    : RegisterContext(thread, 0) {
+  lldb::offset_t offset = 0;
+  m_regs.context_flags = data.GetU64(&offset);
+  for (unsigned i = 0; i < 32; ++i)
+    m_regs.x[i] = data.GetU64(&offset);
+  m_regs.pc = data.GetU64(&offset);
+  m_regs.cpsr = data.GetU32(&offset);
+  m_regs.fpsr = data.GetU32(&offset);
+  m_regs.fpcr = data.GetU32(&offset);
+  auto regs_data = data.GetData(&offset, sizeof(m_regs.v));
+  if (regs_data)
+    memcpy(m_regs.v, regs_data, sizeof(m_regs.v));
+  assert(k_num_regs == k_num_reg_infos);
+}
+size_t RegisterContextMinidump_ARM64::GetRegisterCount() { return k_num_regs; }
+
+const RegisterInfo *
+RegisterContextMinidump_ARM64::GetRegisterInfoAtIndex(size_t reg) {
+  if (reg < k_num_reg_infos)
+    return &g_reg_infos[reg];
+  return nullptr;
+}
+
+size_t RegisterContextMinidump_ARM64::GetRegisterSetCount() {
+  return k_num_reg_sets;
+}
+
+const RegisterSet *RegisterContextMinidump_ARM64::GetRegisterSet(size_t set) {
+  if (set < k_num_reg_sets)
+    return &g_reg_sets[set];
+  return nullptr;
+}
+
+const char *RegisterContextMinidump_ARM64::GetRegisterName(unsigned reg) {
+  if (reg < k_num_reg_infos)
+    return g_reg_infos[reg].name;
+  return nullptr;
+}
+
+bool RegisterContextMinidump_ARM64::ReadRegister(const RegisterInfo *reg_info,
+                                                 RegisterValue &reg_value) {
+  Status error;
+  reg_value.SetFromMemoryData(
+      reg_info, (const uint8_t *)&m_regs + reg_info->byte_offset,
+      reg_info->byte_size, lldb::eByteOrderLittle, error);
+  return error.Success();
+}
+
+bool RegisterContextMinidump_ARM64::WriteRegister(const RegisterInfo *,
+                                                  const RegisterValue &) {
+  return false;
+}
+
+uint32_t RegisterContextMinidump_ARM64::ConvertRegisterKindToRegisterNumber(
+    lldb::RegisterKind kind, uint32_t num) {
+  for (size_t i = 0; i < k_num_regs; ++i) {
+    if (g_reg_infos[i].kinds[kind] == num)
+      return i;
+  }
+  return LLDB_INVALID_REGNUM;
+}
diff --git a/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.h b/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.h
new file mode 100644
index 0000000..2a3f254
--- /dev/null
+++ b/lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.h
@@ -0,0 +1,85 @@
+//===-- RegisterContextMinidump_ARM64.h -------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_RegisterContextMinidump_ARM64_h_
+#define liblldb_RegisterContextMinidump_ARM64_h_
+
+// Project includes
+#include "MinidumpTypes.h"
+
+// Other libraries and framework includes
+#include "Plugins/Process/Utility/RegisterInfoInterface.h"
+#include "lldb/Target/RegisterContext.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/BitmaskEnum.h"
+
+// C includes
+// C++ includes
+
+namespace lldb_private {
+
+namespace minidump {
+
+LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
+
+class RegisterContextMinidump_ARM64 : public lldb_private::RegisterContext {
+public:
+  RegisterContextMinidump_ARM64(lldb_private::Thread &thread,
+                                const DataExtractor &data);
+
+  ~RegisterContextMinidump_ARM64() override = default;
+
+  void InvalidateAllRegisters() override {
+    // Do nothing... registers are always valid...
+  }
+
+  size_t GetRegisterCount() override;
+
+  const lldb_private::RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override;
+
+  size_t GetRegisterSetCount() override;
+
+  const lldb_private::RegisterSet *GetRegisterSet(size_t set) override;
+
+  const char *GetRegisterName(unsigned reg);
+
+  bool ReadRegister(const RegisterInfo *reg_info,
+                    RegisterValue &reg_value) override;
+
+  bool WriteRegister(const RegisterInfo *reg_info,
+                     const RegisterValue &reg_value) override;
+
+  uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,
+                                               uint32_t num) override;
+
+  // Reference: see breakpad/crashpad source
+  struct Context {
+    uint64_t context_flags;
+    uint64_t x[32];
+    uint64_t pc;
+    uint32_t cpsr;
+    uint32_t fpsr;
+    uint32_t fpcr;
+    uint8_t v[32 * 16]; // 32 128-bit floating point registers
+  };
+
+protected:
+  enum class Flags : uint32_t {
+    ARM64_Flag = 0x80000000,
+    Integer = ARM64_Flag | 0x00000002,
+    FloatingPoint = ARM64_Flag | 0x00000004,
+    LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ FloatingPoint)
+  };
+  Context m_regs;
+};
+
+} // end namespace minidump
+} // end namespace lldb_private
+#endif // liblldb_RegisterContextMinidump_ARM64_h_
diff --git a/lldb/source/Plugins/Process/minidump/ThreadMinidump.cpp b/lldb/source/Plugins/Process/minidump/ThreadMinidump.cpp
index 3fafb61..97493eb 100644
--- a/lldb/source/Plugins/Process/minidump/ThreadMinidump.cpp
+++ b/lldb/source/Plugins/Process/minidump/ThreadMinidump.cpp
@@ -11,6 +11,8 @@
 #include "ThreadMinidump.h"
 #include "ProcessMinidump.h"
 
+#include "RegisterContextMinidump_ARM.h"
+#include "RegisterContextMinidump_ARM64.h"
 #include "RegisterContextMinidump_x86_32.h"
 #include "RegisterContextMinidump_x86_64.h"
 
@@ -54,7 +56,6 @@
 ThreadMinidump::CreateRegisterContextForFrame(StackFrame *frame) {
   RegisterContextSP reg_ctx_sp;
   uint32_t concrete_frame_idx = 0;
-  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
 
   if (frame)
     concrete_frame_idx = frame->GetConcreteFrameIndex();
@@ -88,15 +89,22 @@
           *this, reg_interface, gpregset, {}));
       break;
     }
-    default:
+    case llvm::Triple::aarch64: {
+      DataExtractor data(m_gpregset_data.data(), m_gpregset_data.size(),
+                         lldb::eByteOrderLittle, 8);
+      m_thread_reg_ctx_sp.reset(new RegisterContextMinidump_ARM64(*this, data));
       break;
     }
-
-    if (!reg_interface) {
-      if (log)
-        log->Printf("elf-core::%s:: Architecture(%d) not supported",
-                    __FUNCTION__, arch.GetMachine());
-      assert(false && "Architecture not supported");
+    case llvm::Triple::arm: {
+      DataExtractor data(m_gpregset_data.data(), m_gpregset_data.size(),
+                         lldb::eByteOrderLittle, 8);
+      const bool apple = arch.GetTriple().getVendor() == llvm::Triple::Apple;
+      m_thread_reg_ctx_sp.reset(
+          new RegisterContextMinidump_ARM(*this, data, apple));
+      break;
+    }
+    default:
+      break;
     }
 
     reg_ctx_sp = m_thread_reg_ctx_sp;