diff options
| author | Greg Clayton <gclayton@apple.com> | 2018-08-02 16:46:15 +0000 |
|---|---|---|
| committer | Greg Clayton <gclayton@apple.com> | 2018-08-02 16:46:15 +0000 |
| commit | 2d953f22a00b298eaa3a79edaba5c4eff1571a24 (patch) | |
| tree | f80d641eb2ecf2791289d2251e7bd4d0aa5e0bc2 /lldb/source/Plugins/Process | |
| parent | 92b16738a1ce78de768d900f9e17c06ed92ed272 (diff) | |
| download | bcm5719-llvm-2d953f22a00b298eaa3a79edaba5c4eff1571a24.tar.gz bcm5719-llvm-2d953f22a00b298eaa3a79edaba5c4eff1571a24.zip | |
Add support for ARM and ARM64 breakpad generated minidump files
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.
Differential Revision: https://reviews.llvm.org/D49750
llvm-svn: 338734
Diffstat (limited to 'lldb/source/Plugins/Process')
8 files changed, 1651 insertions, 75 deletions
diff --git a/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp b/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp index 9a979335e99..7bbd5788bc3 100644 --- a/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp +++ b/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp @@ -145,71 +145,7 @@ const MinidumpSystemInfo *MinidumpParser::GetSystemInfo() { return MinidumpSystemInfo::Parse(data); } -ArchSpec MinidumpParser::GetArchitecture() { - ArchSpec arch_spec; - const MinidumpSystemInfo *system_info = GetSystemInfo(); - - if (!system_info) - return arch_spec; - - // TODO what to do about big endiand flavors of arm ? - // TODO set the arm subarch stuff if the minidump has info about it - - llvm::Triple triple; - triple.setVendor(llvm::Triple::VendorType::UnknownVendor); - - const MinidumpCPUArchitecture arch = - static_cast<const MinidumpCPUArchitecture>( - static_cast<const uint32_t>(system_info->processor_arch)); - - switch (arch) { - case MinidumpCPUArchitecture::X86: - triple.setArch(llvm::Triple::ArchType::x86); - break; - case MinidumpCPUArchitecture::AMD64: - triple.setArch(llvm::Triple::ArchType::x86_64); - break; - case MinidumpCPUArchitecture::ARM: - triple.setArch(llvm::Triple::ArchType::arm); - break; - case MinidumpCPUArchitecture::ARM64: - triple.setArch(llvm::Triple::ArchType::aarch64); - break; - default: - triple.setArch(llvm::Triple::ArchType::UnknownArch); - break; - } - - const MinidumpOSPlatform os = static_cast<const MinidumpOSPlatform>( - static_cast<const uint32_t>(system_info->platform_id)); - - // TODO add all of the OSes that Minidump/breakpad distinguishes? - switch (os) { - case MinidumpOSPlatform::Win32S: - case MinidumpOSPlatform::Win32Windows: - case MinidumpOSPlatform::Win32NT: - case MinidumpOSPlatform::Win32CE: - triple.setOS(llvm::Triple::OSType::Win32); - break; - case MinidumpOSPlatform::Linux: - triple.setOS(llvm::Triple::OSType::Linux); - break; - case MinidumpOSPlatform::MacOSX: - triple.setOS(llvm::Triple::OSType::MacOSX); - break; - case MinidumpOSPlatform::Android: - triple.setOS(llvm::Triple::OSType::Linux); - triple.setEnvironment(llvm::Triple::EnvironmentType::Android); - break; - default: - triple.setOS(llvm::Triple::OSType::UnknownOS); - break; - } - - arch_spec.SetTriple(triple); - - return arch_spec; -} +ArchSpec MinidumpParser::GetArchitecture() { return m_arch; } const MinidumpMiscInfo *MinidumpParser::GetMiscInfo() { llvm::ArrayRef<uint8_t> data = GetStream(MinidumpStreamType::MiscInfo); @@ -552,5 +488,79 @@ Status MinidumpParser::Initialize() { return error; } + // Set the architecture in m_arch + const MinidumpSystemInfo *system_info = GetSystemInfo(); + + if (!system_info) { + error.SetErrorString("invalid minidump: missing system info"); + return error; + } + + // TODO what to do about big endiand flavors of arm ? + // TODO set the arm subarch stuff if the minidump has info about it + + llvm::Triple triple; + triple.setVendor(llvm::Triple::VendorType::UnknownVendor); + + const MinidumpCPUArchitecture arch = + static_cast<const MinidumpCPUArchitecture>( + static_cast<const uint32_t>(system_info->processor_arch)); + + switch (arch) { + case MinidumpCPUArchitecture::X86: + triple.setArch(llvm::Triple::ArchType::x86); + break; + case MinidumpCPUArchitecture::AMD64: + triple.setArch(llvm::Triple::ArchType::x86_64); + break; + case MinidumpCPUArchitecture::ARM: + triple.setArch(llvm::Triple::ArchType::arm); + break; + case MinidumpCPUArchitecture::ARM64: + triple.setArch(llvm::Triple::ArchType::aarch64); + break; + default: + triple.setArch(llvm::Triple::ArchType::UnknownArch); + break; + } + + const MinidumpOSPlatform os = static_cast<const MinidumpOSPlatform>( + static_cast<const uint32_t>(system_info->platform_id)); + + // TODO add all of the OSes that Minidump/breakpad distinguishes? + switch (os) { + case MinidumpOSPlatform::Win32S: + case MinidumpOSPlatform::Win32Windows: + case MinidumpOSPlatform::Win32NT: + case MinidumpOSPlatform::Win32CE: + triple.setOS(llvm::Triple::OSType::Win32); + break; + case MinidumpOSPlatform::Linux: + triple.setOS(llvm::Triple::OSType::Linux); + 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: { + 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; + } + } + m_arch.SetTriple(triple); + return error; } diff --git a/lldb/source/Plugins/Process/minidump/MinidumpParser.h b/lldb/source/Plugins/Process/minidump/MinidumpParser.h index 49b1eef14de..48c752b541e 100644 --- a/lldb/source/Plugins/Process/minidump/MinidumpParser.h +++ b/lldb/source/Plugins/Process/minidump/MinidumpParser.h @@ -98,6 +98,7 @@ private: 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 b43f22382ea..7af6301b7f1 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 @@ Status ProcessMinidump::DoLoadCore() { 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 @@ void ProcessMinidump::RefreshStateAfterStop() { 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 00000000000..2d73da4e5b5 --- /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 ®_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 00000000000..c410df99b1c --- /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 ®_value) override; + + bool WriteRegister(const RegisterInfo *reg_info, + const RegisterValue ®_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 00000000000..5ba58d1ca81 --- /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 ®_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 00000000000..2a3f254c851 --- /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 ®_value) override; + + bool WriteRegister(const RegisterInfo *reg_info, + const RegisterValue ®_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 3fafb6134e7..f0c1c1e2f1e 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" @@ -88,15 +90,22 @@ ThreadMinidump::CreateRegisterContextForFrame(StackFrame *frame) { *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; |

