Skip to content

Commit

Permalink
[PAC][llvm-readobj][AArch64][ELF] Support `GNU_PROPERTY_AARCH64_FEATU…
Browse files Browse the repository at this point in the history
…RE_PAUTH` (#85231)

This adds support for `GNU_PROPERTY_AARCH64_FEATURE_PAUTH` feature (as
defined in ARM-software/abi-aa#240) 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`
defined in #85232:

- bit 0: `PointerAuthIntrinsics`;
- bit 1: `PointerAuthCalls`;
- bit 2: `PointerAuthReturns`;
- bit 3: `PointerAuthAuthTraps`;
- bit 4: `PointerAuthVTPtrAddressDiscrimination`;
- bit 5: `PointerAuthVTPtrTypeDiscrimination`;
- bit 6: `PointerAuthInitFini`.

Support for `.note.AARCH64-PAUTH-ABI-tag` is dropped since it's deleted
from the spec in ARM-software/abi-aa#250.
  • Loading branch information
kovdan01 authored Apr 2, 2024
1 parent 7327014 commit 5029949
Show file tree
Hide file tree
Showing 4 changed files with 303 additions and 157 deletions.
26 changes: 21 additions & 5 deletions llvm/include/llvm/BinaryFormat/ELF.h
Original file line number Diff line number Diff line change
Expand Up @@ -1712,11 +1712,6 @@ 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
Expand All @@ -1740,6 +1735,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,
Expand All @@ -1758,6 +1754,26 @@ 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,
};

// Bit positions of version flags for AARCH64_PAUTH_PLATFORM_LLVM_LINUX.
enum : unsigned {
AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_INTRINSICS = 0,
AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_CALLS = 1,
AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_RETURNS = 2,
AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_AUTHTRAPS = 3,
AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_VPTRADDRDISCR = 4,
AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_VPTRTYPEDISCR = 5,
AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_INITFINI = 6,
AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_LAST =
AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_INITFINI,
};

// x86 processor feature bits.
enum : unsigned {
GNU_PROPERTY_X86_FEATURE_1_IBT = 1 << 0,
Expand Down
305 changes: 209 additions & 96 deletions llvm/test/tools/llvm-readobj/ELF/AArch64/aarch64-feature-pauth.s
Original file line number Diff line number Diff line change
@@ -1,98 +1,211 @@
# 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: <corrupted size: expected at least 16, got 12>
# 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
#--- 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 -DPLATFORM="0x2a (unknown)" -DVERSION=0x1 %s
# RUN: llvm-readobj --notes gnu-42-1.o | \
# RUN: FileCheck --check-prefix=OBJ -DPLATFORM="0x2a (unknown)" -DVERSION=0x1 %s

# ELF: Displaying notes found in: .note.gnu.property
# ELF-NEXT: Owner Data size Description
# ELF-NEXT: GNU 0x00000018 NT_GNU_PROPERTY_TYPE_0 (property note)
# ELF-NEXT: AArch64 PAuth ABI core info: platform [[PLATFORM]], version [[VERSION]]

# OBJ: Notes [
# OBJ-NEXT: NoteSection {
# OBJ-NEXT: Name: .note.gnu.property
# OBJ-NEXT: Offset: 0x40
# OBJ-NEXT: Size: 0x28
# OBJ-NEXT: Note {
# OBJ-NEXT: Owner: GNU
# OBJ-NEXT: Data size: 0x18
# OBJ-NEXT: Type: NT_GNU_PROPERTY_TYPE_0 (property note)
# OBJ-NEXT: Property [
# OBJ-NEXT: AArch64 PAuth ABI core info: platform [[PLATFORM]], version [[VERSION]]
# OBJ-NEXT: ]
# OBJ-NEXT: }
# OBJ-NEXT: }
# OBJ-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 -DPLATFORM="0x0 (invalid)" -DVERSION=0x0 %s
# RUN: llvm-readobj --notes gnu-0-0.o | \
# RUN: FileCheck --check-prefix=OBJ -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 -DPLATFORM="0x1 (baremetal)" -DVERSION=0x0 %s
# RUN: llvm-readobj --notes gnu-1-0.o | \
# RUN: FileCheck --check-prefix=OBJ -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 -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 -DPLATFORM="0x10000002 (llvm_linux)" \
# RUN: -DVERSION="0x55 (PointerAuthIntrinsics, !PointerAuthCalls, PointerAuthReturns, !PointerAuthAuthTraps, PointerAuthVTPtrAddressDiscrimination, !PointerAuthVTPtrTypeDiscrimination, PointerAuthInitFini)" %s

#--- gnu-0x10000002-128.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 128 // PAuth ABI version
.p2align 3 // Align to 8 byte for 64 bit
end:

# RUN: llvm-mc -filetype=obj -triple aarch64-linux-gnu gnu-0x10000002-128.s -o gnu-0x10000002-128.o
# RUN: llvm-readelf --notes gnu-0x10000002-128.o | \
# RUN: FileCheck --check-prefix=ELF -DPLATFORM="0x10000002 (llvm_linux)" -DVERSION="0x80 (unknown)" %s
# RUN: llvm-readobj --notes gnu-0x10000002-128.o | \
# RUN: FileCheck --check-prefix=OBJ -DPLATFORM="0x10000002 (llvm_linux)" -DVERSION="0x80 (unknown)" %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-ERR -DSIZE=28 -DDATASIZE=18 \
# RUN: -DERR="<corrupted size: expected 16, got 12>" %s
# RUN: llvm-readobj --notes gnu-short.o | \
# RUN: FileCheck --check-prefix=OBJ-ERR -DSIZE=28 -DDATASIZE=18 \
# RUN: -DERR="<corrupted size: expected 16, got 12>" %s

# ELF-ERR: Displaying notes found in: .note.gnu.property
# ELF-ERR-NEXT: Owner Data size Description
# ELF-ERR-NEXT: GNU 0x000000[[DATASIZE]] NT_GNU_PROPERTY_TYPE_0 (property note)
# ELF-ERR-NEXT: AArch64 PAuth ABI core info: [[ERR]]

# OBJ-ERR: Notes [
# OBJ-ERR-NEXT: NoteSection {
# OBJ-ERR-NEXT: Name: .note.gnu.property
# OBJ-ERR-NEXT: Offset: 0x40
# OBJ-ERR-NEXT: Size: 0x[[SIZE]]
# OBJ-ERR-NEXT: Note {
# OBJ-ERR-NEXT: Owner: GNU
# OBJ-ERR-NEXT: Data size: 0x[[DATASIZE]]
# OBJ-ERR-NEXT: Type: NT_GNU_PROPERTY_TYPE_0 (property note)
# OBJ-ERR-NEXT: Property [
# OBJ-ERR-NEXT: AArch64 PAuth ABI core info: [[ERR]]
# OBJ-ERR-NEXT: ]
# OBJ-ERR-NEXT: }
# OBJ-ERR-NEXT: }
# OBJ-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-ERR -DSIZE=30 -DDATASIZE=20 \
# RUN: -DERR="<corrupted size: expected 16, got 24>" %s
# RUN: llvm-readobj --notes gnu-long.o | \
# RUN: FileCheck --check-prefix=OBJ-ERR -DSIZE=30 -DDATASIZE=20 \
# RUN: -DERR="<corrupted size: expected 16, got 24>" %s
Original file line number Diff line number Diff line change
@@ -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
Expand Down
Loading

0 comments on commit 5029949

Please sign in to comment.