-
Notifications
You must be signed in to change notification settings - Fork 12.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[PAC][llvm-readobj][AArch64][ELF] Support GNU_PROPERTY_AARCH64_FEATURE_PAUTH
#85231
Conversation
ea59dbb
to
54854fc
Compare
GNU_PROPERTY_AARCH64_FEATURE_PAUTH
GNU_PROPERTY_AARCH64_FEATURE_PAUTH
…RE_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`. Support for `.note.AARCH64-PAUTH-ABI-tag` is dropped since it's deleted from the spec in ARM-software/abi-aa#250.
54854fc
to
34bae39
Compare
@llvm/pr-subscribers-llvm-binary-utilities Author: Daniil Kovalev (kovdan01) ChangesThis adds support for
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
Support for Patch is 20.62 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/85231.diff 4 Files Affected:
diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h
index bace3a92677a82..ca01be089c47f2 100644
--- a/llvm/include/llvm/BinaryFormat/ELF.h
+++ b/llvm/include/llvm/BinaryFormat/ELF.h
@@ -1710,11 +1710,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
@@ -1738,6 +1733,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 +1752,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,
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..3f171acde8eb92 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,98 +1,188 @@
# 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-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 core info: 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 core info: 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="<corrupted size: expected 16, got 12>" %s
+# RUN: llvm-readobj --notes gnu-short.o | \
+# RUN: FileCheck --check-prefix=OBJ-GNU-ERR -DSIZE=28 -DDATASIZE=18 \
+# RUN: -DERR="<corrupted size: expected 16, got 12>" %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 core info: [[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 core info: [[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="<corrupted size: expected 16, got 24>" %s
+# RUN: llvm-readobj --notes gnu-long.o | \
+# RUN: FileCheck --check-prefix=OBJ-GNU-ERR -DSIZE=30 -DDATASIZE=20 \
+# RUN: -DERR="<corrupted size: expected 16, got 24>" %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..ff620e944e1b56 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -5098,6 +5098,83 @@ template <class ELFT> void GNUELFDumper<ELFT>::printAddrsig() {
}
}
+template <class ELFT>
+static bool printAArch64PAuthABICoreInfo(raw_ostream &OS, uint32_t DataSize,
+ ArrayRef<uint8_t> Desc) {
+ OS << " AArch64 PAuth ABI core info: ";
+ // DataSize - size without padding, Desc.size() - size with padding
+ if (DataSize != 16) {
+ OS << format("<corrupted size: expected 16, got %d>", DataSize);
+ return false;
+ }
+
+ uint64_t Platform =
+ support::endian::read64<ELFT::TargetEndianness>(Desc.data() + 0);
+ uint64_t Version =
+ support::endian::read64<ELFT::TargetEndianness>(Desc.data() + 8);
+
+ std::string PlatformDesc = [Platform]() {
+ 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";
+ }
+ }();
+
+ std::string VersionDesc = [Platform, Version]() -> std::string {
+ if (Platform != AARCH64_PAUTH_PLATFORM_LLVM_LINUX)
+ return "";
+ if (Version >= (1 << (AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_LAST + 1)))
+ return "unknown";
+ return std::string("") +
+ ((Version &
+ (1 << AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_INTRINSICS))
+ ? ""
+ : "!") +
+ "PointerAuthIntrinsics, " +
+ ((Version & (1 << AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_CALLS))
+ ? ""
+ : "!") +
+ "PointerAuthCalls, " +
+ ((Version & (1 << AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_RETURNS))
+ ? ""
+ : "!") +
+ "PointerAuthReturns, " +
+ ((Version &
+ (1 << AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_AUTHTRAPS))
+ ? ""
+ : "!") +
+ "PointerAuthAuthTraps, " +
+ ((Version &
+ (1 << AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_VPTRADDRDISCR))
+ ? ""
+ : "!") +
+ "PointerAuthVTPtrAddressDiscrimination, " +
+ ((Version &
+ (1 << AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_VPTRTYPEDISCR))
+ ? ""
+ : "!") +
+ "PointerAuthVTPtrTypeDiscrimination, " +
+ ((Version &
+ (1 << AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_INITFINI))
+ ? ""
+ : "!") +
+ "PointerAuthInitFini";
+ }();
+
+ 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 <typename ELFT>
static std::string getGNUProperty(uint32_t Type, uint32_t DataSize,
ArrayRef<uint8_t> Data) {
@@ -5155,6 +5232,9 @@ static std::string getGNUProperty(uint32_t Type, uint32_t DataSize,
if (PrData)
OS << format("<unknown flags: 0x%x>", PrData);
return OS.str();
+ case GNU_PROPERTY_AARCH64_FEATURE_PAUTH:
+ printAArch64PAuthABICoreInfo<ELFT>(OS, DataSize, Data);
+ return OS.str();
case GNU_PROPERTY_X86_FEATURE_2_NEEDED:
case GNU_PROPERTY_X86_FEATURE_2_USED:
OS << "x86 feature "
@@ -5356,31 +5436,6 @@ static bool printAndroidNote(raw_ostream &OS, uint32_t NoteType,
return true;
}
-template <class ELFT>
-static bool printAArch64Note(raw_ostream &OS, uint32_t NoteType,
- ArrayRef<uint8_t> Desc) {
- if (NoteType != NT_ARM_TYPE_PAUTH_ABI_TAG)
- return false;
-
- OS << " AArch64 PAuth ABI tag: ";
- if (Desc.size() < 16) {
- OS << format("<corrupted size: expected at least 16, got %d>", Desc.size());
- return false;
- }
-
- uint64_t Platform =
- support::endian::read64<ELFT::TargetEndianness>(Desc.data() + 0);
- uint64_t Version =
- support::endian::read64<ELFT::TargetEndianness>(Desc.data() + 8);
- OS << format("platform 0x%" PRIx64 ", version 0x%" PRIx64, Platform, Version);
-
- if (Desc.size() > 16)
- OS << ", additional info 0x"
- << toHex(ArrayRef<uint8_t>(Desc.data() + 16, Desc.size() - 16));
-
- return true;
-}
-
template <class ELFT>
void GNUELFDumper<ELFT>::printMemtag(
const ArrayRef<std::pair<std::string, std::string>> DynamicEntries,
@@ -5780,10 +5835,6 @@ 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)"},
@@ -5902,8 +5953,6 @@ 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);
@@ -6059,9 +6108,6 @@ template <class ELFT> void GNUELFDumper<ELFT>::printNotes() {
} else if (Name == "Android") {
if (printAndroidNote(OS, Type, Descriptor))
return Error::success();
- } else if (Name == "ARM") {
- if (printAArch64Note<ELFT>(OS, Type, Descriptor))
- return Error::success();
}
if (!Descriptor.empty()) {
OS << " description data:";
@@ -7699,29 +7745,6 @@ static bool printAndroidNoteLLVMStyle(uint32_t NoteType, ArrayRef<uint8_t> Desc,
return true;
}
-template <class ELFT>
-static bool printAarch64NoteLLVMStyle(uint32_t NoteType, ArrayRef<uint8_t> 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<ELFT::TargetEndianness>(Desc.data() + 0);
- uint64_t version =
- support::endian::read64<ELFT::TargetEndianness>(Desc.data() + 8);
- W.printNumber("Platform", platform);
- W.printNumber("Version", version);
-
- if (Desc.size() > 16)
- W.printString("Additional info",
- toHex(ArrayRef<uint8_t>(Desc.data() ...
[truncated]
|
|
||
// Bit positions of version flags for AARCH64_PAUTH_PLATFORM_LLVM_LINUX. | ||
enum : unsigned { | ||
AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_INTRINSICS = 0, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where are these constants defined?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Invalid and baremetal platform values are reserved in https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst (constant names themselves are not defined there though). Regarding everything related to llvm_linux platform - it's not defined anywhere and I've defined it here since we need some sort of working ELF marking scheme to at least test things. If different constant names and/or values are preferred or there is some specification which needs to be updated correspondingly - please let me know.
uint64_t Version = | ||
support::endian::read64<ELFT::TargetEndianness>(Desc.data() + 8); | ||
|
||
std::string PlatformDesc = [Platform]() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider const StringRef
instead of a mutable std::string
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for suggestion. I've switched to const char *
since we later use PlatformDesc
as an argument for format(...)
and expect it to be null-terminated. Storing null-terminated strings as const char *
when we don't need anything except the pointer itself looks more clear in this context than calling .data()
on StringRef
and keeping in mind that in this particular case the StringRef
's content is also null-terminated (while it's not guaranteed in other cases).
For VersionDesc
, I still use std::string
- it does not look safe to use StringRef
or smth similar due to dangling references to a temporary.
See 8b56262
return ""; | ||
if (Version >= (1 << (AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_LAST + 1))) | ||
return "unknown"; | ||
return std::string("") + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Define a std::string, then do
if (...)
Desc += ...
if (...)
Desc += ...
is likely more readable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for suggestion. I've switched to a slightly different approach. I've defined an array of flag names and then iterate over them in a loop and test each flag in the loop. Keeping in mind that we always have all flag names in the description and just add '!' for those which are disabled, it looks more clear.
See 8b56262
(1 << AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_INITFINI)) | ||
? "" | ||
: "!") + | ||
"PointerAuthInitFini"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is PointerAuthInitFini always part of the description?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if I got your question - all the flag names are always part of the description, we just add '!' for those which are not set. As for me, it's more clear for a user than only including in the description flags which are set and not including those which are not set - in this case, the user is not aware which flags are available and does not know which features are disabled.
Please let me know if I miss something.
✅ With the latest revision this PR passed the Python code formatter. |
✅ With the latest revision this PR passed the C/C++ code formatter. |
#--- gnu-42-1.s | ||
|
||
.section ".note.gnu.property", "a" | ||
.long 4 /* Name length is always 4 ("GNU") */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
//
is shorter and more common since //
is supported by all targets in GNU as.
#
can be used on aarch64 if there is no leading non-whitespace character.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed, thanks, see 26c8586
In llvm/test/tools/llvm-readobj/ELF/AArch64/aarch64-note-gnu-property.s, which tests other GNU properties, /* */
is used. I can submit a subsequent PR changing that to //
and #
where applicable to keep things consistent. Please let me know what you think on this.
@MaskRay Please let me know if latest updates address your comments - it would be nice to get this merged shortly since it's a prerequisite for several other PRs. |
Previous buildkite failures related to the PR are fixed (renaming |
…64_FEATURE_PAUTH`" (#87434) Reverts #85231 See build failure https://lab.llvm.org/buildbot/#/builders/186/builds/15631
…RE_PAUTH` (#87545) Reland #85231 after fixing build failure https://lab.llvm.org/buildbot/#/builders/186/builds/15631. Use `PRIx64` for format output of `uint64_t` as hex. Original PR description below. 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.
#72714) This patch adds lld support for: - Dynamic R_AARCH64_AUTH_* relocations (without including RELR compressed AUTH relocations) as described here: https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#auth-variant-dynamic-relocations - .note.AARCH64-PAUTH-ABI-tag section as defined here https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#elf-marking Depends on #72713 and #85231 --------- Co-authored-by: Peter Collingbourne <[email protected]> Co-authored-by: Fangrui Song <[email protected]>
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:PointerAuthIntrinsics
;PointerAuthCalls
;PointerAuthReturns
;PointerAuthAuthTraps
;PointerAuthVTPtrAddressDiscrimination
;PointerAuthVTPtrTypeDiscrimination
;PointerAuthInitFini
.Support for
.note.AARCH64-PAUTH-ABI-tag
is dropped since it's deletedfrom the spec in ARM-software/abi-aa#250.