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; }
int main (int argc, char *argv[]) { set<string> UserFunctions; set<string> ParallelFunctions; map<string, vector<string> > LoopLevels; char *env_var; int index; if (getenv("EXTRAE_HOME") == NULL) { cerr << PACKAGE_NAME << ": Environment variable EXTRAE_HOME is undefined" << endl; exit (-1); } if ((env_var = getenv ("DYNINSTAPI_RT_LIB")) == NULL) { env_var = (char*) malloc ((1+strlen("DYNINSTAPI_RT_LIB=")+strlen(DYNINST_RT_LIB))*sizeof(char)); if (env_var == NULL) { cerr << PACKAGE_NAME << ": Cannot allocate memory to define DYNINSTAPI_RT_LIB!" << endl; exit (-1); } sprintf (env_var, "DYNINSTAPI_RT_LIB=%s", DYNINST_RT_LIB); putenv (env_var); } else cout << PACKAGE_NAME << ": Warning, DYNINSTAPI_RT_LIB already set and pointing to " << env_var << endl; /* Parse the params */ index = processParams (argc, argv); char * envvar_dyn = (char *) malloc ((strlen("EXTRAE_DYNINST_RUN=yes")+1)*sizeof (char)); if (NULL == envvar_dyn) { cerr << PACKAGE_NAME << ": Error! Unable to allocate memory for EXTRAE_DYNINST_RUN environment variable" << endl; exit (-1); } sprintf (envvar_dyn, "EXTRAE_DYNINST_RUN=yes"); putenv (envvar_dyn); if (!ListFunctions) { if (configXML != NULL) { char * envvar = (char *) malloc ((strlen(configXML)+strlen("EXTRAE_CONFIG_FILE=")+1)*sizeof (char)); if (NULL == envvar) { cerr << PACKAGE_NAME << ": Error! Unable to allocate memory for EXTRAE_CONFIG_FILE environment variable" << endl; exit (-1); } sprintf (envvar, "EXTRAE_CONFIG_FILE=%s", configXML); putenv (envvar); } else { if (getenv ("EXTRAE_CONFIG_FILE") == NULL) { cerr << PACKAGE_NAME << ": Error! You have to provide a configuration file using the -config parameter or set the EXTRAE_CONFIG_FILE" << endl; exit (-1); } configXML = getenv ("EXTRAE_CONFIG_FILE"); } if (!file_exists(configXML)) { cerr << PACKAGE_NAME << ": Error! Unable to locate " << configXML << endl; exit (-1); } ::Parse_XML_File (0, 0, configXML); } /* Does the binary exists? */ if (!file_exists(argv[index])) { cout << PACKAGE_NAME << ": Executable " << argv[index] << " cannot be found!" << endl; exit (-1); } /* Create an instance of the BPatch library */ bpatch = new BPatch; /* Register a callback function that prints any error messages */ bpatch->registerErrorCallback (errorFunc); /* Don't check recursion in snippets */ bpatch->setTrampRecursive (true); cout << "Welcome to " << PACKAGE_STRING << " launcher using DynInst " << DYNINST_MAJOR << "." << DYNINST_MINOR << "." << DYNINST_SUBMINOR << endl; int i = 1; while (argv[index+i] != NULL) { cout << PACKAGE_NAME << ": Argument " << i << " - " << argv[index+i] << endl; i++; } BPatch_process *appProcess = NULL; BPatch_binaryEdit *appBin = NULL; BPatch_addressSpace *appAddrSpace = NULL; if (!BinaryRewrite) { cout << PACKAGE_NAME << ": Creating process for image binary " << argv[index]; cout.flush (); appProcess = bpatch->processCreate ((const char*) argv[index], (const char**) &argv[index], (const char**) environ); if (appProcess == NULL) { cerr << endl << PACKAGE_NAME << ": Error creating the target application process" << endl; exit (-1); } cout << " PID(" << appProcess->getPid() << ")" << endl; /* Stop the execution in order to load the instrumentation library */ cout << PACKAGE_NAME << ": Stopping mutatee execution" << endl; if (!appProcess->stopExecution()) { cerr << PACKAGE_NAME << ": Cannot stop execution of the target application" << endl; exit (-1); } appAddrSpace = appProcess; } else { cout << PACKAGE_NAME << ": Rewriting binary " << argv[index] << endl; appBin = bpatch->openBinary ((const char*) argv[index], false); /* passed true to instrument libraries before !? */ if (appBin == NULL) { cerr << PACKAGE_NAME << ": Error opening binary for rewriting" << endl; exit (-1); } appAddrSpace = appBin; } BPatch_image *appImage = appAddrSpace->getImage(); if (appImage == NULL) { cerr << PACKAGE_NAME << ": Error while acquiring application image" << endl; exit (-1); } /* The user asks for the list of functions, simply show it */ if (ListFunctions) { ShowFunctions (appImage); if (!BinaryRewrite) appProcess->terminateExecution(); exit (-1); } /* Read files */ if (::XML_have_UFlist()) { if (VerboseLevel) cout << PACKAGE_NAME << ": Reading instrumented user functions from " << ::XML_UFlist() << endl; ReadFileIntoList (::XML_UFlist(), UserFunctions); discoverInstrumentationLevel(UserFunctions, LoopLevels); } if (DecodeBasicBlock) { std::set<string>::iterator f_begin = UserFunctions.begin(); std::set<string>::iterator f_end = UserFunctions.end(); while (f_begin != f_end) { BPatch_function *f = getRoutine ((*f_begin).c_str(), appImage); if (f == NULL) { cerr << PACKAGE_NAME << ": Unable to find " << *f_begin << " function!" << endl; } else { cout<<decodeBasicBlocks(f, *f_begin); } f_begin++; } if (!BinaryRewrite) { appProcess->terminateExecution(); } exit(-1); } if (::XML_CheckTraceEnabled()) { ApplicationType *appType = new ApplicationType (); extrae_detecting_application_type = true; cout << PACKAGE_NAME << ": Detecting application type " << endl; appType->detectApplicationType (appImage); appType->dumpApplicationType (); cout << PACKAGE_NAME << ": Detecting whether the application has been already linked with Extrae : "; BPatch_function *extrae_init = getRoutine ("Extrae_init", appImage, false); BinaryLinkedWithInstrumentation = extrae_init != NULL; cout << (BinaryLinkedWithInstrumentation?"yes":"no") << endl; extrae_detecting_application_type = false; /* If the application has not been linked with instrumentation library, load the appropriate module */ if (!BinaryLinkedWithInstrumentation) { char buffer[1024]; /* will hold the library to load */ /* Check for the correct library to be loaded */ if (appType->get_isMPI()) { if (appType->get_isOpenMP()) { if (appType->get_MPI_type() == ApplicationType::MPI_C) sprintf (buffer, "%s/lib/lib_dyn_ompitracec-%s.so", getenv("EXTRAE_HOME"), PACKAGE_VERSION); else sprintf (buffer, "%s/lib/lib_dyn_ompitracef-%s.so", getenv("EXTRAE_HOME"), PACKAGE_VERSION); } else if (appType->get_isCUDA()) { if (appType->get_MPI_type() == ApplicationType::MPI_C) sprintf (buffer, "%s/lib/lib_dyn_cudampitracec-%s.so", getenv("EXTRAE_HOME"), PACKAGE_VERSION); else sprintf (buffer, "%s/lib/lib_dyn_cudampitracef-%s.so", getenv("EXTRAE_HOME"), PACKAGE_VERSION); } else { if (appType->get_MPI_type() == ApplicationType::MPI_C) sprintf (buffer, "%s/lib/lib_dyn_mpitracec-%s.so", getenv("EXTRAE_HOME"), PACKAGE_VERSION); else sprintf (buffer, "%s/lib/lib_dyn_mpitracef-%s.so", getenv("EXTRAE_HOME"), PACKAGE_VERSION); } } else { if (appType->get_isOpenMP()) { sprintf (buffer, "%s/lib/libomptrace-%s.so", getenv("EXTRAE_HOME"), PACKAGE_VERSION); } else { if (appType->get_isCUDA()) sprintf (buffer, "%s/lib/libcudatrace-%s.so", getenv("EXTRAE_HOME"), PACKAGE_VERSION); else sprintf (buffer, "%s/lib/libseqtrace-%s.so", getenv("EXTRAE_HOME"), PACKAGE_VERSION); } } loadedModule = buffer; /* Load the module into the mutattee */ cout << PACKAGE_NAME << ": Loading " << loadedModule << " into the target application" << endl; if (!file_exists (buffer)) { /* If the library does not exist, terminate the mutatee and exit */ cerr << PACKAGE_NAME << ": Cannot find the module. It must be under $EXTRAE_HOME/lib" << endl; appProcess->terminateExecution(); exit (-1); } if (!appAddrSpace->loadLibrary (loadedModule.c_str())) { /* If the library cannot be loaded, terminate the mutatee and exit */ cerr << PACKAGE_NAME << ": Cannot load library! Retry using -v to gather more information on this error!" << endl; appProcess->terminateExecution(); exit (-1); } } /* ! BinaryLinkedWithInstrumentation */ else cout << PACKAGE_NAME << ": The application seems to be linked with Extrae libraries. Won't load additional libraries..." << endl; /* Load instrumentation API patches */ loadAPIPatches (appImage); if (appType->get_isMPI() && ::XML_GetTraceMPI()) loadMPIPatches (appImage); /* Instrument fork, wait, waitpid and exec calls */ InstrumentForks (appImage); /* Apply instrumentation of runtimes only if not linked with Extrae */ if (!BinaryLinkedWithInstrumentation && appType->get_isOpenMP()) { if (appType->get_OpenMP_rte() == ApplicationType::Intel_v11) { cout << PACKAGE_NAME << ": Gathering information for Intel v11 OpenMP runtime" << endl; # warning "Aixo nomes es per !BinaryRewriting!" InstrumentOMPruntime_Intel (appImage, appProcess); } cout << PACKAGE_NAME << ": Instrumenting OpenMP runtime" << endl; InstrumentOMPruntime (::XML_GetTraceOMP_locks(), appType, appImage); } /* Apply instrumentation of runtimes only if not linked with Extrae */ if (!BinaryLinkedWithInstrumentation && appType->get_isCUDA()) { cout << PACKAGE_NAME << ": Instrumenting CUDA runtime" << endl; InstrumentCUDAruntime (appType, appImage); } /* If the application is NOT MPI, instrument the MAIN symbol in order to initialize and finalize the instrumentation */ /* Apply instrumentation of runtimes only if not linked with Extrae */ if (!appType->get_isMPI()) { /* Typical main entry & exit */ wrapRoutine (appImage, "main", "Extrae_init", "Extrae_fini"); } else { /* Cover those cases that MPI apps do not call MPI_Finalize */ wrapRoutine (appImage, "main", "", "Extrae_fini_last_chance_Wrapper"); } { /* Special cases (e.g., fortran stop call) */ string exit_calls[] = { "exit", /* C */ "_xlfExit", /* Fortran IBM XL */ "_gfortran_stop_numeric", /* Fortran GNU */ "for_stop_core", /* Fortran Intel */ "" }; /* bypass error messages given if these routines are not found */ int i = 0; extrae_detecting_application_type = true; while (exit_calls[i].length() > 0) { BPatch_function *special_exit = getRoutine (exit_calls[i].c_str(), appImage, false); if (NULL != special_exit) wrapRoutine (appImage, exit_calls[i], "Extrae_fini_last_chance_Wrapper", ""); i++; } extrae_detecting_application_type = false; } InstrumentCalls (appImage, appAddrSpace, appType, ParallelFunctions, UserFunctions, LoopLevels, ::XML_GetTraceMPI(), ::XML_GetTraceOMP(), true); GenerateSymFile (ParallelFunctions, UserFunctions, appImage, appAddrSpace); } // bpatch->registerExecCallback(ExecCallback); if (!BinaryRewrite) { cout << PACKAGE_NAME << ": Starting program execution" << endl; if (!appProcess->continueExecution()) { /* If the application cannot continue, terminate the mutatee and exit */ cerr << PACKAGE_NAME << ": Cannot continue execution of the target application" << endl; appProcess->terminateExecution(); exit (-1); } while (!appProcess->isTerminated()) bpatch->waitForStatusChange(); if (appProcess->terminationStatus() == ExitedNormally) appProcess->getExitCode(); else if(appProcess->terminationStatus() == ExitedViaSignal) appProcess->getExitSignal(); delete appProcess; } else { string newfile = string(argv[index])+".extrae"; cout << PACKAGE_NAME << ": Generating the instrumented binary" << endl; if (appBin->writeFile (newfile.c_str())) cout << PACKAGE_NAME << ": Congratulations " << newfile << " has been generated" << endl; else cout << PACKAGE_NAME << ": Error! Could not generate " << newfile << endl; delete appBin; } return 0; }
int launch_mutator() { unsigned i = 0, j = 0; const char *reason = NULL; char buf[STRING_MAX] = {0}; BPatch_Vector< BPatch_module * > *appModules = NULL; BPatch_Vector< BPatch_function * > *appFunctions = NULL; BPatch_flowGraph *appCFG = NULL; dynHandle *dh = mutatorInit(); if (!dh) return(-1); /************************************************************** * Parsing Phase */ // Is this if redundant? Will anybody run this without parsing the modules? if (config.parse_level >= PARSE_MODULE) { sendMsg(config.outfd, ID_PARSE_MODULE, INFO); appModules = dh->image->getModules(); if (!appModules) { sendMsg(config.outfd, ID_PARSE_MODULE, INFO, ID_FAIL, "Failure in BPatch_image::getModules()"); return(-1); } else sendMsg(config.outfd, ID_PARSE_MODULE, INFO, ID_PASS, appModules->size()); } if (config.parse_level >= PARSE_FUNC) { for (i = 0; i < appModules->size(); ++i) { (*appModules)[i]->getName(buf, sizeof(buf)); // Check module inclusion/exclusion regular expression rules. reason = config.mod_rules.getReason(buf); if (reason) sendMsg(config.outfd, ID_DATA_STRING, INFO, ID_INFO, reason); if (!config.mod_rules.isValid(buf)) continue; sendMsg(config.outfd, ID_PARSE_FUNC, INFO, ID_TEST, buf); appFunctions = (*appModules)[i]->getProcedures(); if (!appFunctions) { sendMsg(config.outfd, ID_PARSE_FUNC, INFO, ID_FAIL, "Failure in BPatch_module::getProcedures()"); return(-1); } else sendMsg(config.outfd, ID_PARSE_FUNC, INFO, ID_PASS, appFunctions->size()); if (config.parse_level >= PARSE_CFG) { sendMsg(config.outfd, ID_PARSE_MODULE_CFG, INFO, ID_TEST, (*appModules)[i]->getName(buf, sizeof(buf))); int cfg_warn_cnt = 0, cfg_pass_cnt = 0; for (j = 0; j < appFunctions->size(); ++j) { (*appFunctions)[j]->getName(buf, sizeof(buf)); // Check function inclusion/exclusion regular expression rules. reason = config.func_rules.getReason(buf); if (reason) sendMsg(config.outfd, ID_DATA_STRING, INFO, ID_INFO, reason); if (!config.func_rules.isValid(buf)) continue; sendMsg(config.outfd, ID_PARSE_FUNC_CFG, VERB1, ID_TEST, buf); appCFG = (*appFunctions)[j]->getCFG(); if (!appCFG) { sendMsg(config.outfd, ID_PARSE_FUNC_CFG, VERB1, ID_WARN, "Failure in BPatch_function::getCFG()"); ++cfg_warn_cnt; } else { sendMsg(config.outfd, ID_PARSE_FUNC_CFG, VERB1, ID_PASS); ++cfg_pass_cnt; } } if (cfg_warn_cnt) sendMsg(config.outfd, ID_PARSE_MODULE_CFG, INFO, ID_WARN, sprintf_static("%d warning(s), %d passed.", cfg_warn_cnt, cfg_pass_cnt)); else sendMsg(config.outfd, ID_PARSE_MODULE_CFG, INFO, ID_PASS); } } } /************************************************************** * Instrumentation Phase */ /* Load the library, if specified */ if (config.instType == USER_FUNC) { char instLibrary[1024]; int offset = strcspn(config.inst_function, ":"); strncpy (instLibrary, config.inst_function, offset); instLibrary[offset] = '\0'; if(! dh->addSpace->loadLibrary(instLibrary)) { sendMsg(config.outfd, ID_INST_FIND_POINTS, VERB3, ID_FAIL, "Failure in loading library"); return false; } } if (config.trace_inst) { errno = 0; sendMsg(config.outfd, ID_TRACE_INIT, INFO); sendMsg(config.outfd, ID_TRACE_OPEN_READER, VERB1); if (config.use_process) { config.pipefd = open(config.pipe_filename, O_RDONLY | O_RSYNC | O_NONBLOCK); if (config.pipefd < 0) { sendMsg(config.outfd, ID_TRACE_OPEN_READER, VERB1, ID_FAIL, sprintf_static("Mutator could not open trace pipe (%s) for read: %s\n", config.pipe_filename, strerror(errno))); config.pipefd = -1; } else { sendMsg(config.outfd, ID_TRACE_OPEN_READER, VERB1, ID_PASS); // Run mutatee side of trace initialization. sendMsg(config.outfd, ID_TRACE_INIT_MUTATEE, VERB1); if (!initTraceInMutatee(dh)) { sendMsg(config.outfd, ID_TRACE_INIT_MUTATEE, VERB1, ID_FAIL); config.pipefd = -1; } else sendMsg(config.outfd, ID_TRACE_INIT_MUTATEE, VERB1, ID_PASS); } if (config.pipefd == -1) { sendMsg(config.outfd, ID_TRACE_INIT, INFO, ID_FAIL, "Disabling instrumentation tracing."); } else sendMsg(config.outfd, ID_TRACE_INIT, INFO, ID_PASS); // We should remove the named pipe now, pass or fail. unlink(config.pipe_filename); } } if (config.inst_level >= INST_FUNC_ENTRY) { if (config.transMode == TRANS_PROCESS) if (!dynStartTransaction(dh)) return(-1); for (i = 0; i < appModules->size(); ++i) { int mod_warn_cnt = 0, mod_pass_cnt = 0; (*appModules)[i]->getName(buf, sizeof(buf)); // Check module inclusion/exclusion regular expression rules. reason = config.mod_rules.getReason(buf); if (reason) sendMsg(config.outfd, ID_DATA_STRING, INFO, ID_INFO, reason); if (!config.mod_rules.isValid(buf)) { continue; } if (config.transMode == TRANS_MODULE) if (!dynStartTransaction(dh)) { continue; } sendMsg(config.outfd, ID_INST_MODULE, INFO, ID_TEST, buf); sendMsg(config.outfd, ID_INST_GET_FUNCS, VERB1); appFunctions = (*appModules)[i]->getProcedures(); if (!appFunctions) { sendMsg(config.outfd, ID_INST_GET_FUNCS, VERB1, ID_FAIL, "Failure in BPatch_module::getProcedures()"); return(-1); } else sendMsg(config.outfd, ID_INST_GET_FUNCS, VERB1, ID_PASS, appFunctions->size()); for (j = 0; j < appFunctions->size(); ++j) { int func_warn_cnt = 0, func_pass_cnt = 0; (*appFunctions)[j]->getName(buf, sizeof(buf)); // Check function inclusion/exclusion regular expression rules. reason = config.func_rules.getReason(buf); if (reason) sendMsg(config.outfd, ID_DATA_STRING, INFO, ID_INFO, reason); if (!config.func_rules.isValid(buf)) continue; if (config.transMode == TRANS_FUNCTION) if (!dynStartTransaction(dh)) continue; sendMsg(config.outfd, ID_INST_FUNC, VERB1, ID_TEST, buf); if (config.inst_level == INST_FUNC_ENTRY) { if (!instrumentFunctionEntry(dh, (*appFunctions)[j])) ++func_warn_cnt; else ++func_pass_cnt; } if (config.inst_level == INST_FUNC_EXIT) { if (!instrumentFunctionExit(dh, (*appFunctions)[j])) ++func_warn_cnt; else ++func_pass_cnt; } if (config.inst_level == INST_BASIC_BLOCK) { if (!instrumentBasicBlocks(dh, (*appFunctions)[j])) ++func_warn_cnt; else ++func_pass_cnt; } if (config.inst_level == INST_MEMORY_READ) { if (!instrumentMemoryReads(dh, (*appFunctions)[j])) ++func_warn_cnt; else ++func_pass_cnt; } if (config.inst_level == INST_MEMORY_WRITE) { if (!instrumentMemoryWrites(dh, (*appFunctions)[j])) ++func_warn_cnt; else ++func_pass_cnt; } if (config.transMode == TRANS_FUNCTION) if (!dynEndTransaction(dh)) { func_warn_cnt = func_pass_cnt; func_pass_cnt = 0; } if (func_warn_cnt) { sendMsg(config.outfd, ID_INST_FUNC, VERB1, ID_WARN, sprintf_static("%d warning(s), %d passed.", func_warn_cnt, func_pass_cnt)); ++mod_warn_cnt; } else { sendMsg(config.outfd, ID_INST_FUNC, VERB1, ID_PASS); ++mod_pass_cnt; } } if (config.transMode == TRANS_MODULE) if (!dynEndTransaction(dh)) { mod_warn_cnt = mod_pass_cnt; mod_pass_cnt = 0; } if (mod_warn_cnt) sendMsg(config.outfd, ID_INST_MODULE, INFO, ID_WARN, sprintf_static("%d warning(s), %d passed.", mod_warn_cnt, mod_pass_cnt)); else sendMsg(config.outfd, ID_INST_MODULE, INFO, ID_PASS); } if (config.transMode == TRANS_PROCESS) dynEndTransaction(dh); } if (config.hunt_crashes) { sendMsg(config.outfd, ID_CRASH_HUNT_NUM_ACTIONS, INFO, ID_INFO, numInstsAllowed); } if (!config.use_process) { BPatch_binaryEdit *writeBE = dynamic_cast<BPatch_binaryEdit *>(dh->addSpace); // Load symbol libraries (if necessary) if( writeBE != NULL ) { deque<string>::iterator symLib_iter; for(symLib_iter = config.symbol_libraries.begin(); symLib_iter != config.symbol_libraries.end(); ++symLib_iter) { if( !writeBE->loadLibrary((*symLib_iter).c_str()) ) { sendMsg(config.outfd, ID_INST_FIND_POINTS, VERB3, ID_FAIL, "Unable to load symbol library"); return false; } } } writeBE->writeFile(config.writeFilePath); } if (config.use_process) { sendMsg(config.outfd, ID_RUN_CHILD, INFO); if (!dh->proc->continueExecution()) { sendMsg(config.outfd, ID_RUN_CHILD, INFO, ID_FAIL, "Failure in BPatch_thread::continueExecution()"); return false; } sendMsg(config.outfd, ID_RUN_CHILD, INFO, ID_PASS); // // Child continued. Start reading from trace pipe, if enabled. // if (config.trace_inst) { while (config.pipefd != -1) { sendMsg(config.outfd, ID_POLL_STATUS_CHANGE, DEBUG); bool change = dh->bpatch->pollForStatusChange(); sendMsg(config.outfd, ID_POLL_STATUS_CHANGE, DEBUG, ID_PASS); // Recheck conditional if a change was detected. if (change) continue; readTracePipe(); // Eeeew. I know. But how else do you wait on a file descriptor, // AND BPatch::pollforStatusChange() == true at the same time? // We should probably have BPatch::registerStatusChangeCallback() // or something similar. sleep(1); } } // // All processing complete. Loop indefinitly until exit handler called. // sendMsg(config.outfd, ID_WAIT_TERMINATION, INFO); while (1) { sendMsg(config.outfd, ID_CHECK_TERMINATION, INFO); bool dead = dh->proc->isTerminated(); sendMsg(config.outfd, ID_CHECK_TERMINATION, INFO, ID_PASS); if (dead) break; sendMsg(config.outfd, ID_WAIT_STATUS_CHANGE, DEBUG); if (!dh->bpatch->waitForStatusChange()) sendMsg(config.outfd, ID_WAIT_STATUS_CHANGE, DEBUG, ID_FAIL); else sendMsg(config.outfd, ID_WAIT_STATUS_CHANGE, DEBUG, ID_PASS); } sendMsg(config.outfd, ID_WAIT_TERMINATION, INFO, ID_PASS); } return 0; }
int main(int argc, char **argv) { if (argc < 3 || strncmp(argv[1], "-h", 2) == 0 || strncmp(argv[1], "--h", 3) == 0) { cout << "Usage: " << argv[0] << USAGE; return false; } if (!parseOptions(argc, argv)) { return EXIT_FAILURE; } if (do_bb == true) { if (DYNINST_MAJOR_VERSION < 9 || (DYNINST_MAJOR_VERSION == 9 && DYNINST_MINOR_VERSION < 3) || (DYNINST_MAJOR_VERSION == 9 && DYNINST_MINOR_VERSION == 3 && DYNINST_PATCH_VERSION <= 2)) { if (dynfix == false) fprintf(stderr, "Warning: your dyninst version does not include a critical fix, you should use the -f option!\n"); } else { if (dynfix == true) fprintf(stderr, "Notice: your dyninst version is fixed, the -f option should not be necessary.\n"); } } BPatch bpatch; BPatch_binaryEdit *appBin = bpatch.openBinary(originalBinary, instrumentLibraries.size() != 1); if (appBin == NULL) { cerr << "Failed to open binary" << endl; return EXIT_FAILURE; } BPatch_image *appImage = appBin->getImage(); //get and iterate over all modules, instrumenting only the default and manually specified ones vector < BPatch_module * >*modules = appImage->getModules(); vector < BPatch_module * >::iterator moduleIter; vector < BPatch_function * >*funcsInModule; BPatch_module *defaultModule = NULL; string defaultModuleName; // look for _init if (defaultModuleName.empty()) { for (moduleIter = modules->begin(); moduleIter != modules->end(); ++moduleIter) { funcsInModule = (*moduleIter)->getProcedures(); vector < BPatch_function * >::iterator funcsIterator; for (funcsIterator = funcsInModule->begin(); funcsIterator != funcsInModule->end(); ++funcsIterator) { char funcName[1024]; (*funcsIterator)->getName(funcName, 1024); if (string(funcName) == string("_init")) { char moduleName[1024]; (*moduleIter)->getName(moduleName, 1024); defaultModuleName = string(moduleName); if (verbose) { cout << "Found _init in " << moduleName << endl; } break; } } if (!defaultModuleName.empty()) break; } } // last resort, by name of the binary if (defaultModuleName.empty()) defaultModuleName = string(originalBinary).substr(string(originalBinary).find_last_of("\\/") + 1); if (!appBin->loadLibrary(instLibrary)) { cerr << "Failed to open instrumentation library " << instLibrary << endl; cerr << "It needs to be located in the current working directory." << endl; return EXIT_FAILURE; } appImage = appBin->getImage(); /* Find code coverage functions in the instrumentation library */ BPatch_function *initAflForkServer; save_rdi = findFuncByName(appImage, (char *) "save_rdi"); restore_rdi = findFuncByName(appImage, (char *) "restore_rdi"); BPatch_function *bbCallback = findFuncByName(appImage, (char *) "bbCallback"); BPatch_function *forceCleanExit = findFuncByName(appImage, (char *) "forceCleanExit"); if (do_bb == true) initAflForkServer = findFuncByName(appImage, (char *) "initAflForkServer"); else initAflForkServer = findFuncByName(appImage, (char *) "initOnlyAflForkServer"); if (!initAflForkServer || !bbCallback || !save_rdi || !restore_rdi || !forceCleanExit) { cerr << "Instrumentation library lacks callbacks!" << endl; return EXIT_FAILURE; } int bbIndex = 0; // instrument all shared libraries: 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; } if (do_bb == true) { 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]; int do_patch = 1; curFunc->getName(funcName, 1024); if (string(funcName) == string("_start")) continue; // here's a bug on hlt // XXX: check what happens if removed if (!skipAddresses.empty()) { set < string >::iterator saiter; for (saiter = skipAddresses.begin(); saiter != skipAddresses.end() && do_patch == 1; saiter++) if (*saiter == string(funcName)) do_patch = 0; if (do_patch == 0) { cout << "Skipping instrumenting function " << funcName << endl; continue; } } insertBBCallback(appBin, curFunc, funcName, bbCallback, &bbIndex); } } } // if an entrypoint was set then 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 manually with -e 0xaddr" << 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; } if (!exitAddresses.empty()) { cout << "Instrumenting forced exit addresses." << endl; set < unsigned long >::iterator uliter; for (uliter = exitAddresses.begin(); uliter != exitAddresses.end(); uliter++) { if (*uliter > 0 && (signed long)*uliter != -1) { funcToPatch = defaultModule->findFunctionByEntry(*uliter); if (!funcToPatch) { cerr << "Could not find enty point 0x" << hex << *uliter << " (continuing)" << endl; } else { if (!insertCallToInit(appBin, forceCleanExit, defaultModule, funcToPatch)) cerr << "Could not insert force clean exit callback at 0x" << hex << *uliter << " (continuing)" << endl; } } } } 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; } BPatch_image *libImg = libBin->getImage(); vector < BPatch_module * >*modules = libImg->getModules(); moduleIter = modules->begin(); 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; }