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

Generated on 12 Jul 2013 for SymtabAPI by  doxygen 1.6.1