Esempio n. 1
0
void instrumentFunction(BPatch_function *function)
{
    std::set<BPatch_basicBlock*> blocks;
    std::set<BPatch_basicBlock*>::reverse_iterator b;
    BPatch_flowGraph *cfg = function->getCFG();
    cfg->getAllBasicBlocks(blocks);
    for (b = blocks.rbegin(); b != blocks.rend(); b++) {
        instrumentBasicBlock(function, *b);
    }
}
Esempio n. 2
0
// inserts a callback for each basic block assigning it an instrumentation
// time 16bit random ID just as afl
bool insertBBCallback(BPatch_binaryEdit * appBin, BPatch_function * curFunc,
                      char *funcName, BPatch_function * instBBIncFunc,int *bbIndex)
{

    BPatch_flowGraph *appCFG = curFunc->getCFG ();
    unsigned short randID;

    if (!appCFG) {
        cerr << "Failed to find CFG for function " << funcName << endl;
        return false;
    }

    BPatch_Set < BPatch_basicBlock * >allBlocks;
    if (!appCFG->getAllBasicBlocks (allBlocks)) {
        cerr << "Failed to find basic blocks for function " << funcName << endl;
        return false;
    } else if (allBlocks.size () == 0) {
        cerr << "No basic blocks for function " << funcName << endl;
        return false;
    }

    BPatch_Set < BPatch_basicBlock * >::iterator iter;
    for (iter = allBlocks.begin (); iter != allBlocks.end (); iter++) {
        if(*bbIndex < bbSkip) { // skip over first bbSkip bbs
            (*bbIndex)++;
            continue;

        }
        unsigned long address = (*iter)->getStartAddress ();
        randID = rand() % USHRT_MAX;
        if(verbose) {
            cout << "Instrumenting Basic Block 0x" << hex << address << " of " <<
                 funcName << " with random id " << randID << endl;
        }

        BPatch_Vector < BPatch_snippet * >instArgs;
        BPatch_constExpr bbId (randID);
        instArgs.push_back (&bbId);
        BPatch_point *bbEntry = (*iter)->findEntryPoint ();
        if (NULL == bbEntry) {
            // warn the user, but continue
            cerr << "Failed to find entry for basic block at 0x" << hex << address
                 << endl;
            (*bbIndex)++;
            continue;
        }
        BPatch_funcCallExpr instIncExpr (*instBBIncFunc, instArgs);
        BPatchSnippetHandle *handle =
            appBin->insertSnippet (instIncExpr, *bbEntry, BPatch_callBefore,
                                   BPatch_lastSnippet);
        if (!handle) {
            // warn the user, but continue to next bb
            cerr << "Failed to insert instrumention in basic block at 0x" << hex <<
                 address << endl;
            (*bbIndex)++;
            continue;
        }

        (*bbIndex)++;
    }

    return true;

}
Esempio n. 3
0
bool instrumentMemoryWrites(dynHandle *dh, BPatch_function *func)
{
   BPatch_Set<BPatch_basicBlock*> allBlocks;
   BPatch_snippet incSnippet; 
   BPatch_Set<BPatch_opCode> ops;
   BPatch_Set<BPatch_basicBlock*>::iterator iter;
   int bb_warn_cnt = 0, bb_pass_cnt = 0;

   sendMsg(config.outfd, ID_INST_MEM_WRITE, VERB2);

   sendMsg(config.outfd, ID_GET_CFG, VERB3);
   BPatch_flowGraph *appCFG = func->getCFG();
   if (!appCFG) {
      sendMsg(config.outfd, ID_GET_CFG, VERB3, ID_FAIL,
              "Failure in BPatch_function::getCFG()");
      goto fail;

   } else {
      sendMsg(config.outfd, ID_GET_CFG, VERB3, ID_PASS);
   }

   sendMsg(config.outfd, ID_INST_GET_BB, VERB3);
   if (!appCFG->getAllBasicBlocks(allBlocks)) {
      sendMsg(config.outfd, ID_INST_GET_BB, VERB3, ID_FAIL,
              "Failure in BPatch_flowGraph::getAllBasicBlocks()");
      goto fail;

   } else if (allBlocks.size() == 0) {
      sendMsg(config.outfd, ID_INST_GET_BB, VERB3, ID_WARN,
              "No basic blocks found in function");
      goto fail;

   } else {
      sendMsg(config.outfd, ID_INST_GET_BB, VERB3, ID_PASS);
   }

   if (! generateInstrumentation (dh, func, &incSnippet))
    	goto fail;

   ops.insert(BPatch_opStore);

   sendMsg(config.outfd, ID_INST_BB_LIST, VERB3);
   for (iter = allBlocks.begin(); iter != allBlocks.end(); iter++) {
      if (!shouldInsert())
         continue;
      sendMsg(config.outfd, ID_INST_GET_BB_POINTS, VERB4);
      BPatch_Vector<BPatch_point*> *points = (*iter)->findPoint(ops);
      if (!points) {
         sendMsg(config.outfd, ID_INST_GET_BB_POINTS, VERB4, ID_WARN,
                 "Failure in BPatch_basicBlock::findPoint()");
         ++bb_warn_cnt;
         continue;

      } else if (points->size() == 0) {
         sendMsg(config.outfd,  ID_INST_GET_BB_POINTS, VERB4, ID_WARN,
                 "No instrumentation points found in basic block");
         ++bb_warn_cnt;
         continue;

      } else {
         sendMsg(config.outfd, ID_INST_GET_BB_POINTS, VERB4, ID_PASS);
      }

      sendMsg(config.outfd, ID_INST_INSERT_CODE, VERB4);
      BPatchSnippetHandle *handle = dh->addSpace->insertSnippet(incSnippet, *points);
      if (!handle) {
         sendMsg(config.outfd, ID_INST_INSERT_CODE, VERB4, ID_FAIL,
                 "Failure in BPatch_process::insertSnippet()");
         ++bb_warn_cnt;
         continue;

      } else {
         sendMsg(config.outfd, ID_INST_INSERT_CODE, VERB4, ID_PASS);
         ++bb_pass_cnt;
      }
   }
   if (bb_warn_cnt)
      sendMsg(config.outfd, ID_INST_BB_LIST, VERB3, ID_WARN,
              sprintf_static("%d warning(s), %d passed.", bb_warn_cnt, bb_pass_cnt));
   else
      sendMsg(config.outfd, ID_INST_BB_LIST, VERB3, ID_PASS);

   sendMsg(config.outfd, ID_INST_MEM_WRITE, VERB2, ID_PASS);
   return true;

 fail:
   sendMsg(config.outfd, ID_INST_MEM_WRITE, VERB2, ID_WARN,
           "Failure while instrumenting memory writes.");
   return false;

}
Esempio n. 4
0
test_results_t test1_33_Mutator::executeTest() 
{
	int pvalue;
	unsigned int i;

	if (isMutateeFortran(appImage)) 
	{
		return SKIPPED;
	}

	BPatch_Vector<BPatch_function *> bpfv;
	const char *fn = "test1_33_func2";
	if (NULL == appImage->findFunction(fn, bpfv) || !bpfv.size()
			|| NULL == bpfv[0])
	{
		logerror("**Failed** test #33 (control flow graphs)\n");
		logerror("    Unable to find function %s\n", fn);
		return FAILED;
	}

	BPatch_function *func2 = bpfv[0];

	BPatch_flowGraph *cfg = func2->getCFG();
	if (cfg == NULL) 
	{
		logerror("**Failed** test #33 (control flow graphs)\n");
		logerror("  Unable to get control flow graph of %s\n", fn);
		return FAILED;
	}

	/*
	 * Test for consistency of entry basic blocks.
	 */

	BPatch_Vector<BPatch_basicBlock*> entry_blocks;
	cfg->getEntryBasicBlock(entry_blocks);

	if (entry_blocks.size() != 1) 
	{
		logerror("**Failed** test #33 (control flow graphs)\n");
		logerror("  Detected %d entry basic blocks in %s, should have been one.\n", entry_blocks.size(), fn);
		return FAILED;
	}

	for (i = 0; i < entry_blocks.size(); i++) 
	{
		BPatch_Vector<BPatch_basicBlock*> sources;
		entry_blocks[i]->getSources(sources);

		if (sources.size() > 0) 
		{
			logerror("**Failed** test #33 (control flow graphs)\n");
			logerror("  An entry basic block has incoming edges in the control flow graph\n");
			return FAILED;
		}

		BPatch_Vector<BPatch_basicBlock*> targets;
		entry_blocks[i]->getTargets(targets);

		if (targets.size() < 1) 
		{
			logerror("**Failed** test #33 (control flow graphs\n");
			logerror("  An entry basic block has no outgoing edges in the control flow graph\n");
			return FAILED;
		}
	}

	/*
	 * Test for consistency of exit basic blocks.
	 */

	BPatch_Vector<BPatch_basicBlock*> exit_blocks;
	cfg->getExitBasicBlock(exit_blocks);

	if (exit_blocks.size() != 1) 
	{
		logerror("**Failed** test #33 (control flow graphs)\n");
		logerror("  Detected %d exit basic blocks in %s, should have been one.\n", exit_blocks.size(), fn);
		return FAILED;
	}

	for (i = 0; i < exit_blocks.size(); i++) 
	{
		BPatch_Vector<BPatch_basicBlock*> sources;
		exit_blocks[i]->getSources(sources);

		if (sources.size() < 1) 
		{
			logerror("**Failed** test #33 (control flow graphs)\n");
			logerror("  An exit basic block has no incoming edges in the control flow graph\n");
			return FAILED;
		}

		BPatch_Vector<BPatch_basicBlock*> targets;
		exit_blocks[i]->getTargets(targets);

		if (targets.size() > 0) 
		{
			logerror("**Failed** test #33 (control flow graphs)\n");
			logerror("  An exit basic block has outgoing edges in the control flow graph\n");
			return FAILED;
		}
	}

	/*
	 * Check structure of control flow graph.
	 */

        std::set<BPatch_basicBlock*> blocks;
	cfg->getAllBasicBlocks(blocks);

	if (blocks.size() < 4) 
	{
		logerror("**Failed** test #33 (control flow graphs)\n");
		logerror("  Detected %d basic blocks in %s, should be at least four.\n", blocks.size(), fn);
		return FAILED;
	}

	bool foundOutDegreeTwo = false;
	bool foundInDegreeTwo = false;
	int blocksNoIn = 0, blocksNoOut = 0;

        for (std::set<BPatch_basicBlock *>::iterator iter = blocks.begin();
             iter != blocks.end(); ++iter) {
           BPatch_Vector<BPatch_basicBlock*> in;
           BPatch_Vector<BPatch_basicBlock*> out;
           
           (*iter)->getSources(in);
           (*iter)->getTargets(out);
           
           if (in.size() == 0)
              blocksNoIn++;
           
           if (out.size() == 0)
              blocksNoOut++;
           
           if (in.size() > 2 || out.size() > 2) 
           {
              logerror("**Failed** test #33 (control flow graphs)\n");
              logerror("  Detected a basic block in %s with %d incoming edges and %d\n", fn, in.size(), out.size());
              logerror("  outgoing edges - neither should be greater than two.\n");
              return FAILED;
           } 
           else if (in.size() > 1 && out.size() > 1) 
           {
              logerror("**Failed** test #33 (control flow graphs)\n");
              logerror("  Detected a basic block in %s with %d incoming edges and %d\n", fn, in.size(), out.size());
              logerror("  outgoing edges - only one should be greater than one.\n");
              return FAILED;
           } 
           else if (in.size() == 0 && out.size() == 0) 
           {
              logerror("**Failed** test #33 (control flow graphs)\n");
              logerror("  Detected a basic block in %s with no incoming or outgoing edges.\n", fn);
              return FAILED;
           } 
           else if (in.size() == 2) 
           {
              assert(out.size() <= 1);
              
              if (foundInDegreeTwo) 
              {
                 logerror("**Failed** test #33 (control flow graphs)\n");
                 logerror("  Detected two basic blocks in %s with in degree two, there should only\n", fn);
                 logerror("  be one.\n");
                 return FAILED;
              }
              foundInDegreeTwo = true;
              
              if (in[0]->getBlockNumber() == in[1]->getBlockNumber()) 
              {
                 logerror("**Failed** test #33 (control flow graphs)\n");
                 logerror("  Two edges go to the same block (number %d).\n", in[0]->getBlockNumber());
                 return FAILED;
              }
           } 
           else if (out.size() == 2) 
           {
              assert(in.size() <= 1);
              
              if (foundOutDegreeTwo) 
              {
                 logerror("**Failed** test #33 (control flow graphs)\n");
                 logerror("  Detected two basic blocks in %s with out degree two, there should only\n", fn);
                 logerror("  be one.\n");
                 return FAILED;
              }
              foundOutDegreeTwo = true;
              
              if (out[0]->getBlockNumber() == out[1]->getBlockNumber()) 
              {
                 logerror("**Failed** test #33 (control flow graphs)\n");
                 logerror("  Two edges go to the same block (number %d).\n", out[0]->getBlockNumber());
                 return FAILED;
              }
           } 
           else if (in.size() > 1 || out.size() > 1) 
           {
              /* Shouldn't be able to get here. */
              logerror("**Failed** test #33 (control flow graphs)\n");
              logerror("  Detected a basic block in %s with %d incoming edges and %d\n", fn, in.size(), out.size());
              logerror("  outgoing edges.\n");
              return FAILED;
           }
	}
        
	if (blocksNoIn > 1) 
	{
		logerror("**Failed** test #33 (control flow graphs)\n");
		logerror("  Detected more than one block in %s with no incoming edges.\n", fn);
		return FAILED;
	}

	if (blocksNoOut > 1) 
	{
		logerror("**Failed** test #33 (control flow graphs)\n");
		logerror("  Detected more than block in %s with no outgoing edges.\n", fn);
		return FAILED;
	}

	if (!foundOutDegreeTwo) 
	{
		logerror("**Failed** test #33 (control flow graphs)\n");
		logerror("  Did not detect the \"if\" statement in %s.\n", fn);
		return FAILED;
	}

	/*
	 * Check for loops (there aren't any in the function we're looking at).
	 */

	std::set<int> empty;

	if (hasBackEdge(entry_blocks[0], empty)) 
	{
		logerror("**Failed** test #33 (control flow graphs)\n");
		logerror("  Detected a loop in %s, there should not be one.\n", fn);
		return FAILED;
	}

	/*
	 * Now check a function with a switch statement.
	 */
	bpfv.clear();
	const char *fn2 = "test1_33_func3";

	// Bernat, 8JUN05 -- include uninstrumentable here...

	if (NULL == appImage->findFunction(fn2, bpfv, false, false, true) || !bpfv.size()
			|| NULL == bpfv[0])
	{
		logerror("**Failed** test #33 (control flow graphs)\n");
		logerror("    Unable to find function %s\n", fn2);
		return FAILED;
	}

	BPatch_function *func3 = bpfv[0];
	BPatch_flowGraph *cfg3 = func3->getCFG();

	if (cfg3 == NULL) 
	{
		logerror("**Failed** test #33 (control flow graphs)\n");
		logerror("  Unable to get control flow graph of %s\n", fn2);
		return FAILED;
	}

        std::set<BPatch_basicBlock*> blocks3;
	cfg3->getAllBasicBlocks(blocks3);

	if (blocks3.size() < 10) 
	{
		logerror("**Failed** test #33 (control flow graphs)\n");
		logerror("  Detected %d basic blocks in %s, should be at least ten.\n", blocks3.size(), fn2);
		return FAILED;
	}

	bool foundSwitchIn = false;
	bool foundSwitchOut = false;
	bool foundRangeCheck = false;

        for (std::set<BPatch_basicBlock *>::iterator iter = blocks3.begin();
             iter != blocks3.end(); ++iter) {
           BPatch_basicBlock *block = *iter;

           BPatch_Vector<BPatch_basicBlock*> in;
           BPatch_Vector<BPatch_basicBlock*> out;
           
           block->getSources(in);
           block->getTargets(out);

           if (!foundSwitchOut && out.size() >= 10 && in.size() <= 1) 
           {
              foundSwitchOut = true;
           } 
           else if (!foundSwitchIn && in.size() >= 10 && out.size() <= 1) 
           {
              foundSwitchIn = true;
           } 
           else if (!foundRangeCheck && out.size() == 2 && in.size() <= 1) 
           {
              foundRangeCheck = true;
           } 
           else if (in.size() > 1 && out.size() > 1) 
           {
              logerror("**Failed** test #33 (control flow graphs)\n");
              logerror("  Found basic block in %s with unexpected number of edges.\n", fn2);
              logerror("  %d incoming edges, %d outgoing edges.\n",
                       in.size(), out.size());
              return FAILED;
           }
	}

	if (!foundSwitchIn || !foundSwitchOut) 
	{
		logerror("**Failed** test #33 (control flow graphs)\n");
		if (!foundSwitchIn)
			logerror("  Did not find \"switch\" statement in %s.\n", fn2);
		if (!foundSwitchOut)
			logerror("  Did not find block after \"switch\" statement.\n");
		return FAILED;
	}

	/* Check dominator info. */
	BPatch_Vector<BPatch_basicBlock*> entry3;
	cfg3->getEntryBasicBlock(entry3);

	if (entry3.size() != 1) 
	{
		logerror("**Failed** test #33 (control flow graphs)\n");
		logerror("  Detected %d entry basic blocks in %s, should have been one.\n", entry_blocks.size(), fn2);
		return FAILED;
	}

        for (std::set<BPatch_basicBlock *>::iterator iter2 = blocks3.begin();
             iter2 != blocks3.end(); ++iter2) {
           if (!entry3[0]->dominates(*iter2))  {
              logerror("**Failed** test #33 (control flow graphs)\n");
              logerror("  Entry block does not dominate all blocks in %s\n", fn2);
              return FAILED;
           }
	}

	BPatch_Vector<BPatch_basicBlock*> exit3;
	cfg3->getExitBasicBlock(exit3);

	if (exit3.size() != 1) 
	{
		logerror("**Failed** test #33 (control flow graphs)\n");
		logerror("  Detected %d exit basic blocks in  %s, should have been one.\n", exit3.size(), fn2);
		for (unsigned i = 0; i < exit3.size(); ++i) {
		  logerror("\t%d: 0x%lx\n", i, exit3[i]->getStartAddress());
		}
		return FAILED;
	}

	for (i = 0; i < (unsigned int) exit3.size(); i++) 
	{
		if (!exit3[i]->postdominates(entry3[0])) 
		{
			logerror("**Failed** test #33 (control flow graphs)\n");
			logerror("  Exit block %d does not postdominate all entry blocks in %s\n", i, fn2);
			return FAILED;
		}
	}
#if !defined(os_windows_test) && defined(ENABLE_PARSE_API_GRAPHS)
	logerror("Testing parseAPI dominators\n");
	
	ParseAPI::Function* parse_func = ParseAPI::convert(func3);
	assert(parse_func);
	Block* parse_entry = parse_func->entry();
	bool parse_idoms_ok = true;
	for(Function::blocklist::const_iterator bl = parse_func->blocks().begin();
	    bl != parse_func->blocks().end();
	    ++bl)
	{
	  if(*bl == parse_entry) continue;
	  if(!dominates(*parse_func, parse_entry, *bl))
	  {
	    parse_idoms_ok = false;
	  }
	}
	if(!parse_idoms_ok)
	{
	  logerror("**Failed** test #33 (CFG)\n");
	  logerror("  ParseAPI dominator algorithm does not have entry block dominating all blocks in function\n");
	  return FAILED;
	}
#endif	
		      

	BPatch_variableExpr *expr33_1 = 
		appImage->findVariable("test1_33_globalVariable1");
	if (expr33_1 == NULL) 
	{
		logerror("**Failed** test #33 (control flow graphs)\n");
		logerror("    Unable to locate test1_33_globalVariable1\n");
		return FAILED;
	} 

	pvalue = 1;
	expr33_1->writeValue(&pvalue);

	return PASSED;
}
Esempio 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;
}
Esempio n. 6
0
void
dyninst_analyze_address_taken(BPatch_addressSpace *handle, DICFG *cfg)
{
	/* XXX: this is the most naive address-taken analysis that can be used by the
         * lbr_analysis_pass. More sophisticated ones can be (and are) plugged in in the pass.
         * This naive solution is provided only for comparison with more sophisticated ones.
	 * 
         * This analysis looks for instruction operands that correspond to known function addresses,
         * and then marks these functions as having their address taken. In particular, we
         * do /not/ look for function pointers stored in (static) memory, or for function
         * pointers that are computed at runtime. 
         */

	SymtabCodeSource *sts;
	CodeObject *co;

	std::vector<BPatch_object*> objs;
	handle->getImage()->getObjects(objs);
	assert(objs.size() > 0);
	const char *bin = objs[0]->pathName().c_str();

	// Create a new binary object 
	sts 	= new SymtabCodeSource((char*)bin);
	co 	= new CodeObject(sts);

	// Parse the binary 
	co->parse(); 

	BPatch_image *image = handle->getImage();
	std::vector<BPatch_module *> *mods = image->getModules();
	std::vector<BPatch_module *>::iterator mods_iter; 
	for (mods_iter = mods->begin(); mods_iter != mods->end(); mods_iter++) {
		std::vector<BPatch_function *> *funcs = (*mods_iter)->getProcedures(false); 
		std::vector<BPatch_function *>::iterator funcs_iter = funcs->begin();
		for(; funcs_iter != funcs->end(); funcs_iter++) {
			co->parse((Address)(*funcs_iter)->getBaseAddr(), true);
			BPatch_flowGraph *fg = (*funcs_iter)->getCFG();
			std::set<BPatch_basicBlock*> blocks;
			fg->getAllBasicBlocks(blocks);
			std::set<BPatch_basicBlock*>::iterator block_iter;
			for (block_iter = blocks.begin(); block_iter != blocks.end(); ++block_iter) {
				BPatch_basicBlock *block = (*block_iter);
				std::vector<Instruction::Ptr> insns;
				block->getInstructions(insns);
				std::vector<Instruction::Ptr>::iterator insn_iter;
				for (insn_iter = insns.begin(); insn_iter != insns.end(); ++insn_iter) {
					Instruction::Ptr ins = *insn_iter;
					std::vector<Operand> ops;
					ins->getOperands(ops);
					std::vector<Operand>::iterator op_iter;
					for (op_iter = ops.begin(); op_iter != ops.end(); ++op_iter) {
						Expression::Ptr expr = (*op_iter).getValue();

						struct OperandAnalyzer : public Dyninst::InstructionAPI::Visitor {
							virtual void visit(BinaryFunction* op) {};
							virtual void visit(Dereference* op) {}
							virtual void visit(Immediate* op) {
								address_t addr;
								ArmsFunction *func;
								switch(op->eval().type) {
								case s32:
									addr = op->eval().val.s32val;
									break;
								case u32:
									addr = op->eval().val.u32val;
									break;
								case s64:
									addr = op->eval().val.s64val;
									break;
								case u64:
									addr = op->eval().val.u64val;
									break;
								default:
									return;
								}
								func = cfg_->find_function(addr);
								if(func) {
									printf("Instruction [%s] references function 0x%jx\n", ins_->format().c_str(), addr);
									func->set_addr_taken();
								}
							}
							virtual void visit(RegisterAST* op) {}
							OperandAnalyzer(DICFG *cfg, Instruction::Ptr ins) {
								cfg_ = cfg;
								ins_ = ins;
							};
							DICFG *cfg_;
							Instruction::Ptr ins_;
						};

						OperandAnalyzer oa(cfg, ins);
						expr->apply(&oa);
					}
				}
			}
		} 
	}
}