1dff0c46cSDimitry Andric //===-- ModuleUtils.cpp - Functions to manipulate Modules -----------------===// 2dff0c46cSDimitry Andric // 3dff0c46cSDimitry Andric // The LLVM Compiler Infrastructure 4dff0c46cSDimitry Andric // 5dff0c46cSDimitry Andric // This file is distributed under the University of Illinois Open Source 6dff0c46cSDimitry Andric // License. See LICENSE.TXT for details. 7dff0c46cSDimitry Andric // 8dff0c46cSDimitry Andric //===----------------------------------------------------------------------===// 9dff0c46cSDimitry Andric // 10dff0c46cSDimitry Andric // This family of functions perform manipulations on Modules. 11dff0c46cSDimitry Andric // 12dff0c46cSDimitry Andric //===----------------------------------------------------------------------===// 13dff0c46cSDimitry Andric 14dff0c46cSDimitry Andric #include "llvm/Transforms/Utils/ModuleUtils.h" 15139f7f9bSDimitry Andric #include "llvm/IR/DerivedTypes.h" 16139f7f9bSDimitry Andric #include "llvm/IR/Function.h" 17139f7f9bSDimitry Andric #include "llvm/IR/IRBuilder.h" 18139f7f9bSDimitry Andric #include "llvm/IR/Module.h" 19ff0cc061SDimitry Andric #include "llvm/Support/raw_ostream.h" 20dff0c46cSDimitry Andric 21dff0c46cSDimitry Andric using namespace llvm; 22dff0c46cSDimitry Andric 233ca95b02SDimitry Andric static void appendToGlobalArray(const char *Array, Module &M, Function *F, 243ca95b02SDimitry Andric int Priority, Constant *Data) { 25dff0c46cSDimitry Andric IRBuilder<> IRB(M.getContext()); 26dff0c46cSDimitry Andric FunctionType *FnTy = FunctionType::get(IRB.getVoidTy(), false); 27dff0c46cSDimitry Andric 28dff0c46cSDimitry Andric // Get the current set of static global constructors and add the new ctor 29dff0c46cSDimitry Andric // to the list. 30dff0c46cSDimitry Andric SmallVector<Constant *, 16> CurrentCtors; 3191bc56edSDimitry Andric StructType *EltTy; 32dff0c46cSDimitry Andric if (GlobalVariable *GVCtor = M.getNamedGlobal(Array)) { 333ca95b02SDimitry Andric ArrayType *ATy = cast<ArrayType>(GVCtor->getValueType()); 343ca95b02SDimitry Andric StructType *OldEltTy = cast<StructType>(ATy->getElementType()); 353ca95b02SDimitry Andric // Upgrade a 2-field global array type to the new 3-field format if needed. 363ca95b02SDimitry Andric if (Data && OldEltTy->getNumElements() < 3) 373ca95b02SDimitry Andric EltTy = StructType::get(IRB.getInt32Ty(), PointerType::getUnqual(FnTy), 383ca95b02SDimitry Andric IRB.getInt8PtrTy(), nullptr); 393ca95b02SDimitry Andric else 403ca95b02SDimitry Andric EltTy = OldEltTy; 41dff0c46cSDimitry Andric if (Constant *Init = GVCtor->getInitializer()) { 42dff0c46cSDimitry Andric unsigned n = Init->getNumOperands(); 43dff0c46cSDimitry Andric CurrentCtors.reserve(n + 1); 443ca95b02SDimitry Andric for (unsigned i = 0; i != n; ++i) { 453ca95b02SDimitry Andric auto Ctor = cast<Constant>(Init->getOperand(i)); 463ca95b02SDimitry Andric if (EltTy != OldEltTy) 473ca95b02SDimitry Andric Ctor = ConstantStruct::get( 483ca95b02SDimitry Andric EltTy, Ctor->getAggregateElement((unsigned)0), 493ca95b02SDimitry Andric Ctor->getAggregateElement(1), 503ca95b02SDimitry Andric Constant::getNullValue(IRB.getInt8PtrTy()), nullptr); 513ca95b02SDimitry Andric CurrentCtors.push_back(Ctor); 523ca95b02SDimitry Andric } 53dff0c46cSDimitry Andric } 54dff0c46cSDimitry Andric GVCtor->eraseFromParent(); 5591bc56edSDimitry Andric } else { 567d523365SDimitry Andric // Use the new three-field struct if there isn't one already. 5791bc56edSDimitry Andric EltTy = StructType::get(IRB.getInt32Ty(), PointerType::getUnqual(FnTy), 587d523365SDimitry Andric IRB.getInt8PtrTy(), nullptr); 59dff0c46cSDimitry Andric } 60dff0c46cSDimitry Andric 6191bc56edSDimitry Andric // Build a 2 or 3 field global_ctor entry. We don't take a comdat key. 6291bc56edSDimitry Andric Constant *CSVals[3]; 6391bc56edSDimitry Andric CSVals[0] = IRB.getInt32(Priority); 6491bc56edSDimitry Andric CSVals[1] = F; 6591bc56edSDimitry Andric // FIXME: Drop support for the two element form in LLVM 4.0. 6691bc56edSDimitry Andric if (EltTy->getNumElements() >= 3) 673ca95b02SDimitry Andric CSVals[2] = Data ? ConstantExpr::getPointerCast(Data, IRB.getInt8PtrTy()) 683ca95b02SDimitry Andric : Constant::getNullValue(IRB.getInt8PtrTy()); 6991bc56edSDimitry Andric Constant *RuntimeCtorInit = 7091bc56edSDimitry Andric ConstantStruct::get(EltTy, makeArrayRef(CSVals, EltTy->getNumElements())); 7191bc56edSDimitry Andric 72dff0c46cSDimitry Andric CurrentCtors.push_back(RuntimeCtorInit); 73dff0c46cSDimitry Andric 74dff0c46cSDimitry Andric // Create a new initializer. 7591bc56edSDimitry Andric ArrayType *AT = ArrayType::get(EltTy, CurrentCtors.size()); 76dff0c46cSDimitry Andric Constant *NewInit = ConstantArray::get(AT, CurrentCtors); 77dff0c46cSDimitry Andric 78dff0c46cSDimitry Andric // Create the new global variable and replace all uses of 79dff0c46cSDimitry Andric // the old global variable with the new one. 80dff0c46cSDimitry Andric (void)new GlobalVariable(M, NewInit->getType(), false, 81dff0c46cSDimitry Andric GlobalValue::AppendingLinkage, NewInit, Array); 82dff0c46cSDimitry Andric } 83dff0c46cSDimitry Andric 843ca95b02SDimitry Andric void llvm::appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data) { 853ca95b02SDimitry Andric appendToGlobalArray("llvm.global_ctors", M, F, Priority, Data); 86dff0c46cSDimitry Andric } 87dff0c46cSDimitry Andric 883ca95b02SDimitry Andric void llvm::appendToGlobalDtors(Module &M, Function *F, int Priority, Constant *Data) { 893ca95b02SDimitry Andric appendToGlobalArray("llvm.global_dtors", M, F, Priority, Data); 90f785676fSDimitry Andric } 91ff0cc061SDimitry Andric 92ff0cc061SDimitry Andric Function *llvm::checkSanitizerInterfaceFunction(Constant *FuncOrBitcast) { 93ff0cc061SDimitry Andric if (isa<Function>(FuncOrBitcast)) 94ff0cc061SDimitry Andric return cast<Function>(FuncOrBitcast); 95ff0cc061SDimitry Andric FuncOrBitcast->dump(); 96ff0cc061SDimitry Andric std::string Err; 97ff0cc061SDimitry Andric raw_string_ostream Stream(Err); 98ff0cc061SDimitry Andric Stream << "Sanitizer interface function redefined: " << *FuncOrBitcast; 99ff0cc061SDimitry Andric report_fatal_error(Err); 100ff0cc061SDimitry Andric } 101ff0cc061SDimitry Andric 102ff0cc061SDimitry Andric std::pair<Function *, Function *> llvm::createSanitizerCtorAndInitFunctions( 103ff0cc061SDimitry Andric Module &M, StringRef CtorName, StringRef InitName, 1047d523365SDimitry Andric ArrayRef<Type *> InitArgTypes, ArrayRef<Value *> InitArgs, 1057d523365SDimitry Andric StringRef VersionCheckName) { 106ff0cc061SDimitry Andric assert(!InitName.empty() && "Expected init function name"); 107ff0cc061SDimitry Andric assert(InitArgTypes.size() == InitArgTypes.size() && 108ff0cc061SDimitry Andric "Sanitizer's init function expects different number of arguments"); 109ff0cc061SDimitry Andric Function *Ctor = Function::Create( 110ff0cc061SDimitry Andric FunctionType::get(Type::getVoidTy(M.getContext()), false), 111ff0cc061SDimitry Andric GlobalValue::InternalLinkage, CtorName, &M); 112ff0cc061SDimitry Andric BasicBlock *CtorBB = BasicBlock::Create(M.getContext(), "", Ctor); 113ff0cc061SDimitry Andric IRBuilder<> IRB(ReturnInst::Create(M.getContext(), CtorBB)); 114ff0cc061SDimitry Andric Function *InitFunction = 115ff0cc061SDimitry Andric checkSanitizerInterfaceFunction(M.getOrInsertFunction( 116ff0cc061SDimitry Andric InitName, FunctionType::get(IRB.getVoidTy(), InitArgTypes, false), 117ff0cc061SDimitry Andric AttributeSet())); 118ff0cc061SDimitry Andric InitFunction->setLinkage(Function::ExternalLinkage); 119ff0cc061SDimitry Andric IRB.CreateCall(InitFunction, InitArgs); 1207d523365SDimitry Andric if (!VersionCheckName.empty()) { 1217d523365SDimitry Andric Function *VersionCheckFunction = 1227d523365SDimitry Andric checkSanitizerInterfaceFunction(M.getOrInsertFunction( 1237d523365SDimitry Andric VersionCheckName, FunctionType::get(IRB.getVoidTy(), {}, false), 1247d523365SDimitry Andric AttributeSet())); 1257d523365SDimitry Andric IRB.CreateCall(VersionCheckFunction, {}); 1267d523365SDimitry Andric } 127ff0cc061SDimitry Andric return std::make_pair(Ctor, InitFunction); 128ff0cc061SDimitry Andric } 129