Author: Daniil Kovalev Date: 2024-12-16T10:24:09+03:00 New Revision: f65a21a4ecc2e712c700c59842b6b9a1d2a9a060
URL: https://github.com/llvm/llvm-project/commit/f65a21a4ecc2e712c700c59842b6b9a1d2a9a060 DIFF: https://github.com/llvm/llvm-project/commit/f65a21a4ecc2e712c700c59842b6b9a1d2a9a060.diff LOG: [PAC][ELF][AArch64] Support signed personality function pointer (#119361) Re-apply #113148 after revert in #119331 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. Added: llvm/test/CodeGen/AArch64/ptrauth-sign-personality.ll Modified: clang/lib/CodeGen/CodeGenModule.cpp clang/test/CodeGen/ptrauth-module-flags.c llvm/include/llvm/CodeGen/MachineModuleInfoImpls.h llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h llvm/include/llvm/Target/TargetLoweringObjectFile.h llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp llvm/lib/CodeGen/MachineModuleInfoImpls.cpp llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp llvm/lib/Target/AArch64/AArch64TargetObjectFile.h llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.cpp llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h llvm/lib/Target/TargetLoweringObjectFile.cpp Removed: ################################################################################ diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index d3d5c0743a520b..841fb1ced9a02b 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1218,6 +1218,9 @@ void CodeGenModule::Release() { getModule().addModuleFlag(llvm::Module::Min, "ptrauth-elf-got", 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 index 5a7e9a7c2a36fe..e441d52cb7c62b 100644 --- a/clang/test/CodeGen/ptrauth-module-flags.c +++ b/clang/test/CodeGen/ptrauth-module-flags.c @@ -1,8 +1,13 @@ // RUN: %clang_cc1 -triple aarch64-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=OFF // RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-elf-got -emit-llvm %s -o - | FileCheck %s --check-prefix=ELFGOT +// RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-calls -emit-llvm %s -o - | FileCheck %s --check-prefix=PERSONALITY // ELFGOT: !llvm.module.flags = !{ // ELFGOT-SAME: !1 // ELFGOT: !1 = !{i32 8, !"ptrauth-elf-got", i32 1} +// 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..5c5f4b6738bb9c 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,10 @@ 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")); + HasSignedPersonality = Flag && Flag->getZExtValue() == 1; +} diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp index ce50a3c19ffe04..be243c0e74e9db 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,7 +432,13 @@ void TargetLoweringObjectFileELF::emitPersonalityValue( Streamer.emitELFSize(Label, E); Streamer.emitLabel(Label); - Streamer.emitSymbolValue(Sym, Size); + emitPersonalityValueImpl(Streamer, DL, Sym, MMI); +} + +void TargetLoweringObjectFileELF::emitPersonalityValueImpl( + MCStreamer &Streamer, const DataLayout &DL, const MCSymbol *Sym, + const MachineModuleInfo *MMI) const { + Streamer.emitSymbolValue(Sym, DL.getPointerSize()); } const MCExpr *TargetLoweringObjectFileELF::getTTypeGlobalReference( diff --git a/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp b/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp index 54de42a094f340..8729fd4b802c8e 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, /*HasAddressDiversity=*/true); +} + 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..7bd89c9e29a728 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) { + Streamer.emitValueImpl(AArch64AuthMCExpr::create(Expr, Discriminator, Key, + HasAddressDiversity, + Streamer.getContext()), + 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..1c0f5d848c00c6 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,11 @@ 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); + /// 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..ef0e203b55ee2d --- /dev/null +++ b/llvm/test/CodeGen/AArch64/ptrauth-sign-personality.ll @@ -0,0 +1,73 @@ +; RUN: rm -rf %t && split-file %s %t && cd %t +; RUN: cat common.ll authflag.ll > auth.ll +; RUN: cat common.ll noauthflag.ll > noauth1.ll +; RUN: cat common.ll > noauth2.ll + +; RUN: llc -mtriple=aarch64-linux -filetype=asm auth.ll -o - | \ +; RUN: FileCheck --check-prefix=AUTH-ASM %s +; RUN: llc -mtriple=aarch64-linux -filetype=obj auth.ll -o - | \ +; RUN: llvm-readelf -r -x .data.DW.ref.__gxx_personality_v0 - | \ +; RUN: FileCheck --check-prefix=AUTH-RELOC %s + +; AUTH-ASM: DW.ref.__gxx_personality_v0: +; AUTH-ASM-NEXT: .xword __gxx_personality_v0@AUTH(ia,32429,addr) + +; AUTH-RELOC: Relocation section '.rela.data.DW.ref.__gxx_personality_v0' at offset 0x2a0 contains 1 entries: +; AUTH-RELOC-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend +; AUTH-RELOC-NEXT: 0000000000000000 0000000f00000244 R_AARCH64_AUTH_ABS64 0000000000000000 __gxx_personality_v0 + 0 + +; AUTH-RELOC: Hex dump of section '.data.DW.ref.__gxx_personality_v0': +; AUTH-RELOC-NEXT: 0x00000000 00000000 ad7e0080 +; ^^^^ 0x7EAD = discriminator +; ^^ 0b10000000: bit 63 = 1 -> address diversity enabled, bits 61:60 = 0b00 -> key is IA + +; RUN: llc -mtriple=aarch64-linux -filetype=asm noauth1.ll -o - | \ +; RUN: FileCheck --check-prefix=NOAUTH-ASM %s +; RUN: llc -mtriple=aarch64-linux -filetype=obj noauth1.ll -o - | \ +; RUN: llvm-readelf -r -x .data.DW.ref.__gxx_personality_v0 - | \ +; RUN: FileCheck --check-prefix=NOAUTH-RELOC %s + +; RUN: llc -mtriple=aarch64-linux -filetype=asm noauth2.ll -o - | \ +; RUN: FileCheck --check-prefix=NOAUTH-ASM %s +; RUN: llc -mtriple=aarch64-linux -filetype=obj noauth2.ll -o - | \ +; RUN: llvm-readelf -r -x .data.DW.ref.__gxx_personality_v0 - | \ +; RUN: FileCheck --check-prefix=NOAUTH-RELOC %s + +; NOAUTH-ASM: DW.ref.__gxx_personality_v0: +; NOAUTH-ASM-NEXT: .xword __gxx_personality_v0{{$}} + +; NOAUTH-RELOC: Relocation section '.rela.data.DW.ref.__gxx_personality_v0' at offset 0x2a0 contains 1 entries: +; NOAUTH-RELOC-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend +; NOAUTH-RELOC-NEXT: 0000000000000000 0000000f00000101 R_AARCH64_ABS64 0000000000000000 __gxx_personality_v0 + 0 + +; NOAUTH-RELOC: Hex dump of section '.data.DW.ref.__gxx_personality_v0': +; NOAUTH-RELOC-NEXT: 0x00000000 00000000 00000000 + +;--- common.ll +@_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() + +;--- authflag.ll +!llvm.module.flags = !{!0} +!0 = !{i32 8, !"ptrauth-sign-personality", i32 1} + +;--- noauthflag.ll +!llvm.module.flags = !{!0} +!0 = !{i32 8, !"ptrauth-sign-personality", i32 0} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits