From ea59dbbacde825433b787d07e0612680e58f2d5c Mon Sep 17 00:00:00 2001 From: Daniil Kovalev Date: Tue, 12 Mar 2024 20:40:16 +0300 Subject: [PATCH] [PAC][llvm-readobj][AArch64][ELF] Support `GNU_PROPERTY_AARCH64_FEATURE_PAUTH` This adds support for `GNU_PROPERTY_AARCH64_FEATURE_PAUTH` feature handling in llvm-readobj and llvm-readelf. The following constants for supported platforms are also introduced: - `AARCH64_PAUTH_PLATFORM_INVALID = 0x0` - `AARCH64_PAUTH_PLATFORM_BAREMETAL = 0x1` - `AARCH64_PAUTH_PLATFORM_LLVM_LINUX = 0x10000002` For the llvm_linux platform, output of the tools contains descriptions of PAuth features which are enabled/disabled depending on the version value. Version value bits correspond to the following `LangOptions`: - bit 0: `PointerAuthIntrinsics`; - bit 1: `PointerAuthCalls`; - bit 2: `PointerAuthReturns`; - bit 3: `PointerAuthAuthTraps`; - bit 4: `PointerAuthVTPtrAddressDiscrimination`; - bit 5: `PointerAuthVTPtrTypeDiscrimination`; - bit 6: `PointerAuthInitFini`. --- llvm/include/llvm/BinaryFormat/ELF.h | 8 + .../ELF/AArch64/aarch64-feature-pauth.s | 395 +++++++++++++++--- .../ELF/AArch64/aarch64-note-gnu-property.s | 2 + llvm/tools/llvm-readobj/ELFDumper.cpp | 110 +++-- 4 files changed, 421 insertions(+), 94 deletions(-) diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h index bace3a92677a82..178461daaf1a05 100644 --- a/llvm/include/llvm/BinaryFormat/ELF.h +++ b/llvm/include/llvm/BinaryFormat/ELF.h @@ -1738,6 +1738,7 @@ enum : unsigned { GNU_PROPERTY_STACK_SIZE = 1, GNU_PROPERTY_NO_COPY_ON_PROTECTED = 2, GNU_PROPERTY_AARCH64_FEATURE_1_AND = 0xc0000000, + GNU_PROPERTY_AARCH64_FEATURE_PAUTH = 0xc0000001, GNU_PROPERTY_X86_FEATURE_1_AND = 0xc0000002, GNU_PROPERTY_X86_UINT32_OR_LO = 0xc0008000, @@ -1756,6 +1757,13 @@ enum : unsigned { GNU_PROPERTY_AARCH64_FEATURE_1_GCS = 1 << 2, }; +// aarch64 PAuth platforms. +enum : unsigned { + AARCH64_PAUTH_PLATFORM_INVALID = 0x0, + AARCH64_PAUTH_PLATFORM_BAREMETAL = 0x1, + AARCH64_PAUTH_PLATFORM_LLVM_LINUX = 0x10000002, +}; + // x86 processor feature bits. enum : unsigned { GNU_PROPERTY_X86_FEATURE_1_IBT = 1 << 0, 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 index f28d92eae85754..526e7debf769ec 100644 --- a/llvm/test/tools/llvm-readobj/ELF/AArch64/aarch64-feature-pauth.s +++ b/llvm/test/tools/llvm-readobj/ELF/AArch64/aarch64-feature-pauth.s @@ -1,69 +1,6 @@ # 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 +#--- tag-42-1.s .section ".note.AARCH64-PAUTH-ABI-tag", "a" .long 4 @@ -74,7 +11,101 @@ .quad 42 // platform .quad 1 // version -#--- abi-tag-short.s +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu tag-42-1.s -o tag-42-1.o +# RUN: llvm-readelf --notes tag-42-1.o | \ +# RUN: FileCheck --check-prefix ELF-TAG -DPLATFORM="0x2a (unknown)" -DVERSION=0x1 %s +# RUN: llvm-readobj --notes tag-42-1.o | \ +# RUN: FileCheck --check-prefix OBJ-TAG -DPLATFORM=42 -DPLATFORMDESC=unknown -DVERSION=1 %s + +# ELF-TAG: AArch64 PAuth ABI tag: platform [[PLATFORM]], version [[VERSION]] + +# OBJ-TAG: Notes [ +# OBJ-TAG-NEXT: NoteSection { +# OBJ-TAG-NEXT: Name: .note.AARCH64-PAUTH-ABI-tag +# OBJ-TAG-NEXT: Offset: 0x40 +# OBJ-TAG-NEXT: Size: 0x20 +# OBJ-TAG-NEXT: Note { +# OBJ-TAG-NEXT: Owner: ARM +# OBJ-TAG-NEXT: Data size: 0x10 +# OBJ-TAG-NEXT: Type: NT_ARM_TYPE_PAUTH_ABI_TAG +# OBJ-TAG-NEXT: Platform: [[PLATFORM]] +# OBJ-TAG-NEXT: PlatformDesc: [[PLATFORMDESC]] +# OBJ-TAG-NEXT: Version: [[VERSION]] +# OBJ-TAG-NEXT: } +# OBJ-TAG-NEXT: } +# OBJ-TAG-NEXT: ] + +#--- tag-0-0.s + +.section ".note.AARCH64-PAUTH-ABI-tag", "a" +.long 4 +.long 16 +.long 1 +.asciz "ARM" + +.quad 0 // platform +.quad 0 // version + +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu tag-0-0.s -o tag-0-0.o +# RUN: llvm-readelf --notes tag-0-0.o | \ +# RUN: FileCheck --check-prefix ELF-TAG -DPLATFORM="0x0 (invalid)" -DVERSION=0x0 %s +# RUN: llvm-readobj --notes tag-0-0.o | \ +# RUN: FileCheck --check-prefix OBJ-TAG -DPLATFORM=0 -DPLATFORMDESC=invalid -DVERSION=0 %s + +#--- tag-1-0.s + +.section ".note.AARCH64-PAUTH-ABI-tag", "a" +.long 4 +.long 16 +.long 1 +.asciz "ARM" + +.quad 1 // platform +.quad 0 // version + +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu tag-1-0.s -o tag-1-0.o +# RUN: llvm-readelf --notes tag-1-0.o | \ +# RUN: FileCheck --check-prefix ELF-TAG -DPLATFORM="0x1 (baremetal)" -DVERSION=0x0 %s +# RUN: llvm-readobj --notes tag-1-0.o | \ +# RUN: FileCheck --check-prefix OBJ-TAG -DPLATFORM=1 -DPLATFORMDESC=baremetal -DVERSION=0 %s + +#--- tag-0x10000002-85.s + +.section ".note.AARCH64-PAUTH-ABI-tag", "a" +.long 4 +.long 16 +.long 1 +.asciz "ARM" + +.quad 0x10000002 // platform +.quad 85 // version + +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu tag-0x10000002-85.s -o tag-0x10000002-85.o +# RUN: llvm-readelf --notes tag-0x10000002-85.o | \ +# RUN: FileCheck --check-prefix ELF-TAG -DPLATFORM="0x10000002 (llvm_linux)" \ +# RUN: -DVERSION="0x55 (PointerAuthIntrinsics, !PointerAuthCalls, PointerAuthReturns, !PointerAuthAuthTraps, PointerAuthVTPtrAddressDiscrimination, !PointerAuthVTPtrTypeDiscrimination, PointerAuthInitFini)" %s +# RUN: llvm-readobj --notes tag-0x10000002-85.o | \ +# RUN: FileCheck --check-prefix OBJ-TAG-LINUX -DPLATFORM=268435458 -DPLATFORMDESC=llvm_linux -DVERSION=85 \ +# RUN: -DVERSIONDESC="PointerAuthIntrinsics, !PointerAuthCalls, PointerAuthReturns, !PointerAuthAuthTraps, PointerAuthVTPtrAddressDiscrimination, !PointerAuthVTPtrTypeDiscrimination, PointerAuthInitFini" %s + +# OBJ-TAG-LINUX: Notes [ +# OBJ-TAG-LINUX-NEXT: NoteSection { +# OBJ-TAG-LINUX-NEXT: Name: .note.AARCH64-PAUTH-ABI-tag +# OBJ-TAG-LINUX-NEXT: Offset: 0x40 +# OBJ-TAG-LINUX-NEXT: Size: 0x20 +# OBJ-TAG-LINUX-NEXT: Note { +# OBJ-TAG-LINUX-NEXT: Owner: ARM +# OBJ-TAG-LINUX-NEXT: Data size: 0x10 +# OBJ-TAG-LINUX-NEXT: Type: NT_ARM_TYPE_PAUTH_ABI_TAG +# OBJ-TAG-LINUX-NEXT: Platform: [[PLATFORM]] +# OBJ-TAG-LINUX-NEXT: PlatformDesc: [[PLATFORMDESC]] +# OBJ-TAG-LINUX-NEXT: Version: [[VERSION]] +# OBJ-TAG-LINUX-NEXT: VersionDesc: [[VERSIONDESC]] +# OBJ-TAG-LINUX-NEXT: } +# OBJ-TAG-LINUX-NEXT: } +# OBJ-TAG-LINUX-NEXT: ] + +#--- tag-short.s .section ".note.AARCH64-PAUTH-ABI-tag", "a" .long 4 @@ -85,7 +116,29 @@ .quad 42 .word 1 -#--- abi-tag-long.s +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu tag-short.s -o tag-short.o +# RUN: llvm-readelf --notes tag-short.o | FileCheck --check-prefix ELF-TAG-SHORT %s +# RUN: llvm-readobj --notes tag-short.o | FileCheck --check-prefix OBJ-TAG-SHORT %s + +# ELF-TAG-SHORT: AArch64 PAuth ABI tag: + +# OBJ-TAG-SHORT: Notes [ +# OBJ-TAG-SHORT-NEXT: NoteSection { +# OBJ-TAG-SHORT-NEXT: Name: .note.AARCH64-PAUTH-ABI-tag +# OBJ-TAG-SHORT-NEXT: Offset: 0x40 +# OBJ-TAG-SHORT-NEXT: Size: 0x1C +# OBJ-TAG-SHORT-NEXT: Note { +# OBJ-TAG-SHORT-NEXT: Owner: ARM +# OBJ-TAG-SHORT-NEXT: Data size: 0xC +# OBJ-TAG-SHORT-NEXT: Type: NT_ARM_TYPE_PAUTH_ABI_TAG +# OBJ-TAG-SHORT-NEXT: Description data ( +# OBJ-TAG-SHORT-NEXT: 0000: 2A000000 00000000 01000000 +# OBJ-TAG-SHORT-NEXT: ) +# OBJ-TAG-SHORT-NEXT: } +# OBJ-TAG-SHORT-NEXT: } +# OBJ-TAG-SHORT-NEXT: ] + +#--- tag-long.s .section ".note.AARCH64-PAUTH-ABI-tag", "a" .long 4 @@ -96,3 +149,213 @@ .quad 42 // platform .quad 1 // version .quad 0x0123456789ABCDEF // extra data + +# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu tag-long.s -o tag-long.o +# RUN: llvm-readelf --notes tag-long.o | FileCheck --check-prefix ELF-TAG-LONG %s +# RUN: llvm-readobj --notes tag-long.o | FileCheck --check-prefix OBJ-TAG-LONG %s + +# ELF-TAG-LONG: AArch64 PAuth ABI tag: + +# OBJ-TAG-LONG: Notes [ +# OBJ-TAG-LONG-NEXT: NoteSection { +# OBJ-TAG-LONG-NEXT: Name: .note.AARCH64-PAUTH-ABI-tag +# OBJ-TAG-LONG-NEXT: Offset: 0x40 +# OBJ-TAG-LONG-NEXT: Size: 0x28 +# OBJ-TAG-LONG-NEXT: Note { +# OBJ-TAG-LONG-NEXT: Owner: ARM +# OBJ-TAG-LONG-NEXT: Data size: 0x18 +# OBJ-TAG-LONG-NEXT: Type: NT_ARM_TYPE_PAUTH_ABI_TAG +# OBJ-TAG-LONG-NEXT: Description data ( +# OBJ-TAG-LONG-NEXT: 0000: 2A000000 00000000 01000000 00000000 +# OBJ-TAG-LONG-NEXT: 0010: EFCDAB89 67452301 +# OBJ-TAG-LONG-NEXT: ) +# OBJ-TAG-LONG-NEXT: } +# OBJ-TAG-LONG-NEXT: } +# OBJ-TAG-LONG-NEXT: ] + +#--- gnu-42-1.s + +.section ".note.gnu.property", "a" + .long 4 /* Name length is always 4 ("GNU") */ + .long end - begin /* Data length */ + .long 5 /* Type: NT_GNU_PROPERTY_TYPE_0 */ + .asciz "GNU" /* Name */ + .p2align 3 +begin: + /* PAuth ABI property note */ + .long 0xc0000001 /* Type: GNU_PROPERTY_AARCH64_FEATURE_PAUTH */ + .long 16 /* Data size */ + .quad 42 /* PAuth ABI platform */ + .quad 1 /* PAuth ABI version */ + .p2align 3 /* Align to 8 byte for 64 bit */ +end: + +# RUN: llvm-mc -filetype=obj -triple aarch64-linux-gnu gnu-42-1.s -o gnu-42-1.o +# RUN: llvm-readelf --notes gnu-42-1.o | \ +# RUN: FileCheck --check-prefix=ELF-GNU -DPLATFORM="0x2a (unknown)" -DVERSION=0x1 %s +# RUN: llvm-readobj --notes gnu-42-1.o | \ +# RUN: FileCheck --check-prefix=OBJ-GNU -DPLATFORM="0x2a (unknown)" -DVERSION=0x1 %s + +# ELF-GNU: Displaying notes found in: .note.gnu.property +# ELF-GNU-NEXT: Owner Data size Description +# ELF-GNU-NEXT: GNU 0x00000018 NT_GNU_PROPERTY_TYPE_0 (property note) +# ELF-GNU-NEXT: AArch64 PAuth ABI tag: platform [[PLATFORM]], version [[VERSION]] + +# OBJ-GNU: Notes [ +# OBJ-GNU-NEXT: NoteSection { +# OBJ-GNU-NEXT: Name: .note.gnu.property +# OBJ-GNU-NEXT: Offset: 0x40 +# OBJ-GNU-NEXT: Size: 0x28 +# OBJ-GNU-NEXT: Note { +# OBJ-GNU-NEXT: Owner: GNU +# OBJ-GNU-NEXT: Data size: 0x18 +# OBJ-GNU-NEXT: Type: NT_GNU_PROPERTY_TYPE_0 (property note) +# OBJ-GNU-NEXT: Property [ +# OBJ-GNU-NEXT: AArch64 PAuth ABI tag: platform [[PLATFORM]], version [[VERSION]] +# OBJ-GNU-NEXT: ] +# OBJ-GNU-NEXT: } +# OBJ-GNU-NEXT: } +# OBJ-GNU-NEXT: ] + +#--- gnu-0-0.s + +.section ".note.gnu.property", "a" + .long 4 /* Name length is always 4 ("GNU") */ + .long end - begin /* Data length */ + .long 5 /* Type: NT_GNU_PROPERTY_TYPE_0 */ + .asciz "GNU" /* Name */ + .p2align 3 +begin: + /* PAuth ABI property note */ + .long 0xc0000001 /* Type: GNU_PROPERTY_AARCH64_FEATURE_PAUTH */ + .long 16 /* Data size */ + .quad 0 /* PAuth ABI platform */ + .quad 0 /* PAuth ABI version */ + .p2align 3 /* Align to 8 byte for 64 bit */ +end: + +# RUN: llvm-mc -filetype=obj -triple aarch64-linux-gnu gnu-0-0.s -o gnu-0-0.o +# RUN: llvm-readelf --notes gnu-0-0.o | \ +# RUN: FileCheck --check-prefix=ELF-GNU -DPLATFORM="0x0 (invalid)" -DVERSION=0x0 %s +# RUN: llvm-readobj --notes gnu-0-0.o | \ +# RUN: FileCheck --check-prefix=OBJ-GNU -DPLATFORM="0x0 (invalid)" -DVERSION=0x0 %s + +#--- gnu-1-0.s + +.section ".note.gnu.property", "a" + .long 4 /* Name length is always 4 ("GNU") */ + .long end - begin /* Data length */ + .long 5 /* Type: NT_GNU_PROPERTY_TYPE_0 */ + .asciz "GNU" /* Name */ + .p2align 3 +begin: + /* PAuth ABI property note */ + .long 0xc0000001 /* Type: GNU_PROPERTY_AARCH64_FEATURE_PAUTH */ + .long 16 /* Data size */ + .quad 1 /* PAuth ABI platform */ + .quad 0 /* PAuth ABI version */ + .p2align 3 /* Align to 8 byte for 64 bit */ +end: + +# RUN: llvm-mc -filetype=obj -triple aarch64-linux-gnu gnu-1-0.s -o gnu-1-0.o +# RUN: llvm-readelf --notes gnu-1-0.o | \ +# RUN: FileCheck --check-prefix=ELF-GNU -DPLATFORM="0x1 (baremetal)" -DVERSION=0x0 %s +# RUN: llvm-readobj --notes gnu-1-0.o | \ +# RUN: FileCheck --check-prefix=OBJ-GNU -DPLATFORM="0x1 (baremetal)" -DVERSION=0x0 %s + +#--- gnu-0x10000002-85.s + +.section ".note.gnu.property", "a" + .long 4 /* Name length is always 4 ("GNU") */ + .long end - begin /* Data length */ + .long 5 /* Type: NT_GNU_PROPERTY_TYPE_0 */ + .asciz "GNU" /* Name */ + .p2align 3 +begin: + /* PAuth ABI property note */ + .long 0xc0000001 /* Type: GNU_PROPERTY_AARCH64_FEATURE_PAUTH */ + .long 16 /* Data size */ + .quad 0x10000002 /* PAuth ABI platform */ + .quad 85 /* PAuth ABI version */ + .p2align 3 /* Align to 8 byte for 64 bit */ +end: + +# RUN: llvm-mc -filetype=obj -triple aarch64-linux-gnu gnu-0x10000002-85.s -o gnu-0x10000002-85.o +# RUN: llvm-readelf --notes gnu-0x10000002-85.o | \ +# RUN: FileCheck --check-prefix=ELF-GNU -DPLATFORM="0x10000002 (llvm_linux)" \ +# RUN: -DVERSION="0x55 (PointerAuthIntrinsics, !PointerAuthCalls, PointerAuthReturns, !PointerAuthAuthTraps, PointerAuthVTPtrAddressDiscrimination, !PointerAuthVTPtrTypeDiscrimination, PointerAuthInitFini)" %s +# RUN: llvm-readobj --notes gnu-0x10000002-85.o | \ +# RUN: FileCheck --check-prefix=OBJ-GNU -DPLATFORM="0x10000002 (llvm_linux)" \ +# RUN: -DVERSION="0x55 (PointerAuthIntrinsics, !PointerAuthCalls, PointerAuthReturns, !PointerAuthAuthTraps, PointerAuthVTPtrAddressDiscrimination, !PointerAuthVTPtrTypeDiscrimination, PointerAuthInitFini)" %s + +#--- gnu-short.s + +.section ".note.gnu.property", "a" + .long 4 /* Name length is always 4 ("GNU") */ + .long end - begin /* Data length */ + .long 5 /* Type: NT_GNU_PROPERTY_TYPE_0 */ + .asciz "GNU" /* Name */ + .p2align 3 +begin: + /* PAuth ABI property note */ + .long 0xc0000001 /* Type: GNU_PROPERTY_AARCH64_FEATURE_PAUTH */ + .long 12 /* Data size */ + .quad 42 /* PAuth ABI platform */ + .word 1 /* PAuth ABI version */ + .p2align 3 /* Align to 8 byte for 64 bit */ +end: + +# RUN: llvm-mc -filetype=obj -triple aarch64-linux-gnu gnu-short.s -o gnu-short.o +# RUN: llvm-readelf --notes gnu-short.o | \ +# RUN: FileCheck --check-prefix=ELF-GNU-ERR -DSIZE=28 -DDATASIZE=18 \ +# RUN: -DERR="" %s +# RUN: llvm-readobj --notes gnu-short.o | \ +# RUN: FileCheck --check-prefix=OBJ-GNU-ERR -DSIZE=28 -DDATASIZE=18 \ +# RUN: -DERR="" %s + +# ELF-GNU-ERR: Displaying notes found in: .note.gnu.property +# ELF-GNU-ERR-NEXT: Owner Data size Description +# ELF-GNU-ERR-NEXT: GNU 0x000000[[DATASIZE]] NT_GNU_PROPERTY_TYPE_0 (property note) +# ELF-GNU-ERR-NEXT: AArch64 PAuth ABI tag: [[ERR]] + +# OBJ-GNU-ERR: Notes [ +# OBJ-GNU-ERR-NEXT: NoteSection { +# OBJ-GNU-ERR-NEXT: Name: .note.gnu.property +# OBJ-GNU-ERR-NEXT: Offset: 0x40 +# OBJ-GNU-ERR-NEXT: Size: 0x[[SIZE]] +# OBJ-GNU-ERR-NEXT: Note { +# OBJ-GNU-ERR-NEXT: Owner: GNU +# OBJ-GNU-ERR-NEXT: Data size: 0x[[DATASIZE]] +# OBJ-GNU-ERR-NEXT: Type: NT_GNU_PROPERTY_TYPE_0 (property note) +# OBJ-GNU-ERR-NEXT: Property [ +# OBJ-GNU-ERR-NEXT: AArch64 PAuth ABI tag: [[ERR]] +# OBJ-GNU-ERR-NEXT: ] +# OBJ-GNU-ERR-NEXT: } +# OBJ-GNU-ERR-NEXT: } +# OBJ-GNU-ERR-NEXT: ] + +#--- gnu-long.s + +.section ".note.gnu.property", "a" + .long 4 /* Name length is always 4 ("GNU") */ + .long end - begin /* Data length */ + .long 5 /* Type: NT_GNU_PROPERTY_TYPE_0 */ + .asciz "GNU" /* Name */ + .p2align 3 +begin: + /* PAuth ABI property note */ + .long 0xc0000001 /* Type: GNU_PROPERTY_AARCH64_FEATURE_PAUTH */ + .long 24 /* Data size */ + .quad 42 /* PAuth ABI platform */ + .quad 1 /* PAuth ABI version */ + .quad 0x0123456789ABCDEF + .p2align 3 /* Align to 8 byte for 64 bit */ +end: + +# RUN: llvm-mc -filetype=obj -triple aarch64-linux-gnu gnu-long.s -o gnu-long.o +# RUN: llvm-readelf --notes gnu-long.o | \ +# RUN: FileCheck --check-prefix=ELF-GNU-ERR -DSIZE=30 -DDATASIZE=20 \ +# RUN: -DERR="" %s +# RUN: llvm-readobj --notes gnu-long.o | \ +# RUN: FileCheck --check-prefix=OBJ-GNU-ERR -DSIZE=30 -DDATASIZE=20 \ +# RUN: -DERR="" %s diff --git a/llvm/test/tools/llvm-readobj/ELF/AArch64/aarch64-note-gnu-property.s b/llvm/test/tools/llvm-readobj/ELF/AArch64/aarch64-note-gnu-property.s index 377e6f93448ca7..b517f0b3815547 100644 --- a/llvm/test/tools/llvm-readobj/ELF/AArch64/aarch64-note-gnu-property.s +++ b/llvm/test/tools/llvm-readobj/ELF/AArch64/aarch64-note-gnu-property.s @@ -1,3 +1,5 @@ +// See tests for GNU_PROPERTY_AARCH64_FEATURE_PAUTH in aarch64-feature-pauth.s + // RUN: llvm-mc -filetype=obj -triple aarch64-linux-gnu %s -o %t // RUN: llvm-readelf --notes %t | FileCheck %s --check-prefix=GNU // RUN: llvm-readobj --notes %t | FileCheck %s --check-prefix=LLVM diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index e78732353cc877..d24d5c5a378cb7 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -5098,6 +5098,71 @@ template void GNUELFDumper::printAddrsig() { } } +std::pair +getAArch64PAuthABIPlatformVersionDesc(uint64_t Platform, uint64_t Version) { + return std::make_pair( + [Platform]() -> std::string { + switch (Platform) { + case AARCH64_PAUTH_PLATFORM_INVALID: + return "invalid"; + case AARCH64_PAUTH_PLATFORM_BAREMETAL: + return "baremetal"; + case AARCH64_PAUTH_PLATFORM_LLVM_LINUX: + return "llvm_linux"; + default: + return "unknown"; + } + }(), + [Platform, Version]() -> std::string { + if (Platform != AARCH64_PAUTH_PLATFORM_LLVM_LINUX) + return ""; + constexpr size_t FlagsCount = 7; + if (Version >= (1 << FlagsCount)) + return "unknown"; + const char *Flags[FlagsCount] = {"Intrinsics", + "Calls", + "Returns", + "AuthTraps", + "VTPtrAddressDiscrimination", + "VTPtrTypeDiscrimination", + "InitFini"}; + std::string VersionString; + for (size_t I = 0; I < FlagsCount; ++I) { + VersionString += ((Version & (1 << I)) ? "" : "!"); + VersionString += "PointerAuth"; + VersionString += Flags[I]; + VersionString += ", "; + } + VersionString.resize(VersionString.size() - 2); // Trim last ", " + return VersionString; + }()); +} + +template +static bool printAArch64PAuthABITag(raw_ostream &OS, uint32_t DataSize, + ArrayRef Desc) { + OS << " AArch64 PAuth ABI tag: "; + // DataSize - size without padding, Desc.size() - size with padding + if (DataSize != 16) { + OS << format("", DataSize); + return false; + } + + uint64_t Platform = + support::endian::read64(Desc.data() + 0); + uint64_t Version = + support::endian::read64(Desc.data() + 8); + + auto [PlatformDesc, VersionDesc] = + getAArch64PAuthABIPlatformVersionDesc(Platform, Version); + OS << format("platform 0x%x (%s), version 0x%x", Platform, + PlatformDesc.c_str(), Version); + if (!VersionDesc.empty()) + OS << format(" (%s)", VersionDesc.c_str()); + + return true; +} + template static std::string getGNUProperty(uint32_t Type, uint32_t DataSize, ArrayRef Data) { @@ -5155,6 +5220,9 @@ static std::string getGNUProperty(uint32_t Type, uint32_t DataSize, if (PrData) OS << format("", PrData); return OS.str(); + case GNU_PROPERTY_AARCH64_FEATURE_PAUTH: + printAArch64PAuthABITag(OS, DataSize, Data); + return OS.str(); case GNU_PROPERTY_X86_FEATURE_2_NEEDED: case GNU_PROPERTY_X86_FEATURE_2_USED: OS << "x86 feature " @@ -5359,26 +5427,11 @@ static bool printAndroidNote(raw_ostream &OS, uint32_t NoteType, 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; + switch (NoteType) { + case NT_ARM_TYPE_PAUTH_ABI_TAG: + return printAArch64PAuthABITag(OS, Desc.size(), Desc); } - - uint64_t Platform = - support::endian::read64(Desc.data() + 0); - uint64_t Version = - support::endian::read64(Desc.data() + 8); - OS << format("platform 0x%" PRIx64 ", version 0x%" PRIx64, Platform, Version); - - if (Desc.size() > 16) - OS << ", additional info 0x" - << toHex(ArrayRef(Desc.data() + 16, Desc.size() - 16)); - - return true; + return false; } template @@ -7705,19 +7758,20 @@ static bool printAarch64NoteLLVMStyle(uint32_t NoteType, ArrayRef Desc, if (NoteType != NT_ARM_TYPE_PAUTH_ABI_TAG) return false; - if (Desc.size() < 16) + if (Desc.size() != 16) return false; - uint64_t platform = + uint64_t Platform = support::endian::read64(Desc.data() + 0); - uint64_t version = + 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))); + auto [PlatformDesc, VersionDesc] = + getAArch64PAuthABIPlatformVersionDesc(Platform, Version); + W.printNumber("Platform", Platform); + W.printString("PlatformDesc", PlatformDesc); + W.printNumber("Version", Version); + if (!VersionDesc.empty()) + W.printString("VersionDesc", VersionDesc); return true; }