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; }
/* * Given a string variable name and an expected value, lookup the varaible * in the process, and verify that the value matches. * */ bool verifyProcMemory(BPatch_thread *appThread, const char *name, int expectedVal, procType proc_type) { BPatch_image *appImage = appThread->getImage(); if (!appImage) { dprintf("unable to locate image for %d\n", appThread->getPid()); return false; } BPatch_variableExpr *var = appImage->findVariable(name); if (!var) { dprintf("unable to located variable %s in child\n", name); return false; } int actualVal; var->readValue(&actualVal); if (expectedVal != actualVal) { fprintf(stderr,"*** for %s (%s), expected val = %d, but actual was %d\n", name, procName[proc_type], expectedVal, actualVal); return false; } else { dprintf("verified %s (%s) was = %d\n", name, procName[proc_type], actualVal); return true; } }
void prepareTestCase6(procType proc_type, BPatch_thread *thread, forkWhen when) { const int TN = 6; if(proc_type == Parent_p && when == PostFork) { BPatch_image *parImage = thread->getImage(); BPatch_variableExpr *var7_6p = parImage->findVariable("globalVariable7_6"); if(doError(TN, (var7_6p==NULL), " Unable to locate variable globalVariable7_6\n")) return; BPatch_arithExpr a_expr7_6p(BPatch_plus, *var7_6p, BPatch_constExpr(5)); BPatch_arithExpr b_expr7_6p(BPatch_assign, *var7_6p, a_expr7_6p); thread->oneTimeCode(b_expr7_6p); } else if(proc_type == Child_p && when == PostFork) { BPatch_image *childImage = thread->getImage(); BPatch_variableExpr *var7_6c = childImage->findVariable("globalVariable7_6"); if(doError(TN, (var7_6c==NULL), " Unable to locate variable globalVariable7_6\n")) return; BPatch_arithExpr a_expr7_6c(BPatch_plus, *var7_6c, BPatch_constExpr(9)); BPatch_arithExpr b_expr7_6c(BPatch_assign, *var7_6c, a_expr7_6c); thread->oneTimeCode(b_expr7_6c); } }
void DICFG::parse_all(void) { BPatch_addressSpace *handle = cfg_handle; SymtabCodeSource *sts = cfg_sts; CodeObject *co = cfg_co; // Parse the binary co->parse(); /* Parse the functions found by the BPatch API */ 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++) { address_t mod_start = (address_t)(*mods_iter)->getBaseAddr(); address_t mod_end = (address_t)(*mods_iter)->getBaseAddr() + (*mods_iter)->getSize(); if((get_start_addr() == 0) || (mod_start < get_start_addr())) { set_start_addr(mod_start); } if((get_end_addr() == 0) || (mod_end > get_end_addr())) { set_end_addr(mod_end); } 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); } } /* Parse PLT entries */ Symtab *symtab = Symtab::findOpenSymtab(string((char *) this->get_module_name().c_str())); vector<SymtabAPI::relocationEntry> fbt; vector<SymtabAPI::relocationEntry>::iterator fbt_iter; symtab->getFuncBindingTable(fbt); for (fbt_iter = fbt.begin(); fbt_iter != fbt.end(); fbt_iter++) { co->parse((Address)((*fbt_iter).target_addr()), true); } const CodeObject::funclist& funcs = co->funcs(); insert_functions_and_bbs(funcs); for (fbt_iter = fbt.begin(); fbt_iter != fbt.end(); fbt_iter++) { address_t plt_fun_addr = (address_t)(*fbt_iter).target_addr(); if((get_start_addr() == 0) || (plt_fun_addr < get_start_addr())) { set_start_addr(plt_fun_addr); } if((get_end_addr() == 0) || (plt_fun_addr > get_end_addr())) { set_end_addr(plt_fun_addr); } mark_function_as_plt(plt_fun_addr); } }
int main() { BPatch bpatch; BPatch_process* appProc = bpatch.processCreate("/bin/ls", NULL); BPatch_image* img = NULL; img = appProc->getImage(); vector<BPatch_module*> *mdl = img->getModules(); vector<BPatch_module*>::iterator moduleIter = mdl->begin(); void* addr = (*moduleIter)->getBaseAddr(); printf("0x%x\n",addr); return 0; }
bool BPatch_image::setFuncModulesCallback(BPatch_function *bpf, void *data) { BPatch_image *img = (BPatch_image *) data; if (bpf->getModule() == NULL && bpf->func->mod() != NULL) { bpf->mod = img->findModule(bpf->func->mod()->fileName().c_str()); } if( bpf->getModule() == NULL ) { char name[256]; fprintf(stderr, "Warning: bpf '%s' unclaimed, setting to DEFAULT_MODULE\n", bpf->getName( name, 255 ) ); bpf->setModule( img->defaultModule ); } return true; }
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); } }
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); } }
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); } }
// Gets the stab and stabstring section and parses it for types // and variables void BPatch_module::parseTypes() { int i, j; int nlines; int nstabs; char* lines; SYMENT *syms; SYMENT *tsym; char *stringPool; char tempName[9]; char *stabstr=NULL; union auxent *aux; image * imgPtr=NULL; pdstring funcName; Address staticBlockBaseAddr = 0; unsigned long linesfdptr; BPatch_typeCommon *commonBlock = NULL; BPatch_variableExpr *commonBlockVar = NULL; pdstring currentSourceFile; bool inCommonBlock = false; #if defined(TIMED_PARSE) struct timeval starttime; gettimeofday(&starttime, NULL); #endif imgPtr = mod->obj()->parse_img(); const Object &objPtr = imgPtr->getObject(); //Using the Object to get the pointers to the .stab and .stabstr objPtr.get_stab_info(stabstr, nstabs, syms, stringPool); objPtr.get_line_info(nlines,lines,linesfdptr); bool parseActive = true; //fprintf(stderr, "%s[%d]: parseTypes for module %s: nstabs = %d\n", FILE__, __LINE__,mod->fileName().c_str(),nstabs); //int num_active = 0; for (i=0; i < nstabs; i++) { /* do the pointer addition by hand since sizeof(struct syment) * seems to be 20 not 18 as it should be */ SYMENT *sym = (SYMENT *) (((unsigned) syms) + i * SYMESZ); // SYMENT *sym = (SYMENT *) (((unsigned) syms) + i * sizeof(struct syment)); if (sym->n_sclass == C_FILE) { char *moduleName; if (!sym->n_zeroes) { moduleName = &stringPool[sym->n_offset]; } else { memset(tempName, 0, 9); strncpy(tempName, sym->n_name, 8); moduleName = tempName; } /* look in aux records */ for (j=1; j <= sym->n_numaux; j++) { aux = (union auxent *) ((char *) sym + j * SYMESZ); if (aux->x_file._x.x_ftype == XFT_FN) { if (!aux->x_file._x.x_zeroes) { moduleName = &stringPool[aux->x_file._x.x_offset]; } else { // x_fname is 14 bytes memset(moduleName, 0, 15); strncpy(moduleName, aux->x_file.x_fname, 14); } } } currentSourceFile = pdstring(moduleName); currentSourceFile = mod->processDirectories(currentSourceFile); if (strrchr(moduleName, '/')) { moduleName = strrchr(moduleName, '/'); moduleName++; } if (!strcmp(moduleName, mod->fileName().c_str())) { parseActive = true; // Clear out old types moduleTypes->clearNumberedTypes(); } else { parseActive = false; } } if (!parseActive) continue; //num_active++; char *nmPtr; if (!sym->n_zeroes && ((sym->n_sclass & DBXMASK) || (sym->n_sclass == C_BINCL) || (sym->n_sclass == C_EINCL))) { if (sym->n_offset < 3) { if (sym->n_offset == 2 && stabstr[0]) { nmPtr = &stabstr[0]; } else { nmPtr = &stabstr[sym->n_offset]; } } else if (!stabstr[sym->n_offset-3]) { nmPtr = &stabstr[sym->n_offset]; } else { /* has off by two error */ nmPtr = &stabstr[sym->n_offset-2]; } #ifdef notdef bperr("using nmPtr = %s\n", nmPtr); bperr("got n_offset = (%d) %s\n", sym->n_offset, &stabstr[sym->n_offset]); if (sym->n_offset>=2) bperr("got n_offset-2 = %s\n", &stabstr[sym->n_offset-2]); if (sym->n_offset>=3) bperr("got n_offset-3 = %x\n", stabstr[sym->n_offset-3]); if (sym->n_offset>=4) bperr("got n_offset-4 = %x\n", stabstr[sym->n_offset-4]); #endif } else { // names 8 or less chars on inline, not in stabstr memset(tempName, 0, 9); strncpy(tempName, sym->n_name, 8); nmPtr = tempName; } if ((sym->n_sclass == C_BINCL) || (sym->n_sclass == C_EINCL) || (sym->n_sclass == C_FUN)) { funcName = nmPtr; /* The call to parseLineInformation(), below, used to modify the symbols passed to it. */ if (funcName.find(":") < funcName.length()) funcName = funcName.substr(0,funcName.find(":")); // I'm not sure why we bother with this here, since we fetch line numbers in symtab.C anyway. // mod->parseLineInformation(proc->llproc, currentSourceFile, // funcName, sym, // linesfdptr, lines, nlines); } if (sym->n_sclass & DBXMASK) { if (sym->n_sclass == C_BCOMM) { char *commonBlockName; inCommonBlock = true; commonBlockName = nmPtr; // find the variable for the common block BPatch_image *progam = (BPatch_image *) getObjParent(); commonBlockVar = progam->findVariable(commonBlockName); if (!commonBlockVar) { bperr("unable to find variable %s\n", commonBlockName); } else { commonBlock = dynamic_cast<BPatch_typeCommon *>(const_cast<BPatch_type *> (commonBlockVar->getType())); if (commonBlock == NULL) { // its still the null type, create a new one for it commonBlock = new BPatch_typeCommon(commonBlockName); commonBlockVar->setType(commonBlock); moduleTypes->addGlobalVariable(commonBlockName, commonBlock); } // reset field list commonBlock->beginCommonBlock(); } } else if (sym->n_sclass == C_ECOMM) { inCommonBlock = false; if (commonBlock == NULL) continue; // copy this set of fields BPatch_Vector<BPatch_function *> bpmv; if (NULL == findFunction(funcName.c_str(), bpmv) || !bpmv.size()) { bperr("unable to locate current function %s\n", funcName.c_str()); } else { BPatch_function *func = bpmv[0]; commonBlock->endCommonBlock(func, commonBlockVar->getBaseAddr()); } // update size if needed if (commonBlockVar) commonBlockVar->setSize(commonBlock->getSize()); commonBlockVar = NULL; commonBlock = NULL; } else if (sym->n_sclass == C_BSTAT) { // begin static block // find the variable for the common block tsym = (SYMENT *) (((unsigned) syms) + sym->n_value * SYMESZ); // We can't lookup the value by name, because the name might have been // redefined later on (our lookup would then pick the last one) // Since this whole function is AIX only, we're ok to get this info staticBlockBaseAddr = tsym->n_value; /* char *staticName, tempName[9]; if (!tsym->n_zeroes) { staticName = &stringPool[tsym->n_offset]; } else { memset(tempName, 0, 9); strncpy(tempName, tsym->n_name, 8); staticName = tempName; } BPatch_image *progam = (BPatch_image *) getObjParent(); BPatch_variableExpr *staticBlockVar = progam->findVariable(staticName); if (!staticBlockVar) { bperr("unable to find static block %s\n", staticName); staticBlockBaseAddr = 0; } else { staticBlockBaseAddr = (Address) staticBlockVar->getBaseAddr(); } */ } else if (sym->n_sclass == C_ESTAT) { staticBlockBaseAddr = 0; } // There's a possibility that we were parsing a common block that // was never instantiated (meaning there's type info, but no // variable info if (inCommonBlock && commonBlock == NULL) continue; if (staticBlockBaseAddr && (sym->n_sclass == C_STSYM)) { parseStabString(this, 0, nmPtr, sym->n_value+staticBlockBaseAddr, commonBlock); } else { parseStabString(this, 0, nmPtr, sym->n_value, commonBlock); } } } #if defined(TIMED_PARSE) struct timeval endtime; gettimeofday(&endtime, NULL); unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec; unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec; unsigned long difftime = lendtime - lstarttime; double dursecs = difftime/(1000 ); cout << __FILE__ << ":" << __LINE__ <<": parseTypes("<< mod->fileName() <<") took "<<dursecs <<" msecs" << endl; #endif // fprintf(stderr, "%s[%d]: parseTypes for %s, num_active = %d\n", FILE__, __LINE__, mod->fileName().c_str(), num_active); }
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; } } } }
// static int mutatorTest(char *pathname, BPatch *bpatch) test_results_t test1_41_Mutator::executeTest() { unsigned int n=0; const char *child_argv[5]; child_argv[n++] = pathname; if (debugPrint) child_argv[n++] = const_cast<char*>("-verbose"); child_argv[n++] = const_cast<char*>("-run"); child_argv[n++] = const_cast<char*>("test1_41"); // run test41 in mutatee child_argv[n++] = NULL; int counts[iterations]; // Run the mutatee twice, querying line info each time & store the info for (n = 0; n < iterations; n++) { dprintf("Starting \"%s\"\n", pathname); BPatch_process *proc = bpatch->processCreate(pathname, child_argv, NULL); if (!proc) { logerror("*ERROR*: unable to create handle for executable\n", n); logerror("**Failed** test #41 (repeated line information)\n"); return FAILED; } dprintf("Mutatee started, pid=%d\n", n, proc->getPid()); BPatch_image *image = proc->getImage(); if (!image) { logerror("*ERROR*: unable to get image from thread\n"); logerror("**Failed** test #41 (repeated line information)\n"); return FAILED; } if (isMutateeFortran(image)) { // This shouldn't happen.. proc->terminateExecution(); logerror("Skipped test #41 (repeated line information)\n"); return SKIPPED; } BPatch_module *module = image->findModule("test1_41_mutatee.c", true); if (!module) { module = image->findModule("solo_mutatee_boilerplate.c", true); if (true) { logerror("*ERROR*: unable to get module from image\n"); logerror("Looking for \"test1_41_solo_me.c\" or \"solo_mutatee_boilerplate.c\". Available modules:\n"); BPatch_Vector<BPatch_module *> *mods = image->getModules(); char buffer[512]; for (unsigned i = 0; i < mods->size(); i++) { BPatch_module *mod = (*mods)[i]; char name[512]; mod->getName(name, 512); sprintf(buffer, "\t%s\n", name); logerror(buffer); } } } if (!module) { fprintf(stderr, "%s[%d]: could not find module solo_mutatee_boilerplate.c\n", FILE__, __LINE__); // First try again for 'test1_41_solo_me.c' module = image->findModule("test1_41_solo_me.c", true); if (!module) { logerror("*ERROR*: unable to get module from image\n"); logerror("Looking for \"test1_41_solo_me.c\" or \"solo_mutatee_boilerplate.c\". Available modules:\n"); BPatch_Vector<BPatch_module *> *mods = image->getModules(); char buffer[512]; for (unsigned i = 0; i < mods->size(); i++) { BPatch_module *mod = (*mods)[i]; char name[512]; mod->getName(name, 512); sprintf(buffer, "\t%s\n", name); logerror(buffer); } logerror("**Failed** test #41 (repeated line information)\n"); return FAILED; } } char buffer[16384]; // FIXME ugly magic number; No module name should be that long.. module->getName(buffer, sizeof(buffer)); BPatch_Vector<BPatch_statement> statements; bool res = module->getStatements(statements); if (!res) { fprintf(stderr, "%s[%d]: getStatements()\n", __FILE__, __LINE__); return FAILED; } counts[n] = statements.size(); dprintf("Trial %d: found %d statements\n", n, statements.size()); proc->terminateExecution(); } // Make sure we got the same info each time we ran the mutatee int last_count = -1; for (int i = 0; i < iterations; i++) { if ((last_count >= 0) && (last_count != counts[i])) { logerror("*ERROR*: statement counts didn't match: %d vs. %d\n", last_count, counts[i]); logerror("**Failed** test #41 (repeated line information)\n"); return FAILED; } last_count = counts[i]; } logerror("Passed test #41 (repeated line information)\n"); return PASSED; }
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()); } }
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; } }
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; }
int main (int argc, char **argv) { if(!parseOptions(argc,argv)) { return EXIT_FAILURE; } BPatch bpatch; BPatch_binaryEdit *appBin = bpatch.openBinary (originalBinary, !instrumentLibraries.empty()); if (appBin == NULL) { cerr << "Failed to open binary" << endl; return EXIT_FAILURE; } if (!appBin->loadLibrary (instLibrary)) { cerr << "Failed to open instrumentation library." << endl; cerr << "It needs to be located in the current working directory." << endl; return EXIT_FAILURE; } BPatch_image *appImage = appBin->getImage (); /* Find code coverage functions in the instrumentation library */ BPatch_function *initAflForkServer = findFuncByName (appImage, (char *) "initAflForkServer"); BPatch_function *bbCallback = findFuncByName (appImage, (char *) "bbCallback"); if (!initAflForkServer || !bbCallback ) { cerr << "Instrumentation library lacks callbacks!" << endl; return EXIT_FAILURE; } //get and iterate over all modules, instrumenting only the default and manualy specified ones vector < BPatch_module * >*modules = appImage->getModules (); vector < BPatch_module * >::iterator moduleIter; BPatch_module *defaultModule = NULL; string defaultModuleName; for (moduleIter = modules->begin (); moduleIter != modules->end (); ++moduleIter) { //find default module name char moduleName[1024]; (*moduleIter)->getName (moduleName, 1024); if (string (moduleName).find ("DEFAULT_MODULE") != string::npos) { defaultModuleName = "DEFAULT_MODULE"; } } if(defaultModuleName.empty()) defaultModuleName = string(originalBinary).substr(string(originalBinary).find_last_of("\\/")+1); int bbIndex = 0; for (moduleIter = modules->begin (); moduleIter != modules->end (); ++moduleIter) { char moduleName[1024]; (*moduleIter)->getName (moduleName, 1024); if ((*moduleIter)->isSharedLib ()) { if (instrumentLibraries.find (moduleName) == instrumentLibraries.end ()) { cout << "Skipping library: " << moduleName << endl; continue; } } if (string (moduleName).find (defaultModuleName) != string::npos) { defaultModule = (*moduleIter); if(skipMainModule) continue; } cout << "Instrumenting module: " << moduleName << endl; vector < BPatch_function * >*allFunctions = (*moduleIter)->getProcedures (); vector < BPatch_function * >::iterator funcIter; // iterate over all functions in the module for (funcIter = allFunctions->begin (); funcIter != allFunctions->end (); ++funcIter) { BPatch_function *curFunc = *funcIter; char funcName[1024]; curFunc->getName (funcName, 1024); if(string (funcName) == string("_start")) continue; // here's a bug on hlt insertBBCallback (appBin, curFunc, funcName, bbCallback, &bbIndex); } } //if entrypoint set ,find function , else find _init BPatch_function *funcToPatch = NULL; if(!entryPoint) { BPatch_Vector<BPatch_function*> funcs; defaultModule->findFunction("_init", funcs); if(!funcs.size()) { cerr << "Couldn't locate _init, specify entry point manualy. "<< endl; return EXIT_FAILURE; } // there should really be only one funcToPatch = funcs[0]; } else { funcToPatch = defaultModule->findFunctionByEntry(entryPoint); } if(!funcToPatch) { cerr << "Couldn't locate function at given entry point. "<< endl; return EXIT_FAILURE; } if(!insertCallToInit (appBin, initAflForkServer,defaultModule,funcToPatch)){ cerr << "Could not insert init callback at given entry point." << endl; return EXIT_FAILURE; } cout << "Saving the instrumented binary to " << instrumentedBinary << "..." << endl; // Output the instrumented binary if (!appBin->writeFile (instrumentedBinary)) { cerr << "Failed to write output file: " << instrumentedBinary << endl; return EXIT_FAILURE; } if(!runtimeLibraries.empty()) { cout << "Instrumenting runtime libraries." << endl; set<string>::iterator rtLibIter ; for(rtLibIter = runtimeLibraries.begin(); rtLibIter != runtimeLibraries.end(); rtLibIter++) { BPatch_binaryEdit *libBin = bpatch.openBinary ((*rtLibIter).c_str(), false); if (libBin == NULL) { cerr << "Failed to open binary "<< *rtLibIter << endl; return EXIT_FAILURE; } libBin->loadLibrary (instLibrary); BPatch_image *libImg = libBin->getImage (); vector < BPatch_module * >*modules = libImg->getModules (); moduleIter = modules->begin (); ++moduleIter; for ( ; moduleIter != modules->end (); ++moduleIter) { char moduleName[1024]; (*moduleIter)->getName (moduleName, 1024); cout << "Instrumenting module: " << moduleName << endl; vector < BPatch_function * >*allFunctions = (*moduleIter)->getProcedures (); vector < BPatch_function * >::iterator funcIter; // iterate over all functions in the module for (funcIter = allFunctions->begin (); funcIter != allFunctions->end (); ++funcIter) { BPatch_function *curFunc = *funcIter; char funcName[1024]; curFunc->getName (funcName, 1024); if(string (funcName) == string("_start")) continue; insertBBCallback (libBin, curFunc, funcName, bbCallback, &bbIndex); } } if (!libBin->writeFile ((*rtLibIter + ".ins").c_str())) { cerr << "Failed to write output file: " <<(*rtLibIter + ".ins").c_str() << endl; return EXIT_FAILURE; } else { cout << "Saved the instrumented library to " << (*rtLibIter + ".ins").c_str() << "." << endl; } } } cout << "All done! Happy fuzzing!" << endl; return EXIT_SUCCESS; }
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); } } } } } }
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); } }
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; }
// 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; }
// parseStabTypes: parses type and variable info, does some init // does NOT parse file-line info anymore, this is done later, upon request. void BPatch_module::parseStabTypes() { stab_entry *stabptr; const char *next_stabstr; unsigned i; char *modName; pdstring temp; image * imgPtr=NULL; char *ptr, *ptr2, *ptr3; bool parseActive = false; pdstring* currentFunctionName = NULL; Address currentFunctionBase = 0; BPatch_variableExpr *commonBlockVar = NULL; char *commonBlockName; BPatch_typeCommon *commonBlock = NULL; int mostRecentLinenum = 0; #if defined(TIMED_PARSE) struct timeval starttime; gettimeofday(&starttime, NULL); unsigned int pss_count = 0; double pss_dur = 0; unsigned int src_count = 0; double src_dur = 0; unsigned int fun_count = 0; double fun_dur = 0; struct timeval t1, t2; #endif imgPtr = mod->obj()->parse_img(); imgPtr->analyzeIfNeeded(); const Object &objPtr = imgPtr->getObject(); //Using the Object to get the pointers to the .stab and .stabstr // XXX - Elf32 specific needs to be in seperate file -- jkh 3/18/99 stabptr = objPtr.get_stab_info(); next_stabstr = stabptr->getStringBase(); for (i=0; i<stabptr->count(); i++) { switch(stabptr->type(i)){ case N_UNDF: /* start of object file */ /* value contains offset of the next string table for next module */ // assert(stabptr->nameIdx(i) == 1); stabptr->setStringBase(next_stabstr); next_stabstr = stabptr->getStringBase() + stabptr->val(i); //N_UNDF is the start of object file. It is time to //clean source file name at this moment. /* if(currentSourceFile){ delete currentSourceFile; currentSourceFile = NULL; delete absoluteDirectory; absoluteDirectory = NULL; delete currentFunctionName; currentFunctionName = NULL; currentFileInfo = NULL; currentFuncInfo = NULL; } */ break; case N_ENDM: /* end of object file */ break; case N_SO: /* compilation source or file name */ /* bperr("Resetting CURRENT FUNCTION NAME FOR NEXT OBJECT FILE\n");*/ #ifdef TIMED_PARSE src_count++; gettimeofday(&t1, NULL); #endif current_func_name = ""; // reset for next object file current_mangled_func_name = ""; // reset for next object file current_func = NULL; modName = const_cast<char*>(stabptr->name(i)); // cerr << "checkpoint B" << endl; ptr = strrchr(modName, '/'); // cerr << "checkpoint C" << endl; if (ptr) { ptr++; modName = ptr; } if (!strcmp(modName, mod->fileName().c_str())) { parseActive = true; moduleTypes->clearNumberedTypes(); BPatch_language lang; // language should be set in the constructor, this is probably redundant switch (stabptr->desc(i)) { case N_SO_FORTRAN: lang = BPatch_fortran; break; case N_SO_F90: lang = BPatch_fortran90; break; case N_SO_AS: lang = BPatch_assembly; break; case N_SO_ANSI_C: case N_SO_C: lang = BPatch_c; break; case N_SO_CC: lang = BPatch_cPlusPlus; break; default: lang = BPatch_unknownLanguage; break; } if (BPatch_f90_demangled_stabstr != getLanguage()) setLanguage(lang); } else { parseActive = false; } #ifdef TIMED_PARSE gettimeofday(&t2, NULL); src_dur += (t2.tv_sec - t1.tv_sec)*1000.0 + (t2.tv_usec - t1.tv_usec)/1000.0; //src_dur += (t2.tv_sec/1000 + t2.tv_usec*1000) - (t1.tv_sec/1000 + t1.tv_usec*1000) ; #endif break; case N_SLINE: mostRecentLinenum = stabptr->desc(i); break; default: break; } if(parseActive || mod->obj()->isSharedLib()) { BPatch_Vector<BPatch_function *> bpfv; switch(stabptr->type(i)){ case N_FUN: #ifdef TIMED_PARSE fun_count++; gettimeofday(&t1, NULL); #endif //all we have to do with function stabs at this point is to assure that we have //properly set the var currentFunctionName for the later case of (parseActive) current_func = NULL; int currentEntry = i; int funlen = strlen(stabptr->name(currentEntry)); ptr = new char[funlen+1]; strcpy(ptr, stabptr->name(currentEntry)); while(strlen(ptr) != 0 && ptr[strlen(ptr)-1] == '\\'){ ptr[strlen(ptr)-1] = '\0'; currentEntry++; strcat(ptr,stabptr->name(currentEntry)); } char* colonPtr = NULL; if(currentFunctionName) delete currentFunctionName; if(!ptr || !(colonPtr = strchr(ptr,':'))) currentFunctionName = NULL; else { char* tmp = new char[colonPtr-ptr+1]; strncpy(tmp,ptr,colonPtr-ptr); tmp[colonPtr-ptr] = '\0'; currentFunctionName = new pdstring(tmp); currentFunctionBase = 0; Symbol info; // Shouldn't this be a function name lookup? if (!proc->llproc->getSymbolInfo(*currentFunctionName, info)) { pdstring fortranName = *currentFunctionName + pdstring("_"); if (proc->llproc->getSymbolInfo(fortranName,info)) { delete currentFunctionName; currentFunctionName = new pdstring(fortranName); } } currentFunctionBase = info.addr(); delete[] tmp; // if(currentSourceFile && (currentFunctionBase > 0)){ // lineInformation->insertSourceFileName( // *currentFunctionName, // *currentSourceFile, // ¤tFileInfo,¤tFuncInfo); //} } // used to be a symbol lookup here to find currentFunctionBase, do we need it? delete[] ptr; #ifdef TIMED_PARSE gettimeofday(&t2, NULL); fun_dur += (t2.tv_sec - t1.tv_sec)*1000.0 + (t2.tv_usec - t1.tv_usec)/1000.0; //fun_dur += (t2.tv_sec/1000 + t2.tv_usec*1000) - (t1.tv_sec/1000 + t1.tv_usec*1000); #endif break; } if (!parseActive) continue; switch(stabptr->type(i)){ case N_BCOMM: { // begin Fortran named common block commonBlockName = const_cast<char*>(stabptr->name(i)); // find the variable for the common block BPatch_image *progam = (BPatch_image *) getObjParent(); commonBlockVar = progam->findVariable(commonBlockName); if (!commonBlockVar) { bperr("unable to find variable %s\n", commonBlockName); } else { commonBlock = dynamic_cast<BPatch_typeCommon *>(const_cast<BPatch_type *> (commonBlockVar->getType())); if (commonBlock == NULL) { // its still the null type, create a new one for it commonBlock = new BPatch_typeCommon(commonBlockName); commonBlockVar->setType(commonBlock); moduleTypes->addGlobalVariable(commonBlockName, commonBlock); } // reset field list commonBlock->beginCommonBlock(); } break; } case N_ECOMM: { // copy this set of fields assert(currentFunctionName); if (NULL == findFunction(currentFunctionName->c_str(), bpfv) || !bpfv.size()) { bperr("unable to locate current function %s\n", currentFunctionName->c_str()); } else { if (bpfv.size() > 1) { // warn if we find more than one function with this name bperr("%s[%d]: WARNING: found %d funcs matching name %s, using the first\n", __FILE__, __LINE__, bpfv.size(), currentFunctionName->c_str()); } BPatch_function *func = bpfv[0]; commonBlock->endCommonBlock(func, commonBlockVar->getBaseAddr()); } // update size if needed if (commonBlockVar) commonBlockVar->setSize(commonBlock->getSize()); commonBlockVar = NULL; commonBlock = NULL; break; } // case C_BINCL: -- what is the elf version of this jkh 8/21/01 // case C_EINCL: -- what is the elf version of this jkh 8/21/01 case 32: // Global symbols -- N_GYSM case 38: // Global Static -- N_STSYM case N_FUN: case 128: // typedefs and variables -- N_LSYM case 160: // parameter variable -- N_PSYM case 0xc6: // position-independant local typedefs -- N_ISYM case 0xc8: // position-independant external typedefs -- N_ESYM #ifdef TIMED_PARSE pss_count++; gettimeofday(&t1, NULL); #endif if (stabptr->type(i) == N_FUN) current_func = NULL; ptr = const_cast<char *>(stabptr->name(i)); while (ptr[strlen(ptr)-1] == '\\') { //ptr[strlen(ptr)-1] = '\0'; ptr2 = const_cast<char *>(stabptr->name(i+1)); ptr3 = (char *) malloc(strlen(ptr) + strlen(ptr2)); strcpy(ptr3, ptr); ptr3[strlen(ptr)-1] = '\0'; strcat(ptr3, ptr2); ptr = ptr3; i++; // XXX - memory leak on multiple cont. lines } // bperr("stab #%d = %s\n", i, ptr); // may be nothing to parse - XXX jdd 5/13/99 if (nativeCompiler) temp = parseStabString(this, mostRecentLinenum, (char *)ptr, stabptr->val(i), commonBlock); else temp = parseStabString(this, stabptr->desc(i), (char *)ptr, stabptr->val(i), commonBlock); if (temp.length()) { //Error parsing the stabstr, return should be \0 bperr( "Stab string parsing ERROR!! More to parse: %s\n", temp.c_str()); bperr( " symbol: %s\n", ptr); } #ifdef TIMED_PARSE gettimeofday(&t2, NULL); pss_dur += (t2.tv_sec - t1.tv_sec)*1000.0 + (t2.tv_usec - t1.tv_usec)/1000.0; // pss_dur += (t2.tv_sec/1000 + t2.tv_usec*1000) - (t1.tv_sec/1000 + t1.tv_usec*1000); #endif break; default: break; } } } #if defined(TIMED_PARSE) struct timeval endtime; gettimeofday(&endtime, NULL); unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec; unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec; unsigned long difftime = lendtime - lstarttime; double dursecs = difftime/(1000 ); cout << __FILE__ << ":" << __LINE__ <<": parseTypes("<< mod->fileName() <<") took "<<dursecs <<" msecs" << endl; cout << "Breakdown:" << endl; cout << " Functions: " << fun_count << " took " << fun_dur << "msec" << endl; cout << " Sources: " << src_count << " took " << src_dur << "msec" << endl; cout << " parseStabString: " << pss_count << " took " << pss_dur << "msec" << endl; cout << " Total: " << pss_dur + fun_dur + src_dur << " msec" << endl; #endif }
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); */ }
int main(int argc, char **argv) { if (argc < 3 || strncmp(argv[1], "-h", 2) == 0 || strncmp(argv[1], "--h", 3) == 0) { cout << "Usage: " << argv[0] << USAGE; return false; } if (!parseOptions(argc, argv)) { return EXIT_FAILURE; } if (do_bb == true) { if (DYNINST_MAJOR_VERSION < 9 || (DYNINST_MAJOR_VERSION == 9 && DYNINST_MINOR_VERSION < 3) || (DYNINST_MAJOR_VERSION == 9 && DYNINST_MINOR_VERSION == 3 && DYNINST_PATCH_VERSION <= 2)) { if (dynfix == false) fprintf(stderr, "Warning: your dyninst version does not include a critical fix, you should use the -f option!\n"); } else { if (dynfix == true) fprintf(stderr, "Notice: your dyninst version is fixed, the -f option should not be necessary.\n"); } } BPatch bpatch; BPatch_binaryEdit *appBin = bpatch.openBinary(originalBinary, instrumentLibraries.size() != 1); if (appBin == NULL) { cerr << "Failed to open binary" << endl; return EXIT_FAILURE; } BPatch_image *appImage = appBin->getImage(); //get and iterate over all modules, instrumenting only the default and manually specified ones vector < BPatch_module * >*modules = appImage->getModules(); vector < BPatch_module * >::iterator moduleIter; vector < BPatch_function * >*funcsInModule; BPatch_module *defaultModule = NULL; string defaultModuleName; // look for _init if (defaultModuleName.empty()) { for (moduleIter = modules->begin(); moduleIter != modules->end(); ++moduleIter) { funcsInModule = (*moduleIter)->getProcedures(); vector < BPatch_function * >::iterator funcsIterator; for (funcsIterator = funcsInModule->begin(); funcsIterator != funcsInModule->end(); ++funcsIterator) { char funcName[1024]; (*funcsIterator)->getName(funcName, 1024); if (string(funcName) == string("_init")) { char moduleName[1024]; (*moduleIter)->getName(moduleName, 1024); defaultModuleName = string(moduleName); if (verbose) { cout << "Found _init in " << moduleName << endl; } break; } } if (!defaultModuleName.empty()) break; } } // last resort, by name of the binary if (defaultModuleName.empty()) defaultModuleName = string(originalBinary).substr(string(originalBinary).find_last_of("\\/") + 1); if (!appBin->loadLibrary(instLibrary)) { cerr << "Failed to open instrumentation library " << instLibrary << endl; cerr << "It needs to be located in the current working directory." << endl; return EXIT_FAILURE; } appImage = appBin->getImage(); /* Find code coverage functions in the instrumentation library */ BPatch_function *initAflForkServer; save_rdi = findFuncByName(appImage, (char *) "save_rdi"); restore_rdi = findFuncByName(appImage, (char *) "restore_rdi"); BPatch_function *bbCallback = findFuncByName(appImage, (char *) "bbCallback"); BPatch_function *forceCleanExit = findFuncByName(appImage, (char *) "forceCleanExit"); if (do_bb == true) initAflForkServer = findFuncByName(appImage, (char *) "initAflForkServer"); else initAflForkServer = findFuncByName(appImage, (char *) "initOnlyAflForkServer"); if (!initAflForkServer || !bbCallback || !save_rdi || !restore_rdi || !forceCleanExit) { cerr << "Instrumentation library lacks callbacks!" << endl; return EXIT_FAILURE; } int bbIndex = 0; // instrument all shared libraries: for (moduleIter = modules->begin(); moduleIter != modules->end(); ++moduleIter) { char moduleName[1024]; (*moduleIter)->getName(moduleName, 1024); if ((*moduleIter)->isSharedLib()) { if (instrumentLibraries.find(moduleName) == instrumentLibraries.end()) { cout << "Skipping library: " << moduleName << endl; continue; } } if (string(moduleName).find(defaultModuleName) != string::npos) { defaultModule = (*moduleIter); if (skipMainModule) continue; } if (do_bb == true) { cout << "Instrumenting module: " << moduleName << endl; vector < BPatch_function * >*allFunctions = (*moduleIter)->getProcedures(); vector < BPatch_function * >::iterator funcIter; // iterate over all functions in the module for (funcIter = allFunctions->begin(); funcIter != allFunctions->end(); ++funcIter) { BPatch_function *curFunc = *funcIter; char funcName[1024]; int do_patch = 1; curFunc->getName(funcName, 1024); if (string(funcName) == string("_start")) continue; // here's a bug on hlt // XXX: check what happens if removed if (!skipAddresses.empty()) { set < string >::iterator saiter; for (saiter = skipAddresses.begin(); saiter != skipAddresses.end() && do_patch == 1; saiter++) if (*saiter == string(funcName)) do_patch = 0; if (do_patch == 0) { cout << "Skipping instrumenting function " << funcName << endl; continue; } } insertBBCallback(appBin, curFunc, funcName, bbCallback, &bbIndex); } } } // if an entrypoint was set then find function, else find _init BPatch_function *funcToPatch = NULL; if (!entryPoint) { BPatch_Vector < BPatch_function * >funcs; defaultModule->findFunction("_init", funcs); if (!funcs.size()) { cerr << "Couldn't locate _init, specify entry point manually with -e 0xaddr" << endl; return EXIT_FAILURE; } // there should really be only one funcToPatch = funcs[0]; } else { funcToPatch = defaultModule->findFunctionByEntry(entryPoint); } if (!funcToPatch) { cerr << "Couldn't locate function at given entry point. " << endl; return EXIT_FAILURE; } if (!insertCallToInit(appBin, initAflForkServer, defaultModule, funcToPatch)) { cerr << "Could not insert init callback at given entry point." << endl; return EXIT_FAILURE; } if (!exitAddresses.empty()) { cout << "Instrumenting forced exit addresses." << endl; set < unsigned long >::iterator uliter; for (uliter = exitAddresses.begin(); uliter != exitAddresses.end(); uliter++) { if (*uliter > 0 && (signed long)*uliter != -1) { funcToPatch = defaultModule->findFunctionByEntry(*uliter); if (!funcToPatch) { cerr << "Could not find enty point 0x" << hex << *uliter << " (continuing)" << endl; } else { if (!insertCallToInit(appBin, forceCleanExit, defaultModule, funcToPatch)) cerr << "Could not insert force clean exit callback at 0x" << hex << *uliter << " (continuing)" << endl; } } } } cout << "Saving the instrumented binary to " << instrumentedBinary << " ..." << endl; // Output the instrumented binary if (!appBin->writeFile(instrumentedBinary)) { cerr << "Failed to write output file: " << instrumentedBinary << endl; return EXIT_FAILURE; } if (!runtimeLibraries.empty()) { cout << "Instrumenting runtime libraries." << endl; set < string >::iterator rtLibIter; for (rtLibIter = runtimeLibraries.begin(); rtLibIter != runtimeLibraries.end(); rtLibIter++) { BPatch_binaryEdit *libBin = bpatch.openBinary((*rtLibIter).c_str(), false); if (libBin == NULL) { cerr << "Failed to open binary " << *rtLibIter << endl; return EXIT_FAILURE; } BPatch_image *libImg = libBin->getImage(); vector < BPatch_module * >*modules = libImg->getModules(); moduleIter = modules->begin(); for (; moduleIter != modules->end(); ++moduleIter) { char moduleName[1024]; (*moduleIter)->getName(moduleName, 1024); cout << "Instrumenting module: " << moduleName << endl; vector < BPatch_function * >*allFunctions = (*moduleIter)->getProcedures(); vector < BPatch_function * >::iterator funcIter; // iterate over all functions in the module for (funcIter = allFunctions->begin(); funcIter != allFunctions->end(); ++funcIter) { BPatch_function *curFunc = *funcIter; char funcName[1024]; curFunc->getName(funcName, 1024); if (string(funcName) == string("_start")) continue; insertBBCallback(libBin, curFunc, funcName, bbCallback, &bbIndex); } } if (!libBin->writeFile((*rtLibIter + ".ins").c_str())) { cerr << "Failed to write output file: " << (*rtLibIter + ".ins").c_str() << endl; return EXIT_FAILURE; } else { cout << "Saved the instrumented library to " << (*rtLibIter + ".ins").c_str() << "." << endl; } } } cout << "All done! Happy fuzzing!" << endl; return EXIT_SUCCESS; }