/* * Instrument switch instructions to log the index of the taken branch. */ void PandaInstrumentVisitor::visitSwitchInst(SwitchInst &I){ SExtInst *SEI; CallInst *CI; std::vector<Value*> argValues; Function *F = mod->getFunction("log_dynval"); if (!F) { printf("Instrumentation function not found\n"); assert(1==0); } if (I.getCondition()->getType() != wordType){ SEI = static_cast<SExtInst*>(IRB.CreateSExt(I.getCondition(), wordType)); argValues.push_back(ConstantInt::get(ptrType, (uintptr_t)dynval_buffer)); argValues.push_back(ConstantInt::get(intType, SWITCHENTRY)); argValues.push_back(ConstantInt::get(intType, SWITCH)); argValues.push_back(static_cast<Value*>(SEI)); CI = IRB.CreateCall(F, ArrayRef<Value*>(argValues)); CI->insertBefore(static_cast<Instruction*>(&I)); SEI->insertBefore(static_cast<Instruction*>(CI)); } else { argValues.push_back(ConstantInt::get(ptrType, (uintptr_t)dynval_buffer)); argValues.push_back(ConstantInt::get(intType, SWITCHENTRY)); argValues.push_back(ConstantInt::get(intType, SWITCH)); argValues.push_back(static_cast<Value*>(I.getCondition())); CI = IRB.CreateCall(F, ArrayRef<Value*>(argValues)); CI->insertBefore(static_cast<Instruction*>(&I)); } }
void replaceAllCallsWith(Value* OldFunc, Value* NewFunc) { for (Value::use_iterator I = OldFunc->use_begin(), E = OldFunc->use_end(); I != E; ++I) { if (CallInst* call = dyn_cast<CallInst>(*I)) { std::vector<Value*> args; for(int i=0; i<call->getNumArgOperands(); i++) { args.push_back(call->getArgOperand(i)); } ArrayRef<Value*> Args(args); CallInst *newCall = CallInst::Create(NewFunc, Args); if (newCall->getType() != call->getType()) { if (call->use_begin() != call->use_end()) { errs() << "Cannot handle usage of non matching return types for " << *call->getType() << " and " << *newCall->getType() << "\n"; } newCall->insertBefore(call); call->replaceAllUsesWith(newCall); call->eraseFromParent(); } else { ReplaceInstWithInst(call, newCall); } } else { (*I)->print(errs()); errs() << "\n"; exit(1); } } }
void PandaInstrumentVisitor::visitMemSetInst(MemSetInst &I){ Function *F = mod->getFunction("log_dynval"); if (!F) { printf("Instrumentation function not found\n"); assert(1==0); } int bytes = 0; Value *length = I.getLength(); if (ConstantInt* CI = dyn_cast<ConstantInt>(length)) { if (CI->getBitWidth() <= 64) { bytes = CI->getSExtValue(); } } if (bytes > 100) { //This mostly happens in cpu state reset printf("Note: dyn log ignoring memset greater than 100 bytes\n"); return; } PtrToIntInst *PTII; CallInst *CI; std::vector<Value*> argValues; PTII = static_cast<PtrToIntInst*>(IRB.CreatePtrToInt( I.getOperand(0), wordType)); argValues.push_back(ConstantInt::get(ptrType, (uintptr_t)dynval_buffer)); argValues.push_back(ConstantInt::get(intType, ADDRENTRY)); argValues.push_back(ConstantInt::get(intType, STORE)); argValues.push_back(static_cast<Value*>(PTII)); CI = IRB.CreateCall(F, ArrayRef<Value*>(argValues)); CI->insertBefore(static_cast<Instruction*>(&I)); PTII->insertBefore(static_cast<Instruction*>(CI)); }
void insert_function_limits(Function &F){ //Functions to be inserted as pragmas FunctionType* funvoid = FunctionType::get(Type::getVoidTy( F.getParent()->getContext() ), false); InlineAsm* fun_begin; InlineAsm* fun_end; if (sizeof(void*)==sizeof(long long)){ fun_begin = InlineAsm::get(funvoid, "callq\tpragma_function_begin", "", false); fun_end = InlineAsm::get(funvoid, "callq\tpragma_function_end", "", false); } else { fun_begin = InlineAsm::get(funvoid, "call\tpragma_function_begin", "", false); fun_end = InlineAsm::get(funvoid, "call\tpragma_function_end", "", false); } //In the beginning { BasicBlock& first = F.getEntryBlock(); int preds = 0; for (pred_iterator pi = pred_begin(&first), pe = pred_end(&first); pi != pe; pi++){ preds++; } if (preds > 0){ report_fatal_error("Error: The first basic block has predecessor.\n"); //TODO: insert a new basic block in the beginning } CallInst* before = CallInst::Create(fun_begin); before->setDoesNotThrow(); before->insertBefore( first.getFirstNonPHI() ); } //In the end for (Function::iterator bb = F.begin(), en = F.end(); bb != en; bb++){ TerminatorInst* inst = bb->getTerminator(); if ( isa<ReturnInst>(inst) ){ CallInst* after = CallInst::Create(fun_end); after->setDoesNotThrow(); //after->insertBefore( inst ); after->insertBefore( bb->getFirstNonPHI() ); } } }
void GEOSProfiler::instrumentBasicBlock(BasicBlock &BB, Module &M, int ID) { IRBuilder<> Builder(BB.getContext()); auto ConstantId = ConstantInt::get(Builder.getInt32Ty(), ID); CallInst *CountCall = Builder.CreateCall( M.getFunction("count"), ConstantId); CountCall->insertBefore(BB.getFirstNonPHI()); }
/// CopyPrecedingStopPoint - If I is immediately preceded by a StopPoint, /// make a copy of the stoppoint before InsertPos (presumably before copying /// or moving I). void llvm::CopyPrecedingStopPoint(Instruction *I, BasicBlock::iterator InsertPos) { if (I != I->getParent()->begin()) { BasicBlock::iterator BBI = I; --BBI; if (DbgStopPointInst *DSPI = dyn_cast<DbgStopPointInst>(BBI)) { CallInst *newDSPI = cast<CallInst>(DSPI->clone()); newDSPI->insertBefore(InsertPos); } } }
/** * Inserts new call instruction. * @param CalleeF function to be called * @param args arguments of the function to be called * @param rw_rule relevant rewrite rule * @param currentInstr current instruction * @param Iiterator pointer to instructions iterator */ void InsertCallInstruction(Function* CalleeF, vector<Value *> args, RewriteRule rw_rule, Instruction *currentInstr, inst_iterator *Iiterator) { // Create new call instruction CallInst *newInstr = CallInst::Create(CalleeF, args); // duplicate the metadata of the instruction for which we // instrument the code, some passes (e.g. inliner) can // break the code when there's an instruction without metadata // when all other instructions have metadata if (currentInstr->hasMetadata()) { CloneMetadata(currentInstr, newInstr); } else if (const DISubprogram *DS = currentInstr->getParent()->getParent()->getSubprogram()) { // no metadata? then it is going to be the instrumentation // of alloca or such at the beggining of function, // so just add debug loc of the beginning of the function newInstr->setDebugLoc(DebugLoc::get(DS->getLine(), 0, DS)); } if(rw_rule.where == InstrumentPlacement::BEFORE) { // Insert before newInstr->insertBefore(currentInstr); logger.log_insertion("before", CalleeF, currentInstr); } else if(rw_rule.where == InstrumentPlacement::AFTER) { // Insert after newInstr->insertAfter(currentInstr); logger.log_insertion("after", CalleeF, currentInstr); } else if(rw_rule.where == InstrumentPlacement::REPLACE) { // TODO: Make the functions use the iterator instead of // the instruction then check this works // In the end we move the iterator to the newInst position // so we can safely remove the sequence of instructions being // replaced newInstr->insertAfter(currentInstr); inst_iterator helper(*Iiterator); *Iiterator = ++helper; EraseInstructions(currentInstr, rw_rule.foundInstrs.size()); logger.log_insertion(rw_rule.foundInstrs, rw_rule.newInstr.instruction); } }
/** * Inserts new call instruction for globals. * @param CalleeF function to be called * @param args arguments of the function to be called * @param currentInstr current instruction */ void InsertCallInstruction(Function* CalleeF, vector<Value *> args, Instruction *currentInstr) { // Create new call instruction CallInst *newInstr = CallInst::Create(CalleeF, args); // duplicate the metadata of the instruction for which we // instrument the code, some passes (e.g. inliner) can // break the code when there's an instruction without metadata // when all other instructions have metadata if (currentInstr->hasMetadata()) { CloneMetadata(currentInstr, newInstr); } else if (const DISubprogram *DS = currentInstr->getParent()->getParent()->getSubprogram()) { // no metadata? then it is going to be the instrumentation // of alloca or such at the beggining of function, // so just add debug loc of the beginning of the function newInstr->setDebugLoc(DebugLoc::get(DS->getLine(), 0, DS)); } // Insert before newInstr->insertBefore(currentInstr); logger.log_insertion("before", CalleeF, currentInstr); }
void FuncAddrTaken::addPatchAt(Module &M, FunctionType *FT, Value *V, Instruction *MI, std::map<BasicBlock*, std::set<std::string> >& UniqPatchAt) { if (isa<Function>(V) && cast<Function>(V)->hasName()) { StringRef fn = cast<Function>(V)->getName(); if (fn.startswith("_GLOBAL__D_") || fn.startswith("_GLOBAL__E_")) return; std::string patchname = std::string("__patch_at") + fn.str(); BasicBlock* BB = MI->getParent(); if (UniqPatchAt.find(BB) == UniqPatchAt.end()) UniqPatchAt[BB] = std::set<std::string>(); if (UniqPatchAt[BB].find(patchname) != UniqPatchAt[BB].end()) return; UniqPatchAt[BB].insert(patchname); IRBuilder<> Builder(M.getContext()); Constant* PatchAtHere = M.getOrInsertFunction( std::string("__patch_at") + fn.str(), FT); CallInst *PatchAtCI = Builder.CreateCall(PatchAtHere); PatchAtCI->insertBefore(MI); } }
/// CreateGlobalPool - Create a global pool descriptor object, and insert a /// poolinit for it into the global constructor. GlobalVariable * PoolAllocateSimple::CreateGlobalPool (unsigned RecSize, unsigned Align, Module& M) { // // See if the global pool has already been created. If so, then just return // it. // if (GlobalVariable * GV = M.getNamedGlobal ("__poolalloc_GlobalPool")) { return GV; } // // Create the global pool descriptor. // GlobalVariable *GV = new GlobalVariable(M, getPoolType(&M.getContext()), false, GlobalValue::ExternalLinkage, ConstantAggregateZero::get(getPoolType(&M.getContext())), "__poolalloc_GlobalPool" ); // // Get the global pool constructor. Create and insert the poolinit call // inside it. // Function *InitFunc = createGlobalPoolCtor(M); Value *ElSize = ConstantInt::get(Int32Type, RecSize); Value *AlignV = ConstantInt::get(Int32Type, Align); Value *Opts[3] = { GV, ElSize, AlignV }; CallInst *InitCall = CallInst::Create(PoolInit, Opts, ""); InitCall->insertBefore(&InitFunc->getEntryBlock().front()); return GV; }
/* * Instrument select instructions similar to how we instrument branches. */ void PandaInstrumentVisitor::visitSelectInst(SelectInst &I){ BinaryOperator *BO; ZExtInst *ZEI; CallInst *CI; std::vector<Value*> argValues; Value *condition; Function *F = mod->getFunction("log_dynval"); if (!F) { printf("Instrumentation function not found\n"); assert(1==0); } condition = I.getCondition(); BO = static_cast<BinaryOperator*>(IRB.CreateNot(condition)); ZEI = static_cast<ZExtInst*>(IRB.CreateZExt(BO, wordType)); argValues.push_back(ConstantInt::get(ptrType, (uintptr_t)dynval_buffer)); argValues.push_back(ConstantInt::get(intType, SELECTENTRY)); argValues.push_back(ConstantInt::get(intType, SELECT)); argValues.push_back(static_cast<Value*>(ZEI)); CI = IRB.CreateCall(F, ArrayRef<Value*>(argValues)); CI->insertBefore(static_cast<Instruction*>(&I)); ZEI->insertBefore(static_cast<Instruction*>(CI)); BO->insertBefore(static_cast<Instruction*>(ZEI)); }
/* * Call the logging function, logging the address of the load. If it's loading * the root of a global value (likely CPUState), then we can ignore it. */ void PandaInstrumentVisitor::visitLoadInst(LoadInst &I){ Function *F = mod->getFunction("log_dynval"); if (!F) { printf("Instrumentation function not found\n"); assert(1==0); } // We used to ignore global values, but I think we will keep it now since // global QEMU values may be referenced in helper functions //if (!(isa<GlobalValue>(I.getPointerOperand()))){ if (isa<GetElementPtrInst>(I.getPointerOperand())){ // Result from a getelementptr instruction CallInst *CI; PtrToIntInst *PTII; std::vector<Value*> argValues; PTII = static_cast<PtrToIntInst*>( IRB.CreatePtrToInt(I.getPointerOperand(), ptrType)); argValues.push_back(ConstantInt::get(ptrType, (uintptr_t)dynval_buffer)); argValues.push_back(ConstantInt::get(intType, ADDRENTRY)); argValues.push_back(ConstantInt::get(intType, LOAD)); argValues.push_back(static_cast<Value*>(PTII)); //argValues.push_back(static_cast<Value*>(I.getPointerOperand())); CI = IRB.CreateCall(F, ArrayRef<Value*>(argValues)); CI->insertBefore(static_cast<Instruction*>(&I)); PTII->insertBefore(static_cast<Instruction*>(CI)); } else if ( // GetElementPtr ConstantExpr (isa<ConstantExpr>(I.getPointerOperand()) && static_cast<ConstantExpr*>(I.getPointerOperand())->getOpcode() == Instruction::GetElementPtr) // IntToPtr ConstantExpr || (isa<ConstantExpr>(I.getPointerOperand()) && static_cast<ConstantExpr*>(I.getPointerOperand())->getOpcode() == Instruction::IntToPtr) // env, or some other global variable || (isa<GlobalVariable>(I.getPointerOperand())) ){ CallInst *CI; PtrToIntInst *PTII; std::vector<Value*> argValues; PTII = static_cast<PtrToIntInst*>( IRB.CreatePtrToInt(I.getPointerOperand(), ptrType)); argValues.push_back(ConstantInt::get(ptrType, (uintptr_t)dynval_buffer)); argValues.push_back(ConstantInt::get(intType, ADDRENTRY)); argValues.push_back(ConstantInt::get(intType, LOAD)); argValues.push_back(static_cast<Value*>(PTII)); CI = IRB.CreateCall(F, ArrayRef<Value*>(argValues)); CI->insertBefore(static_cast<Instruction*>(&I)); } else { PtrToIntInst *PTII; CallInst *CI; std::vector<Value*> argValues; PTII = static_cast<PtrToIntInst*>(IRB.CreatePtrToInt( I.getPointerOperand(), wordType)); argValues.push_back(ConstantInt::get(ptrType, (uintptr_t)dynval_buffer)); argValues.push_back(ConstantInt::get(intType, ADDRENTRY)); argValues.push_back(ConstantInt::get(intType, LOAD)); argValues.push_back(static_cast<Value*>(PTII)); CI = IRB.CreateCall(F, ArrayRef<Value*>(argValues)); CI->insertBefore(static_cast<Instruction*>(&I)); PTII->insertBefore(static_cast<Instruction*>(CI)); } //} }
/* * Call the logging function, logging the branch target. Target[0] is the true * branch, and target[1] is the false branch. So when logging, we NOT the * condition to actually log the target taken. We are also logging and * processing unconditional branches for the time being. */ void PandaInstrumentVisitor::visitBranchInst(BranchInst &I){ BinaryOperator *BO; ZExtInst *ZEI; CallInst *CI; std::vector<Value*> argValues; Value *condition; Function *F = mod->getFunction("log_dynval"); if (!F) { printf("Instrumentation function not found\n"); assert(1==0); } if (I.isConditional()){ condition = I.getCondition(); if(isa<UndefValue>(condition)){ BO = static_cast<BinaryOperator*>(IRB.CreateNot(condition)); ZEI = static_cast<ZExtInst*>(IRB.CreateZExt(BO, wordType)); argValues.push_back(ConstantInt::get(ptrType, (uintptr_t)dynval_buffer)); argValues.push_back(ConstantInt::get(intType, BRANCHENTRY)); argValues.push_back(ConstantInt::get(intType, BRANCHOP)); argValues.push_back(static_cast<Value*>(ZEI)); CI = IRB.CreateCall(F, ArrayRef<Value*>(argValues)); CI->insertBefore(static_cast<Instruction*>(&I)); } else if (isa<Constant>(condition)){ CallInst *CI; std::vector<Value*> argValues; uint64_t constcond = static_cast<ConstantInt*>( I.getCondition())->getZExtValue(); argValues.push_back(ConstantInt::get(ptrType, (uintptr_t)dynval_buffer)); argValues.push_back(ConstantInt::get(intType, BRANCHENTRY)); argValues.push_back(ConstantInt::get(intType, BRANCHOP)); argValues.push_back(ConstantInt::get(wordType, !constcond)); CI = IRB.CreateCall(F, ArrayRef<Value*>(argValues)); CI->insertBefore(static_cast<Instruction*>(&I)); } else { BO = static_cast<BinaryOperator*>(IRB.CreateNot(condition)); ZEI = static_cast<ZExtInst*>(IRB.CreateZExt(BO, wordType)); argValues.push_back(ConstantInt::get(ptrType, (uintptr_t)dynval_buffer)); argValues.push_back(ConstantInt::get(intType, BRANCHENTRY)); argValues.push_back(ConstantInt::get(intType, BRANCHOP)); argValues.push_back(static_cast<Value*>(ZEI)); CI = IRB.CreateCall(F, ArrayRef<Value*>(argValues)); CI->insertBefore(static_cast<Instruction*>(&I)); ZEI->insertBefore(static_cast<Instruction*>(CI)); BO->insertBefore(static_cast<Instruction*>(ZEI)); } } else { argValues.push_back(ConstantInt::get(ptrType, (uintptr_t)dynval_buffer)); argValues.push_back(ConstantInt::get(intType, BRANCHENTRY)); argValues.push_back(ConstantInt::get(intType, BRANCHOP)); argValues.push_back(ConstantInt::get(wordType, 0)); CI = IRB.CreateCall(F, ArrayRef<Value*>(argValues)); CI->insertBefore(static_cast<Instruction*>(&I)); } }
// Call the logging function, logging the address of the store void PandaInstrumentVisitor::visitStoreInst(StoreInst &I){ Function *F = mod->getFunction("log_dynval"); if (!F) { printf("Instrumentation function not found\n"); assert(1==0); } if (I.isVolatile()){ // Stores to LLVM runtime that we don't care about return; } else if (isa<ConstantExpr>(I.getPointerOperand()) && isa<Constant>(static_cast<Instruction*>( I.getPointerOperand())->getOperand(0))){ /* * Storing to a constant looks something like this: * store i32 %29, i32* inttoptr (i64 135186980 to i32*), * sort of like an inttoptr instruction as an operand. This is how we * deal with logging that weirdness. */ CallInst *CI; std::vector<Value*> argValues; uint64_t constaddr = static_cast<ConstantInt*>( static_cast<Instruction*>( I.getPointerOperand())->getOperand(0))->getZExtValue(); argValues.push_back(ConstantInt::get(ptrType, (uintptr_t)dynval_buffer)); argValues.push_back(ConstantInt::get(intType, ADDRENTRY)); argValues.push_back(ConstantInt::get(intType, STORE)); argValues.push_back(ConstantInt::get(wordType, constaddr)); CI = IRB.CreateCall(F, ArrayRef<Value*>(argValues)); CI->insertBefore(static_cast<Instruction*>(&I)); } else if (isa<GlobalVariable>(I.getPointerOperand())){ //else if (isa<GlobalValue>(I.getPointerOperand())){ // env, or some other global variable CallInst *CI; PtrToIntInst *PTII; std::vector<Value*> argValues; PTII = static_cast<PtrToIntInst*>( IRB.CreatePtrToInt(I.getPointerOperand(), ptrType)); argValues.push_back(ConstantInt::get(ptrType, (uintptr_t)dynval_buffer)); argValues.push_back(ConstantInt::get(intType, ADDRENTRY)); argValues.push_back(ConstantInt::get(intType, STORE)); argValues.push_back(static_cast<Value*>(PTII)); CI = IRB.CreateCall(F, ArrayRef<Value*>(argValues)); CI->insertBefore(static_cast<Instruction*>(&I)); } else { PtrToIntInst *PTII; CallInst *CI; std::vector<Value*> argValues; PTII = static_cast<PtrToIntInst*>(IRB.CreatePtrToInt( I.getPointerOperand(), wordType)); argValues.push_back(ConstantInt::get(ptrType, (uintptr_t)dynval_buffer)); argValues.push_back(ConstantInt::get(intType, ADDRENTRY)); argValues.push_back(ConstantInt::get(intType, STORE)); argValues.push_back(static_cast<Value*>(PTII)); CI = IRB.CreateCall(F, ArrayRef<Value*>(argValues)); CI->insertBefore(static_cast<Instruction*>(&I)); PTII->insertBefore(static_cast<Instruction*>(CI)); } }