Exemple #1
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;
}
Exemple #2
0
void prepareTestCase9(procType proc_type, BPatch_thread *thread, forkWhen when)
{
   const int TN = 9;

   if(proc_type == Parent_p  &&  when == PreFork) {
      BPatch_image *parImage = thread->getImage();
      var7_9p = thread->malloc(*(parImage->findType("int")));
      if(doError(TN, (var7_9p==NULL),
		 "  Unable to malloc variable in parent\n")) return;

      BPatch_arithExpr a_expr7_9p(BPatch_assign, *var7_9p,
				  BPatch_constExpr(10));
      thread->oneTimeCode(a_expr7_9p);
   } else if(proc_type == Parent_p  &&  when == PostFork) {
      // can't delete var7_9p here, since then the getInheritedVariable
      // would be operating on a freed variable
   } else if(proc_type == Child_p  &&  when == PostFork) {
      var7_9c = thread->getInheritedVariable(*var7_9p);
      parentThread->free(*var7_9p);

      BPatch_image *childImage = thread->getImage();

      BPatch_Vector<BPatch_function *> found_funcs;
      const char *inFunction = "func7_9";
      if ((NULL == childImage->findFunction(inFunction, found_funcs, 1)) || !found_funcs.size()) {
	fprintf(stderr, "    Unable to find function %s\n",
		inFunction);
	exit(1);
      }
      
      if (1 < found_funcs.size()) {
	fprintf(stderr, "%s[%d]:  WARNING  : found %d functions named %s.  Using the first.\n", 
		__FILE__, __LINE__, found_funcs.size(), inFunction);
      }
      
      BPatch_Vector<BPatch_point *> *points7_9c = found_funcs[0]->findPoint(BPatch_entry);

      if(doError(TN, !points7_9c || ((*points7_9c).size() == 0),
		 "  Unable to find entry point to \"func7_9\".\n")) return;
      BPatch_point *point7_9c = (*points7_9c)[0];

      BPatch_arithExpr a_expr7_9c(BPatch_plus, *var7_9c, BPatch_constExpr(5));
      BPatch_arithExpr b_expr7_9c(BPatch_assign, *var7_9c, a_expr7_9c);

      thread->insertSnippet(b_expr7_9c, *point7_9c, BPatch_callBefore);
   }
}
Exemple #3
0
void prepareTestCase1(procType proc_type, BPatch_thread *thread, forkWhen when)
{
   static BPatchSnippetHandle *parSnippetHandle1;
   
   if(proc_type == Parent_p  &&  when == PreFork) {
       BPatch_image *parImage = thread->getImage();
       
       BPatch_Vector<BPatch_function *> found_funcs;
       const char *inFunction = "func7_1";
       if ((NULL == parImage->findFunction(inFunction, found_funcs, 1)) || !found_funcs.size()) {
           fprintf(stderr, "    Unable to find function %s\n",
                   inFunction);
           exit(1);
       }
       
       if (1 < found_funcs.size()) {
           fprintf(stderr, "%s[%d]:  WARNING  : found %d functions named %s.  Using the first.\n", 
                   __FILE__, __LINE__, found_funcs.size(), inFunction);
       }
       
       BPatch_Vector<BPatch_point *> *point7_1p = found_funcs[0]->findPoint(BPatch_entry);
       
       if(doError(1, !point7_1p || ((*point7_1p).size() == 0),
                  "  Unable to find entry point to \"func7_1\".\n")) return;
       
       BPatch_variableExpr *var7_1p = 
       parImage->findVariable("globalVariable7_1");
       if(doError(1, (var7_1p==NULL),
                  "  Unable to locate variable globalVariable7_1\n")) return;
       
       BPatch_arithExpr expr7_1p(BPatch_assign, *var7_1p,BPatch_constExpr(321));
       
       parSnippetHandle1 =
       thread->insertSnippet(expr7_1p, *point7_1p, BPatch_callBefore);
       if(doError(1, (parSnippetHandle1 == NULL),
                  "  Unable to insert snippet into parent for test 1\n")) return;
   } else if(proc_type == Parent_p  &&  when == PostFork) {
       thread->deleteSnippet(parSnippetHandle1);
   }
}
Exemple #4
0
void prepareTestCase4(procType proc_type, BPatch_thread *thread, forkWhen when)
{
   const int TN = 4;
   static BPatchSnippetHandle *parSnippetHandle4;

   if(proc_type == Child_p  &&  when == PostFork) {
      BPatch_image *childImage = thread->getImage();

      BPatch_Vector<BPatch_function *> found_funcs;
      const char *inFunction = "func7_4";
      if ((NULL == childImage->findFunction(inFunction, found_funcs, 1)) || !found_funcs.size()) {
	fprintf(stderr, "    Unable to find function %s\n",
		inFunction);
	exit(1);
      }
      
      if (1 < found_funcs.size()) {
	fprintf(stderr, "%s[%d]:  WARNING  : found %d functions named %s.  Using the first.\n", 
		__FILE__, __LINE__, found_funcs.size(), inFunction);
      }
      
      BPatch_Vector<BPatch_point *> *points7_4c = found_funcs[0]->findPoint(BPatch_entry);
      if(doError(TN, !points7_4c || ((*points7_4c).size() == 0),
		 "  Unable to find entry point to \"func7_4\".\n")) return;
      BPatch_point *point7_4c = (*points7_4c)[0];

      BPatch_variableExpr *var7_4c = 
	 childImage->findVariable("globalVariable7_4");
      if(doError(TN, (var7_4c==NULL),
		 "  Unable to locate variable globalVariable7_4\n")) return;

      BPatch_arithExpr a_expr7_4c(BPatch_plus, *var7_4c,BPatch_constExpr(211));
      BPatch_arithExpr b_expr7_4c(BPatch_assign, *var7_4c, a_expr7_4c);
      parSnippetHandle4 =
	thread->insertSnippet(b_expr7_4c, *point7_4c, BPatch_callBefore);
   }
}
Exemple #5
0
// Instrument a function: eztrace_code0(code_entry) is called at the
// beginning of the function and eztrace_code0(code_entry) is called
// at the end of the function.
// If code_entry or code_exit is null, the corresponding call to
// eztrace_code0 is skipped
static int __intercept_function(BPatch_addressSpace *app,
			const char* function_name,
			uint32_t code_entry,
			uint32_t code_exit)
{
  BPatch_image *appImage;
  BPatch_Vector<BPatch_point*> *points;
  BPatch_Vector<BPatch_function *> functions;

  BPatch_Vector<BPatch_function *> record_event0_ptr;

  appImage = app->getImage();

  // search for record_event0 function
  BPatch_Vector<BPatch_module*> *loaded_modules = appImage->getModules();
  printf("Threre are %d modules\n", loaded_modules->size());

  for(int i=0; i< loaded_modules->size(); i++) {
    BPatch_module* cur_mod = (*loaded_modules)[i];

    char mod_name[80];
    cur_mod->getName(mod_name, 80);

    cur_mod->findFunction("record_event0", record_event0_ptr, false);

    if(!record_event0_ptr.size()) {
      printf("\tfunction record_event0 not found in module %s\n", mod_name);
    } else {
      printf("Found ! in module %s\n", mod_name);
      break;
    }
  }

  if(!record_event0_ptr.size()) {
    printf("Cannot find record_event0 function\n");
    return -1;
  }

  printf("PLOP\n");

  for(int i=0; i< loaded_modules->size(); i++) {
    BPatch_module* cur_mod = (*loaded_modules)[i];

    char mod_name[80];
    cur_mod->getName(mod_name, 80);

    cur_mod->findFunction(function_name, functions, false);

    if(!functions.size()) {
      printf("\tfunction %s not found in module %s\n", function_name, mod_name);
    } else {
      printf("Found %s! \n", function_name );
      break;
    }
  }

 if(!functions.size()) {
    fprintf(stderr, "warning: cannot find function %s in executable\n", function_name);
    return 0;
  }

  // Instrument the entry of the function
  if(code_entry) {
    // We need to call eztrace_generic(code, nb_param, param1, param2, ...)
    points = functions[0]->findPoint(BPatch_entry);
    BPatch_Vector<BPatch_snippet*> dummyArgs;

    // Create the parameter (code_entry)
    BPatch_constExpr code(code_entry);
    dummyArgs.push_back(&code);

    // Create the function call
#if 0
    BPatch_Vector<BPatch_function *> funcs;
    appImage->findFunction("record_event0", funcs);
    BPatch_function *dummyFunc = funcs[0];

    BPatch_funcCallExpr dummyCall(*dummyFunc, dummyArgs);
#else
    BPatch_funcCallExpr dummyCall(*record_event0_ptr[0], dummyArgs);
#endif

    //Insert the function call at the point
    app->insertSnippet(dummyCall, *points);
  }

  // Instrument the exit of the function
  if(code_exit) {
    // the function parameters are not available here, so we have to
    // call eztrace_code0(code)

    points = functions[0]->findPoint(BPatch_exit);
    // Create the parameter (code_entry)
    BPatch_Vector<BPatch_snippet*> dummyArgs;
    BPatch_constExpr code(code_exit);
    dummyArgs.push_back(&code);

    // Create the function call
#if 0
    BPatch_Vector<BPatch_function *> funcs;
    appImage->findFunction("record_event0", funcs);
    BPatch_function *dummyFunc = funcs[0];

    BPatch_funcCallExpr dummyCall(*dummyFunc, dummyArgs);
#else
    BPatch_funcCallExpr dummyCall(*record_event0_ptr[0], dummyArgs);
#endif

    //Insert the function call at the point
    app->insertSnippet(dummyCall, *points);
  }
  return 1;
}
Exemple #6
0
void prepareTestCase3(procType proc_type, BPatch_thread *thread, forkWhen when)
{
   static BPatchSnippetHandle *parSnippetHandle3;

   if(proc_type == Parent_p  &&  when == PreFork) {
      BPatch_image *parImage = thread->getImage();

      BPatch_Vector<BPatch_function *> found_funcs;
      const char *inFunction = "func7_3";
      if ((NULL == parImage->findFunction(inFunction, found_funcs, 1)) || !found_funcs.size()) {
	fprintf(stderr, "    Unable to find function %s\n",
		inFunction);
	exit(1);
      }
      
      if (1 < found_funcs.size()) {
	fprintf(stderr, "%s[%d]:  WARNING  : found %d functions named %s.  Using the first.\n", 
		__FILE__, __LINE__, found_funcs.size(), inFunction);
      }
      
      BPatch_Vector<BPatch_point *> *points7_3p = found_funcs[0]->findPoint(BPatch_entry);

      if(doError(3, !points7_3p || ((*points7_3p).size() == 0),
		 "  Unable to find entry point to \"func7_3\".\n")) return;
      BPatch_point *point7_3p = (*points7_3p)[0];

      BPatch_variableExpr *var7_3p = 
	 parImage->findVariable("globalVariable7_3");
      if(doError(3, (var7_3p==NULL),
		 "  Unable to locate variable globalVariable7_3\n")) return;

      BPatch_arithExpr expr7_3p(BPatch_assign, *var7_3p,BPatch_constExpr(642));

      parSnippetHandle3 =
	 thread->insertSnippet(expr7_3p, *point7_3p, BPatch_callBefore);
   } else if(proc_type == Parent_p  &&  when == PostFork) {
      bool result = thread->deleteSnippet(parSnippetHandle3);
      if(result == false) {
	 fprintf(stderr, "  error, couldn't delete snippet\n");
	 passedTest[3] = false;
	 return;
      }
   } else if(proc_type == Child_p  &&  when == PostFork) {
      BPatch_image *childImage = thread->getImage();

      BPatch_Vector<BPatch_function *> found_funcs;
      const char *inFunction = "func7_3";
      if ((NULL == childImage->findFunction(inFunction, found_funcs, 1)) || !found_funcs.size()) {
	fprintf(stderr, "    Unable to find function %s\n",
		inFunction);
	exit(1);
      }
      
      if (1 < found_funcs.size()) {
	fprintf(stderr, "%s[%d]:  WARNING  : found %d functions named %s.  Using the first.\n", 
		__FILE__, __LINE__, found_funcs.size(), inFunction);
      }
      
      BPatch_Vector<BPatch_point *> *points7_3c = found_funcs[0]->findPoint(BPatch_entry);
      
      if(doError(3, !points7_3c || ((*points7_3c).size() == 0),
		 "  Unable to find entry point to \"func7_3\".\n")) return;
      BPatch_point *point7_3c = (*points7_3c)[0];

      BPatch_Vector<BPatchSnippetHandle *> childSnippets =
	 point7_3c->getCurrentSnippets();
      if(doError(3, (childSnippets.size()==0),
		 " No snippets were found at func7_3\n")) return;

      for(unsigned i=0; i<childSnippets.size(); i++) {
	 bool result = thread->deleteSnippet(childSnippets[i]);
	 if(result == false) {
	    fprintf(stderr, "  error, couldn't delete snippet\n");
	    passedTest[3] = false;
	    return;
	 }
      }
   }
}
Exemple #7
0
void execFunc(BPatch_thread *thread)
{
  BPatch_Vector<BPatch_function *> bpfv;

    if (inTest == 1 || inTest == 2) {
	printf("**Failed Test #%d\n", inTest);
	printf("    execCallback invoked, but exec was not called!\n");
    } else if (inTest == 3) {
	dprintf("in exec callback for %d\n", thread->getPid());

	// insert code into parent
	BPatch_Vector<BPatch_snippet *> nullArgs;
        BPatch_image *appImage = thread->getImage();
        assert(appImage);

	char *fn = "func3_2";
	if (NULL == appImage->findFunction(fn, bpfv) || !bpfv.size()
	    || NULL == bpfv[0]){
	  fprintf(stderr, "    Unable to find function %s\n",fn);
	  exit(1);
	}

        BPatch_function *func3_2_parent = bpfv[0];
        BPatch_funcCallExpr callExpr(*func3_2_parent, nullArgs);

	bpfv.clear();
	char *fn2 = "func3_1";
	if (NULL == appImage->findFunction(fn2, bpfv) || !bpfv.size()
	    || NULL == bpfv[0]){
	  fprintf(stderr, "    Unable to find function %s\n",fn2);
	  exit(1);
	}

	BPatch_function *func3_1_parent = bpfv[0];
	BPatch_Vector<BPatch_point *> *point = func3_1_parent->findPoint(BPatch_exit);

        assert(point);
        thread->insertSnippet(callExpr, *point);
	dprintf("%s[%d]:  MUTATEE: exec callback for %d, done with insert snippet\n", __FILE__, __LINE__, thread->getPid());
    } else if (inTest == 4) {
	dprintf("in exec callback for %d\n", thread->getPid());

        // insert code into child
	BPatch_Vector<BPatch_snippet *> nullArgs;
        BPatch_image *appImage = thread->getImage();
        assert(appImage);

	char *fn3 = "func4_4";
	if (NULL == appImage->findFunction(fn3, bpfv) || !bpfv.size()
	    || NULL == bpfv[0]){
	  fprintf(stderr, "    Unable to find function %s\n",fn3);
	  exit(1);
	}

	BPatch_function *func4_4_child = bpfv[0];
	BPatch_funcCallExpr callExpr1(*func4_4_child, nullArgs);
	
	bpfv.clear();
	char *fn4 = "func4_2";
	if (NULL == appImage->findFunction(fn4, bpfv) || !bpfv.size()
	    || NULL == bpfv[0]){
	  fprintf(stderr, "    Unable to find function %s\n",fn4);
	  exit(1);
	}

	BPatch_function *func4_2_child = bpfv[0];
	BPatch_Vector<BPatch_point *> *point1 = func4_2_child->findPoint(BPatch_exit);

	assert(point1);
        thread->insertSnippet(callExpr1, *point1);
    } else {
	printf("in exec callback for %d\n", thread->getPid());
    }
}
Exemple #8
0
void forkFunc(BPatch_thread *parent, BPatch_thread *child)
{
  dprintf("forkFunc called with parent %p, child %p\n", parent, child);
    BPatch_image *appImage;
    BPatch_Vector<BPatch_function *> bpfv;
    BPatch_Vector<BPatch_snippet *> nullArgs;

    if (child) mythreads[threadCount++] = child;

    if (!child) {
       dprintf("in prefork for %d\n", parent->getPid());
    } else {
       dprintf("in fork of %d to %d\n", parent->getPid(), child->getPid());
    }

    if (inTest == 1) {
       // nothing to do for this case
    } else if (inTest == 2) {
       if (!child) return;	// skip prefork case

       // Make a race condition always show up -- we don't run
       // until the processes have had a chance.
#if !defined(os_windows)
       sleep(1);
#endif
       // That'll make erroneous continues break...

       // insert code into parent
       appImage = parent->getImage();
       assert(appImage);

       char *fn = "func2_3";
       if (NULL == appImage->findFunction(fn, bpfv) || !bpfv.size()
	   || NULL == bpfv[0]){
	 fprintf(stderr, "    Unable to find function %s\n",fn);
	 exit(1);
       }

       BPatch_function *func2_3_parent = bpfv[0];
       BPatch_funcCallExpr callExpr2(*func2_3_parent, nullArgs);
 
       bpfv.clear();
       char *fn2 = "func2_2";
       if (NULL == appImage->findFunction(fn2, bpfv) || !bpfv.size()
	   || NULL == bpfv[0]){
	 fprintf(stderr, "    Unable to find function %s\n",fn2);
	 exit(1);
       }

       BPatch_function *func2_2_parent = bpfv[0];
       BPatch_Vector<BPatch_point *> *point2 = func2_2_parent->findPoint(BPatch_exit);
       assert(point2);
       
       parent->insertSnippet(callExpr2, *point2);

       dprintf("MUTATEE:  after insert in fork of %d to %d\n", parent->getPid(), child->getPid());
       // insert different code into child
       appImage = child->getImage();
       assert(appImage);

       bpfv.clear();
       char *fn3 = "func2_4";
       if (NULL == appImage->findFunction(fn3, bpfv) || !bpfv.size()
	   || NULL == bpfv[0]){
	 fprintf(stderr, "    Unable to find function %s\n",fn3);
	 exit(1);
       }

       BPatch_function *func2_4_child = bpfv[0];
       BPatch_funcCallExpr callExpr1(*func2_4_child, nullArgs);

       bpfv.clear();
       char *fn4 = "func2_2";
       if (NULL == appImage->findFunction(fn4, bpfv) || !bpfv.size()
	   || NULL == bpfv[0]){
	 fprintf(stderr, "    Unable to find function %s\n",fn4);
	 exit(1);
       }

       BPatch_function *func2_2_child = bpfv[0];
       BPatch_Vector<BPatch_point *> *point1 = func2_2_child->findPoint(BPatch_exit);
       assert(point1);

       child->insertSnippet(callExpr1, *point1);

       dprintf("MUTATEE:  after insert2 in fork of %d to %d\n", parent->getPid(), child->getPid());
       test2Child = child;
       test2Parent = parent;
    } else if (inTest == 4) {
       if (!child) return;	// skip prefork case

       // insert code into parent
       appImage = parent->getImage();
       assert(appImage);

       char *fn5 = "func4_3";
       if (NULL == appImage->findFunction(fn5, bpfv) || !bpfv.size()
	   || NULL == bpfv[0]){
	 fprintf(stderr, "    Unable to find function %s\n",fn5);
	 exit(1);
       }

       BPatch_function *func4_3_parent = bpfv[0];
       BPatch_funcCallExpr callExpr2(*func4_3_parent, nullArgs);

       bpfv.clear();
       char *fn6 = "func4_2";
       if (NULL == appImage->findFunction(fn6, bpfv) || !bpfv.size()
	   || NULL == bpfv[0]){
	 fprintf(stderr, "    Unable to find function %s\n",fn6);
	 exit(1);
       }

       BPatch_function *func4_2_parent = bpfv[0];
       BPatch_Vector<BPatch_point *> *point2 = func4_2_parent->findPoint(BPatch_exit);
       assert(point2);
       parent->insertSnippet(callExpr2, *point2);

       // code goes into child after in-exec in this test.

       test4Child = child;
    }
}
Exemple #9
0
int main(int argc, const char *argv[]) {

  // Use BPatch_* classes to initialize
  BPatch bpatch;
  BPatch_binaryEdit* app = bpatch.openBinary("mutatee/c");
  BPatch_image* image = app->getImage();


  BPatch_Vector<BPatch_function *> found_funcs;
  app->loadLibrary("mutatee/liblib.so");

  found_funcs.clear();
  image->findFunction("foo3", found_funcs);
  Function* foo3_func = found_funcs[0]->getParseAPIFunc();

  // Here we go, create PatchAPI objects!
  vector<AddressSpace*> addrSpaces;
  app->getAS(addrSpaces);

  mapped_object* obj = addrSpaces[0]->getAOut();
  DynAddrSpacePtr as = DynAddrSpace::create(obj);
  PatchMgrPtr mgr = PatchMgr::create(as);

  mapped_object* lib_obj = addrSpaces[1]->getAOut();
  as->loadLibrary(lib_obj);

  // Find Points
  PatchFunction* foo3 = lib_obj->getFunc(foo3_func);
  const vector<PatchBlock*>& blks = foo3->getCallBlocks();
  for (int i = 0; i < blks.size(); i++) {
    vector<Point*> func_points;
    mgr->findPoints(blks[i], Point::PreInsn|Point::PostInsn, inserter(func_points, func_points.begin()));
    cerr << std::hex << blks[i]->start() << "--" << func_points.size() << " points found\n";
  }
  /*
  vector<Point*> pts;
  mgr->findPoints(foo3, Point::FuncExit, inserter(pts, pts.begin()));
  cerr << pts.size() << " exit points found\n";
  const vector<PatchBlock*>& blks2 = foo3->getExitBlocks();
  cerr << blks2.size() << " exit blocks\n";

  // Insert snippets
  BPatch_variableExpr *intCounter = app->malloc(*image->findType("int"));
  BPatch_arithExpr addOne(BPatch_assign, *intCounter,
                          BPatch_arithExpr(BPatch_plus, *intCounter, BPatch_constExpr(1)));
  BPatch_arithExpr addTwo(BPatch_assign, *intCounter,
                          BPatch_arithExpr(BPatch_plus, *intCounter, BPatch_constExpr(2)));
  BPatch_arithExpr addThree(BPatch_assign, *intCounter,
                            BPatch_arithExpr(BPatch_plus, *intCounter, BPatch_constExpr(3)));
  BPatch_arithExpr addFour(BPatch_assign, *intCounter,
                           BPatch_arithExpr(BPatch_plus, *intCounter, BPatch_constExpr(4)));

  SnippetRep<AstNodePtr> one(addOne.ast_wrapper);
  SnippetRep<AstNodePtr> two(addTwo.ast_wrapper);
  SnippetRep<AstNodePtr> three(addThree.ast_wrapper);
  SnippetRep<AstNodePtr> four(addFour.ast_wrapper);
  SnippetPtr snippet = Snippet::create(&one);
  SnippetPtr snippet1 = Snippet::create(&two);
  SnippetPtr snippet2 = Snippet::create(&three);
  SnippetPtr snippet3 = Snippet::create(&four);

  vector<InstancePtr> errorInstances;

  mgr->batchStart();
  func_points[0]->push_back(snippet);
  mgr->batchFinish(errorInstances);
  */
}
Exemple #10
0
static void prepareTestCase5(procType proc_type, BPatch_thread *thread, forkWhen when)
{
   static BPatchSnippetHandle *parSnippetHandle5;
   logerror("prepareTestCase5, %d, %p, %d\n",
	    proc_type, thread, when);
   

   if(proc_type == Parent_p  &&  when == PreFork) {
       BPatch_image *parImage = thread->getProcess()->getImage();

      BPatch_Vector<BPatch_function *> found_funcs;
      const char *inFunction = "test_fork_9_func1";
      if ((NULL == parImage->findFunction(inFunction, found_funcs, 1)) || !found_funcs.size()) {
	logerror("    Unable to find function %s\n",
		inFunction);
	exit(1);
      }
      
      if (1 < found_funcs.size()) {
	logerror("%s[%d]:  WARNING  : found %d functions named %s.  Using the first.\n", 
		__FILE__, __LINE__, found_funcs.size(), inFunction);
      }
      
      BPatch_Vector<BPatch_point *> *points7_5p = found_funcs[0]->findPoint(BPatch_entry);

      if(doError(&passedTest, !points7_5p || ((*points7_5p).size() == 0),
		 "  Unable to find entry point to \"test_fork_9_func1\".\n")) return;
      BPatch_point *point7_5p = (*points7_5p)[0];

      BPatch_variableExpr *var7_5p = 
	 parImage->findVariable("test_fork_9_global1");
      if(doError(&passedTest, (var7_5p==NULL),
		 "  Unable to locate variable test_fork_9_global1\n")) return;

      BPatch_arithExpr expr7_5p(BPatch_plus, *var7_5p, BPatch_constExpr(9));
      BPatch_arithExpr b_expr7_5p(BPatch_assign, *var7_5p, expr7_5p);
      parSnippetHandle5 =
              thread->getProcess()->insertSnippet(b_expr7_5p, *point7_5p, BPatch_callBefore);
   } else if(proc_type == Parent_p  &&  when == PostFork) {
       BPatch_image *parImage = thread->getProcess()->getImage();

      BPatch_Vector<BPatch_function *> found_funcs;
      const char *inFunction = "test_fork_9_func1";
      if ((NULL == parImage->findFunction(inFunction, found_funcs, 1)) || !found_funcs.size()) {
	logerror("    Unable to find function %s\n",
		inFunction);
	exit(1);
      }
      
      if (1 < found_funcs.size()) {
	logerror("%s[%d]:  WARNING  : found %d functions named %s.  Using the first.\n", 
		__FILE__, __LINE__, found_funcs.size(), inFunction);
      }
      
      BPatch_Vector<BPatch_point *> *points7_5p = found_funcs[0]->findPoint(BPatch_entry);

      if(doError(&passedTest, !points7_5p || ((*points7_5p).size() == 0),
		 "  Unable to find entry point to \"test_fork_9_func1\".\n")) return;
      BPatch_point *point7_5p = (*points7_5p)[0];

      BPatch_variableExpr *var7_5p = 
	 parImage->findVariable("test_fork_9_global1");
      if(doError(&passedTest, (var7_5p==NULL),
		 "  Unable to locate variable test_fork_9_global1\n")) return;

      BPatch_arithExpr a_expr7_5p(BPatch_plus, *var7_5p, BPatch_constExpr(11));
      BPatch_arithExpr b_expr7_5p(BPatch_assign, *var7_5p, a_expr7_5p);
      parSnippetHandle5 =
              thread->getProcess()->insertSnippet(b_expr7_5p, *point7_5p, BPatch_callBefore,
			       BPatch_lastSnippet);

      BPatch_arithExpr c_expr7_5p(BPatch_plus, *var7_5p, BPatch_constExpr(13));
      BPatch_arithExpr d_expr7_5p(BPatch_assign, *var7_5p, c_expr7_5p);
      parSnippetHandle5 =
              thread->getProcess()->insertSnippet(d_expr7_5p, *point7_5p, BPatch_callBefore);
   } else if(proc_type == Child_p  &&  when == PostFork) {
       BPatch_image *childImage = thread->getProcess()->getImage();

      BPatch_Vector<BPatch_function *> found_funcs;
      const char *inFunction = "test_fork_9_func1";
      if ((NULL == childImage->findFunction(inFunction, found_funcs, 1)) || !found_funcs.size()) {
	logerror("    Unable to find function %s\n",
		inFunction);
	exit(1);
      }
      
      if (1 < found_funcs.size()) {
	logerror("%s[%d]:  WARNING  : found %d functions named %s.  Using the first.\n", 
		__FILE__, __LINE__, found_funcs.size(), inFunction);
      }
      
      BPatch_Vector<BPatch_point *> *points7_5c = found_funcs[0]->findPoint(BPatch_entry);

      if(doError(&passedTest, !points7_5c || ((*points7_5c).size() == 0),
		 "  Unable to find entry point to \"test_fork_9_func1\".\n")) return;
      BPatch_point *point7_5c = (*points7_5c)[0];

      BPatch_variableExpr *var7_5c = 
	 childImage->findVariable("test_fork_9_global1");
      if(doError(&passedTest, (var7_5c==NULL),
		 "  Unable to locate variable test_fork_9_global1\n")) return;

      BPatch_arithExpr a_expr7_5c(BPatch_plus, *var7_5c, BPatch_constExpr(5));
      BPatch_arithExpr b_expr7_5c(BPatch_assign, *var7_5c, a_expr7_5c);
      parSnippetHandle5 =
              thread->getProcess()->insertSnippet(b_expr7_5c, *point7_5c, BPatch_callBefore,
			      BPatch_lastSnippet);
      BPatch_arithExpr c_expr7_5c(BPatch_plus, *var7_5c, BPatch_constExpr(3));
      BPatch_arithExpr d_expr7_5c(BPatch_assign, *var7_5c, c_expr7_5c);
      parSnippetHandle5 =
              thread->getProcess()->insertSnippet(d_expr7_5c, *point7_5c, BPatch_callBefore);
   }
}
Exemple #11
0
int main(int argc, char *argv[], char* envp[])
{
    if (argc < 2) {
        fprintf(stderr, "Usage: %s prog_filename prog_aruments\n", argv[0]);
        return 3;
    }
#if 0
    if (strcmp(argv[1], "prog") != 0 && strcmp(argv[1], "all"))
    {
        fprintf(stderr, "Options for patch selection are 'progonly' or 'all'\n");
        return 3;
    }
#endif
    int patchall = 0; //strcmp(argv[1], "all") != 0;

    // Create process
    BPatch_process *appProc = bpatch.processCreate(argv[1], (const char**) &(argv[1]));

    // Load pthread into the process...
    appProc->loadLibrary("libpthread.so.0");
    
    // Get the process image    
    BPatch_image *appImage = appProc->getImage();

    // Find all the instrumentable procedures
    BPatch_Vector<BPatch_function*> *functions = appImage->getProcedures();


    /*************************************************************************
     * General function search                                               *
     *************************************************************************/

    // Find the printf function
    BPatch_Vector<BPatch_function*> printfFuncs;
    appImage->findFunction("printf", printfFuncs);
    if (printfFuncs.size() == 0)
        appImage->findFunction("_printf", printfFuncs);
    if (printfFuncs.size() == 0)
        appImage->findFunction("__printf", printfFuncs);

    if(printfFuncs.size() == 0)
    {
        fprintf(stderr, "Could not find printf() function");
        return 2;
    }

    // Find the exit function
    BPatch_Vector<BPatch_function*> exitFuncs;
        appImage->findFunction("exit", exitFuncs);
    if (exitFuncs.size() == 0)
        appImage->findFunction("_exit", exitFuncs);
    if (exitFuncs.size() == 0)
        appImage->findFunction("__exit", exitFuncs);

    if(exitFuncs.size() == 0)
    {
        fprintf(stderr, "Could not find exit() function");
        return 2;
    }

    // Find the perror function
    BPatch_Vector<BPatch_function*> perrorFuncs;
    appImage->findFunction("perror", perrorFuncs);
    if (perrorFuncs.size() == 0)
        appImage->findFunction("_perror", perrorFuncs);
    if (perrorFuncs.size() == 0)
        appImage->findFunction("__perror", perrorFuncs);

    if(perrorFuncs.size() == 0)
    {
        fprintf(stderr, "Could not find perror() function");
        return 2;
    }

    BPatch_Vector<BPatch_snippet*> mainEntryBlock;

    /************************************************************************
     * Error exit call                                                      *
     ************************************************************************/

    BPatch_Vector<BPatch_snippet*> exitArgs;
    BPatch_constExpr exitCode(-2);
    exitArgs.push_back(&exitCode);

    // Open call
    BPatch_funcCallExpr exitOnErrorCall(*exitFuncs[0], exitArgs);

 
    /************************************************************************
     * Open imitate device patch                                            *
     * **********************************************************************/

    // Find main()
    BPatch_Vector<BPatch_function*> mainFunctions;
        appImage->findFunction("main", mainFunctions);
    if (mainFunctions.size() == 0)
        appImage->findFunction("_main", mainFunctions);
    if (mainFunctions.size() == 0)
        appImage->findFunction("__main", mainFunctions);

    if(mainFunctions.size() == 0)
    {
        fprintf(stderr, "Could not find main() function");
        return 2;
    }

    // find open()
    BPatch_Vector<BPatch_function*> openFunctions;
        appImage->findFunction("open64", openFunctions);
    if (openFunctions.size() == 0)
        appImage->findFunction("open", openFunctions);
    if (openFunctions.size() == 0)
        appImage->findFunction("_open", openFunctions);
    if (openFunctions.size() == 0)
        appImage->findFunction("__open", openFunctions);

    if(openFunctions.size() == 0)
    {
        fprintf(stderr, "Could not find open() function");
        return 2;
    }

    // Get main() entry point
    BPatch_Vector<BPatch_point*> *mainPoints = mainFunctions[0]->findPoint(BPatch_entry);

    // Open call arguments
    BPatch_Vector<BPatch_snippet*> openArgs;
    BPatch_constExpr fileName("/dev/imitate0");
    BPatch_constExpr fileFlags(O_RDWR);
    openArgs.push_back(&fileName);
    openArgs.push_back(&fileFlags);

    // Open call
    BPatch_funcCallExpr openDevCall(*openFunctions[0], openArgs);

    // Allocate file descriptor
    BPatch_variableExpr *devFd = appProc->malloc(*appImage->findType("int"));

    // Assign fd with result of open call
    BPatch_arithExpr openDevice(BPatch_assign, *devFd, openDevCall);

    // defFd check
    BPatch_boolExpr devFdCheck(BPatch_lt, *devFd, BPatch_constExpr(0));
    
    // perror message
    BPatch_Vector<BPatch_snippet*> devFdErrorArgs;
    BPatch_constExpr devFdErrorMsg("Opening imitate kernel device");
    devFdErrorArgs.push_back(&devFdErrorMsg);
    BPatch_funcCallExpr devFdError(*perrorFuncs[0], devFdErrorArgs);

    BPatch_Vector<BPatch_snippet*> openErrorBlock;
    openErrorBlock.push_back(&devFdError);
    openErrorBlock.push_back(&exitOnErrorCall);

    // if (devFd < 0) { perror(...) }
    BPatch_ifExpr devFdBlock(devFdCheck, BPatch_sequence(openErrorBlock));

    mainEntryBlock.push_back(&openDevice);
    mainEntryBlock.push_back(&devFdBlock);
    

    /*************************************************************************
     * Send ioctl IMITATE_APP_RECORD to module                               *
     *************************************************************************/

    // find ioctl()
    BPatch_Vector<BPatch_function*> ioctlFunctions;
        appImage->findFunction("ioctl", ioctlFunctions);
    if (ioctlFunctions.size() == 0)
        appImage->findFunction("_ioctl", ioctlFunctions);
    if (ioctlFunctions.size() == 0)
        appImage->findFunction("__ioctl", ioctlFunctions);

    if(ioctlFunctions.size() == 0)
    {
        fprintf(stderr, "Could not find ioctl() function");
        return 2;
    }

    // ioctl() arguments
    BPatch_Vector<BPatch_snippet*> ioctlArgs;
    BPatch_constExpr operation(IMITATE_APP_RECORD);
    fprintf(stderr, "PPID: %d\n", getppid());
    BPatch_constExpr monitorPid(getppid());
    ioctlArgs.push_back(devFd);
    ioctlArgs.push_back(&operation);
    ioctlArgs.push_back(&monitorPid);

    // ioctl() call
    BPatch_funcCallExpr ioctlCall(*ioctlFunctions[0], ioctlArgs);

    // ioctl() result check
    BPatch_boolExpr ioctlCheck(BPatch_lt, ioctlCall, BPatch_constExpr(0));
    
    // perror message
    BPatch_Vector<BPatch_snippet*> ioctlErrorArgs;
    BPatch_constExpr ioctlErrorMsg("Notifying imitate kernel driver of RECORD");
    ioctlErrorArgs.push_back(&ioctlErrorMsg);
    BPatch_funcCallExpr ioctlError(*perrorFuncs[0], ioctlErrorArgs);

    BPatch_Vector<BPatch_snippet*> ioctlErrorBlock;
    ioctlErrorBlock.push_back(&ioctlError);
    ioctlErrorBlock.push_back(&exitOnErrorCall);

    // if (ioctl(...) < 0) { perror(...) }
    BPatch_ifExpr ioctlBlock(ioctlCheck, BPatch_sequence(ioctlErrorBlock));

    // Add ioctl check to entry block
    mainEntryBlock.push_back(&ioctlBlock);

    /*************************************************************************
     * Counter mmap()                                                        *
     *************************************************************************/

    // Find the mmap function
    BPatch_Vector<BPatch_function*> mmapFuncs;
        appImage->findFunction("mmap", mmapFuncs);
    if (mmapFuncs.size() == 0)
        appImage->findFunction("_mmap", mmapFuncs);
    if (mmapFuncs.size() == 0)
        appImage->findFunction("__mmap", mmapFuncs);

    if(mmapFuncs.size() == 0)
    {
        fprintf(stderr, "Could not find mmap() function");
        return 2;
    }

    // Allocate counter
    BPatch_variableExpr *counterAddr = appProc->malloc(sizeof(sched_counter_t*));
    sched_counter_t counterVal = 0;
    counterAddr->writeValue(&counterVal, sizeof(sched_counter_t*), false);

    // Notify kernel of address
    BPatch_Vector<BPatch_snippet*> mmapArgs;
    BPatch_constExpr mmapStart(0);
    BPatch_constExpr mmapLength(sizeof(sched_counter_t));
    BPatch_constExpr mmapProt(PROT_READ | PROT_WRITE);
    BPatch_constExpr mmapFlags(MAP_SHARED);
    BPatch_constExpr mmapOffset(0);

    mmapArgs.push_back(&mmapStart);
    mmapArgs.push_back(&mmapLength);
    mmapArgs.push_back(&mmapProt);
    mmapArgs.push_back(&mmapFlags);
    mmapArgs.push_back(devFd);
    mmapArgs.push_back(&mmapOffset);

    // mmap() call
    BPatch_funcCallExpr mmapCall(*mmapFuncs[0], mmapArgs);

    // assign result to counterAddr
    BPatch_arithExpr mmapAssign(BPatch_assign, *counterAddr, mmapCall);

    // Add to entry block
    mainEntryBlock.push_back(&mmapAssign);

    // mmap() result check
    BPatch_boolExpr mmapCheck(BPatch_eq, *counterAddr, BPatch_constExpr(MAP_FAILED));

    // perror message
    BPatch_Vector<BPatch_snippet*> mmapErrorArgs;
    BPatch_constExpr mmapErrorMsg("Memory mapping schedule (back edge) counter");
    mmapErrorArgs.push_back(&mmapErrorMsg);
    BPatch_funcCallExpr mmapError(*perrorFuncs[0], mmapErrorArgs);

    BPatch_Vector<BPatch_snippet*> mmapErrorBlock;
    mmapErrorBlock.push_back(&mmapError);
    mmapErrorBlock.push_back(&exitOnErrorCall);

    // if (mmap(...) == MAP_FAILED) { perror(...) }
    BPatch_ifExpr mmapBlock(mmapCheck, BPatch_sequence(mmapErrorBlock));

    mainEntryBlock.push_back(&mmapBlock);


    // Patch main entry
    BPatch_sequence mainEntrySeq(mainEntryBlock);
    appProc->insertSnippet(mainEntrySeq, *mainPoints);


    /*************************************************************************
     * Back-edge patching                                                    *
     *************************************************************************/

#if 0
    printf("intCounter address: %x\n PID: %d\n", intCounter->getBaseAddr(), appProc->getPid());
    fflush(stdout);
#endif

    // Find the mutex lock/unlock functions
    BPatch_Vector<BPatch_function*> mutexLockFunctions;
        appImage->findFunction("pthread_mutex_lock", mutexLockFunctions);
    if (mutexLockFunctions.size() == 0)
        appImage->findFunction("_pthread_mutex_lock", mutexLockFunctions);
    if (mutexLockFunctions.size() == 0)
        appImage->findFunction("__pthread_mutex_lock", mutexLockFunctions);

    if(mutexLockFunctions.size() == 0)
    {
        fprintf(stderr, "Could not find pthread_mutex_lock() function");
        return 2;
    }

    BPatch_Vector<BPatch_function*> mutexUnlockFunctions;
        appImage->findFunction("pthread_mutex_unlock", mutexUnlockFunctions);
    if (mutexUnlockFunctions.size() == 0)
        appImage->findFunction("_pthread_mutex_unlock", mutexUnlockFunctions);
    if (mutexUnlockFunctions.size() == 0)
        appImage->findFunction("__pthread_mutex_unlock", mutexUnlockFunctions);

    if(mutexUnlockFunctions.size() == 0)
    {
        fprintf(stderr, "Could not find pthread_mutex_unlock() function");
        return 2;
    }

    // Allocate a mutex
    pthread_mutex_t mutexValue = PTHREAD_MUTEX_INITIALIZER;
    BPatch_variableExpr *mutex = appProc->malloc(sizeof(pthread_mutex_t));
    mutex->writeValue(&mutexValue, sizeof(pthread_mutex_t), false);

    // Build mutex lock call
    BPatch_Vector<BPatch_snippet*> mutexArgs;
    BPatch_constExpr mutexAddress(mutex->getBaseAddr());

    mutexArgs.push_back(&mutexAddress);

    BPatch_funcCallExpr mutexLockCall(*mutexLockFunctions[0], mutexArgs);
    BPatch_funcCallExpr mutexUnlockCall(*mutexUnlockFunctions[0], mutexArgs);

    BPatch_arithExpr derefCounter(BPatch_deref, *counterAddr);

    // Create 'increment counter' snippet
    BPatch_arithExpr addOneToCounter(BPatch_assign, derefCounter,
        BPatch_arithExpr(BPatch_plus, derefCounter, BPatch_constExpr(1)));

    BPatch_Vector<BPatch_snippet*> snippet;
    snippet.push_back(&mutexLockCall);
    snippet.push_back(&addOneToCounter);
    snippet.push_back(&mutexUnlockCall);

    BPatch_sequence addOneAtomic(snippet);

    char *name = (char*) malloc(sizeof(char)*200);
    char *modname = (char*) malloc(sizeof(char)*200);
    if (! (name && modname))
    {
        fprintf(stderr, "%s %d: Out of memory!", __FILE__, __LINE__);
        return 1;
    }

    appProc->beginInsertionSet();

    // Iterate through the procedures
    for (int i = 0; i < functions->size(); i++)
    {
        (*functions)[i]->getName(name, 199);
        (*functions)[i]->getModuleName(modname, 199);
        if ((patchall && strcmp(modname, "DEFAULT_MODULE") != 0) ||
            strncmp(name, "pthread", 7) == 0 ||
            strncmp(modname, "libpthread", 10) == 0 ||
            strncmp(modname, "libdyninst", 10) == 0 ||
            (name[0] == '_' && name[1] != '_' && strncmp(modname, "libc", 4) == 0))
            continue;

        fprintf(stderr, "patcher: Patching function: '%s' (%s)", name, modname);

        // Patch back-edge for call
        if (strcmp(name, "main") != 0)
            appProc->insertSnippet(addOneAtomic, *((*functions)[i]->findPoint(BPatch_entry)));

        // Get the control flow graph for the procedure
        BPatch_flowGraph *graph = (*functions)[i]->getCFG();

        // Find the loops
        BPatch_Vector<BPatch_basicBlockLoop*> *loops = new BPatch_Vector<BPatch_basicBlockLoop*>();
        graph->getLoops(*loops);
    
        // Patch the loop back-edges
        for(int j = 0; j < loops->size(); j++)
        {
            appProc->insertSnippet(addOneAtomic, *((*loops)[j]->getBackEdge()->getPoint()));
            fprintf(stderr, ".", (int) (*loops)[j]->getBackEdge()->getPoint()->getAddress());
        }
        fprintf(stderr, "\n");

        // Free the loops found
        delete(loops);
    }

    fprintf(stderr, "Finalising patches...");
    fflush(stderr);
    appProc->finalizeInsertionSet(false);
    fprintf(stderr, "Done.\n----------------------------------------\n");

    // Clear up memory used to store the name
    free(name);
    free(modname);


#if 0
    /*************************************************************************
     * Exit point counter print patch                                        *
     *************************************************************************/

    // Patch exit() function to print out no of back branches at the end
    // Get exit() exit point
    BPatch_Vector<BPatch_point*> *exitPoints = exitFuncs[0]->findPoint(BPatch_entry);

    // Build printf() call:
    //    printf("Total Total Back-branches: %d\n", counter);

    // Build arguments to printf()
    BPatch_Vector<BPatch_snippet*> printfArgs;
    BPatch_constExpr formatString("Total Back-branches: %d\n");

    printfArgs.push_back(&formatString);
    printfArgs.push_back(&derefCounter);

    // Build call to printf()
    BPatch_funcCallExpr printfCall(*printfFuncs[0], printfArgs);

    // Patch into exit()
    appProc->insertSnippet(printfCall, *exitPoints);
#endif

    // Continue mutatee...
    appProc->continueExecution();

    // Wait for mutatee to finish
    while (!appProc->isTerminated())
    {
        bpatch.waitForStatusChange();
    }

    fprintf(stderr, "----------------------------------------\n");
    fprintf(stderr, "Done.\n");
    return 0;
}
int main (int argc, char *argv[])
{
	set<string> Routines;
	char *env_var;
	int index;

	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, Routines);

	/* Does the binary exists? */
	if (!__Extrae_Utils_file_exists(argv[index]))
	{
		cout << PACKAGE_NAME << ": Executable " << argv[index] << " cannot be found!" << endl;
		exit (-1);
	}

	if (Routines.size() > 0)
	{
		set<string>::iterator it;
		cout << PACKAGE_NAME << ": Will instrument routines ";
		for (it = Routines.begin(); it != Routines.end(); it++)
			cout << *it << " ";
		cout << endl;
	}

	/* 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++;
	}

	cout << PACKAGE_NAME << ": Creating process for image binary " << argv[index];
	cout.flush ();
	BPatch_process * 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 << 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);
	}

	cout << PACKAGE_NAME << ": Acquiring process image" << endl;
	BPatch_image *appImage = appProcess->getImage();
	if (appImage == NULL)
	{
		cerr << PACKAGE_NAME << ": Error while acquiring application image" << endl;
		exit (-1);
	}

	cout << PACKAGE_NAME << ": Looking for printf symbol in application image" << endl;
	appImage->findFunction ("printf", printfFuncs);
	if (printfFuncs.size() == 0)
	{
		cerr << PACKAGE_NAME << ": Error! Cannot locate printf function within image" << endl;
		exit (-1);
	}

	if (!ListFunctions)
	{
		InstrumentCalls (appImage, appProcess, Routines);

		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
		ShowFunctions (appImage);

	return 0;
}