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 <[email protected]> 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); _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
