using Elf_Nhdr = typename ELFT::Nhdr;
using Elf_Note = typename ELFT::Note;
+ uint32_t FeaturesSet = 0;
while (!Data.empty()) {
// Read one NOTE record.
if (Data.size() < sizeof(Elf_Nhdr))
uint32_t Size = read32le(Desc.data() + 4);
if (Type == GNU_PROPERTY_X86_FEATURE_1_AND) {
- // We found the field.
- return read32le(Desc.data() + 8);
+ // We found a FEATURE_1_AND field. There may be more than one of these
+ // in a .note.gnu.propery section, for a relocatable object we
+ // accumulate the bits set.
+ FeaturesSet |= read32le(Desc.data() + 8);
}
// On 64-bit, a payload may be followed by a 4-byte padding to make its
Desc = Desc.slice(Size + 8); // +8 for Type and Size
}
- // Go to next NOTE record if a note section didn't contain
- // X86_FEATURES_1_AND description.
+ // Go to next NOTE record to look for more FEATURE_1_AND descriptions.
Data = Data.slice(Nhdr->getSize());
}
- return 0;
+ return FeaturesSet;
}
template <class ELFT>
--- /dev/null
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: ld.lld -r %t.o -o %t2.o
+# RUN: llvm-readelf -n %t2.o | FileCheck -match-full-lines %s
+
+## Test that .note.gnu.property is passed through -r, and that we can handle
+## more than one FEATURE_AND in the same object file. This is logically the
+## same as if the features were combined in a single FEATURE_AND as the rule
+## states that the bit in the output pr_data field if it is set in all
+.text
+ret
+
+.section ".note.gnu.property", "a"
+.p2align 3
+.long 4
+.long 0x10
+.long 0x5
+.asciz "GNU"
+
+.long 0xc0000002 // GNU_PROPERTY_X86_FEATURE_1_AND
+.long 4
+.long 1 // GNU_PROPERTY_X86_FEATURE_1_IBT
+.long 0
+
+.long 4
+.long 0x10
+.long 0x5
+.asciz "GNU"
+.long 0xc0000002 // GNU_PROPERTY_X86_FEATURE_1_AND
+.long 4
+.long 2 // GNU_PROPERTY_X86_FEATURE_1_SHSTK
+.long 0
+
+# CHECK: Owner Data size Description
+# CHECK-NEXT: GNU 0x00000010 NT_GNU_PROPERTY_TYPE_0 (property note)
+# CHECK-NEXT: Properties: x86 feature: IBT, SHSTK