/** * Build an inverted CFG for doing post-dominator analysis. Running * the dominator analysis on this code will actually produce post-dominators **/ void dominatorBB::postDominatorPredAndSucc() { unsigned i; if (!bpatchBlock) return; //Predecessors BPatch_Vector<BPatch_basicBlock*> blocks; bpatchBlock->getTargets(blocks); for (i=0; i<blocks.size(); i++) { dominatorBB *p = dom_cfg->bpatchToDomBB(blocks[i]); assert(p); pred.push_back(p); } if (bpatchBlock->isExitBlock() || !blocks.size()) { dom_cfg->entryBlock->succ.push_back(this); pred.push_back(dom_cfg->entryBlock); } //Successors blocks.clear(); bpatchBlock->getSources(blocks); for (i=0; i<blocks.size(); i++) { dominatorBB *s = dom_cfg->bpatchToDomBB(blocks[i]); assert(s); succ.push_back(s); } }
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 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_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()
// static bool mutatorTest3and4(int testno, const char *testname) test_results_t test_thread_3_Mutator::executeTest() { test3_threadCreateCounter = 0; callback_tids.clear(); unsigned int timeout = 0; // in ms int err = 0; 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 value of setVar() setVar("mutateeIdle", (void *) &zero, TESTNO, TESTDESC); dprintf("%s[%d]: continue execution for test %d\n", __FILE__, __LINE__, TESTNO); appThread->continueExecution(); #endif // wait until we have received the desired number of events // (or timeout happens) 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)) && (timeout < TIMEOUT)) { dprintf("%s[%d]: waiting for completion for test %d, num active threads = %d\n", __FILE__, __LINE__, TESTNO, active_threads); sleep_ms(SLEEP_INTERVAL/*ms*/); timeout += SLEEP_INTERVAL; if (appProc->isTerminated()) { dprintf("%s[%d]: BAD NEWS: somehow the process died\n", __FILE__, __LINE__); err = 1; break; } bpatch->pollForStatusChange(); if (appProc->isStopped()) { appProc->continueExecution(); } appProc->getThreads(threads); active_threads = threads.size(); threads.clear(); } if (timeout >= TIMEOUT) { FAIL_MES(TESTNAME, TESTDESC); logerror("%s[%d]: test timed out. got %d/10 events\n", __FILE__, __LINE__, test3_threadCreateCounter); logerror("test3_createCounter is %d, expected %d; active threads %d, expected %d\n", test3_threadCreateCounter, TEST3_THREADS, active_threads, 1); err = 1; } 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 = "test4_threads"; getVar(threads_varname, (void *) mutatee_tids, (sizeof(unsigned long) * TEST3_THREADS), TESTNO, TESTDESC); 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 = true; 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 = true; } if (!err) { PASS_MES(TESTNAME, TESTDESC); appProc->terminateExecution(); return PASSED; } appProc->terminateExecution(); return FAILED; }
void execFunc(BPatch_thread *thread) { BPatch_Vector<BPatch_function *> bpfv; if (inTest == 1 || inTest == 2) { printf("**Failed Test #%d\n", inTest); printf(" execCallback invoked, but exec was not called!\n"); } else if (inTest == 3) { dprintf("in exec callback for %d\n", thread->getPid()); // insert code into parent BPatch_Vector<BPatch_snippet *> nullArgs; BPatch_image *appImage = thread->getImage(); assert(appImage); char *fn = "func3_2"; if (NULL == appImage->findFunction(fn, bpfv) || !bpfv.size() || NULL == bpfv[0]){ fprintf(stderr, " Unable to find function %s\n",fn); exit(1); } BPatch_function *func3_2_parent = bpfv[0]; BPatch_funcCallExpr callExpr(*func3_2_parent, nullArgs); bpfv.clear(); char *fn2 = "func3_1"; if (NULL == appImage->findFunction(fn2, bpfv) || !bpfv.size() || NULL == bpfv[0]){ fprintf(stderr, " Unable to find function %s\n",fn2); exit(1); } BPatch_function *func3_1_parent = bpfv[0]; BPatch_Vector<BPatch_point *> *point = func3_1_parent->findPoint(BPatch_exit); assert(point); thread->insertSnippet(callExpr, *point); dprintf("%s[%d]: MUTATEE: exec callback for %d, done with insert snippet\n", __FILE__, __LINE__, thread->getPid()); } else if (inTest == 4) { dprintf("in exec callback for %d\n", thread->getPid()); // insert code into child BPatch_Vector<BPatch_snippet *> nullArgs; BPatch_image *appImage = thread->getImage(); assert(appImage); char *fn3 = "func4_4"; if (NULL == appImage->findFunction(fn3, bpfv) || !bpfv.size() || NULL == bpfv[0]){ fprintf(stderr, " Unable to find function %s\n",fn3); exit(1); } BPatch_function *func4_4_child = bpfv[0]; BPatch_funcCallExpr callExpr1(*func4_4_child, nullArgs); bpfv.clear(); char *fn4 = "func4_2"; if (NULL == appImage->findFunction(fn4, bpfv) || !bpfv.size() || NULL == bpfv[0]){ fprintf(stderr, " Unable to find function %s\n",fn4); exit(1); } BPatch_function *func4_2_child = bpfv[0]; BPatch_Vector<BPatch_point *> *point1 = func4_2_child->findPoint(BPatch_exit); assert(point1); thread->insertSnippet(callExpr1, *point1); } else { printf("in exec callback for %d\n", thread->getPid()); } }
void forkFunc(BPatch_thread *parent, BPatch_thread *child) { dprintf("forkFunc called with parent %p, child %p\n", parent, child); BPatch_image *appImage; BPatch_Vector<BPatch_function *> bpfv; BPatch_Vector<BPatch_snippet *> nullArgs; if (child) mythreads[threadCount++] = child; if (!child) { dprintf("in prefork for %d\n", parent->getPid()); } else { dprintf("in fork of %d to %d\n", parent->getPid(), child->getPid()); } if (inTest == 1) { // nothing to do for this case } else if (inTest == 2) { if (!child) return; // skip prefork case // Make a race condition always show up -- we don't run // until the processes have had a chance. #if !defined(os_windows) sleep(1); #endif // That'll make erroneous continues break... // insert code into parent appImage = parent->getImage(); assert(appImage); char *fn = "func2_3"; if (NULL == appImage->findFunction(fn, bpfv) || !bpfv.size() || NULL == bpfv[0]){ fprintf(stderr, " Unable to find function %s\n",fn); exit(1); } BPatch_function *func2_3_parent = bpfv[0]; BPatch_funcCallExpr callExpr2(*func2_3_parent, nullArgs); bpfv.clear(); char *fn2 = "func2_2"; if (NULL == appImage->findFunction(fn2, bpfv) || !bpfv.size() || NULL == bpfv[0]){ fprintf(stderr, " Unable to find function %s\n",fn2); exit(1); } BPatch_function *func2_2_parent = bpfv[0]; BPatch_Vector<BPatch_point *> *point2 = func2_2_parent->findPoint(BPatch_exit); assert(point2); parent->insertSnippet(callExpr2, *point2); dprintf("MUTATEE: after insert in fork of %d to %d\n", parent->getPid(), child->getPid()); // insert different code into child appImage = child->getImage(); assert(appImage); bpfv.clear(); char *fn3 = "func2_4"; if (NULL == appImage->findFunction(fn3, bpfv) || !bpfv.size() || NULL == bpfv[0]){ fprintf(stderr, " Unable to find function %s\n",fn3); exit(1); } BPatch_function *func2_4_child = bpfv[0]; BPatch_funcCallExpr callExpr1(*func2_4_child, nullArgs); bpfv.clear(); char *fn4 = "func2_2"; if (NULL == appImage->findFunction(fn4, bpfv) || !bpfv.size() || NULL == bpfv[0]){ fprintf(stderr, " Unable to find function %s\n",fn4); exit(1); } BPatch_function *func2_2_child = bpfv[0]; BPatch_Vector<BPatch_point *> *point1 = func2_2_child->findPoint(BPatch_exit); assert(point1); child->insertSnippet(callExpr1, *point1); dprintf("MUTATEE: after insert2 in fork of %d to %d\n", parent->getPid(), child->getPid()); test2Child = child; test2Parent = parent; } else if (inTest == 4) { if (!child) return; // skip prefork case // insert code into parent appImage = parent->getImage(); assert(appImage); char *fn5 = "func4_3"; if (NULL == appImage->findFunction(fn5, bpfv) || !bpfv.size() || NULL == bpfv[0]){ fprintf(stderr, " Unable to find function %s\n",fn5); exit(1); } BPatch_function *func4_3_parent = bpfv[0]; BPatch_funcCallExpr callExpr2(*func4_3_parent, nullArgs); bpfv.clear(); char *fn6 = "func4_2"; if (NULL == appImage->findFunction(fn6, bpfv) || !bpfv.size() || NULL == bpfv[0]){ fprintf(stderr, " Unable to find function %s\n",fn6); exit(1); } BPatch_function *func4_2_parent = bpfv[0]; BPatch_Vector<BPatch_point *> *point2 = func4_2_parent->findPoint(BPatch_exit); assert(point2); parent->insertSnippet(callExpr2, *point2); // code goes into child after in-exec in this test. test4Child = child; } }
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 #9 - (derivation) // // static int mutatorTest(BPatch_thread *, BPatch_image *appImage) test_results_t test5_9_Mutator::executeTest() { bool found = false; BPatch_Vector<BPatch_function *> bpfv; const char *fn = "derivation_test::func_cpp"; if (NULL == appImage->findFunction(fn, bpfv) || !bpfv.size() || NULL == bpfv[0]){ logerror("**Failed** test #9 (derivation)\n"); logerror(" Unable to find function %s\n", fn); return FAILED; } BPatch_function *f1 = bpfv[0]; BPatch_Vector<BPatch_point *> *point9_1 = f1->findPoint(BPatch_exit); if (!point9_1 || (point9_1->size() < 1)) { logerror("Unable to find point derivation_test::func_cpp - exit.\n"); return FAILED; } bpfv.clear(); const char *fn2 = "main"; if (NULL == appImage->findFunction(fn2, bpfv) || !bpfv.size() || NULL == bpfv[0]){ logerror("**Failed** test #9 (derivation)\n"); logerror(" Unable to find function %s\n", fn2); return FAILED; } BPatch_function *f2 = bpfv[0]; BPatch_Vector<BPatch_point *> *point9_2 = f2->findPoint(BPatch_allLocations); if (!point9_2 || (point9_2->size() < 1)) { logerror("Unable to find point in main.\n"); return FAILED; } BPatch_variableExpr *expr9_0=appImage->findVariable(*(*point9_2)[0], "test5_9_test9"); if (!expr9_0) { logerror("**Failed** test #9 (derivation)\n"); logerror(" Unable to locate one of variables\n"); return FAILED; } BPatch_Vector<BPatch_variableExpr *> *fields = expr9_0->getComponents(); if (!fields || fields->size() == 0 ) { logerror("**Failed** test #9 (derivation)\n"); logerror(" struct lacked correct number of elements\n"); return FAILED; } int index = 0; while ( index < fields->size() ) { if ( !strcmp("call_cpp", (*fields)[index]->getName()) || !strcmp("cpp_test_util::call_cpp", (*fields)[index]->getName())) { found = true; break; } index ++; } if ( !found ) { logerror("**Failed** test #9 (derivation)\n"); logerror(" Can't find inherited class member functions\n"); logerror(" Expected call_cpp or cpp_test_util::call_cpp\n"); index = 0; while ( index < fields->size() ) { logerror(" Field %d: %s\n", index, (*fields)[index]->getName()); ++index; } return FAILED; } // TODO pass a success message to the mutatee const char *passfn = "test5_9_passed"; BPatch_Vector<BPatch_function *> passfv; if ((NULL == appImage->findFunction(passfn, passfv)) || (passfv.size() < 1) || (NULL == passfv[0])) { logerror("**Failed** test #9 (derivation)\n"); logerror(" Can't find function %s\n", passfn); return FAILED; } BPatch_function *pass_func = passfv[0]; BPatch_Vector<BPatch_snippet *> pass_args; BPatch_funcCallExpr pass_expr(*pass_func, pass_args); appAddrSpace->insertSnippet(pass_expr, *point9_1); return PASSED; }
test_results_t test1_33_Mutator::executeTest() { int pvalue; unsigned int i; if (isMutateeFortran(appImage)) { return SKIPPED; } BPatch_Vector<BPatch_function *> bpfv; const char *fn = "test1_33_func2"; if (NULL == appImage->findFunction(fn, bpfv) || !bpfv.size() || NULL == bpfv[0]) { logerror("**Failed** test #33 (control flow graphs)\n"); logerror(" Unable to find function %s\n", fn); return FAILED; } BPatch_function *func2 = bpfv[0]; BPatch_flowGraph *cfg = func2->getCFG(); if (cfg == NULL) { logerror("**Failed** test #33 (control flow graphs)\n"); logerror(" Unable to get control flow graph of %s\n", fn); return FAILED; } /* * Test for consistency of entry basic blocks. */ BPatch_Vector<BPatch_basicBlock*> entry_blocks; cfg->getEntryBasicBlock(entry_blocks); if (entry_blocks.size() != 1) { logerror("**Failed** test #33 (control flow graphs)\n"); logerror(" Detected %d entry basic blocks in %s, should have been one.\n", entry_blocks.size(), fn); return FAILED; } for (i = 0; i < entry_blocks.size(); i++) { BPatch_Vector<BPatch_basicBlock*> sources; entry_blocks[i]->getSources(sources); if (sources.size() > 0) { logerror("**Failed** test #33 (control flow graphs)\n"); logerror(" An entry basic block has incoming edges in the control flow graph\n"); return FAILED; } BPatch_Vector<BPatch_basicBlock*> targets; entry_blocks[i]->getTargets(targets); if (targets.size() < 1) { logerror("**Failed** test #33 (control flow graphs\n"); logerror(" An entry basic block has no outgoing edges in the control flow graph\n"); return FAILED; } } /* * Test for consistency of exit basic blocks. */ BPatch_Vector<BPatch_basicBlock*> exit_blocks; cfg->getExitBasicBlock(exit_blocks); if (exit_blocks.size() != 1) { logerror("**Failed** test #33 (control flow graphs)\n"); logerror(" Detected %d exit basic blocks in %s, should have been one.\n", exit_blocks.size(), fn); return FAILED; } for (i = 0; i < exit_blocks.size(); i++) { BPatch_Vector<BPatch_basicBlock*> sources; exit_blocks[i]->getSources(sources); if (sources.size() < 1) { logerror("**Failed** test #33 (control flow graphs)\n"); logerror(" An exit basic block has no incoming edges in the control flow graph\n"); return FAILED; } BPatch_Vector<BPatch_basicBlock*> targets; exit_blocks[i]->getTargets(targets); if (targets.size() > 0) { logerror("**Failed** test #33 (control flow graphs)\n"); logerror(" An exit basic block has outgoing edges in the control flow graph\n"); return FAILED; } } /* * Check structure of control flow graph. */ std::set<BPatch_basicBlock*> blocks; cfg->getAllBasicBlocks(blocks); if (blocks.size() < 4) { logerror("**Failed** test #33 (control flow graphs)\n"); logerror(" Detected %d basic blocks in %s, should be at least four.\n", blocks.size(), fn); return FAILED; } bool foundOutDegreeTwo = false; bool foundInDegreeTwo = false; int blocksNoIn = 0, blocksNoOut = 0; for (std::set<BPatch_basicBlock *>::iterator iter = blocks.begin(); iter != blocks.end(); ++iter) { BPatch_Vector<BPatch_basicBlock*> in; BPatch_Vector<BPatch_basicBlock*> out; (*iter)->getSources(in); (*iter)->getTargets(out); if (in.size() == 0) blocksNoIn++; if (out.size() == 0) blocksNoOut++; if (in.size() > 2 || out.size() > 2) { logerror("**Failed** test #33 (control flow graphs)\n"); logerror(" Detected a basic block in %s with %d incoming edges and %d\n", fn, in.size(), out.size()); logerror(" outgoing edges - neither should be greater than two.\n"); return FAILED; } else if (in.size() > 1 && out.size() > 1) { logerror("**Failed** test #33 (control flow graphs)\n"); logerror(" Detected a basic block in %s with %d incoming edges and %d\n", fn, in.size(), out.size()); logerror(" outgoing edges - only one should be greater than one.\n"); return FAILED; } else if (in.size() == 0 && out.size() == 0) { logerror("**Failed** test #33 (control flow graphs)\n"); logerror(" Detected a basic block in %s with no incoming or outgoing edges.\n", fn); return FAILED; } else if (in.size() == 2) { assert(out.size() <= 1); if (foundInDegreeTwo) { logerror("**Failed** test #33 (control flow graphs)\n"); logerror(" Detected two basic blocks in %s with in degree two, there should only\n", fn); logerror(" be one.\n"); return FAILED; } foundInDegreeTwo = true; if (in[0]->getBlockNumber() == in[1]->getBlockNumber()) { logerror("**Failed** test #33 (control flow graphs)\n"); logerror(" Two edges go to the same block (number %d).\n", in[0]->getBlockNumber()); return FAILED; } } else if (out.size() == 2) { assert(in.size() <= 1); if (foundOutDegreeTwo) { logerror("**Failed** test #33 (control flow graphs)\n"); logerror(" Detected two basic blocks in %s with out degree two, there should only\n", fn); logerror(" be one.\n"); return FAILED; } foundOutDegreeTwo = true; if (out[0]->getBlockNumber() == out[1]->getBlockNumber()) { logerror("**Failed** test #33 (control flow graphs)\n"); logerror(" Two edges go to the same block (number %d).\n", out[0]->getBlockNumber()); return FAILED; } } else if (in.size() > 1 || out.size() > 1) { /* Shouldn't be able to get here. */ logerror("**Failed** test #33 (control flow graphs)\n"); logerror(" Detected a basic block in %s with %d incoming edges and %d\n", fn, in.size(), out.size()); logerror(" outgoing edges.\n"); return FAILED; } } if (blocksNoIn > 1) { logerror("**Failed** test #33 (control flow graphs)\n"); logerror(" Detected more than one block in %s with no incoming edges.\n", fn); return FAILED; } if (blocksNoOut > 1) { logerror("**Failed** test #33 (control flow graphs)\n"); logerror(" Detected more than block in %s with no outgoing edges.\n", fn); return FAILED; } if (!foundOutDegreeTwo) { logerror("**Failed** test #33 (control flow graphs)\n"); logerror(" Did not detect the \"if\" statement in %s.\n", fn); return FAILED; } /* * Check for loops (there aren't any in the function we're looking at). */ std::set<int> empty; if (hasBackEdge(entry_blocks[0], empty)) { logerror("**Failed** test #33 (control flow graphs)\n"); logerror(" Detected a loop in %s, there should not be one.\n", fn); return FAILED; } /* * Now check a function with a switch statement. */ bpfv.clear(); const char *fn2 = "test1_33_func3"; // Bernat, 8JUN05 -- include uninstrumentable here... if (NULL == appImage->findFunction(fn2, bpfv, false, false, true) || !bpfv.size() || NULL == bpfv[0]) { logerror("**Failed** test #33 (control flow graphs)\n"); logerror(" Unable to find function %s\n", fn2); return FAILED; } BPatch_function *func3 = bpfv[0]; BPatch_flowGraph *cfg3 = func3->getCFG(); if (cfg3 == NULL) { logerror("**Failed** test #33 (control flow graphs)\n"); logerror(" Unable to get control flow graph of %s\n", fn2); return FAILED; } std::set<BPatch_basicBlock*> blocks3; cfg3->getAllBasicBlocks(blocks3); if (blocks3.size() < 10) { logerror("**Failed** test #33 (control flow graphs)\n"); logerror(" Detected %d basic blocks in %s, should be at least ten.\n", blocks3.size(), fn2); return FAILED; } bool foundSwitchIn = false; bool foundSwitchOut = false; bool foundRangeCheck = false; for (std::set<BPatch_basicBlock *>::iterator iter = blocks3.begin(); iter != blocks3.end(); ++iter) { BPatch_basicBlock *block = *iter; BPatch_Vector<BPatch_basicBlock*> in; BPatch_Vector<BPatch_basicBlock*> out; block->getSources(in); block->getTargets(out); if (!foundSwitchOut && out.size() >= 10 && in.size() <= 1) { foundSwitchOut = true; } else if (!foundSwitchIn && in.size() >= 10 && out.size() <= 1) { foundSwitchIn = true; } else if (!foundRangeCheck && out.size() == 2 && in.size() <= 1) { foundRangeCheck = true; } else if (in.size() > 1 && out.size() > 1) { logerror("**Failed** test #33 (control flow graphs)\n"); logerror(" Found basic block in %s with unexpected number of edges.\n", fn2); logerror(" %d incoming edges, %d outgoing edges.\n", in.size(), out.size()); return FAILED; } } if (!foundSwitchIn || !foundSwitchOut) { logerror("**Failed** test #33 (control flow graphs)\n"); if (!foundSwitchIn) logerror(" Did not find \"switch\" statement in %s.\n", fn2); if (!foundSwitchOut) logerror(" Did not find block after \"switch\" statement.\n"); return FAILED; } /* Check dominator info. */ BPatch_Vector<BPatch_basicBlock*> entry3; cfg3->getEntryBasicBlock(entry3); if (entry3.size() != 1) { logerror("**Failed** test #33 (control flow graphs)\n"); logerror(" Detected %d entry basic blocks in %s, should have been one.\n", entry_blocks.size(), fn2); return FAILED; } for (std::set<BPatch_basicBlock *>::iterator iter2 = blocks3.begin(); iter2 != blocks3.end(); ++iter2) { if (!entry3[0]->dominates(*iter2)) { logerror("**Failed** test #33 (control flow graphs)\n"); logerror(" Entry block does not dominate all blocks in %s\n", fn2); return FAILED; } } BPatch_Vector<BPatch_basicBlock*> exit3; cfg3->getExitBasicBlock(exit3); if (exit3.size() != 1) { logerror("**Failed** test #33 (control flow graphs)\n"); logerror(" Detected %d exit basic blocks in %s, should have been one.\n", exit3.size(), fn2); for (unsigned i = 0; i < exit3.size(); ++i) { logerror("\t%d: 0x%lx\n", i, exit3[i]->getStartAddress()); } return FAILED; } for (i = 0; i < (unsigned int) exit3.size(); i++) { if (!exit3[i]->postdominates(entry3[0])) { logerror("**Failed** test #33 (control flow graphs)\n"); logerror(" Exit block %d does not postdominate all entry blocks in %s\n", i, fn2); return FAILED; } } #if !defined(os_windows_test) && defined(ENABLE_PARSE_API_GRAPHS) logerror("Testing parseAPI dominators\n"); ParseAPI::Function* parse_func = ParseAPI::convert(func3); assert(parse_func); Block* parse_entry = parse_func->entry(); bool parse_idoms_ok = true; for(Function::blocklist::const_iterator bl = parse_func->blocks().begin(); bl != parse_func->blocks().end(); ++bl) { if(*bl == parse_entry) continue; if(!dominates(*parse_func, parse_entry, *bl)) { parse_idoms_ok = false; } } if(!parse_idoms_ok) { logerror("**Failed** test #33 (CFG)\n"); logerror(" ParseAPI dominator algorithm does not have entry block dominating all blocks in function\n"); return FAILED; } #endif BPatch_variableExpr *expr33_1 = appImage->findVariable("test1_33_globalVariable1"); if (expr33_1 == NULL) { logerror("**Failed** test #33 (control flow graphs)\n"); logerror(" Unable to locate test1_33_globalVariable1\n"); return FAILED; } pvalue = 1; expr33_1->writeValue(&pvalue); return PASSED; }
// // Start Test Case #8 - (declaration) // test_results_t test5_8_Mutator::executeTest() { // Find the exit point to the procedure "func_cpp" BPatch_Vector<BPatch_function *> bpfv; const char *fn = "decl_test::func_cpp"; if (NULL == appImage->findFunction(fn, bpfv) || !bpfv.size() || NULL == bpfv[0]){ logerror( "**Failed** test #8 (declaration)\n"); logerror( " Unable to find function %s\n", fn); return FAILED; } BPatch_function *f1 = bpfv[0]; BPatch_Vector<BPatch_point *> *point8_1 = f1->findPoint(BPatch_exit); if (!point8_1 || (point8_1->size() < 1)) { logerror( "Unable to find point decl_test::func_cpp - exit.\n"); return FAILED; } bpfv.clear(); const char *fn2 = "main"; if (NULL == appImage->findFunction(fn2, bpfv) || !bpfv.size() || NULL == bpfv[0]){ logerror( "**Failed** test #8 (declaration)\n"); logerror( " Unable to find function %s\n", fn2); return FAILED; } BPatch_function *f2 = bpfv[0]; BPatch_Vector<BPatch_point *> *point8_2 = f2->findPoint(BPatch_allLocations); if (!point8_2 || (point8_2->size() < 1)) { logerror( "Unable to find point in main.\n"); return FAILED; } bpfv.clear(); const char *fn3 = "decl_test::call_cpp"; if (NULL == appImage->findFunction(fn3, bpfv) || !bpfv.size() || NULL == bpfv[0]){ logerror( "**Failed** test #8 (declaration)\n"); logerror( " Unable to find function %s\n", fn3); return FAILED; } BPatch_function *call8_func = bpfv[0]; BPatch_variableExpr *this8 = appImage->findVariable("test5_8_test8"); if (this8 == NULL) { logerror( "**Failed** test #8 (declaration)\n"); logerror( "Unable to find variable \"test5_8_test8\"\n"); return FAILED; } BPatch_Vector<BPatch_snippet *> call8_args; BPatch_arithExpr expr8_0(BPatch_addr, *this8); call8_args.push_back(&expr8_0); BPatch_constExpr expr8_1(8); call8_args.push_back(&expr8_1); BPatch_funcCallExpr call8Expr(*call8_func, call8_args); // find the variables of different scopes // What *exactly* are we testing here? Just finding variables of various // types with different point parameters to findVariable()? BPatch_variableExpr *expr8_2=appImage->findVariable("CPP_DEFLT_ARG"); BPatch_variableExpr *expr8_3=appImage->findVariable(*(*point8_2)[0], "test5_8_test8"); BPatch_variableExpr *expr8_4=appImage->findVariable(*(*point8_1)[0], "CPP_DEFLT_ARG"); if (!expr8_2 || !expr8_3 || !expr8_4) { logerror( "**Failed** test #8 (delcaration)\n"); logerror( " Unable to locate one of variables\n"); return FAILED; } BPatch_Vector<BPatch_variableExpr *> *fields = expr8_3->getComponents(); if (!fields || fields->size() == 0 ) { logerror( "**Failed** test #8 (declaration)\n"); logerror( " struct lacked correct number of elements\n"); return FAILED; } unsigned int index = 0; while ( index < fields->size() ) { char fieldName[100]; strcpy(fieldName, (*fields)[index]->getName()); if ( !strcmp("CPP_TEST_UTIL_VAR", (*fields)[index]->getName()) ) { dprintf("Inserted snippet2\n"); checkCost(call8Expr); BPatchSnippetHandle *handle; handle = appAddrSpace->insertSnippet(call8Expr, *point8_1); return PASSED; } index ++; } logerror( "**Failed** test #8 (declaration)\n"); logerror( " Can't find inherited class member variables\n"); return FAILED; }
// // Start Test Case #1 - (C++ argument pass) // // static int mutatorTest(BPatch_thread *appThread, BPatch_image *appImage) test_results_t test5_1_Mutator::executeTest() { BPatch_Vector<BPatch_function *> bpfv; const char *fn = "arg_test::call_cpp"; if (NULL == appImage->findFunction(fn, bpfv) || !bpfv.size() || NULL == bpfv[0]){ logerror("**Failed** test #1\n"); logerror(" Unable to find function %s\n", fn); return FAILED; } BPatch_function *f1 = bpfv[0]; BPatch_Vector<BPatch_point *> *point1_1 = f1->findPoint(BPatch_subroutine); assert(point1_1); assert((*point1_1)[0]); // check the paramter passing modes BPatch_variableExpr *arg0 = appImage->findVariable(*(*point1_1)[0], "reference"); BPatch_variableExpr *arg1 = appImage->findVariable(*(*point1_1)[0], "arg1"); BPatch_variableExpr *arg2 = appImage->findVariable(*(*point1_1)[0], "arg2"); BPatch_variableExpr *arg3 = appImage->findVariable(*(*point1_1)[0], "arg3"); BPatch_variableExpr *arg4 = appImage->findVariable(*(*point1_1)[0], "m"); if (!arg0 || !arg1 || !arg2 || !arg3 || !arg4) { logerror("**Failed** test #1 (argument passing)\n"); if ( !arg0 ) logerror(" can't find local variable 'reference'\n"); if ( !arg1 ) logerror(" can't find local variable 'arg1'\n"); if ( !arg2 ) logerror(" can't find local variable 'arg2'\n"); if ( !arg3 ) logerror(" can't find local variable 'arg3'\n"); if ( !arg4 ) logerror(" can't find local variable 'm'\n"); return FAILED; } BPatch_type *type1_0 = const_cast<BPatch_type *> (arg0->getType()); BPatch_type *type1_1 = const_cast<BPatch_type *> (arg1->getType()); BPatch_type *type1_2 = const_cast<BPatch_type *> (arg2->getType()); BPatch_type *type1_3 = const_cast<BPatch_type *> (arg4->getType()); assert(type1_0 && type1_1 && type1_2 && type1_3); if (!type1_1->isCompatible(type1_3)) { logerror("**Failed** test #1 (C++ argument pass)\n"); logerror(" type1_1 reported as incompatibile with type1_3\n"); return FAILED; } if (!type1_2->isCompatible(type1_0)) { logerror("**Failed** test #1 (C++ argument pass)\n"); logerror(" type1_2 reported as incompatibile with type1_0\n"); return FAILED; } BPatch_arithExpr expr1_1(BPatch_assign, *arg3, BPatch_constExpr(1)); checkCost(expr1_1); appAddrSpace->insertSnippet(expr1_1, *point1_1); // pass a paramter to a class member function bpfv.clear(); const char *fn2 = "arg_test::func_cpp"; if (NULL == appImage->findFunction(fn2, bpfv) || !bpfv.size() || NULL == bpfv[0]){ logerror("**Failed** test #1 (C++ argument pass)\n"); logerror(" Unable to find function %s\n", fn2); return FAILED; } BPatch_function *f2 = bpfv[0]; BPatch_Vector<BPatch_point *> *point1_2 = f2->findPoint(BPatch_subroutine); if (!point1_2 || (point1_2->size() < 1)) { logerror("**Failed** test #1 (C++ argument pass)\n"); logerror("Unable to find point arg_test::func_cpp - exit.\n"); return FAILED; } bpfv.clear(); const char *fn3 = "arg_test::arg_pass"; if (NULL == appImage->findFunction(fn3, bpfv) || !bpfv.size() || NULL == bpfv[0]) { logerror("**Failed** test #1 (C++ argument pass)\n"); logerror(" Unable to find function %s\n", fn3); return FAILED; } BPatch_function *call1_func = bpfv[0]; BPatch_variableExpr *this1 = appImage->findVariable("test1"); if (this1 == NULL) { logerror("**Failed** test #1 (C++ argument pass)\n"); logerror("Unable to find variable \"test1\"\n"); return FAILED; } BPatch_Vector<BPatch_snippet *> call1_args; BPatch_arithExpr expr1_2(BPatch_addr, *this1); call1_args.push_back(&expr1_2); BPatch_constExpr expr1_3(1); call1_args.push_back(&expr1_3); BPatch_funcCallExpr call1Expr(*call1_func, call1_args); checkCost(call1Expr); appAddrSpace->insertSnippet(call1Expr, *point1_2); return PASSED; }