aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CodeGenModule.cpp
diff options
context:
space:
mode:
authorDaniil Kovalev <dkovalev@accesssoftek.com>2024-08-06 08:02:13 +0300
committerGitHub <noreply@github.com>2024-08-06 08:02:13 +0300
commit6e45fa95be9db5318ac7037c673c9b18a48ac5b1 (patch)
treeccd9345d2ec3e0bc661084df846522f7118ee5c2 /clang/lib/CodeGen/CodeGenModule.cpp
parent1745c8e08dde9f32d0f0b701d3a6a271697458eb (diff)
downloadllvm-6e45fa95be9db5318ac7037c673c9b18a48ac5b1.zip
llvm-6e45fa95be9db5318ac7037c673c9b18a48ac5b1.tar.gz
llvm-6e45fa95be9db5318ac7037c673c9b18a48ac5b1.tar.bz2
[PAC][AArch64] Support init/fini array signing (#96478)
If both `-fptrauth-init-fini` and `-fptrauth-calls` are passed, sign function pointers in `llvm.global_ctors` and `llvm.global_dtors` with constant discriminator 0xD9D4 (`ptrauth_string_discriminator("init_fini")`). Additionally, if `-fptrauth-init-fini-address-discrimination` is passed, address discrimination is used for signing (otherwise, just constant discriminator is used). For address discrimination, we use it's special form since uses of `llvm.global_{c|d}tors` are disallowed (see `Verifier::visitGlobalVariable`) and we can't emit `getelementptr` expressions referencing these special arrays. A signed ctor/dtor pointer with special address discrimination applied looks like the following: ``` ptr ptrauth (ptr @foo, i32 0, i64 55764, ptr inttoptr (i64 1 to ptr)) ```
Diffstat (limited to 'clang/lib/CodeGen/CodeGenModule.cpp')
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp67
1 files changed, 43 insertions, 24 deletions
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 31f6632..1f2cbee 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -1218,10 +1218,13 @@ void CodeGenModule::Release() {
(LangOpts.PointerAuthVTPtrTypeDiscrimination
<< AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_VPTRTYPEDISCR) |
(LangOpts.PointerAuthInitFini
- << AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_INITFINI);
- static_assert(AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_INITFINI ==
- AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_LAST,
- "Update when new enum items are defined");
+ << AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_INITFINI) |
+ (LangOpts.PointerAuthInitFiniAddressDiscrimination
+ << AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_INITFINIADDRDISC);
+ static_assert(
+ AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_INITFINIADDRDISC ==
+ AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_LAST,
+ "Update when new enum items are defined");
if (PAuthABIVersion != 0) {
getModule().addModuleFlag(llvm::Module::Error,
"aarch64-elf-pauthabi-platform",
@@ -2082,37 +2085,53 @@ void CodeGenModule::AddGlobalDtor(llvm::Function *Dtor, int Priority,
void CodeGenModule::EmitCtorList(CtorList &Fns, const char *GlobalName) {
if (Fns.empty()) return;
- // Ctor function type is void()*.
- llvm::FunctionType* CtorFTy = llvm::FunctionType::get(VoidTy, false);
- llvm::Type *CtorPFTy = llvm::PointerType::get(CtorFTy,
- TheModule.getDataLayout().getProgramAddressSpace());
+ const PointerAuthSchema &InitFiniAuthSchema =
+ getCodeGenOpts().PointerAuth.InitFiniPointers;
- // Get the type of a ctor entry, { i32, void ()*, i8* }.
- llvm::StructType *CtorStructTy = llvm::StructType::get(
- Int32Ty, CtorPFTy, VoidPtrTy);
+ // Ctor function type is ptr.
+ llvm::PointerType *PtrTy = llvm::PointerType::get(
+ getLLVMContext(), TheModule.getDataLayout().getProgramAddressSpace());
+
+ // Get the type of a ctor entry, { i32, ptr, ptr }.
+ llvm::StructType *CtorStructTy = llvm::StructType::get(Int32Ty, PtrTy, PtrTy);
// Construct the constructor and destructor arrays.
- ConstantInitBuilder builder(*this);
- auto ctors = builder.beginArray(CtorStructTy);
+ ConstantInitBuilder Builder(*this);
+ auto Ctors = Builder.beginArray(CtorStructTy);
for (const auto &I : Fns) {
- auto ctor = ctors.beginStruct(CtorStructTy);
- ctor.addInt(Int32Ty, I.Priority);
- ctor.add(I.Initializer);
+ auto Ctor = Ctors.beginStruct(CtorStructTy);
+ Ctor.addInt(Int32Ty, I.Priority);
+ if (InitFiniAuthSchema) {
+ llvm::Constant *StorageAddress =
+ (InitFiniAuthSchema.isAddressDiscriminated()
+ ? llvm::ConstantExpr::getIntToPtr(
+ llvm::ConstantInt::get(
+ IntPtrTy,
+ llvm::ConstantPtrAuth::AddrDiscriminator_CtorsDtors),
+ PtrTy)
+ : nullptr);
+ llvm::Constant *SignedCtorPtr = getConstantSignedPointer(
+ I.Initializer, InitFiniAuthSchema.getKey(), StorageAddress,
+ llvm::ConstantInt::get(
+ SizeTy, InitFiniAuthSchema.getConstantDiscrimination()));
+ Ctor.add(SignedCtorPtr);
+ } else {
+ Ctor.add(I.Initializer);
+ }
if (I.AssociatedData)
- ctor.add(I.AssociatedData);
+ Ctor.add(I.AssociatedData);
else
- ctor.addNullPointer(VoidPtrTy);
- ctor.finishAndAddTo(ctors);
+ Ctor.addNullPointer(PtrTy);
+ Ctor.finishAndAddTo(Ctors);
}
- auto list =
- ctors.finishAndCreateGlobal(GlobalName, getPointerAlign(),
- /*constant*/ false,
- llvm::GlobalValue::AppendingLinkage);
+ auto List = Ctors.finishAndCreateGlobal(GlobalName, getPointerAlign(),
+ /*constant*/ false,
+ llvm::GlobalValue::AppendingLinkage);
// The LTO linker doesn't seem to like it when we set an alignment
// on appending variables. Take it off as a workaround.
- list->setAlignment(std::nullopt);
+ List->setAlignment(std::nullopt);
Fns.clear();
}