diff options
author | Daniil Kovalev <dkovalev@accesssoftek.com> | 2024-08-06 08:02:13 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-08-06 08:02:13 +0300 |
commit | 6e45fa95be9db5318ac7037c673c9b18a48ac5b1 (patch) | |
tree | ccd9345d2ec3e0bc661084df846522f7118ee5c2 /clang/lib/CodeGen/CodeGenModule.cpp | |
parent | 1745c8e08dde9f32d0f0b701d3a6a271697458eb (diff) | |
download | llvm-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.cpp | 67 |
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(); } |