Skip to content

Commit

Permalink
[AArch64][PAC][MC][ELF] Support PAuth ABI compatibility tag
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
kovdan01 committed Feb 16, 2024
1 parent a0cc186 commit a3ddb4e
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 11 deletions.
19 changes: 16 additions & 3 deletions llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,8 @@ void AArch64AsmPrinter::emitStartOfAsmFile(Module &M) {
S, MCConstantExpr::create(Feat00Value, MMI->getContext()));
}

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

Expand All @@ -283,13 +285,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() {
Expand Down
34 changes: 27 additions & 7 deletions llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,20 @@ void AArch64TargetStreamer::emitConstantPools() {
void AArch64TargetStreamer::finish() {
if (MarkBTIProperty)
emitNoteSection(ELF::GNU_PROPERTY_AARCH64_FEATURE_1_BTI);
// TODO: do we need to handle GNU_PROPERTY_AARCH64_FEATURE_PAUTH here?
}

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();
Expand All @@ -80,15 +90,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);
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
50 changes: 50 additions & 0 deletions llvm/test/CodeGen/AArch64/note-gnu-property-elf-pauthabi.ll
Original file line number Diff line number Diff line change
@@ -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 2}
!1 = !{i32 1, !"aarch64-elf-pauthabi-version", i32 31}

; ASM: .section .note.gnu.property,"a",@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 2
; ASM-NEXT: .xword 31

; 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 0x2 (linux), version 0x1f (PointerAuthCalls, PointerAuthReturns, 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}

0 comments on commit a3ddb4e

Please sign in to comment.