/* * BPatch_image::getProcedures * * Returns a list of all procedures in the image upon success, and NULL * upon failure. */ BPatch_Vector<BPatch_variableExpr *> *BPatch_image::getGlobalVariablesInt() { BPatch_variableExpr *var; BPatch_Vector<BPatch_variableExpr *> *varlist = new BPatch_Vector<BPatch_variableExpr *>; if (varlist == NULL) return NULL; // XXX - should this stuff really be by image ??? jkh 3/19/99 BPatch_Vector<BPatch_module *> *mods = getModules(); //BPatch_type *type; for (unsigned int m = 0; m < mods->size(); m++) { BPatch_module *module = (*mods)[m]; char name[255]; module->getName(name, sizeof(name)); pdvector<pdstring> keys = module->getModuleTypes()->globalVarsByName.keys(); int limit = keys.size(); for (int j = 0; j < limit; j++) { pdstring name = keys[j]; var = createVarExprByName(module, name.c_str()); if (var != NULL) varlist->push_back(var); } } return varlist; }
void BPatch_basicBlock::getOutgoingEdges(BPatch_Vector<BPatch_edge*>& out) { std::set<BPatch_edge*>::iterator outIter = outgoingEdges.begin(); while (outIter != outgoingEdges.end()) { out.push_back(*outIter); outIter++; } }
void BPatch_basicBlock::getIncomingEdges(BPatch_Vector<BPatch_edge*>& inc) { std::set<BPatch_edge*>::iterator incIter = incomingEdges.begin(); while (incIter != incomingEdges.end()) { inc.push_back(*incIter); incIter++; } }
void source_helper(ParseAPI::Edge* e, BPatch_Vector<BPatch_basicBlock*>& srcs, BPatch_flowGraph* flowGraph, func_instance* func) { BPatch_basicBlock* b = flowGraph->findBlock(func->obj()->findBlock(e->src())); assert(b); srcs.push_back(b); }
bool BPatch_loopTreeNode::getCalleesInt(BPatch_Vector<BPatch_function *> &v, BPatch_process *p) { for (unsigned i=0; i<callees.size(); i++) { BPatch_function *f = p->func_map->get(callees[i]); v.push_back(f); } return true; }
bool BPatch_loopTreeNode::getCallees(BPatch_Vector<BPatch_function *> &v, BPatch_addressSpace *p) { for (unsigned i=0; i<callees.size(); i++) { // get() will not allocate a NULL entry in the map BPatch_function *f = p->findOrCreateBPFunc(callees[i], NULL); v.push_back(f); } return true; }
BPatchSnippetHandle *BPatch_addressSpace::insertSnippet(const BPatch_snippet &expr, BPatch_point &point, BPatch_callWhen when, BPatch_snippetOrder order) { BPatch_Vector<BPatch_point *> points; points.push_back(&point); return insertSnippet(expr, points, when, order); }
/* This function should be deprecated. */ bool BPatch_module::getLineToAddrInt( unsigned int lineNo, BPatch_Vector< unsigned long > & buffer, bool ) { if (hasBeenRemoved_) return false; std::vector< std::pair< Address, Address > > ranges; if( ! getAddressRangesInt( NULL, lineNo, ranges ) ) { return false; } for( unsigned int i = 0; i < ranges.size(); ++i ) { buffer.push_back( ranges[i].first ); } return true; } /* end getLineToAddr() */
//returns the successors of the basic block in a set void BPatch_basicBlock::getTargets(BPatch_Vector<BPatch_basicBlock*>& tgrts){ BPatch_basicBlock *b; pdvector<block_instance *> out_blocks; const PatchBlock::edgelist &itrgs = iblock->targets(); for (PatchBlock::edgelist::const_iterator iter = itrgs.begin(); iter != itrgs.end(); ++iter) { edge_instance* iedge = SCAST_EI(*iter); // We don't include interprocedural predecessors in the BPatch layer if (iedge->interproc() || iedge->sinkEdge()) continue; b = flowGraph->findBlock(iedge->trg()); if (b) tgrts.push_back(b); } }
BPatch_Vector<BPatch_function *> *pd_image::getIncludedFunctions() { BPatch_Vector<BPatch_function *> *ret = new BPatch_Vector<BPatch_function *>(); for (unsigned int i = 0; i < some_mods.size(); ++i) { BPatch_Vector<BPatch_function *> *temp; temp = getIncludedFunctions(some_mods[i]->get_dyn_module()); if (NULL == temp) continue; for (unsigned j = 0; j < temp->size(); j++) { ret->push_back((*temp)[j]); } } return ret; }
bool BPatch_module::getVariablesInt(BPatch_Vector<BPatch_variableExpr *> &vars) { if (hasBeenRemoved_) return false; BPatch_variableExpr *var; parseTypesIfNecessary(); pdvector<pdstring> keys = moduleTypes->globalVarsByName.keys(); int limit = keys.size(); for (int j = 0; j < limit; j++) { pdstring name = keys[j]; var = img->createVarExprByName(this, name.c_str()); if (var != NULL) vars.push_back(var); } if (limit) return true; // We may not have top-level (debugging derived) variable info. // If not, go into the low-level code. const pdvector<int_variable *> &allVars = mod->getAllVariables(); for (unsigned i = 0; i < allVars.size(); i++) { BPatch_variableExpr *var = img->createVarExprByName(this, allVars[i]->symTabName().c_str()); if (var) vars.push_back(var); } if (vars.size()) return true; #ifdef IBM_BPATCH_COMPAT // IBM getVariables can be successful while returning an empty set of vars return true; #else return false; #endif }
//returns the source block corresponding to the basic block //which is created looking at the machine code. bool BPatch_basicBlock::getSourceBlocks(BPatch_Vector<BPatch_sourceBlock*>& sBlocks) { if(!sourceBlocks) flowGraph->createSourceBlocks(); if(!sourceBlocks) return false; for(unsigned int i=0;i<sourceBlocks->size();i++) sBlocks.push_back((*sourceBlocks)[i]); return true; }
BPatch_Vector<BPatch_point*>* BPatch_memoryAccess::filterPoints( const BPatch_Vector<BPatch_point *> &points, unsigned int numMAs) { BPatch_Vector<BPatch_point*> *result = new BPatch_Vector<BPatch_point *>; for(unsigned int i = 0; i < points.size(); ++i) { const BPatch_memoryAccess *ma = points[i]->getMemoryAccess(); if(ma) if(ma->getNumberOfAccesses() >= numMAs) result->push_back(points[i]); } return result; }
/* * BPatch_localVarCollection::getAllVars() * this function returns all the local variables in the collection. */ BPatch_Vector<BPatch_localVar *> *BPatch_localVarCollection::getAllVars() { dictionary_hash_iter<pdstring, BPatch_localVar *> li(localVariablesByName); pdstring name; BPatch_localVar *localVar; BPatch_Vector<BPatch_localVar *> *localVarVec = new BPatch_Vector<BPatch_localVar *>; // get all local vars in the localVariablesByName collection while (li.next(name, localVar)) localVarVec->push_back(localVar); return localVarVec; }
/* * BPatch_thread::getCallStack * * Returns information about the frames currently on the thread's stack. * * stack The vector to fill with the stack trace information. */ bool BPatch_thread::getCallStack(BPatch_Vector<BPatch_frame>& stack) { pdvector<Frame> stackWalk; if (!llthread->walkStack(stackWalk) ) { proccontrol_printf("%s[%d]: failed to perform stackwalk on thread %d\n", FILE__, __LINE__, llthread->getLWP()); return false; } for (unsigned int i = 0; i < stackWalk.size(); i++) { bool isSignalFrame = false; bool isInstrumentation = false; BPatch_point *point = NULL; Frame frame = stackWalk[i]; instPoint *iP = NULL; isSignalFrame = frame.isSignalFrame(); isInstrumentation = frame.isInstrumentation(); if (isInstrumentation) { if (NULL != (iP = frame.getPoint())) { point = proc->findOrCreateBPPoint(NULL, iP, BPatch_point::convertInstPointType_t(iP->type())); } if (!point) { isInstrumentation = false; } } stack.push_back(BPatch_frame(this, (void *)frame.getPC(), (void *)frame.getFP(), isSignalFrame, isInstrumentation, point)); } return true; }
static int genVRelTest(BPatch_image *appImage, BPatch_Vector<BPatch_snippet*> &vect7_1, BPatch_relOp op, BPatch_variableExpr *r1, BPatch_variableExpr *r2, const char *var1) { const char *funcName = "test1_7_func2"; BPatch_Vector<BPatch_function *> found_funcs; if ((NULL == appImage->findFunction(funcName, found_funcs)) || !found_funcs.size()) { logerror(" Unable to find function %s\n", funcName); return -1; } if (1 < found_funcs.size()) { logerror("%s[%d]: WARNING : found %d functions named %s. Using the first.\n", __FILE__, __LINE__, found_funcs.size(), funcName); } BPatch_Vector<BPatch_point *> *point7_1 = found_funcs[0]->findPoint(BPatch_entry); if (!point7_1 || ((*point7_1).size() == 0)) { logerror("Unable to find entry point to \"%s\".\n", funcName); return -1; } BPatch_variableExpr *expr1_1 = findVariable(appImage, var1, point7_1); if (!expr1_1) { logerror("**Failed** test #7 (relational operators)\n"); logerror(" Unable to locate variable %s\n", var1); return -1; } BPatch_ifExpr *tempExpr1 = new BPatch_ifExpr( BPatch_boolExpr(op, *r1, *r2), BPatch_arithExpr(BPatch_assign, *expr1_1, BPatch_constExpr(74))); vect7_1.push_back(tempExpr1); return 0; }
/* * BPatch_image::getProcedures * * Returns a list of all procedures in the image upon success, and NULL * upon failure. */ BPatch_Vector<BPatch_function *> *BPatch_image::getProceduresInt(bool incUninstrumentable) { BPatch_Vector<BPatch_function *> *proclist = new BPatch_Vector<BPatch_function *>; if (proclist == NULL) return NULL; // XXX Also, what should we do about getting rid of this? Should // the BPatch_functions already be made and kept around as long // as the process is, so the user doesn't have to delete them? BPatch_Vector<BPatch_module *> *mods = getModules(); for (unsigned int i = 0; i < (unsigned) mods->size(); i++) { BPatch_Vector<BPatch_function *> *funcs = (*mods)[i]->getProcedures(incUninstrumentable); for (unsigned int j=0; j < (unsigned) funcs->size(); j++) { proclist->push_back((*funcs)[j]); } } return proclist; }
BPatch_Vector<BPatch_point*>* BPatch_basicBlock::findPointByPredicate(insnPredicate& f) { BPatch_Vector<BPatch_point*>* ret = new BPatch_Vector<BPatch_point*>; block_instance::Insns insns; block()->getInsns(insns); for (block_instance::Insns::iterator iter = insns.begin(); iter != insns.end(); ++iter) { if(f(iter->second)) { instPoint *p = instPoint::preInsn(ifunc(), block(), iter->first, iter->second, true); BPatch_point *tmp = flowGraph->getAddSpace()->findOrCreateBPPoint(flowGraph->getFunction(), p, BPatch_locInstruction); if(!tmp) { fprintf(stderr, "WARNING: failed to create instpoint for load/store/prefetch %s at 0x%lx\n", iter->second.format().c_str(), iter->first); } else { ret->push_back(tmp); } } } return ret; }
// Instrument a function: eztrace_code0(code_entry) is called at the // beginning of the function and eztrace_code0(code_entry) is called // at the end of the function. // If code_entry or code_exit is null, the corresponding call to // eztrace_code0 is skipped static int __intercept_function(BPatch_addressSpace *app, const char* function_name, uint32_t code_entry, uint32_t code_exit) { BPatch_image *appImage; BPatch_Vector<BPatch_point*> *points; BPatch_Vector<BPatch_function *> functions; BPatch_Vector<BPatch_function *> record_event0_ptr; appImage = app->getImage(); // search for record_event0 function BPatch_Vector<BPatch_module*> *loaded_modules = appImage->getModules(); printf("Threre are %d modules\n", loaded_modules->size()); for(int i=0; i< loaded_modules->size(); i++) { BPatch_module* cur_mod = (*loaded_modules)[i]; char mod_name[80]; cur_mod->getName(mod_name, 80); cur_mod->findFunction("record_event0", record_event0_ptr, false); if(!record_event0_ptr.size()) { printf("\tfunction record_event0 not found in module %s\n", mod_name); } else { printf("Found ! in module %s\n", mod_name); break; } } if(!record_event0_ptr.size()) { printf("Cannot find record_event0 function\n"); return -1; } printf("PLOP\n"); for(int i=0; i< loaded_modules->size(); i++) { BPatch_module* cur_mod = (*loaded_modules)[i]; char mod_name[80]; cur_mod->getName(mod_name, 80); cur_mod->findFunction(function_name, functions, false); if(!functions.size()) { printf("\tfunction %s not found in module %s\n", function_name, mod_name); } else { printf("Found %s! \n", function_name ); break; } } if(!functions.size()) { fprintf(stderr, "warning: cannot find function %s in executable\n", function_name); return 0; } // Instrument the entry of the function if(code_entry) { // We need to call eztrace_generic(code, nb_param, param1, param2, ...) points = functions[0]->findPoint(BPatch_entry); BPatch_Vector<BPatch_snippet*> dummyArgs; // Create the parameter (code_entry) BPatch_constExpr code(code_entry); dummyArgs.push_back(&code); // Create the function call #if 0 BPatch_Vector<BPatch_function *> funcs; appImage->findFunction("record_event0", funcs); BPatch_function *dummyFunc = funcs[0]; BPatch_funcCallExpr dummyCall(*dummyFunc, dummyArgs); #else BPatch_funcCallExpr dummyCall(*record_event0_ptr[0], dummyArgs); #endif //Insert the function call at the point app->insertSnippet(dummyCall, *points); } // Instrument the exit of the function if(code_exit) { // the function parameters are not available here, so we have to // call eztrace_code0(code) points = functions[0]->findPoint(BPatch_exit); // Create the parameter (code_entry) BPatch_Vector<BPatch_snippet*> dummyArgs; BPatch_constExpr code(code_exit); dummyArgs.push_back(&code); // Create the function call #if 0 BPatch_Vector<BPatch_function *> funcs; appImage->findFunction("record_event0", funcs); BPatch_function *dummyFunc = funcs[0]; BPatch_funcCallExpr dummyCall(*dummyFunc, dummyArgs); #else BPatch_funcCallExpr dummyCall(*record_event0_ptr[0], dummyArgs); #endif //Insert the function call at the point app->insertSnippet(dummyCall, *points); } return 1; }
bool insertTraceSnippet(dynHandle *dh, BPatch_function *func, BPatch_Vector<BPatch_point *> *points) { char *buf; BPatch_point *point; BPatch_callWhen when; BPatch_snippetOrder order; int warn_cnt = 0, pass_cnt = 0; sendMsg(config.outfd, ID_TRACE_INSERT, VERB3); for (unsigned int i = 0; i < points->size(); ++i) { if (!shouldInsert()) continue; sendMsg(config.outfd, ID_TRACE_INSERT_ONE, VERB4); point = (*points)[i]; buf = sprintf_static("%0*lx", trace_msglen, (void *)point); BPatch_constExpr data(buf); BPatch_constExpr len(trace_msglen); BPatch_Vector< BPatch_snippet * > param; param.push_back( trace_fd ); param.push_back( &data ); param.push_back( &len ); // write(trace_fd, buf, trace_msglen); BPatch_funcCallExpr writeCall(*trace_write, param); // if (trace_fd > 0) BPatch_boolExpr checkFd(BPatch_gt, *trace_fd, BPatch_constExpr( 0 )); BPatch_ifExpr traceSnippet(checkFd, writeCall); switch (point->getPointType()) { case BPatch_entry: when = BPatch_callBefore; order = BPatch_firstSnippet; break; case BPatch_exit: when = BPatch_callAfter; order = BPatch_lastSnippet; break; default: sendMsg(config.outfd, ID_TRACE_INSERT_ONE, VERB4, ID_FAIL, "Internal error. Attempting to trace non entry/exit point."); ++warn_cnt; continue; } BPatchSnippetHandle *handle = dh->addSpace->insertSnippet(traceSnippet, *point, when, order); if (!handle) { sendMsg(config.outfd, ID_TRACE_INSERT_ONE, VERB4, ID_FAIL, "Error detected in BPatch_process::insertSnippet()."); ++warn_cnt; continue; } sendMsg(config.outfd, ID_TRACE_INSERT_ONE, VERB4, ID_PASS); ++pass_cnt; trace_points[(void *)point] = func; } if (warn_cnt) { sendMsg(config.outfd, ID_TRACE_INSERT, VERB3, ID_WARN, sprintf_static("%d warning(s), %d passed.", warn_cnt, pass_cnt)); } else { sendMsg(config.outfd, ID_TRACE_INSERT, VERB3, ID_PASS); } return true; }
int main(int argc, char *argv[], char* envp[]) { if (argc < 2) { fprintf(stderr, "Usage: %s prog_filename prog_aruments\n", argv[0]); return 3; } #if 0 if (strcmp(argv[1], "prog") != 0 && strcmp(argv[1], "all")) { fprintf(stderr, "Options for patch selection are 'progonly' or 'all'\n"); return 3; } #endif int patchall = 0; //strcmp(argv[1], "all") != 0; // Create process BPatch_process *appProc = bpatch.processCreate(argv[1], (const char**) &(argv[1])); // Load pthread into the process... appProc->loadLibrary("libpthread.so.0"); // Get the process image BPatch_image *appImage = appProc->getImage(); // Find all the instrumentable procedures BPatch_Vector<BPatch_function*> *functions = appImage->getProcedures(); /************************************************************************* * General function search * *************************************************************************/ // Find the printf function BPatch_Vector<BPatch_function*> printfFuncs; appImage->findFunction("printf", printfFuncs); if (printfFuncs.size() == 0) appImage->findFunction("_printf", printfFuncs); if (printfFuncs.size() == 0) appImage->findFunction("__printf", printfFuncs); if(printfFuncs.size() == 0) { fprintf(stderr, "Could not find printf() function"); return 2; } // Find the exit function BPatch_Vector<BPatch_function*> exitFuncs; appImage->findFunction("exit", exitFuncs); if (exitFuncs.size() == 0) appImage->findFunction("_exit", exitFuncs); if (exitFuncs.size() == 0) appImage->findFunction("__exit", exitFuncs); if(exitFuncs.size() == 0) { fprintf(stderr, "Could not find exit() function"); return 2; } // Find the perror function BPatch_Vector<BPatch_function*> perrorFuncs; appImage->findFunction("perror", perrorFuncs); if (perrorFuncs.size() == 0) appImage->findFunction("_perror", perrorFuncs); if (perrorFuncs.size() == 0) appImage->findFunction("__perror", perrorFuncs); if(perrorFuncs.size() == 0) { fprintf(stderr, "Could not find perror() function"); return 2; } BPatch_Vector<BPatch_snippet*> mainEntryBlock; /************************************************************************ * Error exit call * ************************************************************************/ BPatch_Vector<BPatch_snippet*> exitArgs; BPatch_constExpr exitCode(-2); exitArgs.push_back(&exitCode); // Open call BPatch_funcCallExpr exitOnErrorCall(*exitFuncs[0], exitArgs); /************************************************************************ * Open imitate device patch * * **********************************************************************/ // Find main() BPatch_Vector<BPatch_function*> mainFunctions; appImage->findFunction("main", mainFunctions); if (mainFunctions.size() == 0) appImage->findFunction("_main", mainFunctions); if (mainFunctions.size() == 0) appImage->findFunction("__main", mainFunctions); if(mainFunctions.size() == 0) { fprintf(stderr, "Could not find main() function"); return 2; } // find open() BPatch_Vector<BPatch_function*> openFunctions; appImage->findFunction("open64", openFunctions); if (openFunctions.size() == 0) appImage->findFunction("open", openFunctions); if (openFunctions.size() == 0) appImage->findFunction("_open", openFunctions); if (openFunctions.size() == 0) appImage->findFunction("__open", openFunctions); if(openFunctions.size() == 0) { fprintf(stderr, "Could not find open() function"); return 2; } // Get main() entry point BPatch_Vector<BPatch_point*> *mainPoints = mainFunctions[0]->findPoint(BPatch_entry); // Open call arguments BPatch_Vector<BPatch_snippet*> openArgs; BPatch_constExpr fileName("/dev/imitate0"); BPatch_constExpr fileFlags(O_RDWR); openArgs.push_back(&fileName); openArgs.push_back(&fileFlags); // Open call BPatch_funcCallExpr openDevCall(*openFunctions[0], openArgs); // Allocate file descriptor BPatch_variableExpr *devFd = appProc->malloc(*appImage->findType("int")); // Assign fd with result of open call BPatch_arithExpr openDevice(BPatch_assign, *devFd, openDevCall); // defFd check BPatch_boolExpr devFdCheck(BPatch_lt, *devFd, BPatch_constExpr(0)); // perror message BPatch_Vector<BPatch_snippet*> devFdErrorArgs; BPatch_constExpr devFdErrorMsg("Opening imitate kernel device"); devFdErrorArgs.push_back(&devFdErrorMsg); BPatch_funcCallExpr devFdError(*perrorFuncs[0], devFdErrorArgs); BPatch_Vector<BPatch_snippet*> openErrorBlock; openErrorBlock.push_back(&devFdError); openErrorBlock.push_back(&exitOnErrorCall); // if (devFd < 0) { perror(...) } BPatch_ifExpr devFdBlock(devFdCheck, BPatch_sequence(openErrorBlock)); mainEntryBlock.push_back(&openDevice); mainEntryBlock.push_back(&devFdBlock); /************************************************************************* * Send ioctl IMITATE_APP_RECORD to module * *************************************************************************/ // find ioctl() BPatch_Vector<BPatch_function*> ioctlFunctions; appImage->findFunction("ioctl", ioctlFunctions); if (ioctlFunctions.size() == 0) appImage->findFunction("_ioctl", ioctlFunctions); if (ioctlFunctions.size() == 0) appImage->findFunction("__ioctl", ioctlFunctions); if(ioctlFunctions.size() == 0) { fprintf(stderr, "Could not find ioctl() function"); return 2; } // ioctl() arguments BPatch_Vector<BPatch_snippet*> ioctlArgs; BPatch_constExpr operation(IMITATE_APP_RECORD); fprintf(stderr, "PPID: %d\n", getppid()); BPatch_constExpr monitorPid(getppid()); ioctlArgs.push_back(devFd); ioctlArgs.push_back(&operation); ioctlArgs.push_back(&monitorPid); // ioctl() call BPatch_funcCallExpr ioctlCall(*ioctlFunctions[0], ioctlArgs); // ioctl() result check BPatch_boolExpr ioctlCheck(BPatch_lt, ioctlCall, BPatch_constExpr(0)); // perror message BPatch_Vector<BPatch_snippet*> ioctlErrorArgs; BPatch_constExpr ioctlErrorMsg("Notifying imitate kernel driver of RECORD"); ioctlErrorArgs.push_back(&ioctlErrorMsg); BPatch_funcCallExpr ioctlError(*perrorFuncs[0], ioctlErrorArgs); BPatch_Vector<BPatch_snippet*> ioctlErrorBlock; ioctlErrorBlock.push_back(&ioctlError); ioctlErrorBlock.push_back(&exitOnErrorCall); // if (ioctl(...) < 0) { perror(...) } BPatch_ifExpr ioctlBlock(ioctlCheck, BPatch_sequence(ioctlErrorBlock)); // Add ioctl check to entry block mainEntryBlock.push_back(&ioctlBlock); /************************************************************************* * Counter mmap() * *************************************************************************/ // Find the mmap function BPatch_Vector<BPatch_function*> mmapFuncs; appImage->findFunction("mmap", mmapFuncs); if (mmapFuncs.size() == 0) appImage->findFunction("_mmap", mmapFuncs); if (mmapFuncs.size() == 0) appImage->findFunction("__mmap", mmapFuncs); if(mmapFuncs.size() == 0) { fprintf(stderr, "Could not find mmap() function"); return 2; } // Allocate counter BPatch_variableExpr *counterAddr = appProc->malloc(sizeof(sched_counter_t*)); sched_counter_t counterVal = 0; counterAddr->writeValue(&counterVal, sizeof(sched_counter_t*), false); // Notify kernel of address BPatch_Vector<BPatch_snippet*> mmapArgs; BPatch_constExpr mmapStart(0); BPatch_constExpr mmapLength(sizeof(sched_counter_t)); BPatch_constExpr mmapProt(PROT_READ | PROT_WRITE); BPatch_constExpr mmapFlags(MAP_SHARED); BPatch_constExpr mmapOffset(0); mmapArgs.push_back(&mmapStart); mmapArgs.push_back(&mmapLength); mmapArgs.push_back(&mmapProt); mmapArgs.push_back(&mmapFlags); mmapArgs.push_back(devFd); mmapArgs.push_back(&mmapOffset); // mmap() call BPatch_funcCallExpr mmapCall(*mmapFuncs[0], mmapArgs); // assign result to counterAddr BPatch_arithExpr mmapAssign(BPatch_assign, *counterAddr, mmapCall); // Add to entry block mainEntryBlock.push_back(&mmapAssign); // mmap() result check BPatch_boolExpr mmapCheck(BPatch_eq, *counterAddr, BPatch_constExpr(MAP_FAILED)); // perror message BPatch_Vector<BPatch_snippet*> mmapErrorArgs; BPatch_constExpr mmapErrorMsg("Memory mapping schedule (back edge) counter"); mmapErrorArgs.push_back(&mmapErrorMsg); BPatch_funcCallExpr mmapError(*perrorFuncs[0], mmapErrorArgs); BPatch_Vector<BPatch_snippet*> mmapErrorBlock; mmapErrorBlock.push_back(&mmapError); mmapErrorBlock.push_back(&exitOnErrorCall); // if (mmap(...) == MAP_FAILED) { perror(...) } BPatch_ifExpr mmapBlock(mmapCheck, BPatch_sequence(mmapErrorBlock)); mainEntryBlock.push_back(&mmapBlock); // Patch main entry BPatch_sequence mainEntrySeq(mainEntryBlock); appProc->insertSnippet(mainEntrySeq, *mainPoints); /************************************************************************* * Back-edge patching * *************************************************************************/ #if 0 printf("intCounter address: %x\n PID: %d\n", intCounter->getBaseAddr(), appProc->getPid()); fflush(stdout); #endif // Find the mutex lock/unlock functions BPatch_Vector<BPatch_function*> mutexLockFunctions; appImage->findFunction("pthread_mutex_lock", mutexLockFunctions); if (mutexLockFunctions.size() == 0) appImage->findFunction("_pthread_mutex_lock", mutexLockFunctions); if (mutexLockFunctions.size() == 0) appImage->findFunction("__pthread_mutex_lock", mutexLockFunctions); if(mutexLockFunctions.size() == 0) { fprintf(stderr, "Could not find pthread_mutex_lock() function"); return 2; } BPatch_Vector<BPatch_function*> mutexUnlockFunctions; appImage->findFunction("pthread_mutex_unlock", mutexUnlockFunctions); if (mutexUnlockFunctions.size() == 0) appImage->findFunction("_pthread_mutex_unlock", mutexUnlockFunctions); if (mutexUnlockFunctions.size() == 0) appImage->findFunction("__pthread_mutex_unlock", mutexUnlockFunctions); if(mutexUnlockFunctions.size() == 0) { fprintf(stderr, "Could not find pthread_mutex_unlock() function"); return 2; } // Allocate a mutex pthread_mutex_t mutexValue = PTHREAD_MUTEX_INITIALIZER; BPatch_variableExpr *mutex = appProc->malloc(sizeof(pthread_mutex_t)); mutex->writeValue(&mutexValue, sizeof(pthread_mutex_t), false); // Build mutex lock call BPatch_Vector<BPatch_snippet*> mutexArgs; BPatch_constExpr mutexAddress(mutex->getBaseAddr()); mutexArgs.push_back(&mutexAddress); BPatch_funcCallExpr mutexLockCall(*mutexLockFunctions[0], mutexArgs); BPatch_funcCallExpr mutexUnlockCall(*mutexUnlockFunctions[0], mutexArgs); BPatch_arithExpr derefCounter(BPatch_deref, *counterAddr); // Create 'increment counter' snippet BPatch_arithExpr addOneToCounter(BPatch_assign, derefCounter, BPatch_arithExpr(BPatch_plus, derefCounter, BPatch_constExpr(1))); BPatch_Vector<BPatch_snippet*> snippet; snippet.push_back(&mutexLockCall); snippet.push_back(&addOneToCounter); snippet.push_back(&mutexUnlockCall); BPatch_sequence addOneAtomic(snippet); char *name = (char*) malloc(sizeof(char)*200); char *modname = (char*) malloc(sizeof(char)*200); if (! (name && modname)) { fprintf(stderr, "%s %d: Out of memory!", __FILE__, __LINE__); return 1; } appProc->beginInsertionSet(); // Iterate through the procedures for (int i = 0; i < functions->size(); i++) { (*functions)[i]->getName(name, 199); (*functions)[i]->getModuleName(modname, 199); if ((patchall && strcmp(modname, "DEFAULT_MODULE") != 0) || strncmp(name, "pthread", 7) == 0 || strncmp(modname, "libpthread", 10) == 0 || strncmp(modname, "libdyninst", 10) == 0 || (name[0] == '_' && name[1] != '_' && strncmp(modname, "libc", 4) == 0)) continue; fprintf(stderr, "patcher: Patching function: '%s' (%s)", name, modname); // Patch back-edge for call if (strcmp(name, "main") != 0) appProc->insertSnippet(addOneAtomic, *((*functions)[i]->findPoint(BPatch_entry))); // Get the control flow graph for the procedure BPatch_flowGraph *graph = (*functions)[i]->getCFG(); // Find the loops BPatch_Vector<BPatch_basicBlockLoop*> *loops = new BPatch_Vector<BPatch_basicBlockLoop*>(); graph->getLoops(*loops); // Patch the loop back-edges for(int j = 0; j < loops->size(); j++) { appProc->insertSnippet(addOneAtomic, *((*loops)[j]->getBackEdge()->getPoint())); fprintf(stderr, ".", (int) (*loops)[j]->getBackEdge()->getPoint()->getAddress()); } fprintf(stderr, "\n"); // Free the loops found delete(loops); } fprintf(stderr, "Finalising patches..."); fflush(stderr); appProc->finalizeInsertionSet(false); fprintf(stderr, "Done.\n----------------------------------------\n"); // Clear up memory used to store the name free(name); free(modname); #if 0 /************************************************************************* * Exit point counter print patch * *************************************************************************/ // Patch exit() function to print out no of back branches at the end // Get exit() exit point BPatch_Vector<BPatch_point*> *exitPoints = exitFuncs[0]->findPoint(BPatch_entry); // Build printf() call: // printf("Total Total Back-branches: %d\n", counter); // Build arguments to printf() BPatch_Vector<BPatch_snippet*> printfArgs; BPatch_constExpr formatString("Total Back-branches: %d\n"); printfArgs.push_back(&formatString); printfArgs.push_back(&derefCounter); // Build call to printf() BPatch_funcCallExpr printfCall(*printfFuncs[0], printfArgs); // Patch into exit() appProc->insertSnippet(printfCall, *exitPoints); #endif // Continue mutatee... appProc->continueExecution(); // Wait for mutatee to finish while (!appProc->isTerminated()) { bpatch.waitForStatusChange(); } fprintf(stderr, "----------------------------------------\n"); fprintf(stderr, "Done.\n"); return 0; }
test_results_t test1_23_Mutator::executeTest() { const char *funcName = "test1_23_call1"; BPatch_Vector<BPatch_function *> found_funcs; if ((NULL == appImage->findFunction(funcName, found_funcs, 1)) || !found_funcs.size()) { logerror(" Unable to find function %s\n", funcName); return FAILED; } if (1 < found_funcs.size()) { logerror("%s[%d]: WARNING : found %d functions named %s. Using the first.\n", __FILE__, __LINE__, found_funcs.size(), funcName); } BPatch_Vector<BPatch_point *> *point23_calls = found_funcs[0]->findPoint(BPatch_subroutine); if (!point23_calls || (point23_calls->size() < 1)) { logerror("**Failed** test #23 (local variables)\n"); logerror(" Unable to find point %s - subroutine calls\n", funcName); return FAILED; } /* We only want the first one... */ BPatch_Vector<BPatch_point *> point23_1; point23_1.push_back((*point23_calls)[0]); BPatch_variableExpr *var1 = appImage->findVariable(*(point23_1[0]), "localVariable23_1"); BPatch_variableExpr *var2 = appImage->findVariable(*(point23_1[0]), "test1_23_shadowVariable1"); BPatch_variableExpr *var3 = appImage->findVariable("test1_23_shadowVariable2"); BPatch_variableExpr *var4 = appImage->findVariable("test1_23_globalVariable1"); if (!var1 || !var2 || !var3 || !var4) { logerror("**Failed** test #23 (local variables)\n"); if (!var1) { logerror(" can't find local variable localVariable23_1\n"); BPatch_function *f = point23_1[0]->getCalledFunction(); assert(f); BPatch_Vector<BPatch_localVar *> *lvars = f->getVars(); assert(lvars); logerror("%s[%d]: have vars\n", FILE__, __LINE__); for (unsigned int i = 0; i < lvars->size(); ++i) { logerror("\t%s\n", (*lvars)[i]->getName()); } } if (!var2) logerror(" can't find local variable test1_23_shadowVariable1\n"); if (!var3) logerror(" can't find global variable test1_23_shadowVariable2\n"); return FAILED; } BPatch_arithExpr expr23_1(BPatch_assign, *var1, BPatch_constExpr(2300001)); BPatch_arithExpr expr23_2(BPatch_assign, *var2, BPatch_constExpr(2300012)); BPatch_arithExpr expr23_3(BPatch_assign, *var3, BPatch_constExpr(2300023)); BPatch_arithExpr expr23_4(BPatch_assign, *var4, *var1); BPatch_Vector<BPatch_snippet *> exprs; exprs.push_back(&expr23_1); exprs.push_back(&expr23_2); exprs.push_back(&expr23_3); exprs.push_back(&expr23_4); BPatch_sequence allParts(exprs); appAddrSpace->insertSnippet(allParts, point23_1); return PASSED; }
test_results_t test1_28_Mutator::executeTest() { int i; if (isMutateeFortran(appImage)) { return SKIPPED; } // Create the types BPatch_type *intType = appImage->findType("int"); assert(intType); BPatch_Vector<char *> names; BPatch_Vector<BPatch_type *> types; names.push_back(const_cast<char*>("field1")); names.push_back(const_cast<char*>("field2")); types.push_back(intType); types.push_back(intType); // struct28_1 { int field1, int field 2; } BPatch_type *struct28_1 = BPatch::bpatch->createStruct("test1_28_struct1", names, types); BPatch_type *union28_1 = BPatch::bpatch->createUnion("testUnion27_1", names, types); assert(union28_1); names.push_back(const_cast<char*>("field3")); names.push_back(const_cast<char*>("field4")); BPatch_type *intArray = BPatch::bpatch->createArray("intArray", intType, 0, 9); types.push_back(intArray); types.push_back(struct28_1); // struct28_2 { int field1, int field 2, int field3[10],struct26_1 field4 } BPatch_type *struct28_2 = BPatch::bpatch->createStruct("test1_28_struct2", names, types); BPatch_type *type28_2 = BPatch::bpatch->createTypedef("type28_2", struct28_2); // now create variables of these types. BPatch_variableExpr *globalVariable28_1 = appImage->findVariable("test1_28_globalVariable1"); if (!globalVariable28_1) { logerror("[%s:%u] - Unable to find variable test1_28_globalVariable1\n", __FILE__, __LINE__); return FAILED; } globalVariable28_1->setType(type28_2); BPatch_variableExpr *globalVariable28_8 = appImage->findVariable("test1_28_globalVariable8"); if (!globalVariable28_8) { logerror("[%s:%u] - Unable to find variable test1_28_globalVariable8\n", __FILE__, __LINE__); return FAILED; } globalVariable28_8->setType(union28_1); // Next verify that we can find a local variable in call28 const char *fname = "test1_28_call1"; BPatch_Vector<BPatch_function *> found_funcs; if ((NULL == appImage->findFunction(fname, found_funcs)) || !found_funcs.size()) { logerror(" Unable to find function %s\n", fname); return FAILED; } if (1 < found_funcs.size()) { logerror("%s[%d]: WARNING : found %d functions named %s. Using the first.\n", __FILE__, __LINE__, found_funcs.size(), fname); } BPatch_Vector<BPatch_point *> *point28 = found_funcs[0]->findPoint(BPatch_entry); assert(point28 && (point28->size() == 1)); // FIXME We didn't look up a local variable!? BPatch_variableExpr *gvar[8]; for (i=1; i <= 7; i++) { char name[80]; sprintf(name, "test1_28_globalVariable%d", i); gvar[i] = appImage->findVariable(name); if (!gvar[i]) { logerror("**Failed** test #28 (user defined fields)\n"); logerror(" can't find variable %s\n", name); return FAILED; } } // start of code for globalVariable28 BPatch_Vector<BPatch_variableExpr *> *fields = gvar[1]->getComponents(); assert(fields && (fields->size() == 4)); for (i=0; i < 4; i++) { char fieldName[80]; sprintf(fieldName, "field%d", i+1); if (strcmp(fieldName, (*fields)[i]->getName())) { logerror("field %d of the struct is %s, not %s\n", i+1, fieldName, (*fields)[i]->getName()); return FAILED; } } // globalVariable28 = globalVariable28.field1 BPatch_arithExpr assignment1(BPatch_assign, *gvar[2], *((*fields)[0])); appAddrSpace->insertSnippet(assignment1, *point28); // globalVariable28 = globalVariable28.field2 BPatch_arithExpr assignment2(BPatch_assign, *gvar[3], *((*fields)[1])); appAddrSpace->insertSnippet(assignment2, *point28); // globalVariable28 = globalVariable28.field3[0] BPatch_arithExpr assignment3(BPatch_assign, *gvar[4], BPatch_arithExpr(BPatch_ref, *((*fields)[2]), BPatch_constExpr(0))); appAddrSpace->insertSnippet(assignment3, *point28); // globalVariable28 = globalVariable28.field3[5] BPatch_arithExpr assignment4(BPatch_assign, *gvar[5], BPatch_arithExpr(BPatch_ref, *((*fields)[2]), BPatch_constExpr(5))); appAddrSpace->insertSnippet(assignment4, *point28); BPatch_Vector<BPatch_variableExpr *> *subfields = (*fields)[3]->getComponents(); assert(subfields != NULL); // globalVariable28 = globalVariable28.field4.field1 BPatch_arithExpr assignment5(BPatch_assign, *gvar[6], *((*subfields)[0])); appAddrSpace->insertSnippet(assignment5, *point28); // globalVariable28 = globalVariable28.field4.field2 BPatch_arithExpr assignment6(BPatch_assign, *gvar[7], *((*subfields)[1])); appAddrSpace->insertSnippet(assignment6, *point28); // BPatch_Vector<BPatch_variableExpr *> *unionfields = globalVariable28_8->getComponents(); int n=1; int val1, val2, val3; ((*unionfields)[0])->writeValue(&n,true); ((*unionfields)[0])->readValue(&val1); if (val1 != 1) { logerror("**Failed** test #28 (user defined fields)\n"); logerror(" union field1 has wrong value after first set\n"); return FAILED; } n=2; ((*unionfields)[1])->writeValue(&n,true); ((*unionfields)[1])->readValue(&val2); if (val2 != 2) { logerror("**Failed** test #28 (user defined fields)\n"); logerror(" union field2 has wrong value after second set\n"); return FAILED; } ((*unionfields)[1])->readValue(&val3); if (val3 != 2) { logerror("**Failed** test #28 (user defined fields)\n"); logerror(" union field1 has wrong value after second set\n"); return FAILED; } // create a scalar BPatch_type *newScalar1 = BPatch::bpatch->createScalar("scalar1", 8); assert(newScalar1); int scalarSize = newScalar1->getSize(); if (scalarSize != 8) { logerror("**Failed** test #28 (user defined fields)\n"); logerror(" created scalar is %d bytes, expected %d\n", scalarSize, 8); return FAILED; } // create an enum BPatch_Vector<char *> enumItems; BPatch_Vector<int> enumVals; enumItems.push_back(const_cast<char*>("item1")); enumItems.push_back(const_cast<char*>("item2")); enumItems.push_back(const_cast<char*>("item3")); enumVals.push_back(42); enumVals.push_back(43); enumVals.push_back(44); BPatch_type *newEnum1 = BPatch::bpatch->createEnum("enum1", enumItems); BPatch_type *newEnum2 = BPatch::bpatch->createEnum("enum2", enumItems, enumVals); if (!newEnum1 || !newEnum2) { logerror("**Failed** test #28 (user defined fields)\n"); logerror(" failed to create enums as expected\n"); return FAILED; } if (!newEnum1->isCompatible(newEnum1)) { logerror("**Failed** test #28 (user defined fields)\n"); logerror(" identical enums reported incompatible\n"); return FAILED; } if (newEnum1->isCompatible(newEnum2)) { logerror("**Failed** test #28 (user defined fields)\n"); logerror(" different enums declared compatible\n"); return FAILED; } return PASSED; }
test_results_t snip_ref_shlib_var_Mutator::mutatorTest() { // The check function returns 1 on success (value changed as expected) // or 0 on failure. const char *check_fname = "check_snip_ref_shlib_var"; const char *inst_func_name = "srsv1"; BPatch_Vector<BPatch_function *> funcs; appImage->findFunction(inst_func_name, funcs); if (!funcs.size()) { logerror("%s[%d]: failed to find function %s\n", FILE__, __LINE__, inst_func_name); return FAILED; } BPatch_function *inst_func = funcs[0]; std::vector<BPatch_point *> *pts= inst_func->findPoint(BPatch_entry); if (!pts || !pts->size()) { logerror("%s[%d]: failed to find entry point to %s\n", FILE__, __LINE__, inst_func_name); return FAILED; } BPatch_point *entry_point = (*pts)[0]; BPatch_Vector<BPatch_snippet *> allInst; BPatch_snippet *snip; snip = doVarAssign("gv_srsv1", "snip_ref_shlib_var1"); if (NULL == snip) return FAILED; allInst.push_back(snip); snip = doVarAssign("gv_srsv2", "snip_ref_shlib_var2"); if (NULL == snip) return FAILED; allInst.push_back(snip); snip = doVarArrayAssign("gv_srsv3", "snip_ref_shlib_var3", 0); if (NULL == snip) return FAILED; allInst.push_back(snip); snip = doVarAssign("gv_srsv4", "snip_ref_shlib_var4"); if (NULL == snip) return FAILED; allInst.push_back(snip); snip = doVarAssign("gv_srsv5", "snip_ref_shlib_var5"); if (NULL == snip) return FAILED; allInst.push_back(snip); #if 0 snip = doVarAssign("gv_srsv6", "snip_ref_shlib_var6"); if (NULL == snip) return FAILED; allInst.push_back(snip); #endif snip = doVarArrayAssign("gv_srsv7", "snip_ref_shlib_var7", 0); if (NULL == snip) return FAILED; allInst.push_back(snip); BPatch_sequence my_ass(allInst); if (!appAddrSpace->insertSnippet(my_ass, *entry_point)) { logerror("%s[%d]: failed to insert snippet\n", FILE__, __LINE__); return FAILED; } return PASSED; }
bool initTraceInMutatee(dynHandle *dh) { // Chicken: Can't use goto for error handling because it would branch past // variable initialization. // Egg: Can't define variables at top of function (with dummy constructors) // because BPatch_funcCallExpr() needs a valid BPatch_function object. // Temporary solution: Deviate from similar functions and rely on external // error handling. // Permanent solution: BPatch_snippet and derivitives should have default // constructors. int value; BPatch_function *openFunc; BPatch_Vector< BPatch_function * > funcs; sendMsg(config.outfd, ID_TRACE_FIND_OPEN, VERB2, ID_TEST); if (!dh->image->findFunction("^(__)?open(64)?$", funcs)) { sendMsg(config.outfd, ID_TRACE_FIND_OPEN, VERB2, ID_FAIL, "Failure in BPatch_image::findFunction()"); return false; } else if (funcs.size() == 0) { sendMsg(config.outfd, ID_TRACE_FIND_OPEN, VERB2, ID_FAIL, "Could not find any functions named 'open' in mutatee"); return false; } sendMsg(config.outfd, ID_TRACE_FIND_OPEN, VERB2, ID_PASS); openFunc = funcs[0]; // // Initialize global variables // trace_msglen = sizeof(void *) * 2; trace_fd = allocateIntegerInMutatee(dh, -1); funcs.clear(); sendMsg(config.outfd, ID_TRACE_FIND_WRITE, VERB2); if (!dh->image->findFunction("^(__)?write$", funcs)) { sendMsg(config.outfd, ID_TRACE_FIND_WRITE, VERB2, ID_FAIL, "Failure in BPatch_image::findFunction()"); return false; } else if (funcs.size() == 0) { sendMsg(config.outfd, ID_TRACE_FIND_WRITE, VERB2, ID_FAIL, "Could not find any functions named 'write' in mutatee"); return false; } sendMsg(config.outfd, ID_TRACE_FIND_WRITE, VERB2, ID_PASS); trace_write = funcs[0]; // "open(config.pipe_filename, O_WRONLY | O_DSYNC)" BPatch_constExpr path(config.pipe_filename); BPatch_constExpr flags(O_WRONLY | O_DSYNC); BPatch_Vector< BPatch_snippet * > param; param.push_back( &path ); param.push_back( &flags ); BPatch_funcCallExpr openCall(*openFunc, param); // Problem child. See above. // "fd = open(config.pipe_filename, O_WRONLY)" BPatch_arithExpr assign(BPatch_assign, *trace_fd, openCall); // Run the snippet. sendMsg(config.outfd, ID_TRACE_OPEN_WRITER, VERB2); dh->proc->oneTimeCode(assign); trace_fd->readValue(&value); if (value < 0) { sendMsg(config.outfd, ID_TRACE_OPEN_WRITER, VERB2, ID_FAIL, "Error detected in mutatee's call to open()"); return false; } sendMsg(config.outfd, ID_TRACE_OPEN_WRITER, VERB2, ID_PASS); return true; }
// // Start Test Case #3 - (overload operator) // // static int mutatorTest(BPatch_thread *appThread, BPatch_image *appImage) test_results_t test5_3_Mutator::executeTest() { BPatch_Vector<BPatch_function *> bpfv; const char *fn = "overload_op_test::func_cpp"; if (NULL == appImage->findFunction(fn, bpfv) || !bpfv.size() || NULL == bpfv[0]){ logerror("**Failed** test #3 (overloaded operation)\n"); logerror(" Unable to find function %s\n", fn); return FAILED; } BPatch_function *f1 = bpfv[0]; BPatch_Vector<BPatch_point *> *point3_1 = f1->findPoint(BPatch_subroutine); assert(point3_1); if (point3_1->size() == 0) { logerror("**Failed test5_3 (overload operation)\n"); logerror(" Can't find overloaded operator call points\n"); return FAILED; } unsigned int index = 0; char fn3[256]; BPatch_function *func; while (index < point3_1->size()) { if ((func = (*point3_1)[index]->getCalledFunction()) != NULL && !strcmp("overload_op_test::operator++", func->getName(fn3, 256))) { break; } index ++; } if(!func) { logerror("**Failed** test #3 (overload operation)\n"); logerror(" Can't find the overload operator\n"); return FAILED; } if (0 != strcmp("overload_op_test::operator++", func->getName(fn3, 256))) { logerror("**Failed** test #3 (overload operation)\n"); logerror(" Can't find the overloaded operator\n"); return FAILED; } // FIXME It caught fprintf... BPatch_Vector<BPatch_point *> *point3_2 = func->findPoint(BPatch_exit); assert(point3_2); bpfv.clear(); const char *fn2 = "overload_op_test::call_cpp"; if (NULL == appImage->findFunction(fn2, bpfv) || !bpfv.size() || NULL == bpfv[0]){ logerror("**Failed** test #3 (overloaded operation)\n"); logerror(" Unable to find function %s\n", fn2); return FAILED; } BPatch_function *call3_1 = bpfv[0]; BPatch_variableExpr *this2 = appImage->findVariable("test5_3_test3"); if (this2 == NULL) { logerror( "**Failed** test #3 (overloaded operation)\n"); logerror( "Unable to find variable \"test5_3_test3\"\n"); return FAILED; } BPatch_Vector<BPatch_snippet *> opArgs; BPatch_arithExpr expr2_0(BPatch_addr, *this2); opArgs.push_back(&expr2_0); opArgs.push_back(new BPatch_retExpr()); BPatch_funcCallExpr call3_1Expr(*call3_1, opArgs); checkCost(call3_1Expr); appAddrSpace->insertSnippet(call3_1Expr, *point3_2); // int tag = 1; // while (tag != 0) {} return PASSED; }
test_results_t test1_40_Mutator::executeTest() { const char *monitorFuncName = "test1_40_monitorFunc"; const char *callSiteAddrVarName = "test1_40_callsite5_addr"; BPatch_function *monitorFunc = NULL; BPatch_Vector<BPatch_function *> bpfv; BPatch_function *call40_1 = findFunction40("test1_40_call1", appImage); RETURNONNULL(call40_1); RETURNONFAIL(setVar40("test1_40_addr_of_call1", call40_1->getBaseAddr(),appImage)); BPatch_function *call40_2 = findFunction40("test1_40_call2", appImage); RETURNONNULL(call40_2); RETURNONFAIL(setVar40("test1_40_addr_of_call2", call40_2->getBaseAddr(),appImage)); BPatch_function *call40_3 = findFunction40("test1_40_call3", appImage); RETURNONNULL(call40_3); RETURNONFAIL(setVar40("test1_40_addr_of_call3", call40_3->getBaseAddr(),appImage)); // call40_5 is the "dispatcher" of function pointers BPatch_function *targetFunc = findFunction40("test1_40_call5", appImage); RETURNONNULL(targetFunc); //RETURNONFAIL(setVar40("test1_40_addr_of_call5", call40_5->getBaseAddr(),appImage)); monitorFunc = findFunction40(monitorFuncName, appImage); RETURNONNULL(monitorFunc); BPatch_Vector<BPatch_point *> *calls = targetFunc->findPoint(BPatch_subroutine); if (!calls) { logerror("**Failed test #40 (monitor call sites)\n"); logerror(" cannot find call points for test1_40_call5\n"); return FAILED; } BPatch_Vector<BPatch_point *> dyncalls; for (unsigned int i = 0; i < calls->size(); ++i) { BPatch_point *pt = (*calls)[i]; if (pt->isDynamic()) dyncalls.push_back(pt); } if (dyncalls.size() != 1) { logerror("**Failed test #40 (monitor call sites)\n"); logerror(" wrong number of dynamic points found (%d -- not 1)\n", dyncalls.size()); logerror(" total number of calls found: %d\n", calls->size()); return FAILED; } // write address of anticipated call site into mutatee var. void *callsite_address = dyncalls[0]->getAddress(); RETURNONFAIL(setVar40(callSiteAddrVarName, callsite_address, appImage)); // issue command to monitor calls at this site, and we're done. if (! dyncalls[0]->monitorCalls(monitorFunc)) { logerror("**Failed test #40 (monitor call sites)\n"); logerror(" cannot monitor calls\n"); return FAILED; } return PASSED; }