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