Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions lldb/source/Plugins/Process/Utility/AuxVector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions lldb/source/Plugins/Process/Utility/AuxVector.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ class AuxVector {
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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Comment on lines +32 to +35
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought about making the parameters all the same like struct of optional values, but I like the compiler warnings we get from this way.

If we end up with HWCAP4 and a bunch of other context, then yes, some single struct is going to be better. Even if we have a slightly higher chance to get it wrong.


if (!(hwcap2 & HWCAP2_FPMR))
return {};
Expand All @@ -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 {};
Expand All @@ -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 {};
Expand All @@ -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 {};
Expand All @@ -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"}});

Expand Down Expand Up @@ -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.
Expand All @@ -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.
Expand Down Expand Up @@ -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 &reg : 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;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class Arm64RegisterFlagsDetector {
/// 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
Expand All @@ -53,15 +53,22 @@ class Arm64RegisterFlagsDetector {

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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
Expand Down
Loading