clayborg updated this revision to Diff 158371.
clayborg added a comment.
Removed unnecessary Xcode project changes and removed #include that wasn't
needed.
https://reviews.llvm.org/D49750
Files:
include/lldb/Target/Target.h
lldb.xcodeproj/project.pbxproj
packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpNew.py
packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm-linux.dmp
packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm-macos.dmp
packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm64-macos.dmp
source/Plugins/Process/minidump/MinidumpParser.cpp
source/Plugins/Process/minidump/MinidumpParser.h
source/Plugins/Process/minidump/ProcessMinidump.cpp
source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp
source/Plugins/Process/minidump/RegisterContextMinidump_ARM.h
source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.cpp
source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.h
source/Plugins/Process/minidump/ThreadMinidump.cpp
source/Target/Target.cpp
Index: source/Target/Target.cpp
===================================================================
--- source/Target/Target.cpp
+++ source/Target/Target.cpp
@@ -1426,13 +1426,33 @@
}
}
-bool Target::SetArchitecture(const ArchSpec &arch_spec) {
+bool Target::SetArchitecture(const ArchSpec &arch_spec, bool set_platform) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TARGET));
bool missing_local_arch = !m_arch.GetSpec().IsValid();
bool replace_local_arch = true;
bool compatible_local_arch = false;
ArchSpec other(arch_spec);
+ // Changing the architecture might mean that the currently selected platform
+ // isn't compatible. Set the platform correctly if we are asked to do so,
+ // otherwise assume the user will set the platform manually.
+ if (set_platform) {
+ if (other.IsValid()) {
+ auto platform_sp = GetPlatform();
+ if (!platform_sp ||
+ !platform_sp->IsCompatibleArchitecture(other, false, nullptr)) {
+ ArchSpec platform_arch;
+ auto arch_platform_sp = Platform::GetPlatformForArchitecture(
+ other, &platform_arch);
+ if (arch_platform_sp) {
+ SetPlatform(arch_platform_sp);
+ if (platform_arch.IsValid())
+ other = platform_arch;
+ }
+ }
+ }
+ }
+
if (!missing_local_arch) {
if (m_arch.GetSpec().IsCompatibleMatch(arch_spec)) {
other.MergeFrom(m_arch.GetSpec());
Index: source/Plugins/Process/minidump/ThreadMinidump.cpp
===================================================================
--- source/Plugins/Process/minidump/ThreadMinidump.cpp
+++ source/Plugins/Process/minidump/ThreadMinidump.cpp
@@ -13,6 +13,8 @@
#include "RegisterContextMinidump_x86_32.h"
#include "RegisterContextMinidump_x86_64.h"
+#include "RegisterContextMinidump_ARM.h"
+#include "RegisterContextMinidump_ARM64.h"
// Other libraries and framework includes
#include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
@@ -88,17 +90,24 @@
*this, reg_interface, gpregset, {}));
break;
}
+ 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;
+ }
+ 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;
}
- if (!reg_interface) {
- if (log)
- log->Printf("elf-core::%s:: Architecture(%d) not supported",
- __FUNCTION__, arch.GetMachine());
- assert(false && "Architecture not supported");
- }
-
reg_ctx_sp = m_thread_reg_ctx_sp;
} else if (m_unwinder_ap) {
reg_ctx_sp = m_unwinder_ap->CreateRegisterContextForFrame(frame);
Index: source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.h
===================================================================
--- source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.h
+++ source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.h
@@ -0,0 +1,86 @@
+//===-- 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_
Index: source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.cpp
===================================================================
--- source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.cpp
+++ source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.cpp
@@ -0,0 +1,281 @@
+//===-- 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 "lldb/lldb-enumerations.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Utility/DataExtractor.h"
+#include "Utility/ARM64_DWARF_Registers.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;
+}
Index: source/Plugins/Process/minidump/RegisterContextMinidump_ARM.h
===================================================================
--- source/Plugins/Process/minidump/RegisterContextMinidump_ARM.h
+++ source/Plugins/Process/minidump/RegisterContextMinidump_ARM.h
@@ -0,0 +1,96 @@
+//===-- 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_
Index: source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp
===================================================================
--- source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp
+++ source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp
@@ -0,0 +1,234 @@
+//===-- 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 "lldb/lldb-enumerations.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/LLDBAssert.h"
+#include "Utility/ARM_DWARF_Registers.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;
+}
Index: source/Plugins/Process/minidump/ProcessMinidump.cpp
===================================================================
--- source/Plugins/Process/minidump/ProcessMinidump.cpp
+++ 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,12 @@
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);
Index: source/Plugins/Process/minidump/MinidumpParser.h
===================================================================
--- source/Plugins/Process/minidump/MinidumpParser.h
+++ 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
Index: source/Plugins/Process/minidump/MinidumpParser.cpp
===================================================================
--- source/Plugins/Process/minidump/MinidumpParser.cpp
+++ source/Plugins/Process/minidump/MinidumpParser.cpp
@@ -146,69 +146,7 @@
}
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;
+ return m_arch;
}
const MinidumpMiscInfo *MinidumpParser::GetMiscInfo() {
@@ -552,5 +490,77 @@
return error;
}
+ // Set the architecture in m_arch
+ const MinidumpSystemInfo *system_info = GetSystemInfo();
+
+ if (!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;
}
Index: packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpNew.py
===================================================================
--- packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpNew.py
+++ packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpNew.py
@@ -189,6 +189,161 @@
stop_description = thread.GetStopDescription(256)
self.assertEqual(stop_description, "")
+ def check_register_unsigned(self, set, name, expected):
+ reg_value = set.GetChildMemberWithName(name)
+ self.assertTrue(reg_value.IsValid(),
+ 'Verify we have a register named "%s"' % (name))
+ self.assertEqual(reg_value.GetValueAsUnsigned(), expected,
+ 'Verify "%s" == %i' % (name, expected))
+
+ def check_register_string_value(self, set, name, expected, format):
+ reg_value = set.GetChildMemberWithName(name)
+ self.assertTrue(reg_value.IsValid(),
+ 'Verify we have a register named "%s"' % (name))
+ if format is not None:
+ reg_value.SetFormat(format)
+ self.assertEqual(reg_value.GetValue(), expected,
+ 'Verify "%s" has string value "%s"' % (name,
+ expected))
+
+ def test_arm64_registers(self):
+ """Test ARM64 registers from a breakpad created minidump."""
+ # target create -c arm64-macos.dmp
+ self.dbg.CreateTarget(None)
+ self.target = self.dbg.GetSelectedTarget()
+ self.process = self.target.LoadCore("arm64-macos.dmp")
+ self.check_state()
+ self.assertEqual(self.process.GetNumThreads(), 1)
+ thread = self.process.GetThreadAtIndex(0)
+ self.assertEqual(thread.GetStopReason(), lldb.eStopReasonNone)
+ stop_description = thread.GetStopDescription(256)
+ self.assertEqual(stop_description, "")
+ registers = thread.GetFrameAtIndex(0).GetRegisters()
+ # Verify the GPR registers are all correct
+ # Verify x0 - x31 register values
+ gpr = registers.GetValueAtIndex(0)
+ for i in range(32):
+ v = i+1 | i+2 << 32 | i+3 << 48
+ w = i+1
+ self.check_register_unsigned(gpr, 'x%i' % (i), v)
+ self.check_register_unsigned(gpr, 'w%i' % (i), w)
+ # Verify arg1 - arg8 register values
+ for i in range(1, 9):
+ v = i | i+1 << 32 | i+2 << 48
+ self.check_register_unsigned(gpr, 'arg%i' % (i), v)
+ i = 29
+ v = i+1 | i+2 << 32 | i+3 << 48
+ self.check_register_unsigned(gpr, 'fp', v)
+ i = 30
+ v = i+1 | i+2 << 32 | i+3 << 48
+ self.check_register_unsigned(gpr, 'lr', v)
+ i = 31
+ v = i+1 | i+2 << 32 | i+3 << 48
+ self.check_register_unsigned(gpr, 'sp', v)
+ self.check_register_unsigned(gpr, 'pc', 0x1000)
+ self.check_register_unsigned(gpr, 'cpsr', 0x11223344)
+ self.check_register_unsigned(gpr, 'psr', 0x11223344)
+
+ # Verify the FPR registers are all correct
+ fpr = registers.GetValueAtIndex(1)
+ for i in range(32):
+ v = "0x"
+ d = "0x"
+ s = "0x"
+ h = "0x"
+ for j in range(i+15, i-1, -1):
+ v += "%2.2x" % (j)
+ for j in range(i+7, i-1, -1):
+ d += "%2.2x" % (j)
+ for j in range(i+3, i-1, -1):
+ s += "%2.2x" % (j)
+ for j in range(i+1, i-1, -1):
+ h += "%2.2x" % (j)
+ self.check_register_string_value(fpr, "v%i" % (i), v,
+ lldb.eFormatHex)
+ self.check_register_string_value(fpr, "d%i" % (i), d,
+ lldb.eFormatHex)
+ self.check_register_string_value(fpr, "s%i" % (i), s,
+ lldb.eFormatHex)
+ self.check_register_string_value(fpr, "h%i" % (i), h,
+ lldb.eFormatHex)
+ self.check_register_unsigned(gpr, 'fpsr', 0x55667788)
+ self.check_register_unsigned(gpr, 'fpcr', 0x99aabbcc)
+
+ def verify_arm_registers(self, apple=False):
+ """
+ Verify values of all ARM registers from a breakpad created
+ minidump.
+ """
+ self.dbg.CreateTarget(None)
+ self.target = self.dbg.GetSelectedTarget()
+ if apple:
+ self.process = self.target.LoadCore("arm-macos.dmp")
+ else:
+ self.process = self.target.LoadCore("arm-linux.dmp")
+ self.check_state()
+ self.assertEqual(self.process.GetNumThreads(), 1)
+ thread = self.process.GetThreadAtIndex(0)
+ self.assertEqual(thread.GetStopReason(), lldb.eStopReasonNone)
+ stop_description = thread.GetStopDescription(256)
+ self.assertEqual(stop_description, "")
+ registers = thread.GetFrameAtIndex(0).GetRegisters()
+ # Verify the GPR registers are all correct
+ # Verify x0 - x31 register values
+ gpr = registers.GetValueAtIndex(0)
+ for i in range(1, 16):
+ self.check_register_unsigned(gpr, 'r%i' % (i), i+1)
+ # Verify arg1 - arg4 register values
+ for i in range(1, 5):
+ self.check_register_unsigned(gpr, 'arg%i' % (i), i)
+ if apple:
+ self.check_register_unsigned(gpr, 'fp', 0x08)
+ else:
+ self.check_register_unsigned(gpr, 'fp', 0x0c)
+ self.check_register_unsigned(gpr, 'lr', 0x0f)
+ self.check_register_unsigned(gpr, 'sp', 0x0e)
+ self.check_register_unsigned(gpr, 'pc', 0x10)
+ self.check_register_unsigned(gpr, 'cpsr', 0x11223344)
+
+ # Verify the FPR registers are all correct
+ fpr = registers.GetValueAtIndex(1)
+ # Check d0 - d31
+ self.check_register_unsigned(gpr, 'fpscr', 0x55667788aabbccdd)
+ for i in range(32):
+ value = (i+1) | (i+1) << 8 | (i+1) << 32 | (i+1) << 48
+ self.check_register_unsigned(fpr, "d%i" % (i), value)
+ # Check s0 - s31
+ for i in range(32):
+ i_val = (i >> 1) + 1
+ if i & 1:
+ value = "%#8.8x" % (i_val | i_val << 16)
+ else:
+ value = "%#8.8x" % (i_val | i_val << 8)
+ self.check_register_string_value(fpr, "s%i" % (i), value,
+ lldb.eFormatHex)
+ # Check q0 - q15
+ for i in range(15):
+ a = i * 2 + 1
+ b = a + 1
+ value = ("0x00%2.2x00%2.2x0000%2.2x%2.2x"
+ "00%2.2x00%2.2x0000%2.2x%2.2x") % (b, b, b, b, a, a, a, a)
+ self.check_register_string_value(fpr, "q%i" % (i), value,
+ lldb.eFormatHex)
+
+ def test_linux_arm_registers(self):
+ """Test Linux ARM registers from a breakpad created minidump.
+
+ The frame pointer is R11 for linux.
+ """
+ self.verify_arm_registers(apple=False)
+
+ def test_apple_arm_registers(self):
+ """Test Apple ARM registers from a breakpad created minidump.
+
+ The frame pointer is R7 for linux.
+ """
+ self.verify_arm_registers(apple=True)
+
def do_test_deeper_stack(self, binary, core, pid):
target = self.dbg.CreateTarget(binary)
process = target.LoadCore(core)
Index: lldb.xcodeproj/project.pbxproj
===================================================================
--- lldb.xcodeproj/project.pbxproj
+++ lldb.xcodeproj/project.pbxproj
@@ -660,6 +660,10 @@
26474CBE18D0CB2D0073DEBA /* RegisterContextMach_i386.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26474CB818D0CB2D0073DEBA /* RegisterContextMach_i386.cpp */; };
26474CC018D0CB2D0073DEBA /* RegisterContextMach_x86_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26474CBA18D0CB2D0073DEBA /* RegisterContextMach_x86_64.cpp */; };
26474CC918D0CB5B0073DEBA /* RegisterContextMemory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26474CC218D0CB5B0073DEBA /* RegisterContextMemory.cpp */; };
+ 2619C4852107A9A2009CDE81 /* RegisterContextMinidump_ARM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2619C4812107A9A1009CDE81 /* RegisterContextMinidump_ARM.cpp */; };
+ 2619C4872107A9A2009CDE81 /* RegisterContextMinidump_ARM.h in Headers */ = {isa = PBXBuildFile; fileRef = 2619C4832107A9A2009CDE81 /* RegisterContextMinidump_ARM.h */; };
+ 2619C4842107A9A2009CDE81 /* RegisterContextMinidump_ARM64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2619C4802107A9A1009CDE81 /* RegisterContextMinidump_ARM64.cpp */; };
+ 2619C4862107A9A2009CDE81 /* RegisterContextMinidump_ARM64.h in Headers */ = {isa = PBXBuildFile; fileRef = 2619C4822107A9A2009CDE81 /* RegisterContextMinidump_ARM64.h */; };
947CF7761DC7B20D00EF980B /* RegisterContextMinidump_x86_32.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 947CF7741DC7B20D00EF980B /* RegisterContextMinidump_x86_32.cpp */; };
AFD65C811D9B5B2E00D93120 /* RegisterContextMinidump_x86_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFD65C7F1D9B5B2E00D93120 /* RegisterContextMinidump_x86_64.cpp */; };
AFD65C821D9B5B2E00D93120 /* RegisterContextMinidump_x86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = AFD65C801D9B5B2E00D93120 /* RegisterContextMinidump_x86_64.h */; };
@@ -2533,6 +2537,10 @@
26474CC218D0CB5B0073DEBA /* RegisterContextMemory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextMemory.cpp; path = Utility/RegisterContextMemory.cpp; sourceTree = "<group>"; };
262D24E513FB8710002D1960 /* RegisterContextMemory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextMemory.h; path = Utility/RegisterContextMemory.h; sourceTree = "<group>"; };
26474CC318D0CB5B0073DEBA /* RegisterContextMemory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextMemory.h; path = Utility/RegisterContextMemory.h; sourceTree = "<group>"; };
+ 2619C4812107A9A1009CDE81 /* RegisterContextMinidump_ARM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterContextMinidump_ARM.cpp; sourceTree = "<group>"; };
+ 2619C4832107A9A2009CDE81 /* RegisterContextMinidump_ARM.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterContextMinidump_ARM.h; sourceTree = "<group>"; };
+ 2619C4802107A9A1009CDE81 /* RegisterContextMinidump_ARM64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterContextMinidump_ARM64.cpp; sourceTree = "<group>"; };
+ 2619C4822107A9A2009CDE81 /* RegisterContextMinidump_ARM64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterContextMinidump_ARM64.h; sourceTree = "<group>"; };
947CF7741DC7B20D00EF980B /* RegisterContextMinidump_x86_32.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterContextMinidump_x86_32.cpp; sourceTree = "<group>"; };
947CF7721DC7B20300EF980B /* RegisterContextMinidump_x86_32.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RegisterContextMinidump_x86_32.h; sourceTree = "<group>"; };
AFD65C7F1D9B5B2E00D93120 /* RegisterContextMinidump_x86_64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterContextMinidump_x86_64.cpp; sourceTree = "<group>"; };
@@ -3777,6 +3785,10 @@
23E2E5351D9048E7006F38BB /* minidump */ = {
isa = PBXGroup;
children = (
+ 2619C4812107A9A1009CDE81 /* RegisterContextMinidump_ARM.cpp */,
+ 2619C4832107A9A2009CDE81 /* RegisterContextMinidump_ARM.h */,
+ 2619C4802107A9A1009CDE81 /* RegisterContextMinidump_ARM64.cpp */,
+ 2619C4822107A9A2009CDE81 /* RegisterContextMinidump_ARM64.h */,
AFD65C7F1D9B5B2E00D93120 /* RegisterContextMinidump_x86_64.cpp */,
AFD65C801D9B5B2E00D93120 /* RegisterContextMinidump_x86_64.h */,
23E2E5361D9048FB006F38BB /* CMakeLists.txt */,
@@ -6926,8 +6938,10 @@
AF6CA6681FBBAF37005A0DC3 /* ArchSpec.h in Headers */,
AF235EB41FBE7858009C5541 /* RegisterInfoPOSIX_ppc64le.h in Headers */,
AF2E02A41FA2CEAF00A86C34 /* ArchitectureArm.h in Headers */,
+ 2619C4872107A9A2009CDE81 /* RegisterContextMinidump_ARM.h in Headers */,
267F685A1CC02EBE0086832B /* RegisterInfos_s390x.h in Headers */,
267F68541CC02E920086832B /* RegisterContextLinux_s390x.h in Headers */,
+ 2619C4862107A9A2009CDE81 /* RegisterContextMinidump_ARM64.h in Headers */,
AF235EB11FBE77B6009C5541 /* RegisterContextPOSIX_ppc64le.h in Headers */,
267F68501CC02E270086832B /* RegisterContextPOSIXCore_s390x.h in Headers */,
4984BA181B979C08008658D4 /* ExpressionVariable.h in Headers */,
@@ -7629,6 +7643,7 @@
2689002113353DDE00698AC0 /* CommandObjectQuit.cpp in Sources */,
2689002213353DDE00698AC0 /* CommandObjectRegister.cpp in Sources */,
26BC17AF18C7F4CB00D2196D /* RegisterContextPOSIXCore_x86_64.cpp in Sources */,
+ 2619C4842107A9A2009CDE81 /* RegisterContextMinidump_ARM64.cpp in Sources */,
2689002313353DDE00698AC0 /* CommandObjectScript.cpp in Sources */,
2689002413353DDE00698AC0 /* CommandObjectSettings.cpp in Sources */,
2689002513353DDE00698AC0 /* CommandObjectSource.cpp in Sources */,
@@ -7709,6 +7724,7 @@
2689005113353E0400698AC0 /* StringList.cpp in Sources */,
2689005213353E0400698AC0 /* Timer.cpp in Sources */,
2689005413353E0400698AC0 /* UserSettingsController.cpp in Sources */,
+ 2619C4852107A9A2009CDE81 /* RegisterContextMinidump_ARM.cpp in Sources */,
23059A0719532B96007B8189 /* LinuxSignals.cpp in Sources */,
8CCB017E19BA28A80009FD44 /* ThreadCollection.cpp in Sources */,
9A77AD541E64E2760025CE04 /* RegisterInfoPOSIX_arm.cpp in Sources */,
Index: include/lldb/Target/Target.h
===================================================================
--- include/lldb/Target/Target.h
+++ include/lldb/Target/Target.h
@@ -913,28 +913,30 @@
/// Set the architecture for this target.
///
/// If the current target has no Images read in, then this just sets the
- /// architecture, which will
- /// be used to select the architecture of the ExecutableModule when that is
- /// set.
- /// If the current target has an ExecutableModule, then calling
- /// SetArchitecture with a different
+ /// architecture, which will be used to select the architecture of the
+ /// ExecutableModule when that is set. If the current target has an
+ /// ExecutableModule, then calling SetArchitecture with a different
/// architecture from the currently selected one will reset the
- /// ExecutableModule to that slice
- /// of the file backing the ExecutableModule. If the file backing the
- /// ExecutableModule does not
- /// contain a fork of this architecture, then this code will return false, and
- /// the architecture
- /// won't be changed.
- /// If the input arch_spec is the same as the already set architecture, this
- /// is a no-op.
+ /// ExecutableModule to that slice of the file backing the ExecutableModule.
+ /// If the file backing the ExecutableModule does not contain a fork of this
+ /// architecture, then this code will return false, and the architecture
+ /// won't be changed. If the input arch_spec is the same as the already set
+ /// architecture, this is a no-op.
///
/// @param[in] arch_spec
/// The new architecture.
///
+ /// @param[in] adjust_platform
+ /// If \b true, then the platform will be adjusted if the currently
+ /// selected platform is not compatible with the archicture being set.
+ /// If \b false, then just the architecture will be set even if the
+ /// currently selected platform isn't compatible (in case it might be
+ /// manually set following this function call).
+ ///
/// @return
/// \b true if the architecture was successfully set, \bfalse otherwise.
//------------------------------------------------------------------
- bool SetArchitecture(const ArchSpec &arch_spec);
+ bool SetArchitecture(const ArchSpec &arch_spec, bool set_platform = false);
bool MergeArchitecture(const ArchSpec &arch_spec);
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits