Skip to content

Commit a3ddb4e

Browse files
committed
[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.
1 parent a0cc186 commit a3ddb4e

File tree

4 files changed

+95
-11
lines changed

4 files changed

+95
-11
lines changed

llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,8 @@ void AArch64AsmPrinter::emitStartOfAsmFile(Module &M) {
265265
S, MCConstantExpr::create(Feat00Value, MMI->getContext()));
266266
}
267267

268+
// TODO: enhance naming to distinguish MachO ptrauth ABI version and ELF
269+
// pauthabi platform and version
268270
if (TM.getTargetTriple().isOSBinFormatMachO())
269271
EmitPtrAuthVersion(M);
270272

@@ -283,13 +285,24 @@ void AArch64AsmPrinter::emitStartOfAsmFile(Module &M) {
283285
if (Sign->getZExtValue())
284286
Flags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_PAC;
285287

286-
if (Flags == 0)
287-
return;
288+
uint64_t PAuthABIPlatform = -1;
289+
if (const auto *PAP = mdconst::extract_or_null<ConstantInt>(
290+
M.getModuleFlag("aarch64-elf-pauthabi-platform")))
291+
PAuthABIPlatform = PAP->getZExtValue();
292+
uint64_t PAuthABIVersion = -1;
293+
if (const auto *PAV = mdconst::extract_or_null<ConstantInt>(
294+
M.getModuleFlag("aarch64-elf-pauthabi-version")))
295+
PAuthABIVersion = PAV->getZExtValue();
296+
297+
if ((PAuthABIPlatform == uint64_t(-1)) != (PAuthABIVersion == uint64_t(-1)))
298+
report_fatal_error(
299+
"either both or no 'aarch64-elf-pauthabi-platform' and "
300+
"'aarch64-elf-pauthabi-version' module flags must be present");
288301

289302
// Emit a .note.gnu.property section with the flags.
290303
auto *TS =
291304
static_cast<AArch64TargetStreamer *>(OutStreamer->getTargetStreamer());
292-
TS->emitNoteSection(Flags);
305+
TS->emitNoteSection(Flags, PAuthABIPlatform, PAuthABIVersion);
293306
}
294307

295308
void AArch64AsmPrinter::emitFunctionHeaderComment() {

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

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,20 @@ void AArch64TargetStreamer::emitConstantPools() {
5656
void AArch64TargetStreamer::finish() {
5757
if (MarkBTIProperty)
5858
emitNoteSection(ELF::GNU_PROPERTY_AARCH64_FEATURE_1_BTI);
59+
// TODO: do we need to handle GNU_PROPERTY_AARCH64_FEATURE_PAUTH here?
5960
}
6061

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

6575
MCStreamer &OutStreamer = getStreamer();
@@ -80,15 +90,25 @@ void AArch64TargetStreamer::emitNoteSection(unsigned Flags) {
8090
// Emit the note header.
8191
OutStreamer.emitValueToAlignment(Align(8));
8292
OutStreamer.emitIntValue(4, 4); // data size for "GNU\0"
83-
OutStreamer.emitIntValue(4 * 4, 4); // Elf_Prop size
93+
OutStreamer.emitIntValue(DescSz, 4); // Elf_Prop array size
8494
OutStreamer.emitIntValue(ELF::NT_GNU_PROPERTY_TYPE_0, 4);
8595
OutStreamer.emitBytes(StringRef("GNU", 4)); // note name
8696

8797
// 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
98+
if (Flags != 0) {
99+
OutStreamer.emitIntValue(ELF::GNU_PROPERTY_AARCH64_FEATURE_1_AND, 4);
100+
OutStreamer.emitIntValue(4, 4); // data size
101+
OutStreamer.emitIntValue(Flags, 4); // data
102+
OutStreamer.emitIntValue(0, 4); // pad
103+
}
104+
105+
// Emit the PAuth ABI compatibility info
106+
if (PAuthABIPlatform != uint64_t(-1)) {
107+
OutStreamer.emitIntValue(ELF::GNU_PROPERTY_AARCH64_FEATURE_PAUTH, 4);
108+
OutStreamer.emitIntValue(8 * 2, 4); // data size
109+
OutStreamer.emitIntValue(PAuthABIPlatform, 8);
110+
OutStreamer.emitIntValue(PAuthABIVersion, 8);
111+
}
92112

93113
OutStreamer.endSection(Nt);
94114
OutStreamer.switchSection(Cur);

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

Lines changed: 2 additions & 1 deletion
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);
Lines changed: 50 additions & 0 deletions
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 2}
13+
!1 = !{i32 1, !"aarch64-elf-pauthabi-version", i32 31}
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 2
25+
; ASM-NEXT: .xword 31
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 tag: platform 0x2 (linux), version 0x1f (PointerAuthCalls, PointerAuthReturns, 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 --crash 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 --crash 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}

0 commit comments

Comments
 (0)