andrew updated this revision to Diff 427010.
andrew added a comment.
Remove a stray change
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D120485/new/
https://reviews.llvm.org/D120485
Files:
lldb/source/Plugins/ABI/AArch64/ABISysV_arm64.cpp
lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp
lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.h
lldb/source/Plugins/Process/elf-core/RegisterUtilities.h
lldb/test/API/functionalities/unwind/aarch64_unwind_pac/TestAArch64UnwindPAC.py
lldb/test/API/functionalities/unwind/aarch64_unwind_pac/main.c
Index: lldb/test/API/functionalities/unwind/aarch64_unwind_pac/main.c
===================================================================
--- lldb/test/API/functionalities/unwind/aarch64_unwind_pac/main.c
+++ lldb/test/API/functionalities/unwind/aarch64_unwind_pac/main.c
@@ -4,8 +4,32 @@
// To enable PAC return address signing compile with following clang arguments:
// -march=armv8.3-a -mbranch-protection=pac-ret+leaf
+#include <stdbool.h>
#include <stdlib.h>
+#if defined(__FreeBSD__)
+#include <sys/auxv.h>
+
+// Added in FreeBSD 12.2, can be removed when all supported branches define it.
+#if !defined(HWCAP_PACA)
+#define HWCAP_PACA 0x40000000
+#endif
+
+static bool pac_supported(void) {
+ unsigned long hwcap;
+
+ if (elf_aux_info(AT_HWCAP, &hwcap, sizeof(hwcap)) != 0)
+ return false;
+
+ return (hwcap & HWCAP_PACA) != 0;
+}
+#else
+static bool pac_supported(void) {
+ // We expect Linux to check for PAC up front using /proc/cpuinfo.
+ return true;
+}
+#endif
+
static void __attribute__((noinline)) func_c(void) {
exit(0); // Frame func_c
}
@@ -19,6 +43,9 @@
}
int main(int argc, char *argv[]) {
+ if (!pac_supported())
+ return 1;
+
func_a(); // Frame main
return 0;
}
Index: lldb/test/API/functionalities/unwind/aarch64_unwind_pac/TestAArch64UnwindPAC.py
===================================================================
--- lldb/test/API/functionalities/unwind/aarch64_unwind_pac/TestAArch64UnwindPAC.py
+++ lldb/test/API/functionalities/unwind/aarch64_unwind_pac/TestAArch64UnwindPAC.py
@@ -6,28 +6,26 @@
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
+import re
class AArch64UnwindPAC(TestBase):
mydir = TestBase.compute_mydir(__file__)
- @skipIf(archs=no_match(["aarch64"]))
- @skipIf(oslist=no_match(['linux']))
- def test(self):
- """Test that we can backtrace correctly when AArch64 PAC is enabled"""
- if not self.isAArch64PAuth():
- self.skipTest('Target must support Pointer Authentication.')
-
+ def common(self, backtrace_tail):
self.build()
self.line = line_number('main.c', '// Frame func_c')
exe = self.getBuildArtifact("a.out")
self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
-
lldbutil.run_break_set_by_file_and_line(
self, "main.c", self.line, num_expected_locations=1)
self.runCmd("run", RUN_SUCCEEDED)
+ if re.match('Process .* exited with status = 1[^0-9]', self.res.GetOutput()):
+ # No PAC support
+ self.skipTest('Target must support Pointer Authentication.')
+
self.expect("thread backtrace", STOPPED_DUE_TO_BREAKPOINT,
substrs=["stop reason = breakpoint 1."])
@@ -35,13 +33,33 @@
process = target.GetProcess()
thread = process.GetThreadAtIndex(0)
- backtrace = ["func_c", "func_b", "func_a", "main", "__libc_start_main", "_start"]
- self.assertEqual(thread.GetNumFrames(), len(backtrace))
+ backtrace = ["func_c", "func_b", "func_a", "main"] + backtrace_tail
for frame_idx, frame in enumerate(thread.frames):
frame = thread.GetFrameAtIndex(frame_idx)
+ # On FreeBSD we get ___lldb_unnamed_symbol symbols at the bottom
+ # of the stack. Ignore these and assume we have walked the entire
+ # stack, however check this assumption is correct.
+ if frame.GetFunctionName().startswith("___lldb_unnamed_symbol"):
+ self.assertEqual(len(backtrace), frame_idx)
+ break
self.assertTrue(frame)
self.assertEqual(frame.GetFunctionName(), backtrace[frame_idx])
# Check line number for functions in main.c
if (frame_idx < 4):
self.assertEqual(frame.GetLineEntry().GetLine(),
line_number("main.c", "Frame " + backtrace[frame_idx]))
+
+ @skipIf(archs=no_match(["aarch64"]))
+ @skipIf(oslist=no_match(['freebsd']))
+ def test_freebsd(self):
+ """Test that we can backtrace correctly when AArch64 PAC is enabled"""
+ self.common(["__start"])
+
+ @skipIf(archs=no_match(["aarch64"]))
+ @skipIf(oslist=no_match(['linux']))
+ def test_linux(self):
+ """Test that we can backtrace correctly when AArch64 PAC is enabled"""
+ if not self.isAArch64PAuth():
+ self.skipTest('Target must support Pointer Authentication.')
+
+ self.common(["__libc_start_main", "_start"])
Index: lldb/source/Plugins/Process/elf-core/RegisterUtilities.h
===================================================================
--- lldb/source/Plugins/Process/elf-core/RegisterUtilities.h
+++ lldb/source/Plugins/Process/elf-core/RegisterUtilities.h
@@ -120,6 +120,7 @@
};
constexpr RegsetDesc AARCH64_PAC_Desc[] = {
+ {llvm::Triple::FreeBSD, llvm::Triple::aarch64, llvm::ELF::NT_ARM_PAC_MASK},
{llvm::Triple::Linux, llvm::Triple::aarch64, llvm::ELF::NT_ARM_PAC_MASK},
};
Index: lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.h
===================================================================
--- lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.h
+++ lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.h
@@ -36,8 +36,10 @@
: public NativeRegisterContextFreeBSD,
public NativeRegisterContextDBReg_arm64 {
public:
- NativeRegisterContextFreeBSD_arm64(const ArchSpec &target_arch,
- NativeThreadProtocol &native_thread);
+ NativeRegisterContextFreeBSD_arm64(
+ const ArchSpec &target_arch,
+ NativeThreadProtocol &native_thread,
+ std::unique_ptr<RegisterInfoPOSIX_arm64> register_info_up);
uint32_t GetRegisterSetCount() const override;
@@ -65,6 +67,15 @@
// a unittest to assert that).
std::array<uint8_t, sizeof(reg)> m_reg_data;
std::array<uint8_t, sizeof(fpreg)> m_fpreg_data;
+
+ struct arm64_addr_mask {
+ uint64_t data_mask;
+ uint64_t insn_mask;
+ };
+
+ bool m_addr_mask_is_valid;
+ struct arm64_addr_mask m_addr_mask;
+
#ifdef LLDB_HAS_FREEBSD_WATCHPOINT
dbreg m_dbreg;
bool m_read_dbreg;
@@ -76,16 +87,22 @@
void *GetFPRBuffer() { return &m_fpreg_data; }
size_t GetFPRSize() { return sizeof(m_fpreg_data); }
+ void *GetAddrMaskBuffer() { return &m_addr_mask; }
+ size_t GetAddrMaskBufferSize() { return sizeof(m_addr_mask); }
+
bool IsGPR(unsigned reg) const;
bool IsFPR(unsigned reg) const;
+ bool IsAddrMask(unsigned reg) const;
Status ReadGPR();
Status WriteGPR();
+ Status ReadAddrMask();
Status ReadFPR();
Status WriteFPR();
uint32_t CalculateFprOffset(const RegisterInfo *reg_info) const;
+ uint32_t CalculateAddrMaskOffset(const RegisterInfo *reg_info) const;
llvm::Error ReadHardwareDebugInfo() override;
llvm::Error WriteHardwareDebugRegs(DREGType hwbType) override;
Index: lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp
===================================================================
--- lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp
+++ lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp
@@ -19,9 +19,11 @@
#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
// clang-format off
+#include <sys/elf.h>
#include <sys/param.h>
#include <sys/ptrace.h>
#include <sys/types.h>
+#include <sys/uio.h>
// clang-format on
#define REG_CONTEXT_SIZE (GetGPRSize() + GetFPRSize())
@@ -33,13 +35,19 @@
NativeRegisterContextFreeBSD *
NativeRegisterContextFreeBSD::CreateHostNativeRegisterContextFreeBSD(
const ArchSpec &target_arch, NativeThreadProtocol &native_thread) {
- return new NativeRegisterContextFreeBSD_arm64(target_arch, native_thread);
+ Flags opt_regsets;
+ opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskPAuth);
+ auto register_info_up =
+ std::make_unique<RegisterInfoPOSIX_arm64>(target_arch, opt_regsets);
+ return new NativeRegisterContextFreeBSD_arm64(target_arch, native_thread,
+ std::move(register_info_up));
}
NativeRegisterContextFreeBSD_arm64::NativeRegisterContextFreeBSD_arm64(
- const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
- : NativeRegisterContextRegisterInfo(
- native_thread, new RegisterInfoPOSIX_arm64(target_arch, 0))
+ const ArchSpec &target_arch, NativeThreadProtocol &native_thread,
+ std::unique_ptr<RegisterInfoPOSIX_arm64> register_info_up)
+ : NativeRegisterContextRegisterInfo(native_thread,
+ register_info_up.release())
#ifdef LLDB_HAS_FREEBSD_WATCHPOINT
,
m_read_dbreg(false)
@@ -47,6 +55,9 @@
{
::memset(&m_hwp_regs, 0, sizeof(m_hwp_regs));
::memset(&m_hbp_regs, 0, sizeof(m_hbp_regs));
+ ::memset(&m_addr_mask, 0, sizeof(m_addr_mask));
+
+ m_addr_mask_is_valid = false;
}
RegisterInfoPOSIX_arm64 &
@@ -84,6 +95,12 @@
return false;
}
+bool NativeRegisterContextFreeBSD_arm64::IsAddrMask(unsigned reg) const {
+ // Reuse the Linux PAuth mask register for now. On FreeBSD it can be
+ // used when PAC isn't available, e.g. with TBI.
+ return GetRegisterInfo().IsPAuthReg(reg);
+}
+
Status NativeRegisterContextFreeBSD_arm64::ReadGPR() {
return NativeProcessFreeBSD::PtraceWrapper(
PT_GETREGS, m_thread.GetID(), m_reg_data.data());
@@ -104,11 +121,37 @@
PT_SETFPREGS, m_thread.GetID(), m_fpreg_data.data());
}
+Status NativeRegisterContextFreeBSD_arm64::ReadAddrMask() {
+ Status error;
+
+#ifdef NT_ARM_ADDR_MASK
+ if (m_addr_mask_is_valid)
+ return error;
+
+ struct iovec ioVec;
+ ioVec.iov_base = GetAddrMaskBuffer();
+ ioVec.iov_len = GetAddrMaskBufferSize();
+
+ error = NativeProcessFreeBSD::PtraceWrapper(
+ PT_GETREGSET, m_thread.GetID(), &ioVec, NT_ARM_ADDR_MASK);
+
+ if (error.Success())
+ m_addr_mask_is_valid = true;
+#endif
+
+ return error;
+}
+
uint32_t NativeRegisterContextFreeBSD_arm64::CalculateFprOffset(
const RegisterInfo *reg_info) const {
return reg_info->byte_offset - GetGPRSize();
}
+uint32_t NativeRegisterContextFreeBSD_arm64::CalculateAddrMaskOffset(
+ const RegisterInfo *reg_info) const {
+ return reg_info->byte_offset - GetRegisterInfo().GetPAuthOffset();
+}
+
Status
NativeRegisterContextFreeBSD_arm64::ReadRegister(const RegisterInfo *reg_info,
RegisterValue ®_value) {
@@ -145,6 +188,14 @@
offset = CalculateFprOffset(reg_info);
assert(offset < GetFPRSize());
src = (uint8_t *)GetFPRBuffer() + offset;
+ } else if (IsAddrMask(reg)) {
+ error = ReadAddrMask();
+ if (error.Fail())
+ return error;
+
+ offset = CalculateAddrMaskOffset(reg_info);
+ assert(offset < GetAddrMaskBufferSize());
+ src = (uint8_t *)GetAddrMaskBuffer() + offset;
} else
return Status("Failed to read register value");
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
@@ -791,6 +791,31 @@
return (pc & pac_sign_extension) ? pc | mask : pc & (~mask);
}
+// Reads code or data address mask for the current Linux process.
+static lldb::addr_t ReadFreeBSDProcessAddressMask(lldb::ProcessSP process_sp,
+ llvm::StringRef reg_name) {
+ uint64_t address_mask = 0;
+
+ // If Pointer Authentication feature is enabled then FreeBSD 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;
+}
+
// Reads code or data address mask for the current Linux process.
static lldb::addr_t ReadLinuxProcessAddressMask(lldb::ProcessSP process_sp,
llvm::StringRef reg_name) {
@@ -823,6 +848,10 @@
!process_sp->GetCodeAddressMask())
process_sp->SetCodeAddressMask(
ReadLinuxProcessAddressMask(process_sp, "code_mask"));
+ else if (process_sp->GetTarget().GetArchitecture().GetTriple().isOSFreeBSD() &&
+ !process_sp->GetCodeAddressMask())
+ process_sp->SetCodeAddressMask(
+ ReadFreeBSDProcessAddressMask(process_sp, "code_mask"));
return FixAddress(pc, process_sp->GetCodeAddressMask());
}
@@ -835,6 +864,10 @@
!process_sp->GetDataAddressMask())
process_sp->SetDataAddressMask(
ReadLinuxProcessAddressMask(process_sp, "data_mask"));
+ else if (process_sp->GetTarget().GetArchitecture().GetTriple().isOSFreeBSD() &&
+ !process_sp->GetDataAddressMask())
+ process_sp->SetDataAddressMask(
+ ReadFreeBSDProcessAddressMask(process_sp, "data_mask"));
return FixAddress(pc, process_sp->GetDataAddressMask());
}
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits