[clang] [llvm] [PAC][ELF][AArch64] Support signed personality function pointer (PR #113148)
Daniil Kovalev via cfe-commits
cfe-commits at lists.llvm.org
Mon Nov 18 05:20:54 PST 2024
https://github.com/kovdan01 updated https://github.com/llvm/llvm-project/pull/113148
>From e192b193471831d004a715ce3b1684198342dba4 Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Mon, 21 Oct 2024 13:28:58 +0300
Subject: [PATCH] [PAC][ELF][AArch64] Support signed personality function
pointer
If function pointer signing is enabled, sign personality function pointer
stored in `.DW.ref.__gxx_personality_v0` section with IA key,
0x7EAD = `ptrauth_string_discriminator("personality")` constant discriminator
and address diversity enabled.
---
clang/lib/CodeGen/CodeGenModule.cpp | 3 ++
clang/test/CodeGen/ptrauth-module-flags.c | 8 ++++
.../llvm/CodeGen/MachineModuleInfoImpls.h | 8 +++-
.../CodeGen/TargetLoweringObjectFileImpl.h | 8 +++-
.../llvm/Target/TargetLoweringObjectFile.h | 3 +-
.../CodeGen/AsmPrinter/DwarfCFIException.cpp | 3 +-
llvm/lib/CodeGen/MachineModuleInfoImpls.cpp | 12 ++++++
.../CodeGen/TargetLoweringObjectFileImpl.cpp | 10 ++++-
.../AArch64/AArch64TargetObjectFile.cpp | 16 ++++++++
.../Target/AArch64/AArch64TargetObjectFile.h | 4 ++
.../MCTargetDesc/AArch64TargetStreamer.cpp | 10 +++++
.../MCTargetDesc/AArch64TargetStreamer.h | 7 ++++
llvm/lib/Target/TargetLoweringObjectFile.cpp | 7 ++--
.../AArch64/ptrauth-sign-personality.ll | 39 +++++++++++++++++++
14 files changed, 129 insertions(+), 9 deletions(-)
create mode 100644 clang/test/CodeGen/ptrauth-module-flags.c
create mode 100644 llvm/test/CodeGen/AArch64/ptrauth-sign-personality.ll
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 508f53482d4e1f..8b2d92a6cc9379 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -1214,6 +1214,9 @@ void CodeGenModule::Release() {
"sign-return-address-with-bkey", 1);
if (getTriple().isOSLinux()) {
+ if (LangOpts.PointerAuthCalls)
+ getModule().addModuleFlag(llvm::Module::Min, "ptrauth-sign-personality",
+ 1);
assert(getTriple().isOSBinFormatELF());
using namespace llvm::ELF;
uint64_t PAuthABIVersion =
diff --git a/clang/test/CodeGen/ptrauth-module-flags.c b/clang/test/CodeGen/ptrauth-module-flags.c
new file mode 100644
index 00000000000000..150e5bf59fb05e
--- /dev/null
+++ b/clang/test/CodeGen/ptrauth-module-flags.c
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -triple aarch64-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=OFF
+// RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-calls -emit-llvm %s -o - | FileCheck %s --check-prefix=PERSONALITY
+
+// PERSONALITY: !llvm.module.flags = !{
+// PERSONALITY-SAME: !1
+// PERSONALITY: !1 = !{i32 8, !"ptrauth-sign-personality", i32 1}
+
+// OFF-NOT: "ptrauth-
diff --git a/llvm/include/llvm/CodeGen/MachineModuleInfoImpls.h b/llvm/include/llvm/CodeGen/MachineModuleInfoImpls.h
index c1ae3d2d966df5..f7a028625ee3c8 100644
--- a/llvm/include/llvm/CodeGen/MachineModuleInfoImpls.h
+++ b/llvm/include/llvm/CodeGen/MachineModuleInfoImpls.h
@@ -83,10 +83,14 @@ class MachineModuleInfoELF : public MachineModuleInfoImpl {
/// extern_weak symbols.
DenseMap<MCSymbol *, const MCExpr *> AuthPtrStubs;
+ /// HasSignedPersonality is true if the corresponding IR module has the
+ /// "ptrauth-sign-personality" flag set to 1.
+ bool HasSignedPersonality = false;
+
virtual void anchor(); // Out of line virtual method.
public:
- MachineModuleInfoELF(const MachineModuleInfo &) {}
+ MachineModuleInfoELF(const MachineModuleInfo &);
StubValueTy &getGVStubEntry(MCSymbol *Sym) {
assert(Sym && "Key cannot be null");
@@ -105,6 +109,8 @@ class MachineModuleInfoELF : public MachineModuleInfoImpl {
ExprStubListTy getAuthGVStubList() {
return getSortedExprStubs(AuthPtrStubs);
}
+
+ bool hasSignedPersonality() const { return HasSignedPersonality; }
};
/// MachineModuleInfoCOFF - This is a MachineModuleInfoImpl implementation
diff --git a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
index 8eef45ce565deb..a2a9e5d499e527 100644
--- a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
+++ b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
@@ -52,7 +52,13 @@ class TargetLoweringObjectFileELF : public TargetLoweringObjectFile {
void emitModuleMetadata(MCStreamer &Streamer, Module &M) const override;
void emitPersonalityValue(MCStreamer &Streamer, const DataLayout &DL,
- const MCSymbol *Sym) const override;
+ const MCSymbol *Sym,
+ const MachineModuleInfo *MMI) const override;
+
+ virtual void emitPersonalityValueImpl(MCStreamer &Streamer,
+ const DataLayout &DL,
+ const MCSymbol *Sym,
+ const MachineModuleInfo *MMI) const;
/// Given a constant with the SectionKind, return a section that it should be
/// placed in.
diff --git a/llvm/include/llvm/Target/TargetLoweringObjectFile.h b/llvm/include/llvm/Target/TargetLoweringObjectFile.h
index 0c09cfe684783b..4864ba843f4886 100644
--- a/llvm/include/llvm/Target/TargetLoweringObjectFile.h
+++ b/llvm/include/llvm/Target/TargetLoweringObjectFile.h
@@ -82,7 +82,8 @@ class TargetLoweringObjectFile : public MCObjectFileInfo {
virtual void Initialize(MCContext &ctx, const TargetMachine &TM);
virtual void emitPersonalityValue(MCStreamer &Streamer, const DataLayout &TM,
- const MCSymbol *Sym) const;
+ const MCSymbol *Sym,
+ const MachineModuleInfo *MMI) const;
/// Emit the module-level metadata that the platform cares about.
virtual void emitModuleMetadata(MCStreamer &Streamer, Module &M) const {}
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp
index 087ee02a7f2b35..4fac4bbc98477d 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp
@@ -50,7 +50,8 @@ void DwarfCFIException::endModule() {
// Emit indirect reference table for all used personality functions
for (const GlobalValue *Personality : Personalities) {
MCSymbol *Sym = Asm->getSymbol(Personality);
- TLOF.emitPersonalityValue(*Asm->OutStreamer, Asm->getDataLayout(), Sym);
+ TLOF.emitPersonalityValue(*Asm->OutStreamer, Asm->getDataLayout(), Sym,
+ Asm->MMI);
}
Personalities.clear();
}
diff --git a/llvm/lib/CodeGen/MachineModuleInfoImpls.cpp b/llvm/lib/CodeGen/MachineModuleInfoImpls.cpp
index 956317510dc736..0d8c30883d6dcf 100644
--- a/llvm/lib/CodeGen/MachineModuleInfoImpls.cpp
+++ b/llvm/lib/CodeGen/MachineModuleInfoImpls.cpp
@@ -14,6 +14,8 @@
#include "llvm/CodeGen/MachineModuleInfoImpls.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/Module.h"
#include "llvm/MC/MCSymbol.h"
using namespace llvm;
@@ -59,3 +61,13 @@ MachineModuleInfoImpl::ExprStubListTy MachineModuleInfoImpl::getSortedExprStubs(
ExprStubs.clear();
return List;
}
+
+MachineModuleInfoELF::MachineModuleInfoELF(const MachineModuleInfo &MMI) {
+ const Module *M = MMI.getModule();
+ const auto *Flag = mdconst::extract_or_null<ConstantInt>(
+ M->getModuleFlag("ptrauth-sign-personality"));
+ if (Flag && Flag->getZExtValue() == 1)
+ HasSignedPersonality = true;
+ else
+ HasSignedPersonality = false;
+}
diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index ce50a3c19ffe04..d5342b5d3651f1 100644
--- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -413,7 +413,8 @@ MCSymbol *TargetLoweringObjectFileELF::getCFIPersonalitySymbol(
}
void TargetLoweringObjectFileELF::emitPersonalityValue(
- MCStreamer &Streamer, const DataLayout &DL, const MCSymbol *Sym) const {
+ MCStreamer &Streamer, const DataLayout &DL, const MCSymbol *Sym,
+ const MachineModuleInfo *MMI) const {
SmallString<64> NameData("DW.ref.");
NameData += Sym->getName();
MCSymbolELF *Label =
@@ -431,6 +432,13 @@ void TargetLoweringObjectFileELF::emitPersonalityValue(
Streamer.emitELFSize(Label, E);
Streamer.emitLabel(Label);
+ emitPersonalityValueImpl(Streamer, DL, Sym, MMI);
+}
+
+void TargetLoweringObjectFileELF::emitPersonalityValueImpl(
+ MCStreamer &Streamer, const DataLayout &DL, const MCSymbol *Sym,
+ const MachineModuleInfo *MMI) const {
+ unsigned Size = DL.getPointerSize();
Streamer.emitSymbolValue(Sym, Size);
}
diff --git a/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp b/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp
index 54de42a094f340..9b242f3213d01f 100644
--- a/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp
+++ b/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp
@@ -9,6 +9,7 @@
#include "AArch64TargetObjectFile.h"
#include "AArch64TargetMachine.h"
#include "MCTargetDesc/AArch64MCExpr.h"
+#include "MCTargetDesc/AArch64TargetStreamer.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/CodeGen/MachineModuleInfoImpls.h"
#include "llvm/IR/Mangler.h"
@@ -28,6 +29,21 @@ void AArch64_ELFTargetObjectFile::Initialize(MCContext &Ctx,
SupportDebugThreadLocalLocation = false;
}
+void AArch64_ELFTargetObjectFile::emitPersonalityValueImpl(
+ MCStreamer &Streamer, const DataLayout &DL, const MCSymbol *Sym,
+ const MachineModuleInfo *MMI) const {
+ if (!MMI->getObjFileInfo<MachineModuleInfoELF>().hasSignedPersonality()) {
+ TargetLoweringObjectFileELF::emitPersonalityValueImpl(Streamer, DL, Sym,
+ MMI);
+ return;
+ }
+ auto *TS = static_cast<AArch64TargetStreamer *>(Streamer.getTargetStreamer());
+ // The value is ptrauth_string_discriminator("personality")
+ constexpr uint16_t Discriminator = 0x7EAD;
+ TS->emitAuthValue(MCSymbolRefExpr::create(Sym, getContext()), Discriminator,
+ AArch64PACKey::IA, true, getContext());
+}
+
const MCExpr *AArch64_ELFTargetObjectFile::getIndirectSymViaGOTPCRel(
const GlobalValue *GV, const MCSymbol *Sym, const MCValue &MV,
int64_t Offset, MachineModuleInfo *MMI, MCStreamer &Streamer) const {
diff --git a/llvm/lib/Target/AArch64/AArch64TargetObjectFile.h b/llvm/lib/Target/AArch64/AArch64TargetObjectFile.h
index 2ef8bda2988d47..0c822ac84f200c 100644
--- a/llvm/lib/Target/AArch64/AArch64TargetObjectFile.h
+++ b/llvm/lib/Target/AArch64/AArch64TargetObjectFile.h
@@ -35,6 +35,10 @@ class AArch64_ELFTargetObjectFile : public TargetLoweringObjectFileELF {
MachineModuleInfo *MMI, const MCSymbol *RawSym,
AArch64PACKey::ID Key,
uint16_t Discriminator) const;
+
+ void emitPersonalityValueImpl(MCStreamer &Streamer, const DataLayout &DL,
+ const MCSymbol *Sym,
+ const MachineModuleInfo *MMI) const override;
};
/// AArch64_MachoTargetObjectFile - This TLOF implementation is used for Darwin.
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.cpp
index dc5383ce941ed9..c453cd6f768c3d 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.cpp
@@ -35,6 +35,16 @@ AArch64TargetStreamer::AArch64TargetStreamer(MCStreamer &S)
AArch64TargetStreamer::~AArch64TargetStreamer() = default;
+void AArch64TargetStreamer::emitAuthValue(const MCExpr *Expr,
+ uint16_t Discriminator,
+ AArch64PACKey::ID Key,
+ bool HasAddressDiversity,
+ MCContext &Ctx) {
+ Streamer.emitValueImpl(AArch64AuthMCExpr::create(Expr, Discriminator, Key,
+ HasAddressDiversity, Ctx),
+ 8);
+}
+
// The constant pool handling is shared by all AArch64TargetStreamer
// implementations.
const MCExpr *AArch64TargetStreamer::addConstantPoolEntry(const MCExpr *Expr,
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h
index ac441ae3b603ff..e6d448e45d45d3 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h
@@ -9,6 +9,7 @@
#ifndef LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64TARGETSTREAMER_H
#define LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64TARGETSTREAMER_H
+#include "AArch64MCExpr.h"
#include "llvm/MC/MCStreamer.h"
namespace {
@@ -38,6 +39,12 @@ class AArch64TargetStreamer : public MCTargetStreamer {
void emitNoteSection(unsigned Flags, uint64_t PAuthABIPlatform = -1,
uint64_t PAuthABIVersion = -1);
+ /// Callback used to emit AUTH expressions (e.g. signed
+ /// personality function pointer).
+ void emitAuthValue(const MCExpr *Expr, uint16_t Discriminator,
+ AArch64PACKey::ID Key, bool HasAddressDiversity,
+ MCContext &Ctx);
+
/// Callback used to implement the .inst directive.
virtual void emitInst(uint32_t Inst);
diff --git a/llvm/lib/Target/TargetLoweringObjectFile.cpp b/llvm/lib/Target/TargetLoweringObjectFile.cpp
index 7d9b926f4c42b6..4fe9d13d062265 100644
--- a/llvm/lib/Target/TargetLoweringObjectFile.cpp
+++ b/llvm/lib/Target/TargetLoweringObjectFile.cpp
@@ -141,10 +141,9 @@ MCSymbol *TargetLoweringObjectFile::getCFIPersonalitySymbol(
return TM.getSymbol(GV);
}
-void TargetLoweringObjectFile::emitPersonalityValue(MCStreamer &Streamer,
- const DataLayout &,
- const MCSymbol *Sym) const {
-}
+void TargetLoweringObjectFile::emitPersonalityValue(
+ MCStreamer &Streamer, const DataLayout &, const MCSymbol *Sym,
+ const MachineModuleInfo *MMI) const {}
void TargetLoweringObjectFile::emitCGProfileMetadata(MCStreamer &Streamer,
Module &M) const {
diff --git a/llvm/test/CodeGen/AArch64/ptrauth-sign-personality.ll b/llvm/test/CodeGen/AArch64/ptrauth-sign-personality.ll
new file mode 100644
index 00000000000000..d4ee49d9aeeabf
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/ptrauth-sign-personality.ll
@@ -0,0 +1,39 @@
+; RUN: llc -mtriple=aarch64-linux -filetype=asm %s -o - | FileCheck %s
+; RUN: llc -mtriple=aarch64-linux -filetype=obj %s -o - | \
+; RUN: llvm-readelf -r -x .data.DW.ref.__gxx_personality_v0 - | \
+; RUN: FileCheck --check-prefix=RELOC %s
+
+ at _ZTISt9exception = external constant ptr
+
+define i32 @main() personality ptr @__gxx_personality_v0 {
+entry:
+ invoke void @foo() to label %cont unwind label %lpad
+
+lpad:
+ %0 = landingpad { ptr, i32 }
+ catch ptr null
+ catch ptr @_ZTISt9exception
+ ret i32 0
+
+cont:
+ ret i32 0
+}
+
+declare i32 @__gxx_personality_v0(...)
+
+declare void @foo()
+
+!llvm.module.flags = !{!0}
+!0 = !{i32 8, !"ptrauth-sign-personality", i32 1}
+
+; CHECK: DW.ref.__gxx_personality_v0:
+; CHECK-NEXT: .xword __gxx_personality_v0 at AUTH(ia,32429,addr)
+
+; RELOC: Relocation section '.rela.data.DW.ref.__gxx_personality_v0' at offset 0x2a0 contains 1 entries:
+; RELOC-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend
+; RELOC-NEXT: 0000000000000000 0000000f00000244 R_AARCH64_AUTH_ABS64 0000000000000000 __gxx_personality_v0 + 0
+
+; RELOC: Hex dump of section '.data.DW.ref.__gxx_personality_v0':
+; RELOC-NEXT: 0x00000000 00000000 ad7e0080
+; ^^^^ 0x7EAD = discriminator
+; ^^ 0b10000000: bit 63 = 1 -> address diversity enabled, bits 61:60 = 0b00 -> key is IA
More information about the cfe-commits
mailing list