Exemplo n.º 1
0
// static int mutatorTest(BPatch_thread *appThread, BPatch_image *appImage)
test_results_t test_stack_1_Mutator::executeTest() {
    appProc->continueExecution();
    static const frameInfo_t correct_frame_info[] = {
#if defined( os_linux_test ) && (defined( arch_x86_test ) || defined( arch_x86_64_test ))
	{ true, true, BPatch_frameNormal, "_dl_sysinfo_int80" },
#endif
#if !defined(rs6000_ibm_aix4_1_test)
	{ false, false, BPatch_frameNormal, NULL },
#endif
#if !defined(i386_unknown_nt4_0_test)
	{ true,  false, BPatch_frameNormal, "stop_process_" },
#endif
	{ true,  false, BPatch_frameNormal, "test_stack_1_func3" },
	{ true,  false, BPatch_frameNormal, "test_stack_1_func2" },
	{ true,  false, BPatch_frameNormal, "test_stack_1_func1" },
	{ true,  false, BPatch_frameNormal, "test_stack_1_mutateeTest" },
	{ true,  false, BPatch_frameNormal, "main" },
    };

    if (waitUntilStopped(bpatch, appProc, 1, "getCallStack") < 0) {
      appProc->terminateExecution();
      return FAILED;
    }

    if (checkStack(appThread,
		   correct_frame_info,
		   sizeof(correct_frame_info)/sizeof(frameInfo_t),
		   1, "getCallStack")) {
	logerror("Passed test #1 (getCallStack)\n");

    } else {
      appProc->terminateExecution();
       return FAILED;
    }

    appProc->continueExecution();
    while (!appProc->isTerminated()) {
      bpatch->waitForStatusChange();
    }

    return PASSED;
}
Exemplo n.º 2
0
// static bool mutatorTest3and4(int testno, const char *testname)
test_results_t test_thread_2_Mutator::executeTest() {
  test3_threadCreateCounter = 0;
  callback_tids.clear();

  BPatchAsyncThreadEventCallback createcb = threadCreateCB;
  if (!bpatch->registerThreadEventCallback(BPatch_threadCreateEvent, createcb))
  {
    FAIL_MES(TESTNAME, TESTDESC);
    logerror("%s[%d]:  failed to register thread callback\n",
	     __FILE__, __LINE__);
    appThread->getProcess()->terminateExecution();
    return FAILED;
  }

#if 0
  //  unset mutateeIde to trigger thread (10) spawn.
  int zero = 0;
  // FIXME Check the return code for setVar
  setVar("mutateeIdle", (void *) &zero, TESTNO, TESTDESC);
  dprintf("%s[%d]:  continue execution for test %d\n", __FILE__, __LINE__, TESTNO);
  appThread->continueExecution();
#endif

  if( !appProc->continueExecution() ) {
      logerror("%s[%d]: failed to continue process\n", FILE__, __LINE__);
      appProc->terminateExecution();
      return FAILED;
  }

  //  wait until we have received the desired number of events

  int err = 0;
  BPatch_Vector<BPatch_thread *> threads;
  BPatch_process *appProc = appThread->getProcess();
  assert(appProc);
  appProc->getThreads(threads);
  int active_threads = 11; // FIXME Magic number
  threads.clear();
  while (((test3_threadCreateCounter < TEST3_THREADS)
         || (active_threads > 1)) && !appProc->isTerminated() ) {
    dprintf("%s[%d]: waiting for completion for test; ((%d < %d) || (%d > 1)) && !(%d)\n",
	    __FILE__, __LINE__, test3_threadCreateCounter, TEST3_THREADS,
	    active_threads, 1, appProc->isTerminated());
    if( !bpatch->waitForStatusChange() ) {
        logerror("%s[%d]: failed to wait for events\n", __FILE__, __LINE__);
        err = 1;
        break;
    }

    appProc->getThreads(threads);
    active_threads = threads.size();
    threads.clear();
  }

  if( appProc->isTerminated() ) {
      logerror("%s[%d]:  BAD NEWS:  somehow the process died\n", __FILE__, __LINE__);
      return FAILED;
  }

  dprintf("%s[%d]: ending test %d, num active threads = %d\n",
            __FILE__, __LINE__, TESTNO, active_threads);
  dprintf("%s[%d]:  stop execution for test %d\n", __FILE__, __LINE__, TESTNO);
  appProc->stopExecution();

  //   read all tids from the mutatee and verify that we got them all
  unsigned long mutatee_tids[TEST3_THREADS];
  const char *threads_varname = "test3_threads";
  if (getVar(threads_varname, (void *) mutatee_tids,
	     (sizeof(unsigned long) * TEST3_THREADS),
	     TESTNO, TESTDESC)) {
    appProc->terminateExecution();
    return FAILED;
  }

  if (debugPrint()) {
    dprintf("%s[%d]:  read following tids for test%d from mutatee\n", __FILE__, __LINE__, TESTNO);

    for (unsigned int i = 0; i < TEST3_THREADS; ++i) {
       dprintf("\t%lu\n", mutatee_tids[i]);
    }
  }

  for (unsigned int i = 0; i < TEST3_THREADS; ++i) {
     bool found = false;
     for (unsigned int j = 0; j < callback_tids.size(); ++j) {
       if (callback_tids[j] == mutatee_tids[i]) {
         found = true;
         break;
       }
     }

    if (!found) {
      FAIL_MES(TESTNAME, TESTDESC);
      logerror("%s[%d]:  could not find record for tid %lu: have these:\n",
             __FILE__, __LINE__, mutatee_tids[i]);
       for (unsigned int j = 0; j < callback_tids.size(); ++j) {
          logerror("%lu\n", callback_tids[j]);
       }
      err = 1;
      break;
    }
  }

  dprintf("%s[%d]: removing thread callback\n", __FILE__, __LINE__);
  if (!bpatch->removeThreadEventCallback(BPatch_threadCreateEvent, createcb)) {
    FAIL_MES(TESTNAME, TESTDESC);
    logerror("%s[%d]:  failed to remove thread callback\n",
           __FILE__, __LINE__);
    err = 1;
  }

  if (!err)  {
    logerror("No error reported, terminating process and returning success\n");
    PASS_MES(TESTNAME, TESTDESC);
    appProc->terminateExecution();
    logerror("\t Process terminated\n");
    return PASSED;
  }
  appProc->terminateExecution();
  return FAILED;
}
Exemplo n.º 3
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() */
Exemplo n.º 4
0
int main(int argc, char**argv)
{
  if(argc != 3) {
    printf("usage: %s orig_prog new_prog\n", argv[0]);
    return 1;
  }

  char* file = argv[1];
  char* newFile = argv[2];
  bool ret;


  eztrace_dyninst_register ("compute_", 1, 2);
  eztrace_dyninst_register ("dist_", 3, 4);
  eztrace_dyninst_register ("initialize_", 5, 6);
  eztrace_dyninst_register ("timestamp_", 7, 8);
  eztrace_dyninst_register ("update_", 9, 10);


  if(!eztrace_dyninst_nb_function_to_register()) {
    printf("0 functions instrumented\n");
    return 1;
  }


#ifdef CREATE_BINARY
  //Create the BPatch_addressSpace and BPatch_binaryEdit
  appBin = bpatch.openBinary(file, true);
  if(!appBin) {
    fprintf(stderr, "Cannot open %s\n", file);
    return -1;
  }
  app = static_cast<BPatch_addressSpace *>(appBin);


  if(! app->loadLibrary(LIB_EZTRACE_SO)) {
    printf("Cannot load %s\n", LIB_EZTRACE_SO);
    return 1;
  }

#else
  // run the program
  BPatch_process *appProc = bpatch.processCreate(file, NULL);
  if(!appProc) {
    printf("Cannot load program %s\n", file);
  }

  if(! appProc->loadLibrary(LIB_EZTRACE_SO, true)) {
    printf("Cannot load %s\n", LIB_EZTRACE_SO);
    return 1;
  }

  app = static_cast<BPatch_addressSpace *>(appProc);

#endif


  // Instrument all the specified functions
  int nb_inst = eztrace_dyninst_instrument(app);
  printf("%d functions instrumented\n", nb_inst);
  if(! nb_inst)
    return 1;

#ifdef CREATE_BINARY
  if (appBin != NULL) {
    //Write a new instrumented executable
    appBin->writeFile(newFile);
  } else {
    fprintf(stderr, "cannot write %s\n", newFile);
    return -1;
  }
#else

  appProc->continueExecution();
  while(!appProc->isTerminated()) {
    bpatch.waitForStatusChange();
  }
#endif
  return 0;
}
Exemplo n.º 5
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;
}
Exemplo n.º 6
0
// static int mutatorTest(BPatch_thread *appThread, BPatch_image *appImage)
test_results_t test_callback_2_Mutator::executeTest() 
{
	//  a simple single threaded user messagin scenario where we want to send
	//  async messages at function entry/exit and call points.

	// load libtest12.so -- currently only used by subtest 5, but make it generally
	// available
	const char *libname = "./libTest12.so";    
	test7err = false;
	test7done = false;
	callback_counter = 0;
	elog.resize(0);

#if defined(arch_x86_64_test)
	if (appProc->getAddressWidth() == 4)
		libname = "./libTest12_m32.so";
#endif

	dprintf("%s[%d]:  loading test library: %s\n", __FILE__, __LINE__, libname);

	if (!appProc->loadLibrary(libname))
	{
		logerror("%s[%d]:  failed to load library %s, cannot proceed\n", 
				__FILE__, __LINE__, libname);
                appProc->terminateExecution();
		return FAILED;
	}

	dprintf("%s[%d]:  loaded test library: %s\n", __FILE__, __LINE__, libname);
	BPatchUserEventCallback cb = test7cb;

	if (!bpatch->registerUserEventCallback(cb)) 
	{
		FAIL_MES(TESTNAME, TESTDESC);
		logerror("%s[%d]: could not register callback\n", __FILE__, __LINE__);
                appProc->terminateExecution();
		return FAILED;
	}

	//  instrument entry and exit of call7_1, as well as call points inside call7_1

	const char *call1name = "test_callback_2_call1";

	BPatch_function *call7_1 = findFunction(call1name, appImage,TESTNO, TESTNAME);

	BPatch_point *entry = findPoint(call7_1, BPatch_entry,TESTNO, TESTNAME);

	if (NULL == entry) 
	{
		logerror("%s[%d]: Unable to find entry point to function %s\n", 
				__FILE__, __LINE__, call1name);
		bpatch->removeUserEventCallback(test7cb);
                appProc->terminateExecution();
		return FAILED;
	}

	BPatch_point *exit = findPoint(call7_1, BPatch_exit,TESTNO, TESTNAME);

	if (NULL == entry) 
	{
		logerror("%s[%d]:  Unable to find exit point to function %s\n", 
				__FILE__, __LINE__, call1name);
		bpatch->removeUserEventCallback(test7cb);
                appProc->terminateExecution();
		return FAILED;
	}

	BPatch_point *callsite = findPoint(call7_1, BPatch_subroutine,TESTNO, TESTNAME);

	if (NULL == callsite) 
	{
		logerror("%s[%d]:  Unable to find subroutine call point in function %s\n",
				__FILE__, __LINE__, call1name);
		bpatch->removeUserEventCallback(test7cb);
                appProc->terminateExecution();
		return FAILED;
	}

	//  These are our asynchronous message functions (in libTest12) that we
	//  attach to the "interesting" points

	BPatch_function *reportEntry = findFunction("reportEntry", appImage,TESTNO, TESTNAME);
	BPatch_function *reportExit = findFunction("reportExit", appImage,TESTNO, TESTNAME);
	BPatch_function *reportCallsite = findFunction("reportCallsite", appImage,TESTNO, TESTNAME);

	if (!reportEntry)
	{
		logerror("%s[%d]:  reportEntry = NULL\n", FILE__, __LINE__);
		bpatch->removeUserEventCallback(test7cb);
                appProc->terminateExecution();
		return FAILED;
	}
	if (!reportExit)
	{
		logerror("%s[%d]:  reportExit = NULL\n", FILE__, __LINE__);
		bpatch->removeUserEventCallback(test7cb);
                appProc->terminateExecution();
		return FAILED;
	}
	if (!reportCallsite)
	{
		logerror("%s[%d]:  reportCallsite = NULL\n", FILE__, __LINE__);
		bpatch->removeUserEventCallback(test7cb);
                appProc->terminateExecution();
		return FAILED;
	}

	//  Do the instrumentation
	BPatchSnippetHandle *entryHandle = at(entry, reportEntry, TESTNO, TESTNAME);
	BPatchSnippetHandle *exitHandle = at(exit, reportExit, TESTNO, TESTNAME);
	BPatchSnippetHandle *callsiteHandle = at(callsite, reportCallsite, TESTNO, TESTNAME);

	//  "at" may set test7err
	if ((test7err)
			||  (NULL == entryHandle) 
			|| (NULL == exitHandle) 
			|| (NULL == callsiteHandle) )
	{
		logerror("%s[%d]:  instrumentation failed, test7err = %d\n", FILE__, __LINE__, test7err);
		logerror("%s[%d]:  entryHandle = %p\n", FILE__, __LINE__, entryHandle);
		logerror("%s[%d]:  exitHandle = %p\n", FILE__, __LINE__, exitHandle);
		logerror("%s[%d]:  callsiteHandle = %p\n", FILE__, __LINE__, callsiteHandle);
		bpatch->removeUserEventCallback(test7cb);
		return FAILED;
	}
	if (debugPrint()) 
	{
		int one = 1;
		const char *varName = "libraryDebug";
		if (setVar(varName, (void *) &one, TESTNO, TESTNAME)) 
		{
			logerror("%s[%d]:  Error setting variable '%s' in mutatee\n", 
					FILE__, __LINE__, varName);
			bpatch->removeUserEventCallback(test7cb);
                        appProc->terminateExecution();
			return FAILED;
		}
	}

	dprintf("%s[%d]:  did instrumentation, continuing process...: %s\n", 
			__FILE__, __LINE__, libname);
	//  unset mutateeIdle to trigger mutatee to issue messages.

	int timeout = 0;

        appProc->continueExecution();

	dprintf("%s[%d]:  continued process...: %s\n", 
			__FILE__, __LINE__, libname);
	//  wait until we have received the desired number of events
	//  (or timeout happens)

	while(!test7err && !test7done && (timeout < TIMEOUT)) 
	{
		sleep_ms(SLEEP_INTERVAL/*ms*/);
		timeout += SLEEP_INTERVAL;
		bpatch->pollForStatusChange();

                if (appProc->isTerminated())
		{
			BPatch_exitType et = appProc->terminationStatus();
			if (et == ExitedNormally)
			{
				int ecode = appProc->getExitCode();
				logerror("%s[%d]:  normal exit with code %d\n",
						__FILE__, __LINE__, ecode);
			}
			if (et == ExitedViaSignal)
			{
				int ecode = appProc->getExitSignal();
				logerror("%s[%d]:  caught signal %d\n",
						__FILE__, __LINE__, ecode);
			}
			log_res();
			bpatch->removeUserEventCallback(test7cb);
			return FAILED;
		}
	}

	dprintf("%s[%d]:  after wait loop:  test7err = %s, test7done = %s, timeout = %d\n", 
			__FILE__, __LINE__, test7err ? "true" : "false", test7done ? "true" : "false", timeout);

	if (timeout >= TIMEOUT) 
	{
		FAIL_MES(TESTNAME, TESTDESC);
		logerror("%s[%d]:  test timed out: %d ms\n",
				__FILE__, __LINE__, TIMEOUT);
		test7err = true;
	}

	if (!appProc->stopExecution())
	{
		logerror("%s[%d]:  stopExecution failed\n",
				__FILE__, __LINE__);

	}

	dprintf("%s[%d]:  stopped process...\n", 
			__FILE__, __LINE__ );

	if (!bpatch->removeUserEventCallback(test7cb)) 
	{
		FAIL_MES(TESTNAME, TESTDESC);
		logerror("%s[%d]:  failed to remove callback\n",
				__FILE__, __LINE__);
		appProc->terminateExecution();
		log_res();
		return FAILED;
	}

	dprintf("%s[%d]:  removed callback...\n", 
			__FILE__, __LINE__ );
	if (!appProc->terminateExecution())
	{
		//  don't care
		//fprintf(stderr, "%s[%d]:  terminateExecution failed\n", FILE__, __LINE__);
		//return FAILED;
	}

#if 0
	int one = 1;

	if (setVar("test_callback_2_idle", (void *) &one, TESTNO, TESTNAME)) 
	{
		logerror("Error setting variable 'test_callback_2_idle' in mutatee\n");
		test7err = true;
		appProc->terminateExecution();
	}
#endif

#if 0
	// And let it run out
	if (!appThread->isTerminated()) 
	{
		appProc->continueExecution();
	}

	while (!appThread->isTerminated()) 
	{
		// Workaround for pgCC_high mutatee issue
		bpatch->waitForStatusChange();
	}
#endif

	if (!test7err) 
	{
		PASS_MES(TESTNAME, TESTDESC);
		return PASSED;
	}

	log_res();
	FAIL_MES(TESTNAME, TESTDESC);
	return FAILED;
}