Index: lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.h =================================================================== --- lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.h +++ lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.h @@ -85,6 +85,9 @@ uint32_t GetPluginVersion() override; + lldb::addr_t FixCodeAddress(lldb::addr_t pc) override; + lldb::addr_t FixDataAddress(lldb::addr_t pc) override; + protected: lldb::ValueObjectSP GetReturnValueObjectImpl(lldb_private::Thread &thread, Index: lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp =================================================================== --- lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp +++ lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp @@ -787,6 +787,56 @@ return (pc & pac_sign_extension) ? pc | mask : pc & (~mask); } +// Reads code or data address mask for the current Linux process. +static lldb::addr_t ReadLinuxProcessAddressMask(lldb::ProcessSP process_sp, + llvm::StringRef reg_name) { + // Linux configures user-space virtual addresses with top byte ignored. + // We set default value of mask such that top byte is masked out. + uint64_t address_mask = ~((1ULL << 56) - 1); + // If Pointer Authentication feature is enabled then Linux exposes + // PAC data and code mask register. Try reading relevant register + // below and merge it with default address mask calculated above. + lldb::ThreadSP thread_sp = process_sp->GetThreadList().GetSelectedThread(); + if (thread_sp) { + lldb::RegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext(); + if (reg_ctx_sp) { + const RegisterInfo *reg_info = + reg_ctx_sp->GetRegisterInfoByName(reg_name, 0); + if (reg_info) { + lldb::addr_t mask_reg_val = reg_ctx_sp->ReadRegisterAsUnsigned( + reg_info->kinds[eRegisterKindLLDB], LLDB_INVALID_ADDRESS); + if (mask_reg_val != LLDB_INVALID_ADDRESS) + address_mask |= mask_reg_val; + } + } + } + return address_mask; +} + +lldb::addr_t ABISysV_arm64::FixCodeAddress(lldb::addr_t pc) { + if (lldb::ProcessSP process_sp = GetProcessSP()) { + if (process_sp->GetTarget().GetArchitecture().GetTriple().isOSLinux() && + !process_sp->GetCodeAddressMask()) + process_sp->SetCodeAddressMask( + ReadLinuxProcessAddressMask(process_sp, "code_mask")); + + return FixAddress(pc, process_sp->GetCodeAddressMask()); + } + return pc; +} + +lldb::addr_t ABISysV_arm64::FixDataAddress(lldb::addr_t pc) { + if (lldb::ProcessSP process_sp = GetProcessSP()) { + if (process_sp->GetTarget().GetArchitecture().GetTriple().isOSLinux() && + !process_sp->GetDataAddressMask()) + process_sp->SetDataAddressMask( + ReadLinuxProcessAddressMask(process_sp, "data_mask")); + + return FixAddress(pc, process_sp->GetDataAddressMask()); + } + return pc; +} + void ABISysV_arm64::Initialize() { PluginManager::RegisterPlugin(GetPluginNameStatic(), "SysV ABI for AArch64 targets", CreateInstance); Index: lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py =================================================================== --- lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py +++ lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py @@ -20,6 +20,7 @@ mydir = TestBase.compute_mydir(__file__) _aarch64_pid = 37688 + _aarch64_pac_pid = 387 _i386_pid = 32306 _x86_64_pid = 32259 _s390x_pid = 1045 @@ -135,7 +136,7 @@ error = lldb.SBError() bytesread = process.ReadMemory(0x400ff0, 20, error) - + # read only 16 bytes without zero bytes filling self.assertEqual(len(bytesread), 16) self.dbg.DeleteTarget(target) @@ -257,6 +258,18 @@ self.dbg.DeleteTarget(target) + @skipIfLLVMTargetMissing("AArch64") + def test_aarch64_pac(self): + """Test that lldb can unwind stack for AArch64 elf core file with PAC enabled.""" + + target = self.dbg.CreateTarget("linux-aarch64-pac.out") + self.assertTrue(target, VALID_TARGET) + process = target.LoadCore("linux-aarch64-pac.core") + + self.check_all(process, self._aarch64_pac_pid, self._aarch64_regions, "a.out") + + self.dbg.DeleteTarget(target) + @skipIfLLVMTargetMissing("AArch64") @expectedFailureAll(archs=["aarch64"], oslist=["freebsd"], bugnumber="llvm.org/pr49415")