Skip to content

[AArch64][PAC][MC][ELF] Support PAuth ABI compatibility tag #85236

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

Merged
merged 7 commits into from
Apr 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion llvm/lib/IR/Verifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1734,8 +1734,28 @@ 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)))
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) {
Expand Down
12 changes: 9 additions & 3 deletions llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -268,13 +268,19 @@ 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();

// 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
33 changes: 26 additions & 7 deletions llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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);
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 268435458}
!1 = !{i32 1, !"aarch64-elf-pauthabi-version", i32 85}

; 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 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 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

;--- err1.ll

; RUN: not 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 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}
19 changes: 19 additions & 0 deletions llvm/test/Verifier/module-flags-note-gnu-property-elf-pauthabi.ll
Original file line number Diff line number Diff line change
@@ -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}