[Lldb-commits] [lldb] [lldb] Make RegisterFlagsDetector into RegisterTypesDetector (PR #213892)
David Spickett via lldb-commits
lldb-commits at lists.llvm.org
Fri Aug 7 02:06:33 PDT 2026
https://github.com/DavidSpickett updated https://github.com/llvm/llvm-project/pull/213892
>From 30b8621763bc621716f51255c0c568e988134b78 Mon Sep 17 00:00:00 2001
From: David Spickett <david.spickett at linaro.org>
Date: Fri, 6 Sep 2024 10:35:58 +0000
Subject: [PATCH] [lldb] Make RegisterFlagsDetector into RegisterTypesDetector
In future it may be generating things other than flags. Functionality
is the same, but the interface changes to use RegisterType.
---
.../NativeRegisterContextFreeBSD_arm64.cpp | 14 +-
.../NativeRegisterContextLinux_arm64.cpp | 18 +-
.../Plugins/Process/Utility/CMakeLists.txt | 2 +-
.../Utility/RegisterFlagsDetector_arm64.h | 101 ---------
...m64.cpp => RegisterTypeDetector_arm64.cpp} | 198 ++++++++++--------
.../Utility/RegisterTypeDetector_arm64.h | 99 +++++++++
.../RegisterContextPOSIXCore_arm64.cpp | 12 +-
.../elf-core/RegisterContextPOSIXCore_arm64.h | 4 +-
8 files changed, 230 insertions(+), 218 deletions(-)
delete mode 100644 lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.h
rename lldb/source/Plugins/Process/Utility/{RegisterFlagsDetector_arm64.cpp => RegisterTypeDetector_arm64.cpp} (59%)
create mode 100644 lldb/source/Plugins/Process/Utility/RegisterTypeDetector_arm64.h
diff --git a/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp
index 74c55224fed49..1f2e0d5904148 100644
--- a/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp
+++ b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp
@@ -16,8 +16,8 @@
#include "Plugins/Process/FreeBSD/NativeProcessFreeBSD.h"
#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
-#include "Plugins/Process/Utility/RegisterFlagsDetector_arm64.h"
#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
+#include "Plugins/Process/Utility/RegisterTypeDetector_arm64.h"
// clang-format off
#include <sys/param.h>
@@ -33,16 +33,16 @@ using namespace lldb_private::process_freebsd;
// will contain the same fields. Therefore this mutex prevents each instance
// competing with the other, and subsequent instances from having to detect the
// fields all over again.
-static std::mutex g_register_flags_detector_mutex;
-static Arm64RegisterFlagsDetector g_register_flags_detector;
+static std::mutex g_register_type_detector_mutex;
+static Arm64RegisterTypeDetector g_register_type_detector;
NativeRegisterContextFreeBSD *
NativeRegisterContextFreeBSD::CreateHostNativeRegisterContextFreeBSD(
const ArchSpec &target_arch, NativeThreadFreeBSD &native_thread) {
- std::lock_guard<std::mutex> lock(g_register_flags_detector_mutex);
- if (!g_register_flags_detector.HasDetected()) {
+ std::lock_guard<std::mutex> lock(g_register_type_detector_mutex);
+ if (!g_register_type_detector.HasDetected()) {
NativeProcessFreeBSD &process = native_thread.GetProcess();
- g_register_flags_detector.DetectFields(
+ g_register_type_detector.DetectTypes(
process.GetAuxValue(AuxVector::AUXV_FREEBSD_AT_HWCAP).value_or(0),
process.GetAuxValue(AuxVector::AUXV_AT_HWCAP2).value_or(0),
/*hwcap3=*/0);
@@ -56,7 +56,7 @@ NativeRegisterContextFreeBSD_arm64::NativeRegisterContextFreeBSD_arm64(
: NativeRegisterContextRegisterInfo(
native_thread, new RegisterInfoPOSIX_arm64(target_arch, 0)),
m_read_dbreg(false) {
- g_register_flags_detector.UpdateRegisterInfo(
+ g_register_type_detector.UpdateRegisterInfo(
GetRegisterInfoInterface().GetRegisterInfo(),
GetRegisterInfoInterface().GetRegisterCount());
}
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
index 82d6f8658c30b..3c279cd9b1029 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
@@ -24,8 +24,8 @@
#include "Plugins/Process/Linux/Procfs.h"
#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
#include "Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h"
-#include "Plugins/Process/Utility/RegisterFlagsDetector_arm64.h"
#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
+#include "Plugins/Process/Utility/RegisterTypeDetector_arm64.h"
#include "llvm/BinaryFormat/ELF.h"
@@ -63,8 +63,8 @@ using namespace lldb_private::process_linux;
// will contain the same fields. Therefore this mutex prevents each instance
// competing with the other, and subsequent instances from having to detect the
// fields all over again.
-static std::mutex g_register_flags_detector_mutex;
-static Arm64RegisterFlagsDetector g_register_flags_detector;
+static std::mutex g_register_type_detector_mutex;
+static Arm64RegisterTypeDetector g_register_type_detector;
std::unique_ptr<NativeRegisterContextLinux>
NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
@@ -144,11 +144,11 @@ NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
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_hwcap3.value_or(0));
+ std::lock_guard<std::mutex> lock(g_register_type_detector_mutex);
+ if (!g_register_type_detector.HasDetected())
+ g_register_type_detector.DetectTypes(auxv_at_hwcap.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);
@@ -172,7 +172,7 @@ NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64(
: NativeRegisterContextRegisterInfo(native_thread,
register_info_up.release()),
NativeRegisterContextLinux(native_thread) {
- g_register_flags_detector.UpdateRegisterInfo(
+ g_register_type_detector.UpdateRegisterInfo(
GetRegisterInfoInterface().GetRegisterInfo(),
GetRegisterInfoInterface().GetRegisterCount());
diff --git a/lldb/source/Plugins/Process/Utility/CMakeLists.txt b/lldb/source/Plugins/Process/Utility/CMakeLists.txt
index 3652a0cfb530f..90cf4d20bbc07 100644
--- a/lldb/source/Plugins/Process/Utility/CMakeLists.txt
+++ b/lldb/source/Plugins/Process/Utility/CMakeLists.txt
@@ -52,7 +52,7 @@ add_lldb_library(lldbPluginProcessUtility
RegisterContextThreadMemory.cpp
RegisterContextWindows_i386.cpp
RegisterContextWindows_x86_64.cpp
- RegisterFlagsDetector_arm64.cpp
+ RegisterTypeDetector_arm64.cpp
RegisterInfos_x86_64_with_base_shared.cpp
RegisterInfoPOSIX_arm.cpp
RegisterInfoPOSIX_arm64.cpp
diff --git a/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.h b/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.h
deleted file mode 100644
index 217fd41922fc5..0000000000000
--- a/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.h
+++ /dev/null
@@ -1,101 +0,0 @@
-//===-- RegisterFlagsDetector_arm64.h ---------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERFLAGSDETECTOR_ARM64_H
-#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERFLAGSDETECTOR_ARM64_H
-
-#include "lldb/Utility/RegisterTypeFlags.h"
-#include "llvm/ADT/StringRef.h"
-#include <functional>
-
-namespace lldb_private {
-
-struct RegisterInfo;
-
-/// This class manages the storage and detection of register field information.
-/// The same register may have different fields on different CPUs. This class
-/// abstracts out the field detection process so we can use it on live processes
-/// and core files.
-///
-/// The way to use this class is:
-/// * Make an instance somewhere that will last as long as the debug session
-/// (because your final register info will point to this instance).
-/// * Read hardware capabilities from a core note, binary, prctl, etc.
-/// * Pass those to DetectFields.
-/// * Call UpdateRegisterInfo with your RegisterInfo to add pointers
-/// to the detected fields for all registers listed in this class.
-///
-/// This must be done in that order, and you should ensure that if multiple
-/// threads will reference the information, a mutex is used to make sure only
-/// one calls DetectFields.
-class Arm64RegisterFlagsDetector {
-public:
- /// For the registers listed in this class, detect which fields are
- /// present. Must be called before UpdateRegisterInfos.
- /// 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, 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
- /// with a pointer to the instance of this class that you call this on, so
- /// the lifetime of that instance must be at least that of the register info.
- void UpdateRegisterInfo(const RegisterInfo *reg_info, uint32_t num_regs);
-
- /// Returns true if field detection has been run at least once.
- bool HasDetected() const { return m_has_detected; }
-
-private:
- using Fields = std::vector<RegisterTypeFlags::Field>;
- using DetectorFn = std::function<Fields(uint64_t, uint64_t, uint64_t)>;
-
- 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);
- static Fields DetectPOREL0Fields(uint64_t hwcap, uint64_t hwcap2,
- uint64_t hwcap3);
-
- struct RegisterEntry {
- RegisterEntry(llvm::StringRef name, unsigned size, DetectorFn detector)
- : m_name(name), m_flags(std::string(name) + "_flags", size, {}),
- m_detector(detector) {}
-
- llvm::StringRef m_name;
- RegisterTypeFlags m_flags;
- DetectorFn m_detector;
- } m_registers[9] = {
- RegisterEntry("cpsr", 4, DetectCPSRFields),
- RegisterEntry("fpsr", 4, DetectFPSRFields),
- RegisterEntry("fpcr", 4, DetectFPCRFields),
- RegisterEntry("mte_ctrl", 8, DetectMTECtrlFields),
- RegisterEntry("svcr", 8, DetectSVCRFields),
- RegisterEntry("fpmr", 8, DetectFPMRFields),
- RegisterEntry("gcs_features_enabled", 8, DetectGCSFeatureFields),
- RegisterEntry("gcs_features_locked", 8, DetectGCSFeatureFields),
- RegisterEntry("por_el0", 8, DetectPOREL0Fields),
- };
-
- // Becomes true once field detection has been run for all registers.
- bool m_has_detected = false;
-};
-
-} // namespace lldb_private
-
-#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERFLAGSDETECTOR_ARM64_H
diff --git a/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.cpp b/lldb/source/Plugins/Process/Utility/RegisterTypeDetector_arm64.cpp
similarity index 59%
rename from lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.cpp
rename to lldb/source/Plugins/Process/Utility/RegisterTypeDetector_arm64.cpp
index 5c78a690167d0..8e7ddca73b27b 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterTypeDetector_arm64.cpp
@@ -1,4 +1,4 @@
-//===-- RegisterFlagsDetector_arm64.cpp -----------------------------------===//
+//===-- RegisterTypeDetector_arm64.cpp ------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -6,9 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#include "RegisterFlagsDetector_arm64.h"
-#include "lldb/Utility/RegisterInfo.h"
-#include "lldb/lldb-private-types.h"
+#include "RegisterTypeDetector_arm64.h"
+#include "lldb/Utility/RegisterTypeFlags.h"
// This file is built on all systems because it is used by native processes and
// core files, so we manually define the needed HWCAP values here.
@@ -32,9 +31,9 @@
using namespace lldb_private;
-Arm64RegisterFlagsDetector::Fields
-Arm64RegisterFlagsDetector::DetectPOREL0Fields(uint64_t hwcap, uint64_t hwcap2,
- uint64_t hwcap3) {
+const RegisterType *
+Arm64RegisterTypeDetector::DetectPOREL0Type(uint64_t hwcap, uint64_t hwcap2,
+ uint64_t hwcap3) {
(void)hwcap;
(void)hwcap3;
@@ -53,29 +52,33 @@ Arm64RegisterFlagsDetector::DetectPOREL0Fields(uint64_t hwcap, uint64_t hwcap2,
{0b0111, "Read, Write, Execute"},
});
- return {
- {"Perm15", 60, 63, &por_el0_perm_enum},
- {"Perm14", 56, 59, &por_el0_perm_enum},
- {"Perm13", 52, 55, &por_el0_perm_enum},
- {"Perm12", 48, 51, &por_el0_perm_enum},
- {"Perm11", 44, 47, &por_el0_perm_enum},
- {"Perm10", 40, 43, &por_el0_perm_enum},
- {"Perm9", 36, 39, &por_el0_perm_enum},
- {"Perm8", 32, 35, &por_el0_perm_enum},
- {"Perm7", 28, 31, &por_el0_perm_enum},
- {"Perm6", 24, 27, &por_el0_perm_enum},
- {"Perm5", 20, 23, &por_el0_perm_enum},
- {"Perm4", 16, 19, &por_el0_perm_enum},
- {"Perm3", 12, 15, &por_el0_perm_enum},
- {"Perm2", 8, 11, &por_el0_perm_enum},
- {"Perm1", 4, 7, &por_el0_perm_enum},
- {"Perm0", 0, 3, &por_el0_perm_enum},
- };
+ static const RegisterTypeFlags por_el0_flags(
+ "por_el0_flags", 8,
+ {
+ {"Perm15", 60, 63, &por_el0_perm_enum},
+ {"Perm14", 56, 59, &por_el0_perm_enum},
+ {"Perm13", 52, 55, &por_el0_perm_enum},
+ {"Perm12", 48, 51, &por_el0_perm_enum},
+ {"Perm11", 44, 47, &por_el0_perm_enum},
+ {"Perm10", 40, 43, &por_el0_perm_enum},
+ {"Perm9", 36, 39, &por_el0_perm_enum},
+ {"Perm8", 32, 35, &por_el0_perm_enum},
+ {"Perm7", 28, 31, &por_el0_perm_enum},
+ {"Perm6", 24, 27, &por_el0_perm_enum},
+ {"Perm5", 20, 23, &por_el0_perm_enum},
+ {"Perm4", 16, 19, &por_el0_perm_enum},
+ {"Perm3", 12, 15, &por_el0_perm_enum},
+ {"Perm2", 8, 11, &por_el0_perm_enum},
+ {"Perm1", 4, 7, &por_el0_perm_enum},
+ {"Perm0", 0, 3, &por_el0_perm_enum},
+ });
+
+ return &por_el0_flags;
}
-Arm64RegisterFlagsDetector::Fields
-Arm64RegisterFlagsDetector::DetectFPMRFields(uint64_t hwcap, uint64_t hwcap2,
- uint64_t hwcap3) {
+const RegisterType *Arm64RegisterTypeDetector::DetectFPMRType(uint64_t hwcap,
+ uint64_t hwcap2,
+ uint64_t hwcap3) {
(void)hwcap;
(void)hwcap3;
@@ -87,60 +90,59 @@ Arm64RegisterFlagsDetector::DetectFPMRFields(uint64_t hwcap, uint64_t hwcap2,
{0, "FP8_E5M2"},
{1, "FP8_E4M3"},
});
- return {
- {"LSCALE2", 32, 37},
- {"NSCALE", 24, 31},
- {"LSCALE", 16, 22},
- {"OSC", 15},
- {"OSM", 14},
- {"F8D", 6, 8, &fp8_format_enum},
- {"F8S2", 3, 5, &fp8_format_enum},
- {"F8S1", 0, 2, &fp8_format_enum},
- };
+
+ static const RegisterTypeFlags fpmr_flags("fpmr_flags", 8,
+ {{"LSCALE2", 32, 37},
+ {"NSCALE", 24, 31},
+ {"LSCALE", 16, 22},
+ {"OSC", 15},
+ {"OSM", 14},
+ {"F8D", 6, 8, &fp8_format_enum},
+ {"F8S2", 3, 5, &fp8_format_enum},
+ {"F8S1", 0, 2, &fp8_format_enum}});
+
+ return &fpmr_flags;
}
-Arm64RegisterFlagsDetector::Fields
-Arm64RegisterFlagsDetector::DetectGCSFeatureFields(uint64_t hwcap,
- uint64_t hwcap2,
- uint64_t hwcap3) {
+const RegisterType *Arm64RegisterTypeDetector::DetectGCSFeaturesType(
+ uint64_t hwcap, uint64_t hwcap2, uint64_t hwcap3) {
(void)hwcap2;
(void)hwcap3;
if (!(hwcap & HWCAP_GCS))
return {};
- return {
- {"PUSH", 2},
- {"WRITE", 1},
- {"ENABLE", 0},
- };
+ static const RegisterTypeFlags gcs_features_flags(
+ "gcs_features_flags", 8, {{"PUSH", 2}, {"WRITE", 1}, {"ENABLE", 0}});
+
+ return &gcs_features_flags;
}
-Arm64RegisterFlagsDetector::Fields
-Arm64RegisterFlagsDetector::DetectSVCRFields(uint64_t hwcap, uint64_t hwcap2,
- uint64_t hwcap3) {
+const RegisterType *Arm64RegisterTypeDetector::DetectSVCRType(uint64_t hwcap,
+ uint64_t hwcap2,
+ uint64_t hwcap3) {
(void)hwcap;
(void)hwcap3;
if (!(hwcap2 & HWCAP2_SME))
- return {};
+ return nullptr;
// Represents the pseudo register that lldb-server builds, which itself
// matches the architectural register SCVR. The fields match SVCR in the Arm
// manual.
- return {
- {"ZA", 1},
- {"SM", 0},
- };
+ static const RegisterTypeFlags svcr_flags("svcr_flags", 8,
+ {{"ZA", 1}, {"SM", 0}});
+
+ return &svcr_flags;
}
-Arm64RegisterFlagsDetector::Fields
-Arm64RegisterFlagsDetector::DetectMTECtrlFields(uint64_t hwcap, uint64_t hwcap2,
- uint64_t hwcap3) {
+const RegisterType *
+Arm64RegisterTypeDetector::DetectMTECtrlType(uint64_t hwcap, uint64_t hwcap2,
+ uint64_t hwcap3) {
(void)hwcap;
if (!(hwcap2 & HWCAP2_MTE))
- return {};
+ return nullptr;
// Represents the contents of NT_ARM_TAGGED_ADDR_CTRL and the value passed
// to prctl(PR_TAGGED_ADDR_CTRL...). Fields are derived from the defines
@@ -161,16 +163,19 @@ Arm64RegisterFlagsDetector::DetectMTECtrlFields(uint64_t hwcap, uint64_t hwcap2,
{"TCF", 1, 2, &tcf_enum},
{"TAGGED_ADDR_ENABLE", 0}});
- return fields;
+ static const RegisterTypeFlags mte_ctrl_flags("mte_ctrl_flags", 8, fields);
+
+ return &mte_ctrl_flags;
}
-Arm64RegisterFlagsDetector::Fields
-Arm64RegisterFlagsDetector::DetectFPCRFields(uint64_t hwcap, uint64_t hwcap2,
- uint64_t hwcap3) {
+const RegisterType *Arm64RegisterTypeDetector::DetectFPCRType(uint64_t hwcap,
+ uint64_t hwcap2,
+ uint64_t hwcap3) {
(void)hwcap3;
static const RegisterTypeEnum rmode_enum(
"rmode_enum", {{0, "RN"}, {1, "RP"}, {2, "RM"}, {3, "RZ"}});
+ static RegisterTypeFlags fpcr_flags("fpcr_flags", 4, {});
std::vector<RegisterTypeFlags::Field> fpcr_fields{
{"AHP", 26},
@@ -206,39 +211,46 @@ Arm64RegisterFlagsDetector::DetectFPCRFields(uint64_t hwcap, uint64_t hwcap2,
fpcr_fields.push_back({"FIZ", 0});
}
- return fpcr_fields;
+ fpcr_flags.SetFields(fpcr_fields);
+
+ return &fpcr_flags;
}
-Arm64RegisterFlagsDetector::Fields
-Arm64RegisterFlagsDetector::DetectFPSRFields(uint64_t hwcap, uint64_t hwcap2,
- uint64_t hwcap3) {
+const RegisterType *Arm64RegisterTypeDetector::DetectFPSRType(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.
- {"QC", 27},
- // Bits 26-8 reserved.
- {"IDC", 7},
- // Bits 6-5 reserved.
- {"IXC", 4},
- {"UFC", 3},
- {"OFC", 2},
- {"DZC", 1},
- {"IOC", 0},
- };
+ static const RegisterTypeFlags fpsr_flags(
+ "fpsr_flags", 4,
+ {
+ // Bits 31-28 are N/Z/C/V, only used by AArch32.
+ {"QC", 27},
+ // Bits 26-8 reserved.
+ {"IDC", 7},
+ // Bits 6-5 reserved.
+ {"IXC", 4},
+ {"UFC", 3},
+ {"OFC", 2},
+ {"DZC", 1},
+ {"IOC", 0},
+ });
+
+ return &fpsr_flags;
}
-Arm64RegisterFlagsDetector::Fields
-Arm64RegisterFlagsDetector::DetectCPSRFields(uint64_t hwcap, uint64_t hwcap2,
- uint64_t hwcap3) {
+const RegisterType *Arm64RegisterTypeDetector::DetectCPSRType(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.
+ static RegisterTypeFlags cpsr_flags("cpsr_flags", 4, {});
// Status bits that are always present.
std::vector<RegisterTypeFlags::Field> cpsr_fields{
@@ -280,31 +292,33 @@ Arm64RegisterFlagsDetector::DetectCPSRFields(uint64_t hwcap, uint64_t hwcap2,
// Bit 1 is unused and expected to be 0.
cpsr_fields.push_back({"SP", 0});
- return cpsr_fields;
+ cpsr_flags.SetFields(cpsr_fields);
+
+ return &cpsr_flags;
}
-void Arm64RegisterFlagsDetector::DetectFields(uint64_t hwcap, uint64_t hwcap2,
- uint64_t hwcap3) {
+void Arm64RegisterTypeDetector::DetectTypes(uint64_t hwcap, uint64_t hwcap2,
+ uint64_t hwcap3) {
for (auto ® : m_registers)
- reg.m_flags.SetFields(reg.m_detector(hwcap, hwcap2, hwcap3));
+ reg.m_type = reg.m_detector(hwcap, hwcap2, hwcap3);
m_has_detected = true;
}
-void Arm64RegisterFlagsDetector::UpdateRegisterInfo(
- const RegisterInfo *reg_info, uint32_t num_regs) {
+void Arm64RegisterTypeDetector::UpdateRegisterInfo(const RegisterInfo *reg_info,
+ uint32_t num_regs) {
assert(m_has_detected &&
- "Must call DetectFields before updating register info.");
+ "Must call DetectTypes before updating register info.");
// Register names will not be duplicated, so we do not want to compare against
// one if it has already been found. Each time we find one, we erase it from
// this list.
- std::vector<std::pair<llvm::StringRef, const RegisterTypeFlags *>>
+ std::vector<std::pair<llvm::StringRef, const RegisterType *>>
search_registers;
for (const auto ® : m_registers) {
// It is possible that a register is all extension dependent fields, and
// none of them are present.
- if (reg.m_flags.GetFields().size())
- search_registers.push_back({reg.m_name, ®.m_flags});
+ if (reg.m_type)
+ search_registers.push_back({reg.m_name, reg.m_type});
}
// Walk register information while there are registers we know need
diff --git a/lldb/source/Plugins/Process/Utility/RegisterTypeDetector_arm64.h b/lldb/source/Plugins/Process/Utility/RegisterTypeDetector_arm64.h
new file mode 100644
index 0000000000000..18c2f58bd4d4e
--- /dev/null
+++ b/lldb/source/Plugins/Process/Utility/RegisterTypeDetector_arm64.h
@@ -0,0 +1,99 @@
+//===-- RegisterTypeDetector_arm64.h ----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERTYPEDETECTOR_ARM64_H
+#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERTYPEDETECTOR_ARM64_H
+
+#include "lldb/Utility/RegisterInfo.h"
+#include "lldb/Utility/RegisterType.h"
+#include "llvm/ADT/StringRef.h"
+#include <functional>
+
+namespace lldb_private {
+
+/// This class manages the storage and detection of register type information.
+/// The same register may have different fields on different CPUs. This class
+/// abstracts out the field detection process so we can use it on live processes
+/// and core files.
+///
+/// The way to use this class is:
+/// * Make an instance somewhere that will last as long as the debug session
+/// (because your final register info will point to this instance).
+/// * Read hardware capabilities from a core note, binary, prctl, etc.
+/// * Pass those to DetectTypes.
+/// * Call UpdateRegisterInfo with your RegisterInfo to add pointers
+/// to the detected types for all registers listed in this class.
+///
+/// This must be done in that order, and you should ensure that if multiple
+/// threads will reference the information, a mutex is used to make sure only
+/// one calls DetectTypes.
+class Arm64RegisterTypeDetector {
+public:
+ /// For the registers listed in this class, detect which fields are
+ /// present and build types for those. Must be called before
+ /// UpdateRegisterInfos. If called more than once, fields will be redetected
+ /// each time from scratch. If the target would not have this register at all,
+ /// no type is produced.
+ void DetectTypes(uint64_t hwcap, uint64_t hwcap2, uint64_t hwcap3);
+
+ /// Add the type information of any registers named in this class,
+ /// to the relevant RegisterInfo instances. Note that this will be done
+ /// with a pointer to the instance of this class that you call this on, so
+ /// the lifetime of that instance must be at least that of the register info.
+ void UpdateRegisterInfo(const RegisterInfo *reg_info, uint32_t num_regs);
+
+ /// Returns true if field detection has been run at least once.
+ bool HasDetected() const { return m_has_detected; }
+
+private:
+ using DetectorFn =
+ std::function<const RegisterType *(uint64_t, uint64_t, uint64_t)>;
+
+ static const RegisterType *DetectCPSRType(uint64_t hwcap, uint64_t hwcap2,
+ uint64_t hwcap3);
+ static const RegisterType *DetectFPSRType(uint64_t hwcap, uint64_t hwcap2,
+ uint64_t hwcap3);
+ static const RegisterType *DetectFPCRType(uint64_t hwcap, uint64_t hwcap2,
+ uint64_t hwcap3);
+ static const RegisterType *DetectMTECtrlType(uint64_t hwcap, uint64_t hwcap2,
+ uint64_t hwcap3);
+ static const RegisterType *DetectSVCRType(uint64_t hwcap, uint64_t hwcap2,
+ uint64_t hwcap3);
+ static const RegisterType *DetectFPMRType(uint64_t hwcap, uint64_t hwcap2,
+ uint64_t hwcap3);
+ static const RegisterType *
+ DetectGCSFeaturesType(uint64_t hwcap, uint64_t hwcap2, uint64_t hwcap3);
+ static const RegisterType *DetectPOREL0Type(uint64_t hwcap, uint64_t hwcap2,
+ uint64_t hwcap3);
+
+ struct RegisterEntry {
+ RegisterEntry(llvm::StringRef name, unsigned size, DetectorFn detector)
+ : m_name(name), m_type(nullptr), m_detector(detector) {}
+
+ llvm::StringRef m_name;
+ const RegisterType *m_type;
+ DetectorFn m_detector;
+ } m_registers[9] = {
+ RegisterEntry("cpsr", 4, DetectCPSRType),
+ RegisterEntry("fpsr", 4, DetectFPSRType),
+ RegisterEntry("fpcr", 4, DetectFPCRType),
+ RegisterEntry("mte_ctrl", 8, DetectMTECtrlType),
+ RegisterEntry("svcr", 8, DetectSVCRType),
+ RegisterEntry("fpmr", 8, DetectFPMRType),
+ RegisterEntry("gcs_features_enabled", 8, DetectGCSFeaturesType),
+ RegisterEntry("gcs_features_locked", 8, DetectGCSFeaturesType),
+ RegisterEntry("por_el0", 8, DetectPOREL0Type),
+ };
+
+ // Becomes true once field detection has been run for all registers.
+ bool m_has_detected = false;
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERTYPEDETECTOR_ARM64_H
diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp
index feeed4a9f0ac3..837cb30798fe1 100644
--- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp
+++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp
@@ -10,7 +10,7 @@
#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
#include "Plugins/Process/Utility/AuxVector.h"
-#include "Plugins/Process/Utility/RegisterFlagsDetector_arm64.h"
+#include "Plugins/Process/Utility/RegisterTypeDetector_arm64.h"
#include "Plugins/Process/elf-core/ProcessElfCore.h"
#include "Plugins/Process/elf-core/RegisterUtilities.h"
#include "lldb/Target/Thread.h"
@@ -113,11 +113,11 @@ RegisterContextCorePOSIX_arm64::RegisterContextCorePOSIX_arm64(
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_hwcap3.value_or(0));
- m_register_flags_detector.UpdateRegisterInfo(GetRegisterInfo(),
- GetRegisterCount());
+ m_register_type_detector.DetectTypes(auxv_at_hwcap.value_or(0),
+ auxv_at_hwcap2.value_or(0),
+ auxv_at_hwcap3.value_or(0));
+ m_register_type_detector.UpdateRegisterInfo(GetRegisterInfo(),
+ GetRegisterCount());
}
m_gpr_data.SetData(std::make_shared<DataBufferHeap>(gpregset.GetDataStart(),
diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h
index f6d6c522d836a..9d9a2da2bc1b9 100644
--- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h
+++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h
@@ -11,7 +11,7 @@
#include "Plugins/Process/Utility/LinuxPTraceDefines_arm64sve.h"
#include "Plugins/Process/Utility/RegisterContextPOSIX_arm64.h"
-#include "Plugins/Process/Utility/RegisterFlagsDetector_arm64.h"
+#include "Plugins/Process/Utility/RegisterTypeDetector_arm64.h"
#include "Plugins/Process/elf-core/RegisterUtilities.h"
#include "lldb/Utility/DataBufferHeap.h"
@@ -78,7 +78,7 @@ class RegisterContextCorePOSIX_arm64 : public RegisterContextPOSIX_arm64 {
struct sme_pseudo_regs m_sme_pseudo_regs;
- lldb_private::Arm64RegisterFlagsDetector m_register_flags_detector;
+ lldb_private::Arm64RegisterTypeDetector m_register_type_detector;
const uint8_t *GetSVEBuffer(uint64_t offset = 0);
More information about the lldb-commits
mailing list