Skip to content

Commit 88a5b35

Browse files
committed
Revert "Revert "[LLDB] Arm64/Linux Add MTE and Pointer Authentication registers""
This reverts commit 71b648f. There was a typo in the last commit which was causing LLDB AArch64 Linux buildbot testsuite failures. Now fixed in current version.
1 parent 1ed53d4 commit 88a5b35

File tree

7 files changed

+251
-6
lines changed

7 files changed

+251
-6
lines changed

lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp

Lines changed: 119 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,17 @@
3333
#define NT_ARM_SVE 0x405 /* ARM Scalable Vector Extension */
3434
#endif
3535

36+
#ifndef NT_ARM_PAC_MASK
37+
#define NT_ARM_PAC_MASK 0x406 /* Pointer authentication code masks */
38+
#endif
39+
40+
#ifndef NT_ARM_TAGGED_ADDR_CTRL
41+
#define NT_ARM_TAGGED_ADDR_CTRL 0x409 /* Tagged address control register */
42+
#endif
43+
44+
#define HWCAP_PACA (1 << 30)
45+
#define HWCAP2_MTE (1 << 18)
46+
3647
#define REG_CONTEXT_SIZE (GetGPRSize() + GetFPRSize())
3748

3849
using namespace lldb;
@@ -62,6 +73,18 @@ NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
6273
.Success())
6374
opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskSVE);
6475

76+
NativeProcessLinux &process = native_thread.GetProcess();
77+
78+
llvm::Optional<uint64_t> auxv_at_hwcap =
79+
process.GetAuxValue(AuxVector::AUXV_AT_HWCAP);
80+
if (auxv_at_hwcap && (*auxv_at_hwcap & HWCAP_PACA))
81+
opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskPAuth);
82+
83+
llvm::Optional<uint64_t> auxv_at_hwcap2 =
84+
process.GetAuxValue(AuxVector::AUXV_AT_HWCAP2);
85+
if (auxv_at_hwcap2 && (*auxv_at_hwcap2 & HWCAP2_MTE))
86+
opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskMTE);
87+
6588
auto register_info_up =
6689
std::make_unique<RegisterInfoPOSIX_arm64>(target_arch, opt_regsets);
6790
return std::make_unique<NativeRegisterContextLinux_arm64>(
@@ -83,6 +106,9 @@ NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64(
83106
::memset(&m_hwp_regs, 0, sizeof(m_hwp_regs));
84107
::memset(&m_hbp_regs, 0, sizeof(m_hbp_regs));
85108
::memset(&m_sve_header, 0, sizeof(m_sve_header));
109+
::memset(&m_pac_mask, 0, sizeof(m_pac_mask));
110+
111+
m_mte_ctrl_reg = 0;
86112

87113
// 16 is just a maximum value, query hardware for actual watchpoint count
88114
m_max_hwp_supported = 16;
@@ -94,6 +120,8 @@ NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64(
94120
m_fpu_is_valid = false;
95121
m_sve_buffer_is_valid = false;
96122
m_sve_header_is_valid = false;
123+
m_pac_mask_is_valid = false;
124+
m_mte_ctrl_is_valid = false;
97125

98126
if (GetRegisterInfo().IsSVEEnabled())
99127
m_sve_state = SVEState::Unknown;
@@ -230,6 +258,22 @@ NativeRegisterContextLinux_arm64::ReadRegister(const RegisterInfo *reg_info,
230258
src = (uint8_t *)GetSVEBuffer() + offset;
231259
}
232260
}
261+
} else if (IsPAuth(reg)) {
262+
error = ReadPAuthMask();
263+
if (error.Fail())
264+
return error;
265+
266+
offset = reg_info->byte_offset - GetRegisterInfo().GetPAuthOffset();
267+
assert(offset < GetPACMaskSize());
268+
src = (uint8_t *)GetPACMask() + offset;
269+
} else if (IsMTE(reg)) {
270+
error = ReadMTEControl();
271+
if (error.Fail())
272+
return error;
273+
274+
offset = reg_info->byte_offset - GetRegisterInfo().GetMTEOffset();
275+
assert(offset < GetMTEControlSize());
276+
src = (uint8_t *)GetMTEControl() + offset;
233277
} else
234278
return Status("failed - register wasn't recognized to be a GPR or an FPR, "
235279
"write strategy unknown");
@@ -388,6 +432,17 @@ Status NativeRegisterContextLinux_arm64::WriteRegister(
388432
return WriteAllSVE();
389433
}
390434
}
435+
} else if (IsMTE(reg)) {
436+
error = ReadMTEControl();
437+
if (error.Fail())
438+
return error;
439+
440+
offset = reg_info->byte_offset - GetRegisterInfo().GetMTEOffset();
441+
assert(offset < GetMTEControlSize());
442+
dst = (uint8_t *)GetMTEControl() + offset;
443+
::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size);
444+
445+
return WriteMTEControl();
391446
}
392447

393448
return Status("Failed to write register value");
@@ -476,6 +531,14 @@ bool NativeRegisterContextLinux_arm64::IsSVE(unsigned reg) const {
476531
return GetRegisterInfo().IsSVEReg(reg);
477532
}
478533

534+
bool NativeRegisterContextLinux_arm64::IsPAuth(unsigned reg) const {
535+
return GetRegisterInfo().IsPAuthReg(reg);
536+
}
537+
538+
bool NativeRegisterContextLinux_arm64::IsMTE(unsigned reg) const {
539+
return GetRegisterInfo().IsMTEReg(reg);
540+
}
541+
479542
llvm::Error NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo() {
480543
if (!m_refresh_hwdebug_info) {
481544
return llvm::Error::success();
@@ -617,6 +680,8 @@ void NativeRegisterContextLinux_arm64::InvalidateAllRegisters() {
617680
m_fpu_is_valid = false;
618681
m_sve_buffer_is_valid = false;
619682
m_sve_header_is_valid = false;
683+
m_pac_mask_is_valid = false;
684+
m_mte_ctrl_is_valid = false;
620685

621686
// Update SVE registers in case there is change in configuration.
622687
ConfigureRegisterContext();
@@ -634,7 +699,26 @@ Status NativeRegisterContextLinux_arm64::ReadSVEHeader() {
634699

635700
error = ReadRegisterSet(&ioVec, GetSVEHeaderSize(), NT_ARM_SVE);
636701

637-
m_sve_header_is_valid = true;
702+
if (error.Success())
703+
m_sve_header_is_valid = true;
704+
705+
return error;
706+
}
707+
708+
Status NativeRegisterContextLinux_arm64::ReadPAuthMask() {
709+
Status error;
710+
711+
if (m_pac_mask_is_valid)
712+
return error;
713+
714+
struct iovec ioVec;
715+
ioVec.iov_base = GetPACMask();
716+
ioVec.iov_len = GetPACMaskSize();
717+
718+
error = ReadRegisterSet(&ioVec, GetPACMaskSize(), NT_ARM_PAC_MASK);
719+
720+
if (error.Success())
721+
m_pac_mask_is_valid = true;
638722

639723
return error;
640724
}
@@ -694,6 +778,40 @@ Status NativeRegisterContextLinux_arm64::WriteAllSVE() {
694778
return WriteRegisterSet(&ioVec, GetSVEBufferSize(), NT_ARM_SVE);
695779
}
696780

781+
Status NativeRegisterContextLinux_arm64::ReadMTEControl() {
782+
Status error;
783+
784+
if (m_mte_ctrl_is_valid)
785+
return error;
786+
787+
struct iovec ioVec;
788+
ioVec.iov_base = GetMTEControl();
789+
ioVec.iov_len = GetMTEControlSize();
790+
791+
error = ReadRegisterSet(&ioVec, GetMTEControlSize(), NT_ARM_TAGGED_ADDR_CTRL);
792+
793+
if (error.Success())
794+
m_mte_ctrl_is_valid = true;
795+
796+
return error;
797+
}
798+
799+
Status NativeRegisterContextLinux_arm64::WriteMTEControl() {
800+
Status error;
801+
802+
error = ReadMTEControl();
803+
if (error.Fail())
804+
return error;
805+
806+
struct iovec ioVec;
807+
ioVec.iov_base = GetMTEControl();
808+
ioVec.iov_len = GetMTEControlSize();
809+
810+
m_mte_ctrl_is_valid = false;
811+
812+
return WriteRegisterSet(&ioVec, GetMTEControlSize(), NT_ARM_TAGGED_ADDR_CTRL);
813+
}
814+
697815
void NativeRegisterContextLinux_arm64::ConfigureRegisterContext() {
698816
// ConfigureRegisterContext gets called from InvalidateAllRegisters
699817
// on every stop and configures SVE vector length.

lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,10 @@ class NativeRegisterContextLinux_arm64
7676
bool m_gpr_is_valid;
7777
bool m_fpu_is_valid;
7878
bool m_sve_buffer_is_valid;
79+
bool m_mte_ctrl_is_valid;
7980

8081
bool m_sve_header_is_valid;
82+
bool m_pac_mask_is_valid;
8183

8284
struct user_pt_regs m_gpr_arm64; // 64-bit general purpose registers.
8385

@@ -90,6 +92,15 @@ class NativeRegisterContextLinux_arm64
9092

9193
bool m_refresh_hwdebug_info;
9294

95+
struct user_pac_mask {
96+
uint64_t data_mask;
97+
uint64_t insn_mask;
98+
};
99+
100+
struct user_pac_mask m_pac_mask;
101+
102+
uint64_t m_mte_ctrl_reg;
103+
93104
bool IsGPR(unsigned reg) const;
94105

95106
bool IsFPR(unsigned reg) const;
@@ -102,20 +113,36 @@ class NativeRegisterContextLinux_arm64
102113

103114
Status WriteSVEHeader();
104115

116+
Status ReadPAuthMask();
117+
118+
Status ReadMTEControl();
119+
120+
Status WriteMTEControl();
121+
105122
bool IsSVE(unsigned reg) const;
123+
bool IsPAuth(unsigned reg) const;
124+
bool IsMTE(unsigned reg) const;
106125

107126
uint64_t GetSVERegVG() { return m_sve_header.vl / 8; }
108127

109128
void SetSVERegVG(uint64_t vg) { m_sve_header.vl = vg * 8; }
110129

111130
void *GetSVEHeader() { return &m_sve_header; }
112131

132+
void *GetPACMask() { return &m_pac_mask; }
133+
134+
void *GetMTEControl() { return &m_mte_ctrl_reg; }
135+
113136
void *GetSVEBuffer();
114137

115138
size_t GetSVEHeaderSize() { return sizeof(m_sve_header); }
116139

140+
size_t GetPACMaskSize() { return sizeof(m_pac_mask); }
141+
117142
size_t GetSVEBufferSize() { return m_sve_ptrace_payload.size(); }
118143

144+
size_t GetMTEControlSize() { return sizeof(m_mte_ctrl_reg); }
145+
119146
llvm::Error ReadHardwareDebugInfo() override;
120147

121148
llvm::Error WriteHardwareDebugRegs(DREGType hwbType) override;

lldb/source/Plugins/Process/Linux/NativeThreadLinux.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ class NativeThreadLinux : public NativeThreadProtocol {
5353

5454
Status RemoveHardwareBreakpoint(lldb::addr_t addr) override;
5555

56+
NativeProcessLinux &GetProcess();
57+
5658
private:
5759
// Interface for friend classes
5860

@@ -94,8 +96,6 @@ class NativeThreadLinux : public NativeThreadProtocol {
9496
// Private interface
9597
void MaybeLogStateChange(lldb::StateType new_state);
9698

97-
NativeProcessLinux &GetProcess();
98-
9999
void SetStopped();
100100

101101
// Member Variables

lldb/source/Plugins/Process/POSIX/NativeProcessELF.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ namespace lldb_private {
2121
class NativeProcessELF : public NativeProcessProtocol {
2222
using NativeProcessProtocol::NativeProcessProtocol;
2323

24+
public:
25+
llvm::Optional<uint64_t> GetAuxValue(enum AuxVector::EntryType type);
26+
2427
protected:
2528
template <typename T> struct ELFLinkMap {
2629
T l_addr;
@@ -30,8 +33,6 @@ class NativeProcessELF : public NativeProcessProtocol {
3033
T l_prev;
3134
};
3235

33-
llvm::Optional<uint64_t> GetAuxValue(enum AuxVector::EntryType type);
34-
3536
lldb::addr_t GetSharedLibraryInfoAddress() override;
3637

3738
template <typename ELF_EHDR, typename ELF_PHDR, typename ELF_DYN>

lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ enum {
7777
k_num_gpr_registers = gpr_w28 - gpr_x0 + 1,
7878
k_num_fpr_registers = fpu_fpcr - fpu_v0 + 1,
7979
k_num_sve_registers = sve_ffr - sve_vg + 1,
80+
k_num_mte_register = 1,
81+
k_num_pauth_register = 2,
8082
k_num_register_sets_default = 2,
8183
k_num_register_sets = 3
8284
};
@@ -175,6 +177,12 @@ static const lldb_private::RegisterSet g_reg_sets_arm64[k_num_register_sets] = {
175177
{"Scalable Vector Extension Registers", "sve", k_num_sve_registers,
176178
g_sve_regnums_arm64}};
177179

180+
static const lldb_private::RegisterSet g_reg_set_pauth_arm64 = {
181+
"Pointer Authentication Registers", "pauth", k_num_pauth_register, NULL};
182+
183+
static const lldb_private::RegisterSet g_reg_set_mte_arm64 = {
184+
"MTE Control Register", "mte", k_num_mte_register, NULL};
185+
178186
RegisterInfoPOSIX_arm64::RegisterInfoPOSIX_arm64(
179187
const lldb_private::ArchSpec &target_arch, lldb_private::Flags opt_regsets)
180188
: lldb_private::RegisterInfoAndSetInterface(target_arch),
@@ -209,6 +217,12 @@ RegisterInfoPOSIX_arm64::RegisterInfoPOSIX_arm64(
209217
llvm::copy(reg_infos_ref, std::back_inserter(m_dynamic_reg_infos));
210218
llvm::copy(reg_sets_ref, std::back_inserter(m_dynamic_reg_sets));
211219

220+
if (m_opt_regsets.AllSet(eRegsetMaskPAuth))
221+
AddRegSetPAuth();
222+
223+
if (m_opt_regsets.AllSet(eRegsetMaskMTE))
224+
AddRegSetMTE();
225+
212226
m_register_info_count = m_dynamic_reg_infos.size();
213227
m_register_info_p = m_dynamic_reg_infos.data();
214228
m_register_set_p = m_dynamic_reg_sets.data();
@@ -259,6 +273,39 @@ RegisterInfoPOSIX_arm64::GetRegisterSet(size_t set_index) const {
259273
return nullptr;
260274
}
261275

276+
void RegisterInfoPOSIX_arm64::AddRegSetPAuth() {
277+
uint32_t pa_regnum = m_dynamic_reg_infos.size();
278+
for (uint32_t i = 0; i < k_num_pauth_register; i++) {
279+
pauth_regnum_collection.push_back(pa_regnum + i);
280+
m_dynamic_reg_infos.push_back(g_register_infos_pauth[i]);
281+
m_dynamic_reg_infos[pa_regnum + i].byte_offset =
282+
m_dynamic_reg_infos[pa_regnum + i - 1].byte_offset +
283+
m_dynamic_reg_infos[pa_regnum + i - 1].byte_size;
284+
m_dynamic_reg_infos[pa_regnum + i].kinds[lldb::eRegisterKindLLDB] =
285+
pa_regnum + i;
286+
}
287+
288+
m_per_regset_regnum_range[m_register_set_count] =
289+
std::make_pair(pa_regnum, m_dynamic_reg_infos.size());
290+
m_dynamic_reg_sets.push_back(g_reg_set_pauth_arm64);
291+
m_dynamic_reg_sets.back().registers = pauth_regnum_collection.data();
292+
}
293+
294+
void RegisterInfoPOSIX_arm64::AddRegSetMTE() {
295+
uint32_t mte_regnum = m_dynamic_reg_infos.size();
296+
m_mte_regnum_collection.push_back(mte_regnum);
297+
m_dynamic_reg_infos.push_back(g_register_infos_mte[0]);
298+
m_dynamic_reg_infos[mte_regnum].byte_offset =
299+
m_dynamic_reg_infos[mte_regnum - 1].byte_offset +
300+
m_dynamic_reg_infos[mte_regnum - 1].byte_size;
301+
m_dynamic_reg_infos[mte_regnum].kinds[lldb::eRegisterKindLLDB] = mte_regnum;
302+
303+
m_per_regset_regnum_range[m_register_set_count] =
304+
std::make_pair(mte_regnum, mte_regnum + 1);
305+
m_dynamic_reg_sets.push_back(g_reg_set_mte_arm64);
306+
m_dynamic_reg_sets.back().registers = m_mte_regnum_collection.data();
307+
}
308+
262309
uint32_t RegisterInfoPOSIX_arm64::ConfigureVectorLength(uint32_t sve_vq) {
263310
// sve_vq contains SVE Quad vector length in context of AArch64 SVE.
264311
// SVE register infos if enabled cannot be disabled by selecting sve_vq = 0.
@@ -342,6 +389,18 @@ bool RegisterInfoPOSIX_arm64::IsSVERegVG(unsigned reg) const {
342389
return sve_vg == reg;
343390
}
344391

392+
bool RegisterInfoPOSIX_arm64::IsPAuthReg(unsigned reg) const {
393+
return std::find(pauth_regnum_collection.begin(),
394+
pauth_regnum_collection.end(),
395+
reg) != pauth_regnum_collection.end();
396+
}
397+
398+
bool RegisterInfoPOSIX_arm64::IsMTEReg(unsigned reg) const {
399+
return std::find(m_mte_regnum_collection.begin(),
400+
m_mte_regnum_collection.end(),
401+
reg) != m_mte_regnum_collection.end();
402+
}
403+
345404
uint32_t RegisterInfoPOSIX_arm64::GetRegNumSVEZ0() const { return sve_z0; }
346405

347406
uint32_t RegisterInfoPOSIX_arm64::GetRegNumSVEFFR() const { return sve_ffr; }
@@ -351,3 +410,11 @@ uint32_t RegisterInfoPOSIX_arm64::GetRegNumFPCR() const { return fpu_fpcr; }
351410
uint32_t RegisterInfoPOSIX_arm64::GetRegNumFPSR() const { return fpu_fpsr; }
352411

353412
uint32_t RegisterInfoPOSIX_arm64::GetRegNumSVEVG() const { return sve_vg; }
413+
414+
uint32_t RegisterInfoPOSIX_arm64::GetPAuthOffset() const {
415+
return m_register_info_p[pauth_regnum_collection[0]].byte_offset;
416+
}
417+
418+
uint32_t RegisterInfoPOSIX_arm64::GetMTEOffset() const {
419+
return m_register_info_p[m_mte_regnum_collection[0]].byte_offset;
420+
}

0 commit comments

Comments
 (0)