Skip to content

[PAC][ELF][AArch64] Support signed personality function pointer #119361

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 3 commits into from
Dec 16, 2024

Conversation

kovdan01
Copy link
Contributor

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.

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.
@kovdan01
Copy link
Contributor Author

@MaskRay Regarding your comment #113148 (comment):

We should add a subclass of MachineModuleInfoELF similar to AMDGPUMachineModuleInfo, then move HasSignedpersonality there. Here you can use a static_cast.

Maybe I got your intention wrong, but it looks like that following this approach will complicate things. Since getObjFileInfo<T> implicitly creates an instance with type T if not created yet, we'll need to add a check against AArch64 each time we call getObjFileInfo<MachineModuleInfoELF>, and, if AArch64, use getObjFileInfo<AArch64MachineModuleInfo>. Otherwise, we might first create an instance of MachineModuleInfoELF, and then try to use it as AArch64MachineModuleInfo, which is wrong.

AMDGPUMachineModuleInfo, which already exists, is only used in SIMemoryLegalizer pass, and is explicitly created. But here we want to change things in common personality-related code, and the target-specific machine module info is stored as pointer to MachineModuleInfoImpl.

So, I've reverted the changes from b4ca8b1. Also, I added tests ensuring that w/o the module flag set, we do not sign personality.

@kovdan01 kovdan01 requested review from asl and MaskRay December 10, 2024 11:39
@kovdan01 kovdan01 marked this pull request as ready for review December 10, 2024 11:39
@llvmbot llvmbot added clang Clang issues not falling into any other category backend:AArch64 clang:codegen IR generation bugs: mangling, exceptions, etc. debuginfo labels Dec 10, 2024
@llvmbot
Copy link
Member

llvmbot commented Dec 10, 2024

@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clang-codegen

Author: Daniil Kovalev (kovdan01)

Changes

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.


Full diff: https://github.com/llvm/llvm-project/pull/119361.diff

14 Files Affected:

  • (modified) clang/lib/CodeGen/CodeGenModule.cpp (+3)
  • (modified) clang/test/CodeGen/ptrauth-module-flags.c (+5)
  • (modified) llvm/include/llvm/CodeGen/MachineModuleInfoImpls.h (+7-1)
  • (modified) llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h (+7-1)
  • (modified) llvm/include/llvm/Target/TargetLoweringObjectFile.h (+2-1)
  • (modified) llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp (+2-1)
  • (modified) llvm/lib/CodeGen/MachineModuleInfoImpls.cpp (+12)
  • (modified) llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp (+9-1)
  • (modified) llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp (+16)
  • (modified) llvm/lib/Target/AArch64/AArch64TargetObjectFile.h (+4)
  • (modified) llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.cpp (+10)
  • (modified) llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h (+6)
  • (modified) llvm/lib/Target/TargetLoweringObjectFile.cpp (+3-4)
  • (added) llvm/test/CodeGen/AArch64/ptrauth-sign-personality.ll (+73)
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..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..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}

@llvmbot
Copy link
Member

llvmbot commented Dec 10, 2024

@llvm/pr-subscribers-debuginfo

Author: Daniil Kovalev (kovdan01)

Changes

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.


Full diff: https://github.com/llvm/llvm-project/pull/119361.diff

14 Files Affected:

  • (modified) clang/lib/CodeGen/CodeGenModule.cpp (+3)
  • (modified) clang/test/CodeGen/ptrauth-module-flags.c (+5)
  • (modified) llvm/include/llvm/CodeGen/MachineModuleInfoImpls.h (+7-1)
  • (modified) llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h (+7-1)
  • (modified) llvm/include/llvm/Target/TargetLoweringObjectFile.h (+2-1)
  • (modified) llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp (+2-1)
  • (modified) llvm/lib/CodeGen/MachineModuleInfoImpls.cpp (+12)
  • (modified) llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp (+9-1)
  • (modified) llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp (+16)
  • (modified) llvm/lib/Target/AArch64/AArch64TargetObjectFile.h (+4)
  • (modified) llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.cpp (+10)
  • (modified) llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h (+6)
  • (modified) llvm/lib/Target/TargetLoweringObjectFile.cpp (+3-4)
  • (added) llvm/test/CodeGen/AArch64/ptrauth-sign-personality.ll (+73)
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..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..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}

@llvmbot
Copy link
Member

llvmbot commented Dec 10, 2024

@llvm/pr-subscribers-backend-aarch64

Author: Daniil Kovalev (kovdan01)

Changes

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.


Full diff: https://github.com/llvm/llvm-project/pull/119361.diff

14 Files Affected:

  • (modified) clang/lib/CodeGen/CodeGenModule.cpp (+3)
  • (modified) clang/test/CodeGen/ptrauth-module-flags.c (+5)
  • (modified) llvm/include/llvm/CodeGen/MachineModuleInfoImpls.h (+7-1)
  • (modified) llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h (+7-1)
  • (modified) llvm/include/llvm/Target/TargetLoweringObjectFile.h (+2-1)
  • (modified) llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp (+2-1)
  • (modified) llvm/lib/CodeGen/MachineModuleInfoImpls.cpp (+12)
  • (modified) llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp (+9-1)
  • (modified) llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp (+16)
  • (modified) llvm/lib/Target/AArch64/AArch64TargetObjectFile.h (+4)
  • (modified) llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.cpp (+10)
  • (modified) llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h (+6)
  • (modified) llvm/lib/Target/TargetLoweringObjectFile.cpp (+3-4)
  • (added) llvm/test/CodeGen/AArch64/ptrauth-sign-personality.ll (+73)
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..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..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}

@kovdan01 kovdan01 self-assigned this Dec 10, 2024
const Module *M = MMI.getModule();
const auto *Flag = mdconst::extract_or_null<ConstantInt>(
M->getModuleFlag("ptrauth-sign-personality"));
if (Flag && Flag->getZExtValue() == 1)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HasSignedPersonality = Flag && ... == 1

void TargetLoweringObjectFileELF::emitPersonalityValueImpl(
MCStreamer &Streamer, const DataLayout &DL, const MCSymbol *Sym,
const MachineModuleInfo *MMI) const {
unsigned Size = DL.getPointerSize();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inline used-once variable

@kovdan01 kovdan01 merged commit f65a21a into llvm:main Dec 16, 2024
5 of 8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:AArch64 clang:codegen IR generation bugs: mangling, exceptions, etc. clang Clang issues not falling into any other category debuginfo
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

3 participants