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); 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 = ""; }; 262D24E513FB8710002D1960 /* RegisterContextMemory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextMemory.h; path = Utility/RegisterContextMemory.h; sourceTree = ""; }; 26474CC318D0CB5B0073DEBA /* RegisterContextMemory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextMemory.h; path = Utility/RegisterContextMemory.h; sourceTree = ""; }; + 2619C4812107A9A1009CDE81 /* RegisterContextMinidump_ARM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterContextMinidump_ARM.cpp; sourceTree = ""; }; + 2619C4832107A9A2009CDE81 /* RegisterContextMinidump_ARM.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterContextMinidump_ARM.h; sourceTree = ""; }; + 2619C4802107A9A1009CDE81 /* RegisterContextMinidump_ARM64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterContextMinidump_ARM64.cpp; sourceTree = ""; }; + 2619C4822107A9A2009CDE81 /* RegisterContextMinidump_ARM64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterContextMinidump_ARM64.h; sourceTree = ""; }; 947CF7741DC7B20D00EF980B /* RegisterContextMinidump_x86_32.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterContextMinidump_x86_32.cpp; sourceTree = ""; }; 947CF7721DC7B20300EF980B /* RegisterContextMinidump_x86_32.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RegisterContextMinidump_x86_32.h; sourceTree = ""; }; AFD65C7F1D9B5B2E00D93120 /* RegisterContextMinidump_x86_64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterContextMinidump_x86_64.cpp; sourceTree = ""; }; @@ -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,11 @@ 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 */, + 2619C48B2107ABDD009CDE81 /* DumpRegisterValue.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 +7644,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 +7725,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 */, @@ -8051,6 +8068,7 @@ 267C01371368C49C006E963E /* OptionGroupOutputFile.cpp in Sources */, 260E07C6136FA69E00CF21D3 /* OptionGroupUUID.cpp in Sources */, AFC2DCF91E6E318000283714 /* StreamGDBRemote.cpp in Sources */, + 2619C4892107ABD4009CDE81 /* DumpRegisterValue.cpp in Sources */, 260E07C8136FAB9200CF21D3 /* OptionGroupFile.cpp in Sources */, 2686536C1370ACB200D186A3 /* OptionGroupBoolean.cpp in Sources */, 268653701370AE7200D186A3 /* OptionGroupUInt64.cpp in Sources */, 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: 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 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( - static_cast(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( - static_cast(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( + static_cast(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( + static_cast(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: source/Plugins/Process/minidump/ProcessMinidump.cpp =================================================================== --- source/Plugins/Process/minidump/ProcessMinidump.cpp +++ source/Plugins/Process/minidump/ProcessMinidump.cpp @@ -12,6 +12,7 @@ #include "ThreadMinidump.h" // Other libraries and framework includes +//#include "lldb/Core/Architecture.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" @@ -29,6 +30,7 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Threading.h" +#include "Plugins/Process/Utility/StopInfoMachException.h" // C includes // C++ includes @@ -174,19 +176,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 pid = m_minidump_parser.GetPid(); if (!pid) { @@ -229,6 +233,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/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 + +// 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; ibyte_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 + +// 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; iPrintf("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/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());