예제 #1
0
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;
}
예제 #2
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;
   }
}
예제 #3
0
bool BPatch_addressSpace::free(BPatch_variableExpr &ptr)
{
  if(ptr.intvar)
  {
    // kill the symbols

  }

   ptr.getAS()->inferiorFree((Address)ptr.getBaseAddr());
   return true;
}
예제 #4
0
// 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
}
예제 #5
0
// 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
}
예제 #6
0
파일: snippetGen.C 프로젝트: Zirkon/dyninst
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;

}
예제 #7
0
파일: snippetGen.C 프로젝트: Zirkon/dyninst
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;

}
예제 #8
0
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);
}
예제 #9
0
// 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,
	//			&currentFileInfo,&currentFuncInfo);
	//}
      }
      //  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
}
예제 #10
0
// 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);
}
예제 #11
0
int main(int argc, char *argv[], char* envp[])
{
    if (argc < 2) {
        fprintf(stderr, "Usage: %s prog_filename prog_aruments\n", argv[0]);
        return 3;
    }
#if 0
    if (strcmp(argv[1], "prog") != 0 && strcmp(argv[1], "all"))
    {
        fprintf(stderr, "Options for patch selection are 'progonly' or 'all'\n");
        return 3;
    }
#endif
    int patchall = 0; //strcmp(argv[1], "all") != 0;

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

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

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


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

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

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

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

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

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

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

    BPatch_Vector<BPatch_snippet*> mainEntryBlock;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    mainEntryBlock.push_back(&mmapBlock);


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


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

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

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

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

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

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

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

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

    mutexArgs.push_back(&mutexAddress);

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

    BPatch_arithExpr derefCounter(BPatch_deref, *counterAddr);

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

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

    BPatch_sequence addOneAtomic(snippet);

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

    appProc->beginInsertionSet();

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

    fprintf(stderr, "----------------------------------------\n");
    fprintf(stderr, "Done.\n");
    return 0;
}