[lldb][AArch64] Add HWCAP3 to register field detection (#145029)
This will be used to detect the presence of Arm's new Memory Tagging store only checking feature. This commit just adds the plumbing to get that value into the detection function. FreeBSD has not allocated a number for HWCAP3 and already has AT_ARGV defined as 29. So instead of attempting to read from FreeBSD processes, I've explicitly passed 0. We don't want to be reading some other entry accidentally. If/when FreeBSD adds HWCAP3 we can handle it like we do for AUXV_FREEBSD_AT_HWCAP. No extra tests here, those will be coming with the next change for MTE support. (cherry picked from commit d26ca8b87266024546501051ccaf75cb3756aee3)
This commit is contained in:
parent
614544048c
commit
9ad630fcb7
@ -44,7 +44,8 @@ NativeRegisterContextFreeBSD::CreateHostNativeRegisterContextFreeBSD(
|
||||
NativeProcessFreeBSD &process = native_thread.GetProcess();
|
||||
g_register_flags_detector.DetectFields(
|
||||
process.GetAuxValue(AuxVector::AUXV_FREEBSD_AT_HWCAP).value_or(0),
|
||||
process.GetAuxValue(AuxVector::AUXV_AT_HWCAP2).value_or(0));
|
||||
process.GetAuxValue(AuxVector::AUXV_AT_HWCAP2).value_or(0),
|
||||
/*hwcap3=*/0);
|
||||
}
|
||||
|
||||
return new NativeRegisterContextFreeBSD_arm64(target_arch, native_thread);
|
||||
|
@ -162,10 +162,13 @@ NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
|
||||
|
||||
opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskTLS);
|
||||
|
||||
std::optional<uint64_t> auxv_at_hwcap3 =
|
||||
process.GetAuxValue(AuxVector::AUXV_AT_HWCAP3);
|
||||
std::lock_guard<std::mutex> lock(g_register_flags_detector_mutex);
|
||||
if (!g_register_flags_detector.HasDetected())
|
||||
g_register_flags_detector.DetectFields(auxv_at_hwcap.value_or(0),
|
||||
auxv_at_hwcap2.value_or(0));
|
||||
auxv_at_hwcap2.value_or(0),
|
||||
auxv_at_hwcap3.value_or(0));
|
||||
|
||||
auto register_info_up =
|
||||
std::make_unique<RegisterInfoPOSIX_arm64>(target_arch, opt_regsets);
|
||||
|
@ -84,6 +84,7 @@ const char *AuxVector::GetEntryName(EntryType type) const {
|
||||
case ENTRY_NAME(AUXV_AT_BASE_PLATFORM); break;
|
||||
case ENTRY_NAME(AUXV_AT_RANDOM); break;
|
||||
case ENTRY_NAME(AUXV_AT_HWCAP2); break;
|
||||
case ENTRY_NAME(AUXV_AT_HWCAP3); break;
|
||||
case ENTRY_NAME(AUXV_AT_EXECFN); break;
|
||||
case ENTRY_NAME(AUXV_AT_SYSINFO); break;
|
||||
case ENTRY_NAME(AUXV_AT_SYSINFO_EHDR); break;
|
||||
|
@ -57,6 +57,7 @@ public:
|
||||
AUXV_AT_BASE_PLATFORM = 24, ///< String identifying real platforms.
|
||||
AUXV_AT_RANDOM = 25, ///< Address of 16 random bytes.
|
||||
AUXV_AT_HWCAP2 = 26, ///< Extension of AT_HWCAP.
|
||||
AUXV_AT_HWCAP3 = 29, ///< Extension of AT_HWCAP.
|
||||
AUXV_AT_EXECFN = 31, ///< Filename of executable.
|
||||
AUXV_AT_SYSINFO = 32, ///< Pointer to the global system page used for system
|
||||
/// calls and other nice things.
|
||||
|
@ -29,8 +29,10 @@
|
||||
using namespace lldb_private;
|
||||
|
||||
Arm64RegisterFlagsDetector::Fields
|
||||
Arm64RegisterFlagsDetector::DetectFPMRFields(uint64_t hwcap, uint64_t hwcap2) {
|
||||
Arm64RegisterFlagsDetector::DetectFPMRFields(uint64_t hwcap, uint64_t hwcap2,
|
||||
uint64_t hwcap3) {
|
||||
(void)hwcap;
|
||||
(void)hwcap3;
|
||||
|
||||
if (!(hwcap2 & HWCAP2_FPMR))
|
||||
return {};
|
||||
@ -53,8 +55,10 @@ Arm64RegisterFlagsDetector::DetectFPMRFields(uint64_t hwcap, uint64_t hwcap2) {
|
||||
|
||||
Arm64RegisterFlagsDetector::Fields
|
||||
Arm64RegisterFlagsDetector::DetectGCSFeatureFields(uint64_t hwcap,
|
||||
uint64_t hwcap2) {
|
||||
uint64_t hwcap2,
|
||||
uint64_t hwcap3) {
|
||||
(void)hwcap2;
|
||||
(void)hwcap3;
|
||||
|
||||
if (!(hwcap & HWCAP_GCS))
|
||||
return {};
|
||||
@ -67,8 +71,10 @@ Arm64RegisterFlagsDetector::DetectGCSFeatureFields(uint64_t hwcap,
|
||||
}
|
||||
|
||||
Arm64RegisterFlagsDetector::Fields
|
||||
Arm64RegisterFlagsDetector::DetectSVCRFields(uint64_t hwcap, uint64_t hwcap2) {
|
||||
Arm64RegisterFlagsDetector::DetectSVCRFields(uint64_t hwcap, uint64_t hwcap2,
|
||||
uint64_t hwcap3) {
|
||||
(void)hwcap;
|
||||
(void)hwcap3;
|
||||
|
||||
if (!(hwcap2 & HWCAP2_SME))
|
||||
return {};
|
||||
@ -83,9 +89,10 @@ Arm64RegisterFlagsDetector::DetectSVCRFields(uint64_t hwcap, uint64_t hwcap2) {
|
||||
}
|
||||
|
||||
Arm64RegisterFlagsDetector::Fields
|
||||
Arm64RegisterFlagsDetector::DetectMTECtrlFields(uint64_t hwcap,
|
||||
uint64_t hwcap2) {
|
||||
Arm64RegisterFlagsDetector::DetectMTECtrlFields(uint64_t hwcap, uint64_t hwcap2,
|
||||
uint64_t hwcap3) {
|
||||
(void)hwcap;
|
||||
(void)hwcap3;
|
||||
|
||||
if (!(hwcap2 & HWCAP2_MTE))
|
||||
return {};
|
||||
@ -103,7 +110,10 @@ Arm64RegisterFlagsDetector::DetectMTECtrlFields(uint64_t hwcap,
|
||||
}
|
||||
|
||||
Arm64RegisterFlagsDetector::Fields
|
||||
Arm64RegisterFlagsDetector::DetectFPCRFields(uint64_t hwcap, uint64_t hwcap2) {
|
||||
Arm64RegisterFlagsDetector::DetectFPCRFields(uint64_t hwcap, uint64_t hwcap2,
|
||||
uint64_t hwcap3) {
|
||||
(void)hwcap3;
|
||||
|
||||
static const FieldEnum rmode_enum(
|
||||
"rmode_enum", {{0, "RN"}, {1, "RP"}, {2, "RM"}, {3, "RZ"}});
|
||||
|
||||
@ -142,10 +152,12 @@ Arm64RegisterFlagsDetector::DetectFPCRFields(uint64_t hwcap, uint64_t hwcap2) {
|
||||
}
|
||||
|
||||
Arm64RegisterFlagsDetector::Fields
|
||||
Arm64RegisterFlagsDetector::DetectFPSRFields(uint64_t hwcap, uint64_t hwcap2) {
|
||||
Arm64RegisterFlagsDetector::DetectFPSRFields(uint64_t hwcap, uint64_t hwcap2,
|
||||
uint64_t hwcap3) {
|
||||
// fpsr's contents are constant.
|
||||
(void)hwcap;
|
||||
(void)hwcap2;
|
||||
(void)hwcap3;
|
||||
|
||||
return {
|
||||
// Bits 31-28 are N/Z/C/V, only used by AArch32.
|
||||
@ -162,7 +174,10 @@ Arm64RegisterFlagsDetector::DetectFPSRFields(uint64_t hwcap, uint64_t hwcap2) {
|
||||
}
|
||||
|
||||
Arm64RegisterFlagsDetector::Fields
|
||||
Arm64RegisterFlagsDetector::DetectCPSRFields(uint64_t hwcap, uint64_t hwcap2) {
|
||||
Arm64RegisterFlagsDetector::DetectCPSRFields(uint64_t hwcap, uint64_t hwcap2,
|
||||
uint64_t hwcap3) {
|
||||
(void)hwcap3;
|
||||
|
||||
// The fields here are a combination of the Arm manual's SPSR_EL1,
|
||||
// plus a few changes where Linux has decided not to make use of them at all,
|
||||
// or at least not from userspace.
|
||||
@ -207,9 +222,10 @@ Arm64RegisterFlagsDetector::DetectCPSRFields(uint64_t hwcap, uint64_t hwcap2) {
|
||||
return cpsr_fields;
|
||||
}
|
||||
|
||||
void Arm64RegisterFlagsDetector::DetectFields(uint64_t hwcap, uint64_t hwcap2) {
|
||||
void Arm64RegisterFlagsDetector::DetectFields(uint64_t hwcap, uint64_t hwcap2,
|
||||
uint64_t hwcap3) {
|
||||
for (auto ® : m_registers)
|
||||
reg.m_flags.SetFields(reg.m_detector(hwcap, hwcap2));
|
||||
reg.m_flags.SetFields(reg.m_detector(hwcap, hwcap2, hwcap3));
|
||||
m_has_detected = true;
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,7 @@ public:
|
||||
/// If called more than once, fields will be redetected each time from
|
||||
/// scratch. If the target would not have this register at all, the list of
|
||||
/// fields will be left empty.
|
||||
void DetectFields(uint64_t hwcap, uint64_t hwcap2);
|
||||
void DetectFields(uint64_t hwcap, uint64_t hwcap2, uint64_t hwcap3);
|
||||
|
||||
/// Add the field information of any registers named in this class,
|
||||
/// to the relevant RegisterInfo instances. Note that this will be done
|
||||
@ -53,15 +53,22 @@ public:
|
||||
|
||||
private:
|
||||
using Fields = std::vector<RegisterFlags::Field>;
|
||||
using DetectorFn = std::function<Fields(uint64_t, uint64_t)>;
|
||||
using DetectorFn = std::function<Fields(uint64_t, uint64_t, uint64_t)>;
|
||||
|
||||
static Fields DetectCPSRFields(uint64_t hwcap, uint64_t hwcap2);
|
||||
static Fields DetectFPSRFields(uint64_t hwcap, uint64_t hwcap2);
|
||||
static Fields DetectFPCRFields(uint64_t hwcap, uint64_t hwcap2);
|
||||
static Fields DetectMTECtrlFields(uint64_t hwcap, uint64_t hwcap2);
|
||||
static Fields DetectSVCRFields(uint64_t hwcap, uint64_t hwcap2);
|
||||
static Fields DetectFPMRFields(uint64_t hwcap, uint64_t hwcap2);
|
||||
static Fields DetectGCSFeatureFields(uint64_t hwcap, uint64_t hwcap2);
|
||||
static Fields DetectCPSRFields(uint64_t hwcap, uint64_t hwcap2,
|
||||
uint64_t hwcap3);
|
||||
static Fields DetectFPSRFields(uint64_t hwcap, uint64_t hwcap2,
|
||||
uint64_t hwcap3);
|
||||
static Fields DetectFPCRFields(uint64_t hwcap, uint64_t hwcap2,
|
||||
uint64_t hwcap3);
|
||||
static Fields DetectMTECtrlFields(uint64_t hwcap, uint64_t hwcap2,
|
||||
uint64_t hwcap3);
|
||||
static Fields DetectSVCRFields(uint64_t hwcap, uint64_t hwcap2,
|
||||
uint64_t hwcap3);
|
||||
static Fields DetectFPMRFields(uint64_t hwcap, uint64_t hwcap2,
|
||||
uint64_t hwcap3);
|
||||
static Fields DetectGCSFeatureFields(uint64_t hwcap, uint64_t hwcap2,
|
||||
uint64_t hwcap3);
|
||||
|
||||
struct RegisterEntry {
|
||||
RegisterEntry(llvm::StringRef name, unsigned size, DetectorFn detector)
|
||||
|
@ -96,14 +96,19 @@ RegisterContextCorePOSIX_arm64::RegisterContextCorePOSIX_arm64(
|
||||
llvm::Triple::OSType os = process->GetArchitecture().GetTriple().getOS();
|
||||
if ((os == llvm::Triple::Linux) || (os == llvm::Triple::FreeBSD)) {
|
||||
AuxVector aux_vec(process->GetAuxvData());
|
||||
std::optional<uint64_t> auxv_at_hwcap = aux_vec.GetAuxValue(
|
||||
os == llvm::Triple::FreeBSD ? AuxVector::AUXV_FREEBSD_AT_HWCAP
|
||||
: AuxVector::AUXV_AT_HWCAP);
|
||||
bool is_freebsd = os == llvm::Triple::FreeBSD;
|
||||
std::optional<uint64_t> auxv_at_hwcap =
|
||||
aux_vec.GetAuxValue(is_freebsd ? AuxVector::AUXV_FREEBSD_AT_HWCAP
|
||||
: AuxVector::AUXV_AT_HWCAP);
|
||||
std::optional<uint64_t> auxv_at_hwcap2 =
|
||||
aux_vec.GetAuxValue(AuxVector::AUXV_AT_HWCAP2);
|
||||
std::optional<uint64_t> auxv_at_hwcap3 =
|
||||
is_freebsd ? std::nullopt
|
||||
: aux_vec.GetAuxValue(AuxVector::AUXV_AT_HWCAP3);
|
||||
|
||||
m_register_flags_detector.DetectFields(auxv_at_hwcap.value_or(0),
|
||||
auxv_at_hwcap2.value_or(0));
|
||||
auxv_at_hwcap2.value_or(0),
|
||||
auxv_at_hwcap3.value_or(0));
|
||||
m_register_flags_detector.UpdateRegisterInfo(GetRegisterInfo(),
|
||||
GetRegisterCount());
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user