Skip to content

Commit d97d560

Browse files
authored
[AArch64][PAC][MC][ELF] Support PAuth ABI compatibility tag (#85236)
Depends on #87545 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.
1 parent 515d3f7 commit d97d560

6 files changed

+127
-12
lines changed

llvm/lib/IR/Verifier.cpp

+21-1
Original file line numberDiff line numberDiff line change
@@ -1734,8 +1734,28 @@ void Verifier::visitModuleFlags() {
17341734
// Scan each flag, and track the flags and requirements.
17351735
DenseMap<const MDString*, const MDNode*> SeenIDs;
17361736
SmallVector<const MDNode*, 16> Requirements;
1737-
for (const MDNode *MDN : Flags->operands())
1737+
uint64_t PAuthABIPlatform = -1;
1738+
uint64_t PAuthABIVersion = -1;
1739+
for (const MDNode *MDN : Flags->operands()) {
17381740
visitModuleFlag(MDN, SeenIDs, Requirements);
1741+
if (MDN->getNumOperands() != 3)
1742+
continue;
1743+
if (const auto *FlagName = dyn_cast_or_null<MDString>(MDN->getOperand(1))) {
1744+
if (FlagName->getString() == "aarch64-elf-pauthabi-platform") {
1745+
if (const auto *PAP =
1746+
mdconst::dyn_extract_or_null<ConstantInt>(MDN->getOperand(2)))
1747+
PAuthABIPlatform = PAP->getZExtValue();
1748+
} else if (FlagName->getString() == "aarch64-elf-pauthabi-version") {
1749+
if (const auto *PAV =
1750+
mdconst::dyn_extract_or_null<ConstantInt>(MDN->getOperand(2)))
1751+
PAuthABIVersion = PAV->getZExtValue();
1752+
}
1753+
}
1754+
}
1755+
1756+
if ((PAuthABIPlatform == uint64_t(-1)) != (PAuthABIVersion == uint64_t(-1)))
1757+
CheckFailed("either both or no 'aarch64-elf-pauthabi-platform' and "
1758+
"'aarch64-elf-pauthabi-version' module flags must be present");
17391759

17401760
// Validate that the requirements in the module are valid.
17411761
for (const MDNode *Requirement : Requirements) {

llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp

+9-3
Original file line numberDiff line numberDiff line change
@@ -268,13 +268,19 @@ void AArch64AsmPrinter::emitStartOfAsmFile(Module &M) {
268268
if (Sign->getZExtValue())
269269
Flags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_PAC;
270270

271-
if (Flags == 0)
272-
return;
271+
uint64_t PAuthABIPlatform = -1;
272+
if (const auto *PAP = mdconst::extract_or_null<ConstantInt>(
273+
M.getModuleFlag("aarch64-elf-pauthabi-platform")))
274+
PAuthABIPlatform = PAP->getZExtValue();
275+
uint64_t PAuthABIVersion = -1;
276+
if (const auto *PAV = mdconst::extract_or_null<ConstantInt>(
277+
M.getModuleFlag("aarch64-elf-pauthabi-version")))
278+
PAuthABIVersion = PAV->getZExtValue();
273279

274280
// Emit a .note.gnu.property section with the flags.
275281
auto *TS =
276282
static_cast<AArch64TargetStreamer *>(OutStreamer->getTargetStreamer());
277-
TS->emitNoteSection(Flags);
283+
TS->emitNoteSection(Flags, PAuthABIPlatform, PAuthABIVersion);
278284
}
279285

280286
void AArch64AsmPrinter::emitFunctionHeaderComment() {

llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.cpp

+26-7
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,17 @@ void AArch64TargetStreamer::finish() {
5858
emitNoteSection(ELF::GNU_PROPERTY_AARCH64_FEATURE_1_BTI);
5959
}
6060

61-
void AArch64TargetStreamer::emitNoteSection(unsigned Flags) {
62-
if (Flags == 0)
61+
void AArch64TargetStreamer::emitNoteSection(unsigned Flags,
62+
uint64_t PAuthABIPlatform,
63+
uint64_t PAuthABIVersion) {
64+
assert((PAuthABIPlatform == uint64_t(-1)) ==
65+
(PAuthABIVersion == uint64_t(-1)));
66+
uint64_t DescSz = 0;
67+
if (Flags != 0)
68+
DescSz += 4 * 4;
69+
if (PAuthABIPlatform != uint64_t(-1))
70+
DescSz += 4 + 4 + 8 * 2;
71+
if (DescSz == 0)
6372
return;
6473

6574
MCStreamer &OutStreamer = getStreamer();
@@ -80,15 +89,25 @@ void AArch64TargetStreamer::emitNoteSection(unsigned Flags) {
8089
// Emit the note header.
8190
OutStreamer.emitValueToAlignment(Align(8));
8291
OutStreamer.emitIntValue(4, 4); // data size for "GNU\0"
83-
OutStreamer.emitIntValue(4 * 4, 4); // Elf_Prop size
92+
OutStreamer.emitIntValue(DescSz, 4); // Elf_Prop array size
8493
OutStreamer.emitIntValue(ELF::NT_GNU_PROPERTY_TYPE_0, 4);
8594
OutStreamer.emitBytes(StringRef("GNU", 4)); // note name
8695

8796
// Emit the PAC/BTI properties.
88-
OutStreamer.emitIntValue(ELF::GNU_PROPERTY_AARCH64_FEATURE_1_AND, 4);
89-
OutStreamer.emitIntValue(4, 4); // data size
90-
OutStreamer.emitIntValue(Flags, 4); // data
91-
OutStreamer.emitIntValue(0, 4); // pad
97+
if (Flags != 0) {
98+
OutStreamer.emitIntValue(ELF::GNU_PROPERTY_AARCH64_FEATURE_1_AND, 4);
99+
OutStreamer.emitIntValue(4, 4); // data size
100+
OutStreamer.emitIntValue(Flags, 4); // data
101+
OutStreamer.emitIntValue(0, 4); // pad
102+
}
103+
104+
// Emit the PAuth ABI compatibility info
105+
if (PAuthABIPlatform != uint64_t(-1)) {
106+
OutStreamer.emitIntValue(ELF::GNU_PROPERTY_AARCH64_FEATURE_PAUTH, 4);
107+
OutStreamer.emitIntValue(8 * 2, 4); // data size
108+
OutStreamer.emitIntValue(PAuthABIPlatform, 8);
109+
OutStreamer.emitIntValue(PAuthABIVersion, 8);
110+
}
92111

93112
OutStreamer.endSection(Nt);
94113
OutStreamer.switchSection(Cur);

llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ class AArch64TargetStreamer : public MCTargetStreamer {
3535
void emitCurrentConstantPool();
3636

3737
/// Callback used to implement the .note.gnu.property section.
38-
void emitNoteSection(unsigned Flags);
38+
void emitNoteSection(unsigned Flags, uint64_t PAuthABIPlatform = -1,
39+
uint64_t PAuthABIVersion = -1);
3940

4041
/// Callback used to implement the .inst directive.
4142
virtual void emitInst(uint32_t Inst);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
; RUN: rm -rf %t && split-file %s %t && cd %t
2+
3+
;--- ok.ll
4+
5+
; RUN: llc -mtriple=aarch64-linux ok.ll -o - | \
6+
; RUN: FileCheck %s --check-prefix=ASM
7+
; RUN: llc -mtriple=aarch64-linux ok.ll -filetype=obj -o - | \
8+
; RUN: llvm-readelf --notes - | FileCheck %s --check-prefix=OBJ
9+
10+
!llvm.module.flags = !{!0, !1}
11+
12+
!0 = !{i32 1, !"aarch64-elf-pauthabi-platform", i32 268435458}
13+
!1 = !{i32 1, !"aarch64-elf-pauthabi-version", i32 85}
14+
15+
; ASM: .section .note.gnu.property,"a",@note
16+
; ASM-NEXT: .p2align 3, 0x0
17+
; ASM-NEXT: .word 4
18+
; ASM-NEXT: .word 24
19+
; ASM-NEXT: .word 5
20+
; ASM-NEXT: .asciz "GNU"
21+
; 3221225473 = 0xc0000001 = GNU_PROPERTY_AARCH64_FEATURE_PAUTH
22+
; ASM-NEXT: .word 3221225473
23+
; ASM-NEXT: .word 16
24+
; ASM-NEXT: .xword 268435458
25+
; ASM-NEXT: .xword 85
26+
27+
; OBJ: Displaying notes found in: .note.gnu.property
28+
; OBJ-NEXT: Owner Data size Description
29+
; OBJ-NEXT: GNU 0x00000018 NT_GNU_PROPERTY_TYPE_0 (property note)
30+
; OBJ-NEXT: AArch64 PAuth ABI core info: platform 0x10000002 (llvm_linux), version 0x55 (PointerAuthIntrinsics, !PointerAuthCalls, PointerAuthReturns, !PointerAuthAuthTraps, PointerAuthVTPtrAddressDiscrimination, !PointerAuthVTPtrTypeDiscrimination, PointerAuthInitFini)
31+
32+
; ERR: either both or no 'aarch64-elf-pauthabi-platform' and 'aarch64-elf-pauthabi-version' module flags must be present
33+
34+
;--- err1.ll
35+
36+
; RUN: not llc -mtriple=aarch64-linux err1.ll 2>&1 -o - | \
37+
; RUN: FileCheck %s --check-prefix=ERR
38+
39+
!llvm.module.flags = !{!0}
40+
41+
!0 = !{i32 1, !"aarch64-elf-pauthabi-platform", i32 2}
42+
43+
;--- err2.ll
44+
45+
; RUN: not llc -mtriple=aarch64-linux err2.ll 2>&1 -o - | \
46+
; RUN: FileCheck %s --check-prefix=ERR
47+
48+
!llvm.module.flags = !{!0}
49+
50+
!0 = !{i32 1, !"aarch64-elf-pauthabi-version", i32 31}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
; RUN: rm -rf %t && split-file %s %t && cd %t
2+
3+
; CHECK: either both or no 'aarch64-elf-pauthabi-platform' and 'aarch64-elf-pauthabi-version' module flags must be present
4+
5+
;--- err1.ll
6+
7+
; RUN: not llvm-as err1.ll -o /dev/null 2>&1 | FileCheck %s
8+
9+
!llvm.module.flags = !{!0}
10+
11+
!0 = !{i32 1, !"aarch64-elf-pauthabi-platform", i32 2}
12+
13+
;--- err2.ll
14+
15+
; RUN: not llvm-as err2.ll -o /dev/null 2>&1 | FileCheck %s
16+
17+
!llvm.module.flags = !{!0}
18+
19+
!0 = !{i32 1, !"aarch64-elf-pauthabi-version", i32 31}

0 commit comments

Comments
 (0)