75 if (
auto *CPA = dyn_cast<ConstantPtrAuth>(C)) {
76 Fixups.emplace_back(&GV, CPA, GEPPath, ExprPath);
79 if (isa<ConstantAggregate>(C)) {
80 for (
unsigned I = 0, E = C->getNumOperands(); I != E; ++I) {
81 if (
auto *COp = dyn_cast<Constant>(C->getOperand(I))) {
90 if (
auto *CE = dyn_cast<ConstantExpr>(C)) {
91 for (
unsigned I = 0, E = C->getNumOperands(); I != E; ++I) {
92 if (
auto *COp = dyn_cast<Constant>(C->getOperand(I))) {
93 ExprPath.push_back({CE, I});
107 return Error::success();
109 llvm::Triple T(M.getTargetTriple());
113 return Error::success();
116 SmallVector<PtrAuthFixup> Fixups;
117 for (
auto &G : M.globals()) {
118 if (!G.hasInitializer())
120 SmallVector<unsigned> GEPPath;
121 SmallVector<ExprStep> ExprPath;
122 findPtrAuth(G.getInitializer(), G, GEPPath, ExprPath, Fixups);
126 return Error::success();
129 auto &Ctx = M.getContext();
130 Type *Int32Ty = Type::getInt32Ty(Ctx);
131 Type *IntPtrTy = Type::getInt64Ty(Ctx);
133 Intrinsic::getOrInsertDeclaration(&M, Intrinsic::ptrauth_blend);
135 Intrinsic::getOrInsertDeclaration(&M, Intrinsic::ptrauth_sign);
139 Function::Create(FunctionType::get(Type::getVoidTy(Ctx),
false),
140 GlobalValue::InternalLinkage,
"ptrauth.sign", &M);
141 FixupFn->insert(FixupFn->end(), BasicBlock::Create(Ctx));
142 IRBuilder<>
B(&FixupFn->back());
144 for (
auto &Fixup : Fixups) {
145 GlobalVariable *GV = Fixup.GV;
146 ConstantPtrAuth *CPA = Fixup.CPA;
149 if (isa<ConstantPointerNull>(CPA->getPointer())) {
150 CPA->replaceAllUsesWith(CPA->getPointer());
157 if (Fixup.GEPPath.empty()) {
160 SmallVector<Value *> GEPValues;
161 GEPValues.push_back(ConstantInt::get(Int32Ty, 0));
162 for (
unsigned Idx : Fixup.GEPPath)
163 GEPValues.push_back(ConstantInt::get(Int32Ty, Idx));
164 Loc =
B.CreateGEP(GV->getValueType(), GV, GEPValues);
167 Type *PtrTy = CPA->getType();
170 Value *Disc = CPA->getDiscriminator();
171 if (CPA->hasAddressDiscriminator())
172 Disc =
B.CreateCall(BlendIntrinsic,
173 {
B.CreatePointerCast(Loc, IntPtrTy), Disc});
175 if (!Fixup.ExprPath.empty()) {
178 Value *SignedPtr =
B.CreateCall(
179 SignIntrinsic, {
B.CreatePointerCast(CPA->getPointer(), IntPtrTy),
180 CPA->getKey(), Disc});
181 Value *Result =
B.CreateIntToPtr(SignedPtr, PtrTy);
183 for (
auto &
Step : llvm::reverse(Fixup.ExprPath)) {
185 I->setOperand(
Step.OperandIdx, Result);
189 B.CreateStore(Result, Loc);
192 Value *RawPtr =
B.CreateLoad(PtrTy, Loc);
194 B.CreateCall(SignIntrinsic, {
B.CreatePointerCast(RawPtr, IntPtrTy),
195 CPA->getKey(), Disc});
196 B.CreateStore(
B.CreateBitOrPointerCast(SignedPtr, PtrTy), Loc);
199 CPA->replaceAllUsesWith(CPA->getPointer());
206 auto *UInt8PtrTy = PointerType::getUnqual(Ctx);
207 StructType *CtorType =
208 StructType::get(Ctx, {Int32Ty, FixupFn->getType(), UInt8PtrTy});
209 Constant *PtrFixupCtor =
210 ConstantStruct::get(CtorType, {ConstantInt::get(Int32Ty, 0), FixupFn,
211 Constant::getNullValue(UInt8PtrTy)});
213 const char *LLVMGlobalCtorsName =
"llvm.global_ctors";
214 GlobalVariable *OldCtorList = M.getNamedGlobal(LLVMGlobalCtorsName);
215 SmallVector<Constant *> CtorListArgs;
216 CtorListArgs.push_back(PtrFixupCtor);
221 if (OldCtorList->getNumUses() != 0) {
223 raw_string_ostream S(ErrStr);
224 S <<
"Global ctors variable has users, so can not be rewritten to "
225 "include pointer fixups: '"
226 << *OldCtorList <<
"'";
227 return make_error<StringError>(S.str(), inconvertibleErrorCode());
230 for (
auto &Op : OldCtorList->getInitializer()->operands())
231 CtorListArgs.push_back(cast<Constant>(Op.get()));
234 ArrayType *CtorListType = ArrayType::get(CtorType, CtorListArgs.size());
235 Constant *CtorListInit = ConstantArray::get(CtorListType, CtorListArgs);
237 GlobalVariable *NewCtorList =
new GlobalVariable(
238 M, CtorListType,
false, GlobalValue::AppendingLinkage, CtorListInit);
241 NewCtorList->takeName(OldCtorList);
242 OldCtorList->eraseFromParent();
244 NewCtorList->setName(LLVMGlobalCtorsName);
246 return Error::success();