static int setVar40(const char *vname, void *value, BPatch_image *appImage) { BPatch_variableExpr *v; void *buf = value; if (NULL == (v = appImage->findVariable(vname))) { logerror("**Failed test #40 (monitor call sites)\n"); logerror(" cannot find variable %s\n", vname); return -1; } // Get around endianness on cross address-width mutators. // Note: Can't use reinterpret_cast here. G++ produces an error: // reinterpret_cast from `void*' to `unsigned int' loses precision unsigned long longAddr = (unsigned long)(value); unsigned int shortAddr = (unsigned int)(unsigned long)(value); switch (v->getSize()) { case 4: buf = reinterpret_cast<void *>(&shortAddr); break; case 8: buf = reinterpret_cast<void *>(&longAddr); break; default: assert(0 && "Invalid size of mutatee address variable"); } // Done silly casting magic. Write the value. if (! v->writeValue(buf, sizeof(unsigned int),false)) { logerror("**Failed test #40 (monitor call sites)\n"); logerror(" failed to write call site var to mutatee\n"); return -1; } 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; } }
bool BPatch_addressSpace::free(BPatch_variableExpr &ptr) { if(ptr.intvar) { // kill the symbols } ptr.getAS()->inferiorFree((Address)ptr.getBaseAddr()); return true; }
// Returns true on error, false on success bool test_thread_2_Mutator::getVar(const char *vname, void *addr, int len, int testno, const char *testname) { BPatch_variableExpr *v; if (NULL == (v = appImage->findVariable(vname))) { logerror("**Failed test #%d (%s)\n", testno, testname); logerror(" cannot find variable %s: avail vars:\n", vname); dumpVars(); return true; } if (! v->readValue(addr, len)) { logerror("**Failed test #%d (%s)\n", testno, testname); logerror(" failed to read var in mutatee\n"); return true; } return false; // No error }
// Returns true on error, false on success bool test_thread_2_Mutator::setVar(const char *vname, void *addr, int testno, const char *testname) { BPatch_variableExpr *v; void *buf = addr; if (NULL == (v = appImage->findVariable(vname))) { logerror("**Failed test #%d (%s)\n", testno, testname); logerror(" cannot find variable %s, avail vars:\n", vname); dumpVars(); return true; } if (! v->writeValue(buf, sizeof(int),true)) { logerror("**Failed test #%d (%s)\n", testno, testname); logerror(" failed to write call site var to mutatee\n"); return true; } return false; // No error }
BPatch_snippet *SnippetGenerator::findOrCreateVariable(const char * name, const char * type, const void * initialValue){ lastError.str() = ""; int zero = 0; if(initialValue == NULL){ //expand? if (strcmp(type, "int") == 0) initialValue = &zero; if (strcmp(type, "char *") == 0) initialValue = ""; } BPatch_variableExpr *varExpr = image->findVariable(name, false); if(varExpr != NULL){ return varExpr; } BPatch_type *bptype = image->findType(type); if(bptype == NULL){ lastError << "Unable to find type: " << type; lastErrorInfo.type = SG_LookUpFailure; lastErrorInfo.fatal = true; return NULL; } // varExpr = addSpace->malloc(*bptype); varExpr = addSpace->createVariable(std::string(name), (Dyninst::Address)NULL, bptype); if(varExpr == NULL){ lastError << "FIXME: varExpr is null!"; lastErrorInfo.type = SG_InternalError; lastErrorInfo.fatal = true; return NULL; } if(!(varExpr->writeValue(initialValue))){ //unable to initialize... what to do? lastError << "Internal: Variable initialization failed"; lastErrorInfo.type = SG_InternalError; lastErrorInfo.fatal = false; } return varExpr; }
BPatch_snippet *SnippetGenerator::findOrCreateArray(const char * name, const char * elementType, long size){ lastError.str() = ""; BPatch_variableExpr *varExpr = image->findVariable(name, false); if(varExpr != NULL){ return varExpr; } std::stringstream arrayTypeName; arrayTypeName << elementType << "[" << size << "]"; BPatch_type *type = image->findType(elementType); if(type == NULL){ lastError << "Unable to find type:" << elementType; lastErrorInfo.type = SG_LookUpFailure; lastErrorInfo.fatal = true; return NULL; } BPatch_type *array = BPatch::bpatch->createArray(arrayTypeName.str().c_str(), type, 0, size - 1); if(array == NULL){ lastError << "Failed to create array"; lastErrorInfo.type = SG_InternalError; lastErrorInfo.fatal = true; return NULL; } varExpr = addSpace->malloc(*array); varExpr = addSpace->createVariable(std::string(name), (Dyninst::Address)varExpr->getBaseAddr(), array); if(varExpr == NULL){ lastError << "FIXME: varExpr is null!"; lastErrorInfo.type = SG_InternalError; lastErrorInfo.fatal = true; return NULL; } return varExpr; }
BPatch_variableExpr *allocateIntegerInMutatee(dynHandle *dh, int defaultValue = 0) { BPatch_variableExpr *countVar; sendMsg(config.outfd, ID_ALLOC_COUNTER, VERB3); sendMsg(config.outfd, ID_INST_FIND_INT, VERB4); BPatch_type *intType = dh->image->findType("int"); if (!intType) { sendMsg(config.outfd, ID_INST_FIND_INT, VERB4, ID_FAIL, "BPatch_image::findType(\"int\")"); goto fail; } else sendMsg(config.outfd, ID_INST_FIND_INT, VERB4, ID_PASS); sendMsg(config.outfd, ID_INST_MALLOC_INT, VERB4); countVar = dh->addSpace->malloc(*intType); if (!countVar) { sendMsg(config.outfd, ID_INST_MALLOC_INT, VERB4, ID_FAIL, "Failure in BPatch_process::malloc()"); goto fail; } else if (!countVar->writeValue(&defaultValue)) { sendMsg(config.outfd, ID_INST_MALLOC_INT, VERB4, ID_FAIL, "Failure initializing counter in mutatee [BPatch_variableExpr::writeValue()]"); goto fail; } else { sendMsg(config.outfd, ID_INST_MALLOC_INT, VERB4, ID_PASS); } sendMsg(config.outfd, ID_ALLOC_COUNTER, VERB3, ID_PASS); return(countVar); fail: sendMsg(config.outfd, ID_ALLOC_COUNTER, VERB3, ID_FAIL); return(NULL); }
// 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 }
// 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); }
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; }