[clang] [clang][CGObjC] Sign the v-table pointer in ObjC exception RTTI. (PR #135562)

Oliver Hunt via cfe-commits cfe-commits at lists.llvm.org
Wed Jun 4 12:16:36 PDT 2025


https://github.com/ojhunt updated https://github.com/llvm/llvm-project/pull/135562

>From 5dc1e5fbb57f88e412e044605d8fe30a66255a35 Mon Sep 17 00:00:00 2001
From: Oliver Hunt <oliver at apple.com>
Date: Sun, 13 Apr 2025 13:21:49 -0700
Subject: [PATCH 1/4] [clang][CGObjC] Sign the v-table pointer in ObjC
 exception RTTI.

---
 clang/docs/ReleaseNotes.rst                   |  1 +
 .../clang/CodeGen/ConstantInitBuilder.h       |  3 +++
 clang/lib/CodeGen/CGObjCMac.cpp               | 20 +++++++++++++++++--
 clang/lib/CodeGen/ConstantInitBuilder.cpp     | 12 +++++++++++
 .../test/CodeGenObjC/ptrauth-attr-exception.m | 16 +++++++++++++++
 5 files changed, 50 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/CodeGenObjC/ptrauth-attr-exception.m

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 11f62bc881b03..67fef2fa0c37f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -191,6 +191,7 @@ Non-comprehensive list of changes in this release
 - Support parsing the `cc` operand modifier and alias it to the `c` modifier (#GH127719).
 - Added `__builtin_elementwise_exp10`.
 - For AMDPGU targets, added `__builtin_v_cvt_off_f32_i4` that maps to the `v_cvt_off_f32_i4` instruction.
+- Support authenticated ``type_info`` vtable pointers in Objective-C++
 
 New Compiler Flags
 ------------------
diff --git a/clang/include/clang/CodeGen/ConstantInitBuilder.h b/clang/include/clang/CodeGen/ConstantInitBuilder.h
index 28d4764b6d60b..a7424abbc07eb 100644
--- a/clang/include/clang/CodeGen/ConstantInitBuilder.h
+++ b/clang/include/clang/CodeGen/ConstantInitBuilder.h
@@ -206,6 +206,9 @@ class ConstantAggregateBuilderBase {
   void addSignedPointer(llvm::Constant *Pointer,
                         const PointerAuthSchema &Schema, GlobalDecl CalleeDecl,
                         QualType CalleeType);
+  void addSignedPointer(llvm::Constant *Pointer, unsigned Key,
+                        bool UseAddressDiscrimination,
+                        llvm::ConstantInt *OtherDiscriminator);
 
   /// Add a null pointer of a specific type.
   void addNullPointer(llvm::PointerType *ptrTy) {
diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp
index 1f11347b81411..e854f6b5920c8 100644
--- a/clang/lib/CodeGen/CGObjCMac.cpp
+++ b/clang/lib/CodeGen/CGObjCMac.cpp
@@ -7676,10 +7676,26 @@ CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
   }
 
   llvm::Value *VTableIdx = llvm::ConstantInt::get(CGM.Int32Ty, 2);
+  llvm::Constant *VTablePtr = llvm::ConstantExpr::getInBoundsGetElementPtr(
+      VTableGV->getValueType(), VTableGV, VTableIdx);
+
   ConstantInitBuilder builder(CGM);
   auto values = builder.beginStruct(ObjCTypes.EHTypeTy);
-  values.add(llvm::ConstantExpr::getInBoundsGetElementPtr(
-      VTableGV->getValueType(), VTableGV, VTableIdx));
+
+  if (auto &Schema =
+          CGM.getCodeGenOpts().PointerAuth.CXXTypeInfoVTablePointer) {
+    uint32_t discrimination = 0;
+    if (Schema.hasOtherDiscrimination()) {
+      assert(Schema.getOtherDiscrimination() ==
+             PointerAuthSchema::Discrimination::Constant);
+      discrimination = Schema.getConstantDiscrimination();
+    }
+    values.addSignedPointer(
+        VTablePtr, Schema.getKey(), Schema.isAddressDiscriminated(),
+        llvm::ConstantInt::get(CGM.IntPtrTy, discrimination));
+  } else {
+    values.add(VTablePtr);
+  }
   values.add(GetClassName(ClassName));
   values.add(GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition));
 
diff --git a/clang/lib/CodeGen/ConstantInitBuilder.cpp b/clang/lib/CodeGen/ConstantInitBuilder.cpp
index ce1fe137c1919..c5b1ad3a07235 100644
--- a/clang/lib/CodeGen/ConstantInitBuilder.cpp
+++ b/clang/lib/CodeGen/ConstantInitBuilder.cpp
@@ -314,3 +314,15 @@ void ConstantAggregateBuilderBase::addSignedPointer(
       Pointer, Schema, StorageAddress, CalleeDecl, CalleeType);
   add(SignedPointer);
 }
+
+void ConstantAggregateBuilderBase::addSignedPointer(
+    llvm::Constant *Pointer, unsigned Key, bool UseAddressDiscrimination,
+    llvm::ConstantInt *OtherDiscriminator) {
+  llvm::Constant *StorageAddress = nullptr;
+  if (UseAddressDiscrimination)
+    StorageAddress = getAddrOfCurrentPosition(Pointer->getType());
+
+  llvm::Constant *SignedPointer = Builder.CGM.getConstantSignedPointer(
+      Pointer, Key, StorageAddress, OtherDiscriminator);
+  add(SignedPointer);
+}
diff --git a/clang/test/CodeGenObjC/ptrauth-attr-exception.m b/clang/test/CodeGenObjC/ptrauth-attr-exception.m
new file mode 100644
index 0000000000000..1a17828b927da
--- /dev/null
+++ b/clang/test/CodeGenObjC/ptrauth-attr-exception.m
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -triple arm64-apple-ios -fptrauth-calls -emit-llvm -fexceptions -fobjc-exceptions -o - %s | FileCheck %s
+
+__attribute__((objc_root_class))
+ at interface Root {
+  Class isa;
+}
+ at end
+
+__attribute__((objc_exception))
+ at interface A : Root
+ at end
+
+ at implementation A
+ at end
+
+// CHECK: @"OBJC_EHTYPE_$_A" = global {{%.*}} { ptr ptrauth (ptr getelementptr inbounds (ptr, ptr @objc_ehtype_vtable, i32 2), i32 2),

>From 8db3653794797eb6f2b2e18d6e06441f64fa6b7d Mon Sep 17 00:00:00 2001
From: Oliver Hunt <oliver at apple.com>
Date: Tue, 3 Jun 2025 19:26:30 -0700
Subject: [PATCH 2/4] Switch to Schema addSignedPointer API, remove the
 exploded version, and add more tests

---
 clang/include/clang/CodeGen/ConstantInitBuilder.h |  3 ---
 clang/lib/CodeGen/CGObjCMac.cpp                   | 12 +++---------
 clang/lib/CodeGen/ConstantInitBuilder.cpp         | 12 ------------
 clang/test/CodeGenObjC/ptrauth-attr-exception.m   |  6 ++++--
 4 files changed, 7 insertions(+), 26 deletions(-)

diff --git a/clang/include/clang/CodeGen/ConstantInitBuilder.h b/clang/include/clang/CodeGen/ConstantInitBuilder.h
index a7424abbc07eb..28d4764b6d60b 100644
--- a/clang/include/clang/CodeGen/ConstantInitBuilder.h
+++ b/clang/include/clang/CodeGen/ConstantInitBuilder.h
@@ -206,9 +206,6 @@ class ConstantAggregateBuilderBase {
   void addSignedPointer(llvm::Constant *Pointer,
                         const PointerAuthSchema &Schema, GlobalDecl CalleeDecl,
                         QualType CalleeType);
-  void addSignedPointer(llvm::Constant *Pointer, unsigned Key,
-                        bool UseAddressDiscrimination,
-                        llvm::ConstantInt *OtherDiscriminator);
 
   /// Add a null pointer of a specific type.
   void addNullPointer(llvm::PointerType *ptrTy) {
diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp
index ca50a67396042..0810dde380621 100644
--- a/clang/lib/CodeGen/CGObjCMac.cpp
+++ b/clang/lib/CodeGen/CGObjCMac.cpp
@@ -7684,15 +7684,9 @@ CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
 
   if (auto &Schema =
           CGM.getCodeGenOpts().PointerAuth.CXXTypeInfoVTablePointer) {
-    uint32_t discrimination = 0;
-    if (Schema.hasOtherDiscrimination()) {
-      assert(Schema.getOtherDiscrimination() ==
-             PointerAuthSchema::Discrimination::Constant);
-      discrimination = Schema.getConstantDiscrimination();
-    }
-    values.addSignedPointer(
-        VTablePtr, Schema.getKey(), Schema.isAddressDiscriminated(),
-        llvm::ConstantInt::get(CGM.IntPtrTy, discrimination));
+      assert(!Schema.hasOtherDiscrimination() ||
+             Schema.getOtherDiscrimination() == PointerAuthSchema::Discrimination::Constant);
+    values.addSignedPointer(VTablePtr, Schema, GlobalDecl(), QualType());
   } else {
     values.add(VTablePtr);
   }
diff --git a/clang/lib/CodeGen/ConstantInitBuilder.cpp b/clang/lib/CodeGen/ConstantInitBuilder.cpp
index c5b1ad3a07235..ce1fe137c1919 100644
--- a/clang/lib/CodeGen/ConstantInitBuilder.cpp
+++ b/clang/lib/CodeGen/ConstantInitBuilder.cpp
@@ -314,15 +314,3 @@ void ConstantAggregateBuilderBase::addSignedPointer(
       Pointer, Schema, StorageAddress, CalleeDecl, CalleeType);
   add(SignedPointer);
 }
-
-void ConstantAggregateBuilderBase::addSignedPointer(
-    llvm::Constant *Pointer, unsigned Key, bool UseAddressDiscrimination,
-    llvm::ConstantInt *OtherDiscriminator) {
-  llvm::Constant *StorageAddress = nullptr;
-  if (UseAddressDiscrimination)
-    StorageAddress = getAddrOfCurrentPosition(Pointer->getType());
-
-  llvm::Constant *SignedPointer = Builder.CGM.getConstantSignedPointer(
-      Pointer, Key, StorageAddress, OtherDiscriminator);
-  add(SignedPointer);
-}
diff --git a/clang/test/CodeGenObjC/ptrauth-attr-exception.m b/clang/test/CodeGenObjC/ptrauth-attr-exception.m
index 1a17828b927da..145c14b20a65c 100644
--- a/clang/test/CodeGenObjC/ptrauth-attr-exception.m
+++ b/clang/test/CodeGenObjC/ptrauth-attr-exception.m
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -triple arm64-apple-ios -fptrauth-calls -emit-llvm -fexceptions -fobjc-exceptions -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple arm64-apple-ios                                                   -fptrauth-calls -emit-llvm -fexceptions -fobjc-exceptions -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple arm64-apple-ios -fptrauth-type-info-vtable-pointer-discrimination -fptrauth-calls -emit-llvm -fexceptions -fobjc-exceptions -o - %s | FileCheck --check-prefix=TYPEDISC_TYPEINFO %s
 
 __attribute__((objc_root_class))
 @interface Root {
@@ -13,4 +14,5 @@ @interface A : Root
 @implementation A
 @end
 
-// CHECK: @"OBJC_EHTYPE_$_A" = global {{%.*}} { ptr ptrauth (ptr getelementptr inbounds (ptr, ptr @objc_ehtype_vtable, i32 2), i32 2),
+            // CHECK: @"OBJC_EHTYPE_$_A" = global {{%.*}} { ptr ptrauth (ptr getelementptr inbounds (ptr, ptr @objc_ehtype_vtable, i32 2), i32 2),
+// TYPEDISC_TYPEINFO: @"OBJC_EHTYPE_$_A" = global {{%.*}} { ptr ptrauth (ptr getelementptr inbounds (ptr, ptr @objc_ehtype_vtable, i32 2), i32 2, i64 45546, ptr @"OBJC_EHTYPE_$_A"),

>From 252ff4d187b8b75933ef60530dbd7b5ce8b042e5 Mon Sep 17 00:00:00 2001
From: Oliver Hunt <oliver at apple.com>
Date: Tue, 3 Jun 2025 19:31:34 -0700
Subject: [PATCH 3/4] reformatting

---
 clang/lib/CodeGen/CGObjCMac.cpp | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp
index 0810dde380621..b587606936e58 100644
--- a/clang/lib/CodeGen/CGObjCMac.cpp
+++ b/clang/lib/CodeGen/CGObjCMac.cpp
@@ -7684,8 +7684,9 @@ CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
 
   if (auto &Schema =
           CGM.getCodeGenOpts().PointerAuth.CXXTypeInfoVTablePointer) {
-      assert(!Schema.hasOtherDiscrimination() ||
-             Schema.getOtherDiscrimination() == PointerAuthSchema::Discrimination::Constant);
+    assert(!Schema.hasOtherDiscrimination() ||
+           Schema.getOtherDiscrimination() ==
+               PointerAuthSchema::Discrimination::Constant);
     values.addSignedPointer(VTablePtr, Schema, GlobalDecl(), QualType());
   } else {
     values.add(VTablePtr);

>From 86a6d7f33d9465ef9ca608665cc1d8f2ad4d59c8 Mon Sep 17 00:00:00 2001
From: Oliver Hunt <oliver at apple.com>
Date: Wed, 4 Jun 2025 12:16:26 -0700
Subject: [PATCH 4/4] Update clang/docs/ReleaseNotes.rst

Co-authored-by: John McCall <rjmccall at apple.com>
---
 clang/docs/ReleaseNotes.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 5f69ef8b865c1..95fc8a7d5c979 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -317,7 +317,7 @@ Non-comprehensive list of changes in this release
   ``sizeof`` or ``typeof`` expression. (#GH138444)
 - Deprecation warning is emitted for the deprecated ``__reference_binds_to_temporary`` intrinsic.
   ``__reference_constructs_from_temporary`` should be used instead. (#GH44056)
-- Support authenticated ``type_info`` vtable pointers in Objective-C++
+- Support pointer authentication for Objective-C exception `type_info` objects
 
 New Compiler Flags
 ------------------



More information about the cfe-commits mailing list