diff --git a/llvm/include/llvm/BinaryFormat/DynamicTags.def b/llvm/include/llvm/BinaryFormat/DynamicTags.def index f393b82406b41d..1502d375f5c45d 100644 --- a/llvm/include/llvm/BinaryFormat/DynamicTags.def +++ b/llvm/include/llvm/BinaryFormat/DynamicTags.def @@ -132,6 +132,12 @@ AARCH64_DYNAMIC_TAG(AARCH64_MEMTAG_STACK, 0x7000000c) AARCH64_DYNAMIC_TAG(AARCH64_MEMTAG_GLOBALS, 0x7000000d) AARCH64_DYNAMIC_TAG(AARCH64_MEMTAG_GLOBALSSZ, 0x7000000f) +// AArch64 specific dynamic table entries for RELR auth relocations as described here: +// https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#dynamic-section +AARCH64_DYNAMIC_TAG(AARCH64_AUTH_RELRSZ, 0x70000011) +AARCH64_DYNAMIC_TAG(AARCH64_AUTH_RELR, 0x70000012) +AARCH64_DYNAMIC_TAG(AARCH64_AUTH_RELRENT, 0x70000013) + // Hexagon specific dynamic table entries HEXAGON_DYNAMIC_TAG(HEXAGON_SYMSZ, 0x70000000) HEXAGON_DYNAMIC_TAG(HEXAGON_VER, 0x70000001) diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h index d1ce8e20b4be73..40c795410f95ad 100644 --- a/llvm/include/llvm/BinaryFormat/ELF.h +++ b/llvm/include/llvm/BinaryFormat/ELF.h @@ -1060,6 +1060,9 @@ enum : unsigned { SHT_ARM_ATTRIBUTES = 0x70000003U, SHT_ARM_DEBUGOVERLAY = 0x70000004U, SHT_ARM_OVERLAYSECTION = 0x70000005U, + // Special aarch64-specific section for MTE support, as described in: + // https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#section-types + SHT_AARCH64_AUTH_RELR = 0x70000004U, // Special aarch64-specific sections for MTE support, as described in: // https://github.com/ARM-software/abi-aa/blob/main/memtagabielf64/memtagabielf64.rst#7section-types SHT_AARCH64_MEMTAG_GLOBALS_STATIC = 0x70000007U, @@ -1647,6 +1650,11 @@ enum { NT_ANDROID_TYPE_MEMTAG = 4, }; +// ARM note types. +enum { + NT_ARM_TYPE_PAUTH_ABI_TAG = 1, +}; + // Memory tagging values used in NT_ANDROID_TYPE_MEMTAG notes. enum { // Enumeration to determine the tagging mode. In Android-land, 'SYNC' means diff --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/AArch64.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/AArch64.def index b507109b19e1b9..b8ab5113bedf80 100644 --- a/llvm/include/llvm/BinaryFormat/ELFRelocs/AArch64.def +++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/AArch64.def @@ -135,6 +135,7 @@ ELF_RELOC(R_AARCH64_TLS_TPREL64, 0x406) ELF_RELOC(R_AARCH64_TLSDESC, 0x407) ELF_RELOC(R_AARCH64_IRELATIVE, 0x408) ELF_RELOC(R_AARCH64_AUTH_ABS64, 0xe100) +ELF_RELOC(R_AARCH64_AUTH_RELATIVE, 0xe200) // ELF_RELOC(R_AARCH64_P32_NONE, 0) ELF_RELOC(R_AARCH64_P32_ABS32, 0x001) diff --git a/llvm/lib/Object/ELF.cpp b/llvm/lib/Object/ELF.cpp index 1d73a6ffa73f5f..36847d1a2a4223 100644 --- a/llvm/lib/Object/ELF.cpp +++ b/llvm/lib/Object/ELF.cpp @@ -273,6 +273,7 @@ StringRef llvm::object::getELFSectionTypeName(uint32_t Machine, unsigned Type) { break; case ELF::EM_AARCH64: switch (Type) { + STRINGIFY_ENUM_CASE(ELF, SHT_AARCH64_AUTH_RELR); STRINGIFY_ENUM_CASE(ELF, SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC); STRINGIFY_ENUM_CASE(ELF, SHT_AARCH64_MEMTAG_GLOBALS_STATIC); } diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp index 1da4ea4e3edc91..c47d4eaa309dcd 100644 --- a/llvm/lib/ObjectYAML/ELFYAML.cpp +++ b/llvm/lib/ObjectYAML/ELFYAML.cpp @@ -719,6 +719,7 @@ void ScalarEnumerationTraits::enumeration( ECase(SHT_MSP430_ATTRIBUTES); break; case ELF::EM_AARCH64: + ECase(SHT_AARCH64_AUTH_RELR); ECase(SHT_AARCH64_MEMTAG_GLOBALS_STATIC); ECase(SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC); break; diff --git a/llvm/test/tools/llvm-readobj/ELF/AArch64/aarch64-feature-pauth.s b/llvm/test/tools/llvm-readobj/ELF/AArch64/aarch64-feature-pauth.s new file mode 100644 index 00000000000000..f28d92eae85754 --- /dev/null +++ b/llvm/test/tools/llvm-readobj/ELF/AArch64/aarch64-feature-pauth.s @@ -0,0 +1,98 @@ +# RUN: rm -rf %t && split-file %s %t && cd %t + +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag.s -o tag.o +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag-short.s -o tag-short.o +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu abi-tag-long.s -o tag-long.o + +# RUN: llvm-readelf --notes tag.o | FileCheck --check-prefix NORMAL %s +# RUN: llvm-readelf --notes tag-short.o | FileCheck --check-prefix SHORT %s +# RUN: llvm-readelf --notes tag-long.o | FileCheck --check-prefix LONG %s + +# NORMAL: AArch64 PAuth ABI tag: platform 0x2a, version 0x1 +# SHORT: AArch64 PAuth ABI tag: +# LONG: AArch64 PAuth ABI tag: platform 0x2a, version 0x1, additional info 0xEFCDAB8967452301 + +# RUN: llvm-readobj --notes tag.o | FileCheck --check-prefix LLVM-NORMAL %s +# RUN: llvm-readobj --notes tag-short.o | FileCheck --check-prefix LLVM-SHORT %s +# RUN: llvm-readobj --notes tag-long.o | FileCheck --check-prefix LLVM-LONG %s + +# LLVM-SHORT: Notes [ +# LLVM-SHORT-NEXT: NoteSection { +# LLVM-SHORT-NEXT: Name: .note.AARCH64-PAUTH-ABI-tag +# LLVM-SHORT-NEXT: Offset: 0x40 +# LLVM-SHORT-NEXT: Size: 0x1C +# LLVM-SHORT-NEXT: Note { +# LLVM-SHORT-NEXT: Owner: ARM +# LLVM-SHORT-NEXT: Data size: 0xC +# LLVM-SHORT-NEXT: Type: NT_ARM_TYPE_PAUTH_ABI_TAG +# LLVM-SHORT-NEXT: Description data ( +# LLVM-SHORT-NEXT: 0000: 2A000000 00000000 01000000 +# LLVM-SHORT-NEXT: ) +# LLVM-SHORT-NEXT: } +# LLVM-SHORT-NEXT: } +# LLVM-SHORT-NEXT: ] + +# LLVM-NORMAL: Notes [ +# LLVM-NORMAL-NEXT: NoteSection { +# LLVM-NORMAL-NEXT: Name: .note.AARCH64-PAUTH-ABI-tag +# LLVM-NORMAL-NEXT: Offset: 0x40 +# LLVM-NORMAL-NEXT: Size: 0x20 +# LLVM-NORMAL-NEXT: Note { +# LLVM-NORMAL-NEXT: Owner: ARM +# LLVM-NORMAL-NEXT: Data size: 0x10 +# LLVM-NORMAL-NEXT: Type: NT_ARM_TYPE_PAUTH_ABI_TAG +# LLVM-NORMAL-NEXT: Platform: 42 +# LLVM-NORMAL-NEXT: Version: 1 +# LLVM-NORMAL-NEXT: } +# LLVM-NORMAL-NEXT: } +# LLVM-NORMAL-NEXT: ] + +# LLVM-LONG: Notes [ +# LLVM-LONG-NEXT: NoteSection { +# LLVM-LONG-NEXT: Name: .note.AARCH64-PAUTH-ABI-tag +# LLVM-LONG-NEXT: Offset: 0x40 +# LLVM-LONG-NEXT: Size: 0x28 +# LLVM-LONG-NEXT: Note { +# LLVM-LONG-NEXT: Owner: ARM +# LLVM-LONG-NEXT: Data size: 0x18 +# LLVM-LONG-NEXT: Type: NT_ARM_TYPE_PAUTH_ABI_TAG +# LLVM-LONG-NEXT: Platform: 42 +# LLVM-LONG-NEXT: Version: 1 +# LLVM-LONG-NEXT: Additional info: EFCDAB8967452301 +# LLVM-LONG-NEXT: } +# LLVM-LONG-NEXT: } +# LLVM-LONG-NEXT: ] + +#--- abi-tag.s + +.section ".note.AARCH64-PAUTH-ABI-tag", "a" +.long 4 +.long 16 +.long 1 +.asciz "ARM" + +.quad 42 // platform +.quad 1 // version + +#--- abi-tag-short.s + +.section ".note.AARCH64-PAUTH-ABI-tag", "a" +.long 4 +.long 12 +.long 1 +.asciz "ARM" + +.quad 42 +.word 1 + +#--- abi-tag-long.s + +.section ".note.AARCH64-PAUTH-ABI-tag", "a" +.long 4 +.long 24 +.long 1 +.asciz "ARM" + +.quad 42 // platform +.quad 1 // version +.quad 0x0123456789ABCDEF // extra data diff --git a/llvm/test/tools/llvm-readobj/ELF/broken-dynamic-reloc.test b/llvm/test/tools/llvm-readobj/ELF/broken-dynamic-reloc.test index 1a1c6dd4d0d1c2..f4899f6df65131 100644 --- a/llvm/test/tools/llvm-readobj/ELF/broken-dynamic-reloc.test +++ b/llvm/test/tools/llvm-readobj/ELF/broken-dynamic-reloc.test @@ -459,3 +459,43 @@ ProgramHeaders: - Type: PT_DYNAMIC FirstSec: .dynamic LastSec: .dynamic + +## Show we print a warning for an invalid relocation table size stored in a DT_AARCH64_AUTH_RELRSZ entry. +# RUN: yaml2obj --docnum=8 -DRELTYPE=RELR -DTAG1=DT_AARCH64_AUTH_RELRSZ -DTAG1VAL=0xFF -DTAG2=DT_AARCH64_AUTH_RELRENT %s -o %t14 +# RUN: llvm-readobj --dyn-relocations %t14 2>&1 | FileCheck %s -DFILE=%t14 --check-prefix=INVALID-DT-AARCH64-AUTH-RELRSZ +# RUN: llvm-readelf --dyn-relocations %t14 2>&1 | FileCheck %s -DFILE=%t14 --check-prefix=INVALID-DT-AARCH64-AUTH-RELRSZ + +# INVALID-DT-AARCH64-AUTH-RELRSZ: warning: '[[FILE]]': invalid DT_AARCH64_AUTH_RELRSZ value (0xff) or DT_AARCH64_AUTH_RELRENT value (0x18) + +## Show we print a warning for an invalid relocation table entry size stored in a DT_AARCH64_AUTH_RELRENT entry. +# RUN: yaml2obj --docnum=8 -DRELTYPE=RELR -DTAG1=DT_AARCH64_AUTH_RELRSZ -DTAG2=DT_AARCH64_AUTH_RELRENT -DTAG2VAL=0xFF %s -o %t15 +# RUN: llvm-readobj --dyn-relocations %t15 2>&1 | FileCheck %s -DFILE=%t15 --check-prefix=INVALID-DT-AARCH64-AUTH-RELRENT +# RUN: llvm-readelf --dyn-relocations %t15 2>&1 | FileCheck %s -DFILE=%t15 --check-prefix=INVALID-DT-AARCH64-AUTH-RELRENT + +# INVALID-DT-AARCH64-AUTH-RELRENT: invalid DT_AARCH64_AUTH_RELRSZ value (0x18) or DT_AARCH64_AUTH_RELRENT value (0xff) + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_AARCH64 +Sections: + - Name: .relx.dyn + Type: SHT_[[RELTYPE]] + - Name: .dynamic + Type: SHT_DYNAMIC + Entries: + - Tag: DT_[[RELTYPE]] + Value: 0x0 + - Tag: [[TAG1]] + Value: [[TAG1VAL=0x18]] + - Tag: [[TAG2]] + Value: [[TAG2VAL=0x18]] + - Tag: DT_NULL + Value: 0x0 +DynamicSymbols: [] +ProgramHeaders: + - Type: PT_LOAD + FirstSec: .relx.dyn + LastSec: .dynamic diff --git a/llvm/test/tools/llvm-readobj/ELF/dynamic-tags-machine-specific.test b/llvm/test/tools/llvm-readobj/ELF/dynamic-tags-machine-specific.test index c32ea33b9b3cbf..e7bd9cf9b48b23 100644 --- a/llvm/test/tools/llvm-readobj/ELF/dynamic-tags-machine-specific.test +++ b/llvm/test/tools/llvm-readobj/ELF/dynamic-tags-machine-specific.test @@ -355,20 +355,26 @@ ProgramHeaders: # RUN: llvm-readobj --dynamic-table %t.aarch64 | FileCheck %s --check-prefix=LLVM-AARCH64 # RUN: llvm-readelf --dynamic-table %t.aarch64 | FileCheck %s --check-prefix=GNU-AARCH64 -# LLVM-AARCH64: DynamicSection [ (4 entries) +# LLVM-AARCH64: DynamicSection [ (7 entries) # LLVM-AARCH64-NEXT: Tag Type Name/Value -# LLVM-AARCH64-NEXT: 0x0000000070000001 AARCH64_BTI_PLT 1 -# LLVM-AARCH64-NEXT: 0x0000000070000003 AARCH64_PAC_PLT 2 -# LLVM-AARCH64-NEXT: 0x0000000070000005 AARCH64_VARIANT_PCS 3 -# LLVM-AARCH64-NEXT: 0x0000000000000000 NULL 0x0 +# LLVM-AARCH64-NEXT: 0x0000000070000001 AARCH64_BTI_PLT 1 +# LLVM-AARCH64-NEXT: 0x0000000070000003 AARCH64_PAC_PLT 2 +# LLVM-AARCH64-NEXT: 0x0000000070000005 AARCH64_VARIANT_PCS 3 +# LLVM-AARCH64-NEXT: 0x0000000070000012 AARCH64_AUTH_RELR 0x4 +# LLVM-AARCH64-NEXT: 0x0000000070000011 AARCH64_AUTH_RELRSZ 5 +# LLVM-AARCH64-NEXT: 0x0000000070000013 AARCH64_AUTH_RELRENT 6 +# LLVM-AARCH64-NEXT: 0x0000000000000000 NULL 0x0 # LLVM-AARCH64-NEXT:] -# GNU-AARCH64: Dynamic section at offset {{.*}} contains 4 entries: +# GNU-AARCH64: Dynamic section at offset {{.*}} contains 7 entries: # GNU-AARCH64-NEXT: Tag Type Name/Value -# GNU-AARCH64-NEXT: 0x0000000070000001 (AARCH64_BTI_PLT) 1 -# GNU-AARCH64-NEXT: 0x0000000070000003 (AARCH64_PAC_PLT) 2 -# GNU-AARCH64-NEXT: 0x0000000070000005 (AARCH64_VARIANT_PCS) 3 -# GNU-AARCH64-NEXT: 0x0000000000000000 (NULL) 0x0 +# GNU-AARCH64-NEXT: 0x0000000070000001 (AARCH64_BTI_PLT) 1 +# GNU-AARCH64-NEXT: 0x0000000070000003 (AARCH64_PAC_PLT) 2 +# GNU-AARCH64-NEXT: 0x0000000070000005 (AARCH64_VARIANT_PCS) 3 +# GNU-AARCH64-NEXT: 0x0000000070000012 (AARCH64_AUTH_RELR) 0x4 +# GNU-AARCH64-NEXT: 0x0000000070000011 (AARCH64_AUTH_RELRSZ) 5 +# GNU-AARCH64-NEXT: 0x0000000070000013 (AARCH64_AUTH_RELRENT) 6 +# GNU-AARCH64-NEXT: 0x0000000000000000 (NULL) 0x0 --- !ELF FileHeader: @@ -386,6 +392,12 @@ Sections: Value: 2 - Tag: DT_AARCH64_VARIANT_PCS Value: 3 + - Tag: DT_AARCH64_AUTH_RELR + Value: 4 + - Tag: DT_AARCH64_AUTH_RELRSZ + Value: 5 + - Tag: DT_AARCH64_AUTH_RELRENT + Value: 6 - Tag: DT_NULL Value: 0 ProgramHeaders: diff --git a/llvm/test/tools/llvm-readobj/ELF/machine-specific-section-types.test b/llvm/test/tools/llvm-readobj/ELF/machine-specific-section-types.test index 99fafe35fa4433..f9524383e80b6d 100644 --- a/llvm/test/tools/llvm-readobj/ELF/machine-specific-section-types.test +++ b/llvm/test/tools/llvm-readobj/ELF/machine-specific-section-types.test @@ -53,11 +53,14 @@ # MIPS-GNU: abiflags MIPS_ABIFLAGS # MIPS-GNU: dwarf MIPS_DWARF +# AARCH64-LLVM: Name: aarch64_auth_relr +# AARCH64-LLVM: Type: SHT_AARCH64_AUTH_RELR # AARCH64-LLVM: Name: .memtag.globals.dynamic # AARCH64-LLVM: Type: SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC # AARCH64-LLVM: Name: .memtag.globals.static # AARCH64-LLVM: Type: SHT_AARCH64_MEMTAG_GLOBALS_STATIC +# AARCH64-GNU: aarch64_auth_relr AARCH64_AUTH_RELR # AARCH64-GNU: .memtag.globals.dynamic AARCH64_MEMTAG_GLOBALS_DYNAMIC # AARCH64-GNU: .memtag.globals.static AARCH64_MEMTAG_GLOBALS_STATIC @@ -113,6 +116,8 @@ FileHeader: Type: ET_REL Machine: EM_AARCH64 Sections: + - Name: aarch64_auth_relr + Type: SHT_AARCH64_AUTH_RELR - Name: .memtag.globals.dynamic Type: SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC - Name: .memtag.globals.static diff --git a/llvm/test/tools/llvm-readobj/ELF/relr-relocs.test b/llvm/test/tools/llvm-readobj/ELF/relr-relocs.test index 3bb54b1adc1f4f..91b148ebb6e3c8 100644 --- a/llvm/test/tools/llvm-readobj/ELF/relr-relocs.test +++ b/llvm/test/tools/llvm-readobj/ELF/relr-relocs.test @@ -158,7 +158,7 @@ Sections: Link: [[LINK=]] ## Check we report a warning when we are unable to dump relocations -## for a SHT_RELR/SHT_ANDROID_RELR section. +## for a SHT_RELR/SHT_ANDROID_RELR/SHT_AARCH64_AUTH_RELR section. ## Case A: check the case when relocations can't be read from an SHT_RELR section. # RUN: yaml2obj --docnum=2 -DENTSIZE=1 %s -o %t2.broken @@ -186,7 +186,20 @@ Sections: # RUN: llvm-readelf --relocations %t2.broken.android 2>&1 | \ # RUN: FileCheck -DFILE=%t2.broken.android --check-prefix=BROKEN-GNU %s -DSECNAME=SHT_ANDROID_RELR -## Check the behavior when the sh_link field of the SHT_RELR/SHT_ANDROID_RELR section +## Case C: check the case when we have an SHT_AARCH64_AUTH_RELR section in non-AArch64 ELF. +## SHT_AARCH64_AUTH_RELR = 0x70000004. +# RUN: yaml2obj --docnum=2 -DENTSIZE=1 -DSHTYPE=0x70000004 %s -o %t2.broken.aarch64auth +# RUN: llvm-readobj --relocations %t2.broken.aarch64auth 2>&1 | \ +# RUN: FileCheck -DFILE=%t2.broken.aarch64auth --check-prefix=WRONGARCH-LLVM-AARCH64-AUTH %s -DSECNAME=SHT_AARCH64_AUTH_RELR +# RUN: llvm-readelf --relocations %t2.broken.aarch64auth 2>&1 | \ +# RUN: FileCheck -DFILE=%t2.broken.aarch64auth --check-prefix=WRONGARCH-GNU-AARCH64-AUTH %s -DSECNAME=SHT_AARCH64_AUTH_RELR + +# WRONGARCH-LLVM-AARCH64-AUTH: Relocations [ +# WRONGARCH-LLVM-AARCH64-AUTH-NEXT: ] + +# WRONGARCH-GNU-AARCH64-AUTH-NOT: Relocation section + +## Check the behavior when the sh_link field of the SHT_RELR/SHT_ANDROID_RELR/SHT_AARCH64_AUTH_RELR section ## is set to an arbitrary value. Normally, it is set to 0, because such sections contains ## only relative relocations and do not have an associated symbol table, like other ## relocation sections. diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index d6d0ea35044ab3..3e20edfff66458 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -2027,6 +2027,18 @@ template void ELFDumper::parseDynamicTable() { uint64_t StringTableSize = 0; std::optional DynSymFromTable; for (const Elf_Dyn &Dyn : dynamic_table()) { + if (Obj.getHeader().e_machine == EM_AARCH64) { + switch (Dyn.d_tag) { + case ELF::DT_AARCH64_AUTH_RELRSZ: + DynRelrRegion.Size = Dyn.getVal(); + DynRelrRegion.SizePrintName = "DT_AARCH64_AUTH_RELRSZ value"; + continue; + case ELF::DT_AARCH64_AUTH_RELRENT: + DynRelrRegion.EntSize = Dyn.getVal(); + DynRelrRegion.EntSizePrintName = "DT_AARCH64_AUTH_RELRENT value"; + continue; + } + } switch (Dyn.d_tag) { case ELF::DT_HASH: HashTable = reinterpret_cast( @@ -2090,10 +2102,12 @@ template void ELFDumper::parseDynamicTable() { break; case ELF::DT_RELR: case ELF::DT_ANDROID_RELR: + case ELF::DT_AARCH64_AUTH_RELR: DynRelrRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr()); break; case ELF::DT_RELRSZ: case ELF::DT_ANDROID_RELRSZ: + case ELF::DT_AARCH64_AUTH_RELRSZ: DynRelrRegion.Size = Dyn.getVal(); DynRelrRegion.SizePrintName = Dyn.d_tag == ELF::DT_RELRSZ ? "DT_RELRSZ value" @@ -2101,6 +2115,7 @@ template void ELFDumper::parseDynamicTable() { break; case ELF::DT_RELRENT: case ELF::DT_ANDROID_RELRENT: + case ELF::DT_AARCH64_AUTH_RELRENT: DynRelrRegion.EntSize = Dyn.getVal(); DynRelrRegion.EntSizePrintName = Dyn.d_tag == ELF::DT_RELRENT ? "DT_RELRENT value" @@ -2467,6 +2482,8 @@ std::string ELFDumper::getDynamicEntry(uint64_t Type, case DT_PREINIT_ARRAYSZ: case DT_RELRSZ: case DT_RELRENT: + case DT_AARCH64_AUTH_RELRSZ: + case DT_AARCH64_AUTH_RELRENT: case DT_ANDROID_RELSZ: case DT_ANDROID_RELASZ: return std::to_string(Value) + " (bytes)"; @@ -3799,9 +3816,12 @@ void GNUELFDumper::printRelRelaReloc(const Relocation &R, } template -static void printRelocHeaderFields(formatted_raw_ostream &OS, unsigned SType) { +static void printRelocHeaderFields(formatted_raw_ostream &OS, unsigned SType, + const typename ELFT::Ehdr &EHeader) { bool IsRela = SType == ELF::SHT_RELA || SType == ELF::SHT_ANDROID_RELA; - bool IsRelr = SType == ELF::SHT_RELR || SType == ELF::SHT_ANDROID_RELR; + bool IsRelr = + SType == ELF::SHT_RELR || SType == ELF::SHT_ANDROID_RELR || + (EHeader.e_machine == EM_AARCH64 && SType == ELF::SHT_AARCH64_AUTH_RELR); if (ELFT::Is64Bits) OS << " "; else @@ -3826,15 +3846,18 @@ void GNUELFDumper::printDynamicRelocHeader(unsigned Type, StringRef Name, uint64_t Offset = Reg.Addr - this->Obj.base(); OS << "\n'" << Name.str().c_str() << "' relocation section at offset 0x" << utohexstr(Offset, /*LowerCase=*/true) << " contains " << Reg.Size << " bytes:\n"; - printRelocHeaderFields(OS, Type); + printRelocHeaderFields(OS, Type, this->Obj.getHeader()); } template -static bool isRelocationSec(const typename ELFT::Shdr &Sec) { +static bool isRelocationSec(const typename ELFT::Shdr &Sec, + const typename ELFT::Ehdr &EHeader) { return Sec.sh_type == ELF::SHT_REL || Sec.sh_type == ELF::SHT_RELA || Sec.sh_type == ELF::SHT_RELR || Sec.sh_type == ELF::SHT_ANDROID_REL || Sec.sh_type == ELF::SHT_ANDROID_RELA || - Sec.sh_type == ELF::SHT_ANDROID_RELR; + Sec.sh_type == ELF::SHT_ANDROID_RELR || + (EHeader.e_machine == EM_AARCH64 && + Sec.sh_type == ELF::SHT_AARCH64_AUTH_RELR); } template void GNUELFDumper::printRelocations() { @@ -3850,8 +3873,10 @@ template void GNUELFDumper::printRelocations() { return RelasOrErr->size(); } - if (!opts::RawRelr && (Sec.sh_type == ELF::SHT_RELR || - Sec.sh_type == ELF::SHT_ANDROID_RELR)) { + if (!opts::RawRelr && + (Sec.sh_type == ELF::SHT_RELR || Sec.sh_type == ELF::SHT_ANDROID_RELR || + (this->Obj.getHeader().e_machine == EM_AARCH64 && + Sec.sh_type == ELF::SHT_AARCH64_AUTH_RELR))) { Expected RelrsOrErr = this->Obj.relrs(Sec); if (!RelrsOrErr) return RelrsOrErr.takeError(); @@ -3863,7 +3888,7 @@ template void GNUELFDumper::printRelocations() { bool HasRelocSections = false; for (const Elf_Shdr &Sec : cantFail(this->Obj.sections())) { - if (!isRelocationSec(Sec)) + if (!isRelocationSec(Sec, this->Obj.getHeader())) continue; HasRelocSections = true; @@ -3880,7 +3905,7 @@ template void GNUELFDumper::printRelocations() { OS << "\nRelocation section '" << Name << "' at offset 0x" << utohexstr(Offset, /*LowerCase=*/true) << " contains " << EntriesNum << " entries:\n"; - printRelocHeaderFields(OS, Sec.sh_type); + printRelocHeaderFields(OS, Sec.sh_type, this->Obj.getHeader()); this->printRelocationsHelper(Sec); } if (!HasRelocSections) @@ -5312,6 +5337,31 @@ static bool printAndroidNote(raw_ostream &OS, uint32_t NoteType, return true; } +template +static bool printAArch64Note(raw_ostream &OS, uint32_t NoteType, + ArrayRef Desc) { + if (NoteType != NT_ARM_TYPE_PAUTH_ABI_TAG) + return false; + + OS << " AArch64 PAuth ABI tag: "; + if (Desc.size() < 16) { + OS << format("", Desc.size()); + return false; + } + + uint64_t Platform = + support::endian::read64(Desc.data() + 0); + uint64_t Version = + support::endian::read64(Desc.data() + 8); + OS << format("platform 0x%x, version 0x%x", Platform, Version); + + if (Desc.size() > 16) + OS << ", additional info 0x" + << toHex(ArrayRef(Desc.data() + 16, Desc.size() - 16)); + + return true; +} + template void GNUELFDumper::printMemtag( const ArrayRef> DynamicEntries, @@ -5711,6 +5761,10 @@ const NoteType AndroidNoteTypes[] = { "NT_ANDROID_TYPE_MEMTAG (Android memory tagging information)"}, }; +const NoteType ARMNoteTypes[] = { + {ELF::NT_ARM_TYPE_PAUTH_ABI_TAG, "NT_ARM_TYPE_PAUTH_ABI_TAG"}, +}; + const NoteType CoreNoteTypes[] = { {ELF::NT_PRSTATUS, "NT_PRSTATUS (prstatus structure)"}, {ELF::NT_FPREGSET, "NT_FPREGSET (floating point registers)"}, @@ -5829,6 +5883,8 @@ StringRef getNoteTypeName(const typename ELFT::Note &Note, unsigned ELFType) { return FindNote(LLVMOMPOFFLOADNoteTypes); if (Name == "Android") return FindNote(AndroidNoteTypes); + if (Name == "ARM") + return FindNote(ARMNoteTypes); if (ELFType == ELF::ET_CORE) return FindNote(CoreNoteTypes); @@ -5984,6 +6040,9 @@ template void GNUELFDumper::printNotes() { } else if (Name == "Android") { if (printAndroidNote(OS, Type, Descriptor)) return Error::success(); + } else if (Name == "ARM") { + if (printAArch64Note(OS, Type, Descriptor)) + return Error::success(); } if (!Descriptor.empty()) { OS << " description data:"; @@ -6176,11 +6235,13 @@ void ELFDumper::forEachRelocationDo( toString(std::move(E))); }; - // SHT_RELR/SHT_ANDROID_RELR sections do not have an associated symbol table. - // For them we should not treat the value of the sh_link field as an index of - // a symbol table. + // SHT_RELR/SHT_ANDROID_RELR/SHT_AARCH64_AUTH_RELR sections do not have an + // associated symbol table. For them we should not treat the value of the + // sh_link field as an index of a symbol table. const Elf_Shdr *SymTab; - if (Sec.sh_type != ELF::SHT_RELR && Sec.sh_type != ELF::SHT_ANDROID_RELR) { + if (Sec.sh_type != ELF::SHT_RELR && Sec.sh_type != ELF::SHT_ANDROID_RELR && + !(Obj.getHeader().e_machine == EM_AARCH64 && + Sec.sh_type == ELF::SHT_AARCH64_AUTH_RELR)) { Expected SymTabOrErr = Obj.getSection(Sec.sh_link); if (!SymTabOrErr) { Warn(SymTabOrErr.takeError(), "unable to locate a symbol table for"); @@ -6208,6 +6269,10 @@ void ELFDumper::forEachRelocationDo( Warn(RangeOrErr.takeError()); } break; + case ELF::SHT_AARCH64_AUTH_RELR: + if (Obj.getHeader().e_machine != EM_AARCH64) + break; + [[fallthrough]]; case ELF::SHT_RELR: case ELF::SHT_ANDROID_RELR: { Expected RangeOrErr = Obj.relrs(Sec); @@ -6904,7 +6969,7 @@ template void LLVMELFDumper::printRelocations() { ListScope D(W, "Relocations"); for (const Elf_Shdr &Sec : cantFail(this->Obj.sections())) { - if (!isRelocationSec(Sec)) + if (!isRelocationSec(Sec, this->Obj.getHeader())) continue; StringRef Name = this->getPrintableSectionName(Sec); @@ -7545,6 +7610,29 @@ static bool printAndroidNoteLLVMStyle(uint32_t NoteType, ArrayRef Desc, return true; } +template +static bool printAarch64NoteLLVMStyle(uint32_t NoteType, ArrayRef Desc, + ScopedPrinter &W) { + if (NoteType != NT_ARM_TYPE_PAUTH_ABI_TAG) + return false; + + if (Desc.size() < 16) + return false; + + uint64_t platform = + support::endian::read64(Desc.data() + 0); + uint64_t version = + support::endian::read64(Desc.data() + 8); + W.printNumber("Platform", platform); + W.printNumber("Version", version); + + if (Desc.size() > 16) + W.printString("Additional info", + toHex(ArrayRef(Desc.data() + 16, Desc.size() - 16))); + + return true; +} + template void LLVMELFDumper::printMemtag( const ArrayRef> DynamicEntries, @@ -7681,6 +7769,9 @@ template void LLVMELFDumper::printNotes() { } else if (Name == "Android") { if (printAndroidNoteLLVMStyle(Type, Descriptor, W)) return Error::success(); + } else if (Name == "ARM") { + if (printAarch64NoteLLVMStyle(Type, Descriptor, W)) + return Error::success(); } if (!Descriptor.empty()) { W.printBinaryBlock("Description data", Descriptor);