10b57cec5SDimitry Andric //===-- ModuleUtils.cpp - Functions to manipulate Modules -----------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This family of functions perform manipulations on Modules. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "llvm/Transforms/Utils/ModuleUtils.h" 14480093f4SDimitry Andric #include "llvm/Analysis/VectorUtils.h" 1506c3fb27SDimitry Andric #include "llvm/ADT/SmallString.h" 160b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h" 170b57cec5SDimitry Andric #include "llvm/IR/Function.h" 180b57cec5SDimitry Andric #include "llvm/IR/IRBuilder.h" 19bdd1243dSDimitry Andric #include "llvm/IR/MDBuilder.h" 200b57cec5SDimitry Andric #include "llvm/IR/Module.h" 210fca6ea1SDimitry Andric #include "llvm/Support/MD5.h" 220b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 23bdd1243dSDimitry Andric #include "llvm/Support/xxhash.h" 2406c3fb27SDimitry Andric 250b57cec5SDimitry Andric using namespace llvm; 260b57cec5SDimitry Andric 275ffd83dbSDimitry Andric #define DEBUG_TYPE "moduleutils" 285ffd83dbSDimitry Andric 29bdd1243dSDimitry Andric static void appendToGlobalArray(StringRef ArrayName, Module &M, Function *F, 300b57cec5SDimitry Andric int Priority, Constant *Data) { 310b57cec5SDimitry Andric IRBuilder<> IRB(M.getContext()); 320b57cec5SDimitry Andric FunctionType *FnTy = FunctionType::get(IRB.getVoidTy(), false); 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric // Get the current set of static global constructors and add the new ctor 350b57cec5SDimitry Andric // to the list. 360b57cec5SDimitry Andric SmallVector<Constant *, 16> CurrentCtors; 3706c3fb27SDimitry Andric StructType *EltTy; 38bdd1243dSDimitry Andric if (GlobalVariable *GVCtor = M.getNamedGlobal(ArrayName)) { 3906c3fb27SDimitry Andric EltTy = cast<StructType>(GVCtor->getValueType()->getArrayElementType()); 400b57cec5SDimitry Andric if (Constant *Init = GVCtor->getInitializer()) { 410b57cec5SDimitry Andric unsigned n = Init->getNumOperands(); 420b57cec5SDimitry Andric CurrentCtors.reserve(n + 1); 430b57cec5SDimitry Andric for (unsigned i = 0; i != n; ++i) 440b57cec5SDimitry Andric CurrentCtors.push_back(cast<Constant>(Init->getOperand(i))); 450b57cec5SDimitry Andric } 460b57cec5SDimitry Andric GVCtor->eraseFromParent(); 4706c3fb27SDimitry Andric } else { 485f757f3fSDimitry Andric EltTy = StructType::get(IRB.getInt32Ty(), 495f757f3fSDimitry Andric PointerType::get(FnTy, F->getAddressSpace()), 505f757f3fSDimitry Andric IRB.getPtrTy()); 510b57cec5SDimitry Andric } 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric // Build a 3 field global_ctor entry. We don't take a comdat key. 540b57cec5SDimitry Andric Constant *CSVals[3]; 550b57cec5SDimitry Andric CSVals[0] = IRB.getInt32(Priority); 560b57cec5SDimitry Andric CSVals[1] = F; 575f757f3fSDimitry Andric CSVals[2] = Data ? ConstantExpr::getPointerCast(Data, IRB.getPtrTy()) 585f757f3fSDimitry Andric : Constant::getNullValue(IRB.getPtrTy()); 590b57cec5SDimitry Andric Constant *RuntimeCtorInit = 60bdd1243dSDimitry Andric ConstantStruct::get(EltTy, ArrayRef(CSVals, EltTy->getNumElements())); 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric CurrentCtors.push_back(RuntimeCtorInit); 630b57cec5SDimitry Andric 640b57cec5SDimitry Andric // Create a new initializer. 650b57cec5SDimitry Andric ArrayType *AT = ArrayType::get(EltTy, CurrentCtors.size()); 660b57cec5SDimitry Andric Constant *NewInit = ConstantArray::get(AT, CurrentCtors); 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric // Create the new global variable and replace all uses of 690b57cec5SDimitry Andric // the old global variable with the new one. 700b57cec5SDimitry Andric (void)new GlobalVariable(M, NewInit->getType(), false, 71bdd1243dSDimitry Andric GlobalValue::AppendingLinkage, NewInit, ArrayName); 720b57cec5SDimitry Andric } 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric void llvm::appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data) { 750b57cec5SDimitry Andric appendToGlobalArray("llvm.global_ctors", M, F, Priority, Data); 760b57cec5SDimitry Andric } 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric void llvm::appendToGlobalDtors(Module &M, Function *F, int Priority, Constant *Data) { 790b57cec5SDimitry Andric appendToGlobalArray("llvm.global_dtors", M, F, Priority, Data); 800b57cec5SDimitry Andric } 810b57cec5SDimitry Andric 82bdd1243dSDimitry Andric static void collectUsedGlobals(GlobalVariable *GV, 83bdd1243dSDimitry Andric SmallSetVector<Constant *, 16> &Init) { 84bdd1243dSDimitry Andric if (!GV || !GV->hasInitializer()) 85bdd1243dSDimitry Andric return; 86bdd1243dSDimitry Andric 878bcb0991SDimitry Andric auto *CA = cast<ConstantArray>(GV->getInitializer()); 88bdd1243dSDimitry Andric for (Use &Op : CA->operands()) 89bdd1243dSDimitry Andric Init.insert(cast<Constant>(Op)); 900b57cec5SDimitry Andric } 910b57cec5SDimitry Andric 92bdd1243dSDimitry Andric static void appendToUsedList(Module &M, StringRef Name, ArrayRef<GlobalValue *> Values) { 93bdd1243dSDimitry Andric GlobalVariable *GV = M.getGlobalVariable(Name); 94bdd1243dSDimitry Andric 95bdd1243dSDimitry Andric SmallSetVector<Constant *, 16> Init; 96bdd1243dSDimitry Andric collectUsedGlobals(GV, Init); 97bdd1243dSDimitry Andric if (GV) 98bdd1243dSDimitry Andric GV->eraseFromParent(); 99bdd1243dSDimitry Andric 1005f757f3fSDimitry Andric Type *ArrayEltTy = llvm::PointerType::getUnqual(M.getContext()); 101bdd1243dSDimitry Andric for (auto *V : Values) 102bdd1243dSDimitry Andric Init.insert(ConstantExpr::getPointerBitCastOrAddrSpaceCast(V, ArrayEltTy)); 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric if (Init.empty()) 1050b57cec5SDimitry Andric return; 1060b57cec5SDimitry Andric 107bdd1243dSDimitry Andric ArrayType *ATy = ArrayType::get(ArrayEltTy, Init.size()); 1080b57cec5SDimitry Andric GV = new llvm::GlobalVariable(M, ATy, false, GlobalValue::AppendingLinkage, 109bdd1243dSDimitry Andric ConstantArray::get(ATy, Init.getArrayRef()), 110bdd1243dSDimitry Andric Name); 1110b57cec5SDimitry Andric GV->setSection("llvm.metadata"); 1120b57cec5SDimitry Andric } 1130b57cec5SDimitry Andric 1140b57cec5SDimitry Andric void llvm::appendToUsed(Module &M, ArrayRef<GlobalValue *> Values) { 1150b57cec5SDimitry Andric appendToUsedList(M, "llvm.used", Values); 1160b57cec5SDimitry Andric } 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric void llvm::appendToCompilerUsed(Module &M, ArrayRef<GlobalValue *> Values) { 1190b57cec5SDimitry Andric appendToUsedList(M, "llvm.compiler.used", Values); 1200b57cec5SDimitry Andric } 1210b57cec5SDimitry Andric 122bdd1243dSDimitry Andric static void removeFromUsedList(Module &M, StringRef Name, 123bdd1243dSDimitry Andric function_ref<bool(Constant *)> ShouldRemove) { 124bdd1243dSDimitry Andric GlobalVariable *GV = M.getNamedGlobal(Name); 125bdd1243dSDimitry Andric if (!GV) 126bdd1243dSDimitry Andric return; 127bdd1243dSDimitry Andric 128bdd1243dSDimitry Andric SmallSetVector<Constant *, 16> Init; 129bdd1243dSDimitry Andric collectUsedGlobals(GV, Init); 130bdd1243dSDimitry Andric 131bdd1243dSDimitry Andric Type *ArrayEltTy = cast<ArrayType>(GV->getValueType())->getElementType(); 132bdd1243dSDimitry Andric 133bdd1243dSDimitry Andric SmallVector<Constant *, 16> NewInit; 134bdd1243dSDimitry Andric for (Constant *MaybeRemoved : Init) { 135bdd1243dSDimitry Andric if (!ShouldRemove(MaybeRemoved->stripPointerCasts())) 136bdd1243dSDimitry Andric NewInit.push_back(MaybeRemoved); 137bdd1243dSDimitry Andric } 138bdd1243dSDimitry Andric 139bdd1243dSDimitry Andric if (!NewInit.empty()) { 140bdd1243dSDimitry Andric ArrayType *ATy = ArrayType::get(ArrayEltTy, NewInit.size()); 141bdd1243dSDimitry Andric GlobalVariable *NewGV = 142bdd1243dSDimitry Andric new GlobalVariable(M, ATy, false, GlobalValue::AppendingLinkage, 143bdd1243dSDimitry Andric ConstantArray::get(ATy, NewInit), "", GV, 144bdd1243dSDimitry Andric GV->getThreadLocalMode(), GV->getAddressSpace()); 145bdd1243dSDimitry Andric NewGV->setSection(GV->getSection()); 146bdd1243dSDimitry Andric NewGV->takeName(GV); 147bdd1243dSDimitry Andric } 148bdd1243dSDimitry Andric 149bdd1243dSDimitry Andric GV->eraseFromParent(); 150bdd1243dSDimitry Andric } 151bdd1243dSDimitry Andric 152bdd1243dSDimitry Andric void llvm::removeFromUsedLists(Module &M, 153bdd1243dSDimitry Andric function_ref<bool(Constant *)> ShouldRemove) { 154bdd1243dSDimitry Andric removeFromUsedList(M, "llvm.used", ShouldRemove); 155bdd1243dSDimitry Andric removeFromUsedList(M, "llvm.compiler.used", ShouldRemove); 156bdd1243dSDimitry Andric } 157bdd1243dSDimitry Andric 158bdd1243dSDimitry Andric void llvm::setKCFIType(Module &M, Function &F, StringRef MangledType) { 159bdd1243dSDimitry Andric if (!M.getModuleFlag("kcfi")) 160bdd1243dSDimitry Andric return; 161bdd1243dSDimitry Andric // Matches CodeGenModule::CreateKCFITypeId in Clang. 162bdd1243dSDimitry Andric LLVMContext &Ctx = M.getContext(); 163bdd1243dSDimitry Andric MDBuilder MDB(Ctx); 164*d686ce93SDimitry Andric std::string Type = MangledType.str(); 165*d686ce93SDimitry Andric if (M.getModuleFlag("cfi-normalize-integers")) 166*d686ce93SDimitry Andric Type += ".normalized"; 167*d686ce93SDimitry Andric F.setMetadata(LLVMContext::MD_kcfi_type, 168bdd1243dSDimitry Andric MDNode::get(Ctx, MDB.createConstant(ConstantInt::get( 169bdd1243dSDimitry Andric Type::getInt32Ty(Ctx), 170*d686ce93SDimitry Andric static_cast<uint32_t>(xxHash64(Type)))))); 171bdd1243dSDimitry Andric // If the module was compiled with -fpatchable-function-entry, ensure 172bdd1243dSDimitry Andric // we use the same patchable-function-prefix. 173bdd1243dSDimitry Andric if (auto *MD = mdconst::extract_or_null<ConstantInt>( 174bdd1243dSDimitry Andric M.getModuleFlag("kcfi-offset"))) { 175bdd1243dSDimitry Andric if (unsigned Offset = MD->getZExtValue()) 176bdd1243dSDimitry Andric F.addFnAttr("patchable-function-prefix", std::to_string(Offset)); 177bdd1243dSDimitry Andric } 178bdd1243dSDimitry Andric } 179bdd1243dSDimitry Andric 180bdd1243dSDimitry Andric FunctionCallee llvm::declareSanitizerInitFunction(Module &M, StringRef InitName, 181bdd1243dSDimitry Andric ArrayRef<Type *> InitArgTypes, 182bdd1243dSDimitry Andric bool Weak) { 1830b57cec5SDimitry Andric assert(!InitName.empty() && "Expected init function name"); 184bdd1243dSDimitry Andric auto *VoidTy = Type::getVoidTy(M.getContext()); 185bdd1243dSDimitry Andric auto *FnTy = FunctionType::get(VoidTy, InitArgTypes, false); 186bdd1243dSDimitry Andric auto FnCallee = M.getOrInsertFunction(InitName, FnTy); 187bdd1243dSDimitry Andric auto *Fn = cast<Function>(FnCallee.getCallee()); 188bdd1243dSDimitry Andric if (Weak && Fn->isDeclaration()) 189bdd1243dSDimitry Andric Fn->setLinkage(Function::ExternalWeakLinkage); 190bdd1243dSDimitry Andric return FnCallee; 1910b57cec5SDimitry Andric } 1920b57cec5SDimitry Andric 1935ffd83dbSDimitry Andric Function *llvm::createSanitizerCtor(Module &M, StringRef CtorName) { 194fe6060f1SDimitry Andric Function *Ctor = Function::createWithDefaultAttr( 1955ffd83dbSDimitry Andric FunctionType::get(Type::getVoidTy(M.getContext()), false), 196bdd1243dSDimitry Andric GlobalValue::InternalLinkage, M.getDataLayout().getProgramAddressSpace(), 197bdd1243dSDimitry Andric CtorName, &M); 198349cc55cSDimitry Andric Ctor->addFnAttr(Attribute::NoUnwind); 199bdd1243dSDimitry Andric setKCFIType(M, *Ctor, "_ZTSFvvE"); // void (*)(void) 2005ffd83dbSDimitry Andric BasicBlock *CtorBB = BasicBlock::Create(M.getContext(), "", Ctor); 2015ffd83dbSDimitry Andric ReturnInst::Create(M.getContext(), CtorBB); 202fe6060f1SDimitry Andric // Ensure Ctor cannot be discarded, even if in a comdat. 203fe6060f1SDimitry Andric appendToUsed(M, {Ctor}); 2045ffd83dbSDimitry Andric return Ctor; 2055ffd83dbSDimitry Andric } 2065ffd83dbSDimitry Andric 2070b57cec5SDimitry Andric std::pair<Function *, FunctionCallee> llvm::createSanitizerCtorAndInitFunctions( 2080b57cec5SDimitry Andric Module &M, StringRef CtorName, StringRef InitName, 2090b57cec5SDimitry Andric ArrayRef<Type *> InitArgTypes, ArrayRef<Value *> InitArgs, 210bdd1243dSDimitry Andric StringRef VersionCheckName, bool Weak) { 2110b57cec5SDimitry Andric assert(!InitName.empty() && "Expected init function name"); 2120b57cec5SDimitry Andric assert(InitArgs.size() == InitArgTypes.size() && 2130b57cec5SDimitry Andric "Sanitizer's init function expects different number of arguments"); 2140b57cec5SDimitry Andric FunctionCallee InitFunction = 215bdd1243dSDimitry Andric declareSanitizerInitFunction(M, InitName, InitArgTypes, Weak); 2165ffd83dbSDimitry Andric Function *Ctor = createSanitizerCtor(M, CtorName); 217bdd1243dSDimitry Andric IRBuilder<> IRB(M.getContext()); 218bdd1243dSDimitry Andric 219bdd1243dSDimitry Andric BasicBlock *RetBB = &Ctor->getEntryBlock(); 220bdd1243dSDimitry Andric if (Weak) { 221bdd1243dSDimitry Andric RetBB->setName("ret"); 222bdd1243dSDimitry Andric auto *EntryBB = BasicBlock::Create(M.getContext(), "entry", Ctor, RetBB); 223bdd1243dSDimitry Andric auto *CallInitBB = 224bdd1243dSDimitry Andric BasicBlock::Create(M.getContext(), "callfunc", Ctor, RetBB); 225bdd1243dSDimitry Andric auto *InitFn = cast<Function>(InitFunction.getCallee()); 226bdd1243dSDimitry Andric auto *InitFnPtr = 227bdd1243dSDimitry Andric PointerType::get(InitFn->getType(), InitFn->getAddressSpace()); 228bdd1243dSDimitry Andric IRB.SetInsertPoint(EntryBB); 229bdd1243dSDimitry Andric Value *InitNotNull = 230bdd1243dSDimitry Andric IRB.CreateICmpNE(InitFn, ConstantPointerNull::get(InitFnPtr)); 231bdd1243dSDimitry Andric IRB.CreateCondBr(InitNotNull, CallInitBB, RetBB); 232bdd1243dSDimitry Andric IRB.SetInsertPoint(CallInitBB); 233bdd1243dSDimitry Andric } else { 234bdd1243dSDimitry Andric IRB.SetInsertPoint(RetBB->getTerminator()); 235bdd1243dSDimitry Andric } 236bdd1243dSDimitry Andric 2370b57cec5SDimitry Andric IRB.CreateCall(InitFunction, InitArgs); 2380b57cec5SDimitry Andric if (!VersionCheckName.empty()) { 2390b57cec5SDimitry Andric FunctionCallee VersionCheckFunction = M.getOrInsertFunction( 2400b57cec5SDimitry Andric VersionCheckName, FunctionType::get(IRB.getVoidTy(), {}, false), 2410b57cec5SDimitry Andric AttributeList()); 2420b57cec5SDimitry Andric IRB.CreateCall(VersionCheckFunction, {}); 2430b57cec5SDimitry Andric } 244bdd1243dSDimitry Andric 245bdd1243dSDimitry Andric if (Weak) 246bdd1243dSDimitry Andric IRB.CreateBr(RetBB); 247bdd1243dSDimitry Andric 2480b57cec5SDimitry Andric return std::make_pair(Ctor, InitFunction); 2490b57cec5SDimitry Andric } 2500b57cec5SDimitry Andric 2510b57cec5SDimitry Andric std::pair<Function *, FunctionCallee> 2520b57cec5SDimitry Andric llvm::getOrCreateSanitizerCtorAndInitFunctions( 2530b57cec5SDimitry Andric Module &M, StringRef CtorName, StringRef InitName, 2540b57cec5SDimitry Andric ArrayRef<Type *> InitArgTypes, ArrayRef<Value *> InitArgs, 2550b57cec5SDimitry Andric function_ref<void(Function *, FunctionCallee)> FunctionsCreatedCallback, 256bdd1243dSDimitry Andric StringRef VersionCheckName, bool Weak) { 2570b57cec5SDimitry Andric assert(!CtorName.empty() && "Expected ctor function name"); 2580b57cec5SDimitry Andric 2590b57cec5SDimitry Andric if (Function *Ctor = M.getFunction(CtorName)) 2600b57cec5SDimitry Andric // FIXME: Sink this logic into the module, similar to the handling of 2610b57cec5SDimitry Andric // globals. This will make moving to a concurrent model much easier. 262349cc55cSDimitry Andric if (Ctor->arg_empty() || 2630b57cec5SDimitry Andric Ctor->getReturnType() == Type::getVoidTy(M.getContext())) 264bdd1243dSDimitry Andric return {Ctor, 265bdd1243dSDimitry Andric declareSanitizerInitFunction(M, InitName, InitArgTypes, Weak)}; 2660b57cec5SDimitry Andric 2670b57cec5SDimitry Andric Function *Ctor; 2680b57cec5SDimitry Andric FunctionCallee InitFunction; 2690b57cec5SDimitry Andric std::tie(Ctor, InitFunction) = llvm::createSanitizerCtorAndInitFunctions( 270bdd1243dSDimitry Andric M, CtorName, InitName, InitArgTypes, InitArgs, VersionCheckName, Weak); 2710b57cec5SDimitry Andric FunctionsCreatedCallback(Ctor, InitFunction); 2720b57cec5SDimitry Andric return std::make_pair(Ctor, InitFunction); 2730b57cec5SDimitry Andric } 2740b57cec5SDimitry Andric 2750b57cec5SDimitry Andric void llvm::filterDeadComdatFunctions( 27604eeddc0SDimitry Andric SmallVectorImpl<Function *> &DeadComdatFunctions) { 27704eeddc0SDimitry Andric SmallPtrSet<Function *, 32> MaybeDeadFunctions; 27804eeddc0SDimitry Andric SmallPtrSet<Comdat *, 32> MaybeDeadComdats; 2790b57cec5SDimitry Andric for (Function *F : DeadComdatFunctions) { 28004eeddc0SDimitry Andric MaybeDeadFunctions.insert(F); 28104eeddc0SDimitry Andric if (Comdat *C = F->getComdat()) 28204eeddc0SDimitry Andric MaybeDeadComdats.insert(C); 28304eeddc0SDimitry Andric } 28404eeddc0SDimitry Andric 28504eeddc0SDimitry Andric // Find comdats for which all users are dead now. 28604eeddc0SDimitry Andric SmallPtrSet<Comdat *, 32> DeadComdats; 28704eeddc0SDimitry Andric for (Comdat *C : MaybeDeadComdats) { 28804eeddc0SDimitry Andric auto IsUserDead = [&](GlobalObject *GO) { 28904eeddc0SDimitry Andric auto *F = dyn_cast<Function>(GO); 29004eeddc0SDimitry Andric return F && MaybeDeadFunctions.contains(F); 29104eeddc0SDimitry Andric }; 29204eeddc0SDimitry Andric if (all_of(C->getUsers(), IsUserDead)) 29304eeddc0SDimitry Andric DeadComdats.insert(C); 29404eeddc0SDimitry Andric } 29504eeddc0SDimitry Andric 29604eeddc0SDimitry Andric // Only keep functions which have no comdat or a dead comdat. 29704eeddc0SDimitry Andric erase_if(DeadComdatFunctions, [&](Function *F) { 2980b57cec5SDimitry Andric Comdat *C = F->getComdat(); 29904eeddc0SDimitry Andric return C && !DeadComdats.contains(C); 3000b57cec5SDimitry Andric }); 3010b57cec5SDimitry Andric } 3020b57cec5SDimitry Andric 3030b57cec5SDimitry Andric std::string llvm::getUniqueModuleId(Module *M) { 3040b57cec5SDimitry Andric MD5 Md5; 3050b57cec5SDimitry Andric bool ExportsSymbols = false; 3060b57cec5SDimitry Andric auto AddGlobal = [&](GlobalValue &GV) { 3075f757f3fSDimitry Andric if (GV.isDeclaration() || GV.getName().starts_with("llvm.") || 3080b57cec5SDimitry Andric !GV.hasExternalLinkage() || GV.hasComdat()) 3090b57cec5SDimitry Andric return; 3100b57cec5SDimitry Andric ExportsSymbols = true; 3110b57cec5SDimitry Andric Md5.update(GV.getName()); 3120b57cec5SDimitry Andric Md5.update(ArrayRef<uint8_t>{0}); 3130b57cec5SDimitry Andric }; 3140b57cec5SDimitry Andric 3150b57cec5SDimitry Andric for (auto &F : *M) 3160b57cec5SDimitry Andric AddGlobal(F); 3170b57cec5SDimitry Andric for (auto &GV : M->globals()) 3180b57cec5SDimitry Andric AddGlobal(GV); 3190b57cec5SDimitry Andric for (auto &GA : M->aliases()) 3200b57cec5SDimitry Andric AddGlobal(GA); 3210b57cec5SDimitry Andric for (auto &IF : M->ifuncs()) 3220b57cec5SDimitry Andric AddGlobal(IF); 3230b57cec5SDimitry Andric 3240b57cec5SDimitry Andric if (!ExportsSymbols) 3250b57cec5SDimitry Andric return ""; 3260b57cec5SDimitry Andric 3270b57cec5SDimitry Andric MD5::MD5Result R; 3280b57cec5SDimitry Andric Md5.final(R); 3290b57cec5SDimitry Andric 3300b57cec5SDimitry Andric SmallString<32> Str; 3310b57cec5SDimitry Andric MD5::stringifyResult(R, Str); 332fe6060f1SDimitry Andric return ("." + Str).str(); 3330b57cec5SDimitry Andric } 334480093f4SDimitry Andric 3351fd87a68SDimitry Andric void llvm::embedBufferInModule(Module &M, MemoryBufferRef Buf, 33681ad6265SDimitry Andric StringRef SectionName, Align Alignment) { 33781ad6265SDimitry Andric // Embed the memory buffer into the module. 3381fd87a68SDimitry Andric Constant *ModuleConstant = ConstantDataArray::get( 339bdd1243dSDimitry Andric M.getContext(), ArrayRef(Buf.getBufferStart(), Buf.getBufferSize())); 3401fd87a68SDimitry Andric GlobalVariable *GV = new GlobalVariable( 3411fd87a68SDimitry Andric M, ModuleConstant->getType(), true, GlobalValue::PrivateLinkage, 3421fd87a68SDimitry Andric ModuleConstant, "llvm.embedded.object"); 3431fd87a68SDimitry Andric GV->setSection(SectionName); 34481ad6265SDimitry Andric GV->setAlignment(Alignment); 3451fd87a68SDimitry Andric 346753f127fSDimitry Andric LLVMContext &Ctx = M.getContext(); 347753f127fSDimitry Andric NamedMDNode *MD = M.getOrInsertNamedMetadata("llvm.embedded.objects"); 348753f127fSDimitry Andric Metadata *MDVals[] = {ConstantAsMetadata::get(GV), 349753f127fSDimitry Andric MDString::get(Ctx, SectionName)}; 350753f127fSDimitry Andric 351753f127fSDimitry Andric MD->addOperand(llvm::MDNode::get(Ctx, MDVals)); 352753f127fSDimitry Andric GV->setMetadata(LLVMContext::MD_exclude, llvm::MDNode::get(Ctx, {})); 353753f127fSDimitry Andric 3541fd87a68SDimitry Andric appendToCompilerUsed(M, GV); 3551fd87a68SDimitry Andric } 356bdd1243dSDimitry Andric 357bdd1243dSDimitry Andric bool llvm::lowerGlobalIFuncUsersAsGlobalCtor( 358bdd1243dSDimitry Andric Module &M, ArrayRef<GlobalIFunc *> FilteredIFuncsToLower) { 359bdd1243dSDimitry Andric SmallVector<GlobalIFunc *, 32> AllIFuncs; 360bdd1243dSDimitry Andric ArrayRef<GlobalIFunc *> IFuncsToLower = FilteredIFuncsToLower; 361bdd1243dSDimitry Andric if (FilteredIFuncsToLower.empty()) { // Default to lowering all ifuncs 362bdd1243dSDimitry Andric for (GlobalIFunc &GI : M.ifuncs()) 363bdd1243dSDimitry Andric AllIFuncs.push_back(&GI); 364bdd1243dSDimitry Andric IFuncsToLower = AllIFuncs; 365bdd1243dSDimitry Andric } 366bdd1243dSDimitry Andric 367bdd1243dSDimitry Andric bool UnhandledUsers = false; 368bdd1243dSDimitry Andric LLVMContext &Ctx = M.getContext(); 369bdd1243dSDimitry Andric const DataLayout &DL = M.getDataLayout(); 370bdd1243dSDimitry Andric 371bdd1243dSDimitry Andric PointerType *TableEntryTy = 37206c3fb27SDimitry Andric PointerType::get(Ctx, DL.getProgramAddressSpace()); 373bdd1243dSDimitry Andric 374bdd1243dSDimitry Andric ArrayType *FuncPtrTableTy = 375bdd1243dSDimitry Andric ArrayType::get(TableEntryTy, IFuncsToLower.size()); 376bdd1243dSDimitry Andric 377bdd1243dSDimitry Andric Align PtrAlign = DL.getABITypeAlign(TableEntryTy); 378bdd1243dSDimitry Andric 379bdd1243dSDimitry Andric // Create a global table of function pointers we'll initialize in a global 380bdd1243dSDimitry Andric // constructor. 381bdd1243dSDimitry Andric auto *FuncPtrTable = new GlobalVariable( 382bdd1243dSDimitry Andric M, FuncPtrTableTy, false, GlobalValue::InternalLinkage, 383bdd1243dSDimitry Andric PoisonValue::get(FuncPtrTableTy), "", nullptr, 384bdd1243dSDimitry Andric GlobalVariable::NotThreadLocal, DL.getDefaultGlobalsAddressSpace()); 385bdd1243dSDimitry Andric FuncPtrTable->setAlignment(PtrAlign); 386bdd1243dSDimitry Andric 387bdd1243dSDimitry Andric // Create a function to initialize the function pointer table. 388bdd1243dSDimitry Andric Function *NewCtor = Function::Create( 389bdd1243dSDimitry Andric FunctionType::get(Type::getVoidTy(Ctx), false), Function::InternalLinkage, 390bdd1243dSDimitry Andric DL.getProgramAddressSpace(), "", &M); 391bdd1243dSDimitry Andric 392bdd1243dSDimitry Andric BasicBlock *BB = BasicBlock::Create(Ctx, "", NewCtor); 393bdd1243dSDimitry Andric IRBuilder<> InitBuilder(BB); 394bdd1243dSDimitry Andric 395bdd1243dSDimitry Andric size_t TableIndex = 0; 396bdd1243dSDimitry Andric for (GlobalIFunc *GI : IFuncsToLower) { 397bdd1243dSDimitry Andric Function *ResolvedFunction = GI->getResolverFunction(); 398bdd1243dSDimitry Andric 399bdd1243dSDimitry Andric // We don't know what to pass to a resolver function taking arguments 400bdd1243dSDimitry Andric // 401bdd1243dSDimitry Andric // FIXME: Is this even valid? clang and gcc don't complain but this 402bdd1243dSDimitry Andric // probably should be invalid IR. We could just pass through undef. 403bdd1243dSDimitry Andric if (!std::empty(ResolvedFunction->getFunctionType()->params())) { 404bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "Not lowering ifunc resolver function " 405bdd1243dSDimitry Andric << ResolvedFunction->getName() << " with parameters\n"); 406bdd1243dSDimitry Andric UnhandledUsers = true; 407bdd1243dSDimitry Andric continue; 408bdd1243dSDimitry Andric } 409bdd1243dSDimitry Andric 410bdd1243dSDimitry Andric // Initialize the function pointer table. 411bdd1243dSDimitry Andric CallInst *ResolvedFunc = InitBuilder.CreateCall(ResolvedFunction); 412bdd1243dSDimitry Andric Value *Casted = InitBuilder.CreatePointerCast(ResolvedFunc, TableEntryTy); 413bdd1243dSDimitry Andric Constant *GEP = cast<Constant>(InitBuilder.CreateConstInBoundsGEP2_32( 414bdd1243dSDimitry Andric FuncPtrTableTy, FuncPtrTable, 0, TableIndex++)); 415bdd1243dSDimitry Andric InitBuilder.CreateAlignedStore(Casted, GEP, PtrAlign); 416bdd1243dSDimitry Andric 417bdd1243dSDimitry Andric // Update all users to load a pointer from the global table. 418bdd1243dSDimitry Andric for (User *User : make_early_inc_range(GI->users())) { 419bdd1243dSDimitry Andric Instruction *UserInst = dyn_cast<Instruction>(User); 420bdd1243dSDimitry Andric if (!UserInst) { 421bdd1243dSDimitry Andric // TODO: Should handle constantexpr casts in user instructions. Probably 422bdd1243dSDimitry Andric // can't do much about constant initializers. 423bdd1243dSDimitry Andric UnhandledUsers = true; 424bdd1243dSDimitry Andric continue; 425bdd1243dSDimitry Andric } 426bdd1243dSDimitry Andric 427bdd1243dSDimitry Andric IRBuilder<> UseBuilder(UserInst); 428bdd1243dSDimitry Andric LoadInst *ResolvedTarget = 429bdd1243dSDimitry Andric UseBuilder.CreateAlignedLoad(TableEntryTy, GEP, PtrAlign); 430bdd1243dSDimitry Andric Value *ResolvedCast = 431bdd1243dSDimitry Andric UseBuilder.CreatePointerCast(ResolvedTarget, GI->getType()); 432bdd1243dSDimitry Andric UserInst->replaceUsesOfWith(GI, ResolvedCast); 433bdd1243dSDimitry Andric } 434bdd1243dSDimitry Andric 435bdd1243dSDimitry Andric // If we handled all users, erase the ifunc. 436bdd1243dSDimitry Andric if (GI->use_empty()) 437bdd1243dSDimitry Andric GI->eraseFromParent(); 438bdd1243dSDimitry Andric } 439bdd1243dSDimitry Andric 440bdd1243dSDimitry Andric InitBuilder.CreateRetVoid(); 441bdd1243dSDimitry Andric 44206c3fb27SDimitry Andric PointerType *ConstantDataTy = PointerType::get(Ctx, 0); 443bdd1243dSDimitry Andric 444bdd1243dSDimitry Andric // TODO: Is this the right priority? Probably should be before any other 445bdd1243dSDimitry Andric // constructors? 446bdd1243dSDimitry Andric const int Priority = 10; 447bdd1243dSDimitry Andric appendToGlobalCtors(M, NewCtor, Priority, 448bdd1243dSDimitry Andric ConstantPointerNull::get(ConstantDataTy)); 449bdd1243dSDimitry Andric return UnhandledUsers; 450bdd1243dSDimitry Andric } 451