-
Notifications
You must be signed in to change notification settings - Fork 14.8k
[clang][PAC][ObjC] Merge the block metadata support for the arm64e abi to llvm 21 #153725
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
Conversation
@llvm/pr-subscribers-clang @llvm/pr-subscribers-clang-codegen Author: Oliver Hunt (ojhunt) ChangesThis merges the two PRs required for correct support of blocks on arm64e Patch is 23.60 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/153725.diff 11 Files Affected:
diff --git a/clang/include/clang/Basic/Features.def b/clang/include/clang/Basic/Features.def
index 72f23614aef11..2ecd92e2cd94f 100644
--- a/clang/include/clang/Basic/Features.def
+++ b/clang/include/clang/Basic/Features.def
@@ -155,6 +155,7 @@ FEATURE(ptrauth_vtable_pointer_address_discrimination, LangOpts.PointerAuthVTPtr
FEATURE(ptrauth_vtable_pointer_type_discrimination, LangOpts.PointerAuthVTPtrTypeDiscrimination)
FEATURE(ptrauth_type_info_vtable_pointer_discrimination, LangOpts.PointerAuthTypeInfoVTPtrDiscrimination)
FEATURE(ptrauth_member_function_pointer_type_discrimination, LangOpts.PointerAuthCalls)
+FEATURE(ptrauth_signed_block_descriptors, LangOpts.PointerAuthBlockDescriptorPointers)
FEATURE(ptrauth_function_pointer_type_discrimination, LangOpts.PointerAuthFunctionTypeDiscrimination)
FEATURE(ptrauth_indirect_gotos, LangOpts.PointerAuthIndirectGotos)
FEATURE(ptrauth_init_fini, LangOpts.PointerAuthInitFini)
diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def
index f5a5d84eefb80..25f4575a54257 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -138,6 +138,8 @@ LANGOPT(PointerAuthObjcInterfaceSel, 1, 0, NotCompatible, "authentication of SEL
LANGOPT(PointerAuthObjcInterfaceSelKey, 16, 0, NotCompatible, "authentication key for SEL fields of ObjC interfaces")
LANGOPT(PointerAuthObjcClassROPointers, 1, 0, Benign, "class_ro_t pointer authentication")
+LANGOPT(PointerAuthBlockDescriptorPointers, 1, 0, NotCompatible, "enable signed block descriptors")
+
LANGOPT(DoubleSquareBracketAttributes, 1, 0, NotCompatible, "'[[]]' attributes extension for all language standard modes")
LANGOPT(ExperimentalLateParseAttributes, 1, 0, NotCompatible, "experimental late parsing of attributes")
diff --git a/clang/include/clang/Basic/PointerAuthOptions.h b/clang/include/clang/Basic/PointerAuthOptions.h
index fb6dddf3ae9ce..2b920250721fc 100644
--- a/clang/include/clang/Basic/PointerAuthOptions.h
+++ b/clang/include/clang/Basic/PointerAuthOptions.h
@@ -23,6 +23,10 @@
namespace clang {
+/// Constant discriminator to be used with block descriptor pointers. The value
+/// is ptrauth_string_discriminator("block_descriptor")
+constexpr uint16_t BlockDescriptorConstantDiscriminator = 0xC0BB;
+
/// Constant discriminator to be used with function pointers in .init_array and
/// .fini_array. The value is ptrauth_string_discriminator("init_fini")
constexpr uint16_t InitFiniPointerConstantDiscriminator = 0xD9D4;
@@ -223,6 +227,18 @@ struct PointerAuthOptions {
/// The ABI for function addresses in .init_array and .fini_array
PointerAuthSchema InitFiniPointers;
+ /// The ABI for block invocation function pointers.
+ PointerAuthSchema BlockInvocationFunctionPointers;
+
+ /// The ABI for block object copy/destroy function pointers.
+ PointerAuthSchema BlockHelperFunctionPointers;
+
+ /// The ABI for __block variable copy/destroy function pointers.
+ PointerAuthSchema BlockByrefHelperFunctionPointers;
+
+ /// The ABI for pointers to block descriptors.
+ PointerAuthSchema BlockDescriptorPointers;
+
/// The ABI for Objective-C method lists.
PointerAuthSchema ObjCMethodListFunctionPointers;
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 18e4ab406ce4e..958d0d05ade29 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -4527,6 +4527,7 @@ defm aarch64_jump_table_hardening: OptInCC1FFlag<"aarch64-jump-table-hardening",
defm ptrauth_objc_isa : OptInCC1FFlag<"ptrauth-objc-isa", "Enable signing and authentication of Objective-C object's 'isa' field">;
defm ptrauth_objc_interface_sel : OptInCC1FFlag<"ptrauth-objc-interface-sel", "Enable signing and authentication of Objective-C object's 'SEL' fields">;
defm ptrauth_objc_class_ro : OptInCC1FFlag<"ptrauth-objc-class-ro", "Enable signing and authentication for ObjC class_ro pointers">;
+defm ptrauth_block_descriptor_pointers : OptInCC1FFlag<"ptrauth-block-descriptor-pointers", "Enable signing and authentication of block descriptors">;
}
def fenable_matrix : Flag<["-"], "fenable-matrix">, Group<f_Group>,
diff --git a/clang/lib/CodeGen/Address.h b/clang/lib/CodeGen/Address.h
index a748ddaa110a5..4e7f3561ac049 100644
--- a/clang/lib/CodeGen/Address.h
+++ b/clang/lib/CodeGen/Address.h
@@ -176,6 +176,11 @@ class Address {
static Address invalid() { return Address(nullptr); }
bool isValid() const { return Pointer.getPointer() != nullptr; }
+ llvm::Value *getPointerIfNotSigned() const {
+ assert(isValid() && "pointer isn't valid");
+ return !isSigned() ? Pointer.getPointer() : nullptr;
+ }
+
/// This function is used in situations where the caller is doing some sort of
/// opaque "laundering" of the pointer.
void replaceBasePointer(llvm::Value *P) {
diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp
index 1aba841eb5fc2..c1f5b983f7233 100644
--- a/clang/lib/CodeGen/CGBlocks.cpp
+++ b/clang/lib/CodeGen/CGBlocks.cpp
@@ -188,13 +188,14 @@ static llvm::Constant *buildBlockDescriptor(CodeGenModule &CGM,
// Optional copy/dispose helpers.
bool hasInternalHelper = false;
if (blockInfo.NeedsCopyDispose) {
+ auto &Schema = CGM.getCodeGenOpts().PointerAuth.BlockHelperFunctionPointers;
// copy_func_helper_decl
llvm::Constant *copyHelper = buildCopyHelper(CGM, blockInfo);
- elements.add(copyHelper);
+ elements.addSignedPointer(copyHelper, Schema, GlobalDecl(), QualType());
// destroy_func_decl
llvm::Constant *disposeHelper = buildDisposeHelper(CGM, blockInfo);
- elements.add(disposeHelper);
+ elements.addSignedPointer(disposeHelper, Schema, GlobalDecl(), QualType());
if (cast<llvm::Function>(copyHelper->stripPointerCasts())
->hasInternalLinkage() ||
@@ -567,9 +568,8 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF,
llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true);
info.CanBeGlobal = true;
return;
- }
- else if (C.getLangOpts().ObjC &&
- CGM.getLangOpts().getGC() == LangOptions::NonGC)
+ } else if (C.getLangOpts().ObjC &&
+ CGM.getLangOpts().getGC() == LangOptions::NonGC)
info.HasCapturedVariableLayout = true;
if (block->doesNotEscape())
@@ -783,7 +783,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) {
llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
bool IsOpenCL = CGM.getContext().getLangOpts().OpenCL;
- auto GenVoidPtrTy =
+ llvm::PointerType *GenVoidPtrTy =
IsOpenCL ? CGM.getOpenCLRuntime().getGenericVoidPointerType() : VoidPtrTy;
LangAS GenVoidPtrAddr = IsOpenCL ? LangAS::opencl_generic : LangAS::Default;
auto GenVoidPtrSize = CharUnits::fromQuantity(
@@ -817,9 +817,6 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
: CGM.getNSConcreteStackBlock();
isa = blockISA;
- // Build the block descriptor.
- descriptor = buildBlockDescriptor(CGM, blockInfo);
-
// Compute the initial on-stack block flags.
if (!CGM.getCodeGenOpts().DisableBlockSignatureString)
flags = BLOCK_HAS_SIGNATURE;
@@ -833,6 +830,9 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
flags |= BLOCK_USE_STRET;
if (blockInfo.NoEscape)
flags |= BLOCK_IS_NOESCAPE | BLOCK_IS_GLOBAL;
+
+ // Build the block descriptor.
+ descriptor = buildBlockDescriptor(CGM, blockInfo);
}
auto projectField = [&](unsigned index, const Twine &name) -> Address {
@@ -883,11 +883,25 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
llvm::ConstantInt::get(IntTy, blockInfo.BlockAlign.getQuantity()),
getIntSize(), "block.align");
}
- addHeaderField(blockFn, GenVoidPtrSize, "block.invoke");
- if (!IsOpenCL)
- addHeaderField(descriptor, getPointerSize(), "block.descriptor");
- else if (auto *Helper =
- CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) {
+
+ if (!IsOpenCL) {
+ llvm::Value *blockFnPtr =
+ llvm::ConstantExpr::getBitCast(InvokeFn, VoidPtrTy);
+ QualType type = blockInfo.getBlockExpr()
+ ->getType()
+ ->castAs<BlockPointerType>()
+ ->getPointeeType();
+ addSignedHeaderField(
+ blockFnPtr,
+ CGM.getCodeGenOpts().PointerAuth.BlockInvocationFunctionPointers,
+ GlobalDecl(), type, getPointerSize(), "block.invoke");
+
+ addSignedHeaderField(
+ descriptor, CGM.getCodeGenOpts().PointerAuth.BlockDescriptorPointers,
+ GlobalDecl(), type, getPointerSize(), "block.descriptor");
+ } else if (auto *Helper =
+ CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) {
+ addHeaderField(blockFn, GenVoidPtrSize, "block.invoke");
for (auto I : Helper->getCustomFieldValues(*this, blockInfo)) {
addHeaderField(
I.first,
@@ -895,7 +909,8 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
CGM.getDataLayout().getTypeAllocSize(I.first->getType())),
I.second);
}
- }
+ } else
+ addHeaderField(blockFn, GenVoidPtrSize, "block.invoke");
}
// Finally, capture all the values into the block.
@@ -1166,6 +1181,8 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
ASTContext &Ctx = getContext();
CallArgList Args;
+ llvm::Value *FuncPtr = nullptr;
+
if (getLangOpts().OpenCL) {
// For OpenCL, BlockPtr is already casted to generic block literal.
@@ -1185,7 +1202,7 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
if (!isa<ParmVarDecl>(E->getCalleeDecl()))
Func = CGM.getOpenCLRuntime().getInvokeFunction(E->getCallee());
else {
- llvm::Value *FuncPtr = Builder.CreateStructGEP(GenBlockTy, BlockPtr, 2);
+ FuncPtr = Builder.CreateStructGEP(GenBlockTy, BlockPtr, 2);
Func = Builder.CreateAlignedLoad(GenericVoidPtrTy, FuncPtr,
getPointerAlign());
}
@@ -1194,7 +1211,7 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
BlockPtr =
Builder.CreatePointerCast(BlockPtr, UnqualPtrTy, "block.literal");
// Get pointer to the block invoke function
- llvm::Value *FuncPtr = Builder.CreateStructGEP(GenBlockTy, BlockPtr, 3);
+ FuncPtr = Builder.CreateStructGEP(GenBlockTy, BlockPtr, 3);
// First argument is a block literal casted to a void pointer
BlockPtr = Builder.CreatePointerCast(BlockPtr, VoidPtrTy);
@@ -1211,7 +1228,15 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
CGM.getTypes().arrangeBlockFunctionCall(Args, FuncTy);
// Prepare the callee.
- CGCallee Callee(CGCalleeInfo(), Func);
+ CGPointerAuthInfo PointerAuth;
+ if (auto &AuthSchema =
+ CGM.getCodeGenOpts().PointerAuth.BlockInvocationFunctionPointers) {
+ assert(FuncPtr != nullptr && "Missing function pointer for AuthInfo");
+ PointerAuth =
+ EmitPointerAuthInfo(AuthSchema, FuncPtr, GlobalDecl(), FnType);
+ }
+
+ CGCallee Callee(CGCalleeInfo(), Func, PointerAuth);
// And call the block.
return EmitCall(FnInfo, Callee, ReturnValue, Args, CallOrInvoke);
@@ -1295,14 +1320,15 @@ static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
bool IsOpenCL = CGM.getLangOpts().OpenCL;
bool IsWindows = CGM.getTarget().getTriple().isOSWindows();
+ auto &CGOPointerAuth = CGM.getCodeGenOpts().PointerAuth;
if (!IsOpenCL) {
// isa
if (IsWindows)
fields.addNullPointer(CGM.Int8PtrPtrTy);
else
fields.addSignedPointer(CGM.getNSConcreteGlobalBlock(),
- CGM.getCodeGenOpts().PointerAuth.ObjCIsaPointers,
- GlobalDecl(), QualType());
+ CGOPointerAuth.ObjCIsaPointers, GlobalDecl(),
+ QualType());
// __flags
BlockFlags flags = BLOCK_IS_GLOBAL;
@@ -1321,11 +1347,20 @@ static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
}
// Function
- fields.add(blockFn);
+ if (auto &Schema = CGOPointerAuth.BlockInvocationFunctionPointers) {
+ QualType FnType = blockInfo.getBlockExpr()
+ ->getType()
+ ->castAs<BlockPointerType>()
+ ->getPointeeType();
+ fields.addSignedPointer(blockFn, Schema, GlobalDecl(), FnType);
+ } else
+ fields.add(blockFn);
if (!IsOpenCL) {
// Descriptor
- fields.add(buildBlockDescriptor(CGM, blockInfo));
+ llvm::Constant *Descriptor = buildBlockDescriptor(CGM, blockInfo);
+ fields.addSignedPointer(Descriptor, CGOPointerAuth.BlockDescriptorPointers,
+ GlobalDecl(), QualType());
} else if (auto *Helper =
CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) {
for (auto *I : Helper->getCustomFieldValues(CGM, blockInfo)) {
@@ -1995,8 +2030,8 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {
// it. It's not quite worth the annoyance to avoid creating it in the
// first place.
if (!needsEHCleanup(captureType.isDestructedType()))
- if (auto *I =
- cast_or_null<llvm::Instruction>(dstField.getBasePointer()))
+ if (auto *I = cast_or_null<llvm::Instruction>(
+ dstField.getPointerIfNotSigned()))
I->eraseFromParent();
}
break;
@@ -2730,8 +2765,16 @@ void CodeGenFunction::emitByrefStructureInit(const AutoVarEmission &emission) {
unsigned nextHeaderIndex = 0;
CharUnits nextHeaderOffset;
auto storeHeaderField = [&](llvm::Value *value, CharUnits fieldSize,
- const Twine &name) {
+ const Twine &name, bool isFunction = false) {
auto fieldAddr = Builder.CreateStructGEP(addr, nextHeaderIndex, name);
+ if (isFunction) {
+ if (auto &Schema = CGM.getCodeGenOpts()
+ .PointerAuth.BlockByrefHelperFunctionPointers) {
+ auto PointerAuth = EmitPointerAuthInfo(
+ Schema, fieldAddr.emitRawPointer(*this), GlobalDecl(), QualType());
+ value = EmitPointerAuthSign(PointerAuth, value);
+ }
+ }
Builder.CreateStore(value, fieldAddr);
nextHeaderIndex++;
@@ -2814,10 +2857,10 @@ void CodeGenFunction::emitByrefStructureInit(const AutoVarEmission &emission) {
storeHeaderField(V, getIntSize(), "byref.size");
if (helpers) {
- storeHeaderField(helpers->CopyHelper, getPointerSize(),
- "byref.copyHelper");
+ storeHeaderField(helpers->CopyHelper, getPointerSize(), "byref.copyHelper",
+ /*isFunction=*/true);
storeHeaderField(helpers->DisposeHelper, getPointerSize(),
- "byref.disposeHelper");
+ "byref.disposeHelper", /*isFunction=*/true);
}
if (ByRefHasLifetime && HasByrefExtendedLayout) {
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index bf5f427fbfbb4..62613322320cd 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -1752,7 +1752,6 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args,
options::OPT_fno_ptrauth_objc_interface_sel);
Args.addOptInFlag(CmdArgs, options::OPT_fptrauth_objc_class_ro,
options::OPT_fno_ptrauth_objc_class_ro);
-
if (Triple.getEnvironment() == llvm::Triple::PAuthTest)
handlePAuthABI(Args, CmdArgs);
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 08cf0ae6b2c24..08f3b7a7fcc49 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -1542,6 +1542,17 @@ void CompilerInvocation::setDefaultPointerAuthOptions(
Discrimination::Constant, InitFiniPointerConstantDiscriminator);
}
+ Opts.BlockInvocationFunctionPointers =
+ PointerAuthSchema(Key::ASIA, true, Discrimination::None);
+ Opts.BlockHelperFunctionPointers =
+ PointerAuthSchema(Key::ASIA, true, Discrimination::None);
+ Opts.BlockByrefHelperFunctionPointers =
+ PointerAuthSchema(Key::ASIA, true, Discrimination::None);
+ if (LangOpts.PointerAuthBlockDescriptorPointers)
+ Opts.BlockDescriptorPointers =
+ PointerAuthSchema(Key::ASDA, true, Discrimination::Constant,
+ BlockDescriptorConstantDiscriminator);
+
Opts.ObjCMethodListFunctionPointers =
PointerAuthSchema(Key::ASIA, true, Discrimination::None);
Opts.ObjCMethodListPointer =
@@ -3598,6 +3609,8 @@ static void GeneratePointerAuthArgs(const LangOptions &Opts,
GenerateArg(Consumer, OPT_fptrauth_objc_interface_sel);
if (Opts.PointerAuthObjcClassROPointers)
GenerateArg(Consumer, OPT_fptrauth_objc_class_ro);
+ if (Opts.PointerAuthBlockDescriptorPointers)
+ GenerateArg(Consumer, OPT_fptrauth_block_descriptor_pointers);
}
static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args,
@@ -3621,7 +3634,8 @@ static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args,
Opts.PointerAuthELFGOT = Args.hasArg(OPT_fptrauth_elf_got);
Opts.AArch64JumpTableHardening =
Args.hasArg(OPT_faarch64_jump_table_hardening);
-
+ Opts.PointerAuthBlockDescriptorPointers =
+ Args.hasArg(OPT_fptrauth_block_descriptor_pointers);
Opts.PointerAuthObjcIsa = Args.hasArg(OPT_fptrauth_objc_isa);
Opts.PointerAuthObjcClassROPointers = Args.hasArg(OPT_fptrauth_objc_class_ro);
Opts.PointerAuthObjcInterfaceSel =
diff --git a/clang/test/CodeGen/ptrauth-qualifier-blocks.c b/clang/test/CodeGen/ptrauth-qualifier-blocks.c
index 62da59cf327f6..f460da205cac7 100644
--- a/clang/test/CodeGen/ptrauth-qualifier-blocks.c
+++ b/clang/test/CodeGen/ptrauth-qualifier-blocks.c
@@ -82,9 +82,15 @@ void test_block_address_byref_capture() {
// CHECK: store i32 33554432,
// CHECK: store i32 48,
// CHECK: [[COPY_HELPER_FIELD:%.*]] = getelementptr inbounds nuw [[BYREF_T]], ptr [[BYREF]], i32 0, i32 4
- // CHECK: store ptr @__Block_byref_object_copy_, ptr [[COPY_HELPER_FIELD]], align
+ // CHECK: [[T0:%.*]] = ptrtoint ptr [[COPY_HELPER_FIELD]] to i64
+ // CHECK: [[T1:%.*]] = call i64 @llvm.ptrauth.sign(i64 ptrtoint (ptr @__Block_byref_object_copy_ to i64), i32 0, i64 [[T0]])
+ // CHECK: [[T2:%.*]] = inttoptr i64 [[T1]] to ptr
+ // CHECK: store ptr [[T2]], ptr [[COPY_HELPER_FIELD]], align
// CHECK: [[DISPOSE_HELPER_FIELD:%.*]] = getelementptr inbounds nuw [[BYREF_T]], ptr [[BYREF]], i32 0, i32 5
- // CHECK: store ptr @__Block_byref_object_dispose_, ptr [[DISPOSE_HELPER_FIELD]], align
+ // CHECK: [[T0:%.*]] = ptrtoint ptr [[DISPOSE_HELPER_FIELD]] to i64
+ // CHECK: [[T1:%.*]] = call i64 @llvm.ptrauth.sign(i64 ptrtoint (ptr @__Block_byref_object_dispose_ to i64), i32 0, i64 [[T0]])
+ // CHECK: [[T2:%.*]] = inttoptr i64 [[T1]] to ptr
+ // CHECK: store ptr [[T2]], ptr [[DISPOSE_HELPER_FIELD]], align
// flags - copy/dispose required
// CHECK: store i32 1107296256, ptr
__block struct A * __ptrauth(1, 1, 60) ptr = createA();
diff --git a/clang/test/CodeGenObjC/ptrauth-block-descriptor-pointer.m b/clang/test/CodeGenObjC/ptrauth-block-descriptor-pointer.m
new file mode 100644
index 0000000000000..b51670fd6459a
--- /dev/null
+++ b/clang/test/CodeGenObjC/ptrauth-block-descriptor-pointer.m
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -fobjc-arc -fblocks -fptrauth-calls -fptrauth-block-descriptor-pointers -triple arm64e-apple-ios -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -fobjc-arc -fblocks -fptrauth-calls -triple arm64e-apple-ios -DNO_BLOCK_DESC_AUTH -emit-llvm -o - %s | FileCheck %s --check-prefix=NODESCRIPTORAUTH
+
+#ifndef NO_BLOCK_DESC_AUTH
+_Static_assert(__has_feature(ptrauth_signed_block_descriptors), "-fptrauth-block-descriptor-pointers should set ptrauth_signed_block_descriptors");
+#else
+_Static_assert(!__has_feature(ptrauth_signed_block_descriptors), "-fptrauth-block-descriptor-pointers should not be enabled by default");
+#endif
+
+void a() {
+ // Test out a global block.
+ void (^blk)(void) =...
[truncated]
|
@llvm/pr-subscribers-clang-driver Author: Oliver Hunt (ojhunt) ChangesThis merges the two PRs required for correct support of blocks on arm64e Patch is 23.60 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/153725.diff 11 Files Affected:
diff --git a/clang/include/clang/Basic/Features.def b/clang/include/clang/Basic/Features.def
index 72f23614aef11..2ecd92e2cd94f 100644
--- a/clang/include/clang/Basic/Features.def
+++ b/clang/include/clang/Basic/Features.def
@@ -155,6 +155,7 @@ FEATURE(ptrauth_vtable_pointer_address_discrimination, LangOpts.PointerAuthVTPtr
FEATURE(ptrauth_vtable_pointer_type_discrimination, LangOpts.PointerAuthVTPtrTypeDiscrimination)
FEATURE(ptrauth_type_info_vtable_pointer_discrimination, LangOpts.PointerAuthTypeInfoVTPtrDiscrimination)
FEATURE(ptrauth_member_function_pointer_type_discrimination, LangOpts.PointerAuthCalls)
+FEATURE(ptrauth_signed_block_descriptors, LangOpts.PointerAuthBlockDescriptorPointers)
FEATURE(ptrauth_function_pointer_type_discrimination, LangOpts.PointerAuthFunctionTypeDiscrimination)
FEATURE(ptrauth_indirect_gotos, LangOpts.PointerAuthIndirectGotos)
FEATURE(ptrauth_init_fini, LangOpts.PointerAuthInitFini)
diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def
index f5a5d84eefb80..25f4575a54257 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -138,6 +138,8 @@ LANGOPT(PointerAuthObjcInterfaceSel, 1, 0, NotCompatible, "authentication of SEL
LANGOPT(PointerAuthObjcInterfaceSelKey, 16, 0, NotCompatible, "authentication key for SEL fields of ObjC interfaces")
LANGOPT(PointerAuthObjcClassROPointers, 1, 0, Benign, "class_ro_t pointer authentication")
+LANGOPT(PointerAuthBlockDescriptorPointers, 1, 0, NotCompatible, "enable signed block descriptors")
+
LANGOPT(DoubleSquareBracketAttributes, 1, 0, NotCompatible, "'[[]]' attributes extension for all language standard modes")
LANGOPT(ExperimentalLateParseAttributes, 1, 0, NotCompatible, "experimental late parsing of attributes")
diff --git a/clang/include/clang/Basic/PointerAuthOptions.h b/clang/include/clang/Basic/PointerAuthOptions.h
index fb6dddf3ae9ce..2b920250721fc 100644
--- a/clang/include/clang/Basic/PointerAuthOptions.h
+++ b/clang/include/clang/Basic/PointerAuthOptions.h
@@ -23,6 +23,10 @@
namespace clang {
+/// Constant discriminator to be used with block descriptor pointers. The value
+/// is ptrauth_string_discriminator("block_descriptor")
+constexpr uint16_t BlockDescriptorConstantDiscriminator = 0xC0BB;
+
/// Constant discriminator to be used with function pointers in .init_array and
/// .fini_array. The value is ptrauth_string_discriminator("init_fini")
constexpr uint16_t InitFiniPointerConstantDiscriminator = 0xD9D4;
@@ -223,6 +227,18 @@ struct PointerAuthOptions {
/// The ABI for function addresses in .init_array and .fini_array
PointerAuthSchema InitFiniPointers;
+ /// The ABI for block invocation function pointers.
+ PointerAuthSchema BlockInvocationFunctionPointers;
+
+ /// The ABI for block object copy/destroy function pointers.
+ PointerAuthSchema BlockHelperFunctionPointers;
+
+ /// The ABI for __block variable copy/destroy function pointers.
+ PointerAuthSchema BlockByrefHelperFunctionPointers;
+
+ /// The ABI for pointers to block descriptors.
+ PointerAuthSchema BlockDescriptorPointers;
+
/// The ABI for Objective-C method lists.
PointerAuthSchema ObjCMethodListFunctionPointers;
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 18e4ab406ce4e..958d0d05ade29 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -4527,6 +4527,7 @@ defm aarch64_jump_table_hardening: OptInCC1FFlag<"aarch64-jump-table-hardening",
defm ptrauth_objc_isa : OptInCC1FFlag<"ptrauth-objc-isa", "Enable signing and authentication of Objective-C object's 'isa' field">;
defm ptrauth_objc_interface_sel : OptInCC1FFlag<"ptrauth-objc-interface-sel", "Enable signing and authentication of Objective-C object's 'SEL' fields">;
defm ptrauth_objc_class_ro : OptInCC1FFlag<"ptrauth-objc-class-ro", "Enable signing and authentication for ObjC class_ro pointers">;
+defm ptrauth_block_descriptor_pointers : OptInCC1FFlag<"ptrauth-block-descriptor-pointers", "Enable signing and authentication of block descriptors">;
}
def fenable_matrix : Flag<["-"], "fenable-matrix">, Group<f_Group>,
diff --git a/clang/lib/CodeGen/Address.h b/clang/lib/CodeGen/Address.h
index a748ddaa110a5..4e7f3561ac049 100644
--- a/clang/lib/CodeGen/Address.h
+++ b/clang/lib/CodeGen/Address.h
@@ -176,6 +176,11 @@ class Address {
static Address invalid() { return Address(nullptr); }
bool isValid() const { return Pointer.getPointer() != nullptr; }
+ llvm::Value *getPointerIfNotSigned() const {
+ assert(isValid() && "pointer isn't valid");
+ return !isSigned() ? Pointer.getPointer() : nullptr;
+ }
+
/// This function is used in situations where the caller is doing some sort of
/// opaque "laundering" of the pointer.
void replaceBasePointer(llvm::Value *P) {
diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp
index 1aba841eb5fc2..c1f5b983f7233 100644
--- a/clang/lib/CodeGen/CGBlocks.cpp
+++ b/clang/lib/CodeGen/CGBlocks.cpp
@@ -188,13 +188,14 @@ static llvm::Constant *buildBlockDescriptor(CodeGenModule &CGM,
// Optional copy/dispose helpers.
bool hasInternalHelper = false;
if (blockInfo.NeedsCopyDispose) {
+ auto &Schema = CGM.getCodeGenOpts().PointerAuth.BlockHelperFunctionPointers;
// copy_func_helper_decl
llvm::Constant *copyHelper = buildCopyHelper(CGM, blockInfo);
- elements.add(copyHelper);
+ elements.addSignedPointer(copyHelper, Schema, GlobalDecl(), QualType());
// destroy_func_decl
llvm::Constant *disposeHelper = buildDisposeHelper(CGM, blockInfo);
- elements.add(disposeHelper);
+ elements.addSignedPointer(disposeHelper, Schema, GlobalDecl(), QualType());
if (cast<llvm::Function>(copyHelper->stripPointerCasts())
->hasInternalLinkage() ||
@@ -567,9 +568,8 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF,
llvm::StructType::get(CGM.getLLVMContext(), elementTypes, true);
info.CanBeGlobal = true;
return;
- }
- else if (C.getLangOpts().ObjC &&
- CGM.getLangOpts().getGC() == LangOptions::NonGC)
+ } else if (C.getLangOpts().ObjC &&
+ CGM.getLangOpts().getGC() == LangOptions::NonGC)
info.HasCapturedVariableLayout = true;
if (block->doesNotEscape())
@@ -783,7 +783,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) {
llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
bool IsOpenCL = CGM.getContext().getLangOpts().OpenCL;
- auto GenVoidPtrTy =
+ llvm::PointerType *GenVoidPtrTy =
IsOpenCL ? CGM.getOpenCLRuntime().getGenericVoidPointerType() : VoidPtrTy;
LangAS GenVoidPtrAddr = IsOpenCL ? LangAS::opencl_generic : LangAS::Default;
auto GenVoidPtrSize = CharUnits::fromQuantity(
@@ -817,9 +817,6 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
: CGM.getNSConcreteStackBlock();
isa = blockISA;
- // Build the block descriptor.
- descriptor = buildBlockDescriptor(CGM, blockInfo);
-
// Compute the initial on-stack block flags.
if (!CGM.getCodeGenOpts().DisableBlockSignatureString)
flags = BLOCK_HAS_SIGNATURE;
@@ -833,6 +830,9 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
flags |= BLOCK_USE_STRET;
if (blockInfo.NoEscape)
flags |= BLOCK_IS_NOESCAPE | BLOCK_IS_GLOBAL;
+
+ // Build the block descriptor.
+ descriptor = buildBlockDescriptor(CGM, blockInfo);
}
auto projectField = [&](unsigned index, const Twine &name) -> Address {
@@ -883,11 +883,25 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
llvm::ConstantInt::get(IntTy, blockInfo.BlockAlign.getQuantity()),
getIntSize(), "block.align");
}
- addHeaderField(blockFn, GenVoidPtrSize, "block.invoke");
- if (!IsOpenCL)
- addHeaderField(descriptor, getPointerSize(), "block.descriptor");
- else if (auto *Helper =
- CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) {
+
+ if (!IsOpenCL) {
+ llvm::Value *blockFnPtr =
+ llvm::ConstantExpr::getBitCast(InvokeFn, VoidPtrTy);
+ QualType type = blockInfo.getBlockExpr()
+ ->getType()
+ ->castAs<BlockPointerType>()
+ ->getPointeeType();
+ addSignedHeaderField(
+ blockFnPtr,
+ CGM.getCodeGenOpts().PointerAuth.BlockInvocationFunctionPointers,
+ GlobalDecl(), type, getPointerSize(), "block.invoke");
+
+ addSignedHeaderField(
+ descriptor, CGM.getCodeGenOpts().PointerAuth.BlockDescriptorPointers,
+ GlobalDecl(), type, getPointerSize(), "block.descriptor");
+ } else if (auto *Helper =
+ CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) {
+ addHeaderField(blockFn, GenVoidPtrSize, "block.invoke");
for (auto I : Helper->getCustomFieldValues(*this, blockInfo)) {
addHeaderField(
I.first,
@@ -895,7 +909,8 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {
CGM.getDataLayout().getTypeAllocSize(I.first->getType())),
I.second);
}
- }
+ } else
+ addHeaderField(blockFn, GenVoidPtrSize, "block.invoke");
}
// Finally, capture all the values into the block.
@@ -1166,6 +1181,8 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
ASTContext &Ctx = getContext();
CallArgList Args;
+ llvm::Value *FuncPtr = nullptr;
+
if (getLangOpts().OpenCL) {
// For OpenCL, BlockPtr is already casted to generic block literal.
@@ -1185,7 +1202,7 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
if (!isa<ParmVarDecl>(E->getCalleeDecl()))
Func = CGM.getOpenCLRuntime().getInvokeFunction(E->getCallee());
else {
- llvm::Value *FuncPtr = Builder.CreateStructGEP(GenBlockTy, BlockPtr, 2);
+ FuncPtr = Builder.CreateStructGEP(GenBlockTy, BlockPtr, 2);
Func = Builder.CreateAlignedLoad(GenericVoidPtrTy, FuncPtr,
getPointerAlign());
}
@@ -1194,7 +1211,7 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
BlockPtr =
Builder.CreatePointerCast(BlockPtr, UnqualPtrTy, "block.literal");
// Get pointer to the block invoke function
- llvm::Value *FuncPtr = Builder.CreateStructGEP(GenBlockTy, BlockPtr, 3);
+ FuncPtr = Builder.CreateStructGEP(GenBlockTy, BlockPtr, 3);
// First argument is a block literal casted to a void pointer
BlockPtr = Builder.CreatePointerCast(BlockPtr, VoidPtrTy);
@@ -1211,7 +1228,15 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr *E,
CGM.getTypes().arrangeBlockFunctionCall(Args, FuncTy);
// Prepare the callee.
- CGCallee Callee(CGCalleeInfo(), Func);
+ CGPointerAuthInfo PointerAuth;
+ if (auto &AuthSchema =
+ CGM.getCodeGenOpts().PointerAuth.BlockInvocationFunctionPointers) {
+ assert(FuncPtr != nullptr && "Missing function pointer for AuthInfo");
+ PointerAuth =
+ EmitPointerAuthInfo(AuthSchema, FuncPtr, GlobalDecl(), FnType);
+ }
+
+ CGCallee Callee(CGCalleeInfo(), Func, PointerAuth);
// And call the block.
return EmitCall(FnInfo, Callee, ReturnValue, Args, CallOrInvoke);
@@ -1295,14 +1320,15 @@ static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
bool IsOpenCL = CGM.getLangOpts().OpenCL;
bool IsWindows = CGM.getTarget().getTriple().isOSWindows();
+ auto &CGOPointerAuth = CGM.getCodeGenOpts().PointerAuth;
if (!IsOpenCL) {
// isa
if (IsWindows)
fields.addNullPointer(CGM.Int8PtrPtrTy);
else
fields.addSignedPointer(CGM.getNSConcreteGlobalBlock(),
- CGM.getCodeGenOpts().PointerAuth.ObjCIsaPointers,
- GlobalDecl(), QualType());
+ CGOPointerAuth.ObjCIsaPointers, GlobalDecl(),
+ QualType());
// __flags
BlockFlags flags = BLOCK_IS_GLOBAL;
@@ -1321,11 +1347,20 @@ static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM,
}
// Function
- fields.add(blockFn);
+ if (auto &Schema = CGOPointerAuth.BlockInvocationFunctionPointers) {
+ QualType FnType = blockInfo.getBlockExpr()
+ ->getType()
+ ->castAs<BlockPointerType>()
+ ->getPointeeType();
+ fields.addSignedPointer(blockFn, Schema, GlobalDecl(), FnType);
+ } else
+ fields.add(blockFn);
if (!IsOpenCL) {
// Descriptor
- fields.add(buildBlockDescriptor(CGM, blockInfo));
+ llvm::Constant *Descriptor = buildBlockDescriptor(CGM, blockInfo);
+ fields.addSignedPointer(Descriptor, CGOPointerAuth.BlockDescriptorPointers,
+ GlobalDecl(), QualType());
} else if (auto *Helper =
CGM.getTargetCodeGenInfo().getTargetOpenCLBlockHelper()) {
for (auto *I : Helper->getCustomFieldValues(CGM, blockInfo)) {
@@ -1995,8 +2030,8 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {
// it. It's not quite worth the annoyance to avoid creating it in the
// first place.
if (!needsEHCleanup(captureType.isDestructedType()))
- if (auto *I =
- cast_or_null<llvm::Instruction>(dstField.getBasePointer()))
+ if (auto *I = cast_or_null<llvm::Instruction>(
+ dstField.getPointerIfNotSigned()))
I->eraseFromParent();
}
break;
@@ -2730,8 +2765,16 @@ void CodeGenFunction::emitByrefStructureInit(const AutoVarEmission &emission) {
unsigned nextHeaderIndex = 0;
CharUnits nextHeaderOffset;
auto storeHeaderField = [&](llvm::Value *value, CharUnits fieldSize,
- const Twine &name) {
+ const Twine &name, bool isFunction = false) {
auto fieldAddr = Builder.CreateStructGEP(addr, nextHeaderIndex, name);
+ if (isFunction) {
+ if (auto &Schema = CGM.getCodeGenOpts()
+ .PointerAuth.BlockByrefHelperFunctionPointers) {
+ auto PointerAuth = EmitPointerAuthInfo(
+ Schema, fieldAddr.emitRawPointer(*this), GlobalDecl(), QualType());
+ value = EmitPointerAuthSign(PointerAuth, value);
+ }
+ }
Builder.CreateStore(value, fieldAddr);
nextHeaderIndex++;
@@ -2814,10 +2857,10 @@ void CodeGenFunction::emitByrefStructureInit(const AutoVarEmission &emission) {
storeHeaderField(V, getIntSize(), "byref.size");
if (helpers) {
- storeHeaderField(helpers->CopyHelper, getPointerSize(),
- "byref.copyHelper");
+ storeHeaderField(helpers->CopyHelper, getPointerSize(), "byref.copyHelper",
+ /*isFunction=*/true);
storeHeaderField(helpers->DisposeHelper, getPointerSize(),
- "byref.disposeHelper");
+ "byref.disposeHelper", /*isFunction=*/true);
}
if (ByRefHasLifetime && HasByrefExtendedLayout) {
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index bf5f427fbfbb4..62613322320cd 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -1752,7 +1752,6 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args,
options::OPT_fno_ptrauth_objc_interface_sel);
Args.addOptInFlag(CmdArgs, options::OPT_fptrauth_objc_class_ro,
options::OPT_fno_ptrauth_objc_class_ro);
-
if (Triple.getEnvironment() == llvm::Triple::PAuthTest)
handlePAuthABI(Args, CmdArgs);
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 08cf0ae6b2c24..08f3b7a7fcc49 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -1542,6 +1542,17 @@ void CompilerInvocation::setDefaultPointerAuthOptions(
Discrimination::Constant, InitFiniPointerConstantDiscriminator);
}
+ Opts.BlockInvocationFunctionPointers =
+ PointerAuthSchema(Key::ASIA, true, Discrimination::None);
+ Opts.BlockHelperFunctionPointers =
+ PointerAuthSchema(Key::ASIA, true, Discrimination::None);
+ Opts.BlockByrefHelperFunctionPointers =
+ PointerAuthSchema(Key::ASIA, true, Discrimination::None);
+ if (LangOpts.PointerAuthBlockDescriptorPointers)
+ Opts.BlockDescriptorPointers =
+ PointerAuthSchema(Key::ASDA, true, Discrimination::Constant,
+ BlockDescriptorConstantDiscriminator);
+
Opts.ObjCMethodListFunctionPointers =
PointerAuthSchema(Key::ASIA, true, Discrimination::None);
Opts.ObjCMethodListPointer =
@@ -3598,6 +3609,8 @@ static void GeneratePointerAuthArgs(const LangOptions &Opts,
GenerateArg(Consumer, OPT_fptrauth_objc_interface_sel);
if (Opts.PointerAuthObjcClassROPointers)
GenerateArg(Consumer, OPT_fptrauth_objc_class_ro);
+ if (Opts.PointerAuthBlockDescriptorPointers)
+ GenerateArg(Consumer, OPT_fptrauth_block_descriptor_pointers);
}
static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args,
@@ -3621,7 +3634,8 @@ static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args,
Opts.PointerAuthELFGOT = Args.hasArg(OPT_fptrauth_elf_got);
Opts.AArch64JumpTableHardening =
Args.hasArg(OPT_faarch64_jump_table_hardening);
-
+ Opts.PointerAuthBlockDescriptorPointers =
+ Args.hasArg(OPT_fptrauth_block_descriptor_pointers);
Opts.PointerAuthObjcIsa = Args.hasArg(OPT_fptrauth_objc_isa);
Opts.PointerAuthObjcClassROPointers = Args.hasArg(OPT_fptrauth_objc_class_ro);
Opts.PointerAuthObjcInterfaceSel =
diff --git a/clang/test/CodeGen/ptrauth-qualifier-blocks.c b/clang/test/CodeGen/ptrauth-qualifier-blocks.c
index 62da59cf327f6..f460da205cac7 100644
--- a/clang/test/CodeGen/ptrauth-qualifier-blocks.c
+++ b/clang/test/CodeGen/ptrauth-qualifier-blocks.c
@@ -82,9 +82,15 @@ void test_block_address_byref_capture() {
// CHECK: store i32 33554432,
// CHECK: store i32 48,
// CHECK: [[COPY_HELPER_FIELD:%.*]] = getelementptr inbounds nuw [[BYREF_T]], ptr [[BYREF]], i32 0, i32 4
- // CHECK: store ptr @__Block_byref_object_copy_, ptr [[COPY_HELPER_FIELD]], align
+ // CHECK: [[T0:%.*]] = ptrtoint ptr [[COPY_HELPER_FIELD]] to i64
+ // CHECK: [[T1:%.*]] = call i64 @llvm.ptrauth.sign(i64 ptrtoint (ptr @__Block_byref_object_copy_ to i64), i32 0, i64 [[T0]])
+ // CHECK: [[T2:%.*]] = inttoptr i64 [[T1]] to ptr
+ // CHECK: store ptr [[T2]], ptr [[COPY_HELPER_FIELD]], align
// CHECK: [[DISPOSE_HELPER_FIELD:%.*]] = getelementptr inbounds nuw [[BYREF_T]], ptr [[BYREF]], i32 0, i32 5
- // CHECK: store ptr @__Block_byref_object_dispose_, ptr [[DISPOSE_HELPER_FIELD]], align
+ // CHECK: [[T0:%.*]] = ptrtoint ptr [[DISPOSE_HELPER_FIELD]] to i64
+ // CHECK: [[T1:%.*]] = call i64 @llvm.ptrauth.sign(i64 ptrtoint (ptr @__Block_byref_object_dispose_ to i64), i32 0, i64 [[T0]])
+ // CHECK: [[T2:%.*]] = inttoptr i64 [[T1]] to ptr
+ // CHECK: store ptr [[T2]], ptr [[DISPOSE_HELPER_FIELD]], align
// flags - copy/dispose required
// CHECK: store i32 1107296256, ptr
__block struct A * __ptrauth(1, 1, 60) ptr = createA();
diff --git a/clang/test/CodeGenObjC/ptrauth-block-descriptor-pointer.m b/clang/test/CodeGenObjC/ptrauth-block-descriptor-pointer.m
new file mode 100644
index 0000000000000..b51670fd6459a
--- /dev/null
+++ b/clang/test/CodeGenObjC/ptrauth-block-descriptor-pointer.m
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -fobjc-arc -fblocks -fptrauth-calls -fptrauth-block-descriptor-pointers -triple arm64e-apple-ios -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -fobjc-arc -fblocks -fptrauth-calls -triple arm64e-apple-ios -DNO_BLOCK_DESC_AUTH -emit-llvm -o - %s | FileCheck %s --check-prefix=NODESCRIPTORAUTH
+
+#ifndef NO_BLOCK_DESC_AUTH
+_Static_assert(__has_feature(ptrauth_signed_block_descriptors), "-fptrauth-block-descriptor-pointers should set ptrauth_signed_block_descriptors");
+#else
+_Static_assert(!__has_feature(ptrauth_signed_block_descriptors), "-fptrauth-block-descriptor-pointers should not be enabled by default");
+#endif
+
+void a() {
+ // Test out a global block.
+ void (^blk)(void) =...
[truncated]
|
Ah, I see - the bot cherry-pick commands are not a requirement, it can be approved by a release manager manually. |
This fixes #153726 -- (multiple comments to try and see if I can get the bot infra to understand) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not opposed but this is a pretty significant amount of change for being this late in the rc cycles, and the changes haven't been upstream for very long. How risky are these changes?
@@ -155,6 +155,7 @@ FEATURE(ptrauth_vtable_pointer_address_discrimination, LangOpts.PointerAuthVTPtr | |||
FEATURE(ptrauth_vtable_pointer_type_discrimination, LangOpts.PointerAuthVTPtrTypeDiscrimination) | |||
FEATURE(ptrauth_type_info_vtable_pointer_discrimination, LangOpts.PointerAuthTypeInfoVTPtrDiscrimination) | |||
FEATURE(ptrauth_member_function_pointer_type_discrimination, LangOpts.PointerAuthCalls) | |||
FEATURE(ptrauth_signed_block_descriptors, LangOpts.PointerAuthBlockDescriptorPointers) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This follows the pattern of the other ptrauth work but none of these should have been exposed as features to begin with...
This is the upstreaming of code we've had deployed for a few years at this point, the only changes are style improvements and the brief period where we thought we could drop So I do recognize it is a much bigger change than would be ideal at this point, but it is self contained, and only actually applies to one family of platforms, which have significant amounts of deployment experience. e.g even if there is an error in it, it only impacts us, and not having it is even worse as instead of incorrect edge cases (because if there were non-edge case problems we have a number of tests that would presumably detect it) it would be a complete ABI mismatch. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm fine as a code owner with merging this to LLVM 21, and it would be nice to be feature-complete for the arm64e ABI in this release. But of course Aaron should also sign off.
ping @AaronBallman for review |
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
#153700) Pointer auth protection of the block descriptor pointer is only supported in some constrained environments so we do actually need it to be configurable. We had made it non configurable in the first PR to protect block metadata because we believed that was an option but subsequently realised it does need to remain configurable. This PR revives the flags that permit this.
7bcfe6b
to
ad7bb1c
Compare
This merges the two PRs required for correct support of blocks on arm64e
Fixes #153726