diff options
Diffstat (limited to 'lld/ELF/InputFiles.cpp')
-rw-r--r-- | lld/ELF/InputFiles.cpp | 72 |
1 files changed, 65 insertions, 7 deletions
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 71e72e7..37e4c8a 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -21,6 +21,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/LTO/LTO.h" #include "llvm/Object/IRObjectFile.h" +#include "llvm/Support/AArch64AttributeParser.h" #include "llvm/Support/ARMAttributeParser.h" #include "llvm/Support/ARMBuildAttributes.h" #include "llvm/Support/Endian.h" @@ -537,6 +538,41 @@ uint32_t ObjFile<ELFT>::getSectionIndex(const Elf_Sym &sym) const { this); } +template <class ELFT> +static void +handleAArch64BAAndGnuProperties(ObjFile<ELFT> *file, Ctx &ctx, + const AArch64BuildAttrSubsections &baInfo) { + if (file->aarch64PauthAbiCoreInfo) { + // Check for data mismatch. + if (file->aarch64PauthAbiCoreInfo) { + if (baInfo.Pauth.TagPlatform != file->aarch64PauthAbiCoreInfo->platform || + baInfo.Pauth.TagSchema != file->aarch64PauthAbiCoreInfo->version) + Err(ctx) << file + << " GNU properties and build attributes have conflicting " + "AArch64 PAuth data"; + } + if (baInfo.AndFeatures != file->andFeatures) + Err(ctx) << file + << " GNU properties and build attributes have conflicting " + "AArch64 PAuth data"; + } else { + // When BuildAttributes are missing, PauthABI value defaults to (TagPlatform + // = 0, TagSchema = 0). GNU properties do not write PAuthAbiCoreInfo if GNU + // property is not present. To match this behaviour, we only write + // PAuthAbiCoreInfo when there is at least one non-zero value. The + // specification reserves TagPlatform = 0, TagSchema = 1 values to match the + // 'Invalid' GNU property section with platform = 0, version = 0. + if (baInfo.Pauth.TagPlatform || baInfo.Pauth.TagSchema) { + if (baInfo.Pauth.TagPlatform == 0 && baInfo.Pauth.TagSchema == 1) + file->aarch64PauthAbiCoreInfo = {0, 0}; + else + file->aarch64PauthAbiCoreInfo = {baInfo.Pauth.TagPlatform, + baInfo.Pauth.TagSchema}; + } + file->andFeatures = baInfo.AndFeatures; + } +} + template <class ELFT> void ObjFile<ELFT>::parse(bool ignoreComdats) { object::ELFFile<ELFT> obj = this->getObj(); // Read a section table. justSymbols is usually false. @@ -554,6 +590,7 @@ template <class ELFT> void ObjFile<ELFT>::parse(bool ignoreComdats) { sections.resize(size); for (size_t i = 0; i != size; ++i) { const Elf_Shdr &sec = objSections[i]; + if (LLVM_LIKELY(sec.sh_type == SHT_PROGBITS)) continue; if (LLVM_LIKELY(sec.sh_type == SHT_GROUP)) { @@ -637,13 +674,6 @@ template <class ELFT> void ObjFile<ELFT>::parse(bool ignoreComdats) { } break; case EM_AARCH64: - // FIXME: BuildAttributes have been implemented in llvm, but not yet in - // lld. Remove the section so that it does not accumulate in the output - // file. When support is implemented we expect not to output a build - // attributes section in files of type ET_EXEC or ET_SHARED, but ld -r - // ouptut will need a single merged attributes section. - if (sec.sh_type == SHT_AARCH64_ATTRIBUTES) - sections[i] = &InputSection::discarded; // Producing a static binary with MTE globals is not currently supported, // remove all SHT_AARCH64_MEMTAG_GLOBALS_STATIC sections as they're unused // medatada, and we don't want them to end up in the output file for @@ -744,6 +774,8 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats, StringRef shstrtab = CHECK2(obj.getSectionStringTable(objSections), this); uint64_t size = objSections.size(); SmallVector<ArrayRef<Elf_Word>, 0> selectedGroups; + AArch64BuildAttrSubsections aarch64BAsubSections; + bool hasAArch64BuildAttributes = false; for (size_t i = 0; i != size; ++i) { if (this->sections[i] == &InputSection::discarded) continue; @@ -775,6 +807,26 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats, continue; } + // Processor-specific types that do not use the following switch statement. + // + // Extract Build Attributes section contents into aarch64BAsubSections. + // Input objects may contain both build Build Attributes and GNU + // properties. We delay processing Build Attributes until we have finished + // reading all sections so that we can check that these are consistent. + if (type == SHT_AARCH64_ATTRIBUTES && ctx.arg.emachine == EM_AARCH64) { + ArrayRef<uint8_t> contents = check(obj.getSectionContents(sec)); + AArch64AttributeParser attributes; + if (Error e = attributes.parse(contents, ELFT::Endianness)) { + StringRef name = check(obj.getSectionName(sec, shstrtab)); + InputSection isec(*this, sec, name); + Warn(ctx) << &isec << ": " << std::move(e); + } else { + aarch64BAsubSections = extractBuildAttributesSubsections(attributes); + hasAArch64BuildAttributes = true; + } + this->sections[i] = &InputSection::discarded; + continue; + } switch (type) { case SHT_GROUP: { if (!ctx.arg.relocatable) @@ -912,6 +964,12 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats, << linkSec; } + // Handle AArch64 Build Attributes and GNU properties: + // - Err on mismatched values. + // - Store missing values as GNU properties. + if (hasAArch64BuildAttributes) + handleAArch64BAAndGnuProperties<ELFT>(this, ctx, aarch64BAsubSections); + for (ArrayRef<Elf_Word> entries : selectedGroups) handleSectionGroup<ELFT>(this->sections, entries); } |