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