Skip to content

Commit 0ae2370

Browse files
[lldb] Do not produce field information for registers known not to exist (#95125)
Currently the logic is generate field information for all registers in LinuxArm64RegisterFlags and then as we walk the existing register info, only those that are in that existing info will get the new fields patched in. This works fine but on a review for FreeBSD support it was pointed out that this is not obvious from the source code. So instead I've allowed the construction of empty lists of fields, and field detection methods can return an empty field list if they think that the register will never exist. Then the pre-existing code will see the empty field list, and never look for that register in the register info. I think removing the assert is ok because the GDB classes filter out empty field lists at runtime, and anyone updating the built in field information would presumably notice if none of the fields they intended to add were displayed. mte_ctrl and svcr are the only registers that need this so far. There is no extra testing here as the behaviour is the same, it doesn't add field information to regiters that don't exist. The mechanism is just clearer now.
1 parent bdeee9b commit 0ae2370

File tree

3 files changed

+12
-9
lines changed

3 files changed

+12
-9
lines changed

lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.cpp

+9-2
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,18 @@
2020
#define HWCAP2_BTI (1ULL << 17)
2121
#define HWCAP2_MTE (1ULL << 18)
2222
#define HWCAP2_AFP (1ULL << 20)
23+
#define HWCAP2_SME (1ULL << 23)
2324
#define HWCAP2_EBF16 (1ULL << 32)
2425

2526
using namespace lldb_private;
2627

2728
LinuxArm64RegisterFlags::Fields
2829
LinuxArm64RegisterFlags::DetectSVCRFields(uint64_t hwcap, uint64_t hwcap2) {
2930
(void)hwcap;
30-
(void)hwcap2;
31+
32+
if (!(hwcap2 & HWCAP2_SME))
33+
return {};
34+
3135
// Represents the pseudo register that lldb-server builds, which itself
3236
// matches the architectural register SCVR. The fields match SVCR in the Arm
3337
// manual.
@@ -40,7 +44,10 @@ LinuxArm64RegisterFlags::DetectSVCRFields(uint64_t hwcap, uint64_t hwcap2) {
4044
LinuxArm64RegisterFlags::Fields
4145
LinuxArm64RegisterFlags::DetectMTECtrlFields(uint64_t hwcap, uint64_t hwcap2) {
4246
(void)hwcap;
43-
(void)hwcap2;
47+
48+
if (!(hwcap2 & HWCAP2_MTE))
49+
return {};
50+
4451
// Represents the contents of NT_ARM_TAGGED_ADDR_CTRL and the value passed
4552
// to prctl(PR_TAGGED_ADDR_CTRL...). Fields are derived from the defines
4653
// used to build the value.

lldb/source/Plugins/Process/Utility/RegisterFlagsLinux_arm64.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ class LinuxArm64RegisterFlags {
3838
/// For the registers listed in this class, detect which fields are
3939
/// present. Must be called before UpdateRegisterInfos.
4040
/// If called more than once, fields will be redetected each time from
41-
/// scratch. If you do not have access to hwcap, just pass 0 for each one, you
42-
/// will only get unconditional fields.
41+
/// scratch. If the target would not have this register at all, the list of
42+
/// fields will be left empty.
4343
void DetectFields(uint64_t hwcap, uint64_t hwcap2);
4444

4545
/// Add the field information of any registers named in this class,
@@ -63,7 +63,7 @@ class LinuxArm64RegisterFlags {
6363

6464
struct RegisterEntry {
6565
RegisterEntry(llvm::StringRef name, unsigned size, DetectorFn detector)
66-
: m_name(name), m_flags(std::string(name) + "_flags", size, {{"", 0}}),
66+
: m_name(name), m_flags(std::string(name) + "_flags", size, {}),
6767
m_detector(detector) {}
6868

6969
llvm::StringRef m_name;

lldb/source/Target/RegisterFlags.cpp

-4
Original file line numberDiff line numberDiff line change
@@ -108,10 +108,6 @@ uint64_t RegisterFlags::Field::GetMask() const {
108108
}
109109

110110
void RegisterFlags::SetFields(const std::vector<Field> &fields) {
111-
// We expect that the XML processor will discard anything describing flags but
112-
// with no fields.
113-
assert(fields.size() && "Some fields must be provided.");
114-
115111
// We expect that these are unsorted but do not overlap.
116112
// They could fill the register but may have gaps.
117113
std::vector<Field> provided_fields = fields;

0 commit comments

Comments
 (0)