summaryrefslogtreecommitdiffstats
path: root/lld/ELF/InputFiles.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF/InputFiles.cpp')
-rw-r--r--lld/ELF/InputFiles.cpp41
1 files changed, 22 insertions, 19 deletions
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index 6529ea072fae..1f496026d3ae 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -926,25 +926,18 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats,
handleSectionGroup<ELFT>(this->sections, entries);
}
-// If a source file is compiled with x86 hardware-assisted call flow control
-// enabled, the generated object file contains feature flags indicating that
-// fact. This function reads the feature flags and returns it.
-//
-// Essentially we want to read a single 32-bit value in this function, but this
-// function is rather complicated because the value is buried deep inside a
-// .note.gnu.property section.
-//
-// The section consists of one or more NOTE records. Each NOTE record consists
-// of zero or more type-length-value fields. We want to find a field of a
-// certain type. It seems a bit too much to just store a 32-bit value, perhaps
-// the ABI is unnecessarily complicated.
-template <class ELFT> static uint32_t readAndFeatures(const InputSection &sec) {
+// Read the following info from the .note.gnu.property section and write it to
+// the corresponding fields in `ObjFile`:
+// - Feature flags (32 bits) representing x86 or AArch64 features for
+// hardware-assisted call flow control;
+// - AArch64 PAuth ABI core info (16 bytes).
+template <class ELFT>
+void readGnuProperty(const InputSection &sec, ObjFile<ELFT> &f) {
using Elf_Nhdr = typename ELFT::Nhdr;
using Elf_Note = typename ELFT::Note;
- uint32_t featuresSet = 0;
ArrayRef<uint8_t> data = sec.content();
- auto reportFatal = [&](const uint8_t *place, const char *msg) {
+ auto reportFatal = [&](const uint8_t *place, const Twine &msg) {
fatal(toString(sec.file) + ":(" + sec.name + "+0x" +
Twine::utohexstr(place - sec.content().data()) + "): " + msg);
};
@@ -983,7 +976,19 @@ template <class ELFT> static uint32_t readAndFeatures(const InputSection &sec) {
// accumulate the bits set.
if (size < 4)
reportFatal(place, "FEATURE_1_AND entry is too short");
- featuresSet |= read32<ELFT::Endianness>(desc.data());
+ f.andFeatures |= read32<ELFT::Endianness>(desc.data());
+ } else if (config->emachine == EM_AARCH64 &&
+ type == GNU_PROPERTY_AARCH64_FEATURE_PAUTH) {
+ if (!f.aarch64PauthAbiCoreInfo.empty()) {
+ reportFatal(data.data(),
+ "multiple GNU_PROPERTY_AARCH64_FEATURE_PAUTH entries are "
+ "not supported");
+ } else if (size != 16) {
+ reportFatal(data.data(), "GNU_PROPERTY_AARCH64_FEATURE_PAUTH entry "
+ "is invalid: expected 16 bytes, but got " +
+ Twine(size));
+ }
+ f.aarch64PauthAbiCoreInfo = desc;
}
// Padding is present in the note descriptor, if necessary.
@@ -993,8 +998,6 @@ template <class ELFT> static uint32_t readAndFeatures(const InputSection &sec) {
// Go to next NOTE record to look for more FEATURE_1_AND descriptions.
data = data.slice(nhdr->getSize(sec.addralign));
}
-
- return featuresSet;
}
template <class ELFT>
@@ -1051,7 +1054,7 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(uint32_t idx,
// .note.gnu.property containing a single AND'ed bitmap, we discard an input
// file's .note.gnu.property section.
if (name == ".note.gnu.property") {
- this->andFeatures = readAndFeatures<ELFT>(InputSection(*this, sec, name));
+ readGnuProperty<ELFT>(InputSection(*this, sec, name), *this);
return &InputSection::discarded;
}