/// Emit extern decls for functions imported from other modules, and emit /// global declarations for function defined in this module and which are /// available to other modules. /// void PIC16AsmPrinter::EmitFunctionDecls(Module &M) { // Emit declarations for external functions. O <<"\n"<<TAI->getCommentString() << "Function Declarations - BEGIN." <<"\n"; for (Module::iterator I = M.begin(), E = M.end(); I != E; I++) { if (I->isIntrinsic()) continue; std::string Name = Mang->getMangledName(I); if (Name.compare("@abort") == 0) continue; if (!I->isDeclaration() && !I->hasExternalLinkage()) continue; // Do not emit memcpy, memset, and memmove here. // Calls to these routines can be generated in two ways, // 1. User calling the standard lib function // 2. Codegen generating these calls for llvm intrinsics. // In the first case a prototype is alread availale, while in // second case the call is via and externalsym and the prototype is missing. // So declarations for these are currently always getting printing by // tracking both kind of references in printInstrunction. if (I->isDeclaration() && PAN::isMemIntrinsic(Name)) continue; const char *directive = I->isDeclaration() ? TAI->getExternDirective() : TAI->getGlobalDirective(); O << directive << Name << "\n"; O << directive << PAN::getRetvalLabel(Name) << "\n"; O << directive << PAN::getArgsLabel(Name) << "\n"; } O << TAI->getCommentString() << "Function Declarations - END." <<"\n"; }
void MemoryInstrumenter::instrumentGlobals(Module &M) { TargetData &TD = getAnalysis<TargetData>(); IDAssigner &IDA = getAnalysis<IDAssigner>(); // Function HookGlobalsAlloc contains only one basic block. // The BB iterates through all global variables, and calls HookMemAlloc // for each of them. BasicBlock *BB = BasicBlock::Create(M.getContext(), "entry", GlobalsAllocHook); Instruction *Ret = ReturnInst::Create(M.getContext(), BB); for (Module::global_iterator GI = M.global_begin(), E = M.global_end(); GI != E; ++GI) { // We are going to delete llvm.global_ctors. // Therefore, don't instrument it. if (GI->getName() == "llvm.global_ctors") continue; // Prevent global variables from sharing the same address, because it // breaks the assumption that global variables do not alias. // The same goes to functions. if (GI->hasUnnamedAddr()) { GI->setUnnamedAddr(false); } uint64_t TypeSize = TD.getTypeStoreSize(GI->getType()->getElementType()); instrumentMemoryAllocation(GI, ConstantInt::get(LongType, TypeSize), NULL, Ret); instrumentPointer(GI, NULL, Ret); } for (Module::iterator F = M.begin(); F != M.end(); ++F) { // These hooks added by us don't have a value ID. if (MemAllocHook == F || MainArgsAllocHook == F || TopLevelHook == F || AddrTakenHook == F || CallHook == F || ReturnHook == F || GlobalsAllocHook == F || MemHooksIniter == F || AfterForkHook == F || BeforeForkHook == F) { continue; } // InvalidID: maybe this is inserted by alias checker in hybrid mode. if (IDA.getValueID(F) == IDAssigner::InvalidID) continue; // Ignore intrinsic functions because we cannot take the address of // an intrinsic. Also, no function pointers will point to instrinsic // functions. if (F->isIntrinsic()) continue; // Prevent functions from sharing the same address. if (F->hasUnnamedAddr()) { F->setUnnamedAddr(false); } uint64_t TypeSize = TD.getTypeStoreSize(F->getType()); assert(TypeSize == TD.getPointerSize()); instrumentMemoryAllocation(F, ConstantInt::get(LongType, TypeSize), NULL, Ret); instrumentPointer(F, NULL, Ret); } }
void MemoryInstrumenter::checkFeatures(Module &M) { // Check whether any memory allocation function can // potentially be pointed by function pointers. // Also, all intrinsic functions will be called directly, // i.e. not via function pointers. for (Module::iterator F = M.begin(); F != M.end(); ++F) { if (DynAAUtils::IsMalloc(F) || F->isIntrinsic()) { for (Value::use_iterator UI = F->use_begin(); UI != F->use_end(); ++UI) { User *Usr = *UI; assert(isa<CallInst>(Usr) || isa<InvokeInst>(Usr)); CallSite CS(cast<Instruction>(Usr)); for (unsigned i = 0; i < CS.arg_size(); ++i) assert(CS.getArgument(i) != F); } } } // Check whether memory allocation functions are captured. for (Module::iterator F = M.begin(); F != M.end(); ++F) { // 0 is the return, 1 is the first parameter. if (F->isDeclaration() && F->doesNotAlias(0) && !DynAAUtils::IsMalloc(F)) { errs().changeColor(raw_ostream::RED); errs() << F->getName() << "'s return value is marked noalias, "; errs() << "but the function is not treated as malloc.\n"; errs().resetColor(); } } // Global variables shouldn't be of the array type. for (Module::global_iterator GI = M.global_begin(), E = M.global_end(); GI != E; ++GI) { assert(!GI->getType()->isArrayTy()); } // A function parameter or an instruction can be an array, but we don't // instrument such constructs for now. Issue a warning on such cases. for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { for (Function::arg_iterator AI = F->arg_begin(); AI != F->arg_end(); ++AI) { if (AI->getType()->isArrayTy()) { errs().changeColor(raw_ostream::RED); errs() << F->getName() << ":" << *AI << " is an array\n"; errs().resetColor(); } } } for (Module::iterator F = M.begin(); F != M.end(); ++F) { for (Function::iterator BB = F->begin(); BB != F->end(); ++BB) { for (BasicBlock::iterator Ins = BB->begin(); Ins != BB->end(); ++Ins) { if (Ins->getType()->isArrayTy()) { errs().changeColor(raw_ostream::RED); errs() << F->getName() << ":" << *Ins << " is an array\n"; errs().resetColor(); } } } } }
bool MergeFunctions::runOnModule(Module &M) { bool Changed = false; std::map<unsigned long, std::vector<Function *> > FnMap; for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { if (F->isDeclaration() || F->isIntrinsic()) continue; if (!F->hasLocalLinkage() && !F->hasExternalLinkage() && !F->hasWeakLinkage()) continue; if (hasAddressTaken(F)) continue; FnMap[hash(F)].push_back(F); } // TODO: instead of running in a loop, we could also fold functions in callgraph // order. Constructing the CFG probably isn't cheaper than just running in a loop. bool LocalChanged; do { LocalChanged = false; for (std::map<unsigned long, std::vector<Function *> >::iterator I = FnMap.begin(), E = FnMap.end(); I != E; ++I) { DOUT << "size: " << FnMap.size() << "\n"; std::vector<Function *> &FnVec = I->second; DOUT << "hash (" << I->first << "): " << FnVec.size() << "\n"; for (int i = 0, e = FnVec.size(); i != e; ++i) { for (int j = i + 1; j != e; ++j) { bool isEqual = equals(FnVec[i], FnVec[j]); DOUT << " " << FnVec[i]->getName() << (isEqual ? " == " : " != ") << FnVec[j]->getName() << "\n"; if (isEqual) { if (fold(FnVec, i, j)) { LocalChanged = true; FnVec.erase(FnVec.begin() + j); --j, --e; } } } } } Changed |= LocalChanged; } while (LocalChanged); return Changed; }
void MemoryInstrumenter::checkFeatures(Module &M) { // Check whether any memory allocation function can // potentially be pointed by function pointers. // Also, all intrinsic functions will be called directly, // i.e. not via function pointers. for (Module::iterator F = M.begin(); F != M.end(); ++F) { if (DynAAUtils::IsMalloc(F) || F->isIntrinsic()) { for (Value::use_iterator UI = F->use_begin(); UI != F->use_end(); ++UI) { User *Usr = *UI; assert(isa<CallInst>(Usr) || isa<InvokeInst>(Usr)); CallSite CS(cast<Instruction>(Usr)); for (unsigned i = 0; i < CS.arg_size(); ++i) assert(CS.getArgument(i) != F); } } } // Check whether memory allocation functions are captured. for (Module::iterator F = M.begin(); F != M.end(); ++F) { // 0 is the return, 1 is the first parameter. if (F->isDeclaration() && F->doesNotAlias(0) && !DynAAUtils::IsMalloc(F)) { errs().changeColor(raw_ostream::RED); errs() << F->getName() << "'s return value is marked noalias, "; errs() << "but the function is not treated as malloc.\n"; errs().resetColor(); } } // Sequential types except pointer types shouldn't be used as the type of // an instruction, a function parameter, or a global variable. for (Module::global_iterator GI = M.global_begin(), E = M.global_end(); GI != E; ++GI) { if (isa<SequentialType>(GI->getType())) assert(GI->getType()->isPointerTy()); } for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { for (Function::arg_iterator AI = F->arg_begin(); AI != F->arg_end(); ++AI) { if (isa<SequentialType>(AI->getType())) assert(AI->getType()->isPointerTy()); } } for (Module::iterator F = M.begin(); F != M.end(); ++F) { for (Function::iterator BB = F->begin(); BB != F->end(); ++BB) { for (BasicBlock::iterator Ins = BB->begin(); Ins != BB->end(); ++Ins) { if (isa<SequentialType>(Ins->getType())) assert(Ins->getType()->isPointerTy()); } } } // We don't support multi-process programs for now. if (!HookFork) assert(M.getFunction("fork") == NULL); }
void IRWriter::writeIntrisics(Actor* actor){ Module* module = actor->getModule(); for (Module::iterator FI = module->begin(), FE = module->end(); FI != FE; ++FI) { if (FI->isIntrinsic()) { writer->addFunctionProtosExternal(FI); }else if (FI->getName().compare("printf")==0){ writer->linkExternalFunction(FI, FunctionMng::createPrintf(decoder->getModule())); } } }
bool StripAttributes::runOnModule(Module &M) { DataLayout DL(&M); for (Module::iterator Func = M.begin(), E = M.end(); Func != E; ++Func) { // Avoid stripping attributes from intrinsics because the // constructor for Functions just adds them back again. It would // be confusing if the attributes were sometimes present on // intrinsics and sometimes not. if (!Func->isIntrinsic()) { stripGlobalValueAttrs(Func); stripFunctionAttrs(&DL, Func); } } for (Module::global_iterator GV = M.global_begin(), E = M.global_end(); GV != E; ++GV) { stripGlobalValueAttrs(GV); } return true; }
/// CleanupAndPrepareModules - Get the specified modules ready for code /// generator testing. /// static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test, Module *Safe) { // Clean up the modules, removing extra cruft that we don't need anymore... Test = BD.performFinalCleanups(Test); // If we are executing the JIT, we have several nasty issues to take care of. if (!BD.isExecutingJIT()) return; // First, if the main function is in the Safe module, we must add a stub to // the Test module to call into it. Thus, we create a new function `main' // which just calls the old one. if (Function *oldMain = Safe->getFunction("main")) if (!oldMain->isDeclaration()) { // Rename it oldMain->setName("llvm_bugpoint_old_main"); // Create a NEW `main' function with same type in the test module. Function *newMain = Function::Create(oldMain->getFunctionType(), GlobalValue::ExternalLinkage, "main", Test); // Create an `oldmain' prototype in the test module, which will // corresponds to the real main function in the same module. Function *oldMainProto = Function::Create(oldMain->getFunctionType(), GlobalValue::ExternalLinkage, oldMain->getName(), Test); // Set up and remember the argument list for the main function. std::vector<Value*> args; for (Function::arg_iterator I = newMain->arg_begin(), E = newMain->arg_end(), OI = oldMain->arg_begin(); I != E; ++I, ++OI) { I->setName(OI->getName()); // Copy argument names from oldMain args.push_back(I); } // Call the old main function and return its result BasicBlock *BB = BasicBlock::Create(Safe->getContext(), "entry", newMain); CallInst *call = CallInst::Create(oldMainProto, args.begin(), args.end(), "", BB); // If the type of old function wasn't void, return value of call ReturnInst::Create(Safe->getContext(), call, BB); } // The second nasty issue we must deal with in the JIT is that the Safe // module cannot directly reference any functions defined in the test // module. Instead, we use a JIT API call to dynamically resolve the // symbol. // Add the resolver to the Safe module. // Prototype: void *getPointerToNamedFunction(const char* Name) Constant *resolverFunc = Safe->getOrInsertFunction("getPointerToNamedFunction", Type::getInt8PtrTy(Safe->getContext()), Type::getInt8PtrTy(Safe->getContext()), (Type *)0); // Use the function we just added to get addresses of functions we need. for (Module::iterator F = Safe->begin(), E = Safe->end(); F != E; ++F) { if (F->isDeclaration() && !F->use_empty() && &*F != resolverFunc && !F->isIntrinsic() /* ignore intrinsics */) { Function *TestFn = Test->getFunction(F->getName()); // Don't forward functions which are external in the test module too. if (TestFn && !TestFn->isDeclaration()) { // 1. Add a string constant with its name to the global file Constant *InitArray = ConstantArray::get(F->getContext(), F->getName()); GlobalVariable *funcName = new GlobalVariable(*Safe, InitArray->getType(), true /*isConstant*/, GlobalValue::InternalLinkage, InitArray, F->getName() + "_name"); // 2. Use `GetElementPtr *funcName, 0, 0' to convert the string to an // sbyte* so it matches the signature of the resolver function. // GetElementPtr *funcName, ulong 0, ulong 0 std::vector<Constant*> GEPargs(2, Constant::getNullValue(Type::getInt32Ty(F->getContext()))); Value *GEP = ConstantExpr::getGetElementPtr(funcName, &GEPargs[0], 2); std::vector<Value*> ResolverArgs; ResolverArgs.push_back(GEP); // Rewrite uses of F in global initializers, etc. to uses of a wrapper // function that dynamically resolves the calls to F via our JIT API if (!F->use_empty()) { // Create a new global to hold the cached function pointer. Constant *NullPtr = ConstantPointerNull::get(F->getType()); GlobalVariable *Cache = new GlobalVariable(*F->getParent(), F->getType(), false, GlobalValue::InternalLinkage, NullPtr,F->getName()+".fpcache"); // Construct a new stub function that will re-route calls to F const FunctionType *FuncTy = F->getFunctionType(); Function *FuncWrapper = Function::Create(FuncTy, GlobalValue::InternalLinkage, F->getName() + "_wrapper", F->getParent()); BasicBlock *EntryBB = BasicBlock::Create(F->getContext(), "entry", FuncWrapper); BasicBlock *DoCallBB = BasicBlock::Create(F->getContext(), "usecache", FuncWrapper); BasicBlock *LookupBB = BasicBlock::Create(F->getContext(), "lookupfp", FuncWrapper); // Check to see if we already looked up the value. Value *CachedVal = new LoadInst(Cache, "fpcache", EntryBB); Value *IsNull = new ICmpInst(*EntryBB, ICmpInst::ICMP_EQ, CachedVal, NullPtr, "isNull"); BranchInst::Create(LookupBB, DoCallBB, IsNull, EntryBB); // Resolve the call to function F via the JIT API: // // call resolver(GetElementPtr...) CallInst *Resolver = CallInst::Create(resolverFunc, ResolverArgs.begin(), ResolverArgs.end(), "resolver", LookupBB); // Cast the result from the resolver to correctly-typed function. CastInst *CastedResolver = new BitCastInst(Resolver, PointerType::getUnqual(F->getFunctionType()), "resolverCast", LookupBB); // Save the value in our cache. new StoreInst(CastedResolver, Cache, LookupBB); BranchInst::Create(DoCallBB, LookupBB); PHINode *FuncPtr = PHINode::Create(NullPtr->getType(), "fp", DoCallBB); FuncPtr->addIncoming(CastedResolver, LookupBB); FuncPtr->addIncoming(CachedVal, EntryBB); // Save the argument list. std::vector<Value*> Args; for (Function::arg_iterator i = FuncWrapper->arg_begin(), e = FuncWrapper->arg_end(); i != e; ++i) Args.push_back(i); // Pass on the arguments to the real function, return its result if (F->getReturnType()->isVoidTy()) { CallInst::Create(FuncPtr, Args.begin(), Args.end(), "", DoCallBB); ReturnInst::Create(F->getContext(), DoCallBB); } else { CallInst *Call = CallInst::Create(FuncPtr, Args.begin(), Args.end(), "retval", DoCallBB); ReturnInst::Create(F->getContext(),Call, DoCallBB); } // Use the wrapper function instead of the old function F->replaceAllUsesWith(FuncWrapper); } } } } if (verifyModule(*Test) || verifyModule(*Safe)) { errs() << "Bugpoint has a bug, which corrupted a module!!\n"; abort(); } }
// Entry point of the module bool PrepareCSI::runOnModule(Module &M){ vector<pair<string, set<set<string> > > > schemeData; if(VariantsFile.empty()){ outs() << "Reading stdin for instrumentation scheme...\n"; schemeData = readScheme(cin); outs() << "Finished reading stdin for scheme\n"; } else{ ifstream inFile(VariantsFile.c_str(), ios::in); if(!inFile || !inFile.is_open()) report_fatal_error("cannot open specified instrumentation scheme file: " + VariantsFile); schemeData = readScheme(inFile); } DEBUG(printScheme(schemeData)); // verify that all passes provided exist DEBUG(dbgs() << "verifying...\n"); verifyScheme(schemeData); DEBUG(printScheme(schemeData)); Context = &M.getContext(); // Find the matching pattern for each function map<Function*, set<set<string> >*> matches; for(Module::iterator F = M.begin(), E = M.end(); F != E; ++F){ if(F->isDeclaration() || F->isIntrinsic()) continue; bool found = false; for(vector<pair<string, set<set<string> > > >::iterator i = schemeData.begin(), e = schemeData.end(); i != e; ++i){ if(patternMatch(F->getName(), i->first)){ matches[F] = &(i->second); found = true; break; } } if(!found){ errs() << "WARNING: No scheme match found for function '" << F->getName() << "'. Skipping.\n"; continue; } } // Filter patterns matched to each function, and replicate for(map<Function*, set<set<string> >*>::iterator i = matches.begin(), e = matches.end(); i != e; ++i){ Function* F = i->first; // go through all filters for each possible scheme. if it passes all // filters, make a replica of this function with those tags on it, and add // that replica to the "replicas" set. else, print warning set<const set<string>*> replicas; for(set<set<string> >::iterator j = i->second->begin(), je = i->second->end(); j != je; ++j){ bool passed = true; if(!NoFilter){ for(vector<FilterFn>::const_iterator fi = Filters.begin(), fe = Filters.end(); fi != fe; ++fi){ if(!(*fi)(*j, F)){ passed = false; break; } } } if(passed) replicas.insert(&*j); else{ outs() << "WARNING: filtered out scheme '"; for(set<string>::iterator k = j->begin(), ke = j->end(); k != ke; ++k){ if(k != j->begin()) outs() << ","; outs() << *k; } outs() << "' for function '" << F->getName().str() << "'\n"; continue; } } switch (replicas.size()) { case 0: continue; case 1: { // instrument the original body (don't replicate and trampoline) const set<string>* scheme = *(replicas.begin()); for(set<string>::iterator j = scheme->begin(), je = scheme->end(); j != je; ++j) addInstrumentationType(*F, *j); break; } default: // if the function is variable-argument, currently don't support if(F->isVarArg()){ outs() << "WARNING: cannot instrument variable-argument function '" << F->getName() << "'\n"; continue; } // make a function for each scheme vector<Function*> funcReplicas; for(set<const set<string>*>::iterator j = replicas.begin(), je = replicas.end(); j != je; ++j){ ValueToValueMapTy valueMap; SmallVector<ReturnInst*, 1> returns; Function* newF = CloneFunction(F, valueMap, false, NULL); string name = F->getName().str(); if((*j)->begin() == (*j)->end()) name += "$none"; for(set<string>::iterator k = (*j)->begin(), ke = (*j)->end(); k != ke; ++k){ name += "$" + *k; addInstrumentationType(*newF, *k); } newF->setName(name); // NOTE: this does not preserve function ordering, thus it could // randomly slightly impact performance positively or negatively F->getParent()->getFunctionList().push_back(newF); funcReplicas.push_back(newF); } // assign this function a global switcher variable IntegerType* tInt = Type::getInt32Ty(*Context); string globalName = "__CSI_inst_"+getUniqueCFunctionName(*F); const GlobalValue::LinkageTypes linkage = F->hasAvailableExternallyLinkage() ? GlobalValue::WeakAnyLinkage : GlobalValue::ExternalLinkage; GlobalVariable * const functionGlobal = new GlobalVariable(M, tInt, true, linkage, ConstantInt::get(tInt, 0), globalName); functionGlobal->setSection("__CSI_func_inst"); // set up the trampoline call for this function switchIndirect(F, functionGlobal, funcReplicas); } } return(true); }