Function wrapping implementation and Symtab extensions for undefined symbols
[dyninst.git] / symtabAPI / src / emitElf-64.C
1 /*
2  * Copyright (c) 1996-2011 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31
32 /*
33   #if !defined(cap_libelf_so_0) && defined(os_linux)
34   #define _FILE_OFFSET_BITS 64
35   #endif
36 */
37
38 #include <algorithm>
39 #include "Symtab.h"
40 #include "emitElf-64.h"
41 #include "emitElfStatic.h"
42 #include "debug.h"
43
44 #if defined(os_freebsd)
45 #include "common/h/freebsdKludges.h"
46 #endif
47
48 #if defined(os_linux)
49 #include "common/h/linuxKludges.h"
50 #endif
51
52 extern void symtab_log_perror(const char *msg);
53 using namespace Dyninst;
54 using namespace Dyninst::SymtabAPI;
55 using namespace std;
56
57 extern const char *pdelf_get_shnames(Elf_X &elf);
58 extern const char *STRTAB_NAME;
59 extern const char *SYMTAB_NAME;
60 extern const char *INTERP_NAME;
61 extern unsigned int elfHash(const char *name);
62
63 // Error reporting
64 extern void setSymtabError(SymtabError new_err);
65 extern void symtab_log_perror(const char *msg);
66
67 struct sortByIndex
68 {
69   bool operator ()(Symbol * lhs, Symbol* rhs) {
70     return lhs->getIndex() < rhs->getIndex();
71   }
72 };
73
74 static bool libelfso0Flag;
75 static bool libelfso1Flag;
76 static int libelfso1version_major;
77 static int libelfso1version_minor;
78
79 #if defined(os_linux) || defined(os_freebsd)
80 static char *deref_link(const char *path)
81 {
82    static char buffer[PATH_MAX], *p;
83    buffer[PATH_MAX-1] = '\0';
84    p = realpath(path, buffer);
85    return p;
86 }
87 #else
88 static char *deref_link(const char *path)
89 {
90    return const_cast<char *>(path);
91 }
92 #endif
93
94 static void setVersion(){
95   libelfso0Flag = false;
96   libelfso1Flag = false;
97   libelfso1version_major = 0;
98   libelfso1version_minor = 0;
99 #if defined(os_linux) || defined(os_freebsd)
100   unsigned nEntries;
101   map_entries *maps = getVMMaps(getpid(), nEntries);
102   for (unsigned i=0; i< nEntries; i++){
103      if (!strstr(maps[i].path, "libelf"))
104         continue;
105      char *real_file = deref_link(maps[i].path);
106      char *libelf_start = strstr(real_file, "libelf");
107      int num_read, major, minor;
108      num_read = sscanf(libelf_start, "libelf-%d.%d.so", &major, &minor);
109      if (num_read == 2) {
110         libelfso1Flag = true;
111         libelfso1version_major = major;
112         libelfso1version_minor = minor;        
113      }
114      else {
115         libelfso0Flag = true;
116      }
117   }
118   if (libelfso0Flag && libelfso1Flag) {
119      fprintf(stderr, "WARNING: SymtabAPI is linked with libelf.so.0 and "
120              "libelf.so.1!  SymtabAPI likely going to be unable to read "
121              "and write elf files!\n");
122   }
123
124 #if defined(os_freebsd)
125   if( libelfso1Flag ) {
126       fprintf(stderr, "WARNING: SymtabAPI on FreeBSD is known to function "
127               "incorrectly when linked with libelf.so.1\n");
128   }
129 #endif
130 #endif
131 }
132
133 bool emitElf64::hasPHdrSectionBug()
134 {
135    if (movePHdrsFirst)
136       return false;
137    if (!libelfso1Flag)
138       return false;
139    return (libelfso1version_major == 0 && libelfso1version_minor <= 137);
140 }
141
142 bool emitElf64::cannotRelocatePhdrs()
143 {
144 #if defined(bug_phdrs_first_page)
145     return true;
146 #else
147     return false;
148 #endif
149 }
150
151 static int elfSymType(Symbol *sym)
152 {
153   switch (sym->getType()) {
154   case Symbol::ST_MODULE: return STT_FILE;
155   case Symbol::ST_SECTION: return STT_SECTION;
156   case Symbol::ST_OBJECT: return STT_OBJECT;
157   case Symbol::ST_FUNCTION: return STT_FUNC;
158   case Symbol::ST_TLS: return STT_TLS;
159   case Symbol::ST_NOTYPE : return STT_NOTYPE;
160   case Symbol::ST_UNKNOWN: return sym->getInternalType();
161   default: return STT_SECTION;
162   }
163 }
164
165 static int elfSymBind(Symbol::SymbolLinkage sLinkage)
166 {
167   switch (sLinkage) {
168   case Symbol::SL_LOCAL: return STB_LOCAL;
169   case Symbol::SL_WEAK: return STB_WEAK;
170   case Symbol::SL_GLOBAL: return STB_GLOBAL;
171   default: return STB_LOPROC;
172   }
173 }
174
175 static int elfSymVisibility(Symbol::SymbolVisibility sVisibility)
176 {
177   switch (sVisibility) {
178   case Symbol::SV_DEFAULT: return STV_DEFAULT;
179   case Symbol::SV_INTERNAL: return STV_INTERNAL;
180   case Symbol::SV_HIDDEN: return STV_HIDDEN;
181   case Symbol::SV_PROTECTED: return STV_PROTECTED;
182   default: return STV_DEFAULT;
183   }
184 }
185
186 emitElf64::emitElf64(Elf_X &oldElfHandle_, bool isStripped_, Object *obj_, void (*err_func)(const char *)) :
187    oldElfHandle(oldElfHandle_),
188    phdrs_scn(NULL),
189    isStripped(isStripped_),
190    object(obj_),
191    err_func_(err_func)
192 {
193   firstNewLoadSec = NULL;
194   textData = NULL;
195   symStrData = NULL;
196   dynStrData = NULL;
197   symTabData = NULL;
198   hashData = NULL;
199   dynsymData = NULL;
200   rodata = NULL;
201   
202   //Don't expect to use to use this mechanism anymore
203   BSSExpandFlag = false; 
204   //If we're dealing with a library that can be loaded anywhere,
205   // then load the program headers into the later part of the binary,
206   // this may trigger a kernel bug that was fixed in Summer 2007,
207   // but is the only reliable way to modify these libraries.
208   //If we're dealing with a library/executable that loads at a specific
209   // address we'll put the phdrs into the page before that address.  This
210   // works and will avoid the kernel bug.
211   movePHdrsFirst = object && object->getLoadAddress();
212   createNewPhdr = true;
213
214   //If we want to try a mode where we add the program headers to a library
215   // that can be loaded anywhere, and put the program headers in the first 
216   // page (avoiding the kernel bug), then set library_adjust to getpagesize().
217   // This will shift all addresses in the library down by a page, accounting
218   // for the extra page for program headers.  This causes some significant
219   // changes to the binary, and isn't well tested.
220   library_adjust = 0;
221   if( cannotRelocatePhdrs() && !movePHdrsFirst ) {
222       movePHdrsFirst = true;
223       library_adjust = getpagesize();
224   }
225
226   linkedStaticData = NULL;
227   hasRewrittenTLS = false;
228   TLSExists = false;
229   newTLSData = NULL;
230
231   oldElf = oldElfHandle.e_elfp();
232   curVersionNum = 2;
233
234   setVersion();
235 }
236
237 bool emitElf64::createElfSymbol(Symbol *symbol, unsigned strIndex, vector<Elf64_Sym *> &symbols, bool dynSymFlag)
238 {
239   Elf64_Sym *sym = new Elf64_Sym();
240   sym->st_name = strIndex;
241
242   if (symbol->getAddr())
243      sym->st_value = symbol->getAddr() + library_adjust;
244   sym->st_size = symbol->getSize();
245   sym->st_other = ELF64_ST_VISIBILITY(elfSymVisibility(symbol->getVisibility()));
246   sym->st_info = (unsigned char) ELF64_ST_INFO(elfSymBind(symbol->getLinkage()), elfSymType(symbol));
247
248   if (symbol->getSec())
249     {
250 #if defined(os_freebsd)
251       sym->st_shndx = (Elf64_Half) symbol->getSec()->getRegionNumber();
252 #else
253       sym->st_shndx = (Elf64_Section) symbol->getSec()->getRegionNumber();
254 #endif
255     }
256   else if (symbol->isAbsolute())
257     {
258       sym->st_shndx = SHN_ABS;
259     }
260   else
261     {
262       sym->st_shndx = 0;
263     }
264
265   symbols.push_back(sym);
266
267   if (dynSymFlag) 
268     {
269       /*printf("dynamic symbol: %s\n", symbol->getName().c_str());*/
270
271       char msg[2048];
272       char *mpos = msg;
273       msg[0] = '\0';
274       string fileName;
275
276       if (!symbol->getVersionFileName(fileName))
277         {
278           //verdef entry
279           vector<string> *vers;
280           if (!symbol->getVersions(vers))
281             {
282               if (symbol->getLinkage() == Symbol::SL_GLOBAL)
283                 {
284                   versionSymTable.push_back(1);
285                 }
286               else
287                 {
288                   versionSymTable.push_back(0);
289                 }
290             }
291           else 
292             {
293               if (vers->size() > 0)
294                 {
295                   // new verdef entry
296                   mpos += sprintf(mpos, "verdef: symbol=%s  version=%s ", symbol->getName().c_str(), (*vers)[0].c_str());
297                   if (verdefEntries.find((*vers)[0]) != verdefEntries.end())
298                     {
299                       unsigned short index = verdefEntries[(*vers)[0]];
300                       if (symbol->getVersionHidden()) index += 0x8000;
301                       versionSymTable.push_back(index);
302                     }
303                   else 
304                     {
305                       unsigned short index = curVersionNum;
306                       if (symbol->getVersionHidden()) index += 0x8000;
307                       versionSymTable.push_back(index);
308
309                       verdefEntries[(*vers)[0]] = curVersionNum;
310                       curVersionNum++;
311                     }
312                 }
313               // add all versions to the verdef entry
314               for (unsigned i=0; i< vers->size(); i++)
315                 {
316                   mpos += sprintf(mpos, "  {%s}", (*vers)[i].c_str());
317                   if (versionNames.find((*vers)[i]) == versionNames.end())
318                     {
319                       versionNames[(*vers)[i]] = 0;
320                     }
321
322                   if (find( verdauxEntries[verdefEntries[(*vers)[0]]].begin(),
323                             verdauxEntries[verdefEntries[(*vers)[0]]].end(),
324                             (*vers)[i]) == verdauxEntries[verdefEntries[(*vers)[0]]].end())
325                     {
326                       verdauxEntries[verdefEntries[(*vers)[0]]].push_back((*vers)[i]);
327                     }
328                 }
329               mpos += sprintf(mpos, "\n");
330             }
331         }
332       else 
333         {           
334           //verneed entry
335           mpos += sprintf(mpos, "need: symbol=%s    filename=%s\n", 
336                           symbol->getName().c_str(), fileName.c_str());
337
338           vector<string> *vers;
339
340           if (!symbol->getVersions(vers) || (vers && vers->size() != 1)) 
341             {
342               // add an unversioned dependency
343               if (fileName != "") 
344          {
345             if (!symbol->getReferringSymbol()->getSymtab()->isExec()) {
346                if (find(unversionedNeededEntries.begin(),
347                         unversionedNeededEntries.end(),
348                         fileName) == unversionedNeededEntries.end()) 
349                {
350                   mpos += sprintf(mpos, "  new unversioned: %s\n", fileName.c_str());
351                   unversionedNeededEntries.push_back(fileName);
352                }
353             }
354
355                   if (symbol->getLinkage() == Symbol::SL_GLOBAL) {
356                     versionSymTable.push_back(1);
357                   }
358                   else {
359                     versionSymTable.push_back(0);
360                   }
361                 }
362             } 
363           else 
364             {
365               if (!vers)
366                 {
367                   fprintf(stderr, "%s[%d]:  weird inconsistency here...  getVersions returned NULL\n",
368                           FILE__, __LINE__);
369                 }
370               else
371                 {
372                   // There should only be one version string by this time
373                   //If the verison name already exists then add the same version number to the version symbol table
374                   //Else give a new number and add it to the mapping.
375                   if (versionNames.find((*vers)[0]) == versionNames.end()) 
376                     {
377                       mpos += sprintf(mpos, "  new version name: %s\n", (*vers)[0].c_str());
378                       versionNames[(*vers)[0]] = 0;
379                     }
380
381                   if (verneedEntries.find(fileName) != verneedEntries.end())
382                     {
383                       if (verneedEntries[fileName].find((*vers)[0]) != verneedEntries[fileName].end()) 
384                         {
385                           mpos += sprintf(mpos, "  vernum: %d\n", verneedEntries[fileName][(*vers)[0]]);
386                           versionSymTable.push_back((unsigned short) verneedEntries[fileName][(*vers)[0]]);
387                         }
388                       else
389                         {
390                           mpos += sprintf(mpos, "  new entry #%d: %s [%s]\n", 
391                                           curVersionNum, (*vers)[0].c_str(), fileName.c_str());
392                           versionSymTable.push_back((unsigned short) curVersionNum);
393                           verneedEntries[fileName][(*vers)[0]] = curVersionNum;
394                           curVersionNum++;
395                         }
396                     }
397                   else
398                     {
399                       mpos += sprintf(mpos, "  new entry #%d: %s [%s]\n", 
400                                       curVersionNum, (*vers)[0].c_str(), fileName.c_str());
401                       versionSymTable.push_back((unsigned short) curVersionNum);
402                       verneedEntries[fileName][(*vers)[0]] = curVersionNum;
403                       curVersionNum++;
404                     }
405                 } 
406             }
407         }
408 #ifdef BINEDIT_DEBUG
409       printf("%s", msg);
410 #endif
411     }
412   return true;
413 }
414
415 // Find the end of data/text segment
416 void emitElf64::findSegmentEnds()
417 {
418   Elf64_Phdr *tmp = elf64_getphdr(oldElf);
419   // Find the offset of the start of the text & the data segment
420   // The first LOAD segment is the text & the second LOAD segment 
421   // is the data
422   dataSegEnd = 0;
423   for(unsigned i=0;i<oldEhdr->e_phnum;i++)
424     {
425       if(tmp->p_type == PT_LOAD) 
426         {
427           if (dataSegEnd < tmp->p_vaddr+tmp->p_memsz)
428             dataSegEnd = tmp->p_vaddr+tmp->p_memsz;
429         }else if( PT_TLS == tmp->p_type ) {
430             TLSExists = true;
431         }
432       tmp++;
433     }
434 }
435
436 // Rename an old section. Lengths of old and new names must match.
437 // Only renames the FIRST matching section encountered.
438 void emitElf64::renameSection(const std::string &oldStr, const std::string &newStr, bool renameAll) {
439   assert(oldStr.length() == newStr.length());
440   for (unsigned k = 0; k < secNames.size(); k++) {
441     if (secNames[k] == oldStr) {
442       secNames[k].replace(0, oldStr.length(), newStr);
443       if (!renameAll)
444         break;
445     }
446   }
447 }
448
449 bool emitElf64::driver(Symtab *obj, string fName){
450   int newfd;
451   Region *foundSec = NULL;
452   unsigned pgSize = getpagesize();
453
454   //open ELf File for writing
455   if((newfd = (open(fName.c_str(), O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP)))==-1){ 
456     log_elferror(err_func_, "error opening file to write symbols");
457     return false;
458   }
459   if((newElf = elf_begin(newfd, ELF_C_WRITE, NULL)) == NULL){
460     log_elferror(err_func_, "NEWELF_BEGIN_FAIL");
461     fflush(stdout);
462     return false;
463   }
464    
465   //Section name index for all sections
466   secNames.push_back("");
467   secNameIndex = 1;
468   //Section name index for new sections
469   loadSecTotalSize = 0;
470   unsigned NOBITStotalsize = 0;
471   int dirtySecsChange = 0;
472   unsigned extraAlignSize = 0;
473     
474   // ".shstrtab" section: string table for section header names
475   const char *shnames = pdelf_get_shnames(oldElfHandle);
476   if (shnames == NULL) {
477     log_elferror(err_func_, ".shstrtab section");
478     return false;
479   }     
480
481   // Write the Elf header first!
482   newEhdr = elf64_newehdr(newElf);
483   if(!newEhdr){
484     log_elferror(err_func_, "newEhdr failed\n");
485     return false;
486   }
487   oldEhdr = elf64_getehdr(oldElf);
488   memcpy(newEhdr, oldEhdr, sizeof(Elf64_Ehdr));
489     
490   newEhdr->e_shnum += newSecs.size();
491
492   // Find the end of text and data segments
493   findSegmentEnds();
494   unsigned insertPoint = oldEhdr->e_shnum;
495   unsigned insertPointOffset = 0;
496   unsigned NOBITSstartPoint = oldEhdr->e_shnum;
497
498   if (movePHdrsFirst)
499   {
500      newEhdr->e_phoff = sizeof(Elf64_Ehdr);
501   }
502     
503   /* flag the file for no auto-layout */
504   elf_flagelf(newElf,ELF_C_SET,ELF_F_LAYOUT);
505     
506   Elf_Scn *scn = NULL, *newscn = NULL;
507   Elf_Data *newdata = NULL, *olddata = NULL;
508   Elf64_Shdr *newshdr = NULL, *shdr = NULL;
509   dyn_hash_map<unsigned, unsigned> secLinkMapping;
510   dyn_hash_map<unsigned, unsigned> secInfoMapping;
511   dyn_hash_map<unsigned, unsigned> changeMapping;
512   dyn_hash_map<std::string, unsigned> newNameIndexMapping;
513   dyn_hash_map<unsigned, std::string> oldIndexNameMapping;
514
515   bool createdLoadableSections = false;
516   unsigned scncount;
517   unsigned sectionNumber = 0;
518
519   bool startMovingSections = false;
520   for (scncount = 0; (scn = elf_nextscn(oldElf, scn)); scncount++) {
521     //copy sections from oldElf to newElf
522     shdr = elf64_getshdr(scn);
523     // resolve section name
524     Region *previousSec = foundSec;
525     const char *name = &shnames[shdr->sh_name];
526     bool result = obj->findRegion(foundSec, shdr->sh_addr, shdr->sh_size);
527     if (!result) {
528       result = obj->findRegion(foundSec, name);
529     } 
530     else if(previousSec == foundSec ) {
531        result = obj->findRegion(foundSec, name);
532     }
533
534     // write the shstrtabsection at the end
535     if(!strcmp(name, ".shstrtab"))
536       continue;
537
538     sectionNumber++;
539     changeMapping[sectionNumber] = 0;
540     oldIndexNameMapping[scncount+1] = string(name);
541     newNameIndexMapping[string(name)] = sectionNumber;
542
543     newscn = elf_newscn(newElf);
544     newshdr = elf64_getshdr(newscn);
545     newdata = elf_newdata(newscn);
546     olddata = elf_getdata(scn,NULL);
547     memcpy(newshdr, shdr, sizeof(Elf64_Shdr));
548     memcpy(newdata,olddata, sizeof(Elf_Data));
549
550     secNames.push_back(name);
551     newshdr->sh_name = secNameIndex;
552     secNameIndex += strlen(name) + 1;
553     
554       if (newshdr->sh_addr) {
555          newshdr->sh_addr += library_adjust;
556       }
557
558     if(foundSec->isDirty())
559     {
560        newdata->d_buf = (char *)malloc(foundSec->getDiskSize());
561        memcpy(newdata->d_buf, foundSec->getPtrToRawData(), foundSec->getDiskSize());
562        newdata->d_size = foundSec->getDiskSize();
563        newshdr->sh_size = foundSec->getDiskSize();
564     }
565     else if(olddata->d_buf)     //copy the data buffer from oldElf
566     {
567        newdata->d_buf = (char *)malloc(olddata->d_size);
568        memcpy(newdata->d_buf, olddata->d_buf, olddata->d_size);
569     }
570     
571     if (newshdr->sh_entsize && (newshdr->sh_size % newshdr->sh_entsize != 0))
572     {
573        newshdr->sh_entsize = 0x0;
574     }
575
576     if(BSSExpandFlag) {
577       // Add the expanded SHT_NOBITS section size if the section comes after those sections 
578       if(scncount > NOBITSstartPoint)
579         newshdr->sh_offset += NOBITStotalsize;
580         
581       // Expand the NOBITS sections in file & and change the type from SHT_NOBITS to SHT_PROGBITS
582       if(shdr->sh_type == SHT_NOBITS)
583         {
584           newshdr->sh_type = SHT_PROGBITS;
585           newdata->d_buf = (char *)malloc(shdr->sh_size);
586           memset(newdata->d_buf, '\0', shdr->sh_size);
587           newdata->d_size = shdr->sh_size;
588           if(NOBITSstartPoint == oldEhdr->e_shnum)
589             NOBITSstartPoint = scncount;
590           NOBITStotalsize += shdr->sh_size; 
591         }
592     }    
593       
594     std::vector <std::vector <unsigned long> > moveSecAddrRange = obj->getObject()->getMoveSecAddrRange();
595
596     for (unsigned i = 0 ; i != moveSecAddrRange.size(); i++) {
597       if ( (moveSecAddrRange[i][0] == shdr->sh_addr) ||
598            (shdr->sh_addr >= moveSecAddrRange[i][0] && shdr->sh_addr < moveSecAddrRange[i][1]) )
599         {
600           newshdr->sh_type = SHT_PROGBITS;
601           changeMapping[sectionNumber] = 1;
602           string newName = ".o";
603           newName.append(name, 2, strlen(name));
604           renameSection((string)name, newName, false);
605         }
606     }
607
608     if((obj->getObject()->getStrtabAddr() != 0 &&
609        obj->getObject()->getStrtabAddr() == shdr->sh_addr) ||
610        !strcmp(name, STRTAB_NAME))
611       {
612         symStrData = newdata;
613         updateSymbols(symTabData, symStrData, loadSecTotalSize);
614       }
615             
616     //Change sh_link for .symtab to point to .strtab
617     if((obj->getObject()->getSymtabAddr() != 0 && 
618        obj->getObject()->getSymtabAddr() == shdr->sh_addr) ||
619        !strcmp(name, SYMTAB_NAME) ){
620       newshdr->sh_link = secNames.size();
621       changeMapping[sectionNumber] = 1;
622       symTabData = newdata;
623     }
624
625     if(obj->getObject()->getTextAddr() != 0 &&
626        obj->getObject()->getTextAddr() == shdr->sh_addr){
627       textData = newdata;
628     }
629
630     if(obj->getObject()->getDynamicAddr() != 0 &&
631        obj->getObject()->getDynamicAddr() == shdr->sh_addr){
632       dynData = newdata;
633       dynSegOff = newshdr->sh_offset;
634       dynSegAddr = newshdr->sh_addr;
635       // Change the data to update the relocation addr
636       newshdr->sh_type = SHT_PROGBITS;
637       changeMapping[sectionNumber] = 1;
638       string newName = ".o";
639       newName.append(name, 2, strlen(name));
640       renameSection((string)name, newName, false);
641       //newSecs.push_back(new Section(oldEhdr->e_shnum+newSecs.size(),".dynamic", /*addr*/, newdata->d_size, dynData, Section::dynamicSection, true));
642     }
643
644     // Only need to rewrite data section
645     if( hasRewrittenTLS && foundSec->isTLS()
646         && foundSec->getRegionType() == Region::RT_DATA )
647     {
648         // Clear TLS flag
649         newshdr->sh_flags &= ~SHF_TLS;
650
651         string newName = ".o";
652         newName.append(name, 2, strlen(name));
653         renameSection((string)name, newName, false);
654     }
655
656     // Change offsets of sections based on the newly added sections
657     if(movePHdrsFirst) {
658         /* This special case is specific to FreeBSD but there is no hurt in
659          * handling it on other platforms.
660          *
661          * This is necessary because the INTERP header must be located within in
662          * the first page of the file -- if the section is moved to the next
663          * page the object file will not be parsed correctly by the kernel.
664          *
665          * However, the initial sections still need to be shifted, but just
666          * by the difference in size of the new PHDR segment. 
667          */
668         if( newshdr->sh_offset > 0 ) {
669             if( startMovingSections || obj->isStaticBinary() 
670                 || obj->getObjectType() == obj_SharedLib ) newshdr->sh_offset += pgSize;
671             else if( createNewPhdr ) newshdr->sh_offset += oldEhdr->e_phentsize;
672         }
673     }           
674
675     if(scncount > insertPoint && newshdr->sh_offset >= insertPointOffset)
676       newshdr->sh_offset += loadSecTotalSize;
677
678     if (newshdr->sh_offset > 0 ) 
679         newshdr->sh_offset += dirtySecsChange;
680
681     if (BSSExpandFlag) {
682         if( newshdr->sh_offset > 0 ) {
683             newshdr->sh_offset += extraAlignSize;
684         }
685     }else if (newshdr->sh_offset >= insertPointOffset ) {
686         newshdr->sh_offset += extraAlignSize;
687     }
688
689     if(foundSec->isDirty()) 
690       dirtySecsChange += newshdr->sh_size - shdr->sh_size;
691     if(BSSExpandFlag && newshdr->sh_addr){
692       unsigned newOff = newshdr->sh_offset - (newshdr->sh_offset & (pgSize-1)) + (newshdr->sh_addr & (pgSize-1));
693       if(newOff < newshdr->sh_offset)
694         newOff += pgSize;
695       extraAlignSize += newOff - newshdr->sh_offset;
696       newshdr->sh_offset = newOff;
697     }
698         
699
700     secLinkMapping[sectionNumber] = shdr->sh_link; 
701     secInfoMapping[sectionNumber] = shdr->sh_info; 
702
703     rewrite_printf("section %s addr = %lx off = %lx size = %lx\n",
704             name, newshdr->sh_addr, newshdr->sh_offset, newshdr->sh_size);
705
706     //Insert new loadable sections at the end of data segment                   
707     if (shdr->sh_addr+shdr->sh_size == dataSegEnd && !createdLoadableSections) {
708       createdLoadableSections = true;
709       insertPoint = scncount;
710       if( SHT_NOBITS == shdr->sh_type ) {
711           insertPointOffset = shdr->sh_offset;
712       }else{
713           insertPointOffset = shdr->sh_offset + shdr->sh_size;
714       }
715
716       if(!createLoadableSections(obj, newshdr, extraAlignSize, 
717                                  newNameIndexMapping, sectionNumber))
718          return false;
719       if (!movePHdrsFirst) {
720          sectionNumber++;
721          createNewPhdrRegion(newNameIndexMapping);
722         }
723
724       // Update the heap symbols, now that loadSecTotalSize is set
725       updateSymbols(dynsymData, dynStrData, loadSecTotalSize);
726     }
727
728     if ( 0 >  elf_update(newElf, ELF_C_NULL))
729     {
730        fprintf(stderr, "%s[%d]:  elf_update failed: %d, %s\n", FILE__, __LINE__, elf_errno(), elf_errmsg(elf_errno()));
731        return false;
732     }
733
734     if( !strcmp(name, INTERP_NAME) ) {
735         startMovingSections = true;
736     }
737   }
738
739   // Add non-loadable sections at the end of object file
740   if(!createNonLoadableSections(newshdr))
741     return false;
742
743   if ( 0 >  elf_update(newElf, ELF_C_NULL))
744   {
745      fprintf(stderr, "%s[%d]:  elf_update failed: %d, %s\n", FILE__, __LINE__, elf_errno(), elf_errmsg(elf_errno()));
746      return false;
747   }
748    
749   //Add the section header table right at the end        
750   addSectionHeaderTable(newshdr);
751
752   // Second iteration to fix the link fields to point to the correct section
753   scn = NULL;
754
755   for (scncount = 0; (scn = elf_nextscn(newElf, scn)); scncount++) {
756     shdr = elf64_getshdr(scn);
757     if (changeMapping[scncount+1] == 0 && secLinkMapping[scncount+1] != 0) {
758       unsigned linkIndex = secLinkMapping[scncount+1];
759       string secName = oldIndexNameMapping[linkIndex];
760       unsigned newLinkIndex = newNameIndexMapping[secName];
761       shdr->sh_link = newLinkIndex;
762     } 
763
764     if (changeMapping[scncount+1] == 0 && secInfoMapping[scncount+1] != 0) {
765       // For REL and RELA section, info field is a section index - hence of the index changes, the info field must change.
766       // For SYMTAB and DYNSYM, info field is OS specific - so just copy it.
767       // For others, info field is 0, so just copy it
768       if (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA) {
769         unsigned infoIndex = secInfoMapping[scncount+1];
770         string secName = oldIndexNameMapping[infoIndex];
771         unsigned newInfoIndex = newNameIndexMapping[secName];
772         shdr->sh_info = newInfoIndex;
773       } 
774     }
775   }
776
777   newEhdr->e_shstrndx = scncount;
778
779   // Move the section header to the end
780   newEhdr->e_shoff =shdr->sh_offset+shdr->sh_size;
781   if (newEhdr->e_shoff % 8)
782     newEhdr->e_shoff += 8 - (newEhdr->e_shoff % 8);
783   //copy program headers
784   oldPhdr = elf64_getphdr(oldElf);
785   fixPhdrs(extraAlignSize);
786
787   //Write the new Elf file
788   if (elf_update(newElf, ELF_C_WRITE) < 0){
789     int err;
790     if ((err = elf_errno()) != 0)
791       {
792         const char *msg = elf_errmsg(err);
793         /* print msg */
794         fprintf(stderr, "Error: Unable to write ELF file: %s\n", msg);
795       }
796     log_elferror(err_func_, "elf_update failed");
797     return false;
798   }
799   elf_end(newElf);
800   
801   if (hasPHdrSectionBug()) {
802      unsigned long ehdr_off = (unsigned long) &(((Elf64_Ehdr *) 0x0)->e_phoff);
803      lseek(newfd, ehdr_off, SEEK_SET);
804      Elf64_Off offset = (Elf64_Off) phdr_offset;
805      write(newfd, &offset, sizeof(Elf64_Off));
806   }
807   close(newfd);
808
809   return true;
810 }
811
812 void emitElf64::createNewPhdrRegion(dyn_hash_map<std::string, unsigned> &newNameIndexMapping)
813 {
814    assert(!movePHdrsFirst);
815
816    unsigned phdr_size = oldEhdr->e_phnum*oldEhdr->e_phentsize;
817    if (createNewPhdr)
818       phdr_size += oldEhdr->e_phentsize;
819
820    unsigned align = 0;
821    if (currEndOffset % 8)
822       align = 8 - (currEndOffset % 8);
823
824    newEhdr->e_phoff = currEndOffset + align;
825    phdr_offset = newEhdr->e_phoff;
826
827    Address endaddr = currEndAddress;
828    currEndAddress += phdr_size + align;
829    currEndOffset += phdr_size + align;
830    loadSecTotalSize += phdr_size + align;
831
832    //libelf.so.1 is annoying.  It'll overwrite the data
833    // between sections with 0's, even if we've stuck the
834    // program headers in there.  Create a dummy section
835    // to contain the program headers.
836    phdrs_scn = elf_newscn(newElf);
837    Elf64_Shdr *newshdr = elf64_getshdr(phdrs_scn);
838    const char *newname = ".dynphdrs";
839
840    secNames.push_back(newname);
841    newNameIndexMapping[newname] = secNames.size() - 1;
842    newshdr->sh_name = secNameIndex;
843    secNameIndex += strlen(newname) + 1;
844    newshdr->sh_flags = SHF_ALLOC;
845    newshdr->sh_type = SHT_PROGBITS;
846    newshdr->sh_offset = newEhdr->e_phoff;
847    newshdr->sh_addr = endaddr + align;
848    newshdr->sh_size = phdr_size;
849    newshdr->sh_link = SHN_UNDEF;
850    newshdr->sh_info = 0;
851    newshdr->sh_addralign = 4;
852    newshdr->sh_entsize = newEhdr->e_phentsize;
853 }
854
855 void emitElf64::fixPhdrs(unsigned &extraAlignSize)
856 {
857   unsigned pgSize = getpagesize();
858   Elf64_Phdr *old = oldPhdr;
859
860   newEhdr->e_phnum = oldEhdr->e_phnum;
861   newEhdr->e_phentsize = oldEhdr->e_phentsize;
862   if(createNewPhdr) {
863      newEhdr->e_phnum++;
864      if( hasRewrittenTLS && !TLSExists ) newEhdr->e_phnum++;
865   }
866   if(BSSExpandFlag)
867     newEhdr->e_phnum= oldEhdr->e_phnum;
868
869   bool added_new_sec = false;    
870
871   if (!hasPHdrSectionBug())
872      newPhdr = elf64_newphdr(newElf,newEhdr->e_phnum);
873   else {
874      newPhdr = (Elf64_Phdr *) malloc(sizeof(Elf64_Phdr) * newEhdr->e_phnum);
875   }
876   void *phdr_data = (void *) newPhdr;
877
878   Elf64_Phdr newSeg;
879   for(unsigned i=0;i<oldEhdr->e_phnum;i++)
880   {
881     /*
882      * If we've created a new loadable segment, we need to insert a new
883      * program header amidst the other loadable segments.
884      * 
885      * ELF format says:
886      *
887      * `Loadable segment entries in the program header table appear in
888      * ascending order, sorted on the p_vaddr member.'
889      */
890
891     Elf64_Phdr * insert_phdr = NULL;
892       if(createNewPhdr && !added_new_sec && firstNewLoadSec) {
893         if(i+1 == oldEhdr->e_phnum) {
894             insert_phdr = newPhdr + 1;
895         }
896         else if(old->p_type == PT_LOAD && (old+1)->p_type != PT_LOAD) {
897             // insert at end of loadable phdrs
898             insert_phdr = newPhdr+1;
899         }
900         else if(old->p_type != PT_LOAD &&
901                 (old+1)->p_type == PT_LOAD &&
902                 newSegmentStart < (old+1)->p_vaddr)
903         {   
904             // insert at beginning of loadable list (after the
905             // current phdr)
906             insert_phdr = newPhdr+1;
907         }
908         else if(old->p_type == PT_LOAD &&
909                 (old+1)->p_type == PT_LOAD &&
910                 newSegmentStart >= old->p_vaddr &&
911                 newSegmentStart < (old+1)->p_vaddr)
912         {
913             // insert in middle of loadable list, after current
914             insert_phdr = newPhdr+1;
915         }
916         else if(i == 0 && 
917                 old->p_type == PT_LOAD &&
918                 newSegmentStart < old->p_vaddr)
919         {
920             // insert BEFORE current phdr
921             insert_phdr = newPhdr;
922             newPhdr++;
923         }
924     }
925
926       if(insert_phdr)
927       {
928          newSeg.p_type = PT_LOAD;
929          newSeg.p_offset = firstNewLoadSec->sh_offset;
930          newSeg.p_vaddr = newSegmentStart;
931          newSeg.p_paddr = newSeg.p_vaddr;
932          newSeg.p_filesz = loadSecTotalSize - (newSegmentStart - firstNewLoadSec->sh_addr);
933          newSeg.p_memsz = (currEndAddress - firstNewLoadSec->sh_addr) - (newSegmentStart - firstNewLoadSec->sh_addr);
934          newSeg.p_flags = PF_R+PF_W+PF_X;
935          newSeg.p_align = pgSize;
936          memcpy(insert_phdr, &newSeg, oldEhdr->e_phentsize);
937          added_new_sec = true;
938 #ifdef BINEDIT_DEBUG
939          fprintf(stderr, "Added New program header : offset 0x%lx,addr 0x%lx\n", newPhdr->p_offset, newPhdr->p_vaddr);
940 #endif
941       }
942
943
944
945      memcpy(newPhdr, old, oldEhdr->e_phentsize);
946      // Expand the data segment to include the new loadable sections
947      // Also add a executable permission to the segment
948      if(old->p_type == PT_DYNAMIC){
949         newPhdr->p_type = PT_DYNAMIC;
950         newPhdr->p_vaddr = dynSegAddr;
951         newPhdr->p_paddr = dynSegAddr;
952         newPhdr->p_offset = dynSegOff;
953         newPhdr->p_memsz = dynSegSize;
954         newPhdr->p_filesz = newPhdr->p_memsz;
955      }
956      else if(old->p_type == PT_PHDR){
957         newPhdr->p_type = PT_PHDR;
958         newPhdr->p_vaddr = old->p_vaddr - pgSize;
959         newPhdr->p_paddr = newPhdr->p_vaddr;
960         newPhdr->p_filesz = sizeof(Elf64_Phdr) * newEhdr->e_phnum;
961         newPhdr->p_memsz = newPhdr->p_filesz;
962      }else if( hasRewrittenTLS && old->p_type == PT_TLS) {
963           newPhdr->p_offset = newTLSData->sh_offset;
964           newPhdr->p_vaddr = newTLSData->sh_addr;
965           newPhdr->p_paddr = newTLSData->sh_addr;
966           newPhdr->p_filesz = newTLSData->sh_size;
967           newPhdr->p_memsz = newTLSData->sh_size + old->p_memsz - old->p_filesz;
968           newPhdr->p_align = newTLSData->sh_addralign;
969      }else if (old->p_type == PT_LOAD) {
970         if(newPhdr->p_align > pgSize) {
971            newPhdr->p_align = pgSize;
972         }
973         if(BSSExpandFlag) {
974            if(old->p_flags == 6 || old->p_flags == 7)
975            {
976               newPhdr->p_memsz += loadSecTotalSize + extraAlignSize;
977               newPhdr->p_filesz = newPhdr->p_memsz;
978               newPhdr->p_flags = 7;
979            }    
980         }    
981         if(movePHdrsFirst) {
982            if (!old->p_offset) {
983               if (newPhdr->p_vaddr)
984                  newPhdr->p_vaddr = old->p_vaddr - pgSize;
985               newPhdr->p_paddr = newPhdr->p_vaddr;
986               newPhdr->p_filesz += pgSize;
987               newPhdr->p_memsz = newPhdr->p_filesz;
988            }
989            else {
990               newPhdr->p_offset += pgSize;
991            }
992            if (newPhdr->p_vaddr) {
993               newPhdr->p_vaddr += library_adjust;
994               newPhdr->p_paddr += library_adjust;
995            }
996         }
997      }
998      else if (old->p_type == PT_INTERP && movePHdrsFirst
999              && old->p_offset && newEhdr->e_phnum > oldEhdr->e_phnum)
1000      {
1001          newPhdr->p_offset +=
1002              oldEhdr->e_phentsize*(newEhdr->e_phnum-oldEhdr->e_phnum);
1003      }
1004      else if (movePHdrsFirst && old->p_offset) {
1005         newPhdr->p_offset += pgSize;
1006         if (newPhdr->p_vaddr) {
1007            newPhdr->p_vaddr += library_adjust;
1008            newPhdr->p_paddr += library_adjust;
1009         }
1010      } 
1011
1012      newPhdr++;
1013      if(insert_phdr)
1014         newPhdr++;
1015      old++;
1016   }
1017
1018   if( hasRewrittenTLS && !TLSExists ) {
1019     newPhdr->p_type = PT_TLS;
1020     newPhdr->p_offset = newTLSData->sh_offset;
1021     newPhdr->p_vaddr = newTLSData->sh_addr;
1022     newPhdr->p_filesz = newTLSData->sh_size;
1023     newPhdr->p_memsz = newTLSData->sh_size;
1024     newPhdr->p_align = newTLSData->sh_addralign;
1025   }
1026   
1027   if (!phdrs_scn)
1028      return;
1029   //We made a new section to contain the program headers--keeps
1030   // libelf from overwriting the program headers data when outputing
1031   // sections.  Fill in the new section's data with what we just wrote.
1032   Elf_Data *data = elf_newdata(phdrs_scn);
1033   size_t total_size = newEhdr->e_phnum * newEhdr->e_phentsize;
1034   data->d_buf = malloc(total_size);
1035   memcpy(data->d_buf, phdr_data, total_size);
1036   data->d_size = total_size;
1037   data->d_align = 0;
1038   data->d_off = 0;
1039   data->d_type = ELF_T_BYTE;
1040   data->d_version = 1;
1041 }
1042
1043 #if !defined(DT_GNU_HASH)
1044 #define DT_GNU_HASH 0x6ffffef5
1045 #endif
1046 #if !defined(DT_GNU_CONFLICT)
1047 #define DT_GNU_CONFLICT 0x6ffffef8
1048 #endif
1049
1050 //This method updates the .dynamic section to reflect the changes to the relocation section
1051 void emitElf64::updateDynamic(unsigned tag, Elf64_Addr val){
1052   if(dynamicSecData.find(tag) == dynamicSecData.end()) {
1053     return;
1054   }
1055     
1056    switch(dynamicSecData[tag][0]->d_tag) {
1057   case DT_STRSZ:
1058   case DT_RELSZ:
1059   case DT_RELASZ:
1060     dynamicSecData[tag][0]->d_un.d_val = val;
1061     break;
1062   case DT_HASH:
1063   case DT_GNU_HASH:
1064   case DT_SYMTAB:
1065   case DT_STRTAB:
1066   case DT_REL:
1067   case DT_RELA:
1068   case DT_VERSYM:
1069   case DT_JMPREL:
1070     dynamicSecData[tag][0]->d_un.d_ptr = val;
1071     break;
1072   case DT_VERNEED:
1073     dynamicSecData[tag][0]->d_un.d_ptr = val;
1074     dynamicSecData[DT_VERNEEDNUM][0]->d_un.d_val = verneednum;
1075     break;
1076   case DT_VERDEF:
1077     dynamicSecData[tag][0]->d_un.d_ptr = val;
1078     dynamicSecData[DT_VERDEFNUM][0]->d_un.d_val = verdefnum;
1079     break;
1080   }
1081
1082 }
1083
1084 /* This method sets _end and _END_ to the starting position of the heap in the
1085  * new binary. 
1086  */
1087 void emitElf64::updateSymbols(Elf_Data* symtabData,Elf_Data* strData, unsigned long loadSecsSize){
1088   unsigned pgSize = (unsigned)getpagesize();
1089   if( symtabData && strData && loadSecsSize){
1090     Elf64_Sym *symPtr=(Elf64_Sym*)symtabData->d_buf;
1091     for(unsigned int i=0;i< symtabData->d_size/(sizeof(Elf64_Sym));i++,symPtr++){
1092       if(!(strcmp("_end", (char*) strData->d_buf + symPtr->st_name))){
1093         if( newSegmentStart >= symPtr->st_value ) {
1094             symPtr->st_value += ((newSegmentStart - symPtr->st_value) + loadSecsSize);
1095
1096             // Advance the location to the next page boundary
1097             symPtr->st_value = (symPtr->st_value & ~(pgSize-1)) + pgSize;
1098         }
1099       }
1100       if(!(strcmp("_END_", (char*) strData->d_buf + symPtr->st_name))){
1101           if( newSegmentStart >= symPtr->st_value ) {
1102               symPtr->st_value += (newSegmentStart - symPtr->st_value) + loadSecsSize;
1103
1104               // Advance the location to the next page boundary
1105               symPtr->st_value = (symPtr->st_value & ~(pgSize-1)) + pgSize;
1106           }
1107       }
1108     }    
1109   }
1110 }
1111
1112
1113
1114 bool emitElf64::createLoadableSections(Symtab *obj, Elf64_Shdr* &shdr, unsigned &extraAlignSize, dyn_hash_map<std::string, unsigned> &newNameIndexMapping, unsigned &sectionNumber)
1115 {
1116    Elf_Scn *newscn;
1117    Elf_Data *newdata = NULL;
1118    Elf64_Shdr *newshdr;
1119    std::vector<Elf64_Shdr *> updateDynLinkShdr;
1120    std::vector<Elf64_Shdr *> updateStrLinkShdr;
1121    firstNewLoadSec = NULL;
1122    unsigned pgSize = getpagesize();
1123    unsigned strtabIndex = 0;
1124    unsigned dynsymIndex = 0;
1125    Elf64_Shdr *prevshdr = NULL;
1126
1127    /*
1128     * Order the new sections such that those with explicit
1129     * memory offsets come before those without (that will be placed
1130     * after the non-zero sections).
1131     *
1132     * zstart is used to place the first zero-offset section if
1133     * no non-zero-offset sections exist.
1134     */
1135    Address zstart = emitElfUtils::orderLoadableSections(obj,newSecs);
1136
1137    for(unsigned i=0; i < newSecs.size(); i++)
1138    {
1139       if(!newSecs[i]->isLoadable()) {
1140          nonLoadableSecs.push_back(newSecs[i]);
1141          continue;
1142       }
1143       secNames.push_back(newSecs[i]->getRegionName());
1144       newNameIndexMapping[newSecs[i]->getRegionName()] = secNames.size() -1;
1145       sectionNumber++;
1146       // Add a new loadable section
1147       if((newscn = elf_newscn(newElf)) == NULL)
1148       {  
1149          log_elferror(err_func_, "unable to create new function");      
1150          return false;
1151       }         
1152       if ((newdata = elf_newdata(newscn)) == NULL)
1153       {
1154          log_elferror(err_func_, "unable to create section data");      
1155          return false;
1156       } 
1157       memset(newdata, 0, sizeof(Elf_Data));
1158
1159       // Fill out the new section header        
1160       newshdr = elf64_getshdr(newscn);
1161       newshdr->sh_name = secNameIndex;
1162       newshdr->sh_flags = 0;
1163       newshdr->sh_type = SHT_PROGBITS;
1164       switch(newSecs[i]->getRegionType()){
1165          case Region::RT_TEXTDATA:
1166             newshdr->sh_flags = SHF_EXECINSTR | SHF_ALLOC | SHF_WRITE;
1167             break;
1168          case Region::RT_TEXT:
1169             newshdr->sh_flags = SHF_EXECINSTR | SHF_ALLOC;
1170             break;
1171          case Region::RT_BSS:
1172             newshdr->sh_type = SHT_NOBITS;
1173          case Region::RT_DATA:
1174             newshdr->sh_flags = SHF_WRITE | SHF_ALLOC;
1175             break;
1176          default:
1177             break;
1178       }
1179
1180      if(shdr->sh_type == SHT_NOBITS)
1181         newshdr->sh_offset = shdr->sh_offset;
1182      else if( !firstNewLoadSec || !newSecs[i]->getDiskOffset() ) {
1183         newshdr->sh_offset = shdr->sh_offset+shdr->sh_size;
1184      }else{
1185          // The offset can be computed by determing the difference from
1186          // the first new loadable section
1187          newshdr->sh_offset = firstNewLoadSec->sh_offset +
1188              (newSecs[i]->getDiskOffset() - firstNewLoadSec->sh_addr);
1189
1190          // Account for inter-section spacing due to alignment constraints
1191          loadSecTotalSize += newshdr->sh_offset - (shdr->sh_offset+shdr->sh_size);
1192      }
1193
1194       if(newSecs[i]->getDiskOffset()) {
1195          newshdr->sh_addr = newSecs[i]->getDiskOffset() + library_adjust;
1196       }
1197       else if(!prevshdr) {
1198          newshdr->sh_addr = zstart + library_adjust;
1199       } 
1200       else 
1201       {
1202          newshdr->sh_addr = prevshdr->sh_addr + prevshdr->sh_size;
1203       }
1204             
1205       newshdr->sh_link = SHN_UNDEF;
1206       newshdr->sh_info = 0;
1207       newshdr->sh_addralign = newSecs[i]->getMemAlignment();
1208       newshdr->sh_entsize = 0;
1209
1210       // TLS section
1211       if( newSecs[i]->isTLS() ) {
1212           newTLSData = newshdr;
1213           newshdr->sh_flags |= SHF_TLS;
1214       }
1215
1216       if(newSecs[i]->getRegionType() == Region::RT_REL ||
1217          newSecs[i]->getRegionType() == Region::RT_PLTREL)    //Relocation section
1218       {
1219          newshdr->sh_type = SHT_REL;
1220          newshdr->sh_flags = SHF_ALLOC;
1221          newshdr->sh_entsize = sizeof(Elf64_Rel);
1222          updateDynLinkShdr.push_back(newshdr);
1223          newdata->d_type = ELF_T_REL;
1224          newdata->d_align = 4;
1225          if (newSecs[i]->getRegionType() == Region::RT_REL)
1226             updateDynamic(DT_REL, newshdr->sh_addr);
1227          else if (newSecs[i]->getRegionType() == Region::RT_PLTREL)
1228             updateDynamic(DT_JMPREL, newshdr->sh_addr);
1229       }
1230       else if(newSecs[i]->getRegionType() == Region::RT_RELA ||
1231               newSecs[i]->getRegionType() == Region::RT_PLTRELA) //Relocation section
1232       {
1233          newshdr->sh_type = SHT_RELA;
1234          newshdr->sh_flags = SHF_ALLOC;
1235          newshdr->sh_entsize = sizeof(Elf64_Rela);
1236          updateDynLinkShdr.push_back(newshdr);
1237          newdata->d_type = ELF_T_RELA;
1238          newdata->d_align = 4;
1239          if (newSecs[i]->getRegionType() == Region::RT_RELA)
1240             updateDynamic(DT_RELA, newshdr->sh_addr);
1241          else if (newSecs[i]->getRegionType() == Region::RT_PLTRELA)
1242             updateDynamic(DT_JMPREL, newshdr->sh_addr);
1243       }
1244       else if(newSecs[i]->getRegionType() == Region::RT_STRTAB)    //String table Section
1245       {
1246          newshdr->sh_type = SHT_STRTAB;
1247          newshdr->sh_entsize = 1;
1248          newdata->d_type = ELF_T_BYTE;
1249          newshdr->sh_link = SHN_UNDEF;
1250          newshdr->sh_flags=  SHF_ALLOC;
1251          newdata->d_align = 1;
1252          dynStrData = newdata;
1253          strtabIndex = secNames.size()-1;
1254          newshdr->sh_addralign = 1;
1255          updateDynamic(DT_STRTAB, newshdr->sh_addr);
1256          updateDynamic(DT_STRSZ, newSecs[i]->getDiskSize());
1257       }
1258       else if(newSecs[i]->getRegionType() == Region::RT_SYMTAB)
1259       {
1260          newshdr->sh_type = SHT_DYNSYM;
1261          newshdr->sh_entsize = sizeof(Elf64_Sym);
1262          newdata->d_type = ELF_T_SYM;
1263          newdata->d_align = 4;
1264          dynsymData = newdata;
1265          newshdr->sh_link = secNames.size();   //.symtab section should have sh_link = index of .strtab for .dynsym
1266          newshdr->sh_flags = SHF_ALLOC ;
1267          dynsymIndex = secNames.size()-1;
1268          updateDynamic(DT_SYMTAB, newshdr->sh_addr);
1269       }
1270       else if(newSecs[i]->getRegionType() == Region::RT_DYNAMIC)
1271       {
1272          newshdr->sh_entsize = sizeof(Elf64_Dyn);
1273          newshdr->sh_type = SHT_DYNAMIC;
1274          newdata->d_type = ELF_T_DYN;
1275          newdata->d_align = 4;
1276          updateStrLinkShdr.push_back(newshdr);
1277          newshdr->sh_flags=  SHF_ALLOC | SHF_WRITE;
1278          dynSegOff = newshdr->sh_offset;
1279          dynSegAddr = newshdr->sh_addr;
1280          dynSegSize = newSecs[i]->getDiskSize();
1281       }
1282       else if(newSecs[i]->getRegionType() == Region::RT_HASH)
1283       {
1284          newshdr->sh_entsize = sizeof(Elf64_Word);
1285          newshdr->sh_type = SHT_HASH;
1286          newdata->d_type = ELF_T_WORD;
1287          newdata->d_align = 4;
1288          updateDynLinkShdr.push_back(newshdr);
1289          newshdr->sh_flags=  SHF_ALLOC;
1290          newshdr->sh_info = 0;
1291          updateDynamic(DT_HASH, newshdr->sh_addr);
1292       }
1293       else if(newSecs[i]->getRegionType() == Region::RT_SYMVERSIONS)
1294       {
1295          newshdr->sh_type = SHT_GNU_versym;
1296          newshdr->sh_entsize = sizeof(Elf64_Half);
1297          newshdr->sh_addralign = 2;
1298          newdata->d_type = ELF_T_HALF;
1299          newdata->d_align = 2;
1300          updateDynLinkShdr.push_back(newshdr);
1301          newshdr->sh_flags = SHF_ALLOC ;
1302          updateDynamic(DT_VERSYM, newshdr->sh_addr);
1303       }
1304       else if(newSecs[i]->getRegionType() == Region::RT_SYMVERNEEDED)
1305       {
1306          newshdr->sh_type = SHT_GNU_verneed;
1307          newshdr->sh_entsize = 0;
1308          newshdr->sh_addralign = 4;
1309          newdata->d_type = ELF_T_VNEED;
1310          newdata->d_align = 4;
1311          updateStrLinkShdr.push_back(newshdr);
1312          newshdr->sh_flags = SHF_ALLOC ;
1313          newshdr->sh_info = 2;
1314          updateDynamic(DT_VERNEED, newshdr->sh_addr);
1315       }
1316       else if(newSecs[i]->getRegionType() == Region::RT_SYMVERDEF)
1317       {
1318          newshdr->sh_type = SHT_GNU_verdef;
1319          newshdr->sh_entsize = 0;
1320          newdata->d_type = ELF_T_VDEF;
1321          newdata->d_align = 4;
1322          updateStrLinkShdr.push_back(newshdr);
1323          newshdr->sh_flags = SHF_ALLOC ;
1324          updateDynamic(DT_VERDEF, newshdr->sh_addr);
1325       }
1326
1327       if(createNewPhdr)
1328       {
1329          // Check to make sure the (vaddr for the start of the new segment - the offset) is page aligned
1330          if(!firstNewLoadSec)
1331          {
1332             newSegmentStart = newshdr->sh_addr;
1333             Offset newoff = newshdr->sh_offset  - (newshdr->sh_offset & (pgSize-1)) + (newshdr->sh_addr & (pgSize-1));
1334             if(newoff < newshdr->sh_offset)
1335                newoff += pgSize;
1336             extraAlignSize += newoff - newshdr->sh_offset;
1337             newshdr->sh_offset = newoff;
1338          }    
1339       } 
1340       else{
1341          Offset newoff = newshdr->sh_offset  - (newshdr->sh_offset & (pgSize-1)) + (newshdr->sh_addr & (pgSize-1));
1342          if(newoff < newshdr->sh_offset)
1343             newoff += pgSize;
1344          extraAlignSize += newoff - newshdr->sh_offset;
1345          newshdr->sh_offset = newoff;
1346       }
1347
1348       //Set up the data
1349       newdata->d_buf = malloc(newSecs[i]->getDiskSize());
1350       memcpy(newdata->d_buf, newSecs[i]->getPtrToRawData(), newSecs[i]->getDiskSize());
1351       newdata->d_off = 0;
1352       newdata->d_size = newSecs[i]->getDiskSize();
1353       if (!newdata->d_align)
1354          newdata->d_align = newshdr->sh_addralign;
1355       newshdr->sh_size = newdata->d_size;
1356
1357       currEndOffset = newshdr->sh_offset + newshdr->sh_size;
1358       if( newshdr->sh_type == SHT_NOBITS ) {
1359           currEndOffset = newshdr->sh_offset;
1360       }else{
1361           loadSecTotalSize += newshdr->sh_size;
1362           currEndOffset = newshdr->sh_offset + newshdr->sh_size;
1363       }
1364       currEndAddress = newshdr->sh_addr + newshdr->sh_size;
1365
1366       rewrite_printf("new section %s addr = %lx off = %lx size = %lx\n",
1367               newSecs[i]->getRegionName().c_str(), newshdr->sh_addr, newshdr->sh_offset,
1368               newshdr->sh_size);
1369             
1370       newdata->d_version = 1;
1371
1372       if (newshdr->sh_entsize && (newshdr->sh_size % newshdr->sh_entsize != 0))
1373          fprintf(stderr, "%s[%d]:  ERROR:  setting size to non multiple of "
1374                  "entry size in section %s: %lu/%lu\n", FILE__, __LINE__, 
1375                  newSecs[i]->getRegionName().c_str(), newshdr->sh_size, 
1376                  newshdr->sh_entsize);
1377
1378       if (0 > elf_update(newElf, ELF_C_NULL))
1379       {
1380           fprintf(stderr, "%s[%d]:  elf_update failed: %d, %s\n", FILE__, __LINE__, elf_errno(), elf_errmsg(elf_errno()));
1381           return false;
1382       }
1383
1384       shdr = newshdr;
1385       if(!firstNewLoadSec)
1386          firstNewLoadSec = shdr;
1387       secNameIndex += newSecs[i]->getRegionName().size() + 1;
1388       /* DEBUG */
1389 #ifdef BINEDIT_DEBUG
1390       fprintf(stderr, "Added New Section(%s) : secAddr 0x%lx, secOff 0x%lx, "
1391               "secsize 0x%lx, end 0x%lx\n",
1392               newSecs[i]->getRegionName().c_str(), newshdr->sh_addr, 
1393               newshdr->sh_offset, newshdr->sh_size, 
1394               newshdr->sh_offset + newshdr->sh_size );
1395 #endif
1396       prevshdr = newshdr;
1397    }    
1398     
1399    for(unsigned i=0; i < updateDynLinkShdr.size(); i++) {
1400       newshdr = updateDynLinkShdr[i];
1401       newshdr->sh_link = dynsymIndex;   
1402    }
1403     
1404    for(unsigned i=0; i < updateStrLinkShdr.size(); i++) {
1405       newshdr = updateStrLinkShdr[i];
1406       newshdr->sh_link = strtabIndex;   
1407    }
1408    
1409    return true;
1410 }
1411         
1412 bool emitElf64::addSectionHeaderTable(Elf64_Shdr *shdr) {
1413    Elf_Scn *newscn;
1414    Elf_Data *newdata = NULL;
1415    Elf64_Shdr *newshdr;
1416    
1417    if((newscn = elf_newscn(newElf)) == NULL)
1418    {
1419       log_elferror(err_func_, "unable to create new function"); 
1420       return false;
1421    }    
1422    if ((newdata = elf_newdata(newscn)) == NULL)
1423    {
1424       log_elferror(err_func_, "unable to create section data"); 
1425       return false;
1426    } 
1427    //Fill out the new section header
1428    newshdr = elf64_getshdr(newscn);
1429    newshdr->sh_name = secNameIndex;
1430    secNames.push_back(".shstrtab");
1431    secNameIndex += 10;
1432    newshdr->sh_type = SHT_STRTAB;
1433    newshdr->sh_entsize = 1;
1434    newdata->d_type = ELF_T_BYTE;
1435    newshdr->sh_link = SHN_UNDEF; 
1436    newshdr->sh_flags=  0;
1437
1438    newshdr->sh_offset = shdr->sh_offset+shdr->sh_size;
1439    newshdr->sh_addr = 0;
1440    newshdr->sh_info = 0;
1441    newshdr->sh_addralign = 4;
1442    
1443    //Set up the data
1444    newdata->d_buf = (char *)malloc(secNameIndex);
1445    char *ptr = (char *)newdata->d_buf;
1446    for(unsigned i=0;i<secNames.size(); i++)
1447    {
1448       memcpy(ptr, secNames[i].c_str(), secNames[i].length());
1449       memcpy(ptr+secNames[i].length(), "\0", 1);
1450       ptr += secNames[i].length()+1;
1451    }    
1452     
1453    newdata->d_size = secNameIndex;
1454    newshdr->sh_size = newdata->d_size;
1455 #ifdef BINEDIT_DEBUG
1456    fprintf(stderr, "Added New Section(%s) : secAddr 0x%lx, secOff 0x%lx, secsize 0x%lx, end 0x%lx\n",
1457            ".shstrtab", newshdr->sh_addr, newshdr->sh_offset, newshdr->sh_size, newshdr->sh_offset + newshdr->sh_size );
1458 #endif
1459    //elf_update(newElf, ELF_C_NULL);
1460    
1461    newdata->d_align = 4;
1462    newdata->d_version = 1;
1463         if (newshdr->sh_entsize && (newshdr->sh_size % newshdr->sh_entsize != 0))
1464                 fprintf(stderr, "%s[%d]:  ERROR:  setting size to non multiple of entry size in section %s: %lu/%lu\n", FILE__, __LINE__, ".shstrtab", newshdr->sh_size, newshdr->sh_entsize);
1465    return true;
1466 }
1467
1468 bool emitElf64::createNonLoadableSections(Elf64_Shdr *&shdr)
1469 {
1470   Elf_Scn *newscn;
1471   Elf_Data *newdata = NULL;
1472   Elf64_Shdr *newshdr;
1473     
1474   Elf64_Shdr *prevshdr = shdr; 
1475   //All of them that are left are non-loadable. stack'em up at the end.
1476   for(unsigned i = 0; i < nonLoadableSecs.size(); i++)
1477     {
1478       secNames.push_back(nonLoadableSecs[i]->getRegionName());
1479       // Add a new non-loadable section
1480       if((newscn = elf_newscn(newElf)) == NULL)
1481         {
1482           log_elferror(err_func_, "unable to create new function");     
1483           return false;
1484         }       
1485       if ((newdata = elf_newdata(newscn)) == NULL)
1486         {
1487           log_elferror(err_func_, "unable to create section data");     
1488           return false;
1489         } 
1490
1491       //Fill out the new section header
1492       newshdr = elf64_getshdr(newscn);
1493       newshdr->sh_name = secNameIndex;
1494       secNameIndex += nonLoadableSecs[i]->getRegionName().length() + 1;
1495       if(nonLoadableSecs[i]->getRegionType() == Region::RT_TEXT)                //Text Section
1496         {
1497           newshdr->sh_type = SHT_PROGBITS;
1498           newshdr->sh_flags = SHF_EXECINSTR | SHF_WRITE;
1499           newshdr->sh_entsize = 1;
1500           newdata->d_type = ELF_T_BYTE;
1501         }
1502       else if(nonLoadableSecs[i]->getRegionType() == Region::RT_DATA)   //Data Section
1503         {
1504           newshdr->sh_type = SHT_PROGBITS;
1505           newshdr->sh_flags = SHF_WRITE;
1506           newshdr->sh_entsize = 1;
1507           newdata->d_type = ELF_T_BYTE;
1508         }
1509       else if(nonLoadableSecs[i]->getRegionType() == Region::RT_REL)    //Relocations section
1510         {
1511           newshdr->sh_type = SHT_REL;
1512           newshdr->sh_flags = SHF_WRITE;
1513           newshdr->sh_entsize = sizeof(Elf64_Rel);
1514           newdata->d_type = ELF_T_BYTE;
1515         }
1516       else if(nonLoadableSecs[i]->getRegionType() == Region::RT_RELA)   //Relocations section
1517         {
1518           newshdr->sh_type = SHT_RELA;
1519           newshdr->sh_flags = SHF_WRITE;
1520           newshdr->sh_entsize = sizeof(Elf64_Rela);
1521           newdata->d_type = ELF_T_BYTE;
1522         }
1523       else if(nonLoadableSecs[i]->getRegionType() == Region::RT_SYMTAB)
1524         {
1525           newshdr->sh_type = SHT_SYMTAB;
1526           newshdr->sh_entsize = sizeof(Elf64_Sym);
1527           newdata->d_type = ELF_T_SYM;
1528           newshdr->sh_link = secNames.size();   //.symtab section should have sh_link = index of .strtab 
1529           newshdr->sh_flags=  0;
1530         }
1531       else if(nonLoadableSecs[i]->getRegionType() == Region::RT_STRTAB) //String table Section
1532         {
1533           newshdr->sh_type = SHT_STRTAB;
1534           newshdr->sh_entsize = 1;
1535           newdata->d_type = ELF_T_BYTE;
1536           newshdr->sh_link = SHN_UNDEF; 
1537           newshdr->sh_flags=  0;
1538         }
1539       /*
1540         else if(nonLoadableSecs[i]->getFlags() & Section::dynsymtabSection)
1541         {
1542         newshdr->sh_type = SHT_DYNSYM;
1543         newshdr->sh_entsize = sizeof(Elf64_Sym);
1544         newdata->d_type = ELF_T_SYM;
1545         //newshdr->sh_link = newSecSize+i+1;   //.symtab section should have sh_link = index of .strtab
1546         newshdr->sh_flags=  SHF_ALLOC | SHF_WRITE;
1547         }*/
1548       newshdr->sh_offset = prevshdr->sh_offset+prevshdr->sh_size;
1549       if( prevshdr->sh_type == SHT_NOBITS ) {
1550           newshdr->sh_offset = prevshdr->sh_offset;
1551       }else{
1552           newshdr->sh_offset = prevshdr->sh_offset+prevshdr->sh_size;
1553       }
1554       if (newshdr->sh_offset < currEndOffset) {
1555          newshdr->sh_offset = currEndOffset;
1556       }
1557       newshdr->sh_addr = 0;
1558       newshdr->sh_info = 0;
1559       newshdr->sh_addralign = 4;
1560
1561       //Set up the data
1562       newdata->d_buf = nonLoadableSecs[i]->getPtrToRawData();
1563       newdata->d_size = nonLoadableSecs[i]->getDiskSize();
1564       newshdr->sh_size = newdata->d_size;
1565       //elf_update(newElf, ELF_C_NULL);
1566
1567       newdata->d_align = 4;
1568       newdata->d_off = 0;
1569       newdata->d_version = 1;
1570       currEndOffset = newshdr->sh_offset + newshdr->sh_size;
1571       //currEndAddress = newshdr->sh_addr + newshdr->sh_size;
1572       /* DEBUG */
1573 #ifdef BINEDIT_DEBUG
1574       fprintf(stderr, "Added New Section(%s) : secAddr 0x%lx, secOff 0x%lx, secsize 0x%lx, end 0x%lx\n",
1575               nonLoadableSecs[i]->getRegionName().c_str(), newshdr->sh_addr, newshdr->sh_offset, newshdr->sh_size, newshdr->sh_offset + newshdr->sh_size );
1576 #endif
1577
1578         if (newshdr->sh_entsize && (newshdr->sh_size % newshdr->sh_entsize != 0))
1579                 fprintf(stderr, "%s[%d]:  ERROR:  setting size to non multiple of entry size in section %s: %lu/%lu\n", FILE__, __LINE__, nonLoadableSecs[i]->getRegionName().c_str(), newshdr->sh_size, newshdr->sh_entsize);
1580
1581       prevshdr = newshdr;
1582     }   
1583   shdr = prevshdr;
1584   return true;
1585 }       
1586
1587
1588 /* Regenerates the .symtab, .strtab sections from the symbols
1589  * Add new .dynsym, .dynstr sections for the newly added dynamic symbols
1590  * Method - For every symbol call createElfSymbol to get a Elf64_Sym corresposnding 
1591  *          to a Symbol object. Accumulate all and their names to form the sections
1592  *          and add them to the list of new sections
1593  */
1594 bool emitElf64::createSymbolTables(Symtab *obj, vector<Symbol *>&allSymbols)
1595 {
1596   unsigned i;
1597
1598   //Symbol table(.symtab) symbols
1599   std::vector<Elf64_Sym *> symbols;
1600
1601   //Symbol table(.dynsymtab) symbols
1602   std::vector<Elf64_Sym *> dynsymbols;
1603
1604   unsigned symbolNamesLength = 1, dynsymbolNamesLength = 1;
1605   dyn_hash_map<string, unsigned long> dynSymNameMapping;
1606   std::vector<std::string> symbolStrs, dynsymbolStrs;
1607   std::vector<Symbol *> dynsymVector;
1608   std::vector<Symbol *> allDynSymbols;
1609   std::vector<Symbol *> allSymSymbols;
1610
1611   dyn_hash_map<int, Region*> secTagRegionMapping = obj->getObject()->getTagRegionMapping();
1612   dyn_hash_map<int, Region*>::const_iterator foundRegion;
1613   
1614   Region *sec;
1615   foundRegion = secTagRegionMapping.find(DT_STRTAB);
1616   if ((foundRegion != secTagRegionMapping.end()) && (foundRegion->second != NULL)) {
1617     // .dynstr
1618     sec = foundRegion->second;
1619     olddynStrData = (char *)(sec->getPtrToRawData());
1620     olddynStrSize = sec->getRegionSize();
1621     dynsymbolNamesLength = olddynStrSize+1;
1622   }
1623
1624   //Initialize the list of new prereq libraries
1625   set<string> &plibs = obj->getObject()->prereq_libs;
1626   for (set<string>::iterator i = plibs.begin(); i != plibs.end(); i++) {
1627      DT_NEEDEDEntries.push_back(*i);
1628   }
1629   new_dynamic_entries = obj->getObject()->new_dynamic_entries;
1630   Object *object = obj->getObject();
1631
1632
1633   // recreate a "dummy symbol"
1634   Elf64_Sym *sym = new Elf64_Sym();
1635   symbolStrs.push_back("");
1636   // We should increment this here, but for reasons I don't understand we create it with a size of
1637   // 1. 
1638   //symbolNamesLength++;
1639   sym->st_name = 0;
1640   sym->st_value = 0;
1641   sym->st_size = 0;
1642   sym->st_other = 0;
1643   sym->st_info = ELF64_ST_INFO(STB_LOCAL, STT_NOTYPE);
1644   sym->st_shndx = SHN_UNDEF;
1645
1646   symbols.push_back(sym);
1647   if (!obj->isStaticBinary()) {
1648         dynsymbols.push_back(sym);
1649         dynsymVector.push_back(Symbol::magicEmitElfSymbol());
1650         versionSymTable.push_back(0);
1651   }
1652
1653   for(i=0; i<allSymbols.size();i++) {
1654     if(allSymbols[i]->isInSymtab()) {
1655       allSymSymbols.push_back(allSymbols[i]);
1656     }
1657     if (!obj->isStaticBinary()) {
1658         if(allSymbols[i]->isInDynSymtab()) {
1659            allDynSymbols.push_back(allSymbols[i]);
1660         }
1661     }
1662   }
1663  
1664   int max_index = -1;
1665   for(i = 0; i < allDynSymbols.size();i++) {
1666     if (max_index < allDynSymbols[i]->getIndex()) 
1667       max_index = allDynSymbols[i]->getIndex();
1668   }
1669   for(i=0; i<allDynSymbols.size(); i++) {
1670      
1671     if (allDynSymbols[i]->getIndex() == -1) {
1672       max_index++;
1673       allDynSymbols[i]->setIndex(max_index);
1674     }
1675
1676     if (allDynSymbols[i]->getStrIndex() == -1) {
1677       // New Symbol - append to the list of strings
1678       dynsymbolStrs.push_back( allDynSymbols[i]->getMangledName().c_str());
1679       allDynSymbols[i]->setStrIndex(dynsymbolNamesLength);
1680       dynsymbolNamesLength += allDynSymbols[i]->getMangledName().length() + 1;
1681     } 
1682
1683   }     
1684   // reorder allSymbols based on index
1685   std::sort(allDynSymbols.begin(), allDynSymbols.end(), sortByIndex());
1686    
1687   max_index = -1;
1688   for(i = 0; i < allSymSymbols.size();i++) {
1689     if (max_index < allSymSymbols[i]->getIndex()) 
1690       max_index = allSymSymbols[i]->getIndex();
1691   }
1692
1693   for(i=0; i<allSymSymbols.size(); i++) {
1694     if (allSymSymbols[i]->getIndex() == -1) {
1695       max_index++;
1696       allSymSymbols[i]->setIndex(max_index);
1697     }
1698   }     
1699
1700   std::sort(allSymSymbols.begin(), allSymSymbols.end(), sortByIndex());
1701
1702   /* We regenerate symtab and symstr section. We do not 
1703      maintain the order of the strings and symbols as it was in
1704      the original binary. Hence, the strings in symstr have new order and 
1705      new index.
1706      On the other hand, we do not regenerate dynsym and dynstr section. We copy over
1707      old symbols and string in the original order as it was in the 
1708      original binary. We preserve sh_index of Elf symbols (from Symbol's strIndex). We append 
1709      new symbols and string that we create for the new binary (targ*, versions etc).
1710   */  
1711
1712   for(i=0; i<allSymSymbols.size();i++) {
1713     //allSymSymbols[i]->setStrIndex(symbolNamesLength);
1714     createElfSymbol(allSymSymbols[i], symbolNamesLength, symbols);
1715     symbolStrs.push_back(allSymSymbols[i]->getName());
1716     symbolNamesLength += allSymSymbols[i]->getName().length()+1;
1717   }
1718   for(i=0; i<allDynSymbols.size();i++) {
1719      createElfSymbol(allDynSymbols[i], allDynSymbols[i]->getStrIndex(), dynsymbols, true);
1720     dynSymNameMapping[allDynSymbols[i]->getName().c_str()] = allDynSymbols[i]->getIndex();
1721     dynsymVector.push_back(allDynSymbols[i]);
1722   }
1723
1724   //reconstruct .symtab section
1725   Elf64_Sym *syms = (Elf64_Sym *)malloc(symbols.size()* sizeof(Elf64_Sym));
1726   for(i=0;i<symbols.size();i++)
1727     syms[i] = *(symbols[i]);
1728     
1729   char *str = (char *)malloc(symbolNamesLength);
1730   unsigned cur=0;
1731   for(i=0;i<symbolStrs.size();i++)
1732     {
1733       strcpy(&str[cur],symbolStrs[i].c_str());
1734       cur+=symbolStrs[i].length()+1;
1735     }
1736     
1737   if(!isStripped)
1738     {
1739       Region *sec;
1740       if (obj->findRegion(sec,".symtab"))
1741         sec->setPtrToRawData(syms, symbols.size()*sizeof(Elf64_Sym));
1742       else
1743         obj->addRegion(0, syms, symbols.size()*sizeof(Elf64_Sym), ".symtab", Region::RT_SYMTAB);
1744     }
1745   else
1746     obj->addRegion(0, syms, symbols.size()*sizeof(Elf64_Sym), ".symtab", Region::RT_SYMTAB);
1747
1748   //reconstruct .strtab section
1749   if(!isStripped)
1750     {
1751       Region *sec;
1752       if (obj->findRegion(sec,".strtab"))
1753               sec->setPtrToRawData(str, symbolNamesLength);
1754       else
1755               obj->addRegion(0, str, symbolNamesLength , ".strtab", Region::RT_STRTAB);
1756     }
1757   else
1758     obj->addRegion(0, str, symbolNamesLength , ".strtab", Region::RT_STRTAB);
1759     
1760   if(!obj->getAllNewRegions(newSecs))
1761     log_elferror(err_func_, "No new sections to add");
1762
1763   if(dynsymbols.size() == 1)
1764     return true;
1765
1766   if (!obj->isStaticBinary()) {
1767     //reconstruct .dynsym section
1768     Elf64_Sym *dynsyms = (Elf64_Sym *)malloc(dynsymbols.size()* sizeof(Elf64_Sym));
1769     for(i=0;i<dynsymbols.size();i++)
1770       dynsyms[i] = *(dynsymbols[i]);
1771
1772     Elf64_Half *symVers;
1773     char *verneedSecData, *verdefSecData;
1774     unsigned verneedSecSize = 0, verdefSecSize = 0;
1775                
1776     createSymbolVersions(obj, symVers, verneedSecData, verneedSecSize, verdefSecData, verdefSecSize, dynsymbolNamesLength, dynsymbolStrs);
1777     // build new .hash section
1778     Elf64_Word *hashsecData;
1779     unsigned hashsecSize = 0;
1780     createHashSection(obj, hashsecData, hashsecSize, dynsymVector);
1781     if(hashsecSize) {
1782       string name; 
1783       if (secTagRegionMapping.find(DT_HASH) != secTagRegionMapping.end()) {
1784         name = secTagRegionMapping[DT_HASH]->getRegionName();
1785         obj->addRegion(0, hashsecData, hashsecSize*sizeof(Elf64_Word), name, Region::RT_HASH, true);
1786       } else if (secTagRegionMapping.find(0x6ffffef5) != secTagRegionMapping.end()) {
1787         name = secTagRegionMapping[0x6ffffef5]->getRegionName();
1788         obj->addRegion(0, hashsecData, hashsecSize*sizeof(Elf64_Word), name, Region::RT_HASH, true);
1789       } else {
1790         name = ".hash";
1791         obj->addRegion(0, hashsecData, hashsecSize*sizeof(Elf64_Word), name, Region::RT_HASH, true);
1792       } 
1793     }
1794
1795     Elf64_Dyn *dynsecData;
1796     unsigned dynsecSize = 0;
1797     if(obj->findRegion(sec, ".dynamic")) {
1798         // Need to ensure that DT_REL and related fields added to .dynamic
1799         // The values of these fields will be set
1800         if( !object->hasReldyn() && !object->hasReladyn() ) {
1801             if( object->getRelType() == Region::RT_REL ) {
1802                 new_dynamic_entries.push_back(make_pair(DT_REL,0));
1803                 new_dynamic_entries.push_back(make_pair(DT_RELSZ,0));
1804             }else if( object->getRelType() == Region::RT_RELA ) {
1805                 new_dynamic_entries.push_back(make_pair(DT_RELA,0));
1806                 new_dynamic_entries.push_back(make_pair(DT_RELASZ,0));
1807             }else{
1808                 assert(!"Relocation type not set to known RT_REL or RT_RELA.");
1809             }
1810         }
1811
1812         createDynamicSection(sec->getPtrToRawData(), sec->getDiskSize(), dynsecData, dynsecSize, dynsymbolNamesLength, dynsymbolStrs);
1813     }  
1814    
1815     if(!dynsymbolNamesLength)
1816       return true; 
1817
1818     char *dynstr = (char *)malloc(dynsymbolNamesLength);
1819     memcpy((void *)dynstr, (void *)olddynStrData, olddynStrSize);
1820     cur = olddynStrSize+1;
1821     for(i=0;i<dynsymbolStrs.size();i++)
1822       {
1823         strcpy(&dynstr[cur],dynsymbolStrs[i].c_str());
1824         cur+=dynsymbolStrs[i].length()+1;
1825         if ( dynSymNameMapping.find(dynsymbolStrs[i]) == dynSymNameMapping.end()) {
1826           dynSymNameMapping[dynsymbolStrs[i]] = allDynSymbols.size()+i;
1827         }
1828       }
1829
1830     string name; 
1831     if (secTagRegionMapping.find(DT_SYMTAB) != secTagRegionMapping.end()) {
1832       name = secTagRegionMapping[DT_SYMTAB]->getRegionName();
1833     } else {
1834       name = ".dynsym";
1835     }
1836     obj->addRegion(0, dynsyms, dynsymbols.size()*sizeof(Elf64_Sym), name, Region::RT_SYMTAB, true);
1837
1838     if (secTagRegionMapping.find(DT_STRTAB) != secTagRegionMapping.end()) {
1839       name = secTagRegionMapping[DT_STRTAB]->getRegionName();
1840     } else {
1841       name = ".dynstr";
1842     }
1843     obj->addRegion(0, dynstr, dynsymbolNamesLength , name, Region::RT_STRTAB, true);
1844
1845     //add .gnu.version, .gnu.version_r, and .gnu.version_d sections
1846     if (secTagRegionMapping.find(DT_VERSYM) != secTagRegionMapping.end()) {
1847       name = secTagRegionMapping[DT_VERSYM]->getRegionName();
1848     } else {
1849       name = ".gnu.version";
1850     }
1851     obj->addRegion(0, symVers, versionSymTable.size() * sizeof(Elf64_Half), name, Region::RT_SYMVERSIONS, true);
1852
1853     if(verneedSecSize) {
1854       if (secTagRegionMapping.find(DT_VERNEED) != secTagRegionMapping.end()) {
1855         name = secTagRegionMapping[DT_VERNEED]->getRegionName();
1856       } else {
1857         name = ".gnu.version_r";
1858       }
1859       obj->addRegion(0, verneedSecData, verneedSecSize, name, Region::RT_SYMVERNEEDED, true);
1860     }
1861
1862     if(verdefSecSize) {
1863       obj->addRegion(0, verdefSecData, verdefSecSize, ".gnu.version_d", Region::RT_SYMVERDEF, true);
1864     }
1865
1866     //Always create a dyn section, it may get our new relocations.
1867     //If both exist, then just try to maintain order.
1868     bool has_plt = object->hasRelaplt() || object->hasRelplt();
1869     bool has_dyn = object->hasReladyn() || object->hasReldyn();
1870     if (!has_plt) {
1871        createRelocationSections(obj, object->getDynRelocs(), true, dynSymNameMapping);
1872     }
1873     else if (!has_dyn) {
1874        createRelocationSections(obj, object->getPLTRelocs(), false, dynSymNameMapping);
1875        createRelocationSections(obj, object->getDynRelocs(), true, dynSymNameMapping);
1876     }
1877     else if (object->getRelPLTAddr() < object->getRelDynAddr()) {
1878        createRelocationSections(obj, object->getPLTRelocs(), false, dynSymNameMapping);
1879        createRelocationSections(obj, object->getDynRelocs(), true, dynSymNameMapping);
1880     }
1881     else {
1882        createRelocationSections(obj, object->getDynRelocs(), true, dynSymNameMapping);
1883        createRelocationSections(obj, object->getPLTRelocs(), false, dynSymNameMapping);
1884     }
1885
1886     //add .dynamic section
1887     if(dynsecSize)
1888       obj->addRegion(0, dynsecData, dynsecSize*sizeof(Elf64_Dyn), ".dynamic", Region::RT_DYNAMIC, true);
1889   }else{
1890       // Static binary case
1891       vector<Region *> newRegs;
1892       obj->getAllNewRegions(newRegs);
1893       if( newRegs.size() ) {
1894           emitElfStatic linker(obj->getAddressWidth(), isStripped);
1895
1896           emitElfStatic::StaticLinkError err;
1897           std::string errMsg;
1898           linkedStaticData = linker.linkStatic(obj, err, errMsg);
1899           if ( !linkedStaticData ) {
1900                std::string linkStaticError = 
1901                    std::string("Failed to link static library code into the binary: ") +
1902                    emitElfStatic::printStaticLinkError(err) + std::string(" = ")
1903                    + errMsg;
1904                setSymtabError(Emit_Error);
1905                symtab_log_perror(linkStaticError.c_str());
1906                return false;
1907           }
1908
1909           hasRewrittenTLS = linker.hasRewrittenTLS();
1910
1911           // Find the end of the new Regions
1912           obj->getAllNewRegions(newRegs);
1913
1914           Offset lastRegionAddr = 0, lastRegionSize = 0;
1915           vector<Region *>::iterator newRegIter;
1916           for(newRegIter = newRegs.begin(); newRegIter != newRegs.end();
1917               ++newRegIter)
1918           {
1919               if( (*newRegIter)->getRegionAddr() > lastRegionAddr ) {
1920                   lastRegionAddr = (*newRegIter)->getRegionAddr();
1921                   lastRegionSize = (*newRegIter)->getRegionSize();
1922               }
1923           }
1924
1925           if( !emitElfUtils::updateHeapVariables(obj, lastRegionAddr + lastRegionSize) ) {
1926               return false;
1927           }
1928       }
1929   }
1930
1931   if(!obj->getAllNewRegions(newSecs))
1932     log_elferror(err_func_, "No new sections to add");
1933
1934   return true;
1935 }
1936
1937 void emitElf64::createRelocationSections(Symtab *obj, std::vector<relocationEntry> &relocation_table, bool isDynRelocs, dyn_hash_map<std::string, unsigned long> &dynSymNameMapping) {
1938   vector<relocationEntry> newRels;
1939   if(isDynRelocs && newSecs.size()) {
1940     std::vector<Region *>::iterator i;
1941     for (i = newSecs.begin(); i != newSecs.end(); i++) {
1942       std::copy((*i)->getRelocations().begin(),
1943                 (*i)->getRelocations().end(),
1944                 std::back_inserter(newRels));
1945     }
1946   }
1947
1948    unsigned i,j,k,l,m;
1949     
1950    Elf64_Rel *rels = (Elf64_Rel *)malloc(sizeof(Elf64_Rel) * (relocation_table.size()+newRels.size()));
1951    Elf64_Rela *relas = (Elf64_Rela *)malloc(sizeof(Elf64_Rela) * (relocation_table.size()+newRels.size()));
1952    j=0; k=0; l=0; m=0;
1953    //reconstruct .rel
1954    for(i=0;i<relocation_table.size();i++) 
1955    {
1956
1957      if( library_adjust ) {
1958          // If we are shifting the library down in memory, we need to update
1959          // any relative offsets in the library. These relative offsets are 
1960          // found via relocations
1961
1962          // XXX ...ignore the return value
1963          emitElfUtils::updateRelocation(obj, relocation_table[i], library_adjust);
1964      }
1965
1966       if (relocation_table[i].regionType() == Region::RT_REL) {
1967          rels[j].r_offset = relocation_table[i].rel_addr() + library_adjust;
1968          if(relocation_table[i].name().length() &&
1969             dynSymNameMapping.find(relocation_table[i].name()) != dynSymNameMapping.end()) {
1970             rels[j].r_info = ELF64_R_INFO(dynSymNameMapping[relocation_table[i].name()], relocation_table[i].getRelType());
1971          } else {
1972             rels[j].r_info = ELF64_R_INFO((unsigned long)STN_UNDEF, relocation_table[i].getRelType());
1973          }
1974          j++;
1975       } else {
1976          relas[k].r_offset = relocation_table[i].rel_addr() + library_adjust;
1977          relas[k].r_addend = relocation_table[i].addend();
1978          //if (relas[k].r_addend)
1979          //   relas[k].r_addend += library_adjust;
1980          if(relocation_table[i].name().length() && 
1981             dynSymNameMapping.find(relocation_table[i].name()) != dynSymNameMapping.end()) {
1982             relas[k].r_info = ELF64_R_INFO(dynSymNameMapping[relocation_table[i].name()], relocation_table[i].getRelType());
1983          } else {
1984             relas[k].r_info = ELF64_R_INFO((unsigned long)STN_UNDEF, relocation_table[i].getRelType());
1985          }
1986          k++;
1987       }
1988    }
1989    for(i=0;i<newRels.size();i++) 
1990    {
1991       if (newRels[i].regionType() == Region::RT_REL) {
1992          rels[j].r_offset = newRels[i].rel_addr() + library_adjust;
1993          if(dynSymNameMapping.find(newRels[i].name()) != dynSymNameMapping.end()) {
1994 #if defined(arch_x86)
1995             rels[j].r_info = ELF64_R_INFO(dynSymNameMapping[newRels[i].name()], R_386_GLOB_DAT);
1996 #elif defined(arch_x86_64)
1997             rels[j].r_info = ELF64_R_INFO(dynSymNameMapping[newRels[i].name()], R_X86_64_GLOB_DAT);
1998 #elif defined(arch_power)
1999             rels[j].r_info = ELF64_R_INFO(dynSymNameMapping[newRels[i].name()], R_PPC_GLOB_DAT);
2000 #endif
2001          } else {
2002 #if defined(arch_x86)
2003             rels[j].r_info = ELF64_R_INFO(STN_UNDEF, R_386_GLOB_DAT);
2004 #elif defined(arch_x86_64)
2005             rels[j].r_info = ELF64_R_INFO((unsigned long)STN_UNDEF, R_X86_64_GLOB_DAT);
2006 #elif defined(arch_power)
2007             rels[j].r_info = ELF64_R_INFO(STN_UNDEF, R_PPC_GLOB_DAT);
2008 #endif
2009          }
2010          j++;
2011          l++;
2012       } else {
2013          relas[k].r_offset = newRels[i].rel_addr() + library_adjust;
2014          relas[k].r_addend = newRels[i].addend();
2015          //if( relas[k].r_addend ) relas[k].r_addend += library_adjust;
2016          if(dynSymNameMapping.find(newRels[i].name()) != dynSymNameMapping.end()) {
2017 #if defined(arch_x86)
2018             relas[k].r_info = ELF64_R_INFO(dynSymNameMapping[newRels[i].name()], R_386_GLOB_DAT);
2019 #elif defined(arch_x86_64)
2020             relas[k].r_info = ELF64_R_INFO(dynSymNameMapping[newRels[i].name()], R_X86_64_GLOB_DAT);
2021 #elif defined(arch_power)
2022             relas[k].r_info = ELF64_R_INFO(dynSymNameMapping[newRels[i].name()], R_PPC_GLOB_DAT);
2023 #endif
2024          } else {
2025 #if defined(arch_x86)
2026             relas[k].r_info = ELF64_R_INFO(STN_UNDEF, R_386_GLOB_DAT);
2027 #elif defined(arch_x86_64)
2028             relas[k].r_info = ELF64_R_INFO((unsigned long)STN_UNDEF, R_X86_64_GLOB_DAT);
2029 #elif defined(arch_power)
2030             relas[k].r_info = ELF64_R_INFO(STN_UNDEF, R_PPC_GLOB_DAT);
2031 #endif
2032          }
2033          k++;
2034          m++;
2035       }
2036    }
2037
2038    dyn_hash_map<int, Region*> secTagRegionMapping = obj->getObject()->getTagRegionMapping();
2039    int reloc_size, old_reloc_size, dynamic_reloc_size;
2040    const char *new_name;
2041    Region::RegionType rtype;
2042    int dtype;
2043    int dsize_type;
2044    void *buffer = NULL;
2045
2046    reloc_size = j*sizeof(Elf64_Rel)+k*sizeof(Elf64_Rela);
2047    if (!reloc_size)
2048       return;
2049
2050    if (   isDynRelocs 
2051        && object->getRelType() == Region::RT_REL ) 
2052    {
2053       new_name = ".rel.dyn";
2054       dtype = DT_REL;
2055       rtype = Region::RT_REL;
2056       dsize_type = DT_RELSZ;
2057       buffer = rels;
2058    }
2059    if (   isDynRelocs
2060        && object->getRelType() == Region::RT_RELA ) 
2061    {
2062       new_name = ".rela.dyn";
2063       dtype = DT_RELA;
2064       rtype = Region::RT_RELA;
2065       dsize_type = DT_RELASZ;
2066       buffer = relas;
2067    }
2068    if (   !isDynRelocs 
2069        && object->getRelType() == Region::RT_REL ) 
2070    {
2071       new_name = ".rel.plt";
2072       dtype = DT_JMPREL;
2073       rtype = Region::RT_PLTREL;
2074       dsize_type = DT_PLTRELSZ;
2075       buffer = rels;
2076    }
2077    if (   !isDynRelocs 
2078        && object->getRelType() == Region::RT_RELA ) 
2079    {
2080       new_name = ".rela.plt";
2081       dtype = DT_JMPREL;
2082       rtype = Region::RT_PLTRELA;
2083       dsize_type = DT_PLTRELSZ;
2084       buffer = relas;
2085    }
2086    old_reloc_size =  dynamicSecData[dsize_type][0]->d_un.d_val;
2087    dynamic_reloc_size = old_reloc_size+  l*sizeof(Elf64_Rel)+ m*sizeof(Elf64_Rela);
2088    string name;
2089    if (secTagRegionMapping.find(dtype) != secTagRegionMapping.end())
2090       name = secTagRegionMapping[dtype]->getRegionName();
2091    else
2092       name = std::string(new_name);
2093    obj->addRegion(0, buffer, reloc_size, name, rtype, true);
2094    updateDynamic(dsize_type, dynamic_reloc_size); 
2095
2096 }
2097
2098 void emitElf64::createSymbolVersions(Symtab *obj, Elf64_Half *&symVers, char*&verneedSecData, unsigned &verneedSecSize, char
2099 *&verdefSecData, unsigned &verdefSecSize, unsigned &dynSymbolNamesLength, vector<string> &dynStrs){
2100
2101    //Add all names to the new .dynstr section
2102    map<string, unsigned>::iterator iter = versionNames.begin();
2103    for(;iter!=versionNames.end();iter++){
2104       iter->second = dynSymbolNamesLength;
2105       dynStrs.push_back(iter->first);
2106       dynSymbolNamesLength+= iter->first.size()+1;
2107    }
2108
2109    //reconstruct .gnu_version section
2110    symVers = (Elf64_Half *)malloc(versionSymTable.size() * sizeof(Elf64_Half));
2111    for(unsigned i=0; i<versionSymTable.size(); i++)
2112       symVers[i] = versionSymTable[i];
2113
2114    //reconstruct .gnu.version_r section
2115    verneedSecSize = 0;
2116    map<string, map<string, unsigned> >::iterator it = verneedEntries.begin();
2117    for(; it != verneedEntries.end(); it++)
2118       verneedSecSize += sizeof(Elf64_Verneed) + sizeof(Elf64_Vernaux) * it->second.size();
2119
2120    verneedSecData = (char *)malloc(verneedSecSize);
2121    unsigned curpos = 0;
2122    verneednum = 0;
2123    std::vector<std::string>::iterator dit;
2124    for(dit = unversionedNeededEntries.begin(); dit != unversionedNeededEntries.end(); dit++) {
2125       // account for any substitutions due to rewriting a shared lib
2126       std::string name = obj->getDynLibSubstitution(*dit);
2127       // no need for self-references
2128       if (!(obj->name() == name)) {
2129          versionNames[name] = dynSymbolNamesLength;
2130          dynStrs.push_back(name);
2131          dynSymbolNamesLength+= (name).size()+1;
2132          if(find(DT_NEEDEDEntries.begin(), DT_NEEDEDEntries.end(), name) == DT_NEEDEDEntries.end())
2133             DT_NEEDEDEntries.push_back(name);
2134       }
2135    }
2136    for(it = verneedEntries.begin(); it != verneedEntries.end(); it++){
2137       Elf64_Verneed *verneed = (Elf64_Verneed *)(void*)(verneedSecData+curpos);
2138       verneed->vn_version = 1;
2139       verneed->vn_cnt = it->second.size();
2140       verneed->vn_file = dynSymbolNamesLength;
2141       versionNames[it->first] = dynSymbolNamesLength;
2142       dynStrs.push_back(it->first);
2143       dynSymbolNamesLength+= it->first.size()+1;
2144       if(find(DT_NEEDEDEntries.begin(), DT_NEEDEDEntries.end(), it->first) == DT_NEEDEDEntries.end())
2145          DT_NEEDEDEntries.push_back(it->first);
2146       verneed->vn_aux = sizeof(Elf64_Verneed);
2147       verneed->vn_next = sizeof(Elf64_Verneed) + it->second.size()*sizeof(Elf64_Vernaux);
2148       if(curpos + verneed->vn_next == verneedSecSize)
2149          verneed->vn_next = 0;
2150       verneednum++;
2151       int i = 0;
2152       for(iter = it->second.begin(); iter!= it->second.end(); iter++){
2153          Elf64_Vernaux *vernaux = (Elf64_Vernaux *)(void*)(verneedSecData + curpos + verneed->vn_aux + i*sizeof(Elf64_Vernaux));
2154          vernaux->vna_hash = elfHash(iter->first.c_str());
2155          vernaux->vna_flags = 0;
2156          vernaux->vna_other = iter->second;
2157          vernaux->vna_name = versionNames[iter->first];
2158          if(i == verneed->vn_cnt-1)
2159             vernaux->vna_next = 0;
2160          else
2161             vernaux->vna_next = sizeof(Elf64_Vernaux);
2162          i++;
2163       }
2164       curpos += verneed->vn_next;
2165    }
2166
2167    //reconstruct .gnu.version_d section
2168    verdefSecSize = 0;
2169    for(iter = verdefEntries.begin(); iter != verdefEntries.end(); iter++)
2170       verdefSecSize += sizeof(Elf64_Verdef) + sizeof(Elf64_Verdaux) * verdauxEntries[iter->second].size();
2171
2172    verdefSecData = (char *)malloc(verdefSecSize);
2173    curpos = 0;
2174    verdefnum = 0;
2175    for(iter = verdefEntries.begin(); iter != verdefEntries.end(); iter++){
2176       Elf64_Verdef *verdef = (Elf64_Verdef *)(void*)(verdefSecData+curpos);
2177       verdef->vd_version = 1;
2178       verdef->vd_flags = 0;
2179       verdef->vd_ndx = iter->second;
2180       verdef->vd_cnt = verdauxEntries[iter->second].size();
2181       verdef->vd_hash = elfHash(iter->first.c_str());
2182       verdef->vd_aux = sizeof(Elf64_Verdef);
2183       verdef->vd_next = sizeof(Elf64_Verdef) + verdauxEntries[iter->second].size()*sizeof(Elf64_Verdaux);
2184       if(curpos + verdef->vd_next == verdefSecSize)
2185          verdef->vd_next = 0;
2186       verdefnum++;
2187       for(unsigned i = 0; i< verdauxEntries[iter->second].size(); i++){
2188          Elf64_Verdaux *verdaux = (Elf64_Verdaux *)(void*)(verdefSecData + curpos + verdef->vd_aux + i*sizeof(Elf64_Verdaux));
2189          verdaux->vda_name = versionNames[verdauxEntries[iter->second][0]];
2190          if((signed) i == verdef->vd_cnt-1)
2191             verdaux->vda_next = 0;
2192          else
2193             verdaux->vda_next = sizeof(Elf64_Verdaux);
2194       }
2195       curpos += verdef->vd_next;
2196    }
2197    return;
2198 }
2199
2200 void emitElf64::createHashSection(Symtab *obj, Elf64_Word *&hashsecData, unsigned &hashsecSize, vector<Symbol *>&dynSymbols)
2201 {
2202
2203   /* Save the original hash table entries */
2204   std::vector<unsigned> originalHashEntries;
2205   unsigned dynsymSize = obj->getObject()->getDynsymSize();
2206   
2207   Elf_Scn *scn = NULL;
2208   Elf64_Shdr *shdr = NULL;
2209   for (unsigned scncount = 0; (scn = elf_nextscn(oldElf, scn)); scncount++) {
2210     shdr = elf64_getshdr(scn);
2211     if(obj->getObject()->getElfHashAddr() != 0 &&
2212        obj->getObject()->getElfHashAddr() == shdr->sh_addr){
2213       Elf_Data *hashData = elf_getdata(scn,NULL);
2214       Elf64_Word *oldHashSec = (Elf64_Word *) hashData->d_buf;
2215       unsigned original_nbuckets, original_nchains;
2216       original_nbuckets =  oldHashSec[0];
2217       original_nchains = oldHashSec[1];
2218       for (unsigned i = 0; i < original_nbuckets+original_nchains; i++) {
2219         if ( oldHashSec[2+i] != 0) {
2220                 originalHashEntries.push_back( oldHashSec[2+i]);
2221                 //printf(" ELF HASH pushing hash entry %d \n", oldHashSec[2+i] );
2222         }
2223       }
2224     }
2225
2226     if(obj->getObject()->getGnuHashAddr() != 0 &&
2227        obj->getObject()->getGnuHashAddr() == shdr->sh_addr){
2228       Elf_Data *hashData = elf_getdata(scn,NULL);
2229       Elf64_Word *oldHashSec = (Elf64_Word *) hashData->d_buf;
2230       unsigned symndx = oldHashSec[1];
2231       if (dynsymSize != 0)
2232         for (unsigned i = symndx; i < dynsymSize ; i++) {
2233                 originalHashEntries.push_back(i);
2234                 //printf(" GNU HASH pushing hash entry %d \n", i);
2235         }
2236       }
2237   }
2238
2239   vector<Symbol *>::iterator iter;
2240   dyn_hash_map<unsigned, unsigned> lastHash; // bucket number to symbol index
2241   unsigned nbuckets = (unsigned)dynSymbols.size()*2/3;
2242   if (nbuckets % 2 == 0)
2243     nbuckets--;
2244   if (nbuckets < 1)
2245     nbuckets = 1;
2246   unsigned nchains = (unsigned)dynSymbols.size();
2247   hashsecSize = 2 + nbuckets + nchains;
2248   hashsecData = (Elf64_Word *)malloc(hashsecSize*sizeof(Elf64_Word));
2249   unsigned i=0, key;
2250   for (i=0; i<hashsecSize; i++) {
2251     hashsecData[i] = STN_UNDEF;
2252   }
2253   hashsecData[0] = (Elf64_Word)nbuckets;
2254   hashsecData[1] = (Elf64_Word)nchains;
2255   i = 0;
2256   for (iter = dynSymbols.begin(); iter != dynSymbols.end(); iter++, i++) {
2257     if((*iter)->getName().empty()) continue;
2258     unsigned index = (*iter)->getIndex();
2259     if ((find(originalHashEntries.begin(),originalHashEntries.end(),index) == originalHashEntries.end()) && 
2260         (index < obj->getObject()->getDynsymSize())) {
2261         continue;
2262     }
2263     key = elfHash((*iter)->getName().c_str()) % nbuckets;
2264     if (lastHash.find(key) != lastHash.end()) {
2265       hashsecData[2+nbuckets+lastHash[key]] = i;
2266     }
2267     else {
2268       hashsecData[2+key] = i;
2269     }
2270     lastHash[key] = i;
2271     hashsecData[2+nbuckets+i] = STN_UNDEF;
2272   }
2273 }
2274
2275 void emitElf64::createDynamicSection(void *dynData, unsigned size, Elf64_Dyn *&dynsecData, unsigned &dynsecSize, unsigned &dynSymbolNamesLength, std::vector<std::string> &dynStrs) {
2276   dynamicSecData.clear();
2277   Elf64_Dyn *dyns = (Elf64_Dyn *)dynData;
2278   unsigned count = size/sizeof(Elf64_Dyn);
2279   dynsecSize = 2*(count + DT_NEEDEDEntries.size() + new_dynamic_entries.size());
2280   dynsecData = (Elf64_Dyn *)malloc(dynsecSize*sizeof(Elf64_Dyn));
2281   unsigned curpos = 0;
2282   string rpathstr;
2283   for(unsigned i = 0; i< DT_NEEDEDEntries.size(); i++){
2284     dynsecData[curpos].d_tag = DT_NEEDED;
2285     dynStrs.push_back(DT_NEEDEDEntries[i]);
2286     dynsecData[curpos].d_un.d_val = dynSymbolNamesLength;
2287     dynSymbolNamesLength += DT_NEEDEDEntries[i].size()+1;
2288     dynamicSecData[DT_NEEDED].push_back(dynsecData+curpos);
2289     curpos++;
2290   }
2291   for (unsigned i = 0; i<new_dynamic_entries.size(); i++) {
2292      long name = new_dynamic_entries[i].first;
2293      long value = new_dynamic_entries[i].second;
2294      dynsecData[curpos].d_tag = name;
2295      dynsecData[curpos].d_un.d_val = value;
2296      dynamicSecData[name].push_back(dynsecData+curpos);
2297      curpos++;
2298   }
2299
2300   // There may be multiple HASH (ELF, GNU etc) sections in the original binary. We consolidate all of them into one.
2301   bool foundHashSection = false; 
2302
2303   for(unsigned i = 0; i< count;i++){
2304     switch(dyns[i].d_tag){
2305     case DT_NULL:
2306       break;
2307     case 0x6ffffef5: // DT_GNU_HASH (not defined on all platforms)
2308       if (!foundHashSection) {
2309         dynsecData[curpos].d_tag = DT_HASH;
2310         dynsecData[curpos].d_un.d_ptr =dyns[i].d_un.d_ptr ;
2311         dynamicSecData[DT_HASH].push_back(dynsecData+curpos);
2312         curpos++;
2313         foundHashSection = true;
2314       }
2315       break;
2316     case DT_HASH: 
2317       if (!foundHashSection) {
2318         dynsecData[curpos].d_tag = dyns[i].d_tag;
2319         dynsecData[curpos].d_un.d_ptr =dyns[i].d_un.d_ptr ;
2320         dynamicSecData[dyns[i].d_tag].push_back(dynsecData+curpos);
2321         curpos++;
2322         foundHashSection = true;
2323       }
2324       break;
2325     case DT_NEEDED:
2326       rpathstr = &olddynStrData[dyns[i].d_un.d_val];
2327       if(find(DT_NEEDEDEntries.begin(), DT_NEEDEDEntries.end(), rpathstr) != DT_NEEDEDEntries.end())
2328         break;
2329       dynsecData[curpos].d_tag = dyns[i].d_tag;
2330       dynsecData[curpos].d_un.d_val = dynSymbolNamesLength;
2331       dynStrs.push_back(rpathstr);
2332       dynSymbolNamesLength += rpathstr.size() + 1;
2333       dynamicSecData[dyns[i].d_tag].push_back(dynsecData+curpos);
2334       curpos++;
2335       break;
2336     case DT_RPATH:
2337     case DT_RUNPATH:
2338       dynsecData[curpos].d_tag = dyns[i].d_tag;
2339       dynsecData[curpos].d_un.d_val = dynSymbolNamesLength;
2340       rpathstr = &olddynStrData[dyns[i].d_un.d_val];
2341       dynStrs.push_back(rpathstr);
2342       dynSymbolNamesLength += rpathstr.size() + 1;
2343       dynamicSecData[dyns[i].d_tag].push_back(dynsecData+curpos);
2344       curpos++;
2345       break;
2346     case DT_INIT:
2347     case DT_FINI:
2348     case DT_GNU_CONFLICT:
2349     case DT_JMPREL:
2350     case DT_PLTGOT:
2351        /**
2352         * List every dynamic entry that references an address and isn't already
2353         * updated here.  library_adjust will be a page size if
2354         * we're dealing with a library without a fixed load address.  We'll be shifting
2355         * the addresses of that library by a page.
2356         **/
2357        memcpy(dynsecData+curpos, dyns+i, sizeof(Elf64_Dyn));
2358        dynsecData[curpos].d_un.d_ptr += library_adjust;
2359        dynamicSecData[dyns[i].d_tag].push_back(dynsecData+curpos);
2360        curpos++;
2361        break;
2362     default:
2363       memcpy(dynsecData+curpos, dyns+i, sizeof(Elf64_Dyn));
2364       dynamicSecData[dyns[i].d_tag].push_back(dynsecData+curpos);
2365       curpos++;
2366       break;
2367     }
2368   }
2369   dynsecData[curpos].d_tag = DT_NULL;
2370   dynsecData[curpos].d_un.d_val = 0;
2371   curpos++;
2372   dynsecSize = curpos+1;                            //assign size to the correct number of entries
2373 }
2374
2375
2376 void emitElf64::log_elferror(void (*err_func)(const char *), const char* msg) {
2377   const char* err = elf_errmsg(elf_errno());
2378   err = err ? err: "(bad elf error)";
2379   string str = string(err)+string(msg);
2380   err_func(str.c_str());
2381 }