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