[llvm] [AArch64][PAC][MC][ELF] Support PAuth ABI compatibility tag (PR #85236)
Daniil Kovalev via llvm-commits
llvm-commits at lists.llvm.org
Fri Mar 22 00:58:20 PDT 2024
https://github.com/kovdan01 updated https://github.com/llvm/llvm-project/pull/85236
>From 6182b040eeb66e2f413c7ae31bd895e3fbd02b71 Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Wed, 13 Mar 2024 23:07:49 +0300
Subject: [PATCH 1/5] [AArch64][PAC][MC][ELF] Support PAuth ABI compatibility
tag
Emit `GNU_PROPERTY_AARCH64_FEATURE_PAUTH` property in
`.note.gnu.property` section depending on
`aarch64-elf-pauthabi-platform` and `aarch64-elf-pauthabi-version` llvm
module flags.
---
llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp | 17 +++++--
.../MCTargetDesc/AArch64TargetStreamer.cpp | 33 +++++++++---
.../MCTargetDesc/AArch64TargetStreamer.h | 3 +-
.../AArch64/note-gnu-property-elf-pauthabi.ll | 50 +++++++++++++++++++
4 files changed, 92 insertions(+), 11 deletions(-)
create mode 100644 llvm/test/CodeGen/AArch64/note-gnu-property-elf-pauthabi.ll
diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index 4fa719ad67cf33..6f7d1548d09c76 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -268,13 +268,24 @@ void AArch64AsmPrinter::emitStartOfAsmFile(Module &M) {
if (Sign->getZExtValue())
Flags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_PAC;
- if (Flags == 0)
- return;
+ uint64_t PAuthABIPlatform = -1;
+ if (const auto *PAP = mdconst::extract_or_null<ConstantInt>(
+ M.getModuleFlag("aarch64-elf-pauthabi-platform")))
+ PAuthABIPlatform = PAP->getZExtValue();
+ uint64_t PAuthABIVersion = -1;
+ if (const auto *PAV = mdconst::extract_or_null<ConstantInt>(
+ M.getModuleFlag("aarch64-elf-pauthabi-version")))
+ PAuthABIVersion = PAV->getZExtValue();
+
+ if ((PAuthABIPlatform == uint64_t(-1)) != (PAuthABIVersion == uint64_t(-1)))
+ report_fatal_error(
+ "either both or no 'aarch64-elf-pauthabi-platform' and "
+ "'aarch64-elf-pauthabi-version' module flags must be present");
// Emit a .note.gnu.property section with the flags.
auto *TS =
static_cast<AArch64TargetStreamer *>(OutStreamer->getTargetStreamer());
- TS->emitNoteSection(Flags);
+ TS->emitNoteSection(Flags, PAuthABIPlatform, PAuthABIVersion);
}
void AArch64AsmPrinter::emitFunctionHeaderComment() {
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.cpp
index e1d6dd7a056bce..dc5383ce941ed9 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.cpp
@@ -58,8 +58,17 @@ void AArch64TargetStreamer::finish() {
emitNoteSection(ELF::GNU_PROPERTY_AARCH64_FEATURE_1_BTI);
}
-void AArch64TargetStreamer::emitNoteSection(unsigned Flags) {
- if (Flags == 0)
+void AArch64TargetStreamer::emitNoteSection(unsigned Flags,
+ uint64_t PAuthABIPlatform,
+ uint64_t PAuthABIVersion) {
+ assert((PAuthABIPlatform == uint64_t(-1)) ==
+ (PAuthABIVersion == uint64_t(-1)));
+ uint64_t DescSz = 0;
+ if (Flags != 0)
+ DescSz += 4 * 4;
+ if (PAuthABIPlatform != uint64_t(-1))
+ DescSz += 4 + 4 + 8 * 2;
+ if (DescSz == 0)
return;
MCStreamer &OutStreamer = getStreamer();
@@ -80,15 +89,25 @@ void AArch64TargetStreamer::emitNoteSection(unsigned Flags) {
// Emit the note header.
OutStreamer.emitValueToAlignment(Align(8));
OutStreamer.emitIntValue(4, 4); // data size for "GNU\0"
- OutStreamer.emitIntValue(4 * 4, 4); // Elf_Prop size
+ OutStreamer.emitIntValue(DescSz, 4); // Elf_Prop array size
OutStreamer.emitIntValue(ELF::NT_GNU_PROPERTY_TYPE_0, 4);
OutStreamer.emitBytes(StringRef("GNU", 4)); // note name
// Emit the PAC/BTI properties.
- OutStreamer.emitIntValue(ELF::GNU_PROPERTY_AARCH64_FEATURE_1_AND, 4);
- OutStreamer.emitIntValue(4, 4); // data size
- OutStreamer.emitIntValue(Flags, 4); // data
- OutStreamer.emitIntValue(0, 4); // pad
+ if (Flags != 0) {
+ OutStreamer.emitIntValue(ELF::GNU_PROPERTY_AARCH64_FEATURE_1_AND, 4);
+ OutStreamer.emitIntValue(4, 4); // data size
+ OutStreamer.emitIntValue(Flags, 4); // data
+ OutStreamer.emitIntValue(0, 4); // pad
+ }
+
+ // Emit the PAuth ABI compatibility info
+ if (PAuthABIPlatform != uint64_t(-1)) {
+ OutStreamer.emitIntValue(ELF::GNU_PROPERTY_AARCH64_FEATURE_PAUTH, 4);
+ OutStreamer.emitIntValue(8 * 2, 4); // data size
+ OutStreamer.emitIntValue(PAuthABIPlatform, 8);
+ OutStreamer.emitIntValue(PAuthABIVersion, 8);
+ }
OutStreamer.endSection(Nt);
OutStreamer.switchSection(Cur);
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h
index 7676d88a82b5c7..e8a9dc445b96b1 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h
@@ -35,7 +35,8 @@ class AArch64TargetStreamer : public MCTargetStreamer {
void emitCurrentConstantPool();
/// Callback used to implement the .note.gnu.property section.
- void emitNoteSection(unsigned Flags);
+ void emitNoteSection(unsigned Flags, uint64_t PAuthABIPlatform = -1,
+ uint64_t PAuthABIVersion = -1);
/// Callback used to implement the .inst directive.
virtual void emitInst(uint32_t Inst);
diff --git a/llvm/test/CodeGen/AArch64/note-gnu-property-elf-pauthabi.ll b/llvm/test/CodeGen/AArch64/note-gnu-property-elf-pauthabi.ll
new file mode 100644
index 00000000000000..1eb6a2c7aceac3
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/note-gnu-property-elf-pauthabi.ll
@@ -0,0 +1,50 @@
+; RUN: rm -rf %t && split-file %s %t && cd %t
+
+;--- ok.ll
+
+; RUN: llc -mtriple=aarch64-linux ok.ll -o - | \
+; RUN: FileCheck %s --check-prefix=ASM
+; RUN: llc -mtriple=aarch64-linux ok.ll -filetype=obj -o - | \
+; RUN: llvm-readelf --notes - | FileCheck %s --check-prefix=OBJ
+
+!llvm.module.flags = !{!0, !1}
+
+!0 = !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458}
+!1 = !{i32 1, !"aarch64-elf-pauthabi-version", i32 85}
+
+; ASM: .section .note.gnu.property,"a", at note
+; ASM-NEXT: .p2align 3, 0x0
+; ASM-NEXT: .word 4
+; ASM-NEXT: .word 24
+; ASM-NEXT: .word 5
+; ASM-NEXT: .asciz "GNU"
+; 3221225473 = 0xc0000001 = GNU_PROPERTY_AARCH64_FEATURE_PAUTH
+; ASM-NEXT: .word 3221225473
+; ASM-NEXT: .word 16
+; ASM-NEXT: .xword 268435458
+; ASM-NEXT: .xword 85
+
+; OBJ: Displaying notes found in: .note.gnu.property
+; OBJ-NEXT: Owner Data size Description
+; OBJ-NEXT: GNU 0x00000018 NT_GNU_PROPERTY_TYPE_0 (property note)
+; OBJ-NEXT: AArch64 PAuth ABI tag: platform 0x10000002 (llvm_linux), version 0x55 (PointerAuthIntrinsics, !PointerAuthCalls, PointerAuthReturns, !PointerAuthAuthTraps, PointerAuthVTPtrAddressDiscrimination, !PointerAuthVTPtrTypeDiscrimination, PointerAuthInitFini)
+
+; ERR: either both or no 'aarch64-elf-pauthabi-platform' and 'aarch64-elf-pauthabi-version' module flags must be present
+
+;--- err1.ll
+
+; RUN: not --crash llc -mtriple=aarch64-linux err1.ll 2>&1 -o - | \
+; RUN: FileCheck %s --check-prefix=ERR
+
+!llvm.module.flags = !{!0}
+
+!0 = !{i32 1, !"aarch64-elf-pauthabi-platform", i32 2}
+
+;--- err2.ll
+
+; RUN: not --crash llc -mtriple=aarch64-linux err2.ll 2>&1 -o - | \
+; RUN: FileCheck %s --check-prefix=ERR
+
+!llvm.module.flags = !{!0}
+
+!0 = !{i32 1, !"aarch64-elf-pauthabi-version", i32 31}
>From 6a0bec4d09fca0acf1452cfc8e6522f4c4b8cf94 Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Wed, 20 Mar 2024 11:14:43 +0300
Subject: [PATCH 2/5] Rename PAuth ABI tag to PAuth ABI core info (see #85231)
---
llvm/test/CodeGen/AArch64/note-gnu-property-elf-pauthabi.ll | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/test/CodeGen/AArch64/note-gnu-property-elf-pauthabi.ll b/llvm/test/CodeGen/AArch64/note-gnu-property-elf-pauthabi.ll
index 1eb6a2c7aceac3..46c4bb1490375e 100644
--- a/llvm/test/CodeGen/AArch64/note-gnu-property-elf-pauthabi.ll
+++ b/llvm/test/CodeGen/AArch64/note-gnu-property-elf-pauthabi.ll
@@ -27,7 +27,7 @@
; OBJ: Displaying notes found in: .note.gnu.property
; OBJ-NEXT: Owner Data size Description
; OBJ-NEXT: GNU 0x00000018 NT_GNU_PROPERTY_TYPE_0 (property note)
-; OBJ-NEXT: AArch64 PAuth ABI tag: platform 0x10000002 (llvm_linux), version 0x55 (PointerAuthIntrinsics, !PointerAuthCalls, PointerAuthReturns, !PointerAuthAuthTraps, PointerAuthVTPtrAddressDiscrimination, !PointerAuthVTPtrTypeDiscrimination, PointerAuthInitFini)
+; OBJ-NEXT: AArch64 PAuth ABI core info: platform 0x10000002 (llvm_linux), version 0x55 (PointerAuthIntrinsics, !PointerAuthCalls, PointerAuthReturns, !PointerAuthAuthTraps, PointerAuthVTPtrAddressDiscrimination, !PointerAuthVTPtrTypeDiscrimination, PointerAuthInitFini)
; ERR: either both or no 'aarch64-elf-pauthabi-platform' and 'aarch64-elf-pauthabi-version' module flags must be present
>From ab89fdcb49f9ae6dd2d20cac81cca5204eda51a6 Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Wed, 20 Mar 2024 11:16:20 +0300
Subject: [PATCH 3/5] Move check of module flags to verifier
---
llvm/lib/IR/Verifier.cpp | 23 ++++++++++++++++++-
llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp | 5 ----
2 files changed, 22 insertions(+), 6 deletions(-)
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index a923f5e2a34e70..85de16e65c1726 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -1734,8 +1734,29 @@ void Verifier::visitModuleFlags() {
// Scan each flag, and track the flags and requirements.
DenseMap<const MDString*, const MDNode*> SeenIDs;
SmallVector<const MDNode*, 16> Requirements;
- for (const MDNode *MDN : Flags->operands())
+ uint64_t PAuthABIPlatform = -1;
+ uint64_t PAuthABIVersion = -1;
+ for (const MDNode *MDN : Flags->operands()) {
visitModuleFlag(MDN, SeenIDs, Requirements);
+ if (MDN->getNumOperands() != 3)
+ continue;
+ if (const auto *FlagName = dyn_cast_or_null<MDString>(MDN->getOperand(1))) {
+ if (FlagName->getString() == "aarch64-elf-pauthabi-platform") {
+ if (const auto *PAP =
+ mdconst::dyn_extract_or_null<ConstantInt>(MDN->getOperand(2)))
+ PAuthABIPlatform = PAP->getZExtValue();
+ } else if (FlagName->getString() == "aarch64-elf-pauthabi-version") {
+ if (const auto *PAV =
+ mdconst::dyn_extract_or_null<ConstantInt>(MDN->getOperand(2)))
+ PAuthABIVersion = PAV->getZExtValue();
+ }
+ }
+ }
+
+ if ((PAuthABIPlatform == uint64_t(-1)) != (PAuthABIVersion == uint64_t(-1)))
+ report_fatal_error(
+ "either both or no 'aarch64-elf-pauthabi-platform' and "
+ "'aarch64-elf-pauthabi-version' module flags must be present");
// Validate that the requirements in the module are valid.
for (const MDNode *Requirement : Requirements) {
diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index 6f7d1548d09c76..f6ccd0ecfdc893 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -277,11 +277,6 @@ void AArch64AsmPrinter::emitStartOfAsmFile(Module &M) {
M.getModuleFlag("aarch64-elf-pauthabi-version")))
PAuthABIVersion = PAV->getZExtValue();
- if ((PAuthABIPlatform == uint64_t(-1)) != (PAuthABIVersion == uint64_t(-1)))
- report_fatal_error(
- "either both or no 'aarch64-elf-pauthabi-platform' and "
- "'aarch64-elf-pauthabi-version' module flags must be present");
-
// Emit a .note.gnu.property section with the flags.
auto *TS =
static_cast<AArch64TargetStreamer *>(OutStreamer->getTargetStreamer());
>From 2f6dc0adbee9e09176e86dd9960b8d353c31decf Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Fri, 22 Mar 2024 10:18:51 +0300
Subject: [PATCH 4/5] Address review comments
- Use `CheckFailed` instead of `report_fatal_error` in verifier
- Add tests for verifier
---
llvm/lib/IR/Verifier.cpp | 2 +-
.../AArch64/note-gnu-property-elf-pauthabi.ll | 4 ++--
...le-flags-note-gnu-property-elf-pauthabi.ll | 19 +++++++++++++++++++
3 files changed, 22 insertions(+), 3 deletions(-)
create mode 100644 llvm/test/Verifier/module-flags-note-gnu-property-elf-pauthabi.ll
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 85de16e65c1726..f5fd429b99988e 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -1754,7 +1754,7 @@ void Verifier::visitModuleFlags() {
}
if ((PAuthABIPlatform == uint64_t(-1)) != (PAuthABIVersion == uint64_t(-1)))
- report_fatal_error(
+ CheckFailed(
"either both or no 'aarch64-elf-pauthabi-platform' and "
"'aarch64-elf-pauthabi-version' module flags must be present");
diff --git a/llvm/test/CodeGen/AArch64/note-gnu-property-elf-pauthabi.ll b/llvm/test/CodeGen/AArch64/note-gnu-property-elf-pauthabi.ll
index 46c4bb1490375e..728cffeba02a25 100644
--- a/llvm/test/CodeGen/AArch64/note-gnu-property-elf-pauthabi.ll
+++ b/llvm/test/CodeGen/AArch64/note-gnu-property-elf-pauthabi.ll
@@ -33,7 +33,7 @@
;--- err1.ll
-; RUN: not --crash llc -mtriple=aarch64-linux err1.ll 2>&1 -o - | \
+; RUN: not llc -mtriple=aarch64-linux err1.ll 2>&1 -o - | \
; RUN: FileCheck %s --check-prefix=ERR
!llvm.module.flags = !{!0}
@@ -42,7 +42,7 @@
;--- err2.ll
-; RUN: not --crash llc -mtriple=aarch64-linux err2.ll 2>&1 -o - | \
+; RUN: not llc -mtriple=aarch64-linux err2.ll 2>&1 -o - | \
; RUN: FileCheck %s --check-prefix=ERR
!llvm.module.flags = !{!0}
diff --git a/llvm/test/Verifier/module-flags-note-gnu-property-elf-pauthabi.ll b/llvm/test/Verifier/module-flags-note-gnu-property-elf-pauthabi.ll
new file mode 100644
index 00000000000000..435073d01c8e65
--- /dev/null
+++ b/llvm/test/Verifier/module-flags-note-gnu-property-elf-pauthabi.ll
@@ -0,0 +1,19 @@
+; RUN: rm -rf %t && split-file %s %t && cd %t
+
+; CHECK: either both or no 'aarch64-elf-pauthabi-platform' and 'aarch64-elf-pauthabi-version' module flags must be present
+
+;--- err1.ll
+
+; RUN: not llvm-as err1.ll -o /dev/null 2>&1 | FileCheck %s
+
+!llvm.module.flags = !{!0}
+
+!0 = !{i32 1, !"aarch64-elf-pauthabi-platform", i32 2}
+
+;--- err2.ll
+
+; RUN: not llvm-as err2.ll -o /dev/null 2>&1 | FileCheck %s
+
+!llvm.module.flags = !{!0}
+
+!0 = !{i32 1, !"aarch64-elf-pauthabi-version", i32 31}
>From d313921f61139c630652a798afce1ea0a0f438c5 Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Fri, 22 Mar 2024 10:57:44 +0300
Subject: [PATCH 5/5] Fix code formatting
---
llvm/lib/IR/Verifier.cpp | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index f5fd429b99988e..3ae812cfa25015 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -1754,9 +1754,8 @@ void Verifier::visitModuleFlags() {
}
if ((PAuthABIPlatform == uint64_t(-1)) != (PAuthABIVersion == uint64_t(-1)))
- CheckFailed(
- "either both or no 'aarch64-elf-pauthabi-platform' and "
- "'aarch64-elf-pauthabi-version' module flags must be present");
+ CheckFailed("either both or no 'aarch64-elf-pauthabi-platform' and "
+ "'aarch64-elf-pauthabi-version' module flags must be present");
// Validate that the requirements in the module are valid.
for (const MDNode *Requirement : Requirements) {
More information about the llvm-commits
mailing list