Esempio n. 1
0
// Build a list of symbols describing instrumentation and relocated functions. 
// To keep this list (somewhat) short, we're doing one symbol per extent of 
// instrumentation + relocation for a particular function. 
// New: do this for one mapped object. 
void BinaryEdit::buildDyninstSymbols(pdvector<Symbol *> &newSyms, 
                                     Region *newSec,
                                     Module *newMod) {
   for (std::vector<SymtabAPI::Symbol *>::iterator iter = newDyninstSyms_.begin();
        iter != newDyninstSyms_.end(); ++iter) {
      (*iter)->setModule(newMod);
      (*iter)->setRegion(newSec);
      newSyms.push_back(*iter);
   }
                                                                              

   for (CodeTrackers::iterator i = relocatedCode_.begin();
        i != relocatedCode_.end(); ++i) {
      Relocation::CodeTracker *CT = *i;
      func_instance *currFunc = NULL;
      Address start = 0;
      unsigned size = 0;
      
      for (Relocation::CodeTracker::TrackerList::const_iterator iter = CT->trackers().begin();
           iter != CT->trackers().end(); ++iter) {
         const Relocation::TrackerElement *tracker = *iter;
         
         func_instance *tfunc = tracker->func();
         
         if (currFunc != tfunc) {
            // Starting a new function
            if (currFunc) {
               // Record the old one
               // currfunc set
               // start set
               size = tracker->reloc() - start;
               
               std::string name = currFunc->prettyName();
               name.append("_dyninst");
               
               Symbol *newSym = new Symbol(name.c_str(),
                                           Symbol::ST_FUNCTION,
                                           Symbol::SL_GLOBAL,
                                           Symbol::SV_DEFAULT,
                                           start,
                                           newMod,
                                           newSec,
                                           size);                                        
               newSyms.push_back(newSym);
            }
            currFunc = tfunc;
            start = tracker->reloc();
            size = 0;
         }
         else {
            // Accumulate size
            size = tracker->reloc() - start;
         }
      }
   }
}
Esempio n. 2
0
bool dynamic_linking::getSharedObjects(pdvector<mapped_object *> &mapped_objects) 
{
    pdvector<fileDescriptor> descs;
    
    if (!processLinkMaps(descs))
        return false;
    
    // Skip first entry: always the a.out
    for (unsigned i = 0; i < descs.size(); i++) {
        if (descs[i] != proc->getAOut()->getFileDesc()) {
#if 0
            fprintf(stderr, "DEBUG: match pattern %d, %d, %d, %d, %d\n",
                    descs[i].file() == proc->getAOut()->getFileDesc().file(),
                    descs[i].code() == proc->getAOut()->getFileDesc().code(),
                    descs[i].data() == proc->getAOut()->getFileDesc().data(),
                    descs[i].member() == proc->getAOut()->getFileDesc().member(),
                    descs[i].pid() == proc->getAOut()->getFileDesc().pid());
#endif
            mapped_object *newobj = mapped_object::createMappedObject(descs[i], proc);
            if (newobj == NULL) continue;
            mapped_objects.push_back(newobj);
#if defined(cap_save_the_world)
            setlowestSObaseaddr(descs[i].code());
#endif
        }           
    }
    return true;
} /* end getSharedObjects() */
Esempio n. 3
0
bool mapped_module::findFuncVectorByPretty(const pdstring &funcname,
                                           pdvector<int_function *> &funcs)
{
    // For efficiency sake, we grab the image vector and strip out the
    // functions we want.
    // We could also keep them all in modules and ditch the image-wide search; 
    // the problem is that BPatch goes by module and internal goes by image. 
    unsigned orig_size = funcs.size();

    const pdvector<int_function *> *obj_funcs = obj()->findFuncVectorByPretty(funcname);
    if (!obj_funcs) return false;

    for (unsigned i = 0; i < obj_funcs->size(); i++) {
        if ((*obj_funcs)[i]->mod() == this)
            funcs.push_back((*obj_funcs)[i]);
    }
    return funcs.size() > orig_size;
}
Esempio n. 4
0
static void emitNeededCallSaves(codeGen &gen, Register regi, 
                           pdvector<Register> &extra_saves)
{
    extra_saves.push_back(regi);
    switch (regi) {
        case REGNUM_EAX:
            emitSimpleInsn(PUSHEAX, gen);
            break;
        case REGNUM_EBX:
            emitSimpleInsn(PUSHEBX, gen);
            break;
        case REGNUM_ECX:
            emitSimpleInsn(PUSHECX, gen);
            break;
        case REGNUM_EDX:
            emitSimpleInsn(PUSHEDX, gen);
            break;
        case REGNUM_EDI:
            emitSimpleInsn(PUSHEDI, gen);
            break;
    }
}
Esempio n. 5
0
// findChangeToLinkMaps: This routine returns a vector of shared objects
// that have been deleted or added to the link maps as indicated by
// change_type.  If an error occurs it sets error_occured to true.
bool dynamic_linking::findChangeToLinkMaps(u_int &change_type,
					   pdvector<mapped_object *> &changed_objects) 
{
  pdvector<fileDescriptor> new_descs;
  if (!didLinkMapsChange(change_type, new_descs)) {
    return false;
  }

  const pdvector<mapped_object *> &curr_list = proc->mappedObjects();


#if 0
  fprintf(stderr, "CURR_LIST:\n");
  for (unsigned foo = 0; foo < curr_list.size(); foo++) {
      fprintf(stderr, "%d: %s\0x%x\n",
              foo, curr_list[foo]->fileName().c_str(), curr_list[foo]->codeBase());
  }
#endif

  // if change_type is add then figure out what has been added
  if(change_type == SHAREDOBJECT_ADDED) {
      // Look for the one that doesn't match
      for (unsigned int i=0; i < new_descs.size(); i++) {

	  bool found = false;
	  for (unsigned int j = 0; j < curr_list.size(); j++) {
#if 0 
              fprintf(stderr, "Comparing %s/0x%x/0x%x/%s/%d to %s/0x%x/0x%x/%s/%d\n",
                      new_descs[i].file().c_str(),
                      new_descs[i].code(),
                      new_descs[i].data(),
                      new_descs[i].member().c_str(),
                      new_descs[i].pid(),
                      curr_list[j]->getFileDesc().file().c_str(),
                      curr_list[j]->getFileDesc().code(),
                      curr_list[j]->getFileDesc().data(),
                      curr_list[j]->getFileDesc().member().c_str(),
                      curr_list[j]->getFileDesc().pid());
#endif
              if (new_descs[i] == curr_list[j]->getFileDesc()) {
                  found = true;
                  break;
              }
	  }
	  if (!found) {
#if 0
              fprintf(stderr, "Adding %s/%s\n",
                      new_descs[i].file().c_str(),
                      new_descs[i].member().c_str());
#endif
              mapped_object *newobj = mapped_object::createMappedObject(new_descs[i],
                                                                        proc);
              if (!newobj) continue;

              changed_objects.push_back(newobj);

          // SaveTheWorld bookkeeping
#if defined(cap_save_the_world)
              char *tmpStr = new char[1+strlen(newobj->fileName().c_str())];
              strcpy(tmpStr, newobj->fileName().c_str());
              if( !strstr(tmpStr, "libdyninstAPI_RT.so") && 
                  !strstr(tmpStr, "libelf.so")){
                  //bperr(" dlopen: %s \n", tmpStr);
                  newobj->openedWithdlopen();
              }
              setlowestSObaseaddr(newobj->codeBase());
              delete [] tmpStr;	              
              // SaveTheWorld bookkeeping
#endif

	  }
      }
  }
  // if change_type is remove then figure out what has been removed
  else if((change_type == SHAREDOBJECT_REMOVED) && (curr_list.size())) {
      // Look for the one that's not in descs
      bool stillThere[curr_list.size()];
      for (unsigned k = 0; k < curr_list.size(); k++) 
          stillThere[k] = false;
#if defined(os_linux) || defined(os_solaris)
      // Linux never includes the a.out in its list of libraries. This makes a
      // certain amount of sense, but is still annoying.
      // Solaris throws it away; so hey.
      stillThere[0] = true;
#endif
      
      for (unsigned int i=0; i < new_descs.size(); i++) {
	  for (unsigned int j = 0; j < curr_list.size(); j++) {
              if (new_descs[i] == curr_list[j]->getFileDesc()) {
                  stillThere[j] = true;
                  break;
              }
	  }
      }

      for (unsigned l = 0; l < curr_list.size(); l++) {
          if (!stillThere[l]) {
              changed_objects.push_back(curr_list[l]);
          }
      }
  }
  return true;
}
Esempio n. 6
0
// processLinkMaps: get a list of all loaded objects in fileDescriptor form.
bool dynamic_linking::processLinkMaps(pdvector<fileDescriptor> &descs) {
    
    int proc_fd = proc->getRepresentativeLWP()->get_fd();
    if(!proc_fd){ return false;}

    // step 2: get the runtime loader table from the process
    Address ldr_base_addr;
    ldr_context first;
    ldr_module module;

    assert(proc->readDataSpace((const void*)LDR_BASE_ADDR,sizeof(Address), &ldr_base_addr, true));
    assert(proc->readDataSpace((const void*)ldr_base_addr,sizeof(ldr_context), &first, true));
    assert(proc->readDataSpace((const void *) first.head,sizeof(ldr_module), &module, true));
    
    while (module.next != first.head) {
      if (module.nregions == 0)
	{ 
	  assert(proc->readDataSpace((const void *) module.next,sizeof(ldr_module), &module,true));
	  continue;
        }
      pdstring obj_name = pdstring(readDataString(proc, module.name));
      ldr_region *regions;
      
      regions = (ldr_region *) malloc(module.nregions * sizeof(ldr_region));
      assert(proc->readDataSpace((const void *) module.regions, 
				 sizeof(ldr_region)*module.nregions, regions, true));
      
      long offset = regions[0].mapaddr - regions[0].vaddr;
#ifdef notdef
      if (offset) {
	bperr("*** shared lib at non-default offset **: ");
	bperr("    %s\n", obj_name.c_str());
	bperr("    offset = %ld\n", offset);
      } else {
	bperr("*** shared lib **: ");
	bperr("    %s\n", obj_name.c_str());
	bperr("    at = %ld\n", regions[0].mapaddr);
      }
#endif
      
      for (int i=0; i < module.nregions; i++) {
	long newoffset = regions[i].mapaddr - regions[i].vaddr;
	if (newoffset != offset) {
	  bperr( "shared lib regions have different offsets\n");
	}
	regions[i].name = (long unsigned) readDataString(proc,
							 (void *) regions[i].name);
	// bperr("  region %d (%s) ", i, regions[i].name);
	// bperr("addr = %lx, ", regions[i].vaddr);
	// bperr("mapped at = %lx, ", regions[i].mapaddr);
	// bperr("size = %x\n", regions[i].size);
      }
      descs.push_back(fileDescriptor(obj_name, 
				     offset,
				     offset,
				     true));

      free(regions);
      assert(proc->readDataSpace((const void *) module.next,sizeof(ldr_module), &module,true));
    }
    return true;
}
Esempio n. 7
0
// processLinkMaps: This routine is called by getSharedObjects to  
// process all shared objects that have been mapped into the process's
// address space.  This routine reads the link maps from the application 
// process to find the shared object file base mappings. It returns 0 on error.
bool dynamic_linking::processLinkMaps(pdvector<fileDescriptor> &descs) {
   r_debug debug_elm;
   if(!proc->readDataSpace((caddr_t)(r_debug_addr),
                        sizeof(r_debug),(caddr_t)&(debug_elm),true)) {
      // bperr("read d_ptr_addr failed r_debug_addr = 0x%lx\n",r_debug_addr);
      return 0;
   }

   // get each link_map object
   Link_map *next_link_map = debug_elm.r_map;
   Address next_addr = (Address)next_link_map; 
   
   while(next_addr != 0){
       Link_map link_elm;

       if(!proc->readDataSpace((caddr_t)(next_addr),
                               sizeof(Link_map),(caddr_t)&(link_elm),true)) {
           logLine("read next_link_map failed\n");
           return 0;
       }
       // get file name
       char f_name[256]; // assume no file names greater than 256 chars
       // check to see if reading 256 chars will go out of bounds
       // of data segment
       u_int f_amount = 256;
       bool done = false;
       for(u_int i=0; (i<256) && (!done); i++){
           if(!proc->readDataSpace((caddr_t)((u_int)(link_elm.l_name)+i),
                                   sizeof(char),(caddr_t)(&(f_name[i])),true)){
           }
           if(f_name[i] == '\0'){
               done = true;
               f_amount = i+1;
           }
       }
       f_name[f_amount-1] = '\0';
       pdstring obj_name = pdstring(f_name);

      parsing_cerr << 
         "dynamicLinking::processLinkMaps(): file name of next shared obj="
                     << obj_name << endl;

      // create a mapped_object and add it to the list
      // kludge: ignore the entry if it has the same name as the
      // executable file...this seems to be the first link-map entry
      // VG(09/25/01): also ignore if address is 65536 or name is (unknown)
      if(obj_name != proc->getAOut()->fileName() && 
         obj_name != proc->getAOut()->fullName() &&
         link_elm.l_addr != 65536 &&
         obj_name != "(unknown)"
         //strncmp(obj_name.c_str(), "(unknown)", 10)
         ) {
          
          fileDescriptor desc = fileDescriptor(obj_name, link_elm.l_addr,
                                               link_elm.l_addr,
                                               true);
          descs.push_back(desc);          
      }
      
      next_addr = (Address)link_elm.l_next;
   }

   return true;
}