2121#include " llvm/ADT/STLExtras.h"
2222#include " llvm/LTO/LTO.h"
2323#include " llvm/Object/IRObjectFile.h"
24+ #include " llvm/Support/AArch64AttributeParser.h"
2425#include " llvm/Support/ARMAttributeParser.h"
2526#include " llvm/Support/ARMBuildAttributes.h"
2627#include " llvm/Support/Endian.h"
@@ -537,6 +538,41 @@ uint32_t ObjFile<ELFT>::getSectionIndex(const Elf_Sym &sym) const {
537538 this );
538539}
539540
541+ template <class ELFT >
542+ static void
543+ handleAArch64BAAndGnuProperties (ObjFile<ELFT> *file, Ctx &ctx,
544+ const AArch64BuildAttrSubsections &baInfo) {
545+ if (file->aarch64PauthAbiCoreInfo ) {
546+ // Check for data mismatch.
547+ if (file->aarch64PauthAbiCoreInfo ) {
548+ if (baInfo.Pauth .TagPlatform != file->aarch64PauthAbiCoreInfo ->platform ||
549+ baInfo.Pauth .TagSchema != file->aarch64PauthAbiCoreInfo ->version )
550+ Err (ctx) << file
551+ << " GNU properties and build attributes have conflicting "
552+ " AArch64 PAuth data" ;
553+ }
554+ if (baInfo.AndFeatures != file->andFeatures )
555+ Err (ctx) << file
556+ << " GNU properties and build attributes have conflicting "
557+ " AArch64 PAuth data" ;
558+ } else {
559+ // When BuildAttributes are missing, PauthABI value defaults to (TagPlatform
560+ // = 0, TagSchema = 0). GNU properties do not write PAuthAbiCoreInfo if GNU
561+ // property is not present. To match this behaviour, we only write
562+ // PAuthAbiCoreInfo when there is at least one non-zero value. The
563+ // specification reserves TagPlatform = 0, TagSchema = 1 values to match the
564+ // 'Invalid' GNU property section with platform = 0, version = 0.
565+ if (baInfo.Pauth .TagPlatform || baInfo.Pauth .TagSchema ) {
566+ if (baInfo.Pauth .TagPlatform == 0 && baInfo.Pauth .TagSchema == 1 )
567+ file->aarch64PauthAbiCoreInfo = {0 , 0 };
568+ else
569+ file->aarch64PauthAbiCoreInfo = {baInfo.Pauth .TagPlatform ,
570+ baInfo.Pauth .TagSchema };
571+ }
572+ file->andFeatures = baInfo.AndFeatures ;
573+ }
574+ }
575+
540576template <class ELFT > void ObjFile<ELFT>::parse(bool ignoreComdats) {
541577 object::ELFFile<ELFT> obj = this ->getObj ();
542578 // Read a section table. justSymbols is usually false.
@@ -554,6 +590,7 @@ template <class ELFT> void ObjFile<ELFT>::parse(bool ignoreComdats) {
554590 sections.resize (size);
555591 for (size_t i = 0 ; i != size; ++i) {
556592 const Elf_Shdr &sec = objSections[i];
593+
557594 if (LLVM_LIKELY (sec.sh_type == SHT_PROGBITS))
558595 continue ;
559596 if (LLVM_LIKELY (sec.sh_type == SHT_GROUP)) {
@@ -637,13 +674,6 @@ template <class ELFT> void ObjFile<ELFT>::parse(bool ignoreComdats) {
637674 }
638675 break ;
639676 case EM_AARCH64:
640- // FIXME: BuildAttributes have been implemented in llvm, but not yet in
641- // lld. Remove the section so that it does not accumulate in the output
642- // file. When support is implemented we expect not to output a build
643- // attributes section in files of type ET_EXEC or ET_SHARED, but ld -r
644- // ouptut will need a single merged attributes section.
645- if (sec.sh_type == SHT_AARCH64_ATTRIBUTES)
646- sections[i] = &InputSection::discarded;
647677 // Producing a static binary with MTE globals is not currently supported,
648678 // remove all SHT_AARCH64_MEMTAG_GLOBALS_STATIC sections as they're unused
649679 // 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,
744774 StringRef shstrtab = CHECK2 (obj.getSectionStringTable (objSections), this );
745775 uint64_t size = objSections.size ();
746776 SmallVector<ArrayRef<Elf_Word>, 0 > selectedGroups;
777+ AArch64BuildAttrSubsections aarch64BAsubSections;
778+ bool hasAArch64BuildAttributes = false ;
747779 for (size_t i = 0 ; i != size; ++i) {
748780 if (this ->sections [i] == &InputSection::discarded)
749781 continue ;
@@ -775,6 +807,26 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats,
775807 continue ;
776808 }
777809
810+ // Processor-specific types that do not use the following switch statement.
811+ //
812+ // Extract Build Attributes section contents into aarch64BAsubSections.
813+ // Input objects may contain both build Build Attributes and GNU
814+ // properties. We delay processing Build Attributes until we have finished
815+ // reading all sections so that we can check that these are consistent.
816+ if (type == SHT_AARCH64_ATTRIBUTES && ctx.arg .emachine == EM_AARCH64) {
817+ ArrayRef<uint8_t > contents = check (obj.getSectionContents (sec));
818+ AArch64AttributeParser attributes;
819+ if (Error e = attributes.parse (contents, ELFT::Endianness)) {
820+ StringRef name = check (obj.getSectionName (sec, shstrtab));
821+ InputSection isec (*this , sec, name);
822+ Warn (ctx) << &isec << " : " << std::move (e);
823+ } else {
824+ aarch64BAsubSections = extractBuildAttributesSubsections (attributes);
825+ hasAArch64BuildAttributes = true ;
826+ }
827+ this ->sections [i] = &InputSection::discarded;
828+ continue ;
829+ }
778830 switch (type) {
779831 case SHT_GROUP: {
780832 if (!ctx.arg .relocatable )
@@ -912,6 +964,12 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats,
912964 << linkSec;
913965 }
914966
967+ // Handle AArch64 Build Attributes and GNU properties:
968+ // - Err on mismatched values.
969+ // - Store missing values as GNU properties.
970+ if (hasAArch64BuildAttributes)
971+ handleAArch64BAAndGnuProperties<ELFT>(this , ctx, aarch64BAsubSections);
972+
915973 for (ArrayRef<Elf_Word> entries : selectedGroups)
916974 handleSectionGroup<ELFT>(this ->sections , entries);
917975}
0 commit comments