xref: /minix3/minix/llvm/passes/magic/support/MagicUtil.cpp (revision bdb565187c0f1a04513dd488df843317b27f86c8)
13e457fe3SDavid van Moolenbroek #include <magic/support/MagicUtil.h>
23e457fe3SDavid van Moolenbroek 
33e457fe3SDavid van Moolenbroek using namespace llvm;
43e457fe3SDavid van Moolenbroek 
53e457fe3SDavid van Moolenbroek namespace llvm {
63e457fe3SDavid van Moolenbroek 
73e457fe3SDavid van Moolenbroek //===----------------------------------------------------------------------===//
83e457fe3SDavid van Moolenbroek // Public static methods
93e457fe3SDavid van Moolenbroek //===----------------------------------------------------------------------===//
103e457fe3SDavid van Moolenbroek 
113e457fe3SDavid van Moolenbroek static std::map<const std::string, GlobalVariable*> stringRefCache;
123e457fe3SDavid van Moolenbroek 
getLabelHash(std::string label)133e457fe3SDavid van Moolenbroek unsigned getLabelHash(std::string label) {
143e457fe3SDavid van Moolenbroek     unsigned hash = 0;
153e457fe3SDavid van Moolenbroek     for(unsigned i=0;i<label.length();i++){
163e457fe3SDavid van Moolenbroek         hash ^= (label[i]);
173e457fe3SDavid van Moolenbroek         hash = (hash << 9) | (hash >> ((sizeof(unsigned)*8)-9));
183e457fe3SDavid van Moolenbroek     }
193e457fe3SDavid van Moolenbroek     return hash;
203e457fe3SDavid van Moolenbroek }
213e457fe3SDavid van Moolenbroek 
getModuleHash(DIDescriptor DID,const std::string & baseDir,StringRef extraField="")223e457fe3SDavid van Moolenbroek unsigned getModuleHash(DIDescriptor DID, const std::string &baseDir, StringRef extraField="") {
233e457fe3SDavid van Moolenbroek     std::string relPath;
243e457fe3SDavid van Moolenbroek     PassUtil::getDbgLocationInfo(DID, baseDir, NULL, NULL, &relPath);
253e457fe3SDavid van Moolenbroek     return getLabelHash(relPath + "/" + extraField.data());
263e457fe3SDavid van Moolenbroek }
273e457fe3SDavid van Moolenbroek 
getGVSourceName(Module & M,GlobalVariable * GV,DIGlobalVariable ** DIGVP,const std::string & baseDir)283e457fe3SDavid van Moolenbroek StringRef MagicUtil::getGVSourceName(Module &M, GlobalVariable *GV, DIGlobalVariable **DIGVP, const std::string &baseDir) {
293e457fe3SDavid van Moolenbroek     static DIGlobalVariable Var;
30*bdb56518SDavid van Moolenbroek     MDNode *DIGV = PassUtil::findDbgGlobalDeclare(GV);
313e457fe3SDavid van Moolenbroek     if(DIGV) {
32*bdb56518SDavid van Moolenbroek         Var = DIGlobalVariable(DIGV);
333e457fe3SDavid van Moolenbroek         if(DIGVP) *DIGVP = &Var;
343e457fe3SDavid van Moolenbroek         if(GV->getLinkage() == GlobalValue::InternalLinkage){
353e457fe3SDavid van Moolenbroek             /* static variable */
363e457fe3SDavid van Moolenbroek             StringRef funcName, countStr;
373e457fe3SDavid van Moolenbroek             DIScope scope = Var.getContext();
383e457fe3SDavid van Moolenbroek             if(scope.isLexicalBlock()){
393e457fe3SDavid van Moolenbroek                 /* find the subprogram that contains this basic block recursively */
403e457fe3SDavid van Moolenbroek                 while(!scope.isSubprogram()){
413e457fe3SDavid van Moolenbroek                     scope = DILexicalBlock(scope).getContext();
423e457fe3SDavid van Moolenbroek                 }
433e457fe3SDavid van Moolenbroek             }
443e457fe3SDavid van Moolenbroek             if(scope.isSubprogram()){
453e457fe3SDavid van Moolenbroek                 /* static function variable */
463e457fe3SDavid van Moolenbroek 
473e457fe3SDavid van Moolenbroek                 funcName = DISubprogram(scope).getName();
483e457fe3SDavid van Moolenbroek 
493e457fe3SDavid van Moolenbroek                 int count=0;
503e457fe3SDavid van Moolenbroek                 Module::GlobalListType &globalList = M.getGlobalList();
513e457fe3SDavid van Moolenbroek                 for (Module::global_iterator it = globalList.begin(); it != globalList.end(); ++it) {
523e457fe3SDavid van Moolenbroek                     GlobalVariable *OtherGV = &(*it);
53*bdb56518SDavid van Moolenbroek                     MDNode *OtherDIGV = PassUtil::findDbgGlobalDeclare(OtherGV);
543e457fe3SDavid van Moolenbroek                     if(OtherDIGV) {
55*bdb56518SDavid van Moolenbroek                         DIGlobalVariable OtherVar(OtherDIGV);
563e457fe3SDavid van Moolenbroek 
573e457fe3SDavid van Moolenbroek                         DIScope otherScope = OtherVar.getContext();
583e457fe3SDavid van Moolenbroek                         if(otherScope.isLexicalBlock()){
593e457fe3SDavid van Moolenbroek                             /* find the subprogram that contains this basic block recursively */
603e457fe3SDavid van Moolenbroek                             while(!otherScope.isSubprogram()){
613e457fe3SDavid van Moolenbroek                                 otherScope = DILexicalBlock(otherScope).getContext();
623e457fe3SDavid van Moolenbroek                             }
633e457fe3SDavid van Moolenbroek                         }
643e457fe3SDavid van Moolenbroek                         if(otherScope.isSubprogram()){
653e457fe3SDavid van Moolenbroek                             if(!strcmp(Var.getName().data(), OtherVar.getName().data())){
663e457fe3SDavid van Moolenbroek                                 if(DIGV == OtherDIGV){
673e457fe3SDavid van Moolenbroek                                     break;
683e457fe3SDavid van Moolenbroek                                 }
693e457fe3SDavid van Moolenbroek                                 count++;
703e457fe3SDavid van Moolenbroek                             }
713e457fe3SDavid van Moolenbroek                         }
723e457fe3SDavid van Moolenbroek                     }
733e457fe3SDavid van Moolenbroek                 }
743e457fe3SDavid van Moolenbroek 
753e457fe3SDavid van Moolenbroek                 std::stringstream stm;
763e457fe3SDavid van Moolenbroek                 if(count > 0){
773e457fe3SDavid van Moolenbroek                     stm << "." << count;
783e457fe3SDavid van Moolenbroek                 }
793e457fe3SDavid van Moolenbroek                 countStr = StringRef(*new std::string(stm.str()));
803e457fe3SDavid van Moolenbroek 
813e457fe3SDavid van Moolenbroek             }else{
823e457fe3SDavid van Moolenbroek                 /* static global variable */
833e457fe3SDavid van Moolenbroek                 funcName = "";
843e457fe3SDavid van Moolenbroek                 countStr = "";
853e457fe3SDavid van Moolenbroek             }
863e457fe3SDavid van Moolenbroek 
873e457fe3SDavid van Moolenbroek             std::stringstream stm;
883e457fe3SDavid van Moolenbroek             stm << Var.getName().data() << "." << getModuleHash(Var, baseDir, funcName) << countStr.data();
893e457fe3SDavid van Moolenbroek             return StringRef(*new std::string(stm.str()));
903e457fe3SDavid van Moolenbroek 
913e457fe3SDavid van Moolenbroek         }else{
923e457fe3SDavid van Moolenbroek             /* global variable */
933e457fe3SDavid van Moolenbroek             return Var.getName();
943e457fe3SDavid van Moolenbroek         }
953e457fe3SDavid van Moolenbroek     }else{
963e457fe3SDavid van Moolenbroek         /* llvm .str variables and assembly */
973e457fe3SDavid van Moolenbroek         if(DIGVP) *DIGVP = NULL;
983e457fe3SDavid van Moolenbroek         return GV->getName();
993e457fe3SDavid van Moolenbroek     }
1003e457fe3SDavid van Moolenbroek }
1013e457fe3SDavid van Moolenbroek 
getLVSourceName(Module & M,AllocaInst * V,DIVariable ** DIVP)1023e457fe3SDavid van Moolenbroek StringRef MagicUtil::getLVSourceName(Module &M, AllocaInst *V, DIVariable **DIVP) {
1033e457fe3SDavid van Moolenbroek     static DIVariable Var;
104*bdb56518SDavid van Moolenbroek     const DbgDeclareInst *DDI = FindAllocaDbgDeclare(V);
1053e457fe3SDavid van Moolenbroek     if(DDI && DDI != (const DbgDeclareInst *) -1){
1063e457fe3SDavid van Moolenbroek         Var = DIVariable(cast<MDNode>(DDI->getVariable()));
1073e457fe3SDavid van Moolenbroek         if(DIVP) *DIVP = &Var;
1083e457fe3SDavid van Moolenbroek 
1093e457fe3SDavid van Moolenbroek         int count = 0;
1103e457fe3SDavid van Moolenbroek 
1113e457fe3SDavid van Moolenbroek         Function *F = V->getParent()->getParent();
1123e457fe3SDavid van Moolenbroek         for (inst_iterator it = inst_begin(F), et = inst_end(F); it != et; ++it) {
1133e457fe3SDavid van Moolenbroek             Instruction *inst = &(*it);
1143e457fe3SDavid van Moolenbroek             if (DbgDeclareInst *OtherDDI = dyn_cast<DbgDeclareInst>(inst)){
1153e457fe3SDavid van Moolenbroek                 DIVariable otherVar(cast<MDNode>(OtherDDI->getVariable()));
1163e457fe3SDavid van Moolenbroek                 if(!strcmp(Var.getName().data(), otherVar.getName().data())){
1173e457fe3SDavid van Moolenbroek                     if(OtherDDI == DDI){
1183e457fe3SDavid van Moolenbroek                         break;
1193e457fe3SDavid van Moolenbroek                     }
1203e457fe3SDavid van Moolenbroek                     count++;
1213e457fe3SDavid van Moolenbroek                 }
1223e457fe3SDavid van Moolenbroek             }
1233e457fe3SDavid van Moolenbroek         }
1243e457fe3SDavid van Moolenbroek 
1253e457fe3SDavid van Moolenbroek         std::stringstream stm;
1263e457fe3SDavid van Moolenbroek         stm << Var.getName().data();
1273e457fe3SDavid van Moolenbroek         if(count > 0){
1283e457fe3SDavid van Moolenbroek             stm << "." << count;
1293e457fe3SDavid van Moolenbroek         }
1303e457fe3SDavid van Moolenbroek         return StringRef(*new std::string(stm.str()));
1313e457fe3SDavid van Moolenbroek     }else{
1323e457fe3SDavid van Moolenbroek         if(DIVP) *DIVP = NULL;
1333e457fe3SDavid van Moolenbroek         return V->getName();
1343e457fe3SDavid van Moolenbroek     }
1353e457fe3SDavid van Moolenbroek }
1363e457fe3SDavid van Moolenbroek 
getFunctionSourceName(Module & M,Function * F,DISubprogram ** DISP,const std::string & baseDir)1373e457fe3SDavid van Moolenbroek StringRef MagicUtil::getFunctionSourceName(Module &M, Function *F, DISubprogram **DISP, const std::string &baseDir) {
1383e457fe3SDavid van Moolenbroek     static DISubprogram Func;
139*bdb56518SDavid van Moolenbroek     MDNode *DIF = PassUtil::findDbgSubprogramDeclare(F);
1403e457fe3SDavid van Moolenbroek     if(DIF) {
141*bdb56518SDavid van Moolenbroek         Func = DISubprogram(DIF);
1423e457fe3SDavid van Moolenbroek         if(DISP) *DISP = &Func;
1433e457fe3SDavid van Moolenbroek         if(F->getLinkage() == GlobalValue::InternalLinkage){
1443e457fe3SDavid van Moolenbroek             std::stringstream stm;
1453e457fe3SDavid van Moolenbroek             stm << Func.getName().data() << "." << getModuleHash(Func, baseDir);
1463e457fe3SDavid van Moolenbroek             return StringRef(*new std::string(stm.str()));
1473e457fe3SDavid van Moolenbroek         }else{
1483e457fe3SDavid van Moolenbroek             return Func.getName();
1493e457fe3SDavid van Moolenbroek         }
1503e457fe3SDavid van Moolenbroek     }else{
1513e457fe3SDavid van Moolenbroek         /* assembly */
1523e457fe3SDavid van Moolenbroek         if(DISP) *DISP = NULL;
1533e457fe3SDavid van Moolenbroek         return F->getName();
1543e457fe3SDavid van Moolenbroek     }
1553e457fe3SDavid van Moolenbroek }
1563e457fe3SDavid van Moolenbroek 
putStringRefCache(Module & M,const std::string & str,GlobalVariable * GV)1573e457fe3SDavid van Moolenbroek void MagicUtil::putStringRefCache(Module &M, const std::string &str, GlobalVariable *GV) {
1583e457fe3SDavid van Moolenbroek     std::map<const std::string, GlobalVariable*>::iterator it;
1593e457fe3SDavid van Moolenbroek     it = stringRefCache.find(str);
1603e457fe3SDavid van Moolenbroek     if(it == stringRefCache.end()) {
1613e457fe3SDavid van Moolenbroek         stringRefCache.insert(std::pair<const std::string, GlobalVariable*>(str, GV));
1623e457fe3SDavid van Moolenbroek     }
1633e457fe3SDavid van Moolenbroek }
1643e457fe3SDavid van Moolenbroek 
getGetElementPtrConstant(Constant * constant,std::vector<Value * > & indexes)1653e457fe3SDavid van Moolenbroek Constant* MagicUtil::getGetElementPtrConstant(Constant *constant, std::vector<Value*> &indexes) {
1663e457fe3SDavid van Moolenbroek     return PassUtil::getGetElementPtrConstant(constant, indexes);
1673e457fe3SDavid van Moolenbroek }
1683e457fe3SDavid van Moolenbroek 
createGetElementPtrInstruction(Value * ptr,std::vector<Value * > & indexes,const Twine & NameStr,Instruction * InsertBefore)1693e457fe3SDavid van Moolenbroek GetElementPtrInst* MagicUtil::createGetElementPtrInstruction(Value *ptr, std::vector<Value*> &indexes, const Twine &NameStr, Instruction *InsertBefore) {
1703e457fe3SDavid van Moolenbroek     return PassUtil::createGetElementPtrInstruction(ptr, indexes, NameStr, InsertBefore);
1713e457fe3SDavid van Moolenbroek }
1723e457fe3SDavid van Moolenbroek 
createGetElementPtrInstruction(Value * ptr,std::vector<Value * > & indexes,const Twine & NameStr,BasicBlock * InsertAtEnd)1733e457fe3SDavid van Moolenbroek GetElementPtrInst* MagicUtil::createGetElementPtrInstruction(Value *ptr, std::vector<Value*> &indexes, const Twine &NameStr, BasicBlock *InsertAtEnd) {
1743e457fe3SDavid van Moolenbroek     return PassUtil::createGetElementPtrInstruction(ptr, indexes, NameStr, InsertAtEnd);
1753e457fe3SDavid van Moolenbroek }
1763e457fe3SDavid van Moolenbroek 
createCallInstruction(Value * F,std::vector<Value * > & args,const Twine & NameStr,Instruction * InsertBefore)1773e457fe3SDavid van Moolenbroek CallInst* MagicUtil::createCallInstruction(Value *F, std::vector<Value*> &args, const Twine &NameStr, Instruction *InsertBefore) {
1783e457fe3SDavid van Moolenbroek     return PassUtil::createCallInstruction(F, args, NameStr, InsertBefore);
1793e457fe3SDavid van Moolenbroek }
1803e457fe3SDavid van Moolenbroek 
createCallInstruction(Value * F,std::vector<Value * > & args,const Twine & NameStr,BasicBlock * InsertAtEnd)1813e457fe3SDavid van Moolenbroek CallInst* MagicUtil::createCallInstruction(Value *F, std::vector<Value*> &args, const Twine &NameStr, BasicBlock *InsertAtEnd) {
1823e457fe3SDavid van Moolenbroek     return PassUtil::createCallInstruction(F, args, NameStr, InsertAtEnd);
1833e457fe3SDavid van Moolenbroek }
1843e457fe3SDavid van Moolenbroek 
getIntrinsicFunction(Module & M,Intrinsic::ID id,TYPECONST Type ** types,unsigned size)1853e457fe3SDavid van Moolenbroek Function* MagicUtil::getIntrinsicFunction(Module &M, Intrinsic::ID id, TYPECONST Type** types, unsigned size) {
1863e457fe3SDavid van Moolenbroek     return PassUtil::getIntrinsicFunction(M, id, types, size);
1873e457fe3SDavid van Moolenbroek }
1883e457fe3SDavid van Moolenbroek 
getStringRef(Module & M,const std::string & str)1893e457fe3SDavid van Moolenbroek GlobalVariable *MagicUtil::getStringRef(Module &M, const std::string &str) {
1903e457fe3SDavid van Moolenbroek     std::map<const std::string, GlobalVariable*>::iterator it;
1913e457fe3SDavid van Moolenbroek     GlobalVariable *stringRef = NULL;
1923e457fe3SDavid van Moolenbroek     bool debug = false;
1933e457fe3SDavid van Moolenbroek 
1943e457fe3SDavid van Moolenbroek     it = stringRefCache.find(str);
1953e457fe3SDavid van Moolenbroek     if(it != stringRefCache.end()) {
1963e457fe3SDavid van Moolenbroek         if(debug) magicUtilLog("*** getStringRef: cache hit for " << str);
1973e457fe3SDavid van Moolenbroek         stringRef = it->second;
1983e457fe3SDavid van Moolenbroek     }
1993e457fe3SDavid van Moolenbroek     if(stringRef == NULL) {
2003e457fe3SDavid van Moolenbroek     	stringRef = PassUtil::getStringGlobalVariable(M, str, MAGIC_HIDDEN_STR_PREFIX, MAGIC_STATIC_VARS_SECTION_RO);
2013e457fe3SDavid van Moolenbroek         stringRefCache.insert(std::pair<const std::string, GlobalVariable*>(str, stringRef));
2023e457fe3SDavid van Moolenbroek     }
2033e457fe3SDavid van Moolenbroek 
2043e457fe3SDavid van Moolenbroek      return stringRef;
2053e457fe3SDavid van Moolenbroek  }
2063e457fe3SDavid van Moolenbroek 
2073e457fe3SDavid van Moolenbroek 
getIntArrayRef(Module & M,unsigned arrSize,std::vector<int> * arr,bool isConstant)2083e457fe3SDavid van Moolenbroek GlobalVariable *MagicUtil::getIntArrayRef(Module &M, unsigned arrSize, std::vector<int> *arr, bool isConstant) {
2093e457fe3SDavid van Moolenbroek     static std::map<std::vector<int>, GlobalVariable*> arrayRefCache;
2103e457fe3SDavid van Moolenbroek     std::map<std::vector<int>, GlobalVariable*>::iterator it;
2113e457fe3SDavid van Moolenbroek     static std::vector<int> defInitilizer;
2123e457fe3SDavid van Moolenbroek 
2133e457fe3SDavid van Moolenbroek     //construct an appropriate initializer if we do not have one
2143e457fe3SDavid van Moolenbroek     if(!arr) {
2153e457fe3SDavid van Moolenbroek         arr = &defInitilizer;
2163e457fe3SDavid van Moolenbroek         arr->clear();
2173e457fe3SDavid van Moolenbroek         for(unsigned i=0;i<arrSize;i++) arr->push_back(0);
2183e457fe3SDavid van Moolenbroek     }
2193e457fe3SDavid van Moolenbroek     assert(arrSize == arr->size());
2203e457fe3SDavid van Moolenbroek 
2213e457fe3SDavid van Moolenbroek     //cache lookup
2223e457fe3SDavid van Moolenbroek     if(isConstant) {
2233e457fe3SDavid van Moolenbroek         it = arrayRefCache.find(*arr);
2243e457fe3SDavid van Moolenbroek         if(it != arrayRefCache.end()) {
2253e457fe3SDavid van Moolenbroek             return it->second;
2263e457fe3SDavid van Moolenbroek         }
2273e457fe3SDavid van Moolenbroek     }
2283e457fe3SDavid van Moolenbroek 
2293e457fe3SDavid van Moolenbroek     //create a constant internal array reference
2303e457fe3SDavid van Moolenbroek     std::vector<Constant*> arrayElems;
2313e457fe3SDavid van Moolenbroek     for(unsigned i=0;i<arr->size();i++) {
2323e457fe3SDavid van Moolenbroek         arrayElems.push_back(ConstantInt::get(M.getContext(), APInt(32, (*arr)[i], 10)));
2333e457fe3SDavid van Moolenbroek     }
2343e457fe3SDavid van Moolenbroek     ArrayType* arrayTy = ArrayType::get(IntegerType::get(M.getContext(), 32), arr->size());
2353e457fe3SDavid van Moolenbroek     Constant *arrayValue = ConstantArray::get(arrayTy, arrayElems);
2363e457fe3SDavid van Moolenbroek 
2373e457fe3SDavid van Moolenbroek     //create the global variable and record it in the module
2383e457fe3SDavid van Moolenbroek     GlobalVariable *arrayRef = new GlobalVariable(arrayValue->getType(), isConstant,
2393e457fe3SDavid van Moolenbroek         GlobalValue::InternalLinkage, arrayValue,
2403e457fe3SDavid van Moolenbroek         MAGIC_HIDDEN_ARRAY_PREFIX);
2413e457fe3SDavid van Moolenbroek     MagicUtil::setGlobalVariableSection(arrayRef, isConstant ? MAGIC_STATIC_VARS_SECTION_RO : MAGIC_STATIC_VARS_SECTION_DATA);
2423e457fe3SDavid van Moolenbroek     M.getGlobalList().push_back(arrayRef);
2433e457fe3SDavid van Moolenbroek 
2443e457fe3SDavid van Moolenbroek     //populate cache
2453e457fe3SDavid van Moolenbroek     if(isConstant) {
2463e457fe3SDavid van Moolenbroek         arrayRefCache.insert(std::pair<std::vector<int>, GlobalVariable*>(*arr, arrayRef));
2473e457fe3SDavid van Moolenbroek     }
2483e457fe3SDavid van Moolenbroek 
2493e457fe3SDavid van Moolenbroek     return arrayRef;
2503e457fe3SDavid van Moolenbroek }
2513e457fe3SDavid van Moolenbroek 
getStringArrayRef(Module & M,unsigned arrSize,std::vector<std::string> * arr,bool isConstant)2523e457fe3SDavid van Moolenbroek GlobalVariable *MagicUtil::getStringArrayRef(Module &M, unsigned arrSize, std::vector<std::string> *arr, bool isConstant) {
2533e457fe3SDavid van Moolenbroek     static std::map<std::vector<std::string>, GlobalVariable*> arrayRefCache;
2543e457fe3SDavid van Moolenbroek     std::map<std::vector<std::string>, GlobalVariable*>::iterator it;
2553e457fe3SDavid van Moolenbroek     static std::vector<std::string> defInitilizer;
2563e457fe3SDavid van Moolenbroek     //construct an appropriate initializer if we do not have one
2573e457fe3SDavid van Moolenbroek     if(!arr) {
2583e457fe3SDavid van Moolenbroek         arr = &defInitilizer;
2593e457fe3SDavid van Moolenbroek         arr->clear();
2603e457fe3SDavid van Moolenbroek         for(unsigned i=0;i<arrSize;i++) arr->push_back("");
2613e457fe3SDavid van Moolenbroek     }
2623e457fe3SDavid van Moolenbroek     assert(arrSize == arr->size());
2633e457fe3SDavid van Moolenbroek 
2643e457fe3SDavid van Moolenbroek     //cache lookup
2653e457fe3SDavid van Moolenbroek     if(isConstant) {
2663e457fe3SDavid van Moolenbroek         it = arrayRefCache.find(*arr);
2673e457fe3SDavid van Moolenbroek         if(it != arrayRefCache.end()) {
2683e457fe3SDavid van Moolenbroek             return it->second;
2693e457fe3SDavid van Moolenbroek         }
2703e457fe3SDavid van Moolenbroek     }
2713e457fe3SDavid van Moolenbroek 
2723e457fe3SDavid van Moolenbroek     //create a constant internal array reference
2733e457fe3SDavid van Moolenbroek     std::vector<Constant*> arrayElems;
2743e457fe3SDavid van Moolenbroek     std::vector<Value*> arrayIndexes;
2753e457fe3SDavid van Moolenbroek     arrayIndexes.push_back(ConstantInt::get(M.getContext(), APInt(32, 0, 10)));
2763e457fe3SDavid van Moolenbroek     arrayIndexes.push_back(ConstantInt::get(M.getContext(), APInt(32, 0, 10)));
2773e457fe3SDavid van Moolenbroek     for(unsigned i=0;i<arr->size();i++) {
2783e457fe3SDavid van Moolenbroek         arrayElems.push_back(getGetElementPtrConstant(getStringRef(M, (*arr)[i]), arrayIndexes));
2793e457fe3SDavid van Moolenbroek     }
2803e457fe3SDavid van Moolenbroek     ArrayType* arrayTy = ArrayType::get(PointerType::get(IntegerType::get(M.getContext(), 8), 0), arr->size());
2813e457fe3SDavid van Moolenbroek     Constant *arrayValue = ConstantArray::get(arrayTy, arrayElems);
2823e457fe3SDavid van Moolenbroek 
2833e457fe3SDavid van Moolenbroek     //create the global variable and record it in the module
2843e457fe3SDavid van Moolenbroek     GlobalVariable *arrayRef = new GlobalVariable(arrayValue->getType(), isConstant,
2853e457fe3SDavid van Moolenbroek         GlobalValue::InternalLinkage, arrayValue,
2863e457fe3SDavid van Moolenbroek         MAGIC_HIDDEN_ARRAY_PREFIX);
2873e457fe3SDavid van Moolenbroek     MagicUtil::setGlobalVariableSection(arrayRef, isConstant ? MAGIC_STATIC_VARS_SECTION_RO : MAGIC_STATIC_VARS_SECTION_DATA);
2883e457fe3SDavid van Moolenbroek     M.getGlobalList().push_back(arrayRef);
2893e457fe3SDavid van Moolenbroek 
2903e457fe3SDavid van Moolenbroek     //populate cache
2913e457fe3SDavid van Moolenbroek     if(isConstant) {
2923e457fe3SDavid van Moolenbroek         arrayRefCache.insert(std::pair<std::vector<std::string>, GlobalVariable*>(*arr, arrayRef));
2933e457fe3SDavid van Moolenbroek     }
2943e457fe3SDavid van Moolenbroek 
2953e457fe3SDavid van Moolenbroek     return arrayRef;
2963e457fe3SDavid van Moolenbroek }
2973e457fe3SDavid van Moolenbroek 
getGenericArrayRef(Module & M,std::vector<Constant * > & arrayElems,bool isConstant)2983e457fe3SDavid van Moolenbroek GlobalVariable *MagicUtil::getGenericArrayRef(Module &M, std::vector<Constant*> &arrayElems, bool isConstant) {
2993e457fe3SDavid van Moolenbroek     static std::map<std::vector<Constant*>, GlobalVariable*> arrayRefCache;
3003e457fe3SDavid van Moolenbroek     std::map<std::vector<Constant*>, GlobalVariable*>::iterator it;
3013e457fe3SDavid van Moolenbroek     assert(arrayElems.size() > 0);
3023e457fe3SDavid van Moolenbroek 
3033e457fe3SDavid van Moolenbroek     //cache lookup
3043e457fe3SDavid van Moolenbroek     if(isConstant) {
3053e457fe3SDavid van Moolenbroek         it = arrayRefCache.find(arrayElems);
3063e457fe3SDavid van Moolenbroek         if(it != arrayRefCache.end()) {
3073e457fe3SDavid van Moolenbroek             return it->second;
3083e457fe3SDavid van Moolenbroek         }
3093e457fe3SDavid van Moolenbroek     }
3103e457fe3SDavid van Moolenbroek 
3113e457fe3SDavid van Moolenbroek     //create a constant internal array reference
3123e457fe3SDavid van Moolenbroek     ArrayType* arrayTy = ArrayType::get(arrayElems[0]->getType(), arrayElems.size());
3133e457fe3SDavid van Moolenbroek     Constant *arrayValue = ConstantArray::get(arrayTy, arrayElems);
3143e457fe3SDavid van Moolenbroek 
3153e457fe3SDavid van Moolenbroek     //create the global variable and record it in the module
3163e457fe3SDavid van Moolenbroek     GlobalVariable *arrayRef = new GlobalVariable(arrayValue->getType(), isConstant,
3173e457fe3SDavid van Moolenbroek         GlobalValue::InternalLinkage, arrayValue,
3183e457fe3SDavid van Moolenbroek         MAGIC_HIDDEN_ARRAY_PREFIX);
3193e457fe3SDavid van Moolenbroek     MagicUtil::setGlobalVariableSection(arrayRef, isConstant ? MAGIC_STATIC_VARS_SECTION_RO : MAGIC_STATIC_VARS_SECTION_DATA);
3203e457fe3SDavid van Moolenbroek     M.getGlobalList().push_back(arrayRef);
3213e457fe3SDavid van Moolenbroek 
3223e457fe3SDavid van Moolenbroek     //populate cache
3233e457fe3SDavid van Moolenbroek     if(isConstant) {
3243e457fe3SDavid van Moolenbroek         arrayRefCache.insert(std::pair<std::vector<Constant*>, GlobalVariable*>(arrayElems, arrayRef));
3253e457fe3SDavid van Moolenbroek     }
3263e457fe3SDavid van Moolenbroek 
3273e457fe3SDavid van Moolenbroek     return arrayRef;
3283e457fe3SDavid van Moolenbroek }
3293e457fe3SDavid van Moolenbroek 
getMagicTypePtrArrayRef(Module & M,Instruction * InsertBefore,std::vector<Value * > & globalTypeIndexes,GlobalVariable * magicTypeArray)3303e457fe3SDavid van Moolenbroek GlobalVariable *MagicUtil::getMagicTypePtrArrayRef(Module &M, Instruction *InsertBefore, std::vector<Value*> &globalTypeIndexes, GlobalVariable *magicTypeArray) {
3313e457fe3SDavid van Moolenbroek     int numTypeIndexes = globalTypeIndexes.size();
3323e457fe3SDavid van Moolenbroek     TYPECONST StructType* magicTypeStructTy = (TYPECONST StructType*) ((TYPECONST ArrayType*)magicTypeArray->getType()->getElementType())->getElementType();
3333e457fe3SDavid van Moolenbroek     ArrayType* typeIndexesArrTy = ArrayType::get(PointerType::get(magicTypeStructTy, 0), numTypeIndexes+1);
3343e457fe3SDavid van Moolenbroek     std::vector<Constant*> arrayElems;
3353e457fe3SDavid van Moolenbroek     for(int i=0;i<numTypeIndexes;i++) {
3363e457fe3SDavid van Moolenbroek         std::vector<Value*> magicTypeArrayIndexes;
3373e457fe3SDavid van Moolenbroek         magicTypeArrayIndexes.clear();
3383e457fe3SDavid van Moolenbroek         magicTypeArrayIndexes.push_back(ConstantInt::get(M.getContext(), APInt(64, 0, 10)));
3393e457fe3SDavid van Moolenbroek         magicTypeArrayIndexes.push_back(globalTypeIndexes[i]);
3403e457fe3SDavid van Moolenbroek         Constant* typePtr = getGetElementPtrConstant(magicTypeArray, magicTypeArrayIndexes);
3413e457fe3SDavid van Moolenbroek         arrayElems.push_back(typePtr);
3423e457fe3SDavid van Moolenbroek     }
3433e457fe3SDavid van Moolenbroek     arrayElems.push_back(ConstantPointerNull::get(PointerType::get(magicTypeStructTy, 0))); //NULL-terminated array
3443e457fe3SDavid van Moolenbroek 
3453e457fe3SDavid van Moolenbroek     //create the global variable and record it in the module
3463e457fe3SDavid van Moolenbroek     Constant *arrayValue = ConstantArray::get(typeIndexesArrTy, arrayElems);
3473e457fe3SDavid van Moolenbroek     GlobalVariable *arrayRef = new GlobalVariable(arrayValue->getType(), true,
3483e457fe3SDavid van Moolenbroek         GlobalValue::InternalLinkage, arrayValue,
3493e457fe3SDavid van Moolenbroek         MAGIC_HIDDEN_ARRAY_PREFIX);
3503e457fe3SDavid van Moolenbroek     MagicUtil::setGlobalVariableSection(arrayRef, MAGIC_STATIC_VARS_SECTION_RO);
3513e457fe3SDavid van Moolenbroek     M.getGlobalList().push_back(arrayRef);
3523e457fe3SDavid van Moolenbroek 
3533e457fe3SDavid van Moolenbroek     return arrayRef;
3543e457fe3SDavid van Moolenbroek }
3553e457fe3SDavid van Moolenbroek 
getExportedIntGlobalVar(Module & M,std::string name,int value,bool isConstant)3563e457fe3SDavid van Moolenbroek GlobalVariable* MagicUtil::getExportedIntGlobalVar(Module &M, std::string name, int value, bool isConstant) {
3573e457fe3SDavid van Moolenbroek     Constant *intValue = ConstantInt::get(M.getContext(), APInt(32, value, 10));
3583e457fe3SDavid van Moolenbroek 
3593e457fe3SDavid van Moolenbroek     //create the global variable and record it in the module
3603e457fe3SDavid van Moolenbroek     GlobalVariable *GV = new GlobalVariable(intValue->getType(), isConstant,
3613e457fe3SDavid van Moolenbroek         GlobalValue::LinkOnceAnyLinkage, intValue, name);
3623e457fe3SDavid van Moolenbroek     MagicUtil::setGlobalVariableSection(GV, isConstant ? MAGIC_STATIC_VARS_SECTION_RO : MAGIC_STATIC_VARS_SECTION_DATA);
3633e457fe3SDavid van Moolenbroek     M.getGlobalList().push_back(GV);
3643e457fe3SDavid van Moolenbroek 
3653e457fe3SDavid van Moolenbroek     return GV;
3663e457fe3SDavid van Moolenbroek }
3673e457fe3SDavid van Moolenbroek 
getShadowRef(Module & M,GlobalVariable * GV)3683e457fe3SDavid van Moolenbroek GlobalVariable* MagicUtil::getShadowRef(Module &M, GlobalVariable *GV) {
3693e457fe3SDavid van Moolenbroek     //create the shadow global variable and record it in the module
3703e457fe3SDavid van Moolenbroek     TYPECONST Type* type = GV->getType()->getElementType();
3713e457fe3SDavid van Moolenbroek     GlobalVariable *SGV = new GlobalVariable(type, GV->isConstant(),
3723e457fe3SDavid van Moolenbroek                                           GlobalValue::InternalLinkage, 0,
3733e457fe3SDavid van Moolenbroek                                           MAGIC_SHADOW_VAR_PREFIX + GV->getName());
3743e457fe3SDavid van Moolenbroek     SGV->setInitializer(Constant::getNullValue(type));
3753e457fe3SDavid van Moolenbroek     MagicUtil::setGlobalVariableSection(SGV, GV->isConstant() ? MAGIC_SHADOW_VARS_SECTION_RO : MAGIC_SHADOW_VARS_SECTION_DATA);
3763e457fe3SDavid van Moolenbroek     M.getGlobalList().push_back(SGV);
3773e457fe3SDavid van Moolenbroek 
3783e457fe3SDavid van Moolenbroek     if(!GV->hasInitializer()) {
3793e457fe3SDavid van Moolenbroek         magicUtilLog("Shadowing for extern variable: " << GV->getName());
3803e457fe3SDavid van Moolenbroek     }
3813e457fe3SDavid van Moolenbroek     if(GV->isConstant()) {
3823e457fe3SDavid van Moolenbroek         magicUtilLog("Shadowing for constant variable: " << GV->getName());
3833e457fe3SDavid van Moolenbroek     }
3843e457fe3SDavid van Moolenbroek 
3853e457fe3SDavid van Moolenbroek     return SGV;
3863e457fe3SDavid van Moolenbroek }
3873e457fe3SDavid van Moolenbroek 
getMagicStructFieldPtr(Module & M,Instruction * InsertBefore,GlobalVariable * var,Value * arrayIndex,const std::string & structFieldName,std::string * structFieldNames)3883e457fe3SDavid van Moolenbroek Value* MagicUtil::getMagicStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* var, Value* arrayIndex, const std::string &structFieldName, std::string *structFieldNames) {
3893e457fe3SDavid van Moolenbroek     //lookup field index
3903e457fe3SDavid van Moolenbroek     int structFieldIndex;
3913e457fe3SDavid van Moolenbroek     Value *varPtr;
3923e457fe3SDavid van Moolenbroek     for(structFieldIndex=0; structFieldName.compare(structFieldNames[structFieldIndex]) != 0; structFieldIndex++) {}
3933e457fe3SDavid van Moolenbroek 
3943e457fe3SDavid van Moolenbroek     if(arrayIndex) {
3953e457fe3SDavid van Moolenbroek         //get array ptr
3963e457fe3SDavid van Moolenbroek         std::vector<Value*> arrayIndexes;
3973e457fe3SDavid van Moolenbroek         arrayIndexes.push_back(ConstantInt::get(M.getContext(), APInt(64, 0, 10)));
3983e457fe3SDavid van Moolenbroek         arrayIndexes.push_back(arrayIndex);
3993e457fe3SDavid van Moolenbroek         varPtr = createGetElementPtrInstruction(var, arrayIndexes, "", InsertBefore);
4003e457fe3SDavid van Moolenbroek     }
4013e457fe3SDavid van Moolenbroek     else {
4023e457fe3SDavid van Moolenbroek     	varPtr = var;
4033e457fe3SDavid van Moolenbroek     }
4043e457fe3SDavid van Moolenbroek 
4053e457fe3SDavid van Moolenbroek     //get struct field ptr
4063e457fe3SDavid van Moolenbroek     std::vector<Value*> structFieldIndexes;
4073e457fe3SDavid van Moolenbroek     structFieldIndexes.push_back(ConstantInt::get(M.getContext(), APInt(32, 0, 10)));
4083e457fe3SDavid van Moolenbroek     structFieldIndexes.push_back(ConstantInt::get(M.getContext(), APInt(32, structFieldIndex, 10)));
4093e457fe3SDavid van Moolenbroek     Instruction* structFieldPtr = createGetElementPtrInstruction(varPtr, structFieldIndexes, "", InsertBefore);
4103e457fe3SDavid van Moolenbroek 
4113e457fe3SDavid van Moolenbroek     return structFieldPtr;
4123e457fe3SDavid van Moolenbroek }
4133e457fe3SDavid van Moolenbroek 
getMagicSStructFieldPtr(Module & M,Instruction * InsertBefore,GlobalVariable * magicArray,Value * magicArrayIndex,const std::string & structFieldName)4143e457fe3SDavid van Moolenbroek Value* MagicUtil::getMagicSStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* magicArray, Value* magicArrayIndex, const std::string &structFieldName) {
4153e457fe3SDavid van Moolenbroek     static std::string structFieldNames[] = { MAGIC_SSTRUCT_FIELDS };
4163e457fe3SDavid van Moolenbroek     return getMagicStructFieldPtr(M, InsertBefore, magicArray, magicArrayIndex, structFieldName, structFieldNames);
4173e457fe3SDavid van Moolenbroek }
4183e457fe3SDavid van Moolenbroek 
getMagicTStructFieldPtr(Module & M,Instruction * InsertBefore,GlobalVariable * magicTypeArray,Value * magicTypeArrayIndex,const std::string & structFieldName)4193e457fe3SDavid van Moolenbroek Value* MagicUtil::getMagicTStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* magicTypeArray, Value* magicTypeArrayIndex, const std::string &structFieldName) {
4203e457fe3SDavid van Moolenbroek     static std::string structFieldNames[] = { MAGIC_TSTRUCT_FIELDS };
4213e457fe3SDavid van Moolenbroek     return getMagicStructFieldPtr(M, InsertBefore, magicTypeArray, magicTypeArrayIndex, structFieldName, structFieldNames);
4223e457fe3SDavid van Moolenbroek }
4233e457fe3SDavid van Moolenbroek 
getMagicFStructFieldPtr(Module & M,Instruction * InsertBefore,GlobalVariable * magicFunctionArray,Value * magicFunctionArrayIndex,const std::string & structFieldName)4243e457fe3SDavid van Moolenbroek Value* MagicUtil::getMagicFStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* magicFunctionArray, Value* magicFunctionArrayIndex, const std::string &structFieldName) {
4253e457fe3SDavid van Moolenbroek     static std::string structFieldNames[] = { MAGIC_FSTRUCT_FIELDS };
4263e457fe3SDavid van Moolenbroek     return getMagicStructFieldPtr(M, InsertBefore, magicFunctionArray, magicFunctionArrayIndex, structFieldName, structFieldNames);
4273e457fe3SDavid van Moolenbroek }
4283e457fe3SDavid van Moolenbroek 
getMagicRStructFieldPtr(Module & M,Instruction * InsertBefore,GlobalVariable * magicVar,const std::string & structFieldName)4293e457fe3SDavid van Moolenbroek Value* MagicUtil::getMagicRStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* magicVar, const std::string &structFieldName) {
4303e457fe3SDavid van Moolenbroek     static std::string structFieldNames[] = { MAGIC_RSTRUCT_FIELDS };
4313e457fe3SDavid van Moolenbroek     return getMagicStructFieldPtr(M, InsertBefore, magicVar, NULL, structFieldName, structFieldNames);
4323e457fe3SDavid van Moolenbroek }
4333e457fe3SDavid van Moolenbroek 
getMagicDStructFieldPtr(Module & M,Instruction * InsertBefore,GlobalVariable * magicDsindexArray,Value * magicDsindexArrayIndex,const std::string & structFieldName)4343e457fe3SDavid van Moolenbroek Value* MagicUtil::getMagicDStructFieldPtr(Module &M, Instruction *InsertBefore, GlobalVariable* magicDsindexArray, Value* magicDsindexArrayIndex, const std::string &structFieldName) {
4353e457fe3SDavid van Moolenbroek     static std::string structFieldNames[] = { MAGIC_DSTRUCT_FIELDS };
4363e457fe3SDavid van Moolenbroek     return getMagicStructFieldPtr(M, InsertBefore, magicDsindexArray, magicDsindexArrayIndex, structFieldName, structFieldNames);
4373e457fe3SDavid van Moolenbroek }
4383e457fe3SDavid van Moolenbroek 
getArrayPtr(Module & M,GlobalVariable * array)4393e457fe3SDavid van Moolenbroek Constant* MagicUtil::getArrayPtr(Module &M, GlobalVariable* array) {
4403e457fe3SDavid van Moolenbroek     //indexes for array
4413e457fe3SDavid van Moolenbroek     static std::vector<Value*> arrayIndexes;
4423e457fe3SDavid van Moolenbroek     if(arrayIndexes.empty()) {
4433e457fe3SDavid van Moolenbroek         arrayIndexes.push_back(ConstantInt::get(M.getContext(), APInt(64, 0, 10))); //pointer to A[]
4443e457fe3SDavid van Moolenbroek         arrayIndexes.push_back(ConstantInt::get(M.getContext(), APInt(64, 0, 10))); //pointer to A[0]
4453e457fe3SDavid van Moolenbroek     }
4463e457fe3SDavid van Moolenbroek 
4473e457fe3SDavid van Moolenbroek     //get array ptr
4483e457fe3SDavid van Moolenbroek     Constant* arrayPtr = getGetElementPtrConstant(array, arrayIndexes);
4493e457fe3SDavid van Moolenbroek 
4503e457fe3SDavid van Moolenbroek     return arrayPtr;
4513e457fe3SDavid van Moolenbroek }
4523e457fe3SDavid van Moolenbroek 
insertMemcpyInst(Module & M,Instruction * InsertBefore,Value * Dst,Value * Src,Value * Len,unsigned Align)4533e457fe3SDavid van Moolenbroek void MagicUtil::insertMemcpyInst(Module &M, Instruction *InsertBefore, Value *Dst, Value *Src, Value *Len, unsigned Align) {
4543e457fe3SDavid van Moolenbroek     bool useMemCpyIntrinsics = false;
4553e457fe3SDavid van Moolenbroek     Function *MemCpy = M.getFunction("memcpy");
4563e457fe3SDavid van Moolenbroek     if(!MemCpy) {
4573e457fe3SDavid van Moolenbroek         TYPECONST Type *ArgTys[1] = { IntegerType::getInt32Ty(M.getContext()) };
4583e457fe3SDavid van Moolenbroek         MemCpy = getIntrinsicFunction(M, Intrinsic::memcpy, ArgTys, 1);
4593e457fe3SDavid van Moolenbroek         useMemCpyIntrinsics = true;
4603e457fe3SDavid van Moolenbroek     }
4613e457fe3SDavid van Moolenbroek     else {
4623e457fe3SDavid van Moolenbroek         MemCpy = (Function*) M.getOrInsertFunction(MAGIC_MEMCPY_FUNC_NAME, MemCpy->getFunctionType());
4633e457fe3SDavid van Moolenbroek     }
4643e457fe3SDavid van Moolenbroek 
4653e457fe3SDavid van Moolenbroek     // Insert the memcpy instruction
4663e457fe3SDavid van Moolenbroek     std::vector<Value*> MemCpyArgs;
4673e457fe3SDavid van Moolenbroek     MemCpyArgs.push_back(Dst);
4683e457fe3SDavid van Moolenbroek     MemCpyArgs.push_back(Src);
4693e457fe3SDavid van Moolenbroek     MemCpyArgs.push_back(Len);
4703e457fe3SDavid van Moolenbroek     if(useMemCpyIntrinsics) {
4713e457fe3SDavid van Moolenbroek         MemCpyArgs.push_back(ConstantInt::get(M.getContext(), APInt(32, Align, 10)));
4723e457fe3SDavid van Moolenbroek     }
4733e457fe3SDavid van Moolenbroek     createCallInstruction(MemCpy, MemCpyArgs, "", InsertBefore);
4743e457fe3SDavid van Moolenbroek }
4753e457fe3SDavid van Moolenbroek 
insertCopyInst(Module & M,Instruction * InsertBefore,GlobalVariable * GV,GlobalVariable * SGV,int GVSize,bool forceMemcpy)4763e457fe3SDavid van Moolenbroek void MagicUtil::insertCopyInst(Module &M, Instruction *InsertBefore, GlobalVariable *GV, GlobalVariable *SGV, int GVSize, bool forceMemcpy) {
4773e457fe3SDavid van Moolenbroek     //get type and type size
4783e457fe3SDavid van Moolenbroek     TYPECONST Type *GVType = GV->getType()->getElementType();
4793e457fe3SDavid van Moolenbroek     bool isPrimitiveOrPointerType = !GVType->isAggregateType();
4803e457fe3SDavid van Moolenbroek 
4813e457fe3SDavid van Moolenbroek     //no need for memcpy for primitive types or pointer types
4823e457fe3SDavid van Moolenbroek     if(isPrimitiveOrPointerType && !forceMemcpy) {
4833e457fe3SDavid van Moolenbroek         LoadInst* primitiveValue = new LoadInst(GV, "", false, InsertBefore);
4843e457fe3SDavid van Moolenbroek         new StoreInst(primitiveValue, SGV, false, InsertBefore);
4853e457fe3SDavid van Moolenbroek         return;
4863e457fe3SDavid van Moolenbroek     }
4873e457fe3SDavid van Moolenbroek 
4883e457fe3SDavid van Moolenbroek     //cast pointers to match memcpy prototype
4893e457fe3SDavid van Moolenbroek     PointerType* voidPointerType = PointerType::get(IntegerType::get(M.getContext(), 8), 0);
4903e457fe3SDavid van Moolenbroek     Constant* varAddress = ConstantExpr::getCast(Instruction::BitCast, GV, voidPointerType);
4913e457fe3SDavid van Moolenbroek     Constant* varShadowAddress = ConstantExpr::getCast(Instruction::BitCast, SGV, voidPointerType);
4923e457fe3SDavid van Moolenbroek 
4933e457fe3SDavid van Moolenbroek     //insert the memcpy instruction
4943e457fe3SDavid van Moolenbroek     MagicUtil::insertMemcpyInst(M, InsertBefore, varShadowAddress, varAddress, ConstantInt::get(M.getContext(), APInt(32, GVSize, 10)), 0);
4953e457fe3SDavid van Moolenbroek }
4963e457fe3SDavid van Moolenbroek 
getCalledFunctionFromCS(const CallSite & CS)4973e457fe3SDavid van Moolenbroek Function* MagicUtil::getCalledFunctionFromCS(const CallSite &CS) {
4983e457fe3SDavid van Moolenbroek     assert(CS.getInstruction());
4993e457fe3SDavid van Moolenbroek     Function *function = CS.getCalledFunction();
5003e457fe3SDavid van Moolenbroek     if(function) {
5013e457fe3SDavid van Moolenbroek         return function;
5023e457fe3SDavid van Moolenbroek     }
5033e457fe3SDavid van Moolenbroek 
5043e457fe3SDavid van Moolenbroek     //handle the weird case of bitcasted function call
5053e457fe3SDavid van Moolenbroek     //IMPORTANT! function may still be null, if it's an indirect call
5063e457fe3SDavid van Moolenbroek     ConstantExpr *CE = dyn_cast<ConstantExpr>(CS.getCalledValue());
5073e457fe3SDavid van Moolenbroek     if (CE) {
5083e457fe3SDavid van Moolenbroek         assert(CE->getOpcode() == Instruction::BitCast && "Bitcast expected, something else found!");
5093e457fe3SDavid van Moolenbroek         function = dyn_cast<Function>(CE->getOperand(0));
5103e457fe3SDavid van Moolenbroek         assert(function);
5113e457fe3SDavid van Moolenbroek     } else {
5123e457fe3SDavid van Moolenbroek         errs() << "Warning! Indirect call encountered!\n";
5133e457fe3SDavid van Moolenbroek     }
5143e457fe3SDavid van Moolenbroek 
5153e457fe3SDavid van Moolenbroek     return function;
5163e457fe3SDavid van Moolenbroek }
5173e457fe3SDavid van Moolenbroek 
replaceCallInst(Instruction * originalInst,CallInst * newInst,int argOffset,bool removeUnusedFunction)5183e457fe3SDavid van Moolenbroek void MagicUtil::replaceCallInst(Instruction *originalInst, CallInst *newInst, int argOffset, bool removeUnusedFunction) {
5193e457fe3SDavid van Moolenbroek     SmallVector< std::pair< unsigned, MDNode * >, 8> MDs;
5203e457fe3SDavid van Moolenbroek     originalInst->getAllMetadata(MDs);
5213e457fe3SDavid van Moolenbroek     for(unsigned i=0;i<MDs.size();i++) {
5223e457fe3SDavid van Moolenbroek         newInst->setMetadata(MDs[i].first, MDs[i].second);
5233e457fe3SDavid van Moolenbroek     }
5243e457fe3SDavid van Moolenbroek     CallSite CS = MagicUtil::getCallSiteFromInstruction(originalInst);
5253e457fe3SDavid van Moolenbroek     assert(CS);
5263e457fe3SDavid van Moolenbroek     CallingConv::ID CC = CS.getCallingConv();
5273e457fe3SDavid van Moolenbroek     Function *originalFunction = getCalledFunctionFromCS(CS);
5283e457fe3SDavid van Moolenbroek     newInst->setCallingConv(CC);
5293e457fe3SDavid van Moolenbroek     ATTRIBUTE_SET_TY NewAttrs = PassUtil::remapCallSiteAttributes(CS, argOffset);
5303e457fe3SDavid van Moolenbroek     newInst->setAttributes(NewAttrs);
5313e457fe3SDavid van Moolenbroek 
5323e457fe3SDavid van Moolenbroek     originalInst->replaceAllUsesWith(newInst);
5333e457fe3SDavid van Moolenbroek 
5343e457fe3SDavid van Moolenbroek     // If the old instruction was an invoke, add an unconditional branch
5353e457fe3SDavid van Moolenbroek     // before the invoke, which will become the new terminator.
5363e457fe3SDavid van Moolenbroek     if (InvokeInst *II = dyn_cast<InvokeInst>(originalInst))
5373e457fe3SDavid van Moolenbroek       BranchInst::Create(II->getNormalDest(), originalInst);
5383e457fe3SDavid van Moolenbroek 
5393e457fe3SDavid van Moolenbroek     // Delete the old call site
5403e457fe3SDavid van Moolenbroek     originalInst->eraseFromParent();
5413e457fe3SDavid van Moolenbroek 
5423e457fe3SDavid van Moolenbroek     // When asked, remove the original function when nobody uses it any more.
5433e457fe3SDavid van Moolenbroek     if(removeUnusedFunction && originalFunction->use_empty()) {
5443e457fe3SDavid van Moolenbroek         originalFunction->eraseFromParent();
5453e457fe3SDavid van Moolenbroek     }
5463e457fe3SDavid van Moolenbroek }
5473e457fe3SDavid van Moolenbroek 
getGlobalVariablesShadowFunctions(Module & M,std::vector<GlobalVariable * > globalVariables,std::vector<GlobalVariable * > shadowGlobalVariables,std::vector<int> globalVariableSizes,GlobalVariable * magicArray,int magicArraySize,bool forceShadow,bool setDirtyFlag)5483e457fe3SDavid van Moolenbroek std::vector<Function*> MagicUtil::getGlobalVariablesShadowFunctions(Module &M, std::vector<GlobalVariable*> globalVariables, std::vector<GlobalVariable*> shadowGlobalVariables, std::vector<int> globalVariableSizes, GlobalVariable* magicArray, int magicArraySize, bool forceShadow, bool setDirtyFlag) {
5493e457fe3SDavid van Moolenbroek     std::vector<Function*> globalVariableShadowFunctions;
5503e457fe3SDavid van Moolenbroek     for(int i=0;i<magicArraySize;i++) {
5513e457fe3SDavid van Moolenbroek         Function* func = getGlobalVariableShadowFunction(M, globalVariables[i], shadowGlobalVariables[i], globalVariableSizes[i], magicArray, i, forceShadow, setDirtyFlag);
5523e457fe3SDavid van Moolenbroek         globalVariableShadowFunctions.push_back(func);
5533e457fe3SDavid van Moolenbroek     }
5543e457fe3SDavid van Moolenbroek 
5553e457fe3SDavid van Moolenbroek     return globalVariableShadowFunctions;
5563e457fe3SDavid van Moolenbroek }
5573e457fe3SDavid van Moolenbroek 
getGlobalVariableShadowFunction(Module & M,GlobalVariable * GV,GlobalVariable * SGV,int GVSize,GlobalVariable * magicArray,int magicArrayIndex,bool forceShadow,bool setDirtyFlag)5583e457fe3SDavid van Moolenbroek Function* MagicUtil::getGlobalVariableShadowFunction(Module &M, GlobalVariable* GV, GlobalVariable* SGV, int GVSize, GlobalVariable* magicArray, int magicArrayIndex, bool forceShadow, bool setDirtyFlag) {
5593e457fe3SDavid van Moolenbroek     static Constant* magicStateDirty = ConstantInt::get(M.getContext(), APInt(32, MAGIC_STATE_DIRTY, 10));
5603e457fe3SDavid van Moolenbroek     static Function* shadowFunc = NULL;
5613e457fe3SDavid van Moolenbroek     ConstantInt* magicArrayIndexConst = ConstantInt::get(M.getContext(), APInt(32, magicArrayIndex, 10));
5623e457fe3SDavid van Moolenbroek 
5633e457fe3SDavid van Moolenbroek     //determine name
5643e457fe3SDavid van Moolenbroek     std::string name(MAGIC_SHADOW_FUNC_PREFIX);
5653e457fe3SDavid van Moolenbroek     name.append("_");
5663e457fe3SDavid van Moolenbroek     if(forceShadow) {
5673e457fe3SDavid van Moolenbroek         name.append("force_");
5683e457fe3SDavid van Moolenbroek     }
5693e457fe3SDavid van Moolenbroek     if(setDirtyFlag) {
5703e457fe3SDavid van Moolenbroek         name.append("setdf_");
5713e457fe3SDavid van Moolenbroek     }
5723e457fe3SDavid van Moolenbroek     name.append(GV->getName());
5733e457fe3SDavid van Moolenbroek 
5743e457fe3SDavid van Moolenbroek     //create function
5753e457fe3SDavid van Moolenbroek     std::vector<TYPECONST Type*>shadowFuncArgs;
5763e457fe3SDavid van Moolenbroek     FunctionType* shadowFuncType = FunctionType::get(Type::getVoidTy(M.getContext()), shadowFuncArgs, false);
5773e457fe3SDavid van Moolenbroek     shadowFunc = Function::Create(shadowFuncType, GlobalValue::InternalLinkage, name, &M);
5783e457fe3SDavid van Moolenbroek     shadowFunc->setCallingConv(CallingConv::C);
5793e457fe3SDavid van Moolenbroek 
5803e457fe3SDavid van Moolenbroek     //create blocks
5813e457fe3SDavid van Moolenbroek     BasicBlock* label_entry = BasicBlock::Create(M.getContext(), "entry",shadowFunc,0);
5823e457fe3SDavid van Moolenbroek     BasicBlock* label_shadow = BasicBlock::Create(M.getContext(), "shadow",shadowFunc,0);
5833e457fe3SDavid van Moolenbroek     BasicBlock* label_return = BasicBlock::Create(M.getContext(), "return",shadowFunc,0);
5843e457fe3SDavid van Moolenbroek     BranchInst::Create(label_shadow, label_entry);
5853e457fe3SDavid van Moolenbroek     BranchInst::Create(label_return, label_shadow);
5863e457fe3SDavid van Moolenbroek     Instruction* entryTerm = label_entry->getTerminator();
5873e457fe3SDavid van Moolenbroek     Instruction* shadowTerm = label_shadow->getTerminator();
5883e457fe3SDavid van Moolenbroek 
5893e457fe3SDavid van Moolenbroek     if(!forceShadow || setDirtyFlag) {
5903e457fe3SDavid van Moolenbroek         //get flags
5913e457fe3SDavid van Moolenbroek         Value* structFlagsField = MagicUtil::getMagicSStructFieldPtr(M, entryTerm, magicArray, magicArrayIndexConst, MAGIC_SSTRUCT_FIELD_FLAGS);
5923e457fe3SDavid van Moolenbroek         LoadInst* varFlags = new LoadInst(structFlagsField, "", false, entryTerm);
5933e457fe3SDavid van Moolenbroek 
5943e457fe3SDavid van Moolenbroek         //when not forcing, don't shadow if dirty is already set
5953e457fe3SDavid van Moolenbroek         if(!forceShadow) {
5963e457fe3SDavid van Moolenbroek             BinaryOperator* andedVarFlags = BinaryOperator::Create(Instruction::And, varFlags, magicStateDirty, "", entryTerm);
5973e457fe3SDavid van Moolenbroek             ICmpInst* flagsCmp = new ICmpInst(entryTerm, ICmpInst::ICMP_EQ, andedVarFlags, ConstantInt::get(M.getContext(), APInt(32, 0, 10)), "");
5983e457fe3SDavid van Moolenbroek             BranchInst::Create(label_shadow, label_return, flagsCmp, entryTerm);
5993e457fe3SDavid van Moolenbroek             entryTerm->eraseFromParent();
6003e457fe3SDavid van Moolenbroek         }
6013e457fe3SDavid van Moolenbroek 
6023e457fe3SDavid van Moolenbroek         //set the dirty flag for the variable
6033e457fe3SDavid van Moolenbroek         if(setDirtyFlag) {
6043e457fe3SDavid van Moolenbroek             BinaryOperator* oredVarFlags = BinaryOperator::Create(Instruction::Or, varFlags, magicStateDirty, "", shadowTerm);
6053e457fe3SDavid van Moolenbroek             new StoreInst(oredVarFlags, structFlagsField, false, shadowTerm);
6063e457fe3SDavid van Moolenbroek         }
6073e457fe3SDavid van Moolenbroek     }
6083e457fe3SDavid van Moolenbroek 
6093e457fe3SDavid van Moolenbroek     //perform a memory copy from the original variable to the shadow variable
6103e457fe3SDavid van Moolenbroek     MagicUtil::insertCopyInst(M, shadowTerm, GV, SGV, GVSize, /* forceMemcpy */ false);
6113e457fe3SDavid van Moolenbroek 
6123e457fe3SDavid van Moolenbroek     ReturnInst::Create(M.getContext(), label_return);
6133e457fe3SDavid van Moolenbroek 
6143e457fe3SDavid van Moolenbroek     return shadowFunc;
6153e457fe3SDavid van Moolenbroek }
6163e457fe3SDavid van Moolenbroek 
insertGlobalVariableCleanDirtyFlag(Module & M,GlobalVariable * GV,GlobalVariable * magicArray,int magicArrayIndex,Instruction * InsertBefore)6173e457fe3SDavid van Moolenbroek void MagicUtil::insertGlobalVariableCleanDirtyFlag(Module &M, GlobalVariable* GV, GlobalVariable* magicArray, int magicArrayIndex, Instruction *InsertBefore) {
6183e457fe3SDavid van Moolenbroek     Value* structFlagsField = MagicUtil::getMagicSStructFieldPtr(M, InsertBefore, magicArray, ConstantInt::get(M.getContext(), APInt(32, magicArrayIndex, 10)), MAGIC_SSTRUCT_FIELD_FLAGS);
6193e457fe3SDavid van Moolenbroek     new StoreInst(ConstantInt::get(M.getContext(), APInt(32, 0, 10)), structFlagsField, false, InsertBefore);
6203e457fe3SDavid van Moolenbroek }
6213e457fe3SDavid van Moolenbroek 
insertShadowTag(Module & M,GlobalVariable * GV,Instruction * InsertBefore)6223e457fe3SDavid van Moolenbroek void MagicUtil::insertShadowTag(Module &M, GlobalVariable *GV, Instruction *InsertBefore) {
6233e457fe3SDavid van Moolenbroek     static Function* shadowFunc = NULL;
6243e457fe3SDavid van Moolenbroek     PointerType* voidPointerType = PointerType::get(IntegerType::get(M.getContext(), 8), 0);
6253e457fe3SDavid van Moolenbroek 
6263e457fe3SDavid van Moolenbroek     //create function
6273e457fe3SDavid van Moolenbroek     if(!shadowFunc) {
6283e457fe3SDavid van Moolenbroek             std::vector<TYPECONST Type*>shadowFuncArgs;
6293e457fe3SDavid van Moolenbroek             shadowFuncArgs.push_back(voidPointerType);
6303e457fe3SDavid van Moolenbroek             FunctionType* shadowFuncType = FunctionType::get(Type::getVoidTy(M.getContext()), shadowFuncArgs, false);
6313e457fe3SDavid van Moolenbroek             shadowFunc = Function::Create(shadowFuncType, GlobalValue::ExternalLinkage, MAGIC_LAZY_CHECKPOINT_SHADOW_TAG, &M);
6323e457fe3SDavid van Moolenbroek             shadowFunc->setCallingConv(CallingConv::C);
6333e457fe3SDavid van Moolenbroek     }
6343e457fe3SDavid van Moolenbroek 
6353e457fe3SDavid van Moolenbroek     //shadow global variable
6363e457fe3SDavid van Moolenbroek     std::vector<Value*> args;
6373e457fe3SDavid van Moolenbroek     args.push_back(new BitCastInst(GV, voidPointerType, "", InsertBefore));
6383e457fe3SDavid van Moolenbroek     CallInst *callInst = createCallInstruction(shadowFunc, args, "", InsertBefore);
6393e457fe3SDavid van Moolenbroek     callInst->setCallingConv(CallingConv::C);
6403e457fe3SDavid van Moolenbroek }
6413e457fe3SDavid van Moolenbroek 
isShadowTag(Instruction * inst)6423e457fe3SDavid van Moolenbroek bool MagicUtil::isShadowTag(Instruction *inst) {
6433e457fe3SDavid van Moolenbroek     if(dyn_cast<CallInst>(inst)) {
6443e457fe3SDavid van Moolenbroek             CallInst *callInst = dyn_cast<CallInst>(inst);
6453e457fe3SDavid van Moolenbroek             Function *function = callInst->getCalledFunction();
6463e457fe3SDavid van Moolenbroek             if(function == NULL) {
6473e457fe3SDavid van Moolenbroek                     return false;
6483e457fe3SDavid van Moolenbroek             }
6493e457fe3SDavid van Moolenbroek             std::string funcName = function->getName();
6503e457fe3SDavid van Moolenbroek             if(!funcName.compare(MAGIC_LAZY_CHECKPOINT_SHADOW_TAG)) {
6513e457fe3SDavid van Moolenbroek                     return true;
6523e457fe3SDavid van Moolenbroek             }
6533e457fe3SDavid van Moolenbroek     }
6543e457fe3SDavid van Moolenbroek     return false;
6553e457fe3SDavid van Moolenbroek }
6563e457fe3SDavid van Moolenbroek 
getGlobalVariableFromShadowTag(Instruction * inst,std::vector<Instruction * > & instructionsToRemove)6573e457fe3SDavid van Moolenbroek GlobalVariable* MagicUtil::getGlobalVariableFromShadowTag(Instruction *inst, std::vector<Instruction*> &instructionsToRemove) {
6583e457fe3SDavid van Moolenbroek     CallSite CS = MagicUtil::getCallSiteFromInstruction(inst);
6593e457fe3SDavid van Moolenbroek     assert(CS.arg_size() == 1);
6603e457fe3SDavid van Moolenbroek     instructionsToRemove.push_back(inst);
6613e457fe3SDavid van Moolenbroek     CallSite::arg_iterator AI = CS.arg_begin();
6623e457fe3SDavid van Moolenbroek     Value *ActualArg = *AI;
6633e457fe3SDavid van Moolenbroek 
6643e457fe3SDavid van Moolenbroek     while(true) {
6653e457fe3SDavid van Moolenbroek         BitCastInst *castInst = dyn_cast<BitCastInst>(ActualArg);
6663e457fe3SDavid van Moolenbroek         ConstantExpr *castExpr = dyn_cast<ConstantExpr>(ActualArg);
6673e457fe3SDavid van Moolenbroek         if(castInst) {
6683e457fe3SDavid van Moolenbroek             assert(castInst->getNumOperands() == 1);
6693e457fe3SDavid van Moolenbroek             ActualArg = castInst->getOperand(0);
6703e457fe3SDavid van Moolenbroek             instructionsToRemove.push_back(castInst);
6713e457fe3SDavid van Moolenbroek         }
6723e457fe3SDavid van Moolenbroek         else if(castExpr) {
6733e457fe3SDavid van Moolenbroek             //assert(castExpr->getNumOperands() == 1);
6743e457fe3SDavid van Moolenbroek             ActualArg = castExpr->getOperand(0);
6753e457fe3SDavid van Moolenbroek         }
6763e457fe3SDavid van Moolenbroek         else {
6773e457fe3SDavid van Moolenbroek             break;
6783e457fe3SDavid van Moolenbroek         }
6793e457fe3SDavid van Moolenbroek     }
6803e457fe3SDavid van Moolenbroek 
6813e457fe3SDavid van Moolenbroek     GlobalVariable *GV = dyn_cast<GlobalVariable>(ActualArg);
6823e457fe3SDavid van Moolenbroek     if(GV == NULL) {
6833e457fe3SDavid van Moolenbroek         magicUtilLog("Weird ActualArg: " << *ActualArg);
6843e457fe3SDavid van Moolenbroek     }
6853e457fe3SDavid van Moolenbroek     assert(GV != NULL);
6863e457fe3SDavid van Moolenbroek 
6873e457fe3SDavid van Moolenbroek     return GV;
6883e457fe3SDavid van Moolenbroek }
6893e457fe3SDavid van Moolenbroek 
cleanupShadowTag(Module & M,std::vector<Instruction * > & instructionsToRemove)6903e457fe3SDavid van Moolenbroek void MagicUtil::cleanupShadowTag(Module &M, std::vector<Instruction*> &instructionsToRemove) {
6913e457fe3SDavid van Moolenbroek     int i=0;
6923e457fe3SDavid van Moolenbroek 
6933e457fe3SDavid van Moolenbroek     for(i =0;i<(int)instructionsToRemove.size();i++) {
6943e457fe3SDavid van Moolenbroek         Instruction *inst = instructionsToRemove[i];
6953e457fe3SDavid van Moolenbroek         inst->eraseFromParent();
6963e457fe3SDavid van Moolenbroek     }
6973e457fe3SDavid van Moolenbroek     Function* func = M.getFunction(MAGIC_LAZY_CHECKPOINT_SHADOW_TAG);
6983e457fe3SDavid van Moolenbroek     if(func && func->getNumUses() == 0) {
6993e457fe3SDavid van Moolenbroek         func->eraseFromParent();
7003e457fe3SDavid van Moolenbroek     }
7013e457fe3SDavid van Moolenbroek }
7023e457fe3SDavid van Moolenbroek 
hasAddressTaken(const GlobalValue * GV,bool includeMembers)7033e457fe3SDavid van Moolenbroek bool MagicUtil::hasAddressTaken(const GlobalValue *GV, bool includeMembers) {
7043e457fe3SDavid van Moolenbroek   //Most of the code taken from LLVM's SCCP.cpp
7053e457fe3SDavid van Moolenbroek 
7063e457fe3SDavid van Moolenbroek   // Delete any dead constantexpr klingons.
7073e457fe3SDavid van Moolenbroek   GV->removeDeadConstantUsers();
7083e457fe3SDavid van Moolenbroek 
7093e457fe3SDavid van Moolenbroek   std::vector<const User*> sourceUsers;
7103e457fe3SDavid van Moolenbroek   sourceUsers.push_back(GV);
7113e457fe3SDavid van Moolenbroek   if(includeMembers && isa<GlobalVariable>(GV)) {
712*bdb56518SDavid van Moolenbroek       for (const Use &UI : GV->uses()) {
713*bdb56518SDavid van Moolenbroek           const User *U = UI.getUser();
7143e457fe3SDavid van Moolenbroek           const ConstantExpr *constantExpr = dyn_cast<ConstantExpr>(U);
7153e457fe3SDavid van Moolenbroek           if(isa<GetElementPtrInst>(U)) {
7163e457fe3SDavid van Moolenbroek               sourceUsers.push_back(U);
7173e457fe3SDavid van Moolenbroek           }
7183e457fe3SDavid van Moolenbroek           else if(constantExpr && constantExpr->getOpcode() == Instruction::GetElementPtr) {
7193e457fe3SDavid van Moolenbroek               sourceUsers.push_back(U);
7203e457fe3SDavid van Moolenbroek           }
7213e457fe3SDavid van Moolenbroek       }
7223e457fe3SDavid van Moolenbroek   }
7233e457fe3SDavid van Moolenbroek 
7243e457fe3SDavid van Moolenbroek   for(unsigned i=0;i<sourceUsers.size();i++) {
725*bdb56518SDavid van Moolenbroek       for (const Use &UI : sourceUsers[i]->uses()) {
726*bdb56518SDavid van Moolenbroek         const User *U = UI.getUser();
7273e457fe3SDavid van Moolenbroek         if (const StoreInst *SI = dyn_cast<StoreInst>(U)) {
7283e457fe3SDavid van Moolenbroek           if (SI->getOperand(0) == sourceUsers[i] || SI->isVolatile())
7293e457fe3SDavid van Moolenbroek             return true;  // Storing addr of sourceUsers[i].
7303e457fe3SDavid van Moolenbroek         } else if (isa<InvokeInst>(U) || isa<CallInst>(U)) {
7313e457fe3SDavid van Moolenbroek           // Make sure we are calling the function, not passing the address.
7323e457fe3SDavid van Moolenbroek           ImmutableCallSite CS(cast<Instruction>(U));
733*bdb56518SDavid van Moolenbroek           if (!CS.isCallee(&UI))
7343e457fe3SDavid van Moolenbroek             return true;
7353e457fe3SDavid van Moolenbroek         } else if (const LoadInst *LI = dyn_cast<LoadInst>(U)) {
7363e457fe3SDavid van Moolenbroek           if (LI->isVolatile())
7373e457fe3SDavid van Moolenbroek             return true;
7383e457fe3SDavid van Moolenbroek         } else if (isa<BlockAddress>(U)) {
7393e457fe3SDavid van Moolenbroek           // blockaddress doesn't take the address of the function, it takes addr
7403e457fe3SDavid van Moolenbroek           // of label.
7413e457fe3SDavid van Moolenbroek         } else {
7423e457fe3SDavid van Moolenbroek           return true;
7433e457fe3SDavid van Moolenbroek         }
7443e457fe3SDavid van Moolenbroek       }
7453e457fe3SDavid van Moolenbroek   }
7463e457fe3SDavid van Moolenbroek   return false;
7473e457fe3SDavid van Moolenbroek }
7483e457fe3SDavid van Moolenbroek 
lookupValueSet(const GlobalVariable * GV,std::vector<int> & valueSet)7493e457fe3SDavid van Moolenbroek bool MagicUtil::lookupValueSet(const GlobalVariable *GV, std::vector<int> &valueSet) {
7503e457fe3SDavid van Moolenbroek   //Similar to hasAddressTaken above, but we look for values
7513e457fe3SDavid van Moolenbroek 
7523e457fe3SDavid van Moolenbroek   if(!isa<IntegerType>(GV->getType()->getElementType())) {
7533e457fe3SDavid van Moolenbroek       //integers is all we are interested in
7543e457fe3SDavid van Moolenbroek       return false;
7553e457fe3SDavid van Moolenbroek   }
7563e457fe3SDavid van Moolenbroek   if(!GV->hasInitializer()) {
7573e457fe3SDavid van Moolenbroek       //external variable
7583e457fe3SDavid van Moolenbroek       return false;
7593e457fe3SDavid van Moolenbroek   }
7603e457fe3SDavid van Moolenbroek 
7613e457fe3SDavid van Moolenbroek   // Delete any dead constantexpr klingons.
7623e457fe3SDavid van Moolenbroek   GV->removeDeadConstantUsers();
7633e457fe3SDavid van Moolenbroek 
7643e457fe3SDavid van Moolenbroek   std::set<int> set;
765*bdb56518SDavid van Moolenbroek   for (Value::const_user_iterator UI = GV->user_begin(), E = GV->user_end();
7663e457fe3SDavid van Moolenbroek       UI != E; ++UI) {
7673e457fe3SDavid van Moolenbroek       const User *U = *UI;
7683e457fe3SDavid van Moolenbroek       if (const StoreInst *SI = dyn_cast<StoreInst>(U)) {
7693e457fe3SDavid van Moolenbroek           if (SI->getOperand(1) == GV) {
7703e457fe3SDavid van Moolenbroek              Value *value = SI->getOperand(0);
7713e457fe3SDavid van Moolenbroek              if(ConstantInt *intValue = dyn_cast<ConstantInt>(value)) {
7723e457fe3SDavid van Moolenbroek                  set.insert(intValue->getSExtValue());
7733e457fe3SDavid van Moolenbroek              }
7743e457fe3SDavid van Moolenbroek              else {
7753e457fe3SDavid van Moolenbroek                  return false;
7763e457fe3SDavid van Moolenbroek              }
7773e457fe3SDavid van Moolenbroek           }
7783e457fe3SDavid van Moolenbroek       }
7793e457fe3SDavid van Moolenbroek   }
7803e457fe3SDavid van Moolenbroek   const Constant *constant = GV->getInitializer();
7813e457fe3SDavid van Moolenbroek   if(const ConstantInt *intConstant = dyn_cast<const ConstantInt>(constant)) {
7823e457fe3SDavid van Moolenbroek       set.insert(intConstant->getSExtValue());
7833e457fe3SDavid van Moolenbroek   }
7843e457fe3SDavid van Moolenbroek   else {
7853e457fe3SDavid van Moolenbroek       return false;
7863e457fe3SDavid van Moolenbroek   }
7873e457fe3SDavid van Moolenbroek 
7883e457fe3SDavid van Moolenbroek   assert(set.size() > 0);
7893e457fe3SDavid van Moolenbroek   valueSet.push_back(set.size()); //push length as the first value
7903e457fe3SDavid van Moolenbroek   for(std::set<int>::iterator it=set.begin() ; it != set.end(); it++) {
7913e457fe3SDavid van Moolenbroek       valueSet.push_back(*it);
7923e457fe3SDavid van Moolenbroek   }
7933e457fe3SDavid van Moolenbroek 
7943e457fe3SDavid van Moolenbroek   return true;
7953e457fe3SDavid van Moolenbroek }
7963e457fe3SDavid van Moolenbroek 
getStringOwner(GlobalVariable * GV)7973e457fe3SDavid van Moolenbroek Value* MagicUtil::getStringOwner(GlobalVariable *GV)
7983e457fe3SDavid van Moolenbroek {
7993e457fe3SDavid van Moolenbroek   //Similar to hasAddressTaken above, but we look for string owners
8003e457fe3SDavid van Moolenbroek   assert(GV && GV->isConstant());
8013e457fe3SDavid van Moolenbroek 
8023e457fe3SDavid van Moolenbroek   // Skip emtpy strings.
8033e457fe3SDavid van Moolenbroek   if(GV->hasInitializer() && GV->getInitializer()->isNullValue()) {
8043e457fe3SDavid van Moolenbroek       return NULL;
8053e457fe3SDavid van Moolenbroek   }
8063e457fe3SDavid van Moolenbroek 
8073e457fe3SDavid van Moolenbroek   // Delete any dead constantexpr klingons.
8083e457fe3SDavid van Moolenbroek   GV->removeDeadConstantUsers();
8093e457fe3SDavid van Moolenbroek 
8103e457fe3SDavid van Moolenbroek   std::vector<User*> sourceUsers;
8113e457fe3SDavid van Moolenbroek   sourceUsers.push_back(GV);
812*bdb56518SDavid van Moolenbroek   for (Value::user_iterator UI = GV->user_begin(), E = GV->user_end();
8133e457fe3SDavid van Moolenbroek       UI != E; ++UI) {
8143e457fe3SDavid van Moolenbroek       User *U = *UI;
8153e457fe3SDavid van Moolenbroek       ConstantExpr *constantExpr = dyn_cast<ConstantExpr>(U);
8163e457fe3SDavid van Moolenbroek       if(isa<GetElementPtrInst>(U)) {
8173e457fe3SDavid van Moolenbroek           sourceUsers.push_back(U);
8183e457fe3SDavid van Moolenbroek       }
8193e457fe3SDavid van Moolenbroek       else if(constantExpr && constantExpr->getOpcode() == Instruction::GetElementPtr) {
8203e457fe3SDavid van Moolenbroek           sourceUsers.push_back(U);
8213e457fe3SDavid van Moolenbroek       }
8223e457fe3SDavid van Moolenbroek   }
8233e457fe3SDavid van Moolenbroek 
8243e457fe3SDavid van Moolenbroek   Value *stringOwner = NULL;
8253e457fe3SDavid van Moolenbroek   for(unsigned i=0;i<sourceUsers.size();i++) {
826*bdb56518SDavid van Moolenbroek       for (Value::user_iterator UI = sourceUsers[i]->user_begin(), E = sourceUsers[i]->user_end();
8273e457fe3SDavid van Moolenbroek            UI != E; ++UI) {
8283e457fe3SDavid van Moolenbroek           User *U = *UI;
8293e457fe3SDavid van Moolenbroek           Value *V = U;
8303e457fe3SDavid van Moolenbroek           if (StoreInst *SI = dyn_cast<StoreInst>(U)) {
8313e457fe3SDavid van Moolenbroek               V = SI->getPointerOperand();
8323e457fe3SDavid van Moolenbroek           }
8333e457fe3SDavid van Moolenbroek           if(isa<GlobalVariable>(V) || isa<AllocaInst>(V)) {
8343e457fe3SDavid van Moolenbroek               if(stringOwner != NULL && stringOwner != V) {
8353e457fe3SDavid van Moolenbroek                   //no owner in the ambiguous cases
8363e457fe3SDavid van Moolenbroek                   return NULL;
8373e457fe3SDavid van Moolenbroek               }
8383e457fe3SDavid van Moolenbroek               stringOwner = V;
8393e457fe3SDavid van Moolenbroek           }
8403e457fe3SDavid van Moolenbroek       }
8413e457fe3SDavid van Moolenbroek   }
8423e457fe3SDavid van Moolenbroek 
8433e457fe3SDavid van Moolenbroek   return stringOwner;
8443e457fe3SDavid van Moolenbroek }
8453e457fe3SDavid van Moolenbroek 
getFirstNonAllocaInst(Function * F,bool skipAllocaPoint)8463e457fe3SDavid van Moolenbroek Instruction* MagicUtil::getFirstNonAllocaInst(Function *F, bool skipAllocaPoint)
8473e457fe3SDavid van Moolenbroek {
8483e457fe3SDavid van Moolenbroek   Instruction *I = NULL;
8493e457fe3SDavid van Moolenbroek   if (skipAllocaPoint) {
8503e457fe3SDavid van Moolenbroek       PassUtil::getAllocaInfo(F, NULL, &I);
8513e457fe3SDavid van Moolenbroek   }
8523e457fe3SDavid van Moolenbroek   else {
8533e457fe3SDavid van Moolenbroek       PassUtil::getAllocaInfo(F, &I, NULL);
8543e457fe3SDavid van Moolenbroek   }
8553e457fe3SDavid van Moolenbroek   assert(I);
8563e457fe3SDavid van Moolenbroek   return I;
8573e457fe3SDavid van Moolenbroek }
8583e457fe3SDavid van Moolenbroek 
setGlobalVariableSection(GlobalVariable * GV,const std::string & section)8593e457fe3SDavid van Moolenbroek void MagicUtil::setGlobalVariableSection(GlobalVariable *GV, const std::string &section)
8603e457fe3SDavid van Moolenbroek {
8613e457fe3SDavid van Moolenbroek   if(GV->isThreadLocal()) {
8623e457fe3SDavid van Moolenbroek       return;
8633e457fe3SDavid van Moolenbroek   }
8643e457fe3SDavid van Moolenbroek 
8653e457fe3SDavid van Moolenbroek   GV->setSection(section);
8663e457fe3SDavid van Moolenbroek }
8673e457fe3SDavid van Moolenbroek 
getCallAnnotation(Module & M,const CallSite & CS,int * annotation)8683e457fe3SDavid van Moolenbroek bool MagicUtil::getCallAnnotation(Module &M, const CallSite &CS, int *annotation)
8693e457fe3SDavid van Moolenbroek {
8703e457fe3SDavid van Moolenbroek   static GlobalVariable *magicAnnotationVar = NULL;
8713e457fe3SDavid van Moolenbroek   bool instFound = false;
8723e457fe3SDavid van Moolenbroek   bool annotationFound = false;
8733e457fe3SDavid van Moolenbroek   if(!magicAnnotationVar) {
8743e457fe3SDavid van Moolenbroek       magicAnnotationVar = M.getNamedGlobal(MAGIC_CALL_ANNOTATION_VAR_NAME);
8753e457fe3SDavid van Moolenbroek       assert(magicAnnotationVar);
8763e457fe3SDavid van Moolenbroek   }
8773e457fe3SDavid van Moolenbroek   Instruction *I = CS.getInstruction();
8783e457fe3SDavid van Moolenbroek   if(!I) {
8793e457fe3SDavid van Moolenbroek       return false;
8803e457fe3SDavid van Moolenbroek   }
8813e457fe3SDavid van Moolenbroek   BasicBlock *parent = I->getParent();
8823e457fe3SDavid van Moolenbroek   for (BasicBlock::iterator i = parent->begin(), e = parent->end(); i != e; ++i) {
8833e457fe3SDavid van Moolenbroek       Instruction *inst = i;
8843e457fe3SDavid van Moolenbroek       if(inst != I && !instFound) {
8853e457fe3SDavid van Moolenbroek           continue;
8863e457fe3SDavid van Moolenbroek       }
8873e457fe3SDavid van Moolenbroek       instFound = true;
8883e457fe3SDavid van Moolenbroek       if(inst == I) {
8893e457fe3SDavid van Moolenbroek           continue;
8903e457fe3SDavid van Moolenbroek       }
8913e457fe3SDavid van Moolenbroek       if(StoreInst *SI = dyn_cast<StoreInst>(inst)) {
8923e457fe3SDavid van Moolenbroek           if(SI->getOperand(1) == magicAnnotationVar) {
8933e457fe3SDavid van Moolenbroek               ConstantInt *CI = dyn_cast<ConstantInt>(SI->getOperand(0));
8943e457fe3SDavid van Moolenbroek               assert(CI && "Bad call annotation!");
8953e457fe3SDavid van Moolenbroek               annotationFound = true;
8963e457fe3SDavid van Moolenbroek               *annotation = CI->getSExtValue();
8973e457fe3SDavid van Moolenbroek               break;
8983e457fe3SDavid van Moolenbroek           }
8993e457fe3SDavid van Moolenbroek       }
9003e457fe3SDavid van Moolenbroek       else if(isa<CallInst>(inst) || isa<InvokeInst>(inst)) {
9013e457fe3SDavid van Moolenbroek           break;
9023e457fe3SDavid van Moolenbroek       }
9033e457fe3SDavid van Moolenbroek   }
9043e457fe3SDavid van Moolenbroek   return annotationFound;
9053e457fe3SDavid van Moolenbroek }
9063e457fe3SDavid van Moolenbroek 
getVarAnnotation(Module & M,const GlobalVariable * GV,int * annotation)9073e457fe3SDavid van Moolenbroek bool MagicUtil::getVarAnnotation(Module &M, const GlobalVariable *GV, int *annotation)
9083e457fe3SDavid van Moolenbroek {
9093e457fe3SDavid van Moolenbroek   std::string GVName = GV->getName();
9103e457fe3SDavid van Moolenbroek   GlobalVariable *annotationGV = M.getNamedGlobal(MAGIC_VAR_ANNOTATION_PREFIX_NAME + GVName);
9113e457fe3SDavid van Moolenbroek   if(!annotationGV || !annotationGV->hasInitializer()) {
9123e457fe3SDavid van Moolenbroek       return false;
9133e457fe3SDavid van Moolenbroek   }
9143e457fe3SDavid van Moolenbroek   ConstantInt* annotationValue = dyn_cast<ConstantInt>(annotationGV->getInitializer());
9153e457fe3SDavid van Moolenbroek   if(!annotationValue) {
9163e457fe3SDavid van Moolenbroek       return false;
9173e457fe3SDavid van Moolenbroek   }
9183e457fe3SDavid van Moolenbroek   *annotation = (int) annotationValue->getSExtValue();
9193e457fe3SDavid van Moolenbroek   return true;
9203e457fe3SDavid van Moolenbroek }
9213e457fe3SDavid van Moolenbroek 
getCallSiteFromInstruction(Instruction * I)9223e457fe3SDavid van Moolenbroek CallSite MagicUtil::getCallSiteFromInstruction(Instruction *I)
9233e457fe3SDavid van Moolenbroek {
9243e457fe3SDavid van Moolenbroek   return PassUtil::getCallSiteFromInstruction(I);
9253e457fe3SDavid van Moolenbroek }
9263e457fe3SDavid van Moolenbroek 
getAllocaInstFromArgument(Argument * argument)9273e457fe3SDavid van Moolenbroek AllocaInst* MagicUtil::getAllocaInstFromArgument(Argument *argument)
9283e457fe3SDavid van Moolenbroek {
9293e457fe3SDavid van Moolenbroek   Function *parent = argument->getParent();
9303e457fe3SDavid van Moolenbroek   std::string targetString = argument->getName().str() + "_addr";
9313e457fe3SDavid van Moolenbroek   std::string targetString2 = argument->getName().str() + ".addr";
9323e457fe3SDavid van Moolenbroek   StringRef targetName(targetString);
9333e457fe3SDavid van Moolenbroek   StringRef targetName2(targetString2);
9343e457fe3SDavid van Moolenbroek   for (inst_iterator it = inst_begin(parent), et = inst_end(parent); it != et; ++it) {
9353e457fe3SDavid van Moolenbroek       AllocaInst *AI = dyn_cast<AllocaInst>(&(*it));
9363e457fe3SDavid van Moolenbroek       if(!AI) {
9373e457fe3SDavid van Moolenbroek           break;
9383e457fe3SDavid van Moolenbroek       }
9393e457fe3SDavid van Moolenbroek       if(AI->getName().startswith(targetName) || AI->getName().startswith(targetName2)) {
9403e457fe3SDavid van Moolenbroek           return AI;
9413e457fe3SDavid van Moolenbroek       }
9423e457fe3SDavid van Moolenbroek   }
9433e457fe3SDavid van Moolenbroek 
9443e457fe3SDavid van Moolenbroek   return NULL;
9453e457fe3SDavid van Moolenbroek }
9463e457fe3SDavid van Moolenbroek 
9473e457fe3SDavid van Moolenbroek // searches for the specified function in module symbol table assuming that its name has been mangled
9483e457fe3SDavid van Moolenbroek // returns NULL if the function has not been found
getMangledFunction(Module & M,StringRef functionName)9493e457fe3SDavid van Moolenbroek Function* MagicUtil::getMangledFunction(Module &M, StringRef functionName)
9503e457fe3SDavid van Moolenbroek {
9513e457fe3SDavid van Moolenbroek 	Function *F = NULL;
9523e457fe3SDavid van Moolenbroek 	char* outbuf;
9533e457fe3SDavid van Moolenbroek 	const char* functionNameString = functionName.data();
9543e457fe3SDavid van Moolenbroek 	int status;
9553e457fe3SDavid van Moolenbroek 	for (Module::iterator it = M.begin(); it != M.end(); ++it) {
9563e457fe3SDavid van Moolenbroek 		StringRef mangledName = (*it).getName();
9573e457fe3SDavid van Moolenbroek 		outbuf = abi::__cxa_demangle(mangledName.data(), NULL, NULL, &status);
9583e457fe3SDavid van Moolenbroek 		if (status == -2) {
9593e457fe3SDavid van Moolenbroek 			continue; // mangledName is not a valid name under the C++ ABI mangling rules
9603e457fe3SDavid van Moolenbroek 		}
9613e457fe3SDavid van Moolenbroek 		assert(status == 0 && outbuf && "Error when trying to demangle a function name.");
9623e457fe3SDavid van Moolenbroek 		// testing whether this is the function we are looking for
9633e457fe3SDavid van Moolenbroek 		// the unmangled name is similar to a function prototype eg my_func(int, void*, int)
9643e457fe3SDavid van Moolenbroek 		char* pos = strstr(outbuf, functionNameString);
9653e457fe3SDavid van Moolenbroek 		if (!pos) {
9663e457fe3SDavid van Moolenbroek 			free(outbuf);
9673e457fe3SDavid van Moolenbroek 			continue;
9683e457fe3SDavid van Moolenbroek 		}
9693e457fe3SDavid van Moolenbroek 		// function names can only contain alpha-numeric characters and '_'
9703e457fe3SDavid van Moolenbroek 		// if the unmangled name refers to the target function, then that substring should not
9713e457fe3SDavid van Moolenbroek 		// be surrounded by characters allowed in a function name
9723e457fe3SDavid van Moolenbroek 		// (to exclude cases such as myfunc vs _myfunc vs myfunc2)
9733e457fe3SDavid van Moolenbroek 		if (pos > outbuf) {
9743e457fe3SDavid van Moolenbroek 			if (isalnum(*(pos - 1)) || (*(pos - 1) == '_')) {
9753e457fe3SDavid van Moolenbroek 				free(outbuf);
9763e457fe3SDavid van Moolenbroek 				continue;
9773e457fe3SDavid van Moolenbroek 			}
9783e457fe3SDavid van Moolenbroek 		}
9793e457fe3SDavid van Moolenbroek 		if (strlen(pos) > strlen(functionNameString)) {
9803e457fe3SDavid van Moolenbroek 			if (isalnum(*(pos + strlen(functionNameString))) || (*(pos + strlen(functionNameString)) == '_')) {
9813e457fe3SDavid van Moolenbroek 				free(outbuf);
9823e457fe3SDavid van Moolenbroek 				continue;
9833e457fe3SDavid van Moolenbroek 			}
9843e457fe3SDavid van Moolenbroek 		}
9853e457fe3SDavid van Moolenbroek 		F = it;
9863e457fe3SDavid van Moolenbroek 		free(outbuf);
9873e457fe3SDavid van Moolenbroek 		break;
9883e457fe3SDavid van Moolenbroek 	}
9893e457fe3SDavid van Moolenbroek 
9903e457fe3SDavid van Moolenbroek 	return F;
9913e457fe3SDavid van Moolenbroek }
9923e457fe3SDavid van Moolenbroek 
getFunction(Module & M,StringRef functionName)9933e457fe3SDavid van Moolenbroek Function* MagicUtil::getFunction(Module &M, StringRef functionName)
9943e457fe3SDavid van Moolenbroek {
9953e457fe3SDavid van Moolenbroek 	Function* F = M.getFunction(functionName);
9963e457fe3SDavid van Moolenbroek 	if (!F) {
9973e457fe3SDavid van Moolenbroek 		F = MagicUtil::getMangledFunction(M, functionName);
9983e457fe3SDavid van Moolenbroek 	}
9993e457fe3SDavid van Moolenbroek 	return F;
10003e457fe3SDavid van Moolenbroek }
10013e457fe3SDavid van Moolenbroek 
10023e457fe3SDavid van Moolenbroek // can Type1 be represented as Type2 (with no precision loss)
isCompatibleType(const Type * Type1,const Type * Type2)10033e457fe3SDavid van Moolenbroek bool MagicUtil::isCompatibleType(const Type* Type1, const Type* Type2)
10043e457fe3SDavid van Moolenbroek {
10053e457fe3SDavid van Moolenbroek 	if (Type1 == Type2) {
10063e457fe3SDavid van Moolenbroek 		return true;
10073e457fe3SDavid van Moolenbroek 	}
10083e457fe3SDavid van Moolenbroek 	if (Type1->isIntegerTy() && Type2->isIntegerTy()) {
10093e457fe3SDavid van Moolenbroek 		if (((const IntegerType*)Type1)->getBitWidth() <= ((const IntegerType*)Type2)->getBitWidth()) {
10103e457fe3SDavid van Moolenbroek 			return true;
10113e457fe3SDavid van Moolenbroek 		}
10123e457fe3SDavid van Moolenbroek 	}
10133e457fe3SDavid van Moolenbroek 
10143e457fe3SDavid van Moolenbroek 	return false;
10153e457fe3SDavid van Moolenbroek }
10163e457fe3SDavid van Moolenbroek 
10173e457fe3SDavid van Moolenbroek // inserts an inlined call to the pre-hook function before any other instruction is executed
10183e457fe3SDavid van Moolenbroek // it can forward (some of) the original function's parameters and additional trailing arguments
inlinePreHookForwardingCall(Function * function,Function * preHookFunction,std::vector<unsigned> argsMapping,std::vector<Value * > trailingArgs)10193e457fe3SDavid van Moolenbroek void MagicUtil::inlinePreHookForwardingCall(Function* function, Function* preHookFunction, std::vector<unsigned> argsMapping, std::vector<Value*> trailingArgs)
10203e457fe3SDavid van Moolenbroek {
10213e457fe3SDavid van Moolenbroek 	std::vector<Value*> callArgs;
10223e457fe3SDavid van Moolenbroek 	assert(preHookFunction->arg_size() == argsMapping.size() + trailingArgs.size() &&
10233e457fe3SDavid van Moolenbroek 			"The number of parameter values specified for the pre-hook function does not match the signature of the function.");
10243e457fe3SDavid van Moolenbroek 	for (std::vector<unsigned>::iterator it = argsMapping.begin(); it != argsMapping.end(); it++) {
10253e457fe3SDavid van Moolenbroek 		callArgs.push_back(MagicUtil::getFunctionParam(function, *it - 1));
10263e457fe3SDavid van Moolenbroek 	}
10273e457fe3SDavid van Moolenbroek 	for (std::vector<Value*>::iterator it = trailingArgs.begin(); it != trailingArgs.end(); it++) {
10283e457fe3SDavid van Moolenbroek 		callArgs.push_back(*it);
10293e457fe3SDavid van Moolenbroek 	}
10303e457fe3SDavid van Moolenbroek 	// insert the call after the alloca instructions so that they remain for sure in the entry block
10313e457fe3SDavid van Moolenbroek 	Instruction *FirstInst = MagicUtil::getFirstNonAllocaInst(function);
10323e457fe3SDavid van Moolenbroek 	for (unsigned i = 0; i < callArgs.size(); ++i) {
10333e457fe3SDavid van Moolenbroek 		TYPECONST Type* ArgType = callArgs[i]->getType();
10343e457fe3SDavid van Moolenbroek 		TYPECONST Type* ParamType = preHookFunction->getFunctionType()->getParamType(i);
10353e457fe3SDavid van Moolenbroek 
10363e457fe3SDavid van Moolenbroek 		if (!MagicUtil::isCompatibleType(ArgType, ParamType)) {
10373e457fe3SDavid van Moolenbroek 			assert(CastInst::isCastable(ArgType, ParamType) && "The value of the argument cannot be "
10383e457fe3SDavid van Moolenbroek 					"casted to the parameter type required by the function to be called.");
10393e457fe3SDavid van Moolenbroek 			Instruction::CastOps CastOpCode = CastInst::getCastOpcode(callArgs[i], false, ParamType, false);
10403e457fe3SDavid van Moolenbroek 			callArgs[i] = CastInst::Create(CastOpCode, callArgs[i], ParamType, "", FirstInst);
10413e457fe3SDavid van Moolenbroek 		}
10423e457fe3SDavid van Moolenbroek 	}
10433e457fe3SDavid van Moolenbroek 
10443e457fe3SDavid van Moolenbroek 	CallInst* WrapperFuncCall = MagicUtil::createCallInstruction(preHookFunction, callArgs, "", FirstInst);
10453e457fe3SDavid van Moolenbroek 	InlineFunctionInfo IFI;
10463e457fe3SDavid van Moolenbroek 	InlineFunction(WrapperFuncCall, IFI);
10473e457fe3SDavid van Moolenbroek }
10483e457fe3SDavid van Moolenbroek 
10493e457fe3SDavid van Moolenbroek // inserts an inlined call to the post-hook function before all return instructions
10503e457fe3SDavid van Moolenbroek // forwarded arguments from the first function come first, followed by the trailing ones
10513e457fe3SDavid van Moolenbroek // use offsets > 0 for function parameter mappings, and 0 for the return value of the function
inlinePostHookForwardingCall(Function * function,Function * postHookFunction,std::vector<unsigned> mapping,std::vector<Value * > trailingArgs)10523e457fe3SDavid van Moolenbroek void MagicUtil::inlinePostHookForwardingCall(Function* function, Function* postHookFunction, std::vector<unsigned> mapping, std::vector<Value*> trailingArgs)
10533e457fe3SDavid van Moolenbroek {
10543e457fe3SDavid van Moolenbroek 	std::vector<CallInst*> wrapperCalls;
10553e457fe3SDavid van Moolenbroek 	assert(postHookFunction->arg_size() == mapping.size() + trailingArgs.size()
10563e457fe3SDavid van Moolenbroek 			&& "The number of parameter values specified for the post-hook function does not match the signature of the function.");
10573e457fe3SDavid van Moolenbroek 
10583e457fe3SDavid van Moolenbroek 	for (Function::iterator BI = function->getBasicBlockList().begin(); BI != function->getBasicBlockList().end(); ++BI) {
10593e457fe3SDavid van Moolenbroek 		ReturnInst *RetInst = dyn_cast<ReturnInst>(BI->getTerminator());
10603e457fe3SDavid van Moolenbroek 		if (RetInst) {
10613e457fe3SDavid van Moolenbroek 			std::vector<Value*> callArgs;
10623e457fe3SDavid van Moolenbroek 			for (std::vector<unsigned>::iterator it = mapping.begin(); it != mapping.end(); it++) {
10633e457fe3SDavid van Moolenbroek 				if (*it > 0) {
10643e457fe3SDavid van Moolenbroek 					callArgs.push_back(MagicUtil::getFunctionParam(function, *it - 1));
10653e457fe3SDavid van Moolenbroek 				} else {
10663e457fe3SDavid van Moolenbroek 					callArgs.push_back(RetInst->getReturnValue());
10673e457fe3SDavid van Moolenbroek 				}
10683e457fe3SDavid van Moolenbroek 			}
10693e457fe3SDavid van Moolenbroek 			for (std::vector<Value*>::iterator it = trailingArgs.begin(); it != trailingArgs.end(); it++) {
10703e457fe3SDavid van Moolenbroek 				callArgs.push_back(*it);
10713e457fe3SDavid van Moolenbroek 			}
10723e457fe3SDavid van Moolenbroek 			for (unsigned i = 0; i < callArgs.size(); i++) {
10733e457fe3SDavid van Moolenbroek 				TYPECONST Type* ArgType = callArgs[i]->getType();
10743e457fe3SDavid van Moolenbroek 				TYPECONST Type* ParamType = postHookFunction->getFunctionType()->getParamType(i);
10753e457fe3SDavid van Moolenbroek 
10763e457fe3SDavid van Moolenbroek 				if (!MagicUtil::isCompatibleType(ArgType, ParamType)) {
10773e457fe3SDavid van Moolenbroek 					assert(CastInst::isCastable(ArgType, ParamType) && "The value of the argument cannot be "
10783e457fe3SDavid van Moolenbroek 							"casted to the parameter type required by the function to be called.");
10793e457fe3SDavid van Moolenbroek 					Instruction::CastOps CastOpCode = CastInst::getCastOpcode(callArgs[i], false, ParamType, false);
10803e457fe3SDavid van Moolenbroek 					callArgs[i] = CastInst::Create(CastOpCode, callArgs[i], ParamType, "", RetInst);
10813e457fe3SDavid van Moolenbroek 				}
10823e457fe3SDavid van Moolenbroek 			}
10833e457fe3SDavid van Moolenbroek 			CallInst* WrapperFuncCall = MagicUtil::createCallInstruction(postHookFunction, callArgs, "", RetInst);
10843e457fe3SDavid van Moolenbroek 			wrapperCalls.push_back(WrapperFuncCall);
10853e457fe3SDavid van Moolenbroek 		}
10863e457fe3SDavid van Moolenbroek 	}
10873e457fe3SDavid van Moolenbroek 	for (std::vector<CallInst*>::iterator it = wrapperCalls.begin(); it != wrapperCalls.end(); ++it) {
10883e457fe3SDavid van Moolenbroek 		InlineFunctionInfo IFI;
10893e457fe3SDavid van Moolenbroek 		InlineFunction(*it, IFI);
10903e457fe3SDavid van Moolenbroek 	}
10913e457fe3SDavid van Moolenbroek }
10923e457fe3SDavid van Moolenbroek 
getPointerIndirectionLevel(const Type * type)10933e457fe3SDavid van Moolenbroek int MagicUtil::getPointerIndirectionLevel(const Type* type)
10943e457fe3SDavid van Moolenbroek {
10953e457fe3SDavid van Moolenbroek 	int level = 0;
10963e457fe3SDavid van Moolenbroek 	if (const PointerType* ptr_type = dyn_cast<PointerType>(type)) {
10973e457fe3SDavid van Moolenbroek 		while (ptr_type) {
10983e457fe3SDavid van Moolenbroek 			level++;
10993e457fe3SDavid van Moolenbroek 			ptr_type = dyn_cast<PointerType>(ptr_type->getElementType());
11003e457fe3SDavid van Moolenbroek 		}
11013e457fe3SDavid van Moolenbroek 	}
11023e457fe3SDavid van Moolenbroek 
11033e457fe3SDavid van Moolenbroek 	return level;
11043e457fe3SDavid van Moolenbroek }
11053e457fe3SDavid van Moolenbroek 
getFunctionParam(Function * function,unsigned index)11063e457fe3SDavid van Moolenbroek Value* MagicUtil::getFunctionParam(Function* function, unsigned index)
11073e457fe3SDavid van Moolenbroek {
11083e457fe3SDavid van Moolenbroek 	if (index >= function->arg_size()) {
11093e457fe3SDavid van Moolenbroek 		return NULL;
11103e457fe3SDavid van Moolenbroek 	}
11113e457fe3SDavid van Moolenbroek 	Function::arg_iterator AI = function->arg_begin();
11123e457fe3SDavid van Moolenbroek 	while (index --> 0) {
11133e457fe3SDavid van Moolenbroek 		AI++;
11143e457fe3SDavid van Moolenbroek 	}
11153e457fe3SDavid van Moolenbroek 	return AI;
11163e457fe3SDavid van Moolenbroek }
11173e457fe3SDavid van Moolenbroek 
isLocalConstant(Module & M,GlobalVariable * GV)11183e457fe3SDavid van Moolenbroek bool MagicUtil::isLocalConstant(Module &M, GlobalVariable *GV)
11193e457fe3SDavid van Moolenbroek {
11203e457fe3SDavid van Moolenbroek 	if (!GV->isConstant()) {
11213e457fe3SDavid van Moolenbroek 		return false;
11223e457fe3SDavid van Moolenbroek 	}
11233e457fe3SDavid van Moolenbroek 	if (GV->getName().endswith(".v")) {
11243e457fe3SDavid van Moolenbroek 		return true;
11253e457fe3SDavid van Moolenbroek 	}
11263e457fe3SDavid van Moolenbroek 	std::pair<StringRef, StringRef> stringPair = GV->getName().split('.');
11273e457fe3SDavid van Moolenbroek 	StringRef functionName = stringPair.first;
11283e457fe3SDavid van Moolenbroek 	if (!functionName.compare("") || M.getFunction(functionName) == NULL) {
11293e457fe3SDavid van Moolenbroek 		return false;
11303e457fe3SDavid van Moolenbroek 	}
11313e457fe3SDavid van Moolenbroek 
11323e457fe3SDavid van Moolenbroek 	return true;
11333e457fe3SDavid van Moolenbroek }
11343e457fe3SDavid van Moolenbroek 
11353e457fe3SDavid van Moolenbroek }
1136