andrew created this revision.
andrew added a reviewer: mgorny.
Herald added subscribers: kristof.beyls, krytarowski, arichardson.
andrew requested review of this revision.
Herald added a project: LLDB.
Herald added a subscriber: lldb-commits.
Read the mask using ptrace with PT_GETREGSET with NT_ARM_ADDR_MASK
for live processes, or from the NT_ARM_ADDR_MASK note in a core
file.
As NT_ARM_ADDR_MASK is on FreeBSD is the same value as NT_ARM_PAC_MASK
and it contains a structure with the same layout and a superset of the
same data use this when reading a core file.
Repository:
rG LLVM Github Monorepo
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
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,13 @@
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 +122,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 +189,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
@@ -788,6 +788,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) {
@@ -820,6 +845,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());
}
@@ -832,6 +861,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