// static int mutatorTest(BPatch_thread *appThread, BPatch_image *appImage) test_results_t test_stack_1_Mutator::executeTest() { 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(rs6000_ibm_aix4_1_test) { false, false, BPatch_frameNormal, NULL }, #endif #if !defined(i386_unknown_nt4_0_test) { true, false, BPatch_frameNormal, "stop_process_" }, #endif { true, false, BPatch_frameNormal, "test_stack_1_func3" }, { true, false, BPatch_frameNormal, "test_stack_1_func2" }, { true, false, BPatch_frameNormal, "test_stack_1_func1" }, { true, false, BPatch_frameNormal, "test_stack_1_mutateeTest" }, { true, false, BPatch_frameNormal, "main" }, }; if (waitUntilStopped(bpatch, appProc, 1, "getCallStack") < 0) { appProc->terminateExecution(); return FAILED; } if (checkStack(appThread, correct_frame_info, sizeof(correct_frame_info)/sizeof(frameInfo_t), 1, "getCallStack")) { logerror("Passed test #1 (getCallStack)\n"); } else { appProc->terminateExecution(); return FAILED; } appProc->continueExecution(); while (!appProc->isTerminated()) { bpatch->waitForStatusChange(); } return PASSED; }
// 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; }
// 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() */
int main(int argc, char**argv) { if(argc != 3) { printf("usage: %s orig_prog new_prog\n", argv[0]); return 1; } char* file = argv[1]; char* newFile = argv[2]; bool ret; eztrace_dyninst_register ("compute_", 1, 2); eztrace_dyninst_register ("dist_", 3, 4); eztrace_dyninst_register ("initialize_", 5, 6); eztrace_dyninst_register ("timestamp_", 7, 8); eztrace_dyninst_register ("update_", 9, 10); if(!eztrace_dyninst_nb_function_to_register()) { printf("0 functions instrumented\n"); return 1; } #ifdef CREATE_BINARY //Create the BPatch_addressSpace and BPatch_binaryEdit appBin = bpatch.openBinary(file, true); if(!appBin) { fprintf(stderr, "Cannot open %s\n", file); return -1; } app = static_cast<BPatch_addressSpace *>(appBin); if(! app->loadLibrary(LIB_EZTRACE_SO)) { printf("Cannot load %s\n", LIB_EZTRACE_SO); return 1; } #else // run the program BPatch_process *appProc = bpatch.processCreate(file, NULL); if(!appProc) { printf("Cannot load program %s\n", file); } if(! appProc->loadLibrary(LIB_EZTRACE_SO, true)) { printf("Cannot load %s\n", LIB_EZTRACE_SO); return 1; } app = static_cast<BPatch_addressSpace *>(appProc); #endif // Instrument all the specified functions int nb_inst = eztrace_dyninst_instrument(app); printf("%d functions instrumented\n", nb_inst); if(! nb_inst) return 1; #ifdef CREATE_BINARY if (appBin != NULL) { //Write a new instrumented executable appBin->writeFile(newFile); } else { fprintf(stderr, "cannot write %s\n", newFile); return -1; } #else appProc->continueExecution(); while(!appProc->isTerminated()) { bpatch.waitForStatusChange(); } #endif return 0; }
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; }
// static int mutatorTest(BPatch_thread *appThread, BPatch_image *appImage) test_results_t test_callback_2_Mutator::executeTest() { // a simple single threaded user messagin scenario where we want to send // async messages at function entry/exit and call points. // load libtest12.so -- currently only used by subtest 5, but make it generally // available const char *libname = "./libTest12.so"; test7err = false; test7done = false; callback_counter = 0; elog.resize(0); #if defined(arch_x86_64_test) if (appProc->getAddressWidth() == 4) libname = "./libTest12_m32.so"; #endif dprintf("%s[%d]: loading test library: %s\n", __FILE__, __LINE__, libname); if (!appProc->loadLibrary(libname)) { logerror("%s[%d]: failed to load library %s, cannot proceed\n", __FILE__, __LINE__, libname); appProc->terminateExecution(); return FAILED; } dprintf("%s[%d]: loaded test library: %s\n", __FILE__, __LINE__, libname); BPatchUserEventCallback cb = test7cb; if (!bpatch->registerUserEventCallback(cb)) { FAIL_MES(TESTNAME, TESTDESC); logerror("%s[%d]: could not register callback\n", __FILE__, __LINE__); appProc->terminateExecution(); return FAILED; } // instrument entry and exit of call7_1, as well as call points inside call7_1 const char *call1name = "test_callback_2_call1"; BPatch_function *call7_1 = findFunction(call1name, appImage,TESTNO, TESTNAME); BPatch_point *entry = findPoint(call7_1, BPatch_entry,TESTNO, TESTNAME); if (NULL == entry) { logerror("%s[%d]: Unable to find entry point to function %s\n", __FILE__, __LINE__, call1name); bpatch->removeUserEventCallback(test7cb); appProc->terminateExecution(); return FAILED; } BPatch_point *exit = findPoint(call7_1, BPatch_exit,TESTNO, TESTNAME); if (NULL == entry) { logerror("%s[%d]: Unable to find exit point to function %s\n", __FILE__, __LINE__, call1name); bpatch->removeUserEventCallback(test7cb); appProc->terminateExecution(); return FAILED; } BPatch_point *callsite = findPoint(call7_1, BPatch_subroutine,TESTNO, TESTNAME); if (NULL == callsite) { logerror("%s[%d]: Unable to find subroutine call point in function %s\n", __FILE__, __LINE__, call1name); bpatch->removeUserEventCallback(test7cb); appProc->terminateExecution(); return FAILED; } // These are our asynchronous message functions (in libTest12) that we // attach to the "interesting" points BPatch_function *reportEntry = findFunction("reportEntry", appImage,TESTNO, TESTNAME); BPatch_function *reportExit = findFunction("reportExit", appImage,TESTNO, TESTNAME); BPatch_function *reportCallsite = findFunction("reportCallsite", appImage,TESTNO, TESTNAME); if (!reportEntry) { logerror("%s[%d]: reportEntry = NULL\n", FILE__, __LINE__); bpatch->removeUserEventCallback(test7cb); appProc->terminateExecution(); return FAILED; } if (!reportExit) { logerror("%s[%d]: reportExit = NULL\n", FILE__, __LINE__); bpatch->removeUserEventCallback(test7cb); appProc->terminateExecution(); return FAILED; } if (!reportCallsite) { logerror("%s[%d]: reportCallsite = NULL\n", FILE__, __LINE__); bpatch->removeUserEventCallback(test7cb); appProc->terminateExecution(); return FAILED; } // Do the instrumentation BPatchSnippetHandle *entryHandle = at(entry, reportEntry, TESTNO, TESTNAME); BPatchSnippetHandle *exitHandle = at(exit, reportExit, TESTNO, TESTNAME); BPatchSnippetHandle *callsiteHandle = at(callsite, reportCallsite, TESTNO, TESTNAME); // "at" may set test7err if ((test7err) || (NULL == entryHandle) || (NULL == exitHandle) || (NULL == callsiteHandle) ) { logerror("%s[%d]: instrumentation failed, test7err = %d\n", FILE__, __LINE__, test7err); logerror("%s[%d]: entryHandle = %p\n", FILE__, __LINE__, entryHandle); logerror("%s[%d]: exitHandle = %p\n", FILE__, __LINE__, exitHandle); logerror("%s[%d]: callsiteHandle = %p\n", FILE__, __LINE__, callsiteHandle); bpatch->removeUserEventCallback(test7cb); return FAILED; } if (debugPrint()) { int one = 1; const char *varName = "libraryDebug"; if (setVar(varName, (void *) &one, TESTNO, TESTNAME)) { logerror("%s[%d]: Error setting variable '%s' in mutatee\n", FILE__, __LINE__, varName); bpatch->removeUserEventCallback(test7cb); appProc->terminateExecution(); return FAILED; } } dprintf("%s[%d]: did instrumentation, continuing process...: %s\n", __FILE__, __LINE__, libname); // unset mutateeIdle to trigger mutatee to issue messages. int timeout = 0; appProc->continueExecution(); dprintf("%s[%d]: continued process...: %s\n", __FILE__, __LINE__, libname); // wait until we have received the desired number of events // (or timeout happens) while(!test7err && !test7done && (timeout < TIMEOUT)) { sleep_ms(SLEEP_INTERVAL/*ms*/); timeout += SLEEP_INTERVAL; bpatch->pollForStatusChange(); if (appProc->isTerminated()) { BPatch_exitType et = appProc->terminationStatus(); if (et == ExitedNormally) { int ecode = appProc->getExitCode(); logerror("%s[%d]: normal exit with code %d\n", __FILE__, __LINE__, ecode); } if (et == ExitedViaSignal) { int ecode = appProc->getExitSignal(); logerror("%s[%d]: caught signal %d\n", __FILE__, __LINE__, ecode); } log_res(); bpatch->removeUserEventCallback(test7cb); return FAILED; } } dprintf("%s[%d]: after wait loop: test7err = %s, test7done = %s, timeout = %d\n", __FILE__, __LINE__, test7err ? "true" : "false", test7done ? "true" : "false", timeout); if (timeout >= TIMEOUT) { FAIL_MES(TESTNAME, TESTDESC); logerror("%s[%d]: test timed out: %d ms\n", __FILE__, __LINE__, TIMEOUT); test7err = true; } if (!appProc->stopExecution()) { logerror("%s[%d]: stopExecution failed\n", __FILE__, __LINE__); } dprintf("%s[%d]: stopped process...\n", __FILE__, __LINE__ ); if (!bpatch->removeUserEventCallback(test7cb)) { FAIL_MES(TESTNAME, TESTDESC); logerror("%s[%d]: failed to remove callback\n", __FILE__, __LINE__); appProc->terminateExecution(); log_res(); return FAILED; } dprintf("%s[%d]: removed callback...\n", __FILE__, __LINE__ ); if (!appProc->terminateExecution()) { // don't care //fprintf(stderr, "%s[%d]: terminateExecution failed\n", FILE__, __LINE__); //return FAILED; } #if 0 int one = 1; if (setVar("test_callback_2_idle", (void *) &one, TESTNO, TESTNAME)) { logerror("Error setting variable 'test_callback_2_idle' in mutatee\n"); test7err = true; appProc->terminateExecution(); } #endif #if 0 // And let it run out if (!appThread->isTerminated()) { appProc->continueExecution(); } while (!appThread->isTerminated()) { // Workaround for pgCC_high mutatee issue bpatch->waitForStatusChange(); } #endif if (!test7err) { PASS_MES(TESTNAME, TESTDESC); return PASSED; } log_res(); FAIL_MES(TESTNAME, TESTDESC); return FAILED; }