Exemplo n.º 1
0
bool ProfilingPass::runOnFunction(Function &F)
{
	LLVMContext& context = F.getContext();
    Module *m = F.getParent();
	string funcname = F.getNameStr();
	string injectfunc("injectFault");
	if((profileoption == 'p' || profileoption == 'c' || profileoption == 'i') && (funcname.find(injectfunc) != string::npos))
		return false;
	std::vector<Instruction*> insert_worklist;
	for (inst_iterator In = inst_begin(F), E = inst_end(F); In != E; ++In)
    {     
		Instruction *I = dyn_cast<Instruction>(&*In);
		//errs()<<*I<<"\n";
		if(profileoption == 'b')
		{
			if(CmpInst *ci = dyn_cast<CmpInst>(I))
				if(is_used_by_branch(ci)){
					vector<const Type*> argTypes(1);
					argTypes[0] = Type::getInt32Ty(context);	// enum for the options
					FunctionType* countFuncType = FunctionType::get( Type::getVoidTy(context), argTypes, 0 );
					Constant* countFunc = m->getOrInsertFunction("doProfiling", countFuncType);			// get the injection function
					vector<Value*> countArgs(1);
					const IntegerType* itype = IntegerType::get(context,32);
					Value* branchVal = ConstantInt::get(itype, BRANCH );

					countArgs[0] = branchVal; //enum for branch
					CallInst::Create( countFunc, countArgs.begin(),countArgs.end(), "", I); 
				}
		}
		else if(profileoption == 'd')
		{
			//see if the current instruction is a cmp instruction that leads to a conditional branch
			//add the instrumentation to the defs of this cmp instruction
			//--> Static time deduction since branch not known if executed or not
			CmpInst *ci = dyn_cast<CmpInst>(I);
			//errs() <<"reached here:\n";
			if(!ci)
				continue;
	
			//traverse def-use chain
			//int is_used_by_branch = 0;    
	
			if(!is_used_by_branch(I))
				continue;
			//the defines of this instruction I --> would be injectFaultCalls.   
			for (User::op_iterator i = I->op_begin(), e = I->op_end(); i != e; ++i) 
			{    
				Instruction *v = dyn_cast<Instruction>(*i);
				if(!v)
					continue;
				//errs() <<"reached here:"<< *v << "\n"; 
				//do profiling for the def
				vector<const Type*> argTypes(1);
				argTypes[0] = Type::getInt32Ty(context);	// enum for the options
				FunctionType* countFuncType = FunctionType::get( Type::getVoidTy(context), argTypes, 0 );
				Constant* countFunc = m->getOrInsertFunction("doProfiling", countFuncType);			// get the injection function
				vector<Value*> countArgs(1);
				const IntegerType* itype = IntegerType::get(context,32);
				Value* defVal = ConstantInt::get(itype, DEF );
				countArgs[0] = defVal; //enum for branch
				Instruction *beforeInst;
				if(isa<PHINode>(v))
				{	BasicBlock *bb = v->getParent();
					beforeInst = bb->getFirstNonPHI(); 
				}
				else
					beforeInst = v;
				CallInst::Create( countFunc, countArgs.begin(),countArgs.end(), "", beforeInst); 	// insert the profiling call before the def:v

			}
		}
		else if(profileoption == 'a' )
		{
			Instruction *beforeInst;
			//consider all instructions profiling
			vector<const Type*> argTypes(1);
			argTypes[0] = Type::getInt32Ty(context);	// enum for the options
			FunctionType* countFuncType = FunctionType::get( Type::getVoidTy(context), argTypes, 0 );
			Constant* countFunc = m->getOrInsertFunction("doProfiling", countFuncType);			// get the injection function
			vector<Value*> countArgs(1);
			const IntegerType* itype = IntegerType::get(context,32);
			Value* allVal = ConstantInt::get(itype, ALL );
			if(isa<PHINode>(I))
			{	BasicBlock *bb = I->getParent();
				beforeInst = bb->getFirstNonPHI(); 
			}
			else
				beforeInst = I;
			countArgs[0] = allVal; //enum for All inst
			CallInst::Create( countFunc, countArgs.begin(),countArgs.end(), "", beforeInst); 	// Insert the inject call before the instruction
		}
		//in fact, here we only use backwardslice ('s')
		else if(profileoption == 's')
		{
			const Type* returnType = I->getType();
			if (returnType->isVoidTy() || !filter(I))//Here we can insert a new filter ///////////////////////////////////////////////
			{
				//errs()<<"filter not passed\n";
				continue;
			}
//for injection into all instructions except invoke instructions (these are same as unconditional branch instructions with exception handling mechanism)
		  if((isa<InvokeInst>(I)) 
#ifdef EXCLUDE_CASTINST
|| (isa<CastInst>(I))
#endif
) // cast instruction added by Jiesheng
        continue;
			
			//errs()<<"filter passed\n";
			Instruction *beforeInst;
			if(isa<PHINode>(I))
			{	BasicBlock *bb = I->getParent();
				beforeInst = bb->getFirstNonPHI(); 
			}
			else
				beforeInst = I;
			insert_worklist.push_back(beforeInst);
		}

    }

    while(!insert_worklist.empty())
    {
    	Instruction* beforeInst = insert_worklist.back();
    	insert_worklist.pop_back();
    	vector<const Type*> argTypes(1);
			argTypes[0] = Type::getInt32Ty(context);	// enum for the options
			FunctionType* countFuncType = FunctionType::get( Type::getVoidTy(context), argTypes, 0 );
    	Constant* countFunc = m->getOrInsertFunction("doProfiling", countFuncType);
    	vector<Value*> countArgs(1);
    		const IntegerType* itype = IntegerType::get(context,32);
			Value* allVal = ConstantInt::get(itype, BACKWARD_SLICE );
    		countArgs[0] = allVal; //enum for All inst

    	CallInst::Create( countFunc, countArgs.begin(),countArgs.end(), "", beforeInst);

    }
    return true;
}
Exemplo n.º 2
0
  bool runOnFunction(Function &Func) override {
    if (Func.isDeclaration()) {
      return false;
    }
    vector<BranchInst *> BIs;
    for (inst_iterator I = inst_begin(Func); I != inst_end(Func); I++) {
      Instruction *Inst = &(*I);
      if (BranchInst *BI = dyn_cast<BranchInst>(Inst)) {
        BIs.push_back(BI);
      }
    } // Finish collecting branching conditions
    Value *zero =
        ConstantInt::get(Type::getInt32Ty(Func.getParent()->getContext()), 0);
    for (BranchInst *BI : BIs) {
      IRBuilder<> IRB(BI);
      vector<BasicBlock *> BBs;
      // We use the condition's evaluation result to generate the GEP
      // instruction  False evaluates to 0 while true evaluates to 1.  So here
      // we insert the false block first
      if (BI->isConditional()) {
        BBs.push_back(BI->getSuccessor(1));
      }
      BBs.push_back(BI->getSuccessor(0));
      ArrayType *AT = ArrayType::get(
          Type::getInt8PtrTy(Func.getParent()->getContext()), BBs.size());
      vector<Constant *> BlockAddresses;
      for (unsigned i = 0; i < BBs.size(); i++) {
        BlockAddresses.push_back(BlockAddress::get(BBs[i]));
      }
      GlobalVariable *LoadFrom = NULL;

      if (BI->isConditional() || indexmap.find(BI->getSuccessor(0))==indexmap.end()) {
        // Create a new GV
        Constant *BlockAddressArray =
            ConstantArray::get(AT, ArrayRef<Constant *>(BlockAddresses));
        LoadFrom = new GlobalVariable(*Func.getParent(), AT, false,
                                      GlobalValue::LinkageTypes::PrivateLinkage,
                                      BlockAddressArray);
      } else {
        LoadFrom =
            Func.getParent()->getGlobalVariable("IndirectBranchingGlobalTable",true);
      }
      Value *index = NULL;
      if (BI->isConditional()) {
        Value *condition = BI->getCondition();
        index = IRB.CreateZExt(
            condition, Type::getInt32Ty(Func.getParent()->getContext()));
      } else {
        index =
            ConstantInt::get(Type::getInt32Ty(Func.getParent()->getContext()),
                             indexmap[BI->getSuccessor(0)]);
      }
      Value *GEP = IRB.CreateGEP(LoadFrom, {zero, index});
      LoadInst *LI = IRB.CreateLoad(GEP, "IndirectBranchingTargetAddress");
      IndirectBrInst *indirBr = IndirectBrInst::Create(LI, BBs.size());
      for (BasicBlock *BB : BBs) {
        indirBr->addDestination(BB);
      }
      ReplaceInstWithInst(BI, indirBr);
    }
    return true;
  }
Exemplo n.º 3
0
bool ProfilingPass::doInitialization(Module &M)
{
	LLVMContext& context = M.getContext();
	Function* mainFunc = M.getFunction("main");
	const string moduleName = M.getModuleIdentifier();
	if (mainFunc!=NULL) {
		//BasicBlock* entryBlock = &mainFunc->front();
		Constant* Init = ConstantArray::get(context,moduleName,true);	// Convert it to an LLVM Type
		GlobalVariable* nameStr = new GlobalVariable(Init->getType(), true, GlobalValue::InternalLinkage, Init, "NameStr" );
		M.getGlobalList().push_back( nameStr );						// Insert it into the list of globals for module
		std::vector<Constant*>IndicesC(2);
		IndicesC[0] = Constant::getNullValue(Type::getInt32Ty(context));
		IndicesC[1] = ConstantInt::get(Type::getInt32Ty(context),0);
		Constant *getElemExpr =  ConstantExpr::getGetElementPtr(nameStr, &IndicesC[0], IndicesC.size());
		vector<Value*> initInjectArgs;
		initInjectArgs.push_back( getElemExpr ); 
		FunctionType* initInjectionFuncType = FunctionType::get(Type::getVoidTy(context), 
		vector<const Type*>(1,  PointerType::get(Type::getInt8Ty(context),0)),0); 
		
		//BasicBlock *exitBlock = &mainFunc->back();
		Instruction *I;
		for (inst_iterator fi = inst_begin(mainFunc), fe = inst_end(mainFunc); fi!=fe; ++fi){
			I = &*fi;
			if(isa<ReturnInst>(I))
				break;
		}
		BasicBlock *retblock = I->getParent(); //*retpred = retblock->getSinglePredecessor();
		
		Instruction *term = retblock->getTerminator();
		Constant *endFunc = M.getOrInsertFunction("endProfiling", initInjectionFuncType);
		vector<Value*> countArgs(1);
		//const IntegerType* itype = IntegerType::get(context,32);
		//Value* branchVal = ConstantInt::get(itype, BRANCH );
		CallInst::Create(endFunc, initInjectArgs.begin(), initInjectArgs.end(), "", term);
	}
	else
	{
		Constant* Init = ConstantArray::get(context,moduleName,true);	// Convert it to an LLVM Type
		GlobalVariable* nameStr = new GlobalVariable(Init->getType(), true, GlobalValue::InternalLinkage, Init, "NameStr" );
		M.getGlobalList().push_back( nameStr );
	}

	//***********************************************************************************************************
	//code for loading configure file should be here
	ifstream config ("llfi_configure.txt");
	if (config.is_open())
	{
		// we need to extract information from config file here Qining
		// this loop is used to know if the file is end
		while ( config.good() )
    	{
    		string line;
      		getline (config,line);
      		if(line.empty())	continue;
      		//if the line is empty, just skip.
      		//Any block of configure is started with one specific function
      		unsigned found = line.find("FUNCTION_NAME:");
      		if (found < line.length())
      		{
    			//std::cout << "\nfound FUNCTION_NAME at " << found << '\n';
    			std::string func_name = line.substr (found + string("FUNCTION_NAME:").length(),line.length() - found - string("FUNCTION_NAME:").length());
    			//first, I need to trim it
    			while(func_name[0] == ' ')
    			{
    				func_name.erase(0, 1);
    			}
    			while(func_name[func_name.length() - 1] == ' ')
    			{
    				func_name.erase(func_name.length() - 1, 0);
    			}
    			//so now I've got the name of the function
    			if(func_name.empty())	continue;
				std::cout << "The func_name is " << func_name << "\n";
				map_func_argu[func_name] = set<unsigned int>(); // create entry
				//map_func_fault_type[func_name] = set<unsigned int>(); 
				//second, I need to load argument set and type set
				do
				{
					line.clear();
					getline(config,line); // get the next line
					if(!config.good())	break; // if the new line is the end of file, our job is done.
					if(line.find("ARGUMENT:") < line.length())
					{
						//insert argument id to argument set
						std::string arg_set = line.substr(line.find("ARGUMENT:")+string("ARGUMENT:").length(), line.length() - line.find("ARGUMENT:")-string("ARGUMENT:").length());
						std::string arg;
						while(!arg_set.empty())
						{
							while(arg_set[0] <= '9' && arg_set[0] >= '0')
							{
								arg.append(arg_set.substr(0,1));
								if(!arg_set.empty())	arg_set.erase(0,1);
							}
							if(!arg.empty())
							{
								unsigned int arg_num = atoi(arg.c_str()) - 1;
								map_func_argu[func_name].insert(arg_num);
								std::cout << "\tinclude arg: " << arg_num+1 << "\n";
							}
							arg.clear();
							if(!arg_set.empty())	arg_set.erase(0,1);

						}
					}

				}while(line.find("FUNC_DEF_END") != 0);

    		}

    	}
    	// The file is end, we should have already finished our work, now close the file
    	config.close();
	}
	else errs()<<"Unable to open config file, use default config: all instructions, one bit flip\n";
	//***********************************************************************************************************

     return FunctionPass::doInitialization(M);
}
Function * futamurize( const Function * orig_func, DenseMap<const Value*, Value*> &argmap, std::set<const unsigned char *> &constant_addresses_set )
{
	LLVMContext &context = getGlobalContext();
	
	
	// Make a copy of the function, removing constant arguments
	Function * specialized_func = CloneFunction( orig_func, argmap );
	specialized_func->setName( orig_func->getNameStr() + "_1" );
	
	// add it to our module
	LLVM_Module->getFunctionList().push_back( specialized_func );
	
	printf("\nspecialized_func = %p <%s>\n", specialized_func, specialized_func->getName().data());
	//~ specialized_func->dump();

	// Optimize it
	FunctionPassManager PM( LLVM_Module );
	createStandardFunctionPasses( &PM, 3 );
	
	PM.add(createScalarReplAggregatesPass());  // Break up aggregate allocas
	PM.add(createInstructionCombiningPass());  // Cleanup for scalarrepl.
	PM.add(createJumpThreadingPass());         // Thread jumps.
	PM.add(createCFGSimplificationPass());     // Merge & remove BBs
	PM.add(createInstructionCombiningPass());  // Combine silly seq's
	PM.add(createTailCallEliminationPass());   // Eliminate tail calls
	PM.add(createCFGSimplificationPass());     // Merge & remove BBs
	PM.add(createReassociatePass());           // Reassociate expressions
	PM.add(createLoopRotatePass());            // Rotate Loop
	PM.add(createLICMPass());                  // Hoist loop invariants
	PM.add(createLoopUnswitchPass( false ));
	PM.add(createInstructionCombiningPass());
	PM.add(createIndVarSimplifyPass());        // Canonicalize indvars
	PM.add(createLoopDeletionPass());          // Delete dead loops
	PM.add(createLoopUnroll2Pass());            // Unroll small loops
	PM.add(createInstructionCombiningPass());  // Clean up after the unroller
	PM.add(createGVNPass());                   // Remove redundancies
	PM.add(createMemCpyOptPass());             // Remove memcpy / form memset
	PM.add(createSCCPPass());                  // Constant prop with SCCP
	PM.add(createPromoteMemoryToRegisterPass()); 
	PM.add(createConstantPropagationPass());            
	PM.add(createDeadStoreEliminationPass());            
	PM.add(createAggressiveDCEPass());            
	PM.add(new MemoryDependenceAnalysis());            
	//~ PM.add(createAAEvalPass());              
	
	const PassInfo * pinfo = Pass::lookupPassInfo( "print-alias-sets" );
	if( !pinfo ) { printf( "print-alias-sets not found\n" ); exit(-1); }
	PM.add( pinfo->createPass() );
	
	FunctionPassManager PM_Inline( LLVM_Module );
	PM_Inline.add(createSingleFunctionInliningPass());            
	
	bool Changed = false;
	int iterations = 2;
	int inline_iterations = 6;
	
	do
	{
		Changed = false;
		
		// first do some optimizations
		PM.doInitialization();
		PM.run( *specialized_func );
		PM.doFinalization();
		
		// Load from Constant Memory detection
		const TargetData *TD = LLVM_EE->getTargetData();
		
		for (inst_iterator I = inst_begin(specialized_func), E = inst_end(specialized_func); I != E; ++I) 
		{
			Instruction * inst = (Instruction *) &*I;

			// get all Load instructions
			LoadInst * load = dyn_cast<LoadInst>( inst );
			if( !load ) continue;
			if( load->isVolatile() ) continue;

			if (load->use_empty()) continue;        // Don't muck with dead instructions...

			// get the address loaded by load instruction
			Value *ptr_value = load->getPointerOperand();
			
			// we're only interested in constant addresses
			ConstantExpr * ptr_constant_expr =  dyn_cast<ConstantExpr>( ptr_value );
			if( !ptr_constant_expr ) continue;			
			ptr_constant_expr->dump();
			
			// compute real address of constant pointer expression
			Constant * ptr_constant = ConstantFoldConstantExpression( ptr_constant_expr, TD );
			if( !ptr_constant ) continue;
			ptr_constant->dump();
			
			// convert to int constant
			ConstantInt *int_constant =  dyn_cast<ConstantInt>( ConstantExpr::getPtrToInt( ptr_constant, Type::getInt64Ty( context )));
			if( !int_constant ) continue;
			int_constant->dump();
			
			// get data size
			int data_length = TD->getTypeAllocSize( load->getType() );
			ptr_value->getType()->dump();
			
			// get real address (at last !)
			const unsigned char * c_ptr = (const unsigned char *) int_constant->getLimitedValue();
			
			printf( "%ld %d %d\n", c_ptr, constant_addresses_set.count( c_ptr ), data_length );
			
			// check what's in this address	
			int isconst = 1;
			for( int offset=0; offset<data_length; offset++ )
				isconst &= constant_addresses_set.count( c_ptr + offset );
			
			if( !isconst ) continue;
			printf( "It is constant.\n" );
			
			// make a LLVM const with the data
			Constant *new_constant = NULL;
			switch( data_length )
			{
				case 1:	new_constant = ConstantInt::get( Type::getInt8Ty( context ),  *(uint8_t*)c_ptr, false /* signed */ );	break;
				case 2:	new_constant = ConstantInt::get( Type::getInt16Ty( context ), *(uint16_t*)c_ptr, false /* signed */ );	break;
				case 4:	new_constant = ConstantInt::get( Type::getInt32Ty( context ), *(uint32_t*)c_ptr, false /* signed */ );	break;
				case 8:	new_constant = ConstantInt::get( Type::getInt64Ty( context ), *(uint64_t*)c_ptr, false /* signed */ );	break;
				default:
				{
					StringRef const_data ( (const char *) c_ptr, data_length );
					new_constant = ConstantArray::get( context, const_data, false /* dont add terminating null */ );
				}
			}
			
			if( !new_constant ) continue;
			
			new_constant->dump();
							
			//~ // get the type that is loaded
			const Type *Ty = load->getType();
			
			// do we need a cast ?
			if( load->getType() != new_constant->getType() )
			{
				new_constant = ConstantExpr::getBitCast( new_constant, Ty );
				new_constant->dump();
			}
			
			// zap the load and replace with constant address
			load->replaceAllUsesWith( new_constant );
			printf( "\nREPLACED :...\n" );
			load->dump();
			new_constant->dump();
			
			Changed = true;
		}	
		
		if( Changed )
			continue;	// re-optimize and do another pass of constant load elimination
		
		// if we can't do anything else, do an inlining pass
		if( inline_iterations > 0 )
		{
			inline_iterations --;
			
			PM_Inline.doInitialization();
			Changed |= PM_Inline.run( *specialized_func );
			PM_Inline.doFinalization();

			//~ for( int i=0; i<3; i++ )
			{
				PM.doInitialization();
				Changed |= PM.run( *specialized_func );
				PM.doFinalization();
			}
		}
		
		if( iterations>0 && !Changed ) 
			iterations--;
	} while( Changed || iterations>0 );
	
	return specialized_func;
}