LLDB mainline
RegisterTypeDetector_arm64.h
Go to the documentation of this file.
1//===-- RegisterTypeDetector_arm64.h ----------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERTYPEDETECTOR_ARM64_H
10#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERTYPEDETECTOR_ARM64_H
11
14#include "llvm/ADT/StringRef.h"
15#include <functional>
16
17namespace lldb_private {
18
19/// This class manages the storage and detection of register type information.
20/// The same register may have different fields on different CPUs. This class
21/// abstracts out the field detection process so we can use it on live processes
22/// and core files.
23///
24/// The way to use this class is:
25/// * Make an instance somewhere that will last as long as the debug session
26/// (because your final register info will point to this instance).
27/// * Read hardware capabilities from a core note, binary, prctl, etc.
28/// * Pass those to DetectTypes.
29/// * Call UpdateRegisterInfo with your RegisterInfo to add pointers
30/// to the detected types for all registers listed in this class.
31///
32/// This must be done in that order, and you should ensure that if multiple
33/// threads will reference the information, a mutex is used to make sure only
34/// one calls DetectTypes.
36public:
37 /// For the registers listed in this class, detect which fields are
38 /// present and build types for those. Must be called before
39 /// UpdateRegisterInfos. If called more than once, fields will be redetected
40 /// each time from scratch. If the target would not have this register at all,
41 /// no type is produced.
42 void DetectTypes(uint64_t hwcap, uint64_t hwcap2, uint64_t hwcap3);
43
44 /// Add the type information of any registers named in this class,
45 /// to the relevant RegisterInfo instances. Note that this will be done
46 /// with a pointer to the instance of this class that you call this on, so
47 /// the lifetime of that instance must be at least that of the register info.
48 void UpdateRegisterInfo(const RegisterInfo *reg_info, uint32_t num_regs);
49
50 /// Returns true if field detection has been run at least once.
51 bool HasDetected() const { return m_has_detected; }
52
53private:
54 // A detector function inspects the hwcaps and builds a type for that
55 // register. All types should be made using MakeType, and a raw pointer to
56 // the top level type must be returned.
57 using DetectorFn = const RegisterType *(
58 Arm64RegisterTypeDetector::*)(uint64_t, uint64_t, uint64_t);
59
60 const RegisterType *DetectCPSRType(uint64_t hwcap, uint64_t hwcap2,
61 uint64_t hwcap3);
62 const RegisterType *DetectFPSRType(uint64_t hwcap, uint64_t hwcap2,
63 uint64_t hwcap3);
64 const RegisterType *DetectFPCRType(uint64_t hwcap, uint64_t hwcap2,
65 uint64_t hwcap3);
66 const RegisterType *DetectMTECtrlType(uint64_t hwcap, uint64_t hwcap2,
67 uint64_t hwcap3);
68 const RegisterType *DetectSVCRType(uint64_t hwcap, uint64_t hwcap2,
69 uint64_t hwcap3);
70 const RegisterType *DetectFPMRType(uint64_t hwcap, uint64_t hwcap2,
71 uint64_t hwcap3);
72 const RegisterType *DetectGCSFeaturesType(uint64_t hwcap, uint64_t hwcap2,
73 uint64_t hwcap3);
74 const RegisterType *DetectPOREL0Type(uint64_t hwcap, uint64_t hwcap2,
75 uint64_t hwcap3);
76
78 RegisterEntry(const std::vector<llvm::StringRef> &names,
79 DetectorFn detector)
80 : m_names(names), m_type(nullptr), m_detector(detector) {}
81
82 std::vector<llvm::StringRef> m_names;
83 // A raw pointer to the top level type. This pointer's lifetime is managed
84 // by a unique pointer of the same value in m_detected_types.
87 } m_registers[8] = {
89 RegisterEntry({"fpsr"}, &Arm64RegisterTypeDetector::DetectFPSRType),
90 RegisterEntry({"fpcr"}, &Arm64RegisterTypeDetector::DetectFPCRType),
91 RegisterEntry({"mte_ctrl"},
95 RegisterEntry({"gcs_features_enabled", "gcs_features_locked"},
98 };
99
100 // Becomes true once field detection has been run for all registers.
101 bool m_has_detected = false;
102
103 template <typename T, typename... Args> const T *MakeType(Args &&...args) {
104 static_assert(std::is_base_of_v<RegisterType, T>);
105
106 auto type = std::make_unique<T>(std::forward<Args>(args)...);
107 const T *type_ptr = type.get();
108 m_detected_types.detected_types.push_back(std::move(type));
109 return type_ptr;
110 }
111
112 // This stores all the types created. There may be > 1 type per register,
113 // as a register may nest types (enums for fields for example).
114 // We do not use a vector of RegisterType, because the address of the types
115 // must remain the same as new types are created.
116 // Code other than MakeType should not use this vector directly, hence the
117 // class wrapper to enforce that.
119 std::vector<std::unique_ptr<RegisterType>> detected_types;
120
121 template <typename T, typename... Args>
122 friend const T *Arm64RegisterTypeDetector::MakeType(Args &&...args);
124};
125
126} // namespace lldb_private
127
128#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERTYPEDETECTOR_ARM64_H
A command line argument class.
Definition Args.h:33
std::vector< std::unique_ptr< RegisterType > > detected_types
This class manages the storage and detection of register type information.
bool HasDetected() const
Returns true if field detection has been run at least once.
const RegisterType * DetectPOREL0Type(uint64_t hwcap, uint64_t hwcap2, uint64_t hwcap3)
const RegisterType * DetectFPCRType(uint64_t hwcap, uint64_t hwcap2, uint64_t hwcap3)
const RegisterType * DetectFPMRType(uint64_t hwcap, uint64_t hwcap2, uint64_t hwcap3)
const RegisterType * DetectMTECtrlType(uint64_t hwcap, uint64_t hwcap2, uint64_t hwcap3)
const RegisterType * DetectGCSFeaturesType(uint64_t hwcap, uint64_t hwcap2, uint64_t hwcap3)
const RegisterType * DetectCPSRType(uint64_t hwcap, uint64_t hwcap2, uint64_t hwcap3)
void UpdateRegisterInfo(const RegisterInfo *reg_info, uint32_t num_regs)
Add the type information of any registers named in this class, to the relevant RegisterInfo instances...
const RegisterType * DetectFPSRType(uint64_t hwcap, uint64_t hwcap2, uint64_t hwcap3)
struct lldb_private::Arm64RegisterTypeDetector::RegisterEntry m_registers[8]
class lldb_private::Arm64RegisterTypeDetector::DetectedTypesHolder m_detected_types
void DetectTypes(uint64_t hwcap, uint64_t hwcap2, uint64_t hwcap3)
For the registers listed in this class, detect which fields are present and build types for those.
const RegisterType * DetectSVCRType(uint64_t hwcap, uint64_t hwcap2, uint64_t hwcap3)
const RegisterType *( Arm64RegisterTypeDetector::*)(uint64_t, uint64_t, uint64_t) DetectorFn
A class that represents a running process on the host machine.
RegisterEntry(const std::vector< llvm::StringRef > &names, DetectorFn detector)
Every register is described in detail including its name, alternate name (optional),...