emitElf-64.C

Go to the documentation of this file.
00001 /*
00002  * See the dyninst/COPYRIGHT file for copyright information.
00003  * 
00004  * We provide the Paradyn Tools (below described as "Paradyn")
00005  * on an AS IS basis, and do not warrant its validity or performance.
00006  * We reserve the right to update, modify, or discontinue this
00007  * software at any time.  We shall have no obligation to supply such
00008  * updates or modifications or any other form of support to you.
00009  * 
00010  * By your use of Paradyn, you understand and agree that we (or any
00011  * other person or entity with proprietary rights in Paradyn) are
00012  * under no obligation to provide either maintenance services,
00013  * update services, notices of latent defects, or correction of
00014  * defects for Paradyn.
00015  * 
00016  * This library is free software; you can redistribute it and/or
00017  * modify it under the terms of the GNU Lesser General Public
00018  * License as published by the Free Software Foundation; either
00019  * version 2.1 of the License, or (at your option) any later version.
00020  * 
00021  * This library is distributed in the hope that it will be useful,
00022  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00023  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00024  * Lesser General Public License for more details.
00025  * 
00026  * You should have received a copy of the GNU Lesser General Public
00027  * License along with this library; if not, write to the Free Software
00028  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00029  */
00030 
00031 /*
00032   #if !defined(cap_libelf_so_0) && defined(os_linux)
00033   #define _FILE_OFFSET_BITS 64
00034   #endif
00035 */
00036 
00037 #include <algorithm>
00038 #include "Symtab.h"
00039 #include "emitElf-64.h"
00040 #include "emitElfStatic.h"
00041 #include "debug.h"
00042 #include "common/h/pathName.h"
00043 
00044 #if defined(os_freebsd)
00045 #include "common/h/freebsdKludges.h"
00046 #endif
00047 
00048 #if defined(os_linux)
00049 #include "common/h/linuxKludges.h"
00050 #endif
00051 
00052 extern void symtab_log_perror(const char *msg);
00053 using namespace Dyninst;
00054 using namespace Dyninst::SymtabAPI;
00055 using namespace std;
00056 
00057 extern const char *pdelf_get_shnames(Elf_X *elf);
00058 extern const char *STRTAB_NAME;
00059 extern const char *SYMTAB_NAME;
00060 extern const char *INTERP_NAME;
00061 extern unsigned int elfHash(const char *name);
00062 
00063 unsigned long bgq_sh_flags = SHF_EXECINSTR | SHF_ALLOC | SHF_WRITE;;
00064 bool isBlueGeneQ = false;
00065 bool isStaticBinary = false;
00066 
00067 // Error reporting
00068 extern void setSymtabError(SymtabError new_err);
00069 extern void symtab_log_perror(const char *msg);
00070 
00071 struct sortByIndex
00072 {
00073   bool operator ()(Symbol * lhs, Symbol* rhs) {
00074     return lhs->getIndex() < rhs->getIndex();
00075   }
00076 };
00077 
00078 static bool libelfso0Flag;
00079 static bool libelfso1Flag;
00080 static int libelfso1version_major;
00081 static int libelfso1version_minor;
00082 
00083 static void setVersion(){
00084   libelfso0Flag = false;
00085   libelfso1Flag = false;
00086   libelfso1version_major = 0;
00087   libelfso1version_minor = 0;
00088 #if defined(os_linux) || defined(os_freebsd)
00089   unsigned nEntries;
00090   map_entries *maps = getVMMaps(getpid(), nEntries);
00091   for (unsigned i=0; i< nEntries; i++){
00092      if (!strstr(maps[i].path, "libelf"))
00093         continue;
00094      std::string real_file = resolve_file_path(maps[i].path);
00095      const char *libelf_start = strstr(real_file.c_str(), "libelf");
00096      int num_read, major, minor;
00097      num_read = sscanf(libelf_start, "libelf-%d.%d.so", &major, &minor);
00098      if (num_read == 2) {
00099         libelfso1Flag = true;
00100         libelfso1version_major = major;
00101         libelfso1version_minor = minor;        
00102      }
00103      else {
00104         libelfso0Flag = true;
00105      }
00106   }
00107   if (libelfso0Flag && libelfso1Flag) {
00108      fprintf(stderr, "WARNING: SymtabAPI is linked with libelf.so.0 and "
00109              "libelf.so.1!  SymtabAPI likely going to be unable to read "
00110              "and write elf files!\n");
00111   }
00112 
00113 #if defined(os_freebsd)
00114   if( libelfso1Flag ) {
00115       fprintf(stderr, "WARNING: SymtabAPI on FreeBSD is known to function "
00116               "incorrectly when linked with libelf.so.1\n");
00117   }
00118 #endif
00119 #endif
00120 }
00121 
00122 bool emitElf64::hasPHdrSectionBug()
00123 {
00124    if (movePHdrsFirst)
00125       return false;
00126    if (!libelfso1Flag)
00127       return false;
00128    return (libelfso1version_major == 0 && libelfso1version_minor <= 137);
00129 }
00130 
00131 bool emitElf64::cannotRelocatePhdrs()
00132 {
00133 #if defined(bug_phdrs_first_page)
00134     return true;
00135 #else
00136     return false;
00137 #endif
00138 }
00139 
00140 static int elfSymType(Symbol *sym)
00141 {
00142   switch (sym->getType()) {
00143   case Symbol::ST_MODULE: return STT_FILE;
00144   case Symbol::ST_SECTION: return STT_SECTION;
00145   case Symbol::ST_OBJECT: return STT_OBJECT;
00146   case Symbol::ST_FUNCTION: return STT_FUNC;
00147   case Symbol::ST_TLS: return STT_TLS;
00148   case Symbol::ST_NOTYPE : return STT_NOTYPE;
00149   case Symbol::ST_UNKNOWN: return sym->getInternalType();
00150      case Symbol::ST_INDIRECT: return STT_GNU_IFUNC;
00151 
00152   default: return STT_SECTION;
00153   }
00154 }
00155 
00156 static int elfSymBind(Symbol::SymbolLinkage sLinkage)
00157 {
00158   switch (sLinkage) {
00159   case Symbol::SL_LOCAL: return STB_LOCAL;
00160   case Symbol::SL_WEAK: return STB_WEAK;
00161   case Symbol::SL_GLOBAL: return STB_GLOBAL;
00162   default: return STB_LOPROC;
00163   }
00164 }
00165 
00166 static int elfSymVisibility(Symbol::SymbolVisibility sVisibility)
00167 {
00168   switch (sVisibility) {
00169   case Symbol::SV_DEFAULT: return STV_DEFAULT;
00170   case Symbol::SV_INTERNAL: return STV_INTERNAL;
00171   case Symbol::SV_HIDDEN: return STV_HIDDEN;
00172   case Symbol::SV_PROTECTED: return STV_PROTECTED;
00173   default: return STV_DEFAULT;
00174   }
00175 }
00176 
00177 emitElf64::emitElf64(Elf_X *oldElfHandle_, bool isStripped_, Object *obj_, void (*err_func)(const char *)) :
00178    oldElfHandle(oldElfHandle_),
00179    phdrs_scn(NULL),
00180    isStripped(isStripped_),
00181    object(obj_),
00182    err_func_(err_func)
00183 {
00184   firstNewLoadSec = NULL;
00185   textData = NULL;
00186   symStrData = NULL;
00187   symTabData = NULL;
00188   dynsymData = NULL;
00189   dynStrData = NULL;
00190   hashData = NULL;
00191   rodata = NULL;
00192  
00193   linkedStaticData = NULL;
00194   hasRewrittenTLS = false;
00195   TLSExists = false;
00196   newTLSData = NULL;
00197    
00198   oldElf = oldElfHandle->e_elfp();
00199   curVersionNum = 2;
00200   setVersion();
00201  
00202   //Set variable based on the mechanism to add new load segment
00203   // 1) createNewPhdr (Total program headers + 1) - default
00204   //    (a) movePHdrsFirst
00205   //    (b) create new section called dynphdrs and change pointers (createNewPhdrRegion)
00206   //    (c) library_adjust - create room for a new program header in a position-indepdent library 
00207   //                         by increasing all virtual addresses for the library
00208   // 2) Use existing Phdr (used in bleugene - will be handled in function fixPhdrs)
00209   //    (a) replaceNOTE section - if NOTE exists
00210   //    (b) BSSExpandFlag - expand BSS section - default option
00211 
00212   // default
00213   createNewPhdr = true; BSSExpandFlag = false; replaceNOTE = false; 
00214 
00215   //If we're dealing with a library that can be loaded anywhere,
00216   // then load the program headers into the later part of the binary,
00217   // this may trigger a kernel bug that was fixed in Summer 2007,
00218   // but is the only reliable way to modify these libraries.
00219   //If we're dealing with a library/executable that loads at a specific
00220   // address we'll put the phdrs into the page before that address.  This
00221   // works and will avoid the kernel bug.
00222 
00223   isBlueGeneQ = obj_->isBlueGeneQ();
00224   isStaticBinary = obj_->isStaticBinary();
00225   if(isBlueGeneQ){
00226     movePHdrsFirst = false;
00227   } else {
00228     movePHdrsFirst = createNewPhdr && object && object->getLoadAddress();
00229   }
00230 
00231   //If we want to try a mode where we add the program headers to a library
00232   // that can be loaded anywhere, and put the program headers in the first 
00233   // page (avoiding the kernel bug), then set library_adjust to getpagesize().
00234   // This will shift all addresses in the library down by a page, accounting
00235   // for the extra page for program headers.  This causes some significant
00236   // changes to the binary, and isn't well tested.
00237   library_adjust = 0;
00238   if( cannotRelocatePhdrs() && !movePHdrsFirst ) {
00239       movePHdrsFirst = true;
00240       library_adjust = getpagesize();
00241   }
00242 }
00243 
00244 bool emitElf64::createElfSymbol(Symbol *symbol, unsigned strIndex, vector<Elf64_Sym *> &symbols, bool dynSymFlag)
00245 {
00246   Elf64_Sym *sym = new Elf64_Sym();
00247   sym->st_name = strIndex;
00248 
00249   // OPD-based systems
00250   if (symbol->getPtrOffset()) {
00251     sym->st_value = symbol->getPtrOffset() + library_adjust;
00252   }
00253   else if (symbol->getOffset()) {
00254        sym->st_value = symbol->getOffset() + library_adjust;
00255   }
00256 
00257   sym->st_size = symbol->getSize();
00258   sym->st_other = ELF64_ST_VISIBILITY(elfSymVisibility(symbol->getVisibility()));
00259   sym->st_info = (unsigned char) ELF64_ST_INFO(elfSymBind(symbol->getLinkage()), elfSymType(symbol));
00260 
00261   if (symbol->getRegion())
00262     {
00263 #if defined(os_freebsd)
00264       sym->st_shndx = (Elf64_Half) symbol->getRegion()->getRegionNumber();
00265 #else
00266       sym->st_shndx = (Elf64_Section) symbol->getRegion()->getRegionNumber();
00267 #endif
00268     }
00269   else if (symbol->isAbsolute())
00270     {
00271       sym->st_shndx = SHN_ABS;
00272     }
00273   else
00274     {
00275       sym->st_shndx = 0;
00276     }
00277 
00278   symbols.push_back(sym);
00279 
00280   if (dynSymFlag) 
00281     {
00282       //printf("dynamic symbol: %s\n", symbol->getMangledName().c_str());
00283 
00284       char msg[2048];
00285       char *mpos = msg;
00286       msg[0] = '\0';
00287       string fileName;
00288 
00289       if (!symbol->getVersionFileName(fileName))
00290     {
00291       //verdef entry
00292       vector<string> *vers;
00293       if (!symbol->getVersions(vers))
00294         {
00295           if (symbol->getLinkage() == Symbol::SL_GLOBAL)
00296         {
00297           versionSymTable.push_back(1);
00298 
00299         }
00300           else
00301         {
00302           versionSymTable.push_back(0);
00303           mpos += sprintf(mpos, "  local\n");
00304         }
00305         }
00306       else 
00307         {
00308           if (vers->size() > 0)
00309         {
00310           // new verdef entry
00311           mpos += sprintf(mpos, "verdef: symbol=%s  version=%s ", symbol->getMangledName().c_str(), (*vers)[0].c_str());
00312           if (verdefEntries.find((*vers)[0]) != verdefEntries.end())
00313             {
00314               unsigned short index = verdefEntries[(*vers)[0]];
00315               if (symbol->getVersionHidden()) index += 0x8000;
00316               versionSymTable.push_back(index);
00317             }
00318           else 
00319             {
00320               unsigned short index = curVersionNum;
00321               if (symbol->getVersionHidden()) index += 0x8000;
00322               versionSymTable.push_back(index);
00323 
00324               verdefEntries[(*vers)[0]] = curVersionNum;
00325               curVersionNum++;
00326             }
00327         }
00328           // add all versions to the verdef entry
00329           for (unsigned i=0; i< vers->size(); i++)
00330         {
00331           mpos += sprintf(mpos, "  {%s}", (*vers)[i].c_str());
00332           if (versionNames.find((*vers)[i]) == versionNames.end())
00333             {
00334               versionNames[(*vers)[i]] = 0;
00335             }
00336 
00337           if (find( verdauxEntries[verdefEntries[(*vers)[0]]].begin(),
00338                 verdauxEntries[verdefEntries[(*vers)[0]]].end(),
00339                 (*vers)[i]) == verdauxEntries[verdefEntries[(*vers)[0]]].end())
00340             {
00341               verdauxEntries[verdefEntries[(*vers)[0]]].push_back((*vers)[i]);
00342             }
00343         }
00344           mpos += sprintf(mpos, "\n");
00345         }
00346     }
00347       else 
00348     {           
00349       //verneed entry
00350       mpos += sprintf(mpos, "need: symbol=%s    filename=%s\n", 
00351               symbol->getMangledName().c_str(), fileName.c_str());
00352 
00353       vector<string> *vers;
00354 
00355       if (!symbol->getVersions(vers) || (vers && vers->size() != 1)) 
00356         {
00357           // add an unversioned dependency
00358           if (fileName != "") 
00359         {
00360           // If the file is not an executable, then add to unversioned entries
00361          if (!symbol->getReferringSymbol()->getSymtab()->isExec()) {
00362             if (find(unversionedNeededEntries.begin(),
00363                      unversionedNeededEntries.end(),
00364                      fileName) == unversionedNeededEntries.end()) 
00365                 {
00366                mpos += sprintf(mpos, "  new unversioned: %s\n", fileName.c_str());
00367                unversionedNeededEntries.push_back(fileName);
00368                 }
00369          }
00370 
00371           if (symbol->getLinkage() == Symbol::SL_GLOBAL) {
00372             mpos += sprintf(mpos, "  global (w/ filename)\n");
00373             versionSymTable.push_back(1);
00374           }
00375           else {
00376 
00377             versionSymTable.push_back(0);
00378           }
00379         }
00380         } 
00381       else 
00382         {
00383           if (!vers)
00384         {
00385           fprintf(stderr, "%s[%d]:  weird inconsistency here...  getVersions returned NULL\n",
00386               FILE__, __LINE__);
00387         }
00388           else
00389         {
00390           // There should only be one version string by this time
00391           //If the verison name already exists then add the same version number to the version symbol table
00392           //Else give a new number and add it to the mapping.
00393           if (versionNames.find((*vers)[0]) == versionNames.end()) 
00394             {
00395               mpos += sprintf(mpos, "  new version name: %s\n", (*vers)[0].c_str());
00396               versionNames[(*vers)[0]] = 0;
00397             }
00398 
00399           if (verneedEntries.find(fileName) != verneedEntries.end())
00400             {
00401               if (verneedEntries[fileName].find((*vers)[0]) != verneedEntries[fileName].end()) 
00402             {
00403               mpos += sprintf(mpos, "  vernum: %d\n", verneedEntries[fileName][(*vers)[0]]);
00404               versionSymTable.push_back((unsigned short) verneedEntries[fileName][(*vers)[0]]);
00405             }
00406               else
00407             {
00408               mpos += sprintf(mpos, "  new entry #%d: %s [%s]\n", 
00409                       curVersionNum, (*vers)[0].c_str(), fileName.c_str());
00410               versionSymTable.push_back((unsigned short) curVersionNum);
00411               verneedEntries[fileName][(*vers)[0]] = curVersionNum;
00412               curVersionNum++;
00413             }
00414             }
00415           else
00416             {
00417               mpos += sprintf(mpos, "  new entry #%d: %s [%s]\n", 
00418                       curVersionNum, (*vers)[0].c_str(), fileName.c_str());
00419               versionSymTable.push_back((unsigned short) curVersionNum);
00420               verneedEntries[fileName][(*vers)[0]] = curVersionNum;
00421               curVersionNum++;
00422             }
00423         } 
00424         }
00425     }
00426 #ifdef BINEDIT_DEBUG
00427       printf("%s", msg);
00428 #endif
00429     }
00430 
00431   return true;
00432 }
00433 
00434 // Find the end of data/text segment
00435 void emitElf64::findSegmentEnds()
00436 {
00437   Elf64_Phdr *tmp = elf64_getphdr(oldElf);
00438   // Find the offset of the start of the text & the data segment
00439   // The first LOAD segment is the text & the second LOAD segment 
00440   // is the data
00441   dataSegEnd = 0;
00442   for(unsigned i=0;i<oldEhdr->e_phnum;i++)
00443     {
00444       if(tmp->p_type == PT_LOAD)
00445         {
00446       if (dataSegEnd < tmp->p_vaddr+tmp->p_memsz)
00447         dataSegEnd = tmp->p_vaddr+tmp->p_memsz;
00448         }else if( PT_TLS == tmp->p_type ) {
00449             TLSExists = true;
00450         }
00451       tmp++;
00452     }
00453 }
00454 
00455 // Rename an old section. Lengths of old and new names must match.
00456 // Only renames the FIRST matching section encountered.
00457 void emitElf64::renameSection(const std::string &oldStr, const std::string &newStr, bool renameAll) {
00458   assert(oldStr.length() == newStr.length());
00459   for (unsigned k = 0; k < secNames.size(); k++) {
00460     if (secNames[k] == oldStr) {
00461       secNames[k].replace(0, oldStr.length(), newStr);
00462       if (!renameAll)
00463     break;
00464     }
00465   }
00466 }
00467 
00468 bool emitElf64::driver(Symtab *obj, string fName){
00469   int newfd;
00470   Region *foundSec = NULL;
00471   unsigned pgSize = getpagesize();
00472   rewrite_printf("::driver for emitElf64\n");
00473 
00474   string strtmpl = fName + "XXXXXX";
00475   char buf[strtmpl.length() + 1];
00476   strncpy(buf, strtmpl.c_str(), strtmpl.length()+1);
00477 
00478   newfd = mkstemp(buf);
00479 
00480   if (newfd == -1) {
00481     log_elferror(err_func_, "error opening file to write symbols");
00482     return false;
00483   }
00484   strtmpl = buf;
00485 
00486   fchmod(newfd, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP);
00487   rewrite_printf("Emitting to temporary file %s\n", buf);
00488 
00489 #if 0
00490   //open ELF File for writing
00491   if((newfd = (open(fName.c_str(), O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP)))==-1){ 
00492     log_elferror(err_func_, "error opening file to write symbols");
00493     return false;
00494   }
00495 #endif
00496 
00497   if((newElf = elf_begin(newfd, ELF_C_WRITE, NULL)) == NULL){
00498     log_elferror(err_func_, "NEWELF_BEGIN_FAIL");
00499     fflush(stdout);
00500     cerr << "Failed to elf_begin" << endl;
00501     return false;
00502   }
00503 
00504   //Section name index for all sections
00505   secNames.push_back("");
00506   secNameIndex = 1;
00507   //Section name index for new sections
00508   loadSecTotalSize = 0;
00509   unsigned NOBITStotalsize = 0;
00510   int dirtySecsChange = 0;
00511   unsigned extraAlignSize = 0;
00512     
00513   // ".shstrtab" section: string table for section header names
00514   const char *shnames = pdelf_get_shnames(oldElfHandle);
00515   if (shnames == NULL) {
00516     log_elferror(err_func_, ".shstrtab section");
00517     return false;
00518   } 
00519 
00520   // Write the Elf header first!
00521   newEhdr = elf64_newehdr(newElf);
00522   if(!newEhdr){
00523     log_elferror(err_func_, "newEhdr failed\n");
00524     return false;
00525   }
00526   oldEhdr = elf64_getehdr(oldElf);
00527   memcpy(newEhdr, oldEhdr, sizeof(Elf64_Ehdr));
00528     
00529   newEhdr->e_shnum += newSecs.size();
00530 
00531   // Find the end of text and data segments
00532   findSegmentEnds();
00533   unsigned insertPoint = oldEhdr->e_shnum;
00534   unsigned insertPointOffset = 0;
00535   unsigned NOBITSstartPoint = oldEhdr->e_shnum;
00536 
00537   if(movePHdrsFirst)
00538   {
00539      newEhdr->e_phoff = sizeof(Elf64_Ehdr);
00540   }
00541     
00542   /* flag the file for no auto-layout */
00543   elf_flagelf(newElf,ELF_C_SET,ELF_F_LAYOUT);
00544     
00545   Elf_Scn *scn = NULL, *newscn = NULL;
00546   Elf_Data *newdata = NULL, *olddata = NULL;
00547   Elf64_Shdr *newshdr = NULL, *shdr = NULL;
00548   dyn_hash_map<unsigned, unsigned> secLinkMapping;
00549   dyn_hash_map<unsigned, unsigned> secInfoMapping;
00550   dyn_hash_map<unsigned, unsigned> changeMapping;
00551   dyn_hash_map<std::string, unsigned> newNameIndexMapping;
00552   dyn_hash_map<unsigned, std::string> oldIndexNameMapping;
00553 
00554   bool createdLoadableSections = false;
00555   unsigned scncount;
00556   unsigned sectionNumber = 0;
00557 
00558   bool startMovingSections = false;
00559   for (scncount = 0; (scn = elf_nextscn(oldElf, scn)); scncount++) {
00560     //copy sections from oldElf to newElf
00561     shdr = elf64_getshdr(scn);
00562 
00563     // resolve section name
00564     const char *name = &shnames[shdr->sh_name];
00565     bool result = obj->findRegion(foundSec, shdr->sh_addr, shdr->sh_size);
00566     if (!result || foundSec->isDirty()) {
00567       result = obj->findRegion(foundSec, name);
00568     }
00569 
00570     // write the shstrtabsection at the end
00571     if(!strcmp(name, ".shstrtab"))
00572       continue;
00573 
00574     sectionNumber++;
00575     changeMapping[sectionNumber] = 0;
00576     oldIndexNameMapping[scncount+1] = string(name);
00577     newNameIndexMapping[string(name)] = sectionNumber;
00578 
00579     newscn = elf_newscn(newElf);
00580     newshdr = elf64_getshdr(newscn);
00581     newdata = elf_newdata(newscn);
00582     olddata = elf_getdata(scn,NULL);
00583     memcpy(newshdr, shdr, sizeof(Elf64_Shdr));
00584     memcpy(newdata,olddata, sizeof(Elf_Data));
00585 
00586 
00587     secNames.push_back(name);
00588     newshdr->sh_name = secNameIndex;
00589     secNameIndex += strlen(name) + 1;
00590     
00591     if (newshdr->sh_addr) {
00592        newshdr->sh_addr += library_adjust;
00593     }
00594 
00595     if(foundSec->isDirty())
00596     {
00597        newdata->d_buf = (char *)malloc(foundSec->getDiskSize());
00598        memcpy(newdata->d_buf, foundSec->getPtrToRawData(), foundSec->getDiskSize());
00599        newdata->d_size = foundSec->getDiskSize();
00600        newshdr->sh_size = foundSec->getDiskSize();
00601     }
00602     else if(olddata->d_buf)     //copy the data buffer from oldElf
00603     {
00604        newdata->d_buf = (char *)malloc(olddata->d_size);
00605        memcpy(newdata->d_buf, olddata->d_buf, olddata->d_size);
00606       }
00607 
00608     if (newshdr->sh_entsize && (newshdr->sh_size % newshdr->sh_entsize != 0))
00609     {
00610        newshdr->sh_entsize = 0x0;
00611     }
00612 
00613     if(BSSExpandFlag) {
00614       // Add the expanded SHT_NOBITS section size if the section comes after those sections 
00615       if(scncount > NOBITSstartPoint)
00616     newshdr->sh_offset += NOBITStotalsize;
00617     
00618       // Expand the NOBITS sections in file & and change the type from SHT_NOBITS to SHT_PROGBITS
00619       if(shdr->sh_type == SHT_NOBITS)
00620     {
00621       newshdr->sh_type = SHT_PROGBITS;
00622       newdata->d_buf = (char *)malloc(shdr->sh_size);
00623       memset(newdata->d_buf, '\0', shdr->sh_size);
00624       newdata->d_size = shdr->sh_size;
00625       if(NOBITSstartPoint == oldEhdr->e_shnum)
00626         NOBITSstartPoint = scncount;
00627       NOBITStotalsize += shdr->sh_size; 
00628     }
00629     }    
00630       
00631     std::vector <std::vector <unsigned long> > moveSecAddrRange = obj->getObject()->getMoveSecAddrRange();
00632 
00633     for (unsigned i = 0 ; i != moveSecAddrRange.size(); i++) {
00634       if ( (moveSecAddrRange[i][0] == shdr->sh_addr) ||
00635        (shdr->sh_addr >= moveSecAddrRange[i][0] && shdr->sh_addr < moveSecAddrRange[i][1]) )
00636     {
00637       newshdr->sh_type = SHT_PROGBITS;
00638       changeMapping[sectionNumber] = 1;
00639       string newName = ".o";
00640       newName.append(name, 2, strlen(name));
00641       renameSection((string)name, newName, false);
00642     }
00643     }
00644 
00645     if((obj->getObject()->getStrtabAddr() != 0 &&
00646        obj->getObject()->getStrtabAddr() == shdr->sh_addr) ||
00647        !strcmp(name, STRTAB_NAME))
00648       {
00649     symStrData = newdata;
00650     updateSymbols(symTabData, symStrData, loadSecTotalSize);
00651       }
00652         
00653     //Change sh_link for .symtab to point to .strtab
00654     if((obj->getObject()->getSymtabAddr() != 0 && 
00655        obj->getObject()->getSymtabAddr() == shdr->sh_addr) ||
00656        !strcmp(name, SYMTAB_NAME) ){
00657       newshdr->sh_link = secNames.size();
00658       changeMapping[sectionNumber] = 1;
00659       symTabData = newdata;
00660     }
00661 
00662 
00663     if(obj->getObject()->getTextAddr() != 0 &&
00664        obj->getObject()->getTextAddr() == shdr->sh_addr){
00665       textData = newdata;
00666     }
00667 
00668     if(obj->getObject()->getDynamicAddr() != 0 &&
00669        obj->getObject()->getDynamicAddr() == shdr->sh_addr){
00670       dynData = newdata;
00671       dynSegOff = newshdr->sh_offset;
00672       dynSegAddr = newshdr->sh_addr;
00673       // Change the data to update the relocation addr
00674       newshdr->sh_type = SHT_PROGBITS;
00675       changeMapping[sectionNumber] = 1;
00676       string newName = ".o";
00677       newName.append(name, 2, strlen(name));
00678       renameSection((string)name, newName, false);
00679     }
00680 
00681     // Only need to rewrite data section
00682     if( hasRewrittenTLS && foundSec->isTLS() 
00683         && foundSec->getRegionType() == Region::RT_DATA ) 
00684     {
00685         // Clear TLS flag
00686         newshdr->sh_flags &= ~SHF_TLS;
00687 
00688         string newName = ".o";
00689         newName.append(name, 2, strlen(name));
00690         renameSection((string)name, newName, false);
00691     }
00692 
00693 #if defined(arch_power) && defined(arch_64bit)
00694     // DISABLED
00695     if (0 && isStaticBinary && strcmp(name, ".got") == 0) {
00696       string newName = ".o";
00697       newName.append(name, 2, strlen(name));
00698       renameSection((string) name, newName, false);
00699     }
00700 #endif
00701 
00702     if (isStaticBinary && (strcmp(name, ".rela.plt") == 0)) {
00703        string newName = ".o";
00704        newName.append(name, 2, strlen(name));
00705        renameSection(name, newName, false);
00706     }
00707 
00708     if (isStaticBinary && (strcmp(name, ".rela.plt") == 0)) {
00709       string newName = ".o";
00710       newName.append(name, 2, strlen(name));
00711       renameSection(name, newName, false);
00712       // Clear the PLT type; use PROGBITS
00713       newshdr->sh_type = SHT_PROGBITS;
00714     }
00715 
00716     // Change offsets of sections based on the newly added sections
00717     if(movePHdrsFirst) {
00718         /* This special case is specific to FreeBSD but there is no hurt in
00719          * handling it on other platforms.
00720          *
00721          * This is necessary because the INTERP header must be located within in
00722          * the first page of the file -- if the section is moved to the next
00723          * page the object file will not be parsed correctly by the kernel.
00724          *
00725          * However, the initial sections still need to be shifted, but just
00726          * by the difference in size of the new PHDR segment. 
00727          */
00728         if( newshdr->sh_offset > 0 ) {
00729             if( startMovingSections || obj->isStaticBinary() 
00730                 || obj->getObjectType() == obj_SharedLib ) newshdr->sh_offset += pgSize;
00731             else if( createNewPhdr ) newshdr->sh_offset += oldEhdr->e_phentsize;
00732         }
00733     }       
00734 
00735     if(scncount > insertPoint && newshdr->sh_offset >= insertPointOffset )
00736       newshdr->sh_offset += loadSecTotalSize;
00737 
00738     if (newshdr->sh_offset > 0 ) 
00739         newshdr->sh_offset += dirtySecsChange;
00740 
00741     if (BSSExpandFlag) {
00742         if( newshdr->sh_offset > 0 ) {
00743             newshdr->sh_offset += extraAlignSize;
00744         }
00745     }else if (newshdr->sh_offset >= insertPointOffset ) {
00746         newshdr->sh_offset += extraAlignSize;
00747     }
00748 
00749     if(foundSec->isDirty()) 
00750       dirtySecsChange += newshdr->sh_size - shdr->sh_size;
00751 
00752     if(BSSExpandFlag && newshdr->sh_addr) {
00753       unsigned newOff = newshdr->sh_offset - (newshdr->sh_offset & (pgSize-1)) + (newshdr->sh_addr & (pgSize-1));
00754       if(newOff < newshdr->sh_offset)
00755     newOff += pgSize;
00756       extraAlignSize += newOff - newshdr->sh_offset;
00757       newshdr->sh_offset = newOff;
00758     }
00759     
00760     secLinkMapping[sectionNumber] = shdr->sh_link; 
00761     secInfoMapping[sectionNumber] = shdr->sh_info; 
00762 
00763     rewrite_printf("section %s addr = %lx off = %lx size = %lx\n",
00764             name, newshdr->sh_addr, newshdr->sh_offset, newshdr->sh_size);
00765 
00766     //Insert new loadable sections at the end of data segment           
00767     if (shdr->sh_addr+shdr->sh_size == dataSegEnd && !createdLoadableSections) {
00768       createdLoadableSections = true;
00769       insertPoint = scncount;
00770       if( SHT_NOBITS == shdr->sh_type ) {
00771           insertPointOffset = shdr->sh_offset;
00772       }else{
00773           insertPointOffset = shdr->sh_offset + shdr->sh_size;
00774       }
00775       
00776       if(!createLoadableSections(obj,newshdr, extraAlignSize, 
00777                                  newNameIndexMapping, sectionNumber))        
00778          return false;
00779       if (createNewPhdr && !movePHdrsFirst) {
00780      sectionNumber++;
00781          createNewPhdrRegion(newNameIndexMapping);
00782     }
00783 
00784         // Update the heap symbols, now that loadSecTotalSize is set
00785         updateSymbols(dynsymData, dynStrData, loadSecTotalSize);
00786 
00787     }
00788 
00789     if ( 0 > elf_update(newElf, ELF_C_NULL))
00790     {
00791        fprintf(stderr, "%s[%d]:  elf_update failed: %d, %s\n", FILE__, __LINE__, elf_errno(), elf_errmsg(elf_errno()));
00792        return false;
00793     }
00794 
00795     if(!strcmp(name, INTERP_NAME)) {
00796         startMovingSections = true;
00797     }
00798   }
00799 
00800   // Add non-loadable sections at the end of object file
00801   if(!createNonLoadableSections(newshdr))
00802     return false;
00803 
00804   if ( 0 >  elf_update(newElf, ELF_C_NULL))
00805   {
00806      fprintf(stderr, "%s[%d]:  elf_update failed: %d, %s\n", FILE__, __LINE__, elf_errno(), elf_errmsg(elf_errno()));
00807      return false;
00808   }
00809    
00810   //Add the section header table right at the end        
00811   addSectionHeaderTable(newshdr);
00812 
00813   // Second iteration to fix the link fields to point to the correct section
00814   scn = NULL;
00815 
00816   for (scncount = 0; (scn = elf_nextscn(newElf, scn)); scncount++) {
00817     shdr = elf64_getshdr(scn);
00818     if (changeMapping[scncount+1] == 0 && secLinkMapping[scncount+1] != 0) {
00819       unsigned linkIndex = secLinkMapping[scncount+1];
00820       string secName = oldIndexNameMapping[linkIndex];
00821       unsigned newLinkIndex = newNameIndexMapping[secName];
00822       shdr->sh_link = newLinkIndex;
00823     } 
00824 
00825     if (changeMapping[scncount+1] == 0 && secInfoMapping[scncount+1] != 0) {
00826       // For REL and RELA section, info field is a section index - hence of the index changes, the info field must change.
00827       // For SYMTAB and DYNSYM, info field is OS specific - so just copy it.
00828       // For others, info field is 0, so just copy it
00829       if (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA) {
00830     unsigned infoIndex = secInfoMapping[scncount+1];
00831     string secName = oldIndexNameMapping[infoIndex];
00832     unsigned newInfoIndex = newNameIndexMapping[secName];
00833     shdr->sh_info = newInfoIndex;
00834       } 
00835     }
00836   }
00837 
00838   newEhdr->e_shstrndx = scncount;
00839 
00840   // Move the section header to the end
00841   newEhdr->e_shoff =shdr->sh_offset+shdr->sh_size;
00842   if (newEhdr->e_shoff % 8)
00843     newEhdr->e_shoff += 8 - (newEhdr->e_shoff % 8);
00844 
00845   //copy program headers
00846   oldPhdr = elf64_getphdr(oldElf);
00847   fixPhdrs(extraAlignSize);
00848 
00849   //Write the new Elf file
00850   if (elf_update(newElf, ELF_C_WRITE) < 0){
00851     int err;
00852     if ((err = elf_errno()) != 0)
00853       {
00854     const char *msg = elf_errmsg(err);
00855     /* print msg */
00856     fprintf(stderr, "Error: Unable to write ELF file: %s\n", msg);
00857       }
00858     log_elferror(err_func_, "elf_update failed");
00859     return false;
00860   }
00861   elf_end(newElf);
00862   if (hasPHdrSectionBug()) {
00863      unsigned long ehdr_off = (unsigned long) &(((Elf64_Ehdr *) 0x0)->e_phoff);
00864      lseek(newfd, ehdr_off, SEEK_SET);
00865      Elf64_Off offset = (Elf64_Off) phdr_offset;
00866      write(newfd, &offset, sizeof(Elf64_Off));
00867   }
00868   close(newfd);
00869 
00870   if (::rename(strtmpl.c_str(), fName.c_str())) {
00871      return false;
00872   }
00873 
00874   return true;
00875 }
00876 
00877 void emitElf64::createNewPhdrRegion(dyn_hash_map<std::string, unsigned> &newNameIndexMapping)
00878 {
00879    assert(!movePHdrsFirst);
00880 
00881    unsigned phdr_size = oldEhdr->e_phnum*oldEhdr->e_phentsize;
00882    if (createNewPhdr)
00883       phdr_size += oldEhdr->e_phentsize;
00884 
00885    unsigned align = 0;
00886    if (currEndOffset % 8)
00887       align = 8 - (currEndOffset % 8);
00888 
00889    newEhdr->e_phoff = currEndOffset + align;
00890    phdr_offset = newEhdr->e_phoff;
00891 
00892    Address endaddr = currEndAddress;
00893    currEndAddress += phdr_size + align;
00894    currEndOffset += phdr_size + align;
00895    loadSecTotalSize += phdr_size + align;
00896 
00897    //libelf.so.1 is annoying.  It'll overwrite the data
00898    // between sections with 0's, even if we've stuck the
00899    // program headers in there.  Create a dummy section
00900    // to contain the program headers.
00901    phdrs_scn = elf_newscn(newElf);
00902    Elf64_Shdr *newshdr = elf64_getshdr(phdrs_scn);
00903    const char *newname = ".dynphdrs";
00904 
00905    secNames.push_back(newname);
00906    newNameIndexMapping[newname] = secNames.size() - 1;
00907    newshdr->sh_name = secNameIndex;
00908    secNameIndex += strlen(newname) + 1;
00909    newshdr->sh_flags = SHF_ALLOC;
00910     if (isBlueGeneQ) newshdr->sh_flags = bgq_sh_flags;
00911    newshdr->sh_type = SHT_PROGBITS;
00912    newshdr->sh_offset = newEhdr->e_phoff;
00913    newshdr->sh_addr = endaddr + align;
00914    newshdr->sh_size = phdr_size;
00915    newshdr->sh_link = SHN_UNDEF;
00916    newshdr->sh_info = 0;
00917    newshdr->sh_addralign = 4;
00918    newshdr->sh_entsize = newEhdr->e_phentsize;
00919     phdrSegOff = newshdr->sh_offset;
00920     phdrSegAddr = newshdr->sh_addr;
00921     
00922 }
00923 
00924 void emitElf64::fixPhdrs(unsigned &extraAlignSize)
00925 {
00926   unsigned pgSize = getpagesize();
00927   Elf64_Phdr *old = oldPhdr;
00928 
00929   newEhdr->e_phnum = oldEhdr->e_phnum;
00930   newEhdr->e_phentsize = oldEhdr->e_phentsize;
00931 
00932   if(createNewPhdr) {
00933      newEhdr->e_phnum++;
00934      if( hasRewrittenTLS && !TLSExists ) newEhdr->e_phnum++;
00935   }
00936 
00937   bool added_new_sec = false;    
00938   bool replaced = false;
00939 
00940   if (!hasPHdrSectionBug())
00941      newPhdr = elf64_newphdr(newElf,newEhdr->e_phnum);
00942   else {
00943      newPhdr = (Elf64_Phdr *) malloc(sizeof(Elf64_Phdr) * newEhdr->e_phnum);
00944   }
00945   void *phdr_data = (void *) newPhdr;
00946 
00947   Elf64_Phdr newSeg;
00948   bool last_load_segment = false;
00949   for(unsigned i=0;i<oldEhdr->e_phnum;i++)
00950   {
00951     /*
00952      * If we've created a new loadable segment, we need to insert a new
00953      * program header amidst the other loadable segments.
00954      * 
00955      * ELF format says:
00956      *
00957      * `Loadable segment entries in the program header table appear in
00958      * ascending order, sorted on the p_vaddr member.'
00959      * 
00960      * Note: replacing NOTE with LOAD section for bluegene systems 
00961      * does not follow this rule.
00962      */
00963 
00964     Elf64_Phdr * insert_phdr = NULL;
00965    if(createNewPhdr && !added_new_sec && firstNewLoadSec) {
00966        if(i+1 == oldEhdr->e_phnum) {
00967             insert_phdr = newPhdr + 1;
00968 
00969         }
00970         else if(old->p_type == PT_LOAD && (old+1)->p_type != PT_LOAD) {
00971             // insert at end of loadable phdrs
00972             insert_phdr = newPhdr+1;
00973         last_load_segment = true;
00974         }
00975         else if(old->p_type != PT_LOAD &&
00976                 (old+1)->p_type == PT_LOAD &&
00977                 newSegmentStart < (old+1)->p_vaddr)
00978         {
00979             // insert at beginning of loadable list (after the
00980             // current phdr)
00981             insert_phdr = newPhdr+1;
00982         }
00983         else if(old->p_type == PT_LOAD &&
00984                 (old+1)->p_type == PT_LOAD &&
00985                 newSegmentStart >= old->p_vaddr &&
00986                 newSegmentStart < (old+1)->p_vaddr)
00987         {
00988             // insert in middle of loadable list, after current
00989             insert_phdr = newPhdr+1;
00990         }
00991         else if(i == 0 && 
00992                 old->p_type == PT_LOAD &&
00993                 newSegmentStart < old->p_vaddr)
00994         {
00995             // insert BEFORE current phdr
00996             insert_phdr = newPhdr;
00997             newPhdr++;
00998         }
00999     }
01000 
01001       if(insert_phdr)
01002       {
01003          newSeg.p_type = PT_LOAD;
01004          newSeg.p_offset = firstNewLoadSec->sh_offset;
01005          newSeg.p_vaddr = newSegmentStart;
01006          newSeg.p_paddr = newSeg.p_vaddr;
01007          newSeg.p_filesz = loadSecTotalSize - (newSegmentStart - firstNewLoadSec->sh_addr);
01008          newSeg.p_memsz = (currEndAddress - firstNewLoadSec->sh_addr) - (newSegmentStart - firstNewLoadSec->sh_addr);
01009      newSeg.p_flags = PF_R+PF_W+PF_X;
01010          newSeg.p_align = pgSize;
01011          memcpy(insert_phdr, &newSeg, oldEhdr->e_phentsize);
01012          added_new_sec = true;
01013          rewrite_printf("Added New program header : offset 0x%lx,addr 0x%lx file Size 0x%lx memsize 0x%lx \n", newSeg.p_paddr, newSeg.p_vaddr, newSeg.p_filesz, newSeg.p_memsz);
01014 #ifdef BINEDIT_DEBUG
01015          fprintf(stderr, "Added New program header : offset 0x%lx,addr 0x%lx\n", newPhdr->p_offset, newPhdr->p_vaddr);
01016 #endif
01017       }
01018 
01019     memcpy(newPhdr, old, oldEhdr->e_phentsize);
01020 
01021      // Expand the data segment to include the new loadable sections
01022      // Also add a executable permission to the segment
01023 
01024      if(old->p_type == PT_DYNAMIC){
01025     newPhdr->p_vaddr = dynSegAddr;
01026     newPhdr->p_paddr = dynSegAddr;
01027     newPhdr->p_offset = dynSegOff;
01028     newPhdr->p_memsz = dynSegSize;
01029     newPhdr->p_filesz = newPhdr->p_memsz;
01030      }
01031      else if(old->p_type == PT_PHDR){
01032     if(createNewPhdr && !movePHdrsFirst)
01033             newPhdr->p_vaddr = phdrSegAddr;
01034         else if (createNewPhdr && movePHdrsFirst)
01035             newPhdr->p_vaddr = old->p_vaddr - pgSize;
01036     else
01037             newPhdr->p_vaddr = old->p_vaddr;
01038         newPhdr->p_offset = newEhdr->e_phoff;
01039         newPhdr->p_paddr = newPhdr->p_vaddr;
01040         newPhdr->p_filesz = sizeof(Elf64_Phdr) * newEhdr->e_phnum;
01041         newPhdr->p_memsz = newPhdr->p_filesz;
01042      }else if( hasRewrittenTLS && old->p_type == PT_TLS) {
01043           newPhdr->p_offset = newTLSData->sh_offset;
01044           newPhdr->p_vaddr = newTLSData->sh_addr;
01045           newPhdr->p_paddr = newTLSData->sh_addr;
01046           newPhdr->p_filesz = newTLSData->sh_size;
01047           newPhdr->p_memsz = newTLSData->sh_size + old->p_memsz - old->p_filesz;
01048           newPhdr->p_align = newTLSData->sh_addralign;
01049      }else if (old->p_type == PT_LOAD) {
01050         if(!createNewPhdr && newPhdr->p_align > pgSize) { //not on bluegene
01051            newPhdr->p_align = pgSize;
01052         }
01053         if(BSSExpandFlag) {
01054            if(old->p_flags == 6 || old->p_flags == 7)
01055            {
01056               newPhdr->p_memsz += loadSecTotalSize + extraAlignSize;
01057               newPhdr->p_filesz = newPhdr->p_memsz;
01058               newPhdr->p_flags = 7;
01059            }    
01060         }   
01061 
01062         if(movePHdrsFirst) {
01063            if (!old->p_offset) {
01064               if (newPhdr->p_vaddr)
01065                  newPhdr->p_vaddr = old->p_vaddr - pgSize;
01066           newPhdr->p_paddr = newPhdr->p_vaddr;
01067           newPhdr->p_filesz += pgSize;
01068           newPhdr->p_memsz = newPhdr->p_filesz;
01069            } else {
01070               newPhdr->p_offset += pgSize;
01071            }
01072            if (newPhdr->p_vaddr) {
01073               newPhdr->p_vaddr += library_adjust;
01074               newPhdr->p_paddr += library_adjust;
01075            }
01076         }
01077      }else if (replaceNOTE && old->p_type == PT_NOTE && !replaced) {
01078      replaced = true;
01079          newPhdr->p_type = PT_LOAD;
01080          newPhdr->p_offset = firstNewLoadSec->sh_offset;
01081          newPhdr->p_vaddr = newSegmentStart;
01082          newPhdr->p_paddr = newPhdr->p_vaddr; 
01083          newPhdr->p_filesz = loadSecTotalSize - (newSegmentStart - firstNewLoadSec->sh_addr);
01084          newPhdr->p_memsz = (currEndAddress - firstNewLoadSec->sh_addr) - (newSegmentStart - firstNewLoadSec->sh_addr);
01085          newPhdr->p_flags = PF_R+PF_W+PF_X;
01086          newPhdr->p_align = pgSize;
01087      }
01088      else if (old->p_type == PT_INTERP && movePHdrsFirst
01089              && old->p_offset && newEhdr->e_phnum >= oldEhdr->e_phnum)
01090      {
01091          newPhdr->p_offset += 
01092              oldEhdr->e_phentsize*(newEhdr->e_phnum-oldEhdr->e_phnum);
01093      }
01094      else if (movePHdrsFirst && old->p_offset) {
01095         newPhdr->p_offset += pgSize;
01096         if (newPhdr->p_vaddr) {
01097            newPhdr->p_vaddr += library_adjust;
01098            newPhdr->p_paddr += library_adjust;
01099         }
01100      }
01101 
01102      /* For BlueGeneQ statically linked binary, we cannot create a new LOAD section, 
01103          hence we extend existing LOAD section to include instrmentation.
01104           A new LOAD section must be aligned to 1MB in BlueGene. 
01105           But if we create a LOAD segment after 1MB, the TOC pointer will no longer be able to reach the new segment,
01106           as we have only 4 byte offset from TOC */
01107 
01108      if(0 && isBlueGeneQ && isStaticBinary && last_load_segment) {
01109 
01110         // add new load to this segment
01111          newPhdr->p_filesz = (newSeg.p_offset - newPhdr->p_offset) + loadSecTotalSize - (newSegmentStart - firstNewLoadSec->sh_addr);
01112          newPhdr->p_memsz = (newSegmentStart -  newPhdr->p_vaddr) + (currEndAddress - firstNewLoadSec->sh_addr) - (newSegmentStart - firstNewLoadSec->sh_addr);
01113          newPhdr->p_flags = PF_R+PF_W+PF_X;
01114         last_load_segment = false;
01115 
01116         // add new load to this segment
01117      } else {
01118          if(insert_phdr)
01119             newPhdr++;
01120     }   
01121 
01122      rewrite_printf("Existing program header: type %u, offset 0x%lx, addr 0x%lx\n", 
01123              newPhdr->p_type, newPhdr->p_offset, newPhdr->p_vaddr);
01124      
01125      newPhdr++;
01126 
01127      old++;
01128   }
01129 
01130   if( hasRewrittenTLS && !TLSExists ) {
01131     newPhdr->p_type = PT_TLS;
01132     newPhdr->p_offset = newTLSData->sh_offset;
01133     newPhdr->p_vaddr = newTLSData->sh_addr;
01134     newPhdr->p_filesz = newTLSData->sh_size;
01135     newPhdr->p_memsz = newTLSData->sh_size;
01136     newPhdr->p_align = newTLSData->sh_addralign;
01137   }
01138   
01139   if (!phdrs_scn)
01140      return;
01141   //We made a new section to contain the program headers--keeps
01142   // libelf from overwriting the program headers data when outputing
01143   // sections.  Fill in the new section's data with what we just wrote.
01144   Elf_Data *data = elf_newdata(phdrs_scn);
01145   size_t total_size = newEhdr->e_phnum * newEhdr->e_phentsize;
01146   data->d_buf = malloc(total_size);
01147   memcpy(data->d_buf, phdr_data, total_size);
01148   data->d_size = total_size;
01149   data->d_align = 0;
01150   data->d_off = 0;
01151   data->d_type = ELF_T_BYTE;
01152   data->d_version = 1;
01153 }
01154 
01155 #if !defined(DT_GNU_HASH)
01156 #define DT_GNU_HASH 0x6ffffef5
01157 #endif
01158 #if !defined(DT_GNU_CONFLICT)
01159 #define DT_GNU_CONFLICT 0x6ffffef8
01160 #endif
01161 
01162 //This method updates the .dynamic section to reflect the changes to the relocation section
01163 void emitElf64::updateDynamic(unsigned tag, Elf64_Addr val){
01164   if (isStaticBinary) return;
01165   // This is for REL/RELA if it doesnt already exist in the original binary; 
01166   dynamicSecData[tag][0]->d_tag = tag;
01167   switch(dynamicSecData[tag][0]->d_tag){
01168   case DT_STRSZ:
01169   case DT_RELSZ:
01170   case DT_RELASZ:
01171   case DT_PLTRELSZ:
01172   case DT_RELACOUNT:
01173   case DT_RELENT:
01174   case DT_RELAENT:
01175     dynamicSecData[tag][0]->d_un.d_val = val;
01176     break;
01177   case DT_HASH:
01178   case DT_GNU_HASH:
01179   case DT_SYMTAB:
01180   case DT_STRTAB:
01181   case DT_REL:
01182   case DT_RELA:
01183   case DT_VERSYM:
01184   case DT_JMPREL:
01185     dynamicSecData[tag][0]->d_un.d_ptr = val;
01186     break;
01187   case DT_VERNEED:
01188     dynamicSecData[tag][0]->d_un.d_ptr = val;
01189     dynamicSecData[DT_VERNEEDNUM][0]->d_un.d_val = verneednum;
01190     break;
01191   case DT_VERDEF:
01192     dynamicSecData[tag][0]->d_un.d_ptr = val;
01193     dynamicSecData[DT_VERDEFNUM][0]->d_un.d_val = verdefnum;
01194     break;
01195     }
01196 }
01197 
01198 /* This method sets _end and _END_ to the starting position of the heap in the
01199  * new binary. 
01200  */
01201 void emitElf64::updateSymbols(Elf_Data* symtabData,Elf_Data* strData, unsigned long loadSecsSize){
01202   unsigned pgSize = (unsigned)getpagesize();
01203   if( symtabData && strData && loadSecsSize){
01204     Elf64_Sym *symPtr=(Elf64_Sym*)symtabData->d_buf;
01205     for(unsigned int i=0;i< symtabData->d_size/(sizeof(Elf64_Sym));i++,symPtr++){
01206       if(!(strcmp("_end", (char*) strData->d_buf + symPtr->st_name))){
01207         if( newSegmentStart >= symPtr->st_value ) {
01208             symPtr->st_value += ((newSegmentStart - symPtr->st_value) + loadSecsSize);
01209 
01210             // Advance the location to the next page boundary
01211             symPtr->st_value = (symPtr->st_value & ~(pgSize-1)) + pgSize;
01212         }
01213       }
01214       if(!(strcmp("_END_", (char*) strData->d_buf + symPtr->st_name))){
01215         if( newSegmentStart > symPtr->st_value ) {
01216             symPtr->st_value += (newSegmentStart - symPtr->st_value) + loadSecsSize;
01217             
01218             // Advance the location to the next page boundary
01219             symPtr->st_value = (symPtr->st_value & ~(pgSize-1)) + pgSize;
01220         }
01221       }
01222     }    
01223   }
01224 }
01225 
01226 bool emitElf64::createLoadableSections(Symtab *obj, Elf64_Shdr* &shdr, unsigned &extraAlignSize, dyn_hash_map<std::string, unsigned> &newNameIndexMapping, unsigned &sectionNumber)
01227 {
01228    Elf_Scn *newscn;
01229    Elf_Data *newdata = NULL;
01230 
01231    Elf64_Shdr *newshdr;
01232    std::vector<Elf64_Shdr *> updateDynLinkShdr;
01233    std::vector<Elf64_Shdr *> updateStrLinkShdr;
01234    firstNewLoadSec = NULL;
01235    unsigned pgSize = getpagesize();
01236    unsigned strtabIndex = 0;
01237    unsigned dynsymIndex = 0;
01238    Elf64_Shdr *prevshdr = NULL;
01239 
01240    /*
01241     * Order the new sections such that those with explicit
01242     * memory offsets come before those without (that will be placed
01243     * after the non-zero sections).
01244     *
01245     * zstart is used to place the first zero-offset section if
01246     * no non-zero-offset sections exist.
01247     */
01248    Address zstart = emitElfUtils::orderLoadableSections(obj,newSecs);
01249 
01250    for(unsigned i=0; i < newSecs.size(); i++)
01251    {
01252       if(!newSecs[i]->isLoadable()) {
01253          nonLoadableSecs.push_back(newSecs[i]);
01254          continue;
01255       }
01256       secNames.push_back(newSecs[i]->getRegionName());
01257       newNameIndexMapping[newSecs[i]->getRegionName()] = secNames.size() -1;
01258       sectionNumber++;
01259       // Add a new loadable section
01260       if((newscn = elf_newscn(newElf)) == NULL)
01261       {  
01262          log_elferror(err_func_, "unable to create new function");  
01263          return false;
01264       }     
01265       if ((newdata = elf_newdata(newscn)) == NULL)
01266       {
01267          log_elferror(err_func_, "unable to create section data");  
01268          return false;
01269       } 
01270       memset(newdata, 0, sizeof(Elf_Data));
01271 
01272       // Fill out the new section header    
01273      newshdr = elf64_getshdr(newscn);
01274      newshdr->sh_name = secNameIndex;
01275      newshdr->sh_flags = 0;
01276      newshdr->sh_type = SHT_PROGBITS;
01277      switch(newSecs[i]->getRegionType()){
01278         case Region::RT_TEXTDATA:
01279            newshdr->sh_flags = SHF_EXECINSTR | SHF_ALLOC | SHF_WRITE;
01280            break;
01281         case Region::RT_TEXT:
01282            newshdr->sh_flags = SHF_EXECINSTR | SHF_ALLOC;
01283            break;
01284         case Region::RT_BSS:
01285            newshdr->sh_type = SHT_NOBITS;
01286         case Region::RT_DATA:
01287            newshdr->sh_flags = SHF_WRITE | SHF_ALLOC;
01288            break;
01289         default:
01290            break;
01291      }
01292 
01293      if(shdr->sh_type == SHT_NOBITS) {
01294         newshdr->sh_offset = shdr->sh_offset;
01295      }else if( !firstNewLoadSec || !newSecs[i]->getDiskOffset() ) {
01296         newshdr->sh_offset = shdr->sh_offset+shdr->sh_size;
01297      }else{
01298          // The offset can be computed by determing the difference from
01299          // the first new loadable section
01300          newshdr->sh_offset = firstNewLoadSec->sh_offset +
01301              (newSecs[i]->getDiskOffset() - firstNewLoadSec->sh_addr);
01302 
01303          // Account for inter-section spacing due to alignment constraints
01304          loadSecTotalSize += newshdr->sh_offset - (shdr->sh_offset+shdr->sh_size);
01305      }
01306 
01307      if(newSecs[i]->getDiskOffset())
01308         newshdr->sh_addr = newSecs[i]->getDiskOffset() + library_adjust;
01309      else if(!prevshdr) {
01310         newshdr->sh_addr = zstart + library_adjust;
01311      }
01312      else{
01313         newshdr->sh_addr = prevshdr->sh_addr+ prevshdr->sh_size;
01314      }
01315 
01316      newshdr->sh_link = SHN_UNDEF;
01317      newshdr->sh_info = 0;
01318      newshdr->sh_addralign = newSecs[i]->getMemAlignment();
01319      newshdr->sh_entsize = 0;
01320 
01321      // TLS section
01322      if( newSecs[i]->isTLS() ) {
01323           newTLSData = newshdr;
01324           newshdr->sh_flags |= SHF_TLS;
01325      }
01326 
01327      if(newSecs[i]->getRegionType() == Region::RT_REL ||
01328         newSecs[i]->getRegionType() == Region::RT_PLTREL)    //Relocation section
01329      {
01330         newshdr->sh_type = SHT_REL;
01331         newshdr->sh_flags = SHF_ALLOC;
01332         newshdr->sh_entsize = sizeof(Elf64_Rel);
01333         updateDynLinkShdr.push_back(newshdr);
01334         newdata->d_type = ELF_T_REL;
01335          newdata->d_align = 4;
01336          if (newSecs[i]->getRegionType() == Region::RT_REL)
01337             updateDynamic(DT_REL, newshdr->sh_addr);
01338          else if (newSecs[i]->getRegionType() == Region::RT_PLTREL)
01339             updateDynamic(DT_JMPREL, newshdr->sh_addr);
01340       }
01341       else if(newSecs[i]->getRegionType() == Region::RT_RELA ||
01342               newSecs[i]->getRegionType() == Region::RT_PLTRELA) //Relocation section
01343       {
01344          newshdr->sh_type = SHT_RELA;
01345          newshdr->sh_flags = SHF_ALLOC;
01346          newshdr->sh_entsize = sizeof(Elf64_Rela);
01347          updateDynLinkShdr.push_back(newshdr);
01348          newdata->d_type = ELF_T_RELA;
01349          newdata->d_align = 4;
01350          if (newSecs[i]->getRegionType() == Region::RT_RELA)
01351             updateDynamic(DT_RELA, newshdr->sh_addr);
01352          else if (newSecs[i]->getRegionType() == Region::RT_PLTRELA)
01353             updateDynamic(DT_JMPREL, newshdr->sh_addr);
01354       }
01355       else if(newSecs[i]->getRegionType() == Region::RT_STRTAB)    //String table Section
01356       {
01357          newshdr->sh_type = SHT_STRTAB;
01358          newshdr->sh_entsize = 1;
01359          newdata->d_type = ELF_T_BYTE;
01360          newshdr->sh_link = SHN_UNDEF;
01361          newshdr->sh_flags=  SHF_ALLOC;
01362          newdata->d_align = 1;
01363          dynStrData = newdata;
01364          strtabIndex = secNames.size()-1;
01365          newshdr->sh_addralign = 1;
01366          updateDynamic(DT_STRTAB, newshdr->sh_addr);
01367          updateDynamic(DT_STRSZ, newSecs[i]->getDiskSize());
01368       }
01369       else if(newSecs[i]->getRegionType() == Region::RT_SYMTAB)
01370       {
01371          newshdr->sh_type = SHT_DYNSYM;
01372          newshdr->sh_entsize = sizeof(Elf64_Sym);
01373          newdata->d_type = ELF_T_SYM;
01374          newdata->d_align = 4;
01375          dynsymData = newdata;
01376          newshdr->sh_link = secNames.size();   //.symtab section should have sh_link = index of .strtab for .dynsym
01377          newshdr->sh_flags = SHF_ALLOC ;
01378          dynsymIndex = secNames.size()-1;
01379          updateDynamic(DT_SYMTAB, newshdr->sh_addr);
01380       }
01381       else if(newSecs[i]->getRegionType() == Region::RT_DYNAMIC)
01382       {
01383          newshdr->sh_entsize = sizeof(Elf64_Dyn);
01384          newshdr->sh_type = SHT_DYNAMIC;
01385          newdata->d_type = ELF_T_DYN;
01386          newdata->d_align = 4;
01387          updateStrLinkShdr.push_back(newshdr);
01388          newshdr->sh_flags=  SHF_ALLOC | SHF_WRITE;
01389          dynSegOff = newshdr->sh_offset;
01390          dynSegAddr = newshdr->sh_addr;
01391          dynSegSize = newSecs[i]->getDiskSize();
01392       }
01393       else if(newSecs[i]->getRegionType() == Region::RT_HASH)
01394       {
01395          newshdr->sh_entsize = sizeof(Elf64_Word);
01396          newshdr->sh_type = SHT_HASH;
01397          newdata->d_type = ELF_T_WORD;
01398          newdata->d_align = 4;
01399          updateDynLinkShdr.push_back(newshdr);
01400          newshdr->sh_flags=  SHF_ALLOC;
01401          newshdr->sh_info = 0;
01402          updateDynamic(DT_HASH, newshdr->sh_addr);
01403       }
01404       else if(newSecs[i]->getRegionType() == Region::RT_SYMVERSIONS)
01405       {
01406          newshdr->sh_type = SHT_GNU_versym;
01407          newshdr->sh_entsize = sizeof(Elf64_Half);
01408          newshdr->sh_addralign = 2;
01409          newdata->d_type = ELF_T_HALF;
01410          newdata->d_align = 2;
01411          updateDynLinkShdr.push_back(newshdr);
01412          newshdr->sh_flags = SHF_ALLOC ;
01413          updateDynamic(DT_VERSYM, newshdr->sh_addr);
01414       }
01415       else if(newSecs[i]->getRegionType() == Region::RT_SYMVERNEEDED)
01416       {
01417          newshdr->sh_type = SHT_GNU_verneed;
01418          newshdr->sh_entsize = 0;
01419          newshdr->sh_addralign = 4;
01420          newdata->d_type = ELF_T_VNEED;
01421          newdata->d_align = 4;
01422          updateStrLinkShdr.push_back(newshdr);
01423          newshdr->sh_flags = SHF_ALLOC ;
01424          newshdr->sh_info = 2;
01425          updateDynamic(DT_VERNEED, newshdr->sh_addr);
01426       }
01427       else if(newSecs[i]->getRegionType() == Region::RT_SYMVERDEF)
01428       {
01429          newshdr->sh_type = SHT_GNU_verdef;
01430          newshdr->sh_entsize = 0;
01431          newdata->d_type = ELF_T_VDEF;
01432          newdata->d_align = 4;
01433          updateStrLinkShdr.push_back(newshdr);
01434          newshdr->sh_flags = SHF_ALLOC ;
01435          updateDynamic(DT_VERDEF, newshdr->sh_addr);
01436       }
01437 
01438        if(isBlueGeneQ) newshdr->sh_flags = bgq_sh_flags;
01439 
01440      // Check to make sure the (vaddr for the start of the new segment - the offset) is page aligned
01441      if(!firstNewLoadSec)
01442      {
01443         Offset newoff = newshdr->sh_offset  - (newshdr->sh_offset & (pgSize-1)) + (newshdr->sh_addr & (pgSize-1));
01444         if(newoff < newshdr->sh_offset)
01445            newoff += pgSize;
01446         extraAlignSize += newoff - newshdr->sh_offset;
01447         newshdr->sh_offset = newoff;
01448 
01449     // For now, bluegene is the only system for which createNewPhdr is false. 
01450     // Bluegene compute nodes have a 1MB alignment restructions on PT_LOAD section
01451     // When we are replaceing PT_NOTE with PT_LOAD, we need to make sure the new PT_LOAD is 1MB aligned
01452     if (!createNewPhdr && replaceNOTE)  {
01453             Offset newaddr = newshdr->sh_addr  - (newshdr->sh_addr & (0x100000-1));
01454             if(newaddr < newshdr->sh_addr)
01455                  newaddr += 0x100000;
01456             newshdr->sh_addr = newaddr;
01457     }
01458         newSegmentStart = newshdr->sh_addr;
01459      }
01460 
01461       //Set up the data
01462       newdata->d_buf = malloc(newSecs[i]->getDiskSize());
01463       memcpy(newdata->d_buf, newSecs[i]->getPtrToRawData(), newSecs[i]->getDiskSize());
01464       newdata->d_off = 0;
01465       newdata->d_size = newSecs[i]->getDiskSize();
01466       if (!newdata->d_align)
01467          newdata->d_align = newshdr->sh_addralign;
01468       newshdr->sh_size = newdata->d_size;
01469 
01470      if( newshdr->sh_type == SHT_NOBITS ) {
01471          currEndOffset = newshdr->sh_offset;
01472      }else{
01473         loadSecTotalSize += newshdr->sh_size;
01474         currEndOffset = newshdr->sh_offset + newshdr->sh_size;
01475      }
01476      currEndAddress = newshdr->sh_addr + newshdr->sh_size;
01477 
01478       rewrite_printf("new section %s addr = %lx off = %lx size = %lx\n",
01479               newSecs[i]->getRegionName().c_str(), newshdr->sh_addr, newshdr->sh_offset,
01480               newshdr->sh_size);
01481         
01482       newdata->d_version = 1;
01483 
01484      if (0 > elf_update(newElf, ELF_C_NULL))
01485      {
01486        fprintf(stderr, "%s[%d]:  elf_update failed: %d, %s\n", FILE__, __LINE__, errno, elf_errmsg(elf_errno()));
01487        return false;
01488      }
01489 
01490      shdr = newshdr;
01491      if(!firstNewLoadSec)
01492         firstNewLoadSec = shdr;
01493      secNameIndex += newSecs[i]->getRegionName().size() + 1;
01494      prevshdr = newshdr;
01495   }
01496     
01497   for(unsigned i=0; i < updateDynLinkShdr.size(); i++) {
01498     newshdr = updateDynLinkShdr[i];
01499     newshdr->sh_link = dynsymIndex;   
01500   }
01501     
01502   for(unsigned i=0; i < updateStrLinkShdr.size(); i++) {
01503     newshdr = updateStrLinkShdr[i];
01504     newshdr->sh_link = strtabIndex;   
01505   }
01506 
01507    
01508   return true;
01509 }
01510     
01511 bool emitElf64::addSectionHeaderTable(Elf64_Shdr *shdr) {
01512    Elf_Scn *newscn;
01513    Elf_Data *newdata = NULL;
01514    Elf64_Shdr *newshdr;
01515    
01516    if((newscn = elf_newscn(newElf)) == NULL)
01517    {
01518       log_elferror(err_func_, "unable to create new function"); 
01519       return false;
01520    }    
01521    if ((newdata = elf_newdata(newscn)) == NULL)
01522    {
01523       log_elferror(err_func_, "unable to create section data"); 
01524       return false;
01525    } 
01526    //Fill out the new section header
01527    newshdr = elf64_getshdr(newscn);
01528    newshdr->sh_name = secNameIndex;
01529    secNames.push_back(".shstrtab");
01530    secNameIndex += 10;
01531    newshdr->sh_type = SHT_STRTAB;
01532    newshdr->sh_entsize = 1;
01533    newdata->d_type = ELF_T_BYTE;
01534    newshdr->sh_link = SHN_UNDEF; 
01535    newshdr->sh_flags=  0;
01536 
01537    newshdr->sh_offset = shdr->sh_offset+shdr->sh_size;
01538    newshdr->sh_addr = 0;
01539    newshdr->sh_info = 0;
01540    newshdr->sh_addralign = 4;
01541    
01542    //Set up the data
01543    newdata->d_buf = (char *)malloc(secNameIndex);
01544    char *ptr = (char *)newdata->d_buf;
01545    for(unsigned i=0;i<secNames.size(); i++)
01546    {
01547       memcpy(ptr, secNames[i].c_str(), secNames[i].length());
01548       memcpy(ptr+secNames[i].length(), "\0", 1);
01549       ptr += secNames[i].length()+1;
01550    }    
01551     
01552    newdata->d_size = secNameIndex;
01553    newshdr->sh_size = newdata->d_size;
01554 #ifdef BINEDIT_DEBUG
01555    fprintf(stderr, "Added New Section(%s) : secAddr 0x%lx, secOff 0x%lx, secsize 0x%lx, end 0x%lx\n",
01556            ".shstrtab", newshdr->sh_addr, newshdr->sh_offset, newshdr->sh_size, newshdr->sh_offset + newshdr->sh_size );
01557 #endif
01558    //elf_update(newElf, ELF_C_NULL);
01559    
01560    newdata->d_align = 4;
01561    newdata->d_version = 1;
01562     if (newshdr->sh_entsize && (newshdr->sh_size % newshdr->sh_entsize != 0))
01563         fprintf(stderr, "%s[%d]:  ERROR:  setting size to non multiple of entry size in section %s: %lu/%lu\n", FILE__, __LINE__, ".shstrtab", newshdr->sh_size, newshdr->sh_entsize);
01564    return true;
01565 }
01566 
01567 bool emitElf64::createNonLoadableSections(Elf64_Shdr *&shdr)
01568 {
01569   Elf_Scn *newscn;
01570   Elf_Data *newdata = NULL;
01571   Elf64_Shdr *newshdr;
01572     
01573   Elf64_Shdr *prevshdr = shdr; 
01574   //All of them that are left are non-loadable. stack'em up at the end.
01575   for(unsigned i = 0; i < nonLoadableSecs.size(); i++)
01576     {
01577       secNames.push_back(nonLoadableSecs[i]->getRegionName());
01578       // Add a new non-loadable section
01579       if((newscn = elf_newscn(newElf)) == NULL)
01580         {
01581       log_elferror(err_func_, "unable to create new function"); 
01582       return false;
01583         }   
01584       if ((newdata = elf_newdata(newscn)) == NULL)
01585         {
01586       log_elferror(err_func_, "unable to create section data"); 
01587       return false;
01588         } 
01589 
01590       //Fill out the new section header
01591       newshdr = elf64_getshdr(newscn);
01592       newshdr->sh_name = secNameIndex;
01593       secNameIndex += nonLoadableSecs[i]->getRegionName().length() + 1;
01594       if(nonLoadableSecs[i]->getRegionType() == Region::RT_TEXT)        //Text Section
01595         {
01596       newshdr->sh_type = SHT_PROGBITS;
01597       newshdr->sh_flags = SHF_EXECINSTR | SHF_WRITE;
01598       newshdr->sh_entsize = 1;
01599       newdata->d_type = ELF_T_BYTE;
01600         }
01601       else if(nonLoadableSecs[i]->getRegionType() == Region::RT_DATA)   //Data Section
01602         {
01603       newshdr->sh_type = SHT_PROGBITS;
01604       newshdr->sh_flags = SHF_WRITE;
01605       newshdr->sh_entsize = 1;
01606       newdata->d_type = ELF_T_BYTE;
01607         }
01608       else if(nonLoadableSecs[i]->getRegionType() == Region::RT_REL)    //Relocations section
01609         {
01610       newshdr->sh_type = SHT_REL;
01611       newshdr->sh_flags = SHF_WRITE;
01612       newshdr->sh_entsize = sizeof(Elf64_Rel);
01613       newdata->d_type = ELF_T_BYTE;
01614         }
01615       else if(nonLoadableSecs[i]->getRegionType() == Region::RT_RELA)   //Relocations section
01616         {
01617       newshdr->sh_type = SHT_RELA;
01618       newshdr->sh_flags = SHF_WRITE;
01619       newshdr->sh_entsize = sizeof(Elf64_Rela);
01620       newdata->d_type = ELF_T_BYTE;
01621         }
01622       else if(nonLoadableSecs[i]->getRegionType() == Region::RT_SYMTAB)
01623         {
01624       newshdr->sh_type = SHT_SYMTAB;
01625       newshdr->sh_entsize = sizeof(Elf64_Sym);
01626       newdata->d_type = ELF_T_SYM;
01627       newshdr->sh_link = secNames.size();   //.symtab section should have sh_link = index of .strtab 
01628       newshdr->sh_flags=  0;
01629         }
01630       else if(nonLoadableSecs[i]->getRegionType() == Region::RT_STRTAB) //String table Section
01631         {
01632       newshdr->sh_type = SHT_STRTAB;
01633       newshdr->sh_entsize = 1;
01634       newdata->d_type = ELF_T_BYTE;
01635       newshdr->sh_link = SHN_UNDEF; 
01636       newshdr->sh_flags=  0;
01637         }
01638       /*
01639         else if(nonLoadableSecs[i]->getFlags() & Section::dynsymtabSection)
01640         {
01641     newshdr->sh_type = SHT_DYNSYM;
01642     newshdr->sh_entsize = sizeof(Elf64_Sym);
01643     newdata->d_type = ELF_T_SYM;
01644     //newshdr->sh_link = newSecSize+i+1;   //.symtab section should have sh_link = index of .strtab
01645     newshdr->sh_flags=  SHF_ALLOC | SHF_WRITE;
01646         }*/
01647       newshdr->sh_offset = prevshdr->sh_offset+prevshdr->sh_size;
01648       if( prevshdr->sh_type == SHT_NOBITS ) {
01649           newshdr->sh_offset = prevshdr->sh_offset;
01650       }else{
01651           newshdr->sh_offset = prevshdr->sh_offset+prevshdr->sh_size;
01652       }
01653       if (newshdr->sh_offset < currEndOffset) {
01654          newshdr->sh_offset = currEndOffset;
01655       }
01656       newshdr->sh_addr = 0;
01657       newshdr->sh_info = 0;
01658       newshdr->sh_addralign = 4;
01659 
01660       //Set up the data
01661       newdata->d_buf = nonLoadableSecs[i]->getPtrToRawData();
01662       newdata->d_size = nonLoadableSecs[i]->getDiskSize();
01663       newshdr->sh_size = newdata->d_size;
01664       //elf_update(newElf, ELF_C_NULL);
01665 
01666       newdata->d_align = 4;
01667       newdata->d_off = 0;
01668       newdata->d_version = 1;
01669       currEndOffset = newshdr->sh_offset + newshdr->sh_size;
01670       //currEndAddress = newshdr->sh_addr + newshdr->sh_size;
01671       /* DEBUG */
01672 #ifdef BINEDIT_DEBUG
01673       fprintf(stderr, "Added New Section(%s) : secAddr 0x%lx, secOff 0x%lx, secsize 0x%lx, end 0x%lx\n",
01674           nonLoadableSecs[i]->getRegionName().c_str(), newshdr->sh_addr, newshdr->sh_offset, newshdr->sh_size, newshdr->sh_offset + newshdr->sh_size );
01675 #endif
01676 
01677     if (newshdr->sh_entsize && (newshdr->sh_size % newshdr->sh_entsize != 0))
01678         fprintf(stderr, "%s[%d]:  ERROR:  setting size to non multiple of entry size in section %s: %lu/%lu\n", FILE__, __LINE__, nonLoadableSecs[i]->getRegionName().c_str(), newshdr->sh_size, newshdr->sh_entsize);
01679 
01680       prevshdr = newshdr;
01681     }   
01682   shdr = prevshdr;
01683   return true;
01684 }       
01685 
01686 
01687 /* Regenerates the .symtab, .strtab sections from the symbols
01688  * Add new .dynsym, .dynstr sections for the newly added dynamic symbols
01689  * Method - For every symbol call createElfSymbol to get a Elf64_Sym corresposnding 
01690  *          to a Symbol object. Accumulate all and their names to form the sections
01691  *          and add them to the list of new sections
01692  */
01693 bool emitElf64::createSymbolTables(Symtab *obj, vector<Symbol *>&allSymbols)
01694 {
01695   rewrite_printf(" createSymbolTables for %s \n", obj->name().c_str());
01696   unsigned i;
01697 
01698   //Symbol table(.symtab) symbols
01699   std::vector<Elf64_Sym *> symbols;
01700 
01701   //Symbol table(.dynsymtab) symbols
01702   std::vector<Elf64_Sym *> dynsymbols;
01703 
01704   unsigned symbolNamesLength = 1, dynsymbolNamesLength = 1;
01705   dyn_hash_map<string, unsigned long> dynSymNameMapping;
01706   std::vector<std::string> symbolStrs, dynsymbolStrs;
01707   std::vector<Symbol *> dynsymVector;
01708   std::vector<Symbol *> allDynSymbols;
01709   std::vector<Symbol *> allSymSymbols;
01710 
01711   dyn_hash_map<int, Region*> secTagRegionMapping = obj->getObject()->getTagRegionMapping();
01712 
01713   Region *sec;
01714   dyn_hash_map<int, Region*>::const_iterator foundRegion;
01715   foundRegion = secTagRegionMapping.find(DT_STRTAB);
01716   if ((foundRegion != secTagRegionMapping.end()) && (foundRegion->second != NULL)) {
01717     // .dynstr
01718     sec = foundRegion->second;
01719     olddynStrData = (char *)(sec->getPtrToRawData());
01720     olddynStrSize = sec->getMemSize();
01721     dynsymbolNamesLength = olddynStrSize+1;
01722   }
01723 
01724   // Copy over the previous library dependencies
01725   vector<string> &elibs = obj->getObject()->deps_;
01726   for (std::vector<std::string>::iterator iter = elibs.begin();
01727        iter != elibs.end(); ++iter) {
01728      addDTNeeded(*iter);
01729   }
01730 
01731   //Initialize the list of new prereq libraries
01732   set<string> &plibs = obj->getObject()->prereq_libs;
01733   for (set<string>::iterator i = plibs.begin(); i != plibs.end(); i++) {
01734      addDTNeeded(*i);
01735   }
01736   new_dynamic_entries = obj->getObject()->new_dynamic_entries;
01737   Object *object = obj->getObject();
01738   // recreate a "dummy symbol"
01739   Elf64_Sym *sym = new Elf64_Sym();
01740   symbolStrs.push_back("");
01741   // We should increment this here, but for reasons I don't understand we create it with a size of
01742   // 1. 
01743   //symbolNamesLength++;
01744   sym->st_name = 0;
01745   sym->st_value = 0;
01746   sym->st_size = 0;
01747   sym->st_other = 0;
01748   sym->st_info = ELF64_ST_INFO(STB_LOCAL, STT_NOTYPE);
01749   sym->st_shndx = SHN_UNDEF;
01750 
01751   symbols.push_back(sym);
01752   if (!obj->isStaticBinary()) {
01753     dynsymbols.push_back(sym);
01754     dynsymVector.push_back(Symbol::magicEmitElfSymbol());
01755     versionSymTable.push_back(0);
01756   }   
01757  
01758   if (obj->isStaticBinary()) {
01759       // Static binary case
01760       vector<Region *> newRegs;
01761       obj->getAllNewRegions(newRegs);
01762       if( newRegs.size() ) {
01763           emitElfStatic linker(obj->getAddressWidth(), isStripped);
01764 
01765           emitElfStatic::StaticLinkError err;
01766           std::string errMsg;
01767           linkedStaticData = linker.linkStatic(obj, err, errMsg);
01768           if ( !linkedStaticData ) {
01769                std::string linkStaticError = 
01770                    std::string("Failed to link to static library code into the binary: ") +
01771                    emitElfStatic::printStaticLinkError(err) + std::string(" = ")
01772                    + errMsg;
01773                setSymtabError(Emit_Error);
01774                symtab_log_perror(linkStaticError.c_str());
01775                return false;
01776           }
01777 
01778           hasRewrittenTLS = linker.hasRewrittenTLS();
01779 
01780           // Find the end of the new Regions
01781           obj->getAllNewRegions(newRegs);
01782 
01783           Offset lastRegionAddr = 0, lastRegionSize = 0;
01784           vector<Region *>::iterator newRegIter;
01785           for(newRegIter = newRegs.begin(); newRegIter != newRegs.end();
01786               ++newRegIter)
01787           {
01788               if( (*newRegIter)->getDiskOffset() > lastRegionAddr ) {
01789                   lastRegionAddr = (*newRegIter)->getDiskOffset();
01790                   lastRegionSize = (*newRegIter)->getDiskSize();
01791               }
01792           }
01793 
01794           if( !emitElfUtils::updateHeapVariables(obj, lastRegionAddr + lastRegionSize) ) {
01795               return false;
01796           }
01797       }
01798   }
01799 
01800   for(i=0; i<allSymbols.size();i++) {
01801     if(allSymbols[i]->isInSymtab()) {
01802       allSymSymbols.push_back(allSymbols[i]);
01803     }   
01804     if (!obj->isStaticBinary()) {
01805       if(allSymbols[i]->isInDynSymtab()) {
01806         allDynSymbols.push_back(allSymbols[i]);
01807       } 
01808     }
01809   }
01810  
01811   int max_index = -1;
01812   for(i = 0; i < allDynSymbols.size();i++) {
01813     if (max_index < allDynSymbols[i]->getIndex()) 
01814       max_index = allDynSymbols[i]->getIndex();
01815   }
01816   for(i=0; i<allDynSymbols.size(); i++) {
01817     if (allDynSymbols[i]->getIndex() == -1) {
01818       max_index++;
01819       allDynSymbols[i]->setIndex(max_index);
01820     }
01821 
01822     if (allDynSymbols[i]->getStrIndex() == -1) {
01823       // New Symbol - append to the list of strings
01824       dynsymbolStrs.push_back( allDynSymbols[i]->getMangledName().c_str());
01825       allDynSymbols[i]->setStrIndex(dynsymbolNamesLength);
01826       dynsymbolNamesLength += allDynSymbols[i]->getMangledName().length() + 1;
01827     } 
01828 
01829   } 
01830   // reorder allSymbols based on index
01831   std::sort(allDynSymbols.begin(), allDynSymbols.end(), sortByIndex());
01832    
01833   max_index = -1;
01834   for(i = 0; i < allSymSymbols.size();i++) {
01835     if (max_index < allSymSymbols[i]->getIndex()) 
01836       max_index = allSymSymbols[i]->getIndex();
01837   }
01838 
01839   for(i=0; i<allSymSymbols.size(); i++) {
01840     if (allSymSymbols[i]->getIndex() == -1) {
01841       max_index++;
01842       allSymSymbols[i]->setIndex(max_index);
01843     }
01844   } 
01845 
01846   std::sort(allSymSymbols.begin(), allSymSymbols.end(), sortByIndex());
01847 
01848   /* We regenerate symtab and symstr section. We do not 
01849      maintain the order of the strings and symbols as it was in
01850      the original binary. Hence, the strings in symstr have new order and 
01851      new index.
01852      On the other hand, we do not regenerate dynsym and dynstr section. We copy over
01853      old symbols and string in the original order as it was in the 
01854      original binary. We preserve sh_index of Elf symbols (from Symbol's strIndex). We append 
01855      new symbols and string that we create for the new binary (targ*, versions etc).
01856   */  
01857 
01858   for(i=0; i<allSymSymbols.size();i++) {
01859     //allSymSymbols[i]->setStrIndex(symbolNamesLength);
01860     createElfSymbol(allSymSymbols[i], symbolNamesLength, symbols);
01861     symbolStrs.push_back(allSymSymbols[i]->getMangledName());
01862     symbolNamesLength += allSymSymbols[i]->getMangledName().length()+1;
01863   }
01864   for(i=0; i<allDynSymbols.size();i++) {
01865     createElfSymbol(allDynSymbols[i], allDynSymbols[i]->getStrIndex(), dynsymbols, true);
01866     dynSymNameMapping[allDynSymbols[i]->getMangledName().c_str()] = allDynSymbols[i]->getIndex();
01867     dynsymVector.push_back(allDynSymbols[i]);
01868   }
01869 
01870   //reconstruct .symtab section
01871   Elf64_Sym *syms = (Elf64_Sym *)malloc(symbols.size()* sizeof(Elf64_Sym));
01872   for(i=0;i<symbols.size();i++)
01873     syms[i] = *(symbols[i]);
01874 
01875   char *str = (char *)malloc(symbolNamesLength);
01876   unsigned cur=0;
01877   for(i=0;i<symbolStrs.size();i++)
01878     {
01879       strcpy(&str[cur],symbolStrs[i].c_str());
01880       cur+=symbolStrs[i].length()+1;
01881     }
01882     
01883   if(!isStripped)
01884     {
01885       Region *sec;
01886       if (obj->findRegion(sec,".symtab"))
01887     sec->setPtrToRawData(syms, symbols.size()*sizeof(Elf64_Sym));
01888       else
01889     obj->addRegion(0, syms, symbols.size()*sizeof(Elf64_Sym), ".symtab", Region::RT_SYMTAB);
01890     }
01891   else
01892     obj->addRegion(0, syms, symbols.size()*sizeof(Elf64_Sym), ".symtab", Region::RT_SYMTAB);
01893 
01894   //reconstruct .strtab section
01895   if(!isStripped)
01896     {
01897       Region *sec;
01898       if (obj->findRegion(sec,".strtab"))
01899           sec->setPtrToRawData(str, symbolNamesLength);
01900       else
01901               obj->addRegion(0, str, symbolNamesLength , ".strtab", Region::RT_STRTAB);
01902     }
01903   else
01904     obj->addRegion(0, str, symbolNamesLength , ".strtab", Region::RT_STRTAB);
01905     
01906   if(!obj->getAllNewRegions(newSecs))
01907     log_elferror(err_func_, "No new sections to add");
01908 
01909   if(dynsymbols.size() == 1)
01910     return true;
01911 
01912   if (!obj->isStaticBinary()) {
01913     //reconstruct .dynsym section
01914     Elf64_Sym *dynsyms = (Elf64_Sym *)malloc(dynsymbols.size()* sizeof(Elf64_Sym));
01915     for(i=0;i<dynsymbols.size();i++)
01916       dynsyms[i] = *(dynsymbols[i]);
01917 
01918     Elf64_Half *symVers;
01919     char *verneedSecData, *verdefSecData;
01920     unsigned verneedSecSize = 0, verdefSecSize = 0;
01921                
01922     createSymbolVersions(obj, symVers, verneedSecData, verneedSecSize, verdefSecData, verdefSecSize, dynsymbolNamesLength, dynsymbolStrs);
01923     // build new .hash section
01924     Elf64_Word *hashsecData;
01925     unsigned hashsecSize = 0;
01926     createHashSection(obj, hashsecData, hashsecSize, dynsymVector);
01927     if(hashsecSize) {
01928       string name; 
01929       if (secTagRegionMapping.find(DT_HASH) != secTagRegionMapping.end()) {
01930     name = secTagRegionMapping[DT_HASH]->getRegionName();
01931     obj->addRegion(0, hashsecData, hashsecSize*sizeof(Elf64_Word), name, Region::RT_HASH, true);
01932       } else if (secTagRegionMapping.find(0x6ffffef5) != secTagRegionMapping.end()) {
01933     name = secTagRegionMapping[0x6ffffef5]->getRegionName();
01934     obj->addRegion(0, hashsecData, hashsecSize*sizeof(Elf64_Word), name, Region::RT_HASH, true);
01935       } else {
01936     name = ".hash";
01937     obj->addRegion(0, hashsecData, hashsecSize*sizeof(Elf64_Word), name, Region::RT_HASH, true);
01938       } 
01939     }
01940 
01941     Elf64_Dyn *dynsecData;
01942     unsigned dynsecSize = 0;
01943     if(obj->findRegion(sec, ".dynamic")) {
01944         // Need to ensure that DT_REL and related fields added to .dynamic
01945         // The values of these fields will be set
01946 /*
01947         if( !object->hasReldyn() && !object->hasReladyn() ) {
01948             if( object->getRelType() == Region::RT_REL ) {
01949                 new_dynamic_entries.push_back(make_pair(DT_REL,0));
01950                 new_dynamic_entries.push_back(make_pair(DT_RELSZ,0));
01951             }else if( object->getRelType() == Region::RT_RELA ) {
01952                 new_dynamic_entries.push_back(make_pair(DT_RELA,0));
01953                 new_dynamic_entries.push_back(make_pair(DT_RELASZ,0));
01954             }else{
01955                 assert(!"Relocation type not set to known RT_REL or RT_RELA.");
01956             }
01957         } 
01958 */
01959         createDynamicSection(sec->getPtrToRawData(), sec->getDiskSize(), dynsecData, dynsecSize, dynsymbolNamesLength, dynsymbolStrs);
01960     }  
01961    
01962     if(!dynsymbolNamesLength)
01963       return true; 
01964 
01965     char *dynstr = (char *)malloc(dynsymbolNamesLength);
01966     memcpy((void *)dynstr, (void *)olddynStrData, olddynStrSize);
01967     cur = olddynStrSize+1;
01968     for(i=0;i<dynsymbolStrs.size();i++)
01969       {
01970     strcpy(&dynstr[cur],dynsymbolStrs[i].c_str());
01971     cur+=dynsymbolStrs[i].length()+1;
01972     if ( dynSymNameMapping.find(dynsymbolStrs[i]) == dynSymNameMapping.end()) {
01973       dynSymNameMapping[dynsymbolStrs[i]] = allDynSymbols.size()+i;
01974     }
01975       }
01976 
01977     string name; 
01978     if (secTagRegionMapping.find(DT_SYMTAB) != secTagRegionMapping.end()) {
01979       name = secTagRegionMapping[DT_SYMTAB]->getRegionName();
01980     } else {
01981       name = ".dynsym";
01982     }
01983     obj->addRegion(0, dynsyms, dynsymbols.size()*sizeof(Elf64_Sym), name, Region::RT_SYMTAB, true);
01984 
01985     if (secTagRegionMapping.find(DT_STRTAB) != secTagRegionMapping.end()) {
01986       name = secTagRegionMapping[DT_STRTAB]->getRegionName();
01987     } else {
01988       name = ".dynstr";
01989     }
01990     obj->addRegion(0, dynstr, dynsymbolNamesLength , name, Region::RT_STRTAB, true);
01991 
01992     //add .gnu.version, .gnu.version_r, and .gnu.version_d sections
01993     if (secTagRegionMapping.find(DT_VERSYM) != secTagRegionMapping.end()) {
01994       name = secTagRegionMapping[DT_VERSYM]->getRegionName();
01995     } else {
01996       name = ".gnu.version";
01997     }
01998     obj->addRegion(0, symVers, versionSymTable.size() * sizeof(Elf64_Half), name, Region::RT_SYMVERSIONS, true);
01999 
02000     if(verneedSecSize) {
02001       if (secTagRegionMapping.find(DT_VERNEED) != secTagRegionMapping.end()) {
02002     name = secTagRegionMapping[DT_VERNEED]->getRegionName();
02003       } else {
02004     name = ".gnu.version_r";
02005       }
02006       obj->addRegion(0, verneedSecData, verneedSecSize, name, Region::RT_SYMVERNEEDED, true);
02007     }
02008 
02009     if(verdefSecSize) {
02010       obj->addRegion(0, verdefSecData, verdefSecSize, ".gnu.version_d", Region::RT_SYMVERDEF, true);
02011     }
02012 
02013     //Always create a dyn section, it may get our new relocations.
02014     //If both exist, then just try to maintain order.
02015     bool has_plt = object->hasRelaplt() || object->hasRelplt();
02016     bool has_dyn = object->hasReladyn() || object->hasReldyn();
02017     if (!has_plt) {
02018        createRelocationSections(obj, object->getDynRelocs(), true, dynSymNameMapping);
02019     }
02020     else if (!has_dyn) {
02021        createRelocationSections(obj, object->getPLTRelocs(), false, dynSymNameMapping);
02022        createRelocationSections(obj, object->getDynRelocs(), true, dynSymNameMapping);
02023     }
02024     else if (object->getRelPLTAddr() < object->getRelDynAddr()) {
02025        createRelocationSections(obj, object->getPLTRelocs(), false, dynSymNameMapping);
02026        createRelocationSections(obj, object->getDynRelocs(), true, dynSymNameMapping);
02027     }
02028     else {
02029        createRelocationSections(obj, object->getDynRelocs(), true, dynSymNameMapping);
02030        createRelocationSections(obj, object->getPLTRelocs(), false, dynSymNameMapping);
02031     }
02032 
02033     //add .dynamic section
02034     if(dynsecSize)
02035       obj->addRegion(0, dynsecData, dynsecSize*sizeof(Elf64_Dyn), ".dynamic", Region::RT_DYNAMIC, true);
02036   }
02037 
02038   if(!obj->getAllNewRegions(newSecs))
02039     log_elferror(err_func_, "No new sections to add");
02040 
02041   return true;
02042 }
02043 
02044 void emitElf64::createRelocationSections(Symtab *obj, std::vector<relocationEntry> &relocation_table, bool isDynRelocs, dyn_hash_map<std::string, unsigned long> &dynSymNameMapping) {
02045   vector<relocationEntry> newRels;
02046   if(isDynRelocs && newSecs.size()) {
02047     std::vector<Region *>::iterator i;
02048     for (i = newSecs.begin(); i != newSecs.end(); i++) {
02049       std::copy((*i)->getRelocations().begin(),
02050         (*i)->getRelocations().end(),
02051         std::back_inserter(newRels));
02052     }
02053   }
02054 
02055    unsigned i,j,k,l,m;
02056     
02057    Elf64_Rel *rels = (Elf64_Rel *)malloc(sizeof(Elf64_Rel) * (relocation_table.size()+newRels.size()));
02058    Elf64_Rela *relas = (Elf64_Rela *)malloc(sizeof(Elf64_Rela) * (relocation_table.size()+newRels.size()));
02059    j=0; k=0; l=0; m=0;
02060    //reconstruct .rel
02061    for(i=0; i<relocation_table.size(); i++) 
02062    {
02063 
02064      if( library_adjust ) {
02065          // If we are shifting the library down in memory, we need to update
02066          // any relative offsets in the library. These relative offsets are 
02067          // found via relocations
02068 
02069          // XXX ...ignore the return value
02070          emitElfUtils::updateRelocation(obj, relocation_table[i], library_adjust);
02071      }
02072 
02073       if ((object->getRelType()  == Region::RT_REL) && (relocation_table[i].regionType() == Region::RT_REL)) {
02074          rels[j].r_offset = relocation_table[i].rel_addr() + library_adjust;
02075          unsigned long sym_offset = 0;
02076          std::string sym_name = relocation_table[i].name();
02077          if (!sym_name.empty()) {
02078             dyn_hash_map<string, unsigned long>::iterator j = dynSymNameMapping.find(sym_name);
02079             if (j != dynSymNameMapping.end())
02080                sym_offset = j->second;
02081             else {
02082                Symbol *sym = relocation_table[i].getDynSym();
02083                if (sym)
02084                   sym_offset = sym->getIndex();
02085             }
02086          }
02087 
02088          if (sym_offset) {
02089             rels[j].r_info = ELF64_R_INFO(sym_offset, relocation_table[i].getRelType());
02090          } else {
02091             rels[j].r_info = ELF64_R_INFO((unsigned long)STN_UNDEF, relocation_table[i].getRelType());
02092          }
02093          j++;
02094       } else if((object->getRelType()  == Region::RT_RELA) && (relocation_table[i].regionType() == Region::RT_RELA)){
02095          relas[k].r_offset = relocation_table[i].rel_addr() + library_adjust;
02096          relas[k].r_addend = relocation_table[i].addend();
02097          //if (relas[k].r_addend)
02098          //   relas[k].r_addend += library_adjust;
02099          unsigned long sym_offset = 0;
02100          std::string sym_name = relocation_table[i].name();
02101          if (!sym_name.empty()) {
02102             dyn_hash_map<string, unsigned long>::iterator j = dynSymNameMapping.find(sym_name);
02103             if (j != dynSymNameMapping.end())
02104                sym_offset = j->second;
02105             else {
02106                Symbol *sym = relocation_table[i].getDynSym();
02107                if (sym) {
02108                   j = dynSymNameMapping.find(sym->getMangledName());
02109                   if (j != dynSymNameMapping.end())
02110                      sym_offset = j->second;
02111                }
02112             }
02113          }
02114          if (sym_offset) {
02115             relas[k].r_info = ELF64_R_INFO(sym_offset, relocation_table[i].getRelType());
02116          } else {
02117             relas[k].r_info = ELF64_R_INFO((unsigned long)STN_UNDEF, relocation_table[i].getRelType());
02118          }
02119          k++;
02120       }
02121    }
02122    for(i=0;i<newRels.size();i++) 
02123    { 
02124      if ((object->getRelType()  == Region::RT_REL) && (newRels[i].regionType() == Region::RT_REL)) {
02125          rels[j].r_offset = newRels[i].rel_addr() + library_adjust;
02126          if(dynSymNameMapping.find(newRels[i].name()) != dynSymNameMapping.end()) {
02127 #if defined(arch_x86)
02128             rels[j].r_info = ELF64_R_INFO(dynSymNameMapping[newRels[i].name()], R_386_GLOB_DAT);
02129 #elif defined(arch_x86_64)
02130             rels[j].r_info = ELF64_R_INFO(dynSymNameMapping[newRels[i].name()], R_X86_64_GLOB_DAT);
02131 #elif defined(arch_power)
02132         if (newRels[i].getDynSym() && (newRels[i].getDynSym()->getType() == Symbol::ST_FUNCTION))
02133           rels[j].r_info = ELF64_R_INFO(dynSymNameMapping[newRels[i].name()], R_PPC_JMP_SLOT);
02134         else
02135           rels[j].r_info = ELF64_R_INFO(dynSymNameMapping[newRels[i].name()], R_PPC_GLOB_DAT);
02136 #endif
02137          } else {
02138 #if defined(arch_x86)
02139             rels[j].r_info = ELF64_R_INFO(STN_UNDEF, R_386_GLOB_DAT);
02140 #elif defined(arch_x86_64)
02141             rels[j].r_info = ELF64_R_INFO((unsigned long)STN_UNDEF, R_X86_64_GLOB_DAT);
02142 #elif defined(arch_power)
02143             rels[j].r_info = ELF64_R_INFO(STN_UNDEF, R_PPC_GLOB_DAT);
02144 #endif
02145          }
02146          j++;
02147      l++;
02148       } else if ((object->getRelType()  == Region::RT_RELA) && (newRels[i].regionType() == Region::RT_RELA)) {
02149          relas[k].r_offset = newRels[i].rel_addr() + library_adjust;
02150          relas[k].r_addend = newRels[i].addend();
02151          //if( relas[k].r_addend ) relas[k].r_addend += library_adjust;
02152          if(dynSymNameMapping.find(newRels[i].name()) != dynSymNameMapping.end()) {
02153 #if defined(arch_x86)
02154             relas[k].r_info = ELF64_R_INFO(dynSymNameMapping[newRels[i].name()], R_386_GLOB_DAT);
02155 #elif defined(arch_x86_64)
02156             relas[k].r_info = ELF64_R_INFO(dynSymNameMapping[newRels[i].name()], R_X86_64_GLOB_DAT);
02157 #elif defined(arch_power)
02158         if (newRels[i].getDynSym() && (newRels[i].getDynSym()->getType() == Symbol::ST_FUNCTION))
02159           relas[k].r_info = ELF64_R_INFO(dynSymNameMapping[newRels[i].name()], R_PPC_JMP_SLOT);
02160         else
02161           relas[k].r_info = ELF64_R_INFO(dynSymNameMapping[newRels[i].name()], R_PPC_GLOB_DAT);
02162 #endif
02163          } else {
02164 #if defined(arch_x86)
02165             relas[k].r_info = ELF64_R_INFO(STN_UNDEF, R_386_GLOB_DAT);
02166 #elif defined(arch_x86_64)
02167             relas[k].r_info = ELF64_R_INFO((unsigned long)STN_UNDEF, R_X86_64_GLOB_DAT);
02168 #elif defined(arch_power)
02169             relas[k].r_info = ELF64_R_INFO(STN_UNDEF, R_PPC_GLOB_DAT);
02170 #endif
02171          }
02172          k++;
02173      m++;
02174       }
02175    }
02176 
02177    dyn_hash_map<int, Region*> secTagRegionMapping = obj->getObject()->getTagRegionMapping();
02178    int reloc_size, old_reloc_size, dynamic_reloc_size;
02179    const char *new_name;
02180    Region::RegionType rtype;
02181    int dtype;
02182    int dsize_type;
02183    void *buffer = NULL;
02184 
02185    reloc_size = j*sizeof(Elf64_Rel)+k*sizeof(Elf64_Rela);
02186    if (!reloc_size) {
02187       return;
02188    }
02189    if (   isDynRelocs 
02190        && object->getRelType() == Region::RT_REL ) 
02191    {
02192       new_name = ".rel.dyn";
02193       dtype = DT_REL;
02194       rtype = Region::RT_REL;
02195       dsize_type = DT_RELSZ;
02196       buffer = rels;
02197    }
02198    if (   isDynRelocs
02199        && object->getRelType() == Region::RT_RELA ) 
02200    {
02201       new_name = ".rela.dyn";
02202       dtype = DT_RELA;
02203       rtype = Region::RT_RELA;
02204       dsize_type = DT_RELASZ;
02205       buffer = relas;
02206       updateDynamic(DT_RELAENT, sizeof(Elf64_Rela)); 
02207    }
02208    if (   !isDynRelocs 
02209        && object->getRelType() == Region::RT_REL ) 
02210    {
02211       new_name = ".rel.plt";
02212       dtype = DT_JMPREL;
02213       rtype = Region::RT_PLTREL;
02214       dsize_type = DT_PLTRELSZ;
02215       buffer = rels;
02216    }
02217    if (   !isDynRelocs 
02218        && object->getRelType() == Region::RT_RELA ) 
02219    {
02220       new_name = ".rela.plt";
02221       dtype = DT_JMPREL;
02222       rtype = Region::RT_PLTRELA;
02223       dsize_type = DT_PLTRELSZ;
02224       buffer = relas;
02225    }
02226 if(dynamicSecData.find(dsize_type) != dynamicSecData.end())
02227    old_reloc_size =  dynamicSecData[dsize_type][0]->d_un.d_val;
02228 else
02229    old_reloc_size = 0;
02230    dynamic_reloc_size = old_reloc_size+  l*sizeof(Elf64_Rel)+ m*sizeof(Elf64_Rela);
02231    string name;
02232    if (secTagRegionMapping.find(dtype) != secTagRegionMapping.end())
02233       name = secTagRegionMapping[dtype]->getRegionName();
02234    else
02235       name = std::string(new_name);
02236    obj->addRegion(0, buffer, reloc_size, name, rtype, true);
02237    updateDynamic(dsize_type, dynamic_reloc_size); 
02238 
02239 }
02240 
02241 void emitElf64::createSymbolVersions(Symtab *obj, Elf64_Half *&symVers, char*&verneedSecData, unsigned &verneedSecSize, char
02242 *&verdefSecData, unsigned &verdefSecSize, unsigned &dynSymbolNamesLength, vector<string> &dynStrs){
02243 
02244    //Add all names to the new .dynstr section
02245    map<string, unsigned>::iterator iter = versionNames.begin();
02246    for(;iter!=versionNames.end();iter++){
02247       iter->second = dynSymbolNamesLength;
02248       dynStrs.push_back(iter->first);
02249       dynSymbolNamesLength+= iter->first.size()+1;
02250    }
02251 
02252    //reconstruct .gnu_version section
02253    symVers = (Elf64_Half *)malloc(versionSymTable.size() * sizeof(Elf64_Half));
02254    for(unsigned i=0; i<versionSymTable.size(); i++)
02255       symVers[i] = versionSymTable[i];
02256 
02257    //reconstruct .gnu.version_r section
02258    verneedSecSize = 0;
02259    map<string, map<string, unsigned> >::iterator it = verneedEntries.begin();
02260    for(; it != verneedEntries.end(); it++)
02261       verneedSecSize += sizeof(Elf64_Verneed) + sizeof(Elf64_Vernaux) * it->second.size();
02262 
02263    verneedSecData = (char *)malloc(verneedSecSize);
02264    unsigned curpos = 0;
02265    verneednum = 0;
02266    std::vector<std::string>::iterator dit;
02267    for(dit = unversionedNeededEntries.begin(); dit != unversionedNeededEntries.end(); dit++) {
02268       // account for any substitutions due to rewriting a shared lib
02269       std::string name = obj->getDynLibSubstitution(*dit);
02270       // no need for self-references
02271       if (!(obj->name() == name)) {
02272          versionNames[name] = dynSymbolNamesLength;
02273          dynStrs.push_back(name);
02274          dynSymbolNamesLength+= (name).size()+1;
02275          addDTNeeded(name);
02276       }
02277    }
02278    for(it = verneedEntries.begin(); it != verneedEntries.end(); it++){
02279       Elf64_Verneed *verneed = (Elf64_Verneed *)(void*)(verneedSecData+curpos);
02280       verneed->vn_version = 1;
02281       verneed->vn_cnt = it->second.size();
02282       verneed->vn_file = dynSymbolNamesLength;
02283       versionNames[it->first] = dynSymbolNamesLength;
02284       dynStrs.push_back(it->first);
02285       dynSymbolNamesLength+= it->first.size()+1;
02286       addDTNeeded(it->first);
02287       verneed->vn_aux = sizeof(Elf64_Verneed);
02288       verneed->vn_next = sizeof(Elf64_Verneed) + it->second.size()*sizeof(Elf64_Vernaux);
02289       if(curpos + verneed->vn_next == verneedSecSize)
02290          verneed->vn_next = 0;
02291       verneednum++;
02292       int i = 0;
02293       for(iter = it->second.begin(); iter!= it->second.end(); iter++){
02294          Elf64_Vernaux *vernaux = (Elf64_Vernaux *)(void*)(verneedSecData + curpos + verneed->vn_aux + i*sizeof(Elf64_Vernaux));
02295          vernaux->vna_hash = elfHash(iter->first.c_str());
02296          vernaux->vna_flags = 0;
02297          vernaux->vna_other = iter->second;
02298          vernaux->vna_name = versionNames[iter->first];
02299          if(i == verneed->vn_cnt-1)
02300             vernaux->vna_next = 0;
02301          else
02302             vernaux->vna_next = sizeof(Elf64_Vernaux);
02303          i++;
02304       }
02305       curpos += verneed->vn_next;
02306    }
02307 
02308    //reconstruct .gnu.version_d section
02309    verdefSecSize = 0;
02310    for(iter = verdefEntries.begin(); iter != verdefEntries.end(); iter++)
02311       verdefSecSize += sizeof(Elf64_Verdef) + sizeof(Elf64_Verdaux) * verdauxEntries[iter->second].size();
02312 
02313    verdefSecData = (char *)malloc(verdefSecSize);
02314    curpos = 0;
02315    verdefnum = 0;
02316    for(iter = verdefEntries.begin(); iter != verdefEntries.end(); iter++){
02317       Elf64_Verdef *verdef = (Elf64_Verdef *)(void*)(verdefSecData+curpos);
02318       verdef->vd_version = 1;
02319       verdef->vd_flags = 0;
02320       verdef->vd_ndx = iter->second;
02321       verdef->vd_cnt = verdauxEntries[iter->second].size();
02322       verdef->vd_hash = elfHash(iter->first.c_str());
02323       verdef->vd_aux = sizeof(Elf64_Verdef);
02324       verdef->vd_next = sizeof(Elf64_Verdef) + verdauxEntries[iter->second].size()*sizeof(Elf64_Verdaux);
02325       if(curpos + verdef->vd_next == verdefSecSize)
02326          verdef->vd_next = 0;
02327       verdefnum++;
02328       for(unsigned i = 0; i< verdauxEntries[iter->second].size(); i++){
02329          Elf64_Verdaux *verdaux = (Elf64_Verdaux *)(void*)(verdefSecData + curpos + verdef->vd_aux + i*sizeof(Elf64_Verdaux));
02330          verdaux->vda_name = versionNames[verdauxEntries[iter->second][0]];
02331          if((signed) i == verdef->vd_cnt-1)
02332             verdaux->vda_next = 0;
02333          else
02334             verdaux->vda_next = sizeof(Elf64_Verdaux);
02335       }
02336       curpos += verdef->vd_next;
02337    }
02338    return;
02339 }
02340 
02341 void emitElf64::createHashSection(Symtab *obj, Elf64_Word *&hashsecData, unsigned &hashsecSize, vector<Symbol *>&dynSymbols)
02342 {
02343 
02344   /* Save the original hash table entries */
02345   std::vector<unsigned> originalHashEntries;
02346   unsigned dynsymSize = obj->getObject()->getDynsymSize();
02347   
02348   Elf_Scn *scn = NULL;
02349   Elf64_Shdr *shdr = NULL;
02350   for (unsigned scncount = 0; (scn = elf_nextscn(oldElf, scn)); scncount++) {
02351     shdr = elf64_getshdr(scn);
02352     if(obj->getObject()->getElfHashAddr() != 0 &&
02353        obj->getObject()->getElfHashAddr() == shdr->sh_addr){
02354       Elf_Data *hashData = elf_getdata(scn,NULL);
02355       Elf64_Word *oldHashSec = (Elf64_Word *) hashData->d_buf;
02356       unsigned original_nbuckets, original_nchains;
02357       original_nbuckets =  oldHashSec[0];
02358       original_nchains = oldHashSec[1];
02359       for (unsigned i = 0; i < original_nbuckets+original_nchains; i++) {
02360     if ( oldHashSec[2+i] != 0) {
02361         originalHashEntries.push_back( oldHashSec[2+i]);
02362         //printf(" ELF HASH pushing hash entry %d \n", oldHashSec[2+i] );
02363     }
02364       }
02365     }
02366 
02367     if(obj->getObject()->getGnuHashAddr() != 0 &&
02368        obj->getObject()->getGnuHashAddr() == shdr->sh_addr){
02369       Elf_Data *hashData = elf_getdata(scn,NULL);
02370       Elf64_Word *oldHashSec = (Elf64_Word *) hashData->d_buf;
02371       unsigned symndx = oldHashSec[1];
02372       if (dynsymSize != 0)
02373         for (unsigned i = symndx; i < dynsymSize ; i++) {
02374         originalHashEntries.push_back(i);
02375         //printf(" GNU HASH pushing hash entry %d \n", i);
02376     }
02377       }
02378   }
02379 
02380   vector<Symbol *>::iterator iter;
02381   dyn_hash_map<unsigned, unsigned> lastHash; // bucket number to symbol index
02382   unsigned nbuckets = (unsigned)dynSymbols.size()*2/3;
02383   if (nbuckets % 2 == 0)
02384     nbuckets--;
02385   if (nbuckets < 1)
02386     nbuckets = 1;
02387   unsigned nchains = (unsigned)dynSymbols.size();
02388   hashsecSize = 2 + nbuckets + nchains;
02389   hashsecData = (Elf64_Word *)malloc(hashsecSize*sizeof(Elf64_Word));
02390   unsigned i=0, key;
02391   for (i=0; i<hashsecSize; i++) {
02392     hashsecData[i] = STN_UNDEF;
02393   }
02394   hashsecData[0] = (Elf64_Word)nbuckets;
02395   hashsecData[1] = (Elf64_Word)nchains;
02396   i = 0;
02397   for (iter = dynSymbols.begin(); iter != dynSymbols.end(); iter++, i++) {
02398     if((*iter)->getMangledName().empty()) continue;
02399     unsigned index = (*iter)->getIndex();
02400     if ((find(originalHashEntries.begin(),originalHashEntries.end(),index) == originalHashEntries.end()) && 
02401     (index < obj->getObject()->getDynsymSize())) {
02402     continue;
02403     }
02404     key = elfHash((*iter)->getMangledName().c_str()) % nbuckets;
02405     if (lastHash.find(key) != lastHash.end()) {
02406       hashsecData[2+nbuckets+lastHash[key]] = i;
02407     }
02408     else {
02409       hashsecData[2+key] = i;
02410     }
02411     lastHash[key] = i;
02412     hashsecData[2+nbuckets+i] = STN_UNDEF;
02413   }
02414 }
02415 
02416 void emitElf64::createDynamicSection(void *dynData, unsigned size, Elf64_Dyn *&dynsecData, unsigned &dynsecSize, unsigned &dynSymbolNamesLength, std::vector<std::string> &dynStrs) {
02417   dynamicSecData.clear();
02418   Elf64_Dyn *dyns = (Elf64_Dyn *)dynData;
02419   unsigned count = size/sizeof(Elf64_Dyn);
02420   vector<string> &libs_rmd = object->libsRMd();
02421   dynsecSize = 2*(count + DT_NEEDEDEntries.size() + new_dynamic_entries.size());
02422   dynsecData = (Elf64_Dyn *)malloc(dynsecSize*sizeof(Elf64_Dyn));
02423   unsigned curpos = 0;
02424   string rpathstr;
02425   for(unsigned i = 0; i< DT_NEEDEDEntries.size(); i++){
02426     dynsecData[curpos].d_tag = DT_NEEDED;
02427     dynStrs.push_back(DT_NEEDEDEntries[i]);
02428     dynsecData[curpos].d_un.d_val = dynSymbolNamesLength;
02429     dynSymbolNamesLength += DT_NEEDEDEntries[i].size()+1;
02430     dynamicSecData[DT_NEEDED].push_back(dynsecData+curpos);
02431     curpos++;
02432   }
02433   for (unsigned i = 0; i<new_dynamic_entries.size(); i++) {
02434      long name = new_dynamic_entries[i].first;
02435      long value = new_dynamic_entries[i].second;
02436      dynsecData[curpos].d_tag = name;
02437      dynsecData[curpos].d_un.d_val = value;
02438      dynamicSecData[name].push_back(dynsecData+curpos);
02439      curpos++;
02440   }
02441 
02442   // There may be multiple HASH (ELF, GNU etc) sections in the original binary. We consolidate all of them into one.
02443   bool foundHashSection = false; 
02444 
02445   for(unsigned i = 0; i< count;i++){
02446     switch(dyns[i].d_tag){
02447     case DT_NULL:
02448       break;
02449     case 0x6ffffef5: // DT_GNU_HASH (not defined on all platforms)
02450       if (!foundHashSection) {
02451         dynsecData[curpos].d_tag = DT_HASH;
02452         dynsecData[curpos].d_un.d_ptr =dyns[i].d_un.d_ptr ;
02453         dynamicSecData[DT_HASH].push_back(dynsecData+curpos);
02454         curpos++;
02455         foundHashSection = true;
02456       }
02457       break;
02458     case DT_HASH: 
02459       if (!foundHashSection) {
02460         dynsecData[curpos].d_tag = dyns[i].d_tag;
02461         dynsecData[curpos].d_un.d_ptr =dyns[i].d_un.d_ptr ;
02462         dynamicSecData[dyns[i].d_tag].push_back(dynsecData+curpos);
02463         curpos++;
02464         foundHashSection = true;
02465       }
02466       break;
02467     case DT_NEEDED:
02468       rpathstr = &olddynStrData[dyns[i].d_un.d_val];
02469       if(find(DT_NEEDEDEntries.begin(), DT_NEEDEDEntries.end(), rpathstr) != DT_NEEDEDEntries.end()) {
02470          break;
02471       }
02472       if (find(libs_rmd.begin(), libs_rmd.end(), rpathstr) != libs_rmd.end())
02473          break;
02474       dynsecData[curpos].d_tag = dyns[i].d_tag;
02475       dynsecData[curpos].d_un.d_val = dynSymbolNamesLength;
02476       dynStrs.push_back(rpathstr);
02477       dynSymbolNamesLength += rpathstr.size() + 1;
02478       dynamicSecData[dyns[i].d_tag].push_back(dynsecData+curpos);
02479       curpos++;
02480       break;
02481     case DT_RPATH:
02482     case DT_RUNPATH:
02483       dynsecData[curpos].d_tag = dyns[i].d_tag;
02484       dynsecData[curpos].d_un.d_val = dynSymbolNamesLength;
02485       rpathstr = &olddynStrData[dyns[i].d_un.d_val];
02486       dynStrs.push_back(rpathstr);
02487       dynSymbolNamesLength += rpathstr.size() + 1;
02488       dynamicSecData[dyns[i].d_tag].push_back(dynsecData+curpos);
02489       curpos++;
02490       break;
02491     case DT_INIT:
02492     case DT_FINI:
02493     case DT_GNU_CONFLICT:
02494     case DT_JMPREL:
02495     case DT_PLTGOT:
02496        /**
02497         * List every dynamic entry that references an address and isn't already
02498         * updated here.  library_adjust will be a page size if
02499         * we're dealing with a library without a fixed load address.  We'll be shifting
02500         * the addresses of that library by a page.
02501         **/
02502        memcpy(dynsecData+curpos, dyns+i, sizeof(Elf64_Dyn));
02503        dynsecData[curpos].d_un.d_ptr += library_adjust;
02504        dynamicSecData[dyns[i].d_tag].push_back(dynsecData+curpos);
02505        curpos++;
02506        break;
02507     default:
02508       memcpy(dynsecData+curpos, dyns+i, sizeof(Elf64_Dyn));
02509       dynamicSecData[dyns[i].d_tag].push_back(dynsecData+curpos);
02510       curpos++;
02511       break;
02512     }
02513   }
02514         // Need to ensure that DT_REL and related fields added to .dynamic
02515         // The values of these fields will be set
02516 
02517         if( !object->hasReldyn() && !object->hasReladyn() ) {
02518             if( object->getRelType() == Region::RT_REL ) {
02519                 new_dynamic_entries.push_back(make_pair(DT_REL,0));
02520                 new_dynamic_entries.push_back(make_pair(DT_RELSZ,0));
02521 
02522   dynamicSecData[DT_REL].push_back(dynsecData+curpos);
02523   dynsecData[curpos].d_tag = DT_NULL;
02524   dynsecData[curpos].d_un.d_val = 0;
02525   curpos++;
02526   dynamicSecData[DT_RELSZ].push_back(dynsecData+curpos);
02527   dynsecData[curpos].d_tag = DT_NULL;
02528   dynsecData[curpos].d_un.d_val = 0;
02529   curpos++;
02530   dynamicSecData[DT_RELENT].push_back(dynsecData+curpos);
02531   dynsecData[curpos].d_tag = DT_NULL;
02532   dynsecData[curpos].d_un.d_val = 0;
02533   curpos++;
02534 
02535             }else if( object->getRelType() == Region::RT_RELA ) {
02536 
02537   dynamicSecData[DT_RELA].push_back(dynsecData+curpos);
02538   dynsecData[curpos].d_tag = DT_NULL;
02539   dynsecData[curpos].d_un.d_val = 0;
02540   curpos++;
02541   dynamicSecData[DT_RELASZ].push_back(dynsecData+curpos);
02542   dynsecData[curpos].d_tag = DT_NULL;
02543   dynsecData[curpos].d_un.d_val = 0;
02544   curpos++;
02545   dynamicSecData[DT_RELAENT].push_back(dynsecData+curpos);
02546   dynsecData[curpos].d_tag = DT_NULL;
02547   dynsecData[curpos].d_un.d_val = 0;
02548   curpos++;
02549 
02550             }
02551         } 
02552 
02553 
02554     dynsecData[curpos].d_tag = DT_NULL;
02555   dynsecData[curpos].d_un.d_val = 0;
02556   curpos++;
02557   dynsecSize = curpos+1;                            //assign size to the correct number of entries
02558 }
02559 
02560 
02561 void emitElf64::log_elferror(void (*err_func)(const char *), const char* msg) {
02562   const char* err = elf_errmsg(elf_errno());
02563   err = err ? err: "(bad elf error)";
02564   string str = string(err)+string(msg);
02565   err_func(str.c_str());
02566 }
02567 
02568 void emitElf64::addDTNeeded(string s)
02569 {
02570    if (find(DT_NEEDEDEntries.begin(), DT_NEEDEDEntries.end(), s) != DT_NEEDEDEntries.end())
02571       return;
02572    vector<string> &libs_rmd = object->libsRMd();
02573    if (find(libs_rmd.begin(), libs_rmd.end(), s) != libs_rmd.end())
02574       return;
02575    DT_NEEDEDEntries.push_back(s);
02576 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 12 Jul 2013 for SymtabAPI by  doxygen 1.6.1