Example #1
0
/*
 * BPatch_addressSpace::replaceFunctionCall
 *
 * Replace a function call with a call to a different function.  Returns true
 * upon success, false upon failure.
 *
 * point        The call site that is to be changed.
 * newFunc      The function that the call site will now call.
 */
bool BPatch_addressSpace::replaceFunctionCall(BPatch_point &point,
      BPatch_function &newFunc)
{
   char name[1024];
   newFunc.getName(name, 1024);

   // Can't make changes to code when mutations are not active.
   if (!getMutationsActive())
      return false;

   assert(point.point && newFunc.lowlevel_func());

  /* PatchAPI stuffs */
   AddressSpace* addr_space = point.getAS();
   DynModifyCallCommand* rep_call = DynModifyCallCommand::create(addr_space,
      point.point->block(), newFunc.lowlevel_func(), point.point->func());
  addr_space->patcher()->add(rep_call);
  /* End of PatchAPI */

   if (pendingInsertions == NULL) {
     // Trigger it now
     bool tmp;
     finalizeInsertionSet(false, &tmp);
   }
   return true;
}
Example #2
0
static void printCallingSites (int id, int total, char *name, string sharedlibname, BPatch_Vector<BPatch_point *> *vpoints)
{
	if (vpoints->size() > 0)
	{
		unsigned j = 0;
		cout << id << " of " << total << " - Calling sites for " << name << " within " << sharedlibname << " (num = " << vpoints->size() << "):" << endl;
		while (j < vpoints->size())
		{
			BPatch_function *called = ((*vpoints)[j])->getCalledFunction();
			if (NULL != called)
			{
				char calledname[1024];
				called->getName (calledname, 1024);
				cout << j+1 << " Calling " << calledname;
				BPatch_procedureLocation loc = ((*vpoints)[j])->getPointType();
				if (loc == BPatch_entry)
					cout << " (entry)" << endl;
				else if (loc == BPatch_exit)
					cout << " (exit)" << endl;
				else if (loc == BPatch_subroutine)
					cout << " (subroutine)" << endl;
				else
					cout << " (unknown point type)" << endl;
			}
			else
			{
				cout << j+1 << " Undetermined " << endl;
			}
			j++;
		}
		cout << endl;
	}
}
Example #3
0
int main (int argc, const char* argv[]) {
    BPatch bpatch;

    // argv[2] is muttee's file name, will be muttee's argv[0]
    BPatch_process *proc = bpatch.processCreate(argv[2], argv + 2);

    // Options to tune performance
    char *s;
    if ((s = getenv("SET_TRAMP_RECURSIVE")) && (strcmp(s, "true") == 0))
        bpatch.setTrampRecursive(true);
    if ((s = getenv("SET_SAVE_FPR")) && (strcmp(s, "false") == 0))
        bpatch.setSaveFPR(false);

    BPatch_object *ipa = proc->loadLibrary(argv[1]);
    BPatch_image *image = proc->getImage();

    std::vector<BPatch_function *> tracepoints, probes;
    image->findFunction("do_stuff", tracepoints);
    BPatch_function *tracepoint = tracepoints[0];
    image->findFunction("tpbench_no_arg", probes);
    BPatch_function *probe = probes[0];

    std::vector<BPatch_snippet*> args;
    BPatch_funcCallExpr call_probe(*probe, args);
    proc->insertSnippet(call_probe, (tracepoint->findPoint(BPatch_exit))[0]);

    proc->detach(true);

    return 0;
}
Example #4
0
void instrCodeNode::prepareCatchupInstr(pdvector<instReqNode *> &nodes_for_catchup)
{
    if (instrCatchuped()) return;

   for (unsigned instIter = 0; instIter < V.instRequests.size(); instIter++)
   {
      instReqNode *curInstReq = V.instRequests[instIter];
      //prepareCatchupInstr_debug(V.instRequests[instIter]);

      if (pd_debug_catchup) {     
         char buf[2048];
         BPatch_function *bpf = const_cast<BPatch_function *>(curInstReq->Point()->getFunction());
         if (! bpf) {
           sprintf(buf, "<bad function> in instReq");
         }
         else 
           bpf->getName(buf, 2048);
         cerr << "    looking at instReq [" << instIter << "], in func: "
              << buf <<endl;
      }

      BPatchSnippetHandle *sh = curInstReq->snippetHandle();
   }
   // don't mark catchup as having completed because we don't want to mark
   // this until the processMetFocusNode has completed initiating catchup for
   // all of the threads
}
Example #5
0
//
// findVariable
//	scp	- a BPatch_point that defines the scope of the current search
//	name	- name of the variable to find.
//
BPatch_variableExpr *BPatch_image::findVariableInScope(BPatch_point &scp,
        const char *name)
{
    // Get the function to search for it's local variables.
    // XXX - should really use more detailed scoping info here - jkh 6/30/99
    BPatch_function *func = const_cast<BPatch_function *> (scp.getFunction());
    if (!func) {
        pdstring msg = pdstring("point passed to findVariable lacks a function\n address point type passed?");
        showErrorCallback(100, msg);
        return NULL;
    }
    BPatch_localVar *lv = func->findLocalVar(name);

    if (!lv) {
        // look for it in the parameter scope now
        lv = func->findLocalParam(name);
    }
    if (lv) {
        // create a local expr with the correct frame offset or absolute
        //   address if that is what is needed
        return new BPatch_variableExpr(proc, (void *) lv->getFrameOffset(),
                                       lv->getRegister(), lv->getType(), lv->getStorageClass(), &scp);
    }

    // finally check the global scope.
    // return findVariable(name);

    /* If we have something else to try, don't report errors on this failure. */
    bool reportErrors = true;
    char mangledName[100];
    func->getName( mangledName, 100 );
    char * lastScoping = NULL;
    if( strrchr( mangledName, ':' ) != NULL ) {
        reportErrors = false;
    }
    BPatch_variableExpr * gsVar = findVariable( name, reportErrors );

    if( gsVar == NULL ) {
        /* Try finding it with the function's scope prefixed. */

        if( (lastScoping = strrchr( mangledName, ':' )) != NULL ) {
            * (lastScoping + sizeof(char)) = '\0';
            char scopedName[200];
            memmove( scopedName, mangledName, strlen( mangledName ) );
            memmove( scopedName + strlen( mangledName ), name, strlen( name ) );
            scopedName[ strlen( mangledName ) + strlen( name ) ] = '\0';
            bperr( "Searching for scoped name '%s'\n", scopedName );
            gsVar = findVariable( scopedName );
        }
    }
    return gsVar;
}
Example #6
0
void instrumentModule(BPatch_module *module)
{
	char funcname[BUFFER_STRING_LEN];

	instrumentPLTSection(module);
	std::vector<BPatch_function *>* functions;
	functions = module->getProcedures();

	for (unsigned i = 0; i < functions->size(); i++) {
		BPatch_function *function = functions->at(i);
		function->getName(funcname, BUFFER_STRING_LEN);
		instrumentFunction(function);
	}
}
Example #7
0
static void ShowFunctions (BPatch_image *appImage)
{
	BPatch_Vector<BPatch_function *> *vfunctions = appImage->getProcedures (false);
	cout << PACKAGE_NAME << ": " << vfunctions->size() << " functions found in binary " << endl;

	unsigned i = 0;
	while (i < vfunctions->size())
	{
		char name[1024];
		BPatch_function *f = (*vfunctions)[i];

		f->getName (name, 1024);

		if (VerboseLevel)
		{
			char mname[1024], tname[1024], modname[1024];
			f->getMangledName (mname, 1024);
			f->getTypedName (tname, 1024);
			f->getModuleName (modname, 1024);

			cout << " * " << i+1 << " of " << vfunctions->size() << ", Name: " << name << endl
			     << "    Mangled Name: " << mname << endl
			     << "    Typed Name  : " << tname << endl
			     << "    Module name : " << modname << endl
			     << "    Base address: " << f->getBaseAddr() << endl
			     << "    Instrumentable? " << (f->isInstrumentable()?"yes":"no") << endl
			     << "    In shared library? " << (f->isSharedLib()?"yes":"no") << endl
                 << "    Number of BB: " << getBasicBlocksSize(f) << endl; 

			if (f->isSharedLib())
			{
				char sharedlibname[1024];
				BPatch_module *mod = f->getModule();

				mod->getFullName (sharedlibname, 1024);
				cout << "    Full library name: " << sharedlibname << endl;
				
			}
			cout << endl;
		}
		else
		{
			cout << name << endl;
		}

		i++;
	} 
}
Example #8
0
/* Invoked for every signal handler function, adjusts the value of the saved 
 * fault address to its unrelocated counterpart in the CONTEXT structure,
 * which contains the PC that is used when execution resumes
 */
void HybridAnalysis::signalHandlerEntryCB2(BPatch_point *point, Address excCtxtAddr)
{
    mal_printf("\nAt signalHandlerEntry2(%lx , %lx)\n", 
               point->getAddress(), (Address)excCtxtAddr);

    // calculate the offset of the fault address in the EXCEPTION_RECORD
    CONTEXT *cont= (CONTEXT*)excCtxtAddr; //bogus pointer, but I won't write to it
    Address pcAddr = excCtxtAddr + (Address)(&(cont->Eip)) - (Address)cont;

    // set fault address to the unrelocated address of that instruction
    // and save the PC address in the CONTEXT structure so the exit handler 
    // can read it
    BPatch_function *func = point->getFunction();
    func->setHandlerFaultAddrAddr((Address)pcAddr,true);
    handlerFunctions[(Address)func->getBaseAddr()].faultPCaddr = pcAddr;
}
Example #9
0
/*
 * BPatch_addressSpace::revertReplaceFunction
 *
 * Undoes a replaceFunction operation
 */
bool BPatch_addressSpace::revertReplaceFunction(BPatch_function &oldFunc)
{
  assert(oldFunc.lowlevel_func());
  if (!getMutationsActive())
    return false;

  func_instance *func = oldFunc.lowlevel_func();

  func->proc()->revertReplacedFunction(func);

  if (pendingInsertions == NULL) {
    // Trigger it now
    bool tmp;
    finalizeInsertionSet(false, &tmp);
  }
  return true;
}
Example #10
0
/*
 * BPatch_addressSpace::replaceFunction
 *
 * Replace all calls to function OLDFUNC with calls to NEWFUNC.
 * Returns true upon success, false upon failure.
 *
 * oldFunc      The function to replace
 * newFunc      The replacement function
 */
bool BPatch_addressSpace::replaceFunction(BPatch_function &oldFunc,
      BPatch_function &newFunc)
{
  assert(oldFunc.lowlevel_func() && newFunc.lowlevel_func());
  if (!getMutationsActive())
    return false;

  // Self replacement is a nop
  // We should just test direct equivalence here...
  if (oldFunc.lowlevel_func() == newFunc.lowlevel_func()) {
    return true;
  }

  /* PatchAPI stuffs */
  AddressSpace* addr_space = oldFunc.lowlevel_func()->proc();
  DynReplaceFuncCommand* rep_func = DynReplaceFuncCommand::create(addr_space,
     oldFunc.lowlevel_func(), newFunc.lowlevel_func());
  addr_space->patcher()->add(rep_func);
  /* End of PatchAPI */

  if (pendingInsertions == NULL) {
    // Trigger it now
    bool tmp;
    finalizeInsertionSet(false, &tmp);
  }
  return true;
}
Example #11
0
void handleModule(BPatch_module *mod, const char *name)
{
	char funcname[BUFFER_STRING_LEN];

	// get list of all functions
	std::vector<BPatch_function *>* functions;
	functions = mod->getProcedures();

	// for each function ...
	for (unsigned i = 0; i < functions->size(); i++) {
		BPatch_function *function = functions->at(i);
		function->getName(funcname, BUFFER_STRING_LEN);

        printf("  FUNC: %s (%lx)\n", funcname, (unsigned long)function->getBaseAddr());

	}

}
Example #12
0
/* Invoked for every signal handler function, adjusts the value of the saved 
 * fault address to its unrelocated counterpart in the EXCEPTION_RECORD
 */
void HybridAnalysis::signalHandlerEntryCB(BPatch_point *point, Address excRecAddr)
{
    mal_printf("\nAt signalHandlerEntry(%lx , %lx)\n", 
               point->getAddress(), (Address)excRecAddr);
    stats_.exceptions++;
    // calculate the offset of the fault address in the EXCEPTION_RECORD
    EXCEPTION_RECORD record;
    proc()->lowlevel_process()->readDataSpace(
        (void*)excRecAddr, sizeof(EXCEPTION_RECORD), &record, true);
    Address pcAddr = excRecAddr 
        + (Address) &(record.ExceptionAddress) 
        - (Address) &record;

    // set fault address to the unrelocated address of that instruction
    BPatch_function *func = point->getFunction();
    func->setHandlerFaultAddrAddr((Address)pcAddr,false);
    handlerFunctions[(Address)func->getBaseAddr()].isInterrupt = 
        (record.ExceptionCode == EXCEPTION_BREAKPOINT);
}
static void ShowFunctions (BPatch_image *appImage)
{
	BPatch_Vector<BPatch_function *> *vfunctions = appImage->getProcedures (false);
	cout << PACKAGE_NAME << ": " << vfunctions->size() << " functions found in binary " << endl;

	unsigned i = 0;
	while (i < vfunctions->size())
	{
		char name[1024];
		BPatch_function *f = (*vfunctions)[i];

		f->getName (name, 1024);

		char mname[1024], tname[1024], modname[1024];
		f->getMangledName (mname, 1024);
		f->getTypedName (tname, 1024);
		f->getModuleName (modname, 1024);

		cout << " * " << i+1 << " of " << vfunctions->size() << ", Name: " << name << endl
		     << "    Mangled Name: " << mname << endl
		     << "    Typed Name  : " << tname << endl
		     << "    Module name : " << modname << endl
		     << "    Base address: " << f->getBaseAddr() << endl
		     << "    Instrumentable? " << (f->isInstrumentable()?"yes":"no") << endl
		     << "    In shared library? " << (f->isSharedLib()?"yes":"no") << endl;

		if (f->isSharedLib())
		{
			//Old Dyninst API < 9.x
			//char sharedlibname[1024];
			//mod->getFullName (sharedlibname, 1024);

			BPatch_module *mod = f->getModule();

			string sharedlibname;
			sharedlibname = mod->getObject()->name();
			cout << "    Full library name: " << sharedlibname << endl;
		}
		cout << endl;

		i++;
	} 
}
Example #14
0
/* If the context of the exception has been changed so that execution
 * will resume at a new address, parse and instrument the code at that
 * address; then add a springboard at that address if it is not the 
 * entry point of a function
 */
void HybridAnalysis::signalHandlerExitCB(BPatch_point *point, void *)
{
    BPatch_function *func = point->getFunction();
    std::map<Dyninst::Address, ExceptionDetails>::iterator diter = 
        handlerFunctions.find((Address)func->getBaseAddr());
    assert(handlerFunctions.end() != diter && 
           0 != diter->second.faultPCaddr);
    Address pcLoc = diter->second.faultPCaddr;

    mal_printf("\nAt signalHandlerExit(%lx)\n", point->getAddress());

    // figure out the address the program will resume at by reading 
    // in the stored CONTEXT structure
    Address resumePC;
    assert(sizeof(Address) == proc()->getAddressWidth());
    proc()->lowlevel_process()->readDataSpace(
        (void*)pcLoc, sizeof(resumePC), &resumePC, true);
    if (diter->second.isInterrupt) {
        resumePC += 1;
    }

    // parse at the resumePC address, if necessary
    vector<BPatch_function *> funcs;
    proc()->findFunctionsByAddr((Address)resumePC,funcs);
    if (funcs.empty()) {
        mal_printf("Program will resume in new function at %lx\n", resumePC);
    }
    else {
        mal_printf("Program will resume at %lx in %d existing functions, "
                   "will add shared function starting at %lx\n", 
                   resumePC, funcs.size(), resumePC);
    }
    analyzeNewFunction(point, (Address)resumePC, true, true);

    mal_printf("Exception handler exiting at %lx will resume execution at "
                "%lx %s[%d]\n",
                point->getAddress(), resumePC, FILE__,__LINE__);
}
Example #15
0
void Instrumentcall (BPatch_image *appImage, BPatch_process *appProcess)
{
	unsigned insertion = 0;
	unsigned i = 0;

	BPatch_Vector<BPatch_function *> *vfunctions = appImage->getProcedures (true);
	cout << vfunctions->size() << " functions found in binary " << endl;

	cout << "Parsing functions " << flush;

	while (i < vfunctions->size())
	{
		char name[1024], sharedlibname[1024];

		BPatch_function *f = (*vfunctions)[i];
		(f->getModule())->getFullName (sharedlibname, 1024);
		f->getName (name, 1024);

		BPatch_Vector<BPatch_point *> *vpoints = f->findPoint (BPatch_subroutine);

		unsigned j = 0;
		while (j < vpoints->size())
		{
			BPatch_function *called = ((*vpoints)[j])->getCalledFunction();
			if (NULL != called)
			{
				char calledname[1024];
				called->getName (calledname, 1024);
				if (strcmp (calledname, "functionB") == 0)
				{
					string s = "functionA";
					BPatch_function *patch = getRoutine (s, appImage);
					if (patch != NULL)
					{
						bool replaced = appProcess->replaceFunctionCall (*((*vpoints)[j]), *patch);
						if (replaced)
							cout << "call to functionA has been successfully replaced by a call to functionB" << endl;
						else
							cout << "call to functionA failed to replace a call to functionB" << endl;

						insertion++;
					}
				}
			}
			j++;
		}

		i++;
	}

	cout << endl;

	cout << "insertion = " << insertion << endl;
}
Example #16
0
static void GenerateSymFile (set<string> &ParFunc, set<string> &UserFunc, BPatch_image *appImage, BPatch_addressSpace *appProces)
{
	ofstream symfile;
	string symname = string(::XML_GetFinalDirectory())+string("/")+string(::XML_GetTracePrefix())+".sym";

	symfile.open (symname.c_str());
	if (!symfile.good())
	{
		cerr << "Cannot create the symbolic file" << symname << endl;
		return;
	}

	for (set<string>::iterator iter = ParFunc.begin();
		iter != ParFunc.end(); iter++)
	{
		BPatch_function *f = getRoutine ((*iter).c_str(), appImage);

		if (f != NULL)
		{
			BPatch_Vector< BPatch_statement > lines;

			appProces->getSourceLines ((unsigned long) f->getBaseAddr(), lines);
			if (lines.size() > 0)
			{
				symfile << "P " << hex << f->getBaseAddr() << dec << " \"" << *iter
					<< "\" \"" <<  lines[0].fileName() <<  "\" " << lines[0].lineNumber()
					<< endl;
			}
			else
			{
				/* this happens if the application was not compiled with -g */
				char modname[1024];
				f->getModuleName (modname, 1024);
				symfile << "P " << hex << f->getBaseAddr() << dec << " \"" << *iter
					<< "\" \"" << modname << "\" 0" << endl;
			}
		}
	}

	for (set<string>::iterator iter = UserFunc.begin();
		iter != UserFunc.end(); iter++)
	{
		BPatch_function *f = getRoutine ((*iter).c_str(), appImage);

		if (f != NULL)
		{
			BPatch_Vector< BPatch_statement > lines;

			appProces->getSourceLines ((unsigned long) f->getBaseAddr(), lines);
			if (lines.size() > 0)
			{
				symfile << "U " << hex << f->getBaseAddr() << dec << " \"" << *iter
					<< "\" \"" << lines[0].fileName() <<  "\" " << lines[0].lineNumber()
					<< endl;
			}
			else
			{
				/* this happens if the application was not compiled with -g */
				char modname[1024];
				f->getModuleName (modname, 1024);
				symfile << "U " << hex << f->getBaseAddr() << dec << " \"" << *iter
					<< "\" \"" << modname << "\" 0" << endl;
			}
		}
	}

    map<string, unsigned>::iterator BB_symbols_iter = BB_symbols->begin();
    map<string, unsigned>::iterator BB_symbols_end = BB_symbols->end();
    while(BB_symbols_iter != BB_symbols_end){
        symfile << "b " << BB_symbols_iter->second << " \"" << BB_symbols_iter->first << "\"\n";
        BB_symbols_iter++;
    }



	symfile.close();
}
Example #17
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;

}
Example #18
0
void HybridAnalysis::badTransferCB(BPatch_point *point, void *returnValue) 
{
    Address pointAddr = (Address) point->getAddress();
    Address target = (Address) returnValue;

    time_t tstruct;
    struct tm * tmstruct;
    char timeStr[64];
    time( &tstruct );
    tmstruct = localtime( &tstruct );
    strftime(timeStr, 64, "%X", tmstruct);

    mal_printf("badTransferCB %lx=>%lx %s\n\n", pointAddr, target, timeStr);
    BPatch_module * targMod = proc()->findModuleByAddr(target);
    if (!targMod) {
        mal_printf( "ERROR, NO MODULE for target addr %lx %s[%d]\n", 
                target,FILE__,__LINE__);
        assert(0);
    }

    if (targMod == point->getFunction()->getModule() && targMod->isSystemLib()) {
        return;
    }

// 1. the target address is in a shared library
    if ( targMod != point->getFunction()->getModule()) 
    {
        // process the edge, decide if we should instrument target function
        bool doMoreProcessing = processInterModuleEdge(point, target, targMod);

        if (!doMoreProcessing) {
            return;
        }
    }

// 2. the point is a call: 
    if (point->getPointType() == BPatch_subroutine) {

        proc()->beginInsertionSet();
        // if the target is in the body of an existing function we'll split 
        // the function and wind up with two or more functions that share
        // the target address, so make sure we're not in the middle of an
        // overwrite loop; if we are, check for overwrites immediately
        BPatch_function *targFunc = proc()->findFunctionByEntry(target);
        vector<BPatch_function*> targFuncs;
        proc()->findFunctionsByAddr(target, targFuncs);
        if (!targFunc && targFuncs.size()) {
            mal_printf("discovery instr. got new entry point for func\n");
            std::set<HybridAnalysisOW::owLoop*> loops;
            for (unsigned tidx=0; tidx < targFuncs.size(); tidx++) {
                BPatch_function *curFunc = targFuncs[tidx];
                if ( hybridOW()->hasLoopInstrumentation(false, *curFunc, &loops) )
                {
                    /* Code sharing will change the loops, the appropriate response
                    is to trigger early exit analysis and remove the loops if 
                    the underlying code hasn't changed */
                    mal_printf("[%d] Removing loop instrumentation for func %lx\n", 
                                __LINE__,curFunc->getBaseAddr());
                    std::set<HybridAnalysisOW::owLoop*>::iterator lIter = 
                        loops.begin();
                    while (lIter != loops.end()) {
                        hybridOW()->deleteLoop(*lIter,false);
                        lIter++;
                    }
                }
            }
        }

        // 2.1 if the target is new, parse at the target
        if ( ! targFunc ) {
            mal_printf("stopThread instrumentation found call %lx=>%lx, "
                      "parsing at call target %s[%d]\n",
                     (long)point->getAddress(), target,FILE__,__LINE__);
            if (!analyzeNewFunction( point,target,false,false )) {
                //this happens for some single-instruction functions
                mal_printf("ERROR: parse of call target %lx=>%lx failed %s[%d]\n",
                         (long)point->getAddress(), target, FILE__,__LINE__);
                assert(0);
                instrumentModules(false);
                proc()->finalizeInsertionSet(false);
                return;
            }
            targFunc = proc()->findFunctionByEntry(target);
        }

        // 2.2 if the target is a returning function, parse at the fallthrough
        bool instrument = true;
        if ( ParseAPI::RETURN == 
             targFunc->lowlevel_func()->ifunc()->retstatus() ) 
        {
            //mal_printf("stopThread instrumentation found returning call %lx=>%lx, "
            //          "parsing after call site\n",
            //         (long)point->getAddress(), target);
            if (parseAfterCallAndInstrument(point, targFunc, false)) {
               instrument = false;
            }
        } 
        if (instrument) {
            instrumentModules(false);
        }
        proc()->finalizeInsertionSet(false);
        // 2. return
        return;
    }

// 3. the point is a return instruction:
    if ( point->getPointType() == BPatch_locExit ) {

        // 3.2 find the call point so we can parse after it
        //   ( In this case "point" is the return statement and 
        //   "target" is the fallthrough address of the call insn )
        //   in order to find the callPoint in the caller function that 
        //   corresponds to the non-returning call, we traverse list of
        //   the caller's points to find the callpoint that is nearest
        //   to the return address

        Address returnAddr = target;
        using namespace ParseAPI;


        // Find the call blocks preceding the address that we're returning 
        // past, but only set set returningCallB if we can be sure that 
        // that we've found a call block that actually called the function
        // we're returning from 
        pair<Block*, Address> returningCallB((Block*)NULL,0); 
        set<Block*> callBlocks;
        getCallBlocks(returnAddr, point->llpoint()->func(), 
                      point->llpoint()->block(), returningCallB, callBlocks);

        // 3.2.1 parse at returnAddr as the fallthrough of the preceding
        // call block, if there is one 
        if (!callBlocks.empty()) {

            // we don't know if the function we called returns, so 
            // invoke parseAfterCallAndInstrument with NULL as the
            // called func, so we won't try to parse after other 
            // callers to the called func, as it may not actually
            // return in a normal fashion
            if (NULL == returningCallB.first) {
                vector<BPatch_point*> callPts; 
                for (set<Block*>::iterator bit = callBlocks.begin(); 
                     bit != callBlocks.end(); 
                     bit++)
                {
                    getPreCallPoints(*bit, proc(), callPts);
                }
                for (vector<BPatch_point*>::iterator pit = callPts.begin(); 
                     pit != callPts.end(); 
                     pit++)
                {
                    parseAfterCallAndInstrument( *pit, NULL, true );
                }
            }

            // if the return address has been parsed as the entry point
            // of a block, patch post-call areas and return
            else if ( returningCallB.first->obj()->findBlockByEntry(
                          returningCallB.first->region(), 
                          target))
            {
                vector<BPatch_point*> callPts; 
                getPreCallPoints(returningCallB.first, proc(), callPts);
                for (unsigned j=0; j < callPts.size(); j++) {
                    callPts[j]->patchPostCallArea();
                }
            }

            else { // parse at the call fallthrough

                // find one callPoint, any other ones will 
                // be found by parseAfterCallAndInstrument
                vector<BPatch_point*> callPoints;
                getPreCallPoints(returningCallB.first, proc(), callPoints);
                assert(!callPoints.empty());

                mal_printf("stopThread instrumentation found return at %lx, "
                          "parsing return addr %lx as fallthrough of call "
                          "instruction at %lx %s[%d]\n", (long)point->getAddress(), 
                          target,callPoints[0]->getAddress(),FILE__,__LINE__);

                if (point->llpoint()->block()->llb()->isShared()) {
                    // because of pc emulation, if the return point is shared, 
                    // we may have flipped between functions that share the 
                    // return point, so use the call target function
                    BPatch_function *calledFunc = proc()->
                        findFunctionByEntry(returningCallB.second);
                    parseAfterCallAndInstrument( callPoints[0], calledFunc, true );
                }
                else {
                    parseAfterCallAndInstrument( callPoints[0], 
                                                 point->getFunction(),
                                                 true);
                }
            }
        }

        // 3.2.2 no call blocks, parse the return addr as a new function
        else {
            if ( point->getFunction()->getModule()->isExploratoryModeOn() ) {
                // otherwise we've instrumented a function in trusted library
                // because we want to catch its callbacks into our code, but in
                // the process are catching calls into other modules
                mal_printf("hybridCallbacks.C[%d] Observed abuse of normal return "
                        "instruction semantics for insn at %lx target %lx\n",
                        __LINE__, point->getAddress(), returnAddr);
            }
            analyzeNewFunction( point, returnAddr, true , true );

            // there are no call blocks, so we don't have any post-call pads to patch
        }

        // 3. return
        return;
    }

    // 4. else case: the point is a jump/branch 
    proc()->beginInsertionSet();
    // 4.1 if the point is a direct branch, remove any instrumentation
    if (!point->isDynamic()) {
        BPatch_function *func = point->getFunction();
        if (instrumentedFuncs->end() != instrumentedFuncs->find(func)
            &&
            (*instrumentedFuncs)[func]->end() != 
            (*instrumentedFuncs)[func]->find(point))
        {
            proc()->deleteSnippet(
                (*(*instrumentedFuncs)[func])[point] );
            (*instrumentedFuncs)[func]->erase(point);
        }
        //point is set to resolved in handleStopThread
    } 

    bool newParsing;
    vector<BPatch_function*> targFuncs;
    proc()->findFunctionsByAddr(target, targFuncs);
    if ( 0 == targFuncs.size() ) { 
        newParsing = true;
        mal_printf("stopThread instrumentation found jump "
                "at 0x%lx leading to an unparsed target at 0x%lx\n",
                (long)point->getAddress(), target);
    } else {
        newParsing = false;
        mal_printf("stopThread instrumentation added an edge for jump "
                " at 0x%lx leading to a previously parsed target at 0x%lx\n",
                (long)point->getAddress(), target);
    }

    // add the new edge to the program, parseNewEdgeInFunction will figure
    // out whether to extend the current function or parse as a new one. 
    if (targMod != point->getFunction()->getModule()) {
        // Don't put in inter-module branches
        if (newParsing)
            analyzeNewFunction(point, target, true, false);
    }
    else
    {
        parseNewEdgeInFunction(point, target, false);
    }

    if (0 == targFuncs.size()) {
        proc()->findFunctionsByAddr( target, targFuncs );
    }

    // manipulate init_retstatus so that we will instrument the function's 
    // return addresses, since this jump might be a tail call
    for (unsigned tidx=0; tidx < targFuncs.size(); tidx++) {
        parse_func *imgfunc = targFuncs[tidx]->lowlevel_func()->ifunc();
        FuncReturnStatus initStatus = imgfunc->init_retstatus();
        if (ParseAPI::RETURN == initStatus) {
            imgfunc->setinit_retstatus(ParseAPI::UNKNOWN);
            removeInstrumentation(targFuncs[tidx],false,false);
            instrumentFunction(targFuncs[tidx],false,true);
        } 
    }

    // re-instrument the function or the whole module, as needed
    if (newParsing) {
        instrumentModules(false);
    }
    proc()->finalizeInsertionSet(false);
} // end badTransferCB
Example #19
0
// 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() */
Example #20
0
void HybridAnalysis::virtualFreeCB(BPatch_point *, void *t) {
	assert(virtualFreeAddr_ != 0);
	unsigned type = (unsigned) t;
	cerr << "virtualFree [" << hex << virtualFreeAddr_ << "," << virtualFreeAddr_ + (unsigned) virtualFreeSize_ << "], " << (unsigned) type << dec << endl;

	Address pageSize = proc()->lowlevel_process()->getMemoryPageSize();

	// Windows page-aligns everything.

	unsigned addrShift = virtualFreeAddr_ % pageSize;
	unsigned sizeShift = pageSize - (virtualFreeSize_ % pageSize);

	virtualFreeAddr_ -= addrShift;

	if (type != MEM_RELEASE)
	{
		virtualFreeSize_ += addrShift + sizeShift;
	}

	// We need to:
	// 1) Remove any function with a block in the deleted range
	// 2) Remove memory translation for that range
	// 3) Skip trying to set permissions for any page in the range.

	// DEBUG!
	if (1 || type == MEM_RELEASE)
	{
		mapped_object *obj = proc()->lowlevel_process()->findObject(virtualFreeAddr_);

		if (!obj) return;
		virtualFreeAddr_ = obj->codeBase();
		virtualFreeSize_ = obj->imageSize();
		// DEBUG!
		cerr << "Removing VirtualAlloc'ed shared object " << obj->fileName() << endl;
      image *img = obj->parse_img();
		proc()->lowlevel_process()->removeASharedObject(obj);
		virtualFreeAddr_ = 0;
      // Since removeASharedObject doesn't actually delete the object, 
      // or its image (even if its refCount==0), make sure the image
      // goes away from global datastructure allImages
      for (unsigned int i=0; i < allImages.size(); i++) {
         if (img == allImages[i]) {
            allImages[i] = allImages.back();
            allImages.pop_back();
         }
      }
		return;
	}

	std::set<func_instance *> deletedFuncs;
	for (Address i = virtualFreeAddr_; i < (virtualFreeAddr_ + virtualFreeSize_); ++i) {
		proc()->lowlevel_process()->findFuncsByAddr(i, deletedFuncs);
	}
	for (std::set<func_instance *>::iterator iter = deletedFuncs.begin();
		iter != deletedFuncs.end(); ++iter)
	{
		BPatch_function * bpfunc = proc()->findOrCreateBPFunc(*iter, NULL);
		if (!bpfunc) continue;
        PatchAPI::PatchModifier::remove(bpfunc->lowlevel_func());
	}

	proc()->lowlevel_process()->getMemEm()->removeRegion(virtualFreeAddr_, virtualFreeSize_);
	// And nuke the RT cache

	proc()->lowlevel_process()->proc()->flushAddressCache_RT(virtualFreeAddr_, virtualFreeSize_);

	virtualFreeAddr_ = 0;
	return;
}
Example #21
0
static void InstrumentCalls (BPatch_image *appImage, BPatch_addressSpace *appProcess,
	ApplicationType *appType, set<string> &OMPset, set<string> &USERset,
    map<string, vector<string> > & LoopLevels,
    bool instrumentMPI, bool instrumentOMP, bool instrumentUF)
{
	unsigned i = 0;
	unsigned OMPinsertion = 0;
	unsigned OMPreplacement_intel_v11 = 0;
	unsigned MPIinsertion = 0;
	unsigned APIinsertion = 0;
	unsigned UFinsertion = 0;
	const char *PMPI_C_prefix = "PMPI_";
	const char *PMPI_F_prefix = "pmpi_";
	const char *MPI_C_prefix = "MPI_";
	const char *MPI_F_prefix= "mpi_";

	cout << PACKAGE_NAME << ": Obtaining functions from application image (this may take a while)..." << flush;
	BPatch_Vector<BPatch_function *> *vfunctions = appImage->getProcedures (false);
	cout << "Done" << endl;

	set<string> CUDAkernels;

	/* Look for CUDA kernels if the application is CUDA */
	if (appType->get_isCUDA())
	{
		cout << PACKAGE_NAME << ": Looking for CUDA kernels inside binary (this may take a while)..." << endl;

		i = 0;
		while (i < vfunctions->size())
		{
			char name[1024];

			BPatch_function *f = (*vfunctions)[i];
			f->getName (name, sizeof(name));
			BPatch_Vector<BPatch_point *> *vpoints = f->findPoint (BPatch_subroutine);

			if (vpoints != NULL)
			{
				unsigned j = 0;
				while (j < vpoints->size())
				{
					BPatch_function *called = ((*vpoints)[j])->getCalledFunction();
					if (NULL != called)
					{
						char calledname[1024];
						called->getName (calledname, 1024);
	
						if (strncmp (calledname, "__device_stub__", strlen("__device_stub__")) == 0)
						{
							CUDAkernels.insert (name);
							if (VerboseLevel)
								cout << PACKAGE_NAME << ": Found kernel " << name << endl;
						}
					}
					j++;
				}
			}
			i++;
		}
		cout << PACKAGE_NAME << ": Finished looking for CUDA kernels" << endl;
	}

	cout << PACKAGE_NAME << ": Parsing executable looking for instrumentation points (" << vfunctions->size() << ") ";
	if (VerboseLevel)
		cout << endl;
	else
		cout << flush;

	/*
	  The 1st step includes:
	  a) gather information of openmp outlined routines (original is added to USERset),
	  b) instrument openmp outlined routines
	  c) instrument mpi calls
	  d) instrument api calls
	*/

	i = 0;
	while (i < vfunctions->size())
	{
		char name[1024], sharedlibname_c[1024];

		BPatch_function *f = (*vfunctions)[i];
		(f->getModule())->getFullName (sharedlibname_c, sizeof(sharedlibname_c));
		f->getName (name, sizeof(name));

		string sharedlibname = sharedlibname_c;

		string sharedlibname_ext;
		if (sharedlibname.rfind('.') != string::npos)
			sharedlibname_ext = sharedlibname.substr (sharedlibname.rfind('.'));
		else
			sharedlibname_ext = "";

		/* For OpenMP apps, if the application has been linked with Extrae, just need to
		   instrument the function calls that have #pragma omp in them. The outlined
			 routines will be instrumented by the library attached to the binary */
		if (!BinaryLinkedWithInstrumentation &&
		    instrumentOMP && appType->get_isOpenMP() && loadedModule != sharedlibname)
		{
			/* OpenMP instrumentation (just for OpenMP apps) */
			if (appType->isMangledOpenMProutine (name))
			{
				if (VerboseLevel)
					if (!BinaryLinkedWithInstrumentation)
						cout << PACKAGE_NAME << ": Instrumenting OpenMP outlined routine " << name << endl;

				if (!BinaryLinkedWithInstrumentation)
				{
					/* Instrument routine */ 
					wrapTypeRoutine (f, name, OMPFUNC_EV, appImage);

					/* Add to list if not already there */
					OMPset.insert (name);
				}

				/* Demangle name and add into the UF list if it didn't exist there */
				string demangled = appType->demangleOpenMProutine (name);
				if (!XML_excludeAutomaticFunctions())
					USERset.insert (demangled);
				if (VerboseLevel)
				{
					if (!XML_excludeAutomaticFunctions())
						cout << PACKAGE_NAME << ": Adding demangled OpenMP routine " << demangled << " to the user function list" << endl;	
					else
						cout << PACKAGE_NAME << ": Will not add demangled OpenMP routine " << demangled << " due to user request in the XML configuration file" << endl;
				}

				OMPinsertion++;
			}
		}

		if (sharedlibname_ext == ".f" || sharedlibname_ext == ".F" ||   /* fortran */
		  sharedlibname_ext == ".for" || sharedlibname_ext == ".FOR" || /* fortran */
		  sharedlibname_ext == ".f90" || sharedlibname_ext == ".F90" || /* fortran 90 */
		  sharedlibname_ext == ".i90" ||                                /* fortran 90 through ifort */
		  sharedlibname_ext == ".f77" || sharedlibname_ext == ".F77" || /* fortran 77 */
		  sharedlibname_ext == ".c" || sharedlibname_ext == ".C" ||     /* C */
		  sharedlibname_ext == ".cxx" || sharedlibname_ext == ".cpp" || /* c++ */
		  sharedlibname_ext == ".c++" || /* c++ */
		  sharedlibname_ext == ".i" || /* some compilers generate this extension in intermediate files */ 
		  sharedlibname == "DEFAULT_MODULE" /* Dyninst specific container that represents the executable */
		)
		{
			/* API instrumentation (for any kind of apps)
	
			   Skip calls from my own module
			*/
			BPatch_Vector<BPatch_point *> *vpoints = f->findPoint (BPatch_subroutine);

			if (vpoints == NULL)
				break;

			if (VerboseLevel >= 2)
				printCallingSites (i, vfunctions->size(), name, sharedlibname, vpoints);

			unsigned j = 0;
			while (j < vpoints->size())
			{
				BPatch_function *called = ((*vpoints)[j])->getCalledFunction();
				if (NULL != called)
				{
					char calledname[1024];
					called->getName (calledname, 1024);

					/* Check API calls */
					BPatch_function *patch_api = getAPIPatch (calledname);
					if (patch_api != NULL)
					{
						if (appProcess->replaceFunctionCall (*((*vpoints)[j]), *patch_api))
						{
							APIinsertion++;
							if (VerboseLevel)
								cout << PACKAGE_NAME << ": Replaced call " << calledname << " in routine " << name << " (" << sharedlibname << ")" << endl;
						}
						else
							cerr << PACKAGE_NAME << ": Cannot replace " << calledname << " routine" << endl;
					}

					/* Check MPI calls */
					if (!BinaryLinkedWithInstrumentation &&
					    instrumentMPI && appType->get_isMPI() && (
					    strncmp (calledname, PMPI_C_prefix, 5) == 0 || strncmp (calledname, MPI_C_prefix, 4) == 0 ||
					    strncmp (calledname, PMPI_F_prefix, 5) == 0 || strncmp (calledname, MPI_F_prefix, 4) == 0))
					{
						BPatch_function *patch_mpi = getMPIPatch (calledname);
						if (patch_mpi != NULL)
						{
							if (appProcess->replaceFunctionCall (*((*vpoints)[j]), *patch_mpi))
							{
								MPIinsertion++;
								if (VerboseLevel)
									cout << PACKAGE_NAME << ": Replaced call " << calledname << " in routine " << name << " (" << sharedlibname << ")" << endl;
							}
							else
								cerr << PACKAGE_NAME << ": Cannot replace " << calledname << " routine" << endl;
						}
					}

					/* Special instrumentation for calls in Intel OpenMP runtime v11/v12
					   currently only for __kmpc_fork_call */
					if (!BinaryLinkedWithInstrumentation &&
					    appType->get_OpenMP_rte() == ApplicationType::Intel_v11 &&
					    strncmp (calledname, "__kmpc_fork_call", strlen("__kmpc_fork_call")) == 0)
					{
						BPatch_function *patch_openmp = getRoutine (
							"__kmpc_fork_call_extrae_dyninst", appImage, false);
						if (patch_openmp != NULL)
						{
							if (appProcess->replaceFunctionCall (*((*vpoints)[j]), *patch_openmp))
							{
								OMPreplacement_intel_v11++;
								if (VerboseLevel)
									cout << PACKAGE_NAME << ": Replaced call " << calledname << " in routine " << name << " (" << sharedlibname << ")" << endl;
							}
							else
								cerr << PACKAGE_NAME << ": Cannot replace " << calledname << " routine" << endl;
						}

						/* Instrument the routine that invokes the runtime */
						if (!XML_excludeAutomaticFunctions())
							USERset.insert (name);
						if (VerboseLevel)
						{
							if (!XML_excludeAutomaticFunctions())
								cout << PACKAGE_NAME << ": Adding call to OpenMP routine " << name << " to the user function list" << endl;
							else
								cout << PACKAGE_NAME << ": Will not add call to OpenMP routine " << name << " due to user request in the XML configuration file" << endl;
						}
					}

					/* Special instrumentation for fork() / wait() / exec* calls */
					if (!BinaryLinkedWithInstrumentation &&
					   (
					    strncmp (calledname, "fork", strlen("fork")) == 0 ||
					    strncmp (calledname, "wait", strlen("wait")) == 0 ||
					    strncmp (calledname, "waitpid", strlen("waitpid")) == 0 ||
					    strncmp (calledname, "system", strlen("system")) == 0 ||
					    strncmp (calledname, "execl", strlen("execl")) == 0 ||
					    strncmp (calledname, "execle", strlen("execle")) == 0 ||
					    strncmp (calledname, "execlp", strlen("execlp")) == 0 ||
					    strncmp (calledname, "execv", strlen("execv")) == 0 ||
					    strncmp (calledname, "execve", strlen("execve")) == 0 ||
					    strncmp (calledname, "execvp", strlen("execvp")) == 0
						)
					   )
					{
						/* Instrument the routine that invokes the runtime */
						if (!XML_excludeAutomaticFunctions())
							USERset.insert (name);
						if (VerboseLevel)
						{
							if (!XML_excludeAutomaticFunctions())
								cout << PACKAGE_NAME << ": Adding routine " << name << " to the user function list because it calls to " << calledname << endl;
							else
								cout << PACKAGE_NAME << ": Will not add routine to the user function list " << name << " due to user request in the XML configuration file" << endl;
						}
					}

					/* Instrument routines that call CUDA */
					if (appType->get_isCUDA())
					{
						string scalledname (calledname);

						if (find (CUDAkernels.begin(), CUDAkernels.end(), scalledname) != CUDAkernels.end())
						{
							if (!XML_excludeAutomaticFunctions())
								USERset.insert (name);

							if (VerboseLevel)
							{
								if (!XML_excludeAutomaticFunctions())
									cout << PACKAGE_NAME << ": Adding routine " << name << " to the user function list because it calls the CUDA kernel '" << calledname<< "'" << endl;	
								else
									cout << PACKAGE_NAME << ": Will not instrument CUDA routine " << name << " due to user request in the XML configuration file" << endl;
							}
						}
					}

				}
				j++;
			}
		}

		i++;

		if (!VerboseLevel)
		{
			if (i == 1)
				cout << "1" << flush;
			else if (i%1000 == 0)
				cout << i << flush;
			else if (i%100 == 0)
				cout << "." << flush;
		}
	}

	if (!VerboseLevel)
		cout << ".Done" << endl;

	if (USERset.size() > 0 && instrumentUF)
	{
		/* Instrument user functions! */

		cout << PACKAGE_NAME << ": Instrumenting user functions...";
		if (VerboseLevel)
			cout << endl;
		else
			cout << flush;

		set<string>::iterator iter = USERset.begin();
		while (iter != USERset.end())
		{
			if (*iter != "main")
			{
				BPatch_function *f = getRoutine ((*iter).c_str(), appImage);

				if (f != NULL)
				{
					wrapTypeRoutine (f, *iter, USRFUNC_EV, appImage);

                    vector<string> points = LoopLevels[*iter]; // LoopLevels['foo'] = [bb_1,loop_1.2.3,bb_5]
                    instrumentLoops(f, *iter, appImage, points);
                    instrumentBasicBlocks(f, appImage, points);

					UFinsertion++;

					if (VerboseLevel)
						cout << PACKAGE_NAME << ": Instrumenting user function : " << *iter << endl;
				}
				else
				{
					if (VerboseLevel)
						cout << PACKAGE_NAME << ": Unable to instrument user function : " << *iter << endl;
				}
			}
			else
			{
				if (VerboseLevel)
					cout << PACKAGE_NAME << ": Although 'main' symbol was in the instrumented functions list, it will not be instrumented" << endl;
			}
			iter++;
		}
		if (VerboseLevel)
			cout << PACKAGE_NAME << ": End of instrumenting functions" << endl;
		else
			cout << "Done" << endl;
	}

	cout << PACKAGE_NAME << ": " << APIinsertion << " API patches applied" << endl;
	if (appType->get_isMPI())
		cout << PACKAGE_NAME << ": " << MPIinsertion << " MPI patches applied" << endl;
	if (appType->get_isOpenMP())
	{
		cout << PACKAGE_NAME << ": " << OMPinsertion << " OpenMP patches applied to outlined routines" << endl;
		if (appType->get_OpenMP_rte() == ApplicationType::Intel_v11)
			cout << PACKAGE_NAME << ": " << OMPreplacement_intel_v11 << " OpenMP patches applied to specific locations for Intel runtime" << endl;
	}
	if (USERset.size() > 0)
		cout << PACKAGE_NAME << ": " << UFinsertion << " user function" << ((UFinsertion!=1)?"s":"") << " instrumented" << endl;
}
Example #22
0
void readTracePipe()
{
   int read_len;
   char buf[ STRING_MAX ] = { '\0' };

   if (config.pipefd < 0) return;

   do {
      errno = 0;
      sendMsg(config.outfd, ID_TRACE_READ, DEBUG);
      read_len = read(config.pipefd, buf, trace_msglen);
      buf[trace_msglen] = '\0';

      if (read_len < trace_msglen) {
         if (read_len == -1 && errno == EAGAIN) {
            // No data on pipe.  Break out of read loop
            // and re-poll for status change.
            sendMsg(config.outfd, ID_TRACE_READ, DEBUG, ID_PASS);
            break;

         } else if (read_len == 0 && errno == 0) {
            // Read EOF from pipefd.  Close pipe and break.
            sendMsg(config.outfd, ID_TRACE_READ, DEBUG, ID_PASS);
            close(config.pipefd);
            config.pipefd = -1;
            break;

         } else if (read_len > 0) {
            // Partial data written to trace pipe.  Report to monitor.
            sendMsg(config.outfd, ID_TRACE_READ, DEBUG, ID_FAIL,
                    sprintf_static("Read partial message from trace pipe.  Discarding message '%s'.", buf));
            break;

         } else if (errno) {
            // Send error message to monitor.
            sendMsg(config.outfd, ID_TRACE_READ, DEBUG, ID_FAIL,
                    sprintf_static("Mutator encountered error on trace pipe read(): %s", strerror(errno)));
            close(config.pipefd);
            config.pipefd = -1;
            break;
         }
      }

      void *traceMsg = (void *)strtol(buf, NULL, 16);
      map< void *, BPatch_function * >::iterator iter = trace_points.find(traceMsg);
      if (iter == trace_points.end()) {
         sendMsg(config.outfd, ID_TRACE_READ, DEBUG, ID_FAIL,
                 sprintf_static("Read invalid message from trace pipe.  0x%s does not refer to a valid BPatch_point.", buf));
         break;
      }
      sendMsg(config.outfd, ID_TRACE_READ, DEBUG, ID_PASS);

      BPatch_point *point = (BPatch_point *)traceMsg;

      const char *pType = "Unknown ";
      if (point->getPointType() == BPatch_entry) pType = "Entering ";
      if (point->getPointType() == BPatch_exit)  pType = "Exiting ";

      const char *pName = "anonymous function";
      BPatch_function *pFunc = (*iter).second;
      if (pFunc) {
         if (pFunc->getName(buf, sizeof(buf)))
            pName = sprintf_static("function %s", buf);
         else
            pName = sprintf_static("anonymous function at 0x%0*lx", sizeof(void *), pFunc->getBaseAddr());
      }

      if (config.pipefd > 0) {
         // Could have been interrupted by mutatee exit.
	sendMsg(config.outfd, ID_TRACE_POINT, INFO, ID_INFO, strcat_static(pType, pName));
      }
   } while (errno == 0);
}
Example #23
0
test_results_t test1_23_Mutator::executeTest() 
{
	const char *funcName = "test1_23_call1";
	BPatch_Vector<BPatch_function *> found_funcs;

	if ((NULL == appImage->findFunction(funcName, found_funcs, 1)) 
			|| !found_funcs.size()) 
	{
		logerror("    Unable to find function %s\n", funcName);
		return FAILED;
	}

	if (1 < found_funcs.size()) 
	{
		logerror("%s[%d]:  WARNING  : found %d functions named %s.  Using the first.\n", 
				__FILE__, __LINE__, found_funcs.size(), funcName);
	}

	BPatch_Vector<BPatch_point *> *point23_calls = found_funcs[0]->findPoint(BPatch_subroutine);    

	if (!point23_calls || (point23_calls->size() < 1)) 
	{
		logerror("**Failed** test #23 (local variables)\n");
		logerror("  Unable to find point %s - subroutine calls\n", funcName);
		return FAILED;
	}

	/* We only want the first one... */
	BPatch_Vector<BPatch_point *> point23_1;
	point23_1.push_back((*point23_calls)[0]);

	BPatch_variableExpr *var1 = appImage->findVariable(*(point23_1[0]),
			"localVariable23_1");
	BPatch_variableExpr *var2 = appImage->findVariable(*(point23_1[0]),
			"test1_23_shadowVariable1");
	BPatch_variableExpr *var3 = appImage->findVariable("test1_23_shadowVariable2");
	BPatch_variableExpr *var4 = appImage->findVariable("test1_23_globalVariable1");

	if (!var1 || !var2 || !var3 || !var4) 
	{
		logerror("**Failed** test #23 (local variables)\n");

		if (!var1)
		{
			logerror("  can't find local variable localVariable23_1\n");
			BPatch_function *f = point23_1[0]->getCalledFunction();
			assert(f);
			BPatch_Vector<BPatch_localVar *> *lvars = f->getVars();
			assert(lvars);
			logerror("%s[%d]:  have vars\n", FILE__, __LINE__);
			for (unsigned int i = 0; i < lvars->size(); ++i)
			{
				logerror("\t%s\n", (*lvars)[i]->getName());
			}
		}
		if (!var2)
			logerror("  can't find local variable test1_23_shadowVariable1\n");
		if (!var3)
			logerror("  can't find global variable test1_23_shadowVariable2\n");
		return FAILED;
	}

	BPatch_arithExpr expr23_1(BPatch_assign, *var1, BPatch_constExpr(2300001));
	BPatch_arithExpr expr23_2(BPatch_assign, *var2, BPatch_constExpr(2300012));
	BPatch_arithExpr expr23_3(BPatch_assign, *var3, BPatch_constExpr(2300023));
	BPatch_arithExpr expr23_4(BPatch_assign, *var4, *var1);

	BPatch_Vector<BPatch_snippet *> exprs;

	exprs.push_back(&expr23_1);
	exprs.push_back(&expr23_2);
	exprs.push_back(&expr23_3);
	exprs.push_back(&expr23_4);

	BPatch_sequence allParts(exprs);


	appAddrSpace->insertSnippet(allParts, point23_1);

	return PASSED;
}
Example #24
0
/* Parse and instrument any signal handlers that have yet to be
 * analyzed (and instrumented), and that are not in system libraries
 */
void HybridAnalysis::signalHandlerCB(BPatch_point *point, long signum, 
                                     std::vector<Address> &handlers) 
{
    mal_printf("signalHandlerCB(%lx , %lx, %d handlers)\n", 
               point->getAddress(), signum, handlers.size());
    bool onlySysHandlers = true;
    std::vector<Address> handlerAddrs;
    proc()->beginInsertionSet();
    // eliminate any handlers in system libraries, and handlers that have 
    // already been parsed, add new handlers to handler function list
    std::vector<Address>::iterator it=handlers.begin();
    while (it < handlers.end())
    {
        BPatch_module *mod = proc()->findModuleByAddr(*it);
        if (!mod || mod->isSystemLib()) {
            it = handlers.erase(it);
            continue;
        } 

        BPatch_function *handlerFunc = proc()->findFunctionByEntry(*it);
        handlerFunctions[*it] = ExceptionDetails();
        if (handlerFunc) {
            it = handlers.erase(it);
            continue;
        } 

        // parse and instrument handler
        mal_printf("found handler at %x %s[%d]\n", *it,FILE__,__LINE__);
        onlySysHandlers = false;
        analyzeNewFunction(point,*it,true,false);
        handlerFunc = proc()->findFunctionByEntry(*it);
        assert(handlerFunc);
        handlerAddrs.push_back(*it);
        BPatch_point *entryPt =  (*handlerFunc->findPoint(BPatch_entry))[0];

        // instrument the handler at its entry and exit points
        proc()->beginInsertionSet();

        // instrument handler entry with callbacks that will deliver the stack 
        // addresses at which the fault addr is stored
        BPatch_paramExpr excRecAddr(0,BPatch_ploc_entry);
        BPatch_paramExpr excCtxtAddr(2,BPatch_ploc_entry);
        BPatch_stopThreadExpr sThread1
            (signalHandlerEntryCB_wrapper,excRecAddr,false,BPatch_noInterp);
        BPatch_stopThreadExpr sThread2
            (signalHandlerEntryCB2_wrapper,excCtxtAddr,false,BPatch_noInterp);
        proc()->insertSnippet(sThread2, *entryPt);
        proc()->insertSnippet(sThread1, *entryPt);

        // remove any exit-point instrumentation and add new instrumentation 
        // at exit points
        std::map<BPatch_point*,BPatchSnippetHandle*> *funcPoints = 
            (*instrumentedFuncs)[handlerFunc];
        if ( funcPoints ) {
            std::map<BPatch_point*, BPatchSnippetHandle*>::iterator pit;
            pit = funcPoints->begin();
            while (pit != funcPoints->end())
            {
                if ( BPatch_exit == (*pit).first->getPointType() ) {
                    proc()->deleteSnippet((*pit).second);
                    funcPoints->erase( (*pit).first );
                    pit = funcPoints->begin();                    
                } else {
                    pit++;
                }
            }
        }
        instrumentFunction(handlerFunc, false, true);

        it++;
    }
    proc()->finalizeInsertionSet(false);

    // trigger the signal-handler callback
    if (bpatchSignalHandlerCB) {
        bpatchSignalHandlerCB(point,signum,&handlerAddrs);
    }
}
Example #25
0
test_results_t test1_36_Mutator::executeTest() 
{
	const char *funcName = "test1_36_func1";
	BPatch_Vector<BPatch_function *> found_funcs;

	if ((NULL == appImage->findFunction(funcName, found_funcs))
			|| !found_funcs.size()) 
	{
		logerror("    Unable to find function %s\n", funcName);
		return FAILED;
	}

	if (1 < found_funcs.size()) 
	{
		logerror("%s[%d]:  WARNING  : found %d functions named %s.  Using the first.\n", 
				__FILE__, __LINE__, found_funcs.size(), funcName);
	}

	BPatch_Vector<BPatch_point *> *all_points36_1 =
		found_funcs[0]->findPoint(BPatch_subroutine);

	if (!all_points36_1 || (all_points36_1->size() < 1)) 
	{
		logerror("Unable to find point %s - subroutines.\n", funcName);
		return FAILED;
	}

	const char *funcName2 = "test1_36_call1";
	BPatch_point *point36_1 = NULL;

	for (unsigned i=0; i<(*all_points36_1).size(); i++) 
	{
		BPatch_point *cur_point = (*all_points36_1)[i];
		if (cur_point == NULL) 
			continue;

		BPatch_function *func = cur_point->getCalledFunction();
		char funcname[100];

		if (!func) 
			continue;

		if (func->getName(funcname, 99)) 
		{
			if (strstr(funcname, funcName2))
				point36_1 = cur_point;
		}
	}

	if (point36_1 == NULL) 
	{
		logerror("Unable to find callsite %s\n", funcName2);
		return FAILED;
	}

	BPatch_variableExpr *expr36_1 = findVariable(appImage,
			"test1_36_globalVariable1", 
			all_points36_1);
	BPatch_variableExpr *expr36_2 = findVariable(appImage,
			"test1_36_globalVariable2", 
			all_points36_1);
	BPatch_variableExpr *expr36_3 = findVariable(appImage,
			"test1_36_globalVariable3", 
			all_points36_1);
	BPatch_variableExpr *expr36_4 = findVariable(appImage,
			"test1_36_globalVariable4", 
			all_points36_1);
	BPatch_variableExpr *expr36_5 = findVariable(appImage,
			"test1_36_globalVariable5", 
			all_points36_1);
	BPatch_variableExpr *expr36_6 = findVariable(appImage,
			"test1_36_globalVariable6", 
			all_points36_1);
	BPatch_variableExpr *expr36_7 = findVariable(appImage,
			"test1_36_globalVariable7", 
			all_points36_1);
	BPatch_variableExpr *expr36_8 = findVariable(appImage,
			"test1_36_globalVariable8", 
			all_points36_1);
	BPatch_variableExpr *expr36_9 = findVariable(appImage,
			"test1_36_globalVariable9", 
			all_points36_1);
	BPatch_variableExpr *expr36_10 = findVariable(appImage,
			"test1_36_globalVariable10", 
			all_points36_1);

	if (expr36_1 == NULL || expr36_2 == NULL || expr36_3 == NULL ||
			expr36_4 == NULL || expr36_5 == NULL || expr36_6 == NULL ||
			expr36_7 == NULL || expr36_8 == NULL || expr36_9 == NULL ||
			expr36_10 == NULL)
	{
		logerror("**Failed** test #36 (callsite parameter referencing)\n");
		logerror("    Unable to locate at least one of "
				"test1_36_globalVariable{1...10}\n");
		return FAILED;
	}

	BPatch_Vector<BPatch_snippet *> snippet_seq;
	snippet_seq.push_back(makeTest36paramExpr(expr36_1, 0));
	snippet_seq.push_back(makeTest36paramExpr(expr36_2, 1));
	snippet_seq.push_back(makeTest36paramExpr(expr36_3, 2));
	snippet_seq.push_back(makeTest36paramExpr(expr36_4, 3));
	snippet_seq.push_back(makeTest36paramExpr(expr36_5, 4));
	snippet_seq.push_back(makeTest36paramExpr(expr36_6, 5));
	snippet_seq.push_back(makeTest36paramExpr(expr36_7, 6));
	snippet_seq.push_back(makeTest36paramExpr(expr36_8, 7));
	snippet_seq.push_back(makeTest36paramExpr(expr36_9, 8));
	snippet_seq.push_back(makeTest36paramExpr(expr36_10, 9));
	
    BPatch_sequence seqExpr(snippet_seq);

	checkCost(seqExpr);
	appAddrSpace->insertSnippet(seqExpr, *point36_1);

	return PASSED;
}
Example #26
0
test_results_t test1_40_Mutator::executeTest() 
{
	const char *monitorFuncName = "test1_40_monitorFunc";
	const char *callSiteAddrVarName = "test1_40_callsite5_addr";

	BPatch_function *monitorFunc = NULL;
	BPatch_Vector<BPatch_function *> bpfv;

	BPatch_function *call40_1 = findFunction40("test1_40_call1", appImage);
	RETURNONNULL(call40_1);
	RETURNONFAIL(setVar40("test1_40_addr_of_call1", call40_1->getBaseAddr(),appImage));

	BPatch_function *call40_2 = findFunction40("test1_40_call2", appImage);
	RETURNONNULL(call40_2);
	RETURNONFAIL(setVar40("test1_40_addr_of_call2", call40_2->getBaseAddr(),appImage));

	BPatch_function *call40_3 = findFunction40("test1_40_call3", appImage);
	RETURNONNULL(call40_3);
	RETURNONFAIL(setVar40("test1_40_addr_of_call3", call40_3->getBaseAddr(),appImage));

	//  call40_5 is the "dispatcher" of function pointers
	BPatch_function *targetFunc = findFunction40("test1_40_call5", appImage);
	RETURNONNULL(targetFunc);
	//RETURNONFAIL(setVar40("test1_40_addr_of_call5", call40_5->getBaseAddr(),appImage));

	monitorFunc = findFunction40(monitorFuncName, appImage);
	RETURNONNULL(monitorFunc);

	BPatch_Vector<BPatch_point *> *calls = targetFunc->findPoint(BPatch_subroutine);
	if (!calls) 
	{
		logerror("**Failed test #40 (monitor call sites)\n");
		logerror("  cannot find call points for test1_40_call5\n");
		return FAILED;
	}

	BPatch_Vector<BPatch_point *> dyncalls;
	for (unsigned int i = 0; i < calls->size(); ++i) 
	{
		BPatch_point *pt = (*calls)[i];
		if (pt->isDynamic())
			dyncalls.push_back(pt);
	}

	if (dyncalls.size() != 1) 
	{
		logerror("**Failed test #40 (monitor call sites)\n");
		logerror("  wrong number of dynamic points found (%d -- not 1)\n",
				dyncalls.size());
		logerror("  total number of calls found: %d\n", calls->size());
		return FAILED;
	}

	// write address of anticipated call site into mutatee var.
	void *callsite_address = dyncalls[0]->getAddress();
	RETURNONFAIL(setVar40(callSiteAddrVarName, callsite_address, appImage));

	//  issue command to monitor calls at this site, and we're done.
	if (! dyncalls[0]->monitorCalls(monitorFunc)) 
	{
		logerror("**Failed test #40 (monitor call sites)\n");
		logerror("  cannot monitor calls\n");
		return FAILED;
	}

	return PASSED;
}
Example #27
0
//
// Start Test Case #3 - (overload operator)
//      
// static int mutatorTest(BPatch_thread *appThread, BPatch_image *appImage)
test_results_t test5_3_Mutator::executeTest() {

  BPatch_Vector<BPatch_function *> bpfv;
  const char *fn = "overload_op_test::func_cpp";
  if (NULL == appImage->findFunction(fn, bpfv) || !bpfv.size()
      || NULL == bpfv[0]){
    logerror("**Failed** test #3 (overloaded operation)\n");
    logerror("    Unable to find function %s\n", fn);
    return FAILED;
  }
  BPatch_function *f1 = bpfv[0];  
  BPatch_Vector<BPatch_point *> *point3_1 = f1->findPoint(BPatch_subroutine);

  assert(point3_1);
  if (point3_1->size() == 0) {
    logerror("**Failed test5_3 (overload operation)\n");
    logerror("    Can't find overloaded operator call points\n");
    return FAILED;
  }

  unsigned int index = 0;
  char fn3[256];
  BPatch_function *func;
  while (index < point3_1->size()) {
     if ((func = (*point3_1)[index]->getCalledFunction()) != NULL &&
         !strcmp("overload_op_test::operator++", func->getName(fn3, 256)))
     {
        break;
     }
     index ++;
  }
  if(!func) {
    logerror("**Failed** test #3 (overload operation)\n");
    logerror("    Can't find the overload operator\n");
    return FAILED;
  }

  if (0 != strcmp("overload_op_test::operator++", func->getName(fn3, 256))) {
    logerror("**Failed** test #3 (overload operation)\n");
    logerror("    Can't find the overloaded operator\n");
    return FAILED;
  }
  // FIXME It caught fprintf...

  BPatch_Vector<BPatch_point *> *point3_2 = func->findPoint(BPatch_exit);
  assert(point3_2);
  
  bpfv.clear();
  const char *fn2 = "overload_op_test::call_cpp";
  if (NULL == appImage->findFunction(fn2, bpfv) || !bpfv.size()
      || NULL == bpfv[0]){
    logerror("**Failed** test #3 (overloaded operation)\n");
    logerror("    Unable to find function %s\n", fn2);
    return FAILED;
  }
  BPatch_function *call3_1 = bpfv[0];  
  
  BPatch_variableExpr *this2 = appImage->findVariable("test5_3_test3");
  if (this2 == NULL) {
    logerror( "**Failed** test #3 (overloaded operation)\n");
    logerror( "Unable to find variable \"test5_3_test3\"\n");
    return FAILED;
  }

  BPatch_Vector<BPatch_snippet *> opArgs;
  BPatch_arithExpr expr2_0(BPatch_addr, *this2);
  opArgs.push_back(&expr2_0);
  opArgs.push_back(new BPatch_retExpr());
  BPatch_funcCallExpr call3_1Expr(*call3_1, opArgs);
  
  checkCost(call3_1Expr);
  appAddrSpace->insertSnippet(call3_1Expr, *point3_2);
  //  int tag = 1;
  //  while (tag != 0) {}
  
  return PASSED;
}
Example #28
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;
}