Beispiel #1
0
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;

}
Beispiel #2
0
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;
}
Beispiel #3
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;
}