Exemplo n.º 1
0
bool BPatch_binaryEdit::writeFile(const char * outFile)
{
    assert(pendingInsertions);

    // This should be a parameter...
    //bool atomic = false;

    // Define up here so we don't have gotos causing issues
    std::set<func_instance *> instrumentedFunctions;

    // Two loops: first addInst, then generate/install/link
    pdvector<miniTramp *> workDone;
    //bool err = false;

    // Iterate over our AddressSpaces, triggering relocation
    // in each one.
    std::vector<AddressSpace *> as;
    getAS(as);
    bool ret = true;

    /* PatchAPI stuffs */
    if (as.size() > 0) {
          ret = AddressSpace::patch(as[0]);
    }
    /* end of PatchAPI stuffs */


   // Now that we've instrumented we can see if we need to replace the
   // trap handler.
   replaceTrapHandler();

   for(std::map<std::string, BinaryEdit*>::iterator i = llBinEdits.begin();
       i != llBinEdits.end(); i++)
   {
      (*i).second->trapMapping.flush();
   }


   if( !origBinEdit->writeFile(outFile) ) return false;

   std::map<std::string, BinaryEdit *>::iterator curBinEdit;
   for (curBinEdit = llBinEdits.begin(); curBinEdit != llBinEdits.end(); curBinEdit++) {
     BinaryEdit *bin = (*curBinEdit).second;
     if (bin == origBinEdit)
       continue;
     if (!bin->isDirty())
       continue;

     std::string newname = bin->getMappedObject()->fileName();
     if( !bin->writeFile(newname) ) return false;
   }
   return ret;
}
Exemplo n.º 2
0
BPatch_variableExpr *BPatch_addressSpace::createVariable(
                        Dyninst::Address at_addr,
                        BPatch_type *type, std::string var_name,
                        BPatch_module *in_module)
{
   BPatch_binaryEdit *binEdit = dynamic_cast<BPatch_binaryEdit *>(this);
   if (binEdit && !in_module) {
      //Address alone isn't unique when binary rewriting
      return NULL;
   }
   if (!type) {
      //Required for size information.
      return NULL;
   }
   AddressSpace *ll_addressSpace = NULL;

   std::vector<AddressSpace *> as;
   getAS(as);
   if (binEdit) {
      std::vector<AddressSpace *>::iterator as_i;
      for (as_i = as.begin(); as_i != as.end(); as_i++)
      {
         BinaryEdit *b = dynamic_cast<BinaryEdit *>(*as_i);
         assert(b);
         if (in_module->mod->obj() == b->getMappedObject()) {
            ll_addressSpace = *as_i;
            break;
         }
      }
   }
   else {
      assert(as.size() == 1);
      ll_addressSpace = as[0];
   }

   if (!ll_addressSpace) {
      //in_module doesn't belong to 'this'
      return NULL;
   }

   if (!var_name.size()) {
      std::stringstream namestream;
      namestream << "dyninst_var_" << std::hex << at_addr;
      var_name = namestream.str();
   }

   return BPatch_variableExpr::makeVariableExpr(this, ll_addressSpace, var_name,
                                                (void *) at_addr, type);
}
Exemplo n.º 3
0
mapped_object *BinaryEdit::openResolvedLibraryName(std::string filename, std::map<std::string, BinaryEdit *> &allOpened) {
    /*
     * Note: this does not actually do any library name resolution, as that is OS-dependent
     * If resolution is required, it should be implemented in an OS-dependent file
     * (see linux.C for an example)
     *
     * However, this version allows the RT library to be opened with this function regardless
     * if library name resolution has been implemented on a platform.
     */
    std::map<std::string, BinaryEdit *> retMap;
    assert(mgr());
    BinaryEdit *temp = BinaryEdit::openFile(filename, mgr(), patcher());

    if( temp && temp->getAddressWidth() == getAddressWidth() ) {
       allOpened.insert(std::make_pair(filename, temp));
       return temp->getMappedObject();
    }
    
    return NULL;
}
Exemplo n.º 4
0
bool BPatch_binaryEdit::replaceTrapHandler() {
    // Did we use a trap?

    bool usedATrap = false;

    std::map<std::string, BinaryEdit *>::iterator iter = llBinEdits.begin();
    for (; iter != llBinEdits.end(); iter++) {
        if (iter->second->usedATrap()) {
            usedATrap = true;
            break;
        }
    }

    if (!usedATrap) return true;

    // We used a trap, so go through and set up the replacement instrumentation.
    // However, don't let this be the first piece of instrumentation put into
    // a library.

    bool success = true;
    iter = llBinEdits.begin();
    for (; iter != llBinEdits.end(); iter++) {
        BinaryEdit *binEd = iter->second;

        // Did we instrument this already?
        if (!binEd->isDirty()) {
            continue;
        }

        // Okay, replace trap handler
        if (!binEd->replaceTrapHandler()) {
            success = false;
        }
    }
    return success;
}
Exemplo n.º 5
0
// findCallee: finds the function called by the instruction corresponding
// to the instPoint "instr". If the function call has been bound to an
// address, then the callee function is returned in "target" and the 
// instPoint "callee" data member is set to pt to callee's func_instance.  
// If the function has not yet been bound, then "target" is set to the 
// func_instance associated with the name of the target function (this is 
// obtained by the PLT and relocation entries in the image), and the instPoint
// callee is not set.  If the callee function cannot be found, (ex. function
// pointers, or other indirect calls), it returns false.
// Returns false on error (ex. process doesn't contain this instPoint).
//
// HACK: made an func_instance method to remove from instPoint class...
// FURTHER HACK: made a block_instance method so we can share blocks
func_instance *block_instance::callee() {
   // Check 1: pre-computed callee via PLT
   func_instance *ret = obj()->getCallee(this);
   if (ret) return ret;

   // See if we've already done this
   edge_instance *tEdge = getTarget();
   if (!tEdge) {
      return NULL;
   }

   if (!tEdge->sinkEdge()) {
      func_instance *tmp = obj()->findFuncByEntry(tEdge->trg());
      if (tmp && !(tmp->ifunc()->isPLTFunction())) {
         return tmp;
      }
   }

   

   // Do this the hard way - an inter-module jump
   // get the target address of this function
   Address target_addr; bool success;
   boost::tie(success, target_addr) = llb()->callTarget();
   if(!success) {
      // this is either not a call instruction or an indirect call instr
      // that we can't get the target address
      //fprintf(stderr, "%s[%d]:  returning NULL\n", FILE__, __LINE__);
      return NULL;
   }
   
   // get the relocation information for this image
   Symtab *sym = obj()->parse_img()->getObject();
   pdvector<relocationEntry> fbt;
   vector <relocationEntry> fbtvector;
   if (!sym->getFuncBindingTable(fbtvector)) {
      //fprintf(stderr, "%s[%d]:  returning NULL\n", FILE__, __LINE__);
      return NULL;
   }


   /**
    * Object files and static binaries will not have a function binding table
    * because the function binding table holds relocations used by the dynamic
    * linker
    */
   if (!fbtvector.size() && !sym->isStaticBinary() && 
           sym->getObjectType() != obj_RelocatableFile ) 
   {
      fprintf(stderr, "%s[%d]:  WARN:  zero func bindings\n", FILE__, __LINE__);
   }

   for (unsigned index=0; index< fbtvector.size();index++)
      fbt.push_back(fbtvector[index]);
   
   Address base_addr = obj()->codeBase();
   
   std::map<Address, std::string> pltFuncs;
   obj()->parse_img()->getPltFuncs(pltFuncs);

   // find the target address in the list of relocationEntries
   if (pltFuncs.find(target_addr) != pltFuncs.end()) {
      for (u_int i=0; i < fbt.size(); i++) {
         if (fbt[i].target_addr() == target_addr) 
         {
            // check to see if this function has been bound yet...if the
            // PLT entry for this function has been modified by the runtime
            // linker
            func_instance *target_pdf = 0;
            if (proc()->hasBeenBound(fbt[i], target_pdf, base_addr)) {
               updateCallTarget(target_pdf);
               obj()->setCalleeName(this, target_pdf->symTabName());
               obj()->setCallee(this, target_pdf);
               return target_pdf;
            }
         }
      }
      const char *target_name = pltFuncs[target_addr].c_str();
      PCProcess *dproc = dynamic_cast<PCProcess *>(proc());

      BinaryEdit *bedit = dynamic_cast<BinaryEdit *>(proc());
      obj()->setCalleeName(this, std::string(target_name));
      pdvector<func_instance *> pdfv;

      // See if we can name lookup
      if (dproc) {
         if (proc()->findFuncsByMangled(target_name, pdfv)) {
            obj()->setCallee(this, pdfv[0]);
            updateCallTarget(pdfv[0]);
            return pdfv[0];
         }
      }
      else if (bedit) {
         std::vector<BinaryEdit *>::iterator i;
         for (i = bedit->getSiblings().begin(); i != bedit->getSiblings().end(); i++)
         {
            if ((*i)->findFuncsByMangled(target_name, pdfv)) {
               obj()->setCallee(this, pdfv[0]);
               updateCallTarget(pdfv[0]);
               return pdfv[0];
            }
         }
      }
      else 
         assert(0);
   }
   
   //fprintf(stderr, "%s[%d]:  returning NULL: target addr = %p\n", FILE__, __LINE__, (void *)target_addr);
   return NULL;
}
Exemplo n.º 6
0
mapped_object *BinaryEdit::openResolvedLibraryName(std::string filename,
                                                   std::map<std::string, BinaryEdit*> &retMap) {
    std::vector<std::string> paths;
    std::vector<std::string>::iterator pathIter;
    // First, find the specified library file
    bool resolved = getResolvedLibraryPath(filename, paths);

    // Second, create a set of BinaryEdits for the found library
    if ( resolved ) {
        startup_printf("[%s:%u] - Opening dependent file %s\n",
                       FILE__, __LINE__, filename.c_str());

        Symtab *origSymtab = getMappedObject()->parse_img()->getObject();
	assert(mgr());
        // Dynamic case
        if ( !origSymtab->isStaticBinary() ) {
            for(pathIter = paths.begin(); pathIter != paths.end(); ++pathIter) {
               BinaryEdit *temp = BinaryEdit::openFile(*pathIter, mgr(), patcher());

                if (temp && temp->getAddressWidth() == getAddressWidth()) {
                    retMap.insert(std::make_pair(*pathIter, temp));
                    return temp->getMappedObject();
                }
                delete temp;
            }
        } else {
            // Static executable case

            /* 
             * Alright, this is a kludge, but even though the Archive is opened
             * twice (once here and once by the image class later on), it is
             * only parsed once because the Archive class keeps track of all
             * open Archives.
             *
             * This is partly due to the fact that Archives are collections of
             * Symtab objects and their is one Symtab for each BinaryEdit. In
             * some sense, an Archive is a collection of BinaryEdits.
             */
            for(pathIter = paths.begin(); pathIter != paths.end(); ++pathIter) {
                Archive *library;
                Symtab *singleObject;
                if (Archive::openArchive(library, *pathIter)) {
                    std::vector<Symtab *> members;
                    if (library->getAllMembers(members)) {
                        std::vector <Symtab *>::iterator member_it;
                        for (member_it = members.begin(); member_it != members.end();
                             ++member_it) 
                        {
                           BinaryEdit *temp = BinaryEdit::openFile(*pathIter, 
                                                                   mgr(), patcher(), (*member_it)->memberName());

                            if (temp && temp->getAddressWidth() == getAddressWidth()) {
                                std::string mapName = *pathIter + string(":") +
                                    (*member_it)->memberName();
                                retMap.insert(std::make_pair(mapName, temp));
                            }else{
                                if(temp) delete temp;
                                retMap.clear();
                                break;
                            }
                        }

                        if (retMap.size() > 0) {
                            origSymtab->addLinkingResource(library);
                            // So we tried loading "libc.a", and got back a swarm of individual members. 
                            // Lovely. 
                            // Just return the first thing...
                            return retMap.begin()->second->getMappedObject();
                        }
                        //if( library ) delete library;
                    }
                } else if (Symtab::openFile(singleObject, *pathIter)) {
                   BinaryEdit *temp = BinaryEdit::openFile(*pathIter, mgr(), patcher());


                    if (temp && temp->getAddressWidth() == getAddressWidth()) {
                        if( singleObject->getObjectType() == obj_SharedLib ||
                            singleObject->getObjectType() == obj_Executable ) 
                        {
                          startup_printf("%s[%d]: cannot load dynamic object(%s) when rewriting a static binary\n", 
                                  FILE__, __LINE__, pathIter->c_str());
                          std::string msg = std::string("Cannot load a dynamic object when rewriting a static binary");
                          showErrorCallback(71, msg.c_str());

                          delete singleObject;
                        }else{
                            retMap.insert(std::make_pair(*pathIter, temp));
                            return temp->getMappedObject();
                        }
                    }
                    if(temp) delete temp;
                }
            }
        }
    }

    startup_printf("[%s:%u] - Creation error opening %s\n",
                   FILE__, __LINE__, filename.c_str());
    // If the only thing we could find was a dynamic lib for a static executable, we can reach here; caller should handle this.
    return NULL;
}
Exemplo n.º 7
0
/*
 * BPatch_binaryEdit::BPatch_binaryEdit
 *
 * Creates a new BinaryEdit and associates it with the BPatch_binaryEdit
 * being created. Additionally, if specified, the dependencies of the
 * original BinaryEdit are opened and associated with the BPatch_binaryEdit
 *
 * path		     Pathname of the executable
 * openDependencies  if true, the dependencies of the original BinaryEdit are
 *                   also opened
 */
BPatch_binaryEdit::BPatch_binaryEdit(const char *path, bool openDependencies) :
   BPatch_addressSpace(),
   creation_error(false)
{
  pendingInsertions = new BPatch_Vector<batchInsertionRecord *>;

  pdvector<std::string> argv_vec;
  pdvector<std::string> envp_vec;

  std::string directoryName = "";

  startup_printf("[%s:%u] - Opening original file %s\n",
                 FILE__, __LINE__, path);
  origBinEdit = BinaryEdit::openFile(std::string(path));

  if (!origBinEdit){
     startup_printf("[%s:%u] - Creation error opening %s\n",
                    FILE__, __LINE__, path);
     creation_error = true;
     return;
  }
  llBinEdits[path] = origBinEdit;

  if(openDependencies) {
    origBinEdit->getAllDependencies(llBinEdits);
  }
  std::map<std::string, BinaryEdit*>::iterator i, j;

  origBinEdit->getDyninstRTLibName();
  std::string rt_name = origBinEdit->dyninstRT_name;

  // Load the RT library and create the collection of BinaryEdits that represent it
  std::map<std::string, BinaryEdit *> rtlibs;
  origBinEdit->openResolvedLibraryName(rt_name, rtlibs);
  std::map<std::string, BinaryEdit *>::iterator rtlibs_it;
  for(rtlibs_it = rtlibs.begin(); rtlibs_it != rtlibs.end(); ++rtlibs_it) {
      if( !rtlibs_it->second ) {
          std::string msg("Failed to load Dyninst runtime library, check the environment variable DYNINSTAPI_RT_LIB");
          showErrorCallback(70, msg.c_str());
          creation_error = true;
          return;
      }
      rtLib.push_back(rtlibs_it->second);
      // Ensure that the correct type of library is loaded
      if(    rtlibs_it->second->getMappedObject()->isSharedLib()
          && origBinEdit->getMappedObject()->isStaticExec() )
      {
          std::string msg = std::string("RT Library is a shared library ") +
              std::string("when it should be a static library");
          showErrorCallback(70, msg.c_str());
          creation_error = true;
          return;
      }else if(     !rtlibs_it->second->getMappedObject()->isSharedLib()
                &&  !origBinEdit->getMappedObject()->isStaticExec() )
      {
          std::string msg = std::string("RT Library is a static library ") +
              std::string("when it should be a shared library");
          showErrorCallback(70, msg.c_str());
          creation_error = true;
          return;
      }
  }

  for(i = llBinEdits.begin(); i != llBinEdits.end(); i++) {
     (*i).second->setupRTLibrary(rtLib);
  }


  int_variable* masterTrampGuard = origBinEdit->createTrampGuard();
  assert(masterTrampGuard);

  for(i = llBinEdits.begin(); i != llBinEdits.end(); i++) {
     BinaryEdit *llBinEdit = (*i).second;
     llBinEdit->registerFunctionCallback(createBPFuncCB);
     llBinEdit->registerInstPointCallback(createBPPointCB);
     llBinEdit->set_up_ptr(this);
     llBinEdit->setupRTLibrary(rtLib);
     llBinEdit->setTrampGuard(masterTrampGuard);
     llBinEdit->setMultiThreadCapable(isMultiThreadCapable());
     for (j = llBinEdits.begin(); j != llBinEdits.end(); j++) {
        llBinEdit->addSibling((*j).second);
     }
  }

  image = new BPatch_image(this);
}
Exemplo n.º 8
0
BinaryEdit *BinaryEdit::openFile(const std::string &file, 
                                 PatchMgrPtr mgr, 
                                 Dyninst::PatchAPI::Patcher *patch,
                                 const std::string &member) {
    if (!OS::executableExists(file)) {
        startup_printf("%s[%d]:  failed to read file %s\n", FILE__, __LINE__, file.c_str());
        std::string msg = std::string("Can't read executable file ") + file + (": ") + strerror(errno);
        showErrorCallback(68, msg.c_str());
        return NULL;
    }
    
    fileDescriptor desc;
    if (!getStatFileDescriptor(file, desc)) {
        startup_printf("%s[%d]: failed to create file descriptor for %s!\n",
                       FILE__, __LINE__, file.c_str());
        return NULL;
    }
    
    // Open the mapped object as an archive member
    if( !member.empty() ) {
        desc.setMember(member);
    }

    BinaryEdit *newBinaryEdit = new BinaryEdit();
    if (!newBinaryEdit) {
        startup_printf("%s[%d]: failed to create binary representation for %s!\n",
                       FILE__, __LINE__, file.c_str());
    }

    newBinaryEdit->mobj = mapped_object::createMappedObject(desc, newBinaryEdit);
    if (!newBinaryEdit->mobj) {
        startup_printf("%s[%d]: failed to create mapped object for %s\n",
                       FILE__, __LINE__, file.c_str());
        return NULL;
    }

    /* PatchAPI stuffs */
    if (!mgr) {
       newBinaryEdit->initPatchAPI();
    } else {
       newBinaryEdit->setMgr(mgr);
       assert(patch);
       newBinaryEdit->setPatcher(patch);
    }
    newBinaryEdit->addMappedObject(newBinaryEdit->mobj);
    /* End of PatchAPI stuffs */

    // We now need to access the start of the new section we're creating.

    // I'm going through the mapped_object interface for now - 
    // I assume we'll pass it to DynSymtab, then add our base
    // address to it at the mapped_ level. 
    Symtab* linkedFile = newBinaryEdit->getAOut()->parse_img()->getObject();
    Region *newSec = NULL;
    linkedFile->findRegion(newSec, ".dyninstInst");
    if (newSec) {
         // We're re-instrumenting - will fail for now
         fprintf(stderr, "ERROR:  unable to open/reinstrument previously instrumented binary %s!\n", file.c_str());
         return NULL;
    }
    Address base = linkedFile->getFreeOffset(50*1024*1024);
    base += (1024*1024);
    base -= (base & (1024*1024-1));

    newBinaryEdit->highWaterMark_ = base;
    newBinaryEdit->lowWaterMark_ = newBinaryEdit->highWaterMark_;
	//CHEN MODIFIED, this can reserve space for plt table, or even for inline code region
	//newBinaryEdit->highWaterMark_ += 0x100000;

    // Testing

    newBinaryEdit->makeInitAndFiniIfNeeded();

    newBinaryEdit->createMemoryBackingStore(newBinaryEdit->getAOut());
    newBinaryEdit->initialize();

    //Don't count initialization in determining dirty
    newBinaryEdit->isDirty_ = false; //!(foundInit && foundFini);
    return newBinaryEdit;
}