aboutsummaryrefslogtreecommitdiff
path: root/lld/ELF/InputFiles.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF/InputFiles.cpp')
-rw-r--r--lld/ELF/InputFiles.cpp72
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);
}