21
21
#include " llvm/ADT/STLExtras.h"
22
22
#include " llvm/LTO/LTO.h"
23
23
#include " llvm/Object/IRObjectFile.h"
24
+ #include " llvm/Support/AArch64AttributeParser.h"
24
25
#include " llvm/Support/ARMAttributeParser.h"
25
26
#include " llvm/Support/ARMBuildAttributes.h"
26
27
#include " llvm/Support/Endian.h"
@@ -537,6 +538,41 @@ uint32_t ObjFile<ELFT>::getSectionIndex(const Elf_Sym &sym) const {
537
538
this );
538
539
}
539
540
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
+
540
576
template <class ELFT > void ObjFile<ELFT>::parse(bool ignoreComdats) {
541
577
object::ELFFile<ELFT> obj = this ->getObj ();
542
578
// Read a section table. justSymbols is usually false.
@@ -554,6 +590,7 @@ template <class ELFT> void ObjFile<ELFT>::parse(bool ignoreComdats) {
554
590
sections.resize (size);
555
591
for (size_t i = 0 ; i != size; ++i) {
556
592
const Elf_Shdr &sec = objSections[i];
593
+
557
594
if (LLVM_LIKELY (sec.sh_type == SHT_PROGBITS))
558
595
continue ;
559
596
if (LLVM_LIKELY (sec.sh_type == SHT_GROUP)) {
@@ -637,13 +674,6 @@ template <class ELFT> void ObjFile<ELFT>::parse(bool ignoreComdats) {
637
674
}
638
675
break ;
639
676
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;
647
677
// Producing a static binary with MTE globals is not currently supported,
648
678
// remove all SHT_AARCH64_MEMTAG_GLOBALS_STATIC sections as they're unused
649
679
// 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,
744
774
StringRef shstrtab = CHECK2 (obj.getSectionStringTable (objSections), this );
745
775
uint64_t size = objSections.size ();
746
776
SmallVector<ArrayRef<Elf_Word>, 0 > selectedGroups;
777
+ AArch64BuildAttrSubsections aarch64BAsubSections;
778
+ bool hasAArch64BuildAttributes = false ;
747
779
for (size_t i = 0 ; i != size; ++i) {
748
780
if (this ->sections [i] == &InputSection::discarded)
749
781
continue ;
@@ -775,6 +807,26 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats,
775
807
continue ;
776
808
}
777
809
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
+ }
778
830
switch (type) {
779
831
case SHT_GROUP: {
780
832
if (!ctx.arg .relocatable )
@@ -912,6 +964,12 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats,
912
964
<< linkSec;
913
965
}
914
966
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
+
915
973
for (ArrayRef<Elf_Word> entries : selectedGroups)
916
974
handleSectionGroup<ELFT>(this ->sections , entries);
917
975
}
0 commit comments