/** a basic block is instrumented if it is one of the leaf nodes * in the immediate dominator tree of the control flow graph * or it has an outgoing edge to a basic block that it does * not dominate */ bool FCUseDominator::validateBasicBlock(BPatch_basicBlock* bb){ bool ret = false; BPatch_Vector<BPatch_basicBlock*> immediateDominates; bb->getImmediateDominates(immediateDominates); /** if it is a leaf node */ if(!immediateDominates.size()) ret = true; else{ /** or it has outgoing edge to basic block * it does not dominate */ BPatch_Set<BPatch_basicBlock*> allDom; bb->getAllDominates(allDom); BPatch_Vector<BPatch_basicBlock*> targets; bb->getTargets(targets); for(unsigned int j=0;j<targets.size();j++) if(!allDom.contains(targets[j])){ /** target is not in the set * basic block dominates */ ret = true; break; } } return ret; }
/** * Build a CFG on top of the BPatch_flowGraph that matches * the original, but with an extra entry block and using * dominatorBB's instead of BPatch_basicBlocks. **/ void dominatorBB::dominatorPredAndSucc() { unsigned i; if (!bpatchBlock) return; //Predecessors BPatch_Vector<BPatch_basicBlock*> blocks; bpatchBlock->getSources(blocks); for (i=0; i<blocks.size(); i++) { dominatorBB *p = dom_cfg->bpatchToDomBB(blocks[i]); assert(p); pred.push_back(p); } if (bpatchBlock->isEntryBlock() || !blocks.size()) { dom_cfg->entryBlock->succ.push_back(this); pred.push_back(dom_cfg->entryBlock); } //Successors blocks.clear(); bpatchBlock->getTargets(blocks); for (i=0; i<blocks.size(); i++) { dominatorBB *s = dom_cfg->bpatchToDomBB(blocks[i]); assert(s); succ.push_back(s); } }
void Instrumentcall (BPatch_image *appImage, BPatch_process *appProcess) { unsigned insertion = 0; unsigned i = 0; BPatch_Vector<BPatch_function *> *vfunctions = appImage->getProcedures (true); cout << vfunctions->size() << " functions found in binary " << endl; cout << "Parsing functions " << flush; while (i < vfunctions->size()) { char name[1024], sharedlibname[1024]; BPatch_function *f = (*vfunctions)[i]; (f->getModule())->getFullName (sharedlibname, 1024); f->getName (name, 1024); BPatch_Vector<BPatch_point *> *vpoints = f->findPoint (BPatch_subroutine); unsigned j = 0; while (j < vpoints->size()) { BPatch_function *called = ((*vpoints)[j])->getCalledFunction(); if (NULL != called) { char calledname[1024]; called->getName (calledname, 1024); if (strcmp (calledname, "functionB") == 0) { string s = "functionA"; BPatch_function *patch = getRoutine (s, appImage); if (patch != NULL) { bool replaced = appProcess->replaceFunctionCall (*((*vpoints)[j]), *patch); if (replaced) cout << "call to functionA has been successfully replaced by a call to functionB" << endl; else cout << "call to functionA failed to replace a call to functionB" << endl; insertion++; } } } j++; } i++; } cout << endl; cout << "insertion = " << insertion << endl; }
static BPatch_function *findFunction40(const char *fname, BPatch_image *appImage) { BPatch_Vector<BPatch_function *> bpfv; if (NULL == appImage->findFunction(fname, bpfv) || (bpfv.size() != 1)) { logerror("**Failed test #40 (monitor call sites)\n"); logerror(" Expected 1 functions matching %s, got %d\n", fname, bpfv.size()); return NULL; } return bpfv[0]; }
static void ShowFunctions (BPatch_image *appImage) { BPatch_Vector<BPatch_function *> *vfunctions = appImage->getProcedures (false); cout << PACKAGE_NAME << ": " << vfunctions->size() << " functions found in binary " << endl; unsigned i = 0; while (i < vfunctions->size()) { char name[1024]; BPatch_function *f = (*vfunctions)[i]; f->getName (name, 1024); if (VerboseLevel) { char mname[1024], tname[1024], modname[1024]; f->getMangledName (mname, 1024); f->getTypedName (tname, 1024); f->getModuleName (modname, 1024); cout << " * " << i+1 << " of " << vfunctions->size() << ", Name: " << name << endl << " Mangled Name: " << mname << endl << " Typed Name : " << tname << endl << " Module name : " << modname << endl << " Base address: " << f->getBaseAddr() << endl << " Instrumentable? " << (f->isInstrumentable()?"yes":"no") << endl << " In shared library? " << (f->isSharedLib()?"yes":"no") << endl << " Number of BB: " << getBasicBlocksSize(f) << endl; if (f->isSharedLib()) { char sharedlibname[1024]; BPatch_module *mod = f->getModule(); mod->getFullName (sharedlibname, 1024); cout << " Full library name: " << sharedlibname << endl; } cout << endl; } else { cout << name << endl; } i++; } }
/* * BPatch_image::findType * * Returns a BPatch_type* representing the named type. If no such type * exists, returns NULL. * * name The name of type to look up. */ BPatch_type *BPatch_image::findTypeInt(const char *name) { BPatch_type *type; assert(BPatch::bpatch != NULL); // XXX - should this stuff really be by image ??? jkh 3/19/99 BPatch_Vector<BPatch_module *> *mods = getModules(); for (int m = mods->size() -1; m >= 0; m--) { BPatch_module *module = (*mods)[m]; type = module->getModuleTypes()->findType(name); if (type) { return type; } } // check the default base types type = BPatch::bpatch->stdTypes->findType(name); if (type) { return type; } // check the API types of last resort type = BPatch::bpatch->APITypes->findType(name); return type; }
/* * 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 test_thread_2_Mutator::dumpVars() { BPatch_Vector<BPatch_variableExpr *> vars; appImage->getVariables(vars); for (unsigned int i = 0; i < vars.size(); ++i) { logerror("\t%s\n", vars[i]->getName()); } }
BPatch_function* getMutateeFunction(const char *name) { BPatch_Vector<BPatch_function *> funcs; mainImg->findFunction(name, funcs, true, true, true); if (funcs.size() != 1) return NULL; return funcs.at(0); }
ostream& operator<<(ostream& os,BPatch_basicBlock& bb) { unsigned i; os << "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; os << "Basic Block : " << bb.blockNo() <<" : [ "; os << ostream::hex << bb.getStartAddress() << " , "; os << ostream::hex << bb.getLastInsnAddress() << " | "; os << ostream::dec << bb.getEndAddress() - bb.getStartAddress() << " ]\n"; if(bb.isEntryBlock()) os <<"Type : ENTRY TO CFG\n"; else if(bb.isExitBlock()) os <<"Type : EXIT FROM CFG\n"; cout << "Pred :\n"; BPatch_Vector<BPatch_basicBlock *> elements; bb.getSources(elements); for (i=0; i<elements.size(); i++) os << "\t<- " << elements[i]->blockNo() << "\n"; cout << "Succ:\n"; elements.clear(); bb.getTargets(elements); for (i=0; i<elements.size(); i++) os << "\t-> " << elements[i]->blockNo() << "\n"; os << "Immediate Dominates: "; if(bb.immediateDominates){ for (std::set<BPatch_basicBlock *>::iterator iter = bb.immediateDominates->begin(); iter != bb.immediateDominates->end(); ++iter) { os << (*iter)->blockNo() << " "; } } os << "\n"; os << "Immediate Dominator: "; if(!bb.immediateDominator) os << "None\n"; else os << bb.immediateDominator->blockNo() << "\n"; os << "\n"; os << "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"; return os; }
static void ShowFunctions (BPatch_image *appImage) { BPatch_Vector<BPatch_function *> *vfunctions = appImage->getProcedures (false); cout << PACKAGE_NAME << ": " << vfunctions->size() << " functions found in binary " << endl; unsigned i = 0; while (i < vfunctions->size()) { char name[1024]; BPatch_function *f = (*vfunctions)[i]; f->getName (name, 1024); char mname[1024], tname[1024], modname[1024]; f->getMangledName (mname, 1024); f->getTypedName (tname, 1024); f->getModuleName (modname, 1024); cout << " * " << i+1 << " of " << vfunctions->size() << ", Name: " << name << endl << " Mangled Name: " << mname << endl << " Typed Name : " << tname << endl << " Module name : " << modname << endl << " Base address: " << f->getBaseAddr() << endl << " Instrumentable? " << (f->isInstrumentable()?"yes":"no") << endl << " In shared library? " << (f->isSharedLib()?"yes":"no") << endl; if (f->isSharedLib()) { //Old Dyninst API < 9.x //char sharedlibname[1024]; //mod->getFullName (sharedlibname, 1024); BPatch_module *mod = f->getModule(); string sharedlibname; sharedlibname = mod->getObject()->name(); cout << " Full library name: " << sharedlibname << endl; } cout << endl; i++; } }
bool BPatch_basicBlock::getLineNumbers(unsigned int &_startLine, unsigned int &_endLine) { BPatch_Vector<BPatch_sourceBlock *> sbvec; getSourceBlocks(sbvec); if (!sbvec.size()) return false; unsigned int temp_start = UINT_MAX, temp_end = 0; _startLine = UINT_MAX; _endLine = 0; // Loop through all source blocks and accumulate the smallest start line // and the largest end line. (is there a better way? -- don't we know this a priori?) for (unsigned int i = 0; i < sbvec.size(); ++i) { sbvec[i]->getLineNumbers(temp_start, temp_end); if (temp_start < _startLine) _startLine = temp_start; if (temp_end > _endLine) _endLine = temp_end; } return true; }
/* * 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_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; }
// // Start Test Case #1 - (zero arg function call) // test_results_t test1_1_Mutator::executeTest() { const char *funcName = "test1_1_func1_1"; const char* testName = "zero arg function call"; int testNo = 1; // Find the entry point to the procedure "func1_1" 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 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 *> *point1_1 = found_funcs[0]->findPoint(BPatch_entry); if (!point1_1 || ((*point1_1).size() == 0)) { logerror("**Failed** test #%d (%s)\n", testNo,testName); logerror(" Unable to find entry point to \"%s.\"\n", funcName); return FAILED; } BPatch_Vector<BPatch_function *> bpfv; const char *fn = "test1_1_call1_1"; if (NULL == appImage->findFunction(fn, bpfv) || !bpfv.size() || NULL == bpfv[0]){ logerror("**Failed** test #%d (%s)\n", testNo, testName); logerror(" Unable to find function %s\n", fn); return FAILED; } BPatch_function *call1_func = bpfv[0]; BPatch_Vector<BPatch_snippet *> call1_args; BPatch_funcCallExpr call1Expr(*call1_func, call1_args); checkCost(call1Expr); if(!appAddrSpace->insertSnippet(call1Expr, *point1_1)) return FAILED; dprintf("Inserted snippet\n"); return PASSED; } // test1_1_Mutator::executeTest()
bool instrumentFunctionExit(dynHandle *dh, BPatch_function *func) { BPatch_Vector<BPatch_point *> *points; BPatchSnippetHandle *handle; BPatch_snippet incSnippet; sendMsg(config.outfd, ID_INST_FUNC_EXIT, VERB2); if (! generateInstrumentation (dh, func, &incSnippet)) goto fail; sendMsg(config.outfd, ID_INST_FIND_POINTS, VERB3); points = func->findPoint(BPatch_exit); if (!points) { sendMsg(config.outfd, ID_INST_FIND_POINTS, VERB3, ID_FAIL, "Failure in BPatch_function::findPoint(BPatch_exit)"); goto fail; } else if (points->size() == 0) { sendMsg(config.outfd, ID_INST_FIND_POINTS, VERB3, ID_WARN, "No instrumentation points found in function"); goto fail; } else { sendMsg(config.outfd, ID_INST_FIND_POINTS, VERB3, ID_PASS); } sendMsg(config.outfd, ID_INST_INSERT_CODE, VERB3); if (shouldInsert()) { handle = dh->addSpace->insertSnippet(incSnippet, *points); if (!handle) { sendMsg(config.outfd, ID_INST_INSERT_CODE, VERB3, ID_FAIL, "Failure in BPatch_process::insertSnippet()"); goto fail; } else sendMsg(config.outfd, ID_INST_INSERT_CODE, VERB3, ID_PASS); } if (trace_fd) insertTraceSnippet(dh, func, points); sendMsg(config.outfd, ID_INST_FUNC_EXIT, VERB2, ID_PASS); return true; fail: sendMsg(config.outfd, ID_INST_FUNC_EXIT, VERB2, ID_WARN, "Failure while instrumenting function exit."); return false; }
/** the execution counts of the basic block given and the basic blocks * whose execution can be deduced from the given basic block is updated. * If a is immediate dominator of b and if b is executed then we can * deduce a is also executed. So this method iteratively updates * execution counts of the basic blocks through the path towards the root * of the immediate dominator tree starting from the basic block given */ int FCUseDominator::updateExecutionCounts(BPatch_basicBlock* bb,int ec){ for(BPatch_basicBlock* id = bb; id != NULL; id = id->getImmediateDominator()) { if(!executionCounts[id->getBlockNumber()]){ BPatch_Vector<BPatch_sourceBlock*> sb; id->getSourceBlocks(sb); for(unsigned int i=0;i<sb.size();i++) updateLinesCovered(sb[i]); } executionCounts[id->getBlockNumber()] += ec; } return Error_OK; }
static bool hasBackEdge(BPatch_basicBlock *bb, std::set<int> visited) { if (visited.find(bb->getBlockNumber()) != visited.end()) return true; visited.insert(bb->getBlockNumber()); BPatch_Vector<BPatch_basicBlock*> targets; bb->getTargets(targets); unsigned int i; for (i = 0; i < targets.size(); i++) { if (hasBackEdge(targets[i], visited)) return true; } return false; }
static BPatch_point *findPoint(BPatch_function *f, BPatch_procedureLocation loc, int testno, const char *testname) { assert(f); BPatch_Vector<BPatch_point *> *pts = f->findPoint(loc); if (!pts) { logerror("%s[%d]: failed to find point\n", FILE__, __LINE__); FAIL_MES(TESTNAME, TESTDESC); return NULL; } if (pts->size() != 1) { logerror("%s[%d]: failed to find point: found too many\n", FILE__, __LINE__); FAIL_MES(TESTNAME, TESTDESC); return NULL; } return (*pts)[0]; }
pd_image::pd_image(BPatch_image *d_image, pd_process *p_proc) : appImage(d_image), parent_proc(p_proc) { all_pd_images.push_back(this); BPatch_Vector<BPatch_module *> *mods = parent_proc->getAllModules(); for (unsigned int m = 0; m < mods->size(); m++) { BPatch_module *curr = (BPatch_module *) (*mods)[m]; addModule(curr); } char namebuf[NAME_LEN]; d_image->getProgramName(namebuf, NAME_LEN); _name = pdstring(namebuf); d_image->getProgramFileName(namebuf, NAME_LEN); _fname = pdstring(namebuf); //fprintf(stderr, "%s[%d]: new pd_image: '%s'/'%s'\n", // __FILE__, __LINE__, _name.c_str(), _fname.c_str()); }
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 }
// 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; }
// static bool mutatorTest3and4(int testno, const char *testname) test_results_t test_thread_2_Mutator::executeTest() { test3_threadCreateCounter = 0; callback_tids.clear(); BPatchAsyncThreadEventCallback createcb = threadCreateCB; if (!bpatch->registerThreadEventCallback(BPatch_threadCreateEvent, createcb)) { FAIL_MES(TESTNAME, TESTDESC); logerror("%s[%d]: failed to register thread callback\n", __FILE__, __LINE__); appThread->getProcess()->terminateExecution(); return FAILED; } #if 0 // unset mutateeIde to trigger thread (10) spawn. int zero = 0; // FIXME Check the return code for setVar setVar("mutateeIdle", (void *) &zero, TESTNO, TESTDESC); dprintf("%s[%d]: continue execution for test %d\n", __FILE__, __LINE__, TESTNO); appThread->continueExecution(); #endif if( !appProc->continueExecution() ) { logerror("%s[%d]: failed to continue process\n", FILE__, __LINE__); appProc->terminateExecution(); return FAILED; } // wait until we have received the desired number of events int err = 0; BPatch_Vector<BPatch_thread *> threads; BPatch_process *appProc = appThread->getProcess(); assert(appProc); appProc->getThreads(threads); int active_threads = 11; // FIXME Magic number threads.clear(); while (((test3_threadCreateCounter < TEST3_THREADS) || (active_threads > 1)) && !appProc->isTerminated() ) { dprintf("%s[%d]: waiting for completion for test; ((%d < %d) || (%d > 1)) && !(%d)\n", __FILE__, __LINE__, test3_threadCreateCounter, TEST3_THREADS, active_threads, 1, appProc->isTerminated()); if( !bpatch->waitForStatusChange() ) { logerror("%s[%d]: failed to wait for events\n", __FILE__, __LINE__); err = 1; break; } appProc->getThreads(threads); active_threads = threads.size(); threads.clear(); } if( appProc->isTerminated() ) { logerror("%s[%d]: BAD NEWS: somehow the process died\n", __FILE__, __LINE__); return FAILED; } dprintf("%s[%d]: ending test %d, num active threads = %d\n", __FILE__, __LINE__, TESTNO, active_threads); dprintf("%s[%d]: stop execution for test %d\n", __FILE__, __LINE__, TESTNO); appProc->stopExecution(); // read all tids from the mutatee and verify that we got them all unsigned long mutatee_tids[TEST3_THREADS]; const char *threads_varname = "test3_threads"; if (getVar(threads_varname, (void *) mutatee_tids, (sizeof(unsigned long) * TEST3_THREADS), TESTNO, TESTDESC)) { appProc->terminateExecution(); return FAILED; } if (debugPrint()) { dprintf("%s[%d]: read following tids for test%d from mutatee\n", __FILE__, __LINE__, TESTNO); for (unsigned int i = 0; i < TEST3_THREADS; ++i) { dprintf("\t%lu\n", mutatee_tids[i]); } } for (unsigned int i = 0; i < TEST3_THREADS; ++i) { bool found = false; for (unsigned int j = 0; j < callback_tids.size(); ++j) { if (callback_tids[j] == mutatee_tids[i]) { found = true; break; } } if (!found) { FAIL_MES(TESTNAME, TESTDESC); logerror("%s[%d]: could not find record for tid %lu: have these:\n", __FILE__, __LINE__, mutatee_tids[i]); for (unsigned int j = 0; j < callback_tids.size(); ++j) { logerror("%lu\n", callback_tids[j]); } err = 1; break; } } dprintf("%s[%d]: removing thread callback\n", __FILE__, __LINE__); if (!bpatch->removeThreadEventCallback(BPatch_threadCreateEvent, createcb)) { FAIL_MES(TESTNAME, TESTDESC); logerror("%s[%d]: failed to remove thread callback\n", __FILE__, __LINE__); err = 1; } if (!err) { logerror("No error reported, terminating process and returning success\n"); PASS_MES(TESTNAME, TESTDESC); appProc->terminateExecution(); logerror("\t Process terminated\n"); return PASSED; } appProc->terminateExecution(); return FAILED; }
// // 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_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; }
// // Start Test Case #30 - (line information) // // static int mutatorTest(BPatch_thread *appThread, BPatch_image *appImage) // { test_results_t test1_30_Mutator::executeTest() { unsigned long n; unsigned long baseAddr,lastAddr; unsigned int call30_1_line_no; unsigned short lineNo; char fileName[256]; if (isMutateeFortran(appImage)) { return SKIPPED; } const char *funcName = "test1_30_mutatee"; 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 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 *> *point30_1 = found_funcs[0]->findPoint(BPatch_entry); //instrument with the function that will set the line number if (!point30_1 || (point30_1->size() < 1)) { logerror("Unable to find point %s - entry.\n", funcName); return FAILED; } BPatch_Vector<BPatch_function *> bpfv; const char *fn = "test1_30_call1"; if (NULL == appImage->findFunction(fn, bpfv) || !bpfv.size() || NULL == bpfv[0]){ logerror(" Unable to find function %s\n", fn); return FAILED; } BPatch_function *call30_1func = bpfv[0]; BPatch_Vector<BPatch_snippet *> nullArgs; BPatch_funcCallExpr call30_1Expr(*call30_1func, nullArgs); checkCost(call30_1Expr); appAddrSpace->insertSnippet(call30_1Expr, *point30_1); //get the line number of the function call30_1 BPatch_variableExpr *expr30_7 = appImage->findVariable("test1_30_globalVariable7"); if (expr30_7 == NULL) { logerror("**Failed** test #30 (line information)\n"); logerror(" Unable to locate test1_30_globalVariable7\n"); return FAILED; } expr30_7->readValue(&n); call30_1_line_no = (unsigned)(n+1); call30_1func->getAddressRange(baseAddr, lastAddr); //now write the base address and last address of the function BPatch_variableExpr *expr30_8 = appImage->findVariable("test1_30_globalVariable8"); if (expr30_8 == NULL) { logerror("**Failed** test #30 (line information)\n"); logerror(" Unable to locate test1_30_globalVariable8\n"); } BPatch_variableExpr *expr30_9 = appImage->findVariable("test1_30_globalVariable9"); if (expr30_9 == NULL) { logerror("**Failed** test #30 (line information)\n"); logerror(" Unable to locate test1_30_globalVariable9\n"); } expr30_8->writeValue(&baseAddr); expr30_9->writeValue(&lastAddr); //check getLineAddr for appImage BPatch_variableExpr *expr30_3 = appImage->findVariable("test1_30_globalVariable3"); if (expr30_3 == NULL) { logerror("**Failed** test #30 (line information)\n"); logerror(" Unable to locate test1_30_globalVariable3\n"); return FAILED; } std::vector<Dyninst::SymtabAPI::AddressRange > ranges; if( appImage->getAddressRanges( "test1_30_mutatee.c", call30_1_line_no, ranges ) ) { n = ranges[0].first; expr30_3->writeValue( & n ); }else{ logerror("BPatch_image->getAddressRanges returned false!\n"); return FAILED; } //check getLineAddr for module BPatch_variableExpr *expr30_4 = appImage->findVariable("test1_30_globalVariable4"); if (expr30_4 == NULL) { logerror("**Failed** test #30 (line information)\n"); logerror(" Unable to locate test1_30_globalVariable4\n"); return FAILED; } BPatch_Vector<BPatch_module*>* appModules = appImage->getModules(); for(unsigned int i=0;i<appModules->size();i++){ char mname[256]; (*appModules)[i]->getName(mname,255);mname[255] = '\0'; if(!strncmp(mname,"test1_30_mutatee.c",15)){ ranges.clear(); if( (*appModules)[i]->getAddressRanges( NULL, call30_1_line_no, ranges ) ) { n = ranges[0].first; expr30_4->writeValue( & n ); } else { logerror("BPatch_module->getAddressRanges returned false!\n"); return FAILED; } break; } } //check getLineAddr works for the function BPatch_variableExpr *expr30_5 = appImage->findVariable("test1_30_globalVariable5"); if (expr30_5 == NULL) { logerror("**Failed** test #30 (line information)\n"); logerror(" Unable to locate test1_30_globalVariable5\n"); return FAILED; } //check whether getLineFile works for appThread BPatch_variableExpr *expr30_6 = appImage->findVariable("test1_30_globalVariable6"); if (expr30_6 == NULL) { logerror("**Failed** test #30 (line information)\n"); logerror(" Unable to locate test1_30_globalVariable6\n"); return FAILED; } /* since the first line address of a function changes with the compiler type (gcc,native) we need to check with next address etc. Instead I use the last address of the function*/ //std::vector< std::pair< const char *, unsigned int > > lines; BPatch_Vector<BPatch_statement> lines; if (appImage->getSourceLines( lastAddr - 1, lines)) { //n = lines[0].second; n = lines[0].lineNumber(); expr30_6->writeValue( & n ); } else { logerror("appThread->getLineAndFile returned false!\n"); } return PASSED; }
int main (int argc, char **argv) { if(!parseOptions(argc,argv)) { return EXIT_FAILURE; } BPatch bpatch; BPatch_binaryEdit *appBin = bpatch.openBinary (originalBinary, !instrumentLibraries.empty()); if (appBin == NULL) { cerr << "Failed to open binary" << endl; return EXIT_FAILURE; } if (!appBin->loadLibrary (instLibrary)) { cerr << "Failed to open instrumentation library." << endl; cerr << "It needs to be located in the current working directory." << endl; return EXIT_FAILURE; } BPatch_image *appImage = appBin->getImage (); /* Find code coverage functions in the instrumentation library */ BPatch_function *initAflForkServer = findFuncByName (appImage, (char *) "initAflForkServer"); BPatch_function *bbCallback = findFuncByName (appImage, (char *) "bbCallback"); if (!initAflForkServer || !bbCallback ) { cerr << "Instrumentation library lacks callbacks!" << endl; return EXIT_FAILURE; } //get and iterate over all modules, instrumenting only the default and manualy specified ones vector < BPatch_module * >*modules = appImage->getModules (); vector < BPatch_module * >::iterator moduleIter; BPatch_module *defaultModule = NULL; string defaultModuleName; for (moduleIter = modules->begin (); moduleIter != modules->end (); ++moduleIter) { //find default module name char moduleName[1024]; (*moduleIter)->getName (moduleName, 1024); if (string (moduleName).find ("DEFAULT_MODULE") != string::npos) { defaultModuleName = "DEFAULT_MODULE"; } } if(defaultModuleName.empty()) defaultModuleName = string(originalBinary).substr(string(originalBinary).find_last_of("\\/")+1); int bbIndex = 0; for (moduleIter = modules->begin (); moduleIter != modules->end (); ++moduleIter) { char moduleName[1024]; (*moduleIter)->getName (moduleName, 1024); if ((*moduleIter)->isSharedLib ()) { if (instrumentLibraries.find (moduleName) == instrumentLibraries.end ()) { cout << "Skipping library: " << moduleName << endl; continue; } } if (string (moduleName).find (defaultModuleName) != string::npos) { defaultModule = (*moduleIter); if(skipMainModule) continue; } cout << "Instrumenting module: " << moduleName << endl; vector < BPatch_function * >*allFunctions = (*moduleIter)->getProcedures (); vector < BPatch_function * >::iterator funcIter; // iterate over all functions in the module for (funcIter = allFunctions->begin (); funcIter != allFunctions->end (); ++funcIter) { BPatch_function *curFunc = *funcIter; char funcName[1024]; curFunc->getName (funcName, 1024); if(string (funcName) == string("_start")) continue; // here's a bug on hlt insertBBCallback (appBin, curFunc, funcName, bbCallback, &bbIndex); } } //if entrypoint set ,find function , else find _init BPatch_function *funcToPatch = NULL; if(!entryPoint) { BPatch_Vector<BPatch_function*> funcs; defaultModule->findFunction("_init", funcs); if(!funcs.size()) { cerr << "Couldn't locate _init, specify entry point manualy. "<< endl; return EXIT_FAILURE; } // there should really be only one funcToPatch = funcs[0]; } else { funcToPatch = defaultModule->findFunctionByEntry(entryPoint); } if(!funcToPatch) { cerr << "Couldn't locate function at given entry point. "<< endl; return EXIT_FAILURE; } if(!insertCallToInit (appBin, initAflForkServer,defaultModule,funcToPatch)){ cerr << "Could not insert init callback at given entry point." << endl; return EXIT_FAILURE; } cout << "Saving the instrumented binary to " << instrumentedBinary << "..." << endl; // Output the instrumented binary if (!appBin->writeFile (instrumentedBinary)) { cerr << "Failed to write output file: " << instrumentedBinary << endl; return EXIT_FAILURE; } if(!runtimeLibraries.empty()) { cout << "Instrumenting runtime libraries." << endl; set<string>::iterator rtLibIter ; for(rtLibIter = runtimeLibraries.begin(); rtLibIter != runtimeLibraries.end(); rtLibIter++) { BPatch_binaryEdit *libBin = bpatch.openBinary ((*rtLibIter).c_str(), false); if (libBin == NULL) { cerr << "Failed to open binary "<< *rtLibIter << endl; return EXIT_FAILURE; } libBin->loadLibrary (instLibrary); BPatch_image *libImg = libBin->getImage (); vector < BPatch_module * >*modules = libImg->getModules (); moduleIter = modules->begin (); ++moduleIter; for ( ; moduleIter != modules->end (); ++moduleIter) { char moduleName[1024]; (*moduleIter)->getName (moduleName, 1024); cout << "Instrumenting module: " << moduleName << endl; vector < BPatch_function * >*allFunctions = (*moduleIter)->getProcedures (); vector < BPatch_function * >::iterator funcIter; // iterate over all functions in the module for (funcIter = allFunctions->begin (); funcIter != allFunctions->end (); ++funcIter) { BPatch_function *curFunc = *funcIter; char funcName[1024]; curFunc->getName (funcName, 1024); if(string (funcName) == string("_start")) continue; insertBBCallback (libBin, curFunc, funcName, bbCallback, &bbIndex); } } if (!libBin->writeFile ((*rtLibIter + ".ins").c_str())) { cerr << "Failed to write output file: " <<(*rtLibIter + ".ins").c_str() << endl; return EXIT_FAILURE; } else { cout << "Saved the instrumented library to " << (*rtLibIter + ".ins").c_str() << "." << endl; } } } cout << "All done! Happy fuzzing!" << endl; return EXIT_SUCCESS; }
// static int mutatorTest( BPatch_thread * appThread, BPatch_image * appImage ) { test_results_t test_stack_3_Mutator::executeTest() { bool passedTest; BPatch::bpatch->setInstrStackFrames(true); appProc->continueExecution(); static const frameInfo_t correct_frame_info[] = { #if defined( os_linux_test ) && (defined( arch_x86_test ) || defined( arch_x86_64_test )) { true, true, BPatch_frameNormal, "_dl_sysinfo_int80" }, #endif #if defined( os_aix_test ) && defined( arch_power_test ) /* AIX uses kill(), but the PC of a process in a syscall can not be correctly determined, and appears to be the address to which the syscall function will return. */ #elif defined( os_windows_test ) && (defined( arch_x86 ) || defined( arch_x86_64_test )) /* Windows/x86 does not use kill(), so its lowermost frame will be something unidentifiable in a system DLL. */ { false, false, BPatch_frameNormal, NULL }, #else { true, false, BPatch_frameNormal, "kill" }, #endif #if ! defined( os_windows_test ) /* Windows/x86's stop_process_() calls DebugBreak(); it's apparently normal to lose this frame. */ { true, false, BPatch_frameNormal, "stop_process_" }, #endif { true, false, BPatch_frameNormal, "test_stack_3_func3" }, { true, false, BPatch_frameTrampoline, NULL }, /* On AIX and x86 (and others), if our instrumentation fires before frame construction or after frame destruction, it's acceptable to not report the function (since, after all, it doesn't have a frame on the stack. */ { true, true, BPatch_frameNormal, "test_stack_3_func2" }, { true, false, BPatch_frameNormal, "test_stack_3_func1" }, { true, false, BPatch_frameNormal, "test_stack_3_mutateeTest" }, { true, false, BPatch_frameNormal, "main" } }; /* Wait for the mutatee to stop in test_stack_3_func1(). */ if (waitUntilStopped( bpatch, appProc, 1, "getCallStack through instrumentation") < 0) { appProc->terminateExecution(); return FAILED; } /* Instrument test_stack_3_func2() to call test_stack_3_func3(), which will trip another breakpoint. */ BPatch_Vector<BPatch_function *> instrumentedFunctions; const char *fName = "test_stack_3_func2"; appImage->findFunction(fName, instrumentedFunctions ); if (instrumentedFunctions.size() != 1) { // FIXME Print out a useful error message logerror("**Failed** test_stack_3\n"); logerror(" Unable to find function '%s'\n", fName); appProc->terminateExecution(); return FAILED; } BPatch_Vector<BPatch_point *> * functionEntryPoints = instrumentedFunctions[0]->findPoint( BPatch_entry ); if (functionEntryPoints->size() != 1) { // FIXME Print out a useful error message logerror("**Failed** test_stack_3\n"); logerror(" Unable to find entry point to function '%s'\n", fName); appProc->terminateExecution(); return FAILED; } BPatch_Vector<BPatch_function *> calledFunctions; const char *fName2 = "test_stack_3_func3"; appImage->findFunction(fName2, calledFunctions ); if (calledFunctions.size() != 1) { //FIXME Print out a useful error message logerror("**Failed** test_stack_3\n"); logerror(" Unable to find function '%s'\n", fName2); appProc->terminateExecution(); return FAILED; } BPatch_Vector<BPatch_snippet *> functionArguments; BPatch_funcCallExpr functionCall( * calledFunctions[0], functionArguments ); appProc->insertSnippet( functionCall, functionEntryPoints[0] ); /* Repeat for all three types of instpoints. */ BPatch_Vector<BPatch_point *> * functionCallPoints = instrumentedFunctions[0]->findPoint( BPatch_subroutine ); if (functionCallPoints->size() != 1) { logerror("**Failed** test_stack_3\n"); logerror(" Unable to find subroutine call points in '%s'\n", fName); appProc->terminateExecution(); return FAILED; } appProc->insertSnippet( functionCall, functionCallPoints[0] ); BPatch_Vector<BPatch_point *> * functionExitPoints = instrumentedFunctions[0]->findPoint( BPatch_exit ); if (functionExitPoints->size() != 1) { logerror("**Failed** test_stack_3\n"); logerror(" Unable to find exit points in '%s'\n", fName); appProc->terminateExecution(); return FAILED; } appProc->insertSnippet( functionCall, functionExitPoints[0] ); #if defined( DEBUG ) for( int i = 0; i < 80; i++ ) { ptrace( PTRACE_SINGLESTEP, appThread->getPid(), NULL, NULL ); } for( int i = 80; i < 120; i++ ) { ptrace( PTRACE_SINGLESTEP, appThread->getPid(), NULL, NULL ); BPatch_Vector<BPatch_frame> stack; appThread->getCallStack( stack ); dprintf("single-step stack walk, %d instructions after stop for instrumentation.\n", i ); for( unsigned i = 0; i < stack.size(); i++ ) { char name[ 40 ]; BPatch_function * func = stack[i].findFunction(); if( func == NULL ) { strcpy( name, "[UNKNOWN]" ); } else { func->getName( name, 40 ); } dprintf(" %10p: %s, fp = %p\n", stack[i].getPC(), name, stack[i].getFP() ); } /* end stack walk dumper */ dprintf("end of stack walk.\n" ); } /* end single-step iterator */ #endif /* defined( DEBUG ) */ /* After inserting the instrumentation, let it be called. */ appProc->continueExecution(); /* Wait for the mutatee to stop because of the instrumentation we just inserted. */ if (waitUntilStopped( bpatch, appProc, 1, "getCallStack through instrumentation (entry)") < 0) { appProc->terminateExecution(); return FAILED; } passedTest = true; if( !checkStack( appThread, correct_frame_info, sizeof(correct_frame_info)/sizeof(frameInfo_t), 3, "getCallStack through instrumentation (entry)" ) ) { passedTest = false; } /* Repeat for other two types of instpoints. */ appProc->continueExecution(); /* Wait for the mutatee to stop because of the instrumentation we just inserted. */ if (waitUntilStopped( bpatch, appProc, 1, "getCallStack through instrumentation (call)") < 0) { appProc->terminateExecution(); return FAILED; } if( !checkStack( appThread, correct_frame_info, sizeof(correct_frame_info)/sizeof(frameInfo_t), 3, "getCallStack through instrumentation (call)" ) ) { passedTest = false; } appProc->continueExecution(); /* Wait for the mutatee to stop because of the instrumentation we just inserted. */ if (waitUntilStopped( bpatch, appProc, 1, "getCallStack through instrumentation (exit)") < 0) { appProc->terminateExecution(); return FAILED; } if( !checkStack( appThread, correct_frame_info, sizeof(correct_frame_info)/sizeof(frameInfo_t), 3, "getCallStack through instrumentation (exit)" ) ) { passedTest = false; } if (passedTest) logerror("Passed test #3 (unwind through base and mini tramps)\n"); /* Return the mutatee to its normal state. */ appProc->continueExecution(); while (!appProc->isTerminated()) { // Workaround for issue with pgCC_high mutatee bpatch->waitForStatusChange(); } if (passedTest) return PASSED; return FAILED; } /* end mutatorTest3() */
void prepareTestCase3(procType proc_type, BPatch_thread *thread, forkWhen when) { static BPatchSnippetHandle *parSnippetHandle3; if(proc_type == Parent_p && when == PreFork) { BPatch_image *parImage = thread->getImage(); BPatch_Vector<BPatch_function *> found_funcs; const char *inFunction = "func7_3"; if ((NULL == parImage->findFunction(inFunction, found_funcs, 1)) || !found_funcs.size()) { fprintf(stderr, " Unable to find function %s\n", inFunction); exit(1); } if (1 < found_funcs.size()) { fprintf(stderr, "%s[%d]: WARNING : found %d functions named %s. Using the first.\n", __FILE__, __LINE__, found_funcs.size(), inFunction); } BPatch_Vector<BPatch_point *> *points7_3p = found_funcs[0]->findPoint(BPatch_entry); if(doError(3, !points7_3p || ((*points7_3p).size() == 0), " Unable to find entry point to \"func7_3\".\n")) return; BPatch_point *point7_3p = (*points7_3p)[0]; BPatch_variableExpr *var7_3p = parImage->findVariable("globalVariable7_3"); if(doError(3, (var7_3p==NULL), " Unable to locate variable globalVariable7_3\n")) return; BPatch_arithExpr expr7_3p(BPatch_assign, *var7_3p,BPatch_constExpr(642)); parSnippetHandle3 = thread->insertSnippet(expr7_3p, *point7_3p, BPatch_callBefore); } else if(proc_type == Parent_p && when == PostFork) { bool result = thread->deleteSnippet(parSnippetHandle3); if(result == false) { fprintf(stderr, " error, couldn't delete snippet\n"); passedTest[3] = false; return; } } else if(proc_type == Child_p && when == PostFork) { BPatch_image *childImage = thread->getImage(); BPatch_Vector<BPatch_function *> found_funcs; const char *inFunction = "func7_3"; if ((NULL == childImage->findFunction(inFunction, found_funcs, 1)) || !found_funcs.size()) { fprintf(stderr, " Unable to find function %s\n", inFunction); exit(1); } if (1 < found_funcs.size()) { fprintf(stderr, "%s[%d]: WARNING : found %d functions named %s. Using the first.\n", __FILE__, __LINE__, found_funcs.size(), inFunction); } BPatch_Vector<BPatch_point *> *points7_3c = found_funcs[0]->findPoint(BPatch_entry); if(doError(3, !points7_3c || ((*points7_3c).size() == 0), " Unable to find entry point to \"func7_3\".\n")) return; BPatch_point *point7_3c = (*points7_3c)[0]; BPatch_Vector<BPatchSnippetHandle *> childSnippets = point7_3c->getCurrentSnippets(); if(doError(3, (childSnippets.size()==0), " No snippets were found at func7_3\n")) return; for(unsigned i=0; i<childSnippets.size(); i++) { bool result = thread->deleteSnippet(childSnippets[i]); if(result == false) { fprintf(stderr, " error, couldn't delete snippet\n"); passedTest[3] = false; return; } } } }
test_results_t test1_19_Mutator::executeTest() { // Avoid a race condition in fast & loose mode while (!appProc->isStopped()) { BPatch::bpatch->waitForStatusChange(); } appProc->continueExecution(); if (waitUntilStopped(BPatch::bpatch, appProc, 19, "oneTimeCode") < 0) { return FAILED; } BPatch_Vector<BPatch_function *> bpfv; const char *fn = "test1_19_call1"; if (NULL == appImage->findFunction(fn, bpfv) || !bpfv.size() || NULL == bpfv[0]) { logerror(" Unable to find function %s\n", fn); return FAILED; } BPatch_function *call19_1_func = bpfv[0]; BPatch_Vector<BPatch_snippet *> nullArgs; BPatch_funcCallExpr call19_1Expr(*call19_1_func, nullArgs); checkCost(call19_1Expr); appProc->oneTimeCode(call19_1Expr); // Let the mutatee run to check the result appProc->continueExecution(); // Wait for the next test if (waitUntilStopped(BPatch::bpatch, appProc, 19, "oneTimeCode") < 0) { return FAILED; } bpfv.clear(); const char *fn2 = "test1_19_call2"; if (NULL == appImage->findFunction(fn2, bpfv) || !bpfv.size() || NULL == bpfv[0]) { logerror(" Unable to find function %s\n", fn2); return FAILED; } BPatch_function *call19_2_func = bpfv[0]; BPatch_funcCallExpr call19_2Expr(*call19_2_func, nullArgs); checkCost(call19_2Expr); int callbackFlag = 0; // Register a callback that will set the flag callbackFlag BPatchOneTimeCodeCallback oldCallback = BPatch::bpatch->registerOneTimeCodeCallback(test19_oneTimeCodeCallback); appProc->oneTimeCodeAsync(call19_2Expr, (void *)&callbackFlag); while (!appProc->isTerminated() && !appProc->isStopped() ) { BPatch::bpatch->waitForStatusChange(); } // Continue mutatee after one-time code runs appProc->continueExecution(); // Wait for the callback to be called while (!appProc->isTerminated() && !callbackFlag) { if( !BPatch::bpatch->waitForStatusChange() ) { logerror(" FAILED: could not wait for callback to be called\n"); return FAILED; } } if( !callbackFlag ) { logerror(" FAILED: process %d terminated while waiting for async oneTimeCode\n", appProc->getPid()); return FAILED; } // After the oneTimeCode is completed, there could be a crash due to bugs in // the RPC code, wait for termination while( !appProc->isTerminated() ) { if( !BPatch::bpatch->waitForStatusChange() ) { logerror(" FAILED: could not wait for process to terminate\n"); return FAILED; } } // Restore old callback (if there was one) BPatch::bpatch->registerOneTimeCodeCallback(oldCallback); return PASSED; } // test1_19_Mutator::executeTest()