83 return Error::success();
85 llvm::Triple T(M.getTargetTriple());
89 return Error::success();
92 SmallVector<PtrAuthFixup> Fixups;
93 for (
auto &G : M.globals()) {
94 if (!G.hasInitializer())
96 SmallVector<unsigned> Indices;
97 findPtrAuth(G.getInitializer(), G, Indices, Fixups);
101 return Error::success();
104 auto &Ctx = M.getContext();
105 Type *Int32Ty = Type::getInt32Ty(Ctx);
106 Type *IntPtrTy = Type::getInt64Ty(Ctx);
108 Intrinsic::getOrInsertDeclaration(&M, Intrinsic::ptrauth_blend);
110 Intrinsic::getOrInsertDeclaration(&M, Intrinsic::ptrauth_sign);
114 Function::Create(FunctionType::get(Type::getVoidTy(Ctx),
false),
115 GlobalValue::InternalLinkage,
"ptrauth.sign", &M);
116 FixupFn->insert(FixupFn->end(), BasicBlock::Create(Ctx));
117 IRBuilder<>
B(&FixupFn->back());
119 for (
auto &Fixup : Fixups) {
120 GlobalVariable *GV = Fixup.GV;
121 ConstantPtrAuth *CPA = Fixup.CPA;
124 if (isa<ConstantPointerNull>(CPA->getPointer())) {
125 CPA->replaceAllUsesWith(CPA->getPointer());
131 if (Fixup.Indices.empty()) {
134 SmallVector<Value *> GEPIndices;
135 GEPIndices.push_back(ConstantInt::get(Int32Ty, 0));
136 for (
unsigned Idx : Fixup.Indices)
137 GEPIndices.push_back(ConstantInt::get(Int32Ty, Idx));
138 Loc =
B.CreateGEP(GV->getValueType(), GV, GEPIndices);
141 Type *PtrTy = CPA->getType();
144 Value *RawPtr =
B.CreateLoad(PtrTy, Loc);
147 Value *Disc = CPA->getDiscriminator();
148 if (CPA->hasAddressDiscriminator())
149 Disc =
B.CreateCall(BlendIntrinsic,
150 {
B.CreatePointerCast(Loc, IntPtrTy), Disc});
154 B.CreateCall(SignIntrinsic, {
B.CreatePointerCast(RawPtr, IntPtrTy),
155 CPA->getKey(), Disc});
158 B.CreateStore(
B.CreateBitOrPointerCast(SignedPtr, PtrTy), Loc);
161 CPA->replaceAllUsesWith(CPA->getPointer());
168 auto *UInt8PtrTy = PointerType::getUnqual(Ctx);
169 StructType *CtorType =
170 StructType::get(Ctx, {Int32Ty, FixupFn->getType(), UInt8PtrTy});
171 Constant *PtrFixupCtor =
172 ConstantStruct::get(CtorType, {ConstantInt::get(Int32Ty, 0), FixupFn,
173 Constant::getNullValue(UInt8PtrTy)});
175 const char *LLVMGlobalCtorsName =
"llvm.global_ctors";
176 GlobalVariable *OldCtorList = M.getNamedGlobal(LLVMGlobalCtorsName);
177 SmallVector<Constant *> CtorListArgs;
178 CtorListArgs.push_back(PtrFixupCtor);
183 if (OldCtorList->getNumUses() != 0) {
185 raw_string_ostream S(ErrStr);
186 S <<
"Global ctors variable has users, so can not be rewritten to "
187 "include pointer fixups: '"
188 << *OldCtorList <<
"'";
189 return make_error<StringError>(S.str(), inconvertibleErrorCode());
192 for (
auto &Op : OldCtorList->getInitializer()->operands())
193 CtorListArgs.push_back(cast<Constant>(Op.get()));
196 ArrayType *CtorListType = ArrayType::get(CtorType, CtorListArgs.size());
197 Constant *CtorListInit = ConstantArray::get(CtorListType, CtorListArgs);
199 GlobalVariable *NewCtorList =
new GlobalVariable(
200 M, CtorListType,
false, GlobalValue::AppendingLinkage, CtorListInit);
203 NewCtorList->takeName(OldCtorList);
204 OldCtorList->eraseFromParent();
206 NewCtorList->setName(LLVMGlobalCtorsName);
208 return Error::success();