2 * Copyright (c) 1996-2009 Barton P. Miller
4 * We provide the Paradyn Parallel Performance Tools (below
5 * described as "Paradyn") on an AS IS basis, and do not warrant its
6 * validity or performance. We reserve the right to update, modify,
7 * or discontinue this software at any time. We shall have no
8 * obligation to supply such updates or modifications or any other
9 * form of support to you.
11 * By your use of Paradyn, you understand and agree that we (or any
12 * other person or entity with proprietary rights in Paradyn) are
13 * under no obligation to provide either maintenance services,
14 * update services, notices of latent defects, or correction of
15 * defects for Paradyn.
17 * This library is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU Lesser General Public
19 * License as published by the Free Software Foundation; either
20 * version 2.1 of the License, or (at your option) any later version.
22 * This library is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 * Lesser General Public License for more details.
27 * You should have received a copy of the GNU Lesser General Public
28 * License along with this library; if not, write to the Free Software
29 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
33 #if !defined(cap_libelf_so_0) && defined(os_linux)
34 #define _FILE_OFFSET_BITS 64
39 #include "common/h/parseauxv.h"
41 #include "emitElf-64.h"
42 #include "emitElfStatic.h"
44 extern void symtab_log_perror(const char *msg);
45 using namespace Dyninst;
46 using namespace Dyninst::SymtabAPI;
49 extern const char *pdelf_get_shnames(Elf_X &elf);
50 extern unsigned int elfHash(const char *name);
54 bool operator ()(Symbol * lhs, Symbol* rhs) {
55 return lhs->getIndex() < rhs->getIndex();
59 static bool libelfso0Flag;
60 static bool libelfso1Flag;
61 static int libelfso1version_major;
62 static int libelfso1version_minor;
65 static char *deref_link(const char *path)
67 static char buffer[PATH_MAX], *p;
68 buffer[PATH_MAX-1] = '\0';
69 p = realpath(path, buffer);
73 static char *deref_link(const char *path)
79 static void setVersion(){
80 libelfso0Flag = false;
81 libelfso1Flag = false;
82 libelfso1version_major = 0;
83 libelfso1version_minor = 0;
86 map_entries *maps = getLinuxMaps(getpid(), nEntries);
87 for (unsigned i=0; i< nEntries; i++){
88 if (!strstr(maps[i].path, "libelf"))
90 char *real_file = deref_link(maps[i].path);
91 char *libelf_start = strstr(real_file, "libelf");
92 int num_read, major, minor;
93 num_read = sscanf(libelf_start, "libelf-%d.%d.so", &major, &minor);
96 libelfso1version_major = major;
97 libelfso1version_minor = minor;
100 libelfso0Flag = true;
103 if (libelfso0Flag && libelfso1Flag) {
104 fprintf(stderr, "WARNING: SymtabAPI is linked with libelf.so.0 and "
105 "libelf.so.1! SymtabAPI likely going to be unable to read "
106 "and write elf files!\n");
111 bool emitElf64::hasPHdrSectionBug()
117 return (libelfso1version_major == 0 && libelfso1version_minor <= 137);
120 static int elfSymType(Symbol *sym)
122 switch (sym->getType()) {
123 case Symbol::ST_MODULE: return STT_FILE;
124 case Symbol::ST_SECTION: return STT_SECTION;
125 case Symbol::ST_OBJECT: return STT_OBJECT;
126 case Symbol::ST_FUNCTION: return STT_FUNC;
127 case Symbol::ST_TLS: return STT_TLS;
128 case Symbol::ST_NOTYPE : return STT_NOTYPE;
129 case Symbol::ST_UNKNOWN: return sym->getInternalType();
130 default: return STT_SECTION;
134 static int elfSymBind(Symbol::SymbolLinkage sLinkage)
137 case Symbol::SL_LOCAL: return STB_LOCAL;
138 case Symbol::SL_WEAK: return STB_WEAK;
139 case Symbol::SL_GLOBAL: return STB_GLOBAL;
140 default: return STB_LOPROC;
144 static int elfSymVisibility(Symbol::SymbolVisibility sVisibility)
146 switch (sVisibility) {
147 case Symbol::SV_DEFAULT: return STV_DEFAULT;
148 case Symbol::SV_INTERNAL: return STV_INTERNAL;
149 case Symbol::SV_HIDDEN: return STV_HIDDEN;
150 case Symbol::SV_PROTECTED: return STV_PROTECTED;
151 default: return STV_DEFAULT;
155 emitElf64::emitElf64(Elf_X &oldElfHandle_, bool isStripped_, Object *obj_, void (*err_func)(const char *)) :
156 oldElfHandle(oldElfHandle_),
158 isStripped(isStripped_),
162 firstNewLoadSec = NULL;
171 //Don't expect to use to use this mechanism anymore
172 BSSExpandFlag = false;
173 //If we're dealing with a library that can be loaded anywhere,
174 // then load the program headers into the later part of the binary,
175 // this may trigger a kernel bug that was fixed in Summer 2007,
176 // but is the only reliable way to modify these libraries.
177 //If we're dealing with a library/executable that loads at a specific
178 // address we'll put the phdrs into the page before that address. This
179 // works and will avoid the kernel bug.
180 movePHdrsFirst = object && object->getLoadAddress();
181 createNewPhdr = true;
183 //If we want to try a mode where we add the program headers to a library
184 // that can be loaded anywhere, and put the program headers in the first
185 // page (avoiding the kernel bug), then set library_adjust to getpagesize().
186 // This will shift all addresses in the library down by a page, accounting
187 // for the extra page for program headers. This causes some significant
188 // changes to the binary, and isn't well tested.
191 linkedStaticData = NULL;
192 hasRewrittenTLS = false;
195 oldElf = oldElfHandle.e_elfp();
201 bool emitElf64::createElfSymbol(Symbol *symbol, unsigned strIndex, vector<Elf64_Sym *> &symbols, bool dynSymFlag)
203 Elf64_Sym *sym = new Elf64_Sym();
204 sym->st_name = strIndex;
206 if (symbol->getAddr())
207 sym->st_value = symbol->getAddr() + library_adjust;
208 sym->st_size = symbol->getSize();
209 sym->st_other = ELF64_ST_VISIBILITY(elfSymVisibility(symbol->getVisibility()));
210 sym->st_info = (unsigned char) ELF64_ST_INFO(elfSymBind(symbol->getLinkage()), elfSymType(symbol));
212 if (symbol->getSec())
214 #if defined(os_solaris)
215 sym->st_shndx = (Elf64_Half) symbol->getSec()->getRegionNumber();
217 sym->st_shndx = (Elf64_Section) symbol->getSec()->getRegionNumber();
220 else if (symbol->isAbsolute())
222 sym->st_shndx = SHN_ABS;
229 symbols.push_back(sym);
233 /*printf("dynamic symbol: %s\n", symbol->getName().c_str());*/
235 #if !defined(os_solaris)
241 if (!symbol->getVersionFileName(fileName))
244 vector<string> *vers;
245 if (!symbol->getVersions(vers))
247 if (symbol->getLinkage() == Symbol::SL_GLOBAL)
249 versionSymTable.push_back(1);
253 versionSymTable.push_back(0);
258 if (vers->size() > 0)
261 mpos += sprintf(mpos, "verdef: symbol=%s version=%s ", symbol->getName().c_str(), (*vers)[0].c_str());
262 if (verdefEntries.find((*vers)[0]) != verdefEntries.end())
264 versionSymTable.push_back((unsigned short) verdefEntries[(*vers)[0]]);
268 versionSymTable.push_back((unsigned short) curVersionNum);
269 verdefEntries[(*vers)[0]] = curVersionNum;
273 // add all versions to the verdef entry
274 for (unsigned i=0; i< vers->size(); i++)
276 mpos += sprintf(mpos, " {%s}", (*vers)[i].c_str());
277 if (versionNames.find((*vers)[i]) == versionNames.end())
279 versionNames[(*vers)[i]] = 0;
282 if (find( verdauxEntries[verdefEntries[(*vers)[0]]].begin(),
283 verdauxEntries[verdefEntries[(*vers)[0]]].end(),
284 (*vers)[i]) == verdauxEntries[verdefEntries[(*vers)[0]]].end())
286 verdauxEntries[verdefEntries[(*vers)[0]]].push_back((*vers)[i]);
289 mpos += sprintf(mpos, "\n");
295 mpos += sprintf(mpos, "need: symbol=%s filename=%s\n",
296 symbol->getName().c_str(), fileName.c_str());
298 vector<string> *vers;
300 if (!symbol->getVersions(vers) || (vers && vers->size() != 1))
302 // add an unversioned dependency
305 if (!symbol->getReferringSymbol()->getSymtab()->isExec()) {
306 if (find(unversionedNeededEntries.begin(),
307 unversionedNeededEntries.end(),
308 fileName) == unversionedNeededEntries.end())
310 mpos += sprintf(mpos, " new unversioned: %s\n", fileName.c_str());
311 unversionedNeededEntries.push_back(fileName);
315 if (symbol->getLinkage() == Symbol::SL_GLOBAL) {
316 versionSymTable.push_back(1);
319 versionSymTable.push_back(0);
327 fprintf(stderr, "%s[%d]: weird inconsistency here... getVersions returned NULL\n",
332 // There should only be one version string by this time
333 //If the verison name already exists then add the same version number to the version symbol table
334 //Else give a new number and add it to the mapping.
335 if (versionNames.find((*vers)[0]) == versionNames.end())
337 mpos += sprintf(mpos, " new version name: %s\n", (*vers)[0].c_str());
338 versionNames[(*vers)[0]] = 0;
341 if (verneedEntries.find(fileName) != verneedEntries.end())
343 if (verneedEntries[fileName].find((*vers)[0]) != verneedEntries[fileName].end())
345 mpos += sprintf(mpos, " vernum: %d\n", verneedEntries[fileName][(*vers)[0]]);
346 versionSymTable.push_back((unsigned short) verneedEntries[fileName][(*vers)[0]]);
350 mpos += sprintf(mpos, " new entry #%d: %s [%s]\n",
351 curVersionNum, (*vers)[0].c_str(), fileName.c_str());
352 versionSymTable.push_back((unsigned short) curVersionNum);
353 verneedEntries[fileName][(*vers)[0]] = curVersionNum;
359 mpos += sprintf(mpos, " new entry #%d: %s [%s]\n",
360 curVersionNum, (*vers)[0].c_str(), fileName.c_str());
361 versionSymTable.push_back((unsigned short) curVersionNum);
362 verneedEntries[fileName][(*vers)[0]] = curVersionNum;
376 // Find the end of data/text segment
377 void emitElf64::findSegmentEnds()
379 Elf64_Phdr *tmp = elf64_getphdr(oldElf);
380 // Find the offset of the start of the text & the data segment
381 // The first LOAD segment is the text & the second LOAD segment
384 for(unsigned i=0;i<oldEhdr->e_phnum;i++)
386 if(tmp->p_type == PT_LOAD)
388 if (dataSegEnd < tmp->p_vaddr+tmp->p_memsz)
389 dataSegEnd = tmp->p_vaddr+tmp->p_memsz;
395 // Rename an old section. Lengths of old and new names must match.
396 // Only renames the FIRST matching section encountered.
397 void emitElf64::renameSection(const std::string &oldStr, const std::string &newStr, bool renameAll) {
398 assert(oldStr.length() == newStr.length());
399 for (unsigned k = 0; k < secNames.size(); k++) {
400 if (secNames[k] == oldStr) {
401 secNames[k].replace(0, oldStr.length(), newStr);
408 bool emitElf64::driver(Symtab *obj, string fName){
411 unsigned pgSize = getpagesize();
413 //open ELf File for writing
414 if((newfd = (open(fName.c_str(), O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP)))==-1){
415 log_elferror(err_func_, "error opening file to write symbols");
418 if((newElf = elf_begin(newfd, ELF_C_WRITE, NULL)) == NULL){
419 log_elferror(err_func_, "NEWELF_BEGIN_FAIL");
424 //Section name index for all sections
425 secNames.push_back("");
427 //Section name index for new sections
428 loadSecTotalSize = 0;
429 unsigned NOBITStotalsize = 0;
430 int dirtySecsChange = 0;
431 unsigned extraAlignSize = 0;
433 // ".shstrtab" section: string table for section header names
434 const char *shnames = pdelf_get_shnames(oldElfHandle);
435 if (shnames == NULL) {
436 log_elferror(err_func_, ".shstrtab section");
440 // Write the Elf header first!
441 newEhdr = elf64_newehdr(newElf);
443 log_elferror(err_func_, "newEhdr failed\n");
446 oldEhdr = elf64_getehdr(oldElf);
447 memcpy(newEhdr, oldEhdr, sizeof(Elf64_Ehdr));
449 newEhdr->e_shnum += newSecs.size();
451 // Find the end of text and data segments
453 unsigned insertPoint = oldEhdr->e_shnum;
454 unsigned NOBITSstartPoint = oldEhdr->e_shnum;
458 newEhdr->e_phoff = sizeof(Elf64_Ehdr);
461 /* flag the file for no auto-layout */
462 elf_flagelf(newElf,ELF_C_SET,ELF_F_LAYOUT);
464 Elf_Scn *scn = NULL, *newscn = NULL;
465 Elf_Data *newdata = NULL, *olddata = NULL;
466 Elf64_Shdr *newshdr = NULL, *shdr = NULL;
467 dyn_hash_map<unsigned, unsigned> secLinkMapping;
468 dyn_hash_map<unsigned, unsigned> secInfoMapping;
469 dyn_hash_map<unsigned, unsigned> changeMapping;
470 dyn_hash_map<std::string, unsigned> newNameIndexMapping;
471 dyn_hash_map<unsigned, std::string> oldIndexNameMapping;
473 bool createdLoadableSections = false;
475 unsigned sectionNumber = 0;
476 for (scncount = 0; (scn = elf_nextscn(oldElf, scn)); scncount++) {
477 //copy sections from oldElf to newElf
478 shdr = elf64_getshdr(scn);
479 // resolve section name
480 Region *previousSec = foundSec;
481 const char *name = &shnames[shdr->sh_name];
482 bool result = obj->findRegion(foundSec, shdr->sh_addr, shdr->sh_size);
484 result = obj->findRegion(foundSec, name);
485 }else if( previousSec == foundSec ) {
486 result = obj->findRegion(foundSec, name);
489 // write the shstrtabsection at the end
490 if(!strcmp(name, ".shstrtab"))
494 changeMapping[sectionNumber] = 0;
495 oldIndexNameMapping[scncount+1] = string(name);
496 newNameIndexMapping[string(name)] = sectionNumber;
498 newscn = elf_newscn(newElf);
499 newshdr = elf64_getshdr(newscn);
500 newdata = elf_newdata(newscn);
501 olddata = elf_getdata(scn,NULL);
502 memcpy(newshdr, shdr, sizeof(Elf64_Shdr));
503 memcpy(newdata,olddata, sizeof(Elf_Data));
505 secNames.push_back(name);
506 newshdr->sh_name = secNameIndex;
507 secNameIndex += strlen(name) + 1;
509 if (newshdr->sh_addr) {
510 newshdr->sh_addr += library_adjust;
513 if(foundSec->isDirty())
515 newdata->d_buf = (char *)malloc(foundSec->getDiskSize());
516 memcpy(newdata->d_buf, foundSec->getPtrToRawData(), foundSec->getDiskSize());
517 newdata->d_size = foundSec->getDiskSize();
518 newshdr->sh_size = foundSec->getDiskSize();
520 else if(olddata->d_buf) //copy the data buffer from oldElf
522 newdata->d_buf = (char *)malloc(olddata->d_size);
523 memcpy(newdata->d_buf, olddata->d_buf, olddata->d_size);
526 if (newshdr->sh_entsize && (newshdr->sh_size % newshdr->sh_entsize != 0))
528 newshdr->sh_entsize = 0x0;
532 // Add the expanded SHT_NOBITS section size if the section comes after those sections
533 if(scncount > NOBITSstartPoint)
534 newshdr->sh_offset += NOBITStotalsize;
536 // Expand the NOBITS sections in file & and change the type from SHT_NOBITS to SHT_PROGBITS
537 if(shdr->sh_type == SHT_NOBITS)
539 newshdr->sh_type = SHT_PROGBITS;
540 newdata->d_buf = (char *)malloc(shdr->sh_size);
541 memset(newdata->d_buf, '\0', shdr->sh_size);
542 newdata->d_size = shdr->sh_size;
543 if(NOBITSstartPoint == oldEhdr->e_shnum)
544 NOBITSstartPoint = scncount;
545 NOBITStotalsize += shdr->sh_size;
549 std::vector <std::vector <unsigned long> > moveSecAddrRange = obj->getObject()->getMoveSecAddrRange();
551 for (unsigned i = 0 ; i != moveSecAddrRange.size(); i++) {
552 if ( (moveSecAddrRange[i][0] == shdr->sh_addr) ||
553 (shdr->sh_addr >= moveSecAddrRange[i][0] && shdr->sh_addr < moveSecAddrRange[i][1]) )
555 newshdr->sh_type = SHT_PROGBITS;
556 changeMapping[sectionNumber] = 1;
557 string newName = ".o";
558 newName.append(name, 2, strlen(name));
559 renameSection((string)name, newName, false);
563 if(obj->getObject()->getStrtabAddr() != 0 &&
564 obj->getObject()->getStrtabAddr() == shdr->sh_addr)
566 symStrData = newdata;
567 updateSymbols(symTabData, symStrData, loadSecTotalSize);
570 //Change sh_link for .symtab to point to .strtab
571 if(obj->getObject()->getSymtabAddr() != 0 &&
572 obj->getObject()->getSymtabAddr() == shdr->sh_addr){
573 newshdr->sh_link = secNames.size();
574 changeMapping[sectionNumber] = 1;
575 symTabData = newdata;
578 if(obj->getObject()->getTextAddr() != 0 &&
579 obj->getObject()->getTextAddr() == shdr->sh_addr){
583 if(obj->getObject()->getDynamicAddr() != 0 &&
584 obj->getObject()->getDynamicAddr() == shdr->sh_addr){
586 dynSegOff = newshdr->sh_offset;
587 dynSegAddr = newshdr->sh_addr;
588 // Change the data to update the relocation addr
589 newshdr->sh_type = SHT_PROGBITS;
590 changeMapping[sectionNumber] = 1;
591 string newName = ".o";
592 newName.append(name, 2, strlen(name));
593 renameSection((string)name, newName, false);
594 //newSecs.push_back(new Section(oldEhdr->e_shnum+newSecs.size(),".dynamic", /*addr*/, newdata->d_size, dynData, Section::dynamicSection, true));
597 // Only need to rewrite data section
598 if( hasRewrittenTLS && foundSec->isTLS()
599 && foundSec->getRegionType() == Region::RT_DATA )
602 newshdr->sh_flags &= ~SHF_TLS;
604 string newName = ".o";
605 newName.append(name, 2, strlen(name));
606 renameSection((string)name, newName, false);
609 // Change offsets of sections based on the newly added sections
611 if (newshdr->sh_offset > 0)
612 newshdr->sh_offset += pgSize;
615 if(scncount > insertPoint && newshdr->sh_offset > 0)
616 newshdr->sh_offset += loadSecTotalSize;
618 if (newshdr->sh_offset > 0)
619 newshdr->sh_offset += (int) (dirtySecsChange + extraAlignSize);
621 if(foundSec->isDirty())
622 dirtySecsChange += newshdr->sh_size - shdr->sh_size;
623 if(BSSExpandFlag && newshdr->sh_addr){
624 unsigned newOff = newshdr->sh_offset - (newshdr->sh_offset & (pgSize-1)) + (newshdr->sh_addr & (pgSize-1));
625 if(newOff < newshdr->sh_offset)
627 extraAlignSize += newOff - newshdr->sh_offset;
628 newshdr->sh_offset = newOff;
632 secLinkMapping[sectionNumber] = shdr->sh_link;
633 secInfoMapping[sectionNumber] = shdr->sh_info;
636 //Insert new loadable sections at the end of data segment
637 if (shdr->sh_addr+shdr->sh_size == dataSegEnd && !createdLoadableSections) {
638 createdLoadableSections = true;
639 insertPoint = scncount;
640 if(!createLoadableSections(newshdr, extraAlignSize,
641 newNameIndexMapping, sectionNumber))
643 if (!movePHdrsFirst) {
645 createNewPhdrRegion(newNameIndexMapping);
649 if ( 0 > elf_update(newElf, ELF_C_NULL))
651 fprintf(stderr, "%s[%d]: elf_update failed: %d, %s\n", FILE__, __LINE__, elf_errno(), elf_errmsg(elf_errno()));
656 // Add non-loadable sections at the end of object file
657 if(!createNonLoadableSections(newshdr))
660 if ( 0 > elf_update(newElf, ELF_C_NULL))
662 fprintf(stderr, "%s[%d]: elf_update failed: %d, %s\n", FILE__, __LINE__, elf_errno(), elf_errmsg(elf_errno()));
666 //Add the section header table right at the end
667 addSectionHeaderTable(newshdr);
669 // Second iteration to fix the link fields to point to the correct section
672 for (scncount = 0; (scn = elf_nextscn(newElf, scn)); scncount++) {
673 shdr = elf64_getshdr(scn);
674 if (changeMapping[scncount+1] == 0 && secLinkMapping[scncount+1] != 0) {
675 unsigned linkIndex = secLinkMapping[scncount+1];
676 string secName = oldIndexNameMapping[linkIndex];
677 unsigned newLinkIndex = newNameIndexMapping[secName];
678 shdr->sh_link = newLinkIndex;
681 if (changeMapping[scncount+1] == 0 && secInfoMapping[scncount+1] != 0) {
682 // For REL and RELA section, info field is a section index - hence of the index changes, the info field must change.
683 // For SYMTAB and DYNSYM, info field is OS specific - so just copy it.
684 // For others, info field is 0, so just copy it
685 if (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA) {
686 unsigned infoIndex = secInfoMapping[scncount+1];
687 string secName = oldIndexNameMapping[infoIndex];
688 unsigned newInfoIndex = newNameIndexMapping[secName];
689 shdr->sh_info = newInfoIndex;
694 newEhdr->e_shstrndx = scncount;
696 // Move the section header to the end
697 newEhdr->e_shoff =shdr->sh_offset+shdr->sh_size;
698 if (newEhdr->e_shoff % 8)
699 newEhdr->e_shoff += 8 - (newEhdr->e_shoff % 8);
700 //copy program headers
701 oldPhdr = elf64_getphdr(oldElf);
702 fixPhdrs(extraAlignSize);
704 //Write the new Elf file
705 if (elf_update(newElf, ELF_C_WRITE) < 0){
707 if ((err = elf_errno()) != 0)
709 const char *msg = elf_errmsg(err);
711 fprintf(stderr, "Error: Unable to write ELF file: %s\n", msg);
713 log_elferror(err_func_, "elf_update failed");
718 if (hasPHdrSectionBug()) {
719 unsigned long ehdr_off = (unsigned long) &(((Elf64_Ehdr *) 0x0)->e_phoff);
720 lseek(newfd, ehdr_off, SEEK_SET);
721 Elf64_Off offset = (Elf64_Off) phdr_offset;
722 write(newfd, &offset, sizeof(Elf64_Off));
729 void emitElf64::createNewPhdrRegion(dyn_hash_map<std::string, unsigned> &newNameIndexMapping)
731 assert(!movePHdrsFirst);
733 unsigned phdr_size = oldEhdr->e_phnum*oldEhdr->e_phentsize;
735 phdr_size += oldEhdr->e_phentsize;
738 if (currEndOffset % 8)
739 align = 8 - (currEndOffset % 8);
741 newEhdr->e_phoff = currEndOffset + align;
742 phdr_offset = newEhdr->e_phoff;
744 Address endaddr = currEndAddress;
745 currEndAddress += phdr_size + align;
746 currEndOffset += phdr_size + align;
747 loadSecTotalSize += phdr_size + align;
749 //libelf.so.1 is annoying. It'll overwrite the data
750 // between sections with 0's, even if we've stuck the
751 // program headers in there. Create a dummy section
752 // to contain the program headers.
753 phdrs_scn = elf_newscn(newElf);
754 Elf64_Shdr *newshdr = elf64_getshdr(phdrs_scn);
755 const char *newname = ".dynphdrs";
757 secNames.push_back(newname);
758 newNameIndexMapping[newname] = secNames.size() - 1;
759 newshdr->sh_name = secNameIndex;
760 secNameIndex += strlen(newname) + 1;
761 newshdr->sh_flags = SHF_ALLOC;
762 newshdr->sh_type = SHT_PROGBITS;
763 newshdr->sh_offset = newEhdr->e_phoff;
764 newshdr->sh_addr = endaddr + align;
765 newshdr->sh_size = phdr_size;
766 newshdr->sh_link = SHN_UNDEF;
767 newshdr->sh_info = 0;
768 newshdr->sh_addralign = 4;
769 newshdr->sh_entsize = newEhdr->e_phentsize;
772 void emitElf64::fixPhdrs(unsigned &extraAlignSize)
774 unsigned pgSize = getpagesize();
775 Elf64_Phdr *old = oldPhdr;
777 newEhdr->e_phnum = oldEhdr->e_phnum;
778 newEhdr->e_phentsize = oldEhdr->e_phentsize;
783 newEhdr->e_phnum= oldEhdr->e_phnum;
785 bool added_new_sec = false;
787 if (!hasPHdrSectionBug())
788 newPhdr = elf64_newphdr(newElf,newEhdr->e_phnum);
790 newPhdr = (Elf64_Phdr *) malloc(sizeof(Elf64_Phdr) * newEhdr->e_phnum);
792 void *phdr_data = (void *) newPhdr;
795 for(unsigned i=0;i<oldEhdr->e_phnum;i++)
797 memcpy(newPhdr, old, oldEhdr->e_phentsize);
798 // Expand the data segment to include the new loadable sections
799 // Also add a executable permission to the segment
800 if(old->p_type == PT_DYNAMIC){
801 newPhdr->p_vaddr = dynSegAddr;
802 newPhdr->p_paddr = dynSegAddr;
803 newPhdr->p_offset = dynSegOff;
804 newPhdr->p_memsz = dynSegSize;
805 newPhdr->p_filesz = newPhdr->p_memsz;
807 else if(old->p_type == PT_PHDR){
808 newPhdr->p_vaddr = old->p_vaddr - pgSize;
809 newPhdr->p_paddr = newPhdr->p_vaddr;
810 newPhdr->p_filesz = sizeof(Elf64_Phdr) * newEhdr->e_phnum;
811 newPhdr->p_memsz = newPhdr->p_filesz;
812 }else if( hasRewrittenTLS && old->p_type == PT_TLS) {
813 newPhdr->p_offset = newTLSData->sh_offset;
814 newPhdr->p_vaddr = newTLSData->sh_addr;
815 newPhdr->p_paddr = newTLSData->sh_addr;
816 newPhdr->p_filesz = newTLSData->sh_size;
817 newPhdr->p_memsz = newTLSData->sh_size + old->p_memsz - old->p_filesz;
818 newPhdr->p_align = newTLSData->sh_addralign;
819 }else if (old->p_type == PT_LOAD) {
820 if(newPhdr->p_align > pgSize) {
821 newPhdr->p_align = pgSize;
824 if(old->p_flags == 6 || old->p_flags == 7)
826 newPhdr->p_memsz += loadSecTotalSize + extraAlignSize;
827 newPhdr->p_filesz = newPhdr->p_memsz;
828 newPhdr->p_flags = 7;
832 if (!old->p_offset) {
833 if (newPhdr->p_vaddr)
834 newPhdr->p_vaddr = old->p_vaddr - pgSize;
835 newPhdr->p_paddr = newPhdr->p_vaddr;
836 newPhdr->p_filesz += pgSize;
837 newPhdr->p_memsz = newPhdr->p_filesz;
840 newPhdr->p_offset += pgSize;
842 if (newPhdr->p_vaddr) {
843 newPhdr->p_vaddr += library_adjust;
847 else if (movePHdrsFirst && old->p_offset) {
848 newPhdr->p_offset += pgSize;
849 if (newPhdr->p_vaddr) {
850 newPhdr->p_vaddr += library_adjust;
856 (i+1 == oldEhdr->e_phnum || (old+1)->p_type != PT_LOAD) &&
857 old->p_type == PT_LOAD &&
861 newSeg.p_type = PT_LOAD;
862 newSeg.p_offset = firstNewLoadSec->sh_offset;
863 newSeg.p_vaddr = newSegmentStart;
864 newSeg.p_paddr = newSeg.p_vaddr;
865 newSeg.p_filesz = loadSecTotalSize - (newSegmentStart - firstNewLoadSec->sh_addr);
866 newSeg.p_memsz = (currEndAddress - firstNewLoadSec->sh_addr) - (newSegmentStart - firstNewLoadSec->sh_addr);
867 newSeg.p_flags = PF_R+PF_W+PF_X;
868 newSeg.p_align = pgSize;
869 memcpy(newPhdr, &newSeg, oldEhdr->e_phentsize);
870 added_new_sec = true;
872 fprintf(stderr, "Added New program header : offset 0x%lx,addr 0x%lx\n", newPhdr->p_offset, newPhdr->p_vaddr);
881 //We made a new section to contain the program headers--keeps
882 // libelf from overwriting the program headers data when outputing
883 // sections. Fill in the new section's data with what we just wrote.
884 Elf_Data *data = elf_newdata(phdrs_scn);
885 size_t total_size = newEhdr->e_phnum * newEhdr->e_phentsize;
886 data->d_buf = malloc(total_size);
887 memcpy(data->d_buf, phdr_data, total_size);
888 data->d_size = total_size;
891 data->d_type = ELF_T_BYTE;
895 #if !defined(os_solaris)
896 #if !defined(DT_GNU_HASH)
897 #define DT_GNU_HASH 0x6ffffef5
900 //This method updates the .dynamic section to reflect the changes to the relocation section
901 void emitElf64::updateDynamic(unsigned tag, Elf64_Addr val){
902 if(dynamicSecData.find(tag) == dynamicSecData.end())
905 switch(dynamicSecData[tag][0]->d_tag) {
909 dynamicSecData[tag][0]->d_un.d_val = val;
919 dynamicSecData[tag][0]->d_un.d_ptr = val;
922 dynamicSecData[tag][0]->d_un.d_ptr = val;
923 dynamicSecData[DT_VERNEEDNUM][0]->d_un.d_val = verneednum;
926 dynamicSecData[tag][0]->d_un.d_ptr = val;
927 dynamicSecData[DT_VERDEFNUM][0]->d_un.d_val = verdefnum;
934 //This method updates the symbol table,
935 //it shifts each symbol address as necessary AND
936 //sets _end and _END_ to move the heap
937 void emitElf64::updateSymbols(Elf_Data* symtabData,Elf_Data* strData, unsigned long loadSecsSize){
938 if( symtabData && strData && loadSecsSize){
939 Elf64_Sym *symPtr=(Elf64_Sym*)symtabData->d_buf;
940 for(unsigned int i=0;i< symtabData->d_size/(sizeof(Elf64_Sym));i++,symPtr++){
941 if(!(strcmp("_end", (char*) strData->d_buf + symPtr->st_name))){
942 //newHeapAddrIncr = newHeapAddr - symPtr->st_value ;
943 symPtr->st_value += loadSecsSize;
945 if(!(strcmp("_END_", (char*) strData->d_buf + symPtr->st_name))){
946 //newHeapAddrIncr = newHeapAddr - symPtr->st_value ;
947 symPtr->st_value += loadSecsSize;
953 bool emitElf64::createLoadableSections(Elf64_Shdr* &shdr, unsigned &extraAlignSize, dyn_hash_map<std::string, unsigned> &newNameIndexMapping, unsigned §ionNumber)
956 Elf_Data *newdata = NULL;
958 std::vector<Elf64_Shdr *> updateDynLinkShdr;
959 std::vector<Elf64_Shdr *> updateStrLinkShdr;
960 firstNewLoadSec = NULL;
961 unsigned pgSize = getpagesize();
962 unsigned strtabIndex = 0;
963 unsigned dynsymIndex = 0;
964 Elf64_Shdr *prevshdr = NULL;
966 for(unsigned i=0; i < newSecs.size(); i++)
968 if(!newSecs[i]->isLoadable()) {
969 nonLoadableSecs.push_back(newSecs[i]);
972 secNames.push_back(newSecs[i]->getRegionName());
973 newNameIndexMapping[newSecs[i]->getRegionName()] = secNames.size() -1;
975 // Add a new loadable section
976 if((newscn = elf_newscn(newElf)) == NULL)
978 log_elferror(err_func_, "unable to create new function");
981 if ((newdata = elf_newdata(newscn)) == NULL)
983 log_elferror(err_func_, "unable to create section data");
986 memset(newdata, 0, sizeof(Elf_Data));
988 // Fill out the new section header
989 newshdr = elf64_getshdr(newscn);
990 newshdr->sh_name = secNameIndex;
991 newshdr->sh_flags = 0;
992 newshdr->sh_type = SHT_PROGBITS;
993 switch(newSecs[i]->getRegionType()){
994 case Region::RT_TEXTDATA:
995 newshdr->sh_flags = SHF_EXECINSTR | SHF_ALLOC | SHF_WRITE;
997 case Region::RT_TEXT:
998 newshdr->sh_flags = SHF_EXECINSTR | SHF_ALLOC;
1000 case Region::RT_BSS:
1001 newshdr->sh_type = SHT_NOBITS;
1002 case Region::RT_DATA:
1003 newshdr->sh_flags = SHF_WRITE | SHF_ALLOC;
1009 if(shdr->sh_type == SHT_NOBITS)
1010 newshdr->sh_offset = shdr->sh_offset;
1011 else if( !firstNewLoadSec || !newSecs[i]->getDiskOffset() ) {
1012 newshdr->sh_offset = shdr->sh_offset+shdr->sh_size;
1014 // The offset can be computed by determing the difference from
1015 // the first new loadable section
1016 newshdr->sh_offset = firstNewLoadSec->sh_offset +
1017 (newSecs[i]->getDiskOffset() - firstNewLoadSec->sh_addr);
1019 // Account for inter-section spacing due to alignment constraints
1020 loadSecTotalSize += newshdr->sh_offset - (shdr->sh_offset+shdr->sh_size);
1023 if(newSecs[i]->getMemOffset()) {
1024 newshdr->sh_addr = newSecs[i]->getMemOffset() + library_adjust;
1027 newshdr->sh_addr = prevshdr->sh_addr + prevshdr->sh_size;
1030 newshdr->sh_link = SHN_UNDEF;
1031 newshdr->sh_info = 0;
1032 newshdr->sh_addralign = newSecs[i]->getMemAlignment();
1033 newshdr->sh_entsize = 0;
1036 if( newSecs[i]->isTLS() ) {
1037 newTLSData = newshdr;
1038 newshdr->sh_flags |= SHF_TLS;
1041 if(newSecs[i]->getRegionType() == Region::RT_REL ||
1042 newSecs[i]->getRegionType() == Region::RT_PLTREL) //Relocation section
1044 newshdr->sh_type = SHT_REL;
1045 newshdr->sh_flags = SHF_ALLOC;
1046 newshdr->sh_entsize = sizeof(Elf64_Rel);
1047 updateDynLinkShdr.push_back(newshdr);
1048 newdata->d_type = ELF_T_REL;
1049 newdata->d_align = 4;
1050 #if !defined(os_solaris)
1051 if (newSecs[i]->getRegionType() == Region::RT_REL)
1052 updateDynamic(DT_REL, newshdr->sh_addr);
1053 else if (newSecs[i]->getRegionType() == Region::RT_PLTREL)
1054 updateDynamic(DT_JMPREL, newshdr->sh_addr);
1057 else if(newSecs[i]->getRegionType() == Region::RT_RELA ||
1058 newSecs[i]->getRegionType() == Region::RT_PLTRELA) //Relocation section
1060 newshdr->sh_type = SHT_RELA;
1061 newshdr->sh_flags = SHF_ALLOC;
1062 newshdr->sh_entsize = sizeof(Elf64_Rela);
1063 updateDynLinkShdr.push_back(newshdr);
1064 newdata->d_type = ELF_T_RELA;
1065 newdata->d_align = 4;
1066 #if !defined(os_solaris)
1067 if (newSecs[i]->getRegionType() == Region::RT_RELA)
1068 updateDynamic(DT_RELA, newshdr->sh_addr);
1069 else if (newSecs[i]->getRegionType() == Region::RT_PLTRELA)
1070 updateDynamic(DT_JMPREL, newshdr->sh_addr);
1073 else if(newSecs[i]->getRegionType() == Region::RT_STRTAB) //String table Section
1075 newshdr->sh_type = SHT_STRTAB;
1076 newshdr->sh_entsize = 1;
1077 newdata->d_type = ELF_T_BYTE;
1078 newshdr->sh_link = SHN_UNDEF;
1079 newshdr->sh_flags= SHF_ALLOC;
1080 newdata->d_align = 1;
1081 strtabIndex = secNames.size()-1;
1082 newshdr->sh_addralign = 1;
1083 #if !defined(os_solaris)
1084 updateDynamic(DT_STRTAB, newshdr->sh_addr);
1085 updateDynamic(DT_STRSZ, newSecs[i]->getDiskSize());
1088 else if(newSecs[i]->getRegionType() == Region::RT_SYMTAB)
1090 newshdr->sh_type = SHT_DYNSYM;
1091 newshdr->sh_entsize = sizeof(Elf64_Sym);
1092 newdata->d_type = ELF_T_SYM;
1093 newdata->d_align = 4;
1094 newshdr->sh_link = secNames.size(); //.symtab section should have sh_link = index of .strtab for .dynsym
1095 newshdr->sh_flags = SHF_ALLOC ;
1096 dynsymIndex = secNames.size()-1;
1097 #if !defined(os_solaris)
1098 updateDynamic(DT_SYMTAB, newshdr->sh_addr);
1101 else if(newSecs[i]->getRegionType() == Region::RT_DYNAMIC)
1103 #if !defined(os_solaris)
1104 newshdr->sh_entsize = sizeof(Elf64_Dyn);
1106 newshdr->sh_type = SHT_DYNAMIC;
1107 newdata->d_type = ELF_T_DYN;
1108 newdata->d_align = 4;
1109 updateStrLinkShdr.push_back(newshdr);
1110 newshdr->sh_flags= SHF_ALLOC | SHF_WRITE;
1111 dynSegOff = newshdr->sh_offset;
1112 dynSegAddr = newshdr->sh_addr;
1113 dynSegSize = newSecs[i]->getDiskSize();
1115 else if(newSecs[i]->getRegionType() == Region::RT_HASH)
1117 newshdr->sh_entsize = sizeof(Elf64_Word);
1118 newshdr->sh_type = SHT_HASH;
1119 newdata->d_type = ELF_T_WORD;
1120 newdata->d_align = 4;
1121 updateDynLinkShdr.push_back(newshdr);
1122 newshdr->sh_flags= SHF_ALLOC;
1123 newshdr->sh_info = 0;
1124 #if !defined(os_solaris)
1125 updateDynamic(DT_HASH, newshdr->sh_addr);
1128 #if !defined(os_solaris)
1129 else if(newSecs[i]->getRegionType() == Region::RT_SYMVERSIONS)
1131 newshdr->sh_type = SHT_GNU_versym;
1132 newshdr->sh_entsize = sizeof(Elf64_Half);
1133 newshdr->sh_addralign = 2;
1134 newdata->d_type = ELF_T_HALF;
1135 newdata->d_align = 2;
1136 updateDynLinkShdr.push_back(newshdr);
1137 newshdr->sh_flags = SHF_ALLOC ;
1138 updateDynamic(DT_VERSYM, newshdr->sh_addr);
1140 else if(newSecs[i]->getRegionType() == Region::RT_SYMVERNEEDED)
1142 newshdr->sh_type = SHT_GNU_verneed;
1143 newshdr->sh_entsize = 0;
1144 newshdr->sh_addralign = 4;
1145 newdata->d_type = ELF_T_VNEED;
1146 newdata->d_align = 4;
1147 updateStrLinkShdr.push_back(newshdr);
1148 newshdr->sh_flags = SHF_ALLOC ;
1149 newshdr->sh_info = 2;
1150 updateDynamic(DT_VERNEED, newshdr->sh_addr);
1152 else if(newSecs[i]->getRegionType() == Region::RT_SYMVERDEF)
1154 newshdr->sh_type = SHT_GNU_verdef;
1155 newshdr->sh_entsize = 0;
1156 newdata->d_type = ELF_T_VDEF;
1157 newdata->d_align = 4;
1158 updateStrLinkShdr.push_back(newshdr);
1159 newshdr->sh_flags = SHF_ALLOC ;
1160 updateDynamic(DT_VERDEF, newshdr->sh_addr);
1166 // Check to make sure the (vaddr for the start of the new segment - the offset) is page aligned
1167 if(!firstNewLoadSec)
1169 newSegmentStart = newshdr->sh_addr;
1170 Offset newoff = newshdr->sh_offset - (newshdr->sh_offset & (pgSize-1)) + (newshdr->sh_addr & (pgSize-1));
1171 if(newoff < newshdr->sh_offset)
1173 extraAlignSize += newoff - newshdr->sh_offset;
1174 newshdr->sh_offset = newoff;
1178 Offset newoff = newshdr->sh_offset - (newshdr->sh_offset & (pgSize-1)) + (newshdr->sh_addr & (pgSize-1));
1179 if(newoff < newshdr->sh_offset)
1181 extraAlignSize += newoff - newshdr->sh_offset;
1182 newshdr->sh_offset = newoff;
1186 newdata->d_buf = malloc(newSecs[i]->getDiskSize());
1187 memcpy(newdata->d_buf, newSecs[i]->getPtrToRawData(), newSecs[i]->getDiskSize());
1189 newdata->d_size = newSecs[i]->getDiskSize();
1190 if (!newdata->d_align)
1191 newdata->d_align = newshdr->sh_addralign;
1192 newshdr->sh_size = newdata->d_size;
1194 currEndOffset = newshdr->sh_offset + newshdr->sh_size;
1195 if( newshdr->sh_type == SHT_NOBITS ) {
1196 currEndOffset = newshdr->sh_offset;
1198 loadSecTotalSize += newshdr->sh_size;
1199 currEndOffset = newshdr->sh_offset + newshdr->sh_size;
1201 currEndAddress = newshdr->sh_addr + newshdr->sh_size;
1203 newdata->d_version = 1;
1205 if (newshdr->sh_entsize && (newshdr->sh_size % newshdr->sh_entsize != 0))
1206 fprintf(stderr, "%s[%d]: ERROR: setting size to non multiple of "
1207 "entry size in section %s: %lu/%lu\n", FILE__, __LINE__,
1208 newSecs[i]->getRegionName().c_str(), newshdr->sh_size,
1209 newshdr->sh_entsize);
1211 if (0 > elf_update(newElf, ELF_C_NULL))
1213 fprintf(stderr, "%s[%d]: elf_update failed\n", FILE__, __LINE__);
1218 if(!firstNewLoadSec)
1219 firstNewLoadSec = shdr;
1220 secNameIndex += newSecs[i]->getRegionName().size() + 1;
1222 #ifdef BINEDIT_DEBUG
1223 fprintf(stderr, "Added New Section(%s) : secAddr 0x%lx, secOff 0x%lx, "
1224 "secsize 0x%lx, end 0x%lx\n",
1225 newSecs[i]->getRegionName().c_str(), newshdr->sh_addr,
1226 newshdr->sh_offset, newshdr->sh_size,
1227 newshdr->sh_offset + newshdr->sh_size );
1232 for(unsigned i=0; i < updateDynLinkShdr.size(); i++) {
1233 newshdr = updateDynLinkShdr[i];
1234 newshdr->sh_link = dynsymIndex;
1237 for(unsigned i=0; i < updateStrLinkShdr.size(); i++) {
1238 newshdr = updateStrLinkShdr[i];
1239 newshdr->sh_link = strtabIndex;
1245 bool emitElf64::addSectionHeaderTable(Elf64_Shdr *shdr) {
1247 Elf_Data *newdata = NULL;
1248 Elf64_Shdr *newshdr;
1250 if((newscn = elf_newscn(newElf)) == NULL)
1252 log_elferror(err_func_, "unable to create new function");
1255 if ((newdata = elf_newdata(newscn)) == NULL)
1257 log_elferror(err_func_, "unable to create section data");
1260 //Fill out the new section header
1261 newshdr = elf64_getshdr(newscn);
1262 newshdr->sh_name = secNameIndex;
1263 secNames.push_back(".shstrtab");
1265 newshdr->sh_type = SHT_STRTAB;
1266 newshdr->sh_entsize = 1;
1267 newdata->d_type = ELF_T_BYTE;
1268 newshdr->sh_link = SHN_UNDEF;
1269 newshdr->sh_flags= 0;
1271 newshdr->sh_offset = shdr->sh_offset+shdr->sh_size;
1272 newshdr->sh_addr = 0;
1273 newshdr->sh_info = 0;
1274 newshdr->sh_addralign = 4;
1277 newdata->d_buf = (char *)malloc(secNameIndex);
1278 char *ptr = (char *)newdata->d_buf;
1279 for(unsigned i=0;i<secNames.size(); i++)
1281 memcpy(ptr, secNames[i].c_str(), secNames[i].length());
1282 memcpy(ptr+secNames[i].length(), "\0", 1);
1283 ptr += secNames[i].length()+1;
1286 newdata->d_size = secNameIndex;
1287 newshdr->sh_size = newdata->d_size;
1288 #ifdef BINEDIT_DEBUG
1289 fprintf(stderr, "Added New Section(%s) : secAddr 0x%lx, secOff 0x%lx, secsize 0x%lx, end 0x%lx\n",
1290 ".shstrtab", newshdr->sh_addr, newshdr->sh_offset, newshdr->sh_size, newshdr->sh_offset + newshdr->sh_size );
1292 //elf_update(newElf, ELF_C_NULL);
1294 newdata->d_align = 4;
1295 newdata->d_version = 1;
1296 if (newshdr->sh_entsize && (newshdr->sh_size % newshdr->sh_entsize != 0))
1297 fprintf(stderr, "%s[%d]: ERROR: setting size to non multiple of entry size in section %s: %lu/%lu\n", FILE__, __LINE__, ".shstrtab", newshdr->sh_size, newshdr->sh_entsize);
1301 bool emitElf64::createNonLoadableSections(Elf64_Shdr *&shdr)
1304 Elf_Data *newdata = NULL;
1305 Elf64_Shdr *newshdr;
1307 Elf64_Shdr *prevshdr = shdr;
1308 //All of them that are left are non-loadable. stack'em up at the end.
1309 for(unsigned i = 0; i < nonLoadableSecs.size(); i++)
1311 secNames.push_back(nonLoadableSecs[i]->getRegionName());
1312 // Add a new non-loadable section
1313 if((newscn = elf_newscn(newElf)) == NULL)
1315 log_elferror(err_func_, "unable to create new function");
1318 if ((newdata = elf_newdata(newscn)) == NULL)
1320 log_elferror(err_func_, "unable to create section data");
1324 //Fill out the new section header
1325 newshdr = elf64_getshdr(newscn);
1326 newshdr->sh_name = secNameIndex;
1327 secNameIndex += nonLoadableSecs[i]->getRegionName().length() + 1;
1328 if(nonLoadableSecs[i]->getRegionType() == Region::RT_TEXT) //Text Section
1330 newshdr->sh_type = SHT_PROGBITS;
1331 newshdr->sh_flags = SHF_EXECINSTR | SHF_WRITE;
1332 newshdr->sh_entsize = 1;
1333 newdata->d_type = ELF_T_BYTE;
1335 else if(nonLoadableSecs[i]->getRegionType() == Region::RT_DATA) //Data Section
1337 newshdr->sh_type = SHT_PROGBITS;
1338 newshdr->sh_flags = SHF_WRITE;
1339 newshdr->sh_entsize = 1;
1340 newdata->d_type = ELF_T_BYTE;
1342 else if(nonLoadableSecs[i]->getRegionType() == Region::RT_REL) //Relocations section
1344 newshdr->sh_type = SHT_REL;
1345 newshdr->sh_flags = SHF_WRITE;
1346 newshdr->sh_entsize = sizeof(Elf64_Rel);
1347 newdata->d_type = ELF_T_BYTE;
1349 else if(nonLoadableSecs[i]->getRegionType() == Region::RT_RELA) //Relocations section
1351 newshdr->sh_type = SHT_RELA;
1352 newshdr->sh_flags = SHF_WRITE;
1353 newshdr->sh_entsize = sizeof(Elf64_Rela);
1354 newdata->d_type = ELF_T_BYTE;
1356 else if(nonLoadableSecs[i]->getRegionType() == Region::RT_SYMTAB)
1358 newshdr->sh_type = SHT_SYMTAB;
1359 newshdr->sh_entsize = sizeof(Elf64_Sym);
1360 newdata->d_type = ELF_T_SYM;
1361 newshdr->sh_link = secNames.size(); //.symtab section should have sh_link = index of .strtab
1362 newshdr->sh_flags= 0;
1364 else if(nonLoadableSecs[i]->getRegionType() == Region::RT_STRTAB) //String table Section
1366 newshdr->sh_type = SHT_STRTAB;
1367 newshdr->sh_entsize = 1;
1368 newdata->d_type = ELF_T_BYTE;
1369 newshdr->sh_link = SHN_UNDEF;
1370 newshdr->sh_flags= 0;
1373 else if(nonLoadableSecs[i]->getFlags() & Section::dynsymtabSection)
1375 newshdr->sh_type = SHT_DYNSYM;
1376 newshdr->sh_entsize = sizeof(Elf64_Sym);
1377 newdata->d_type = ELF_T_SYM;
1378 //newshdr->sh_link = newSecSize+i+1; //.symtab section should have sh_link = index of .strtab
1379 newshdr->sh_flags= SHF_ALLOC | SHF_WRITE;
1381 newshdr->sh_offset = prevshdr->sh_offset+prevshdr->sh_size;
1382 if( prevshdr->sh_type == SHT_NOBITS ) {
1383 newshdr->sh_offset = prevshdr->sh_offset;
1385 newshdr->sh_offset = prevshdr->sh_offset+prevshdr->sh_size;
1387 if (newshdr->sh_offset < currEndOffset) {
1388 newshdr->sh_offset = currEndOffset;
1390 newshdr->sh_addr = 0;
1391 newshdr->sh_info = 0;
1392 newshdr->sh_addralign = 4;
1395 newdata->d_buf = nonLoadableSecs[i]->getPtrToRawData();
1396 newdata->d_size = nonLoadableSecs[i]->getDiskSize();
1397 newshdr->sh_size = newdata->d_size;
1398 //elf_update(newElf, ELF_C_NULL);
1400 newdata->d_align = 4;
1402 newdata->d_version = 1;
1403 currEndOffset = newshdr->sh_offset + newshdr->sh_size;
1404 //currEndAddress = newshdr->sh_addr + newshdr->sh_size;
1406 #ifdef BINEDIT_DEBUG
1407 fprintf(stderr, "Added New Section(%s) : secAddr 0x%lx, secOff 0x%lx, secsize 0x%lx, end 0x%lx\n",
1408 nonLoadableSecs[i]->getRegionName().c_str(), newshdr->sh_addr, newshdr->sh_offset, newshdr->sh_size, newshdr->sh_offset + newshdr->sh_size );
1411 if (newshdr->sh_entsize && (newshdr->sh_size % newshdr->sh_entsize != 0))
1412 fprintf(stderr, "%s[%d]: ERROR: setting size to non multiple of entry size in section %s: %lu/%lu\n", FILE__, __LINE__, nonLoadableSecs[i]->getRegionName().c_str(), newshdr->sh_size, newshdr->sh_entsize);
1420 /* Regenerates the .symtab, .strtab sections from the symbols
1421 * Add new .dynsym, .dynstr sections for the newly added dynamic symbols
1422 * Method - For every symbol call createElfSymbol to get a Elf64_Sym corresposnding
1423 * to a Symbol object. Accumulate all and their names to form the sections
1424 * and add them to the list of new sections
1426 bool emitElf64::createSymbolTables(Symtab *obj, vector<Symbol *>&allSymbols)
1430 //Symbol table(.symtab) symbols
1431 std::vector<Elf64_Sym *> symbols;
1433 //Symbol table(.dynsymtab) symbols
1434 std::vector<Elf64_Sym *> dynsymbols;
1436 unsigned symbolNamesLength = 1, dynsymbolNamesLength = 1;
1437 dyn_hash_map<string, unsigned> dynSymNameMapping;
1438 std::vector<std::string> symbolStrs, dynsymbolStrs;
1439 std::vector<Symbol *> dynsymVector;
1440 std::vector<Symbol *> allDynSymbols;
1441 std::vector<Symbol *> allSymSymbols;
1443 dyn_hash_map<int, Region*> secTagRegionMapping = obj->getObject()->getTagRegionMapping();
1444 dyn_hash_map<int, Region*>::const_iterator foundRegion;
1447 foundRegion = secTagRegionMapping.find(DT_STRTAB);
1448 if ((foundRegion != secTagRegionMapping.end()) && (foundRegion->second != NULL)) {
1450 sec = foundRegion->second;
1451 olddynStrData = (char *)(sec->getPtrToRawData());
1452 olddynStrSize = sec->getRegionSize();
1453 dynsymbolNamesLength = olddynStrSize+1;
1456 //Initialize the list of new prereq libraries
1457 set<string> &plibs = obj->getObject()->prereq_libs;
1458 for (set<string>::iterator i = plibs.begin(); i != plibs.end(); i++) {
1459 DT_NEEDEDEntries.push_back(*i);
1461 new_dynamic_entries = obj->getObject()->new_dynamic_entries;
1462 Object *object = obj->getObject();
1465 // recreate a "dummy symbol"
1466 Elf64_Sym *sym = new Elf64_Sym();
1467 symbolStrs.push_back("");
1472 sym->st_info = ELF64_ST_INFO(STB_LOCAL, STT_NOTYPE);
1473 sym->st_shndx = SHN_UNDEF;
1475 symbols.push_back(sym);
1476 if (!obj->isStaticBinary()) {
1477 dynsymbols.push_back(sym);
1478 dynsymVector.push_back(Symbol::magicEmitElfSymbol());
1479 versionSymTable.push_back(0);
1482 for(i=0; i<allSymbols.size();i++) {
1483 if(allSymbols[i]->isInSymtab()) {
1484 allSymSymbols.push_back(allSymbols[i]);
1486 if (!obj->isStaticBinary()) {
1487 if(allSymbols[i]->isInDynSymtab()) {
1488 allDynSymbols.push_back(allSymbols[i]);
1494 for(i = 0; i < allDynSymbols.size();i++) {
1495 if (max_index < allDynSymbols[i]->getIndex())
1496 max_index = allDynSymbols[i]->getIndex();
1498 for(i=0; i<allDynSymbols.size(); i++) {
1499 if (allDynSymbols[i]->getIndex() == -1) {
1501 allDynSymbols[i]->setIndex(max_index);
1504 if (allDynSymbols[i]->getStrIndex() == -1) {
1505 // New Symbol - append to the list of strings
1506 dynsymbolStrs.push_back( allDynSymbols[i]->getMangledName().c_str());
1507 allDynSymbols[i]->setStrIndex(dynsymbolNamesLength);
1508 dynsymbolNamesLength += allDynSymbols[i]->getMangledName().length() + 1;
1512 // reorder allSymbols based on index
1513 std::sort(allDynSymbols.begin(), allDynSymbols.end(), sortByIndex());
1516 for(i = 0; i < allSymSymbols.size();i++) {
1517 if (max_index < allSymSymbols[i]->getIndex())
1518 max_index = allSymSymbols[i]->getIndex();
1521 for(i=0; i<allSymSymbols.size(); i++) {
1522 if (allSymSymbols[i]->getIndex() == -1) {
1524 allSymSymbols[i]->setIndex(max_index);
1528 std::sort(allSymSymbols.begin(), allSymSymbols.end(), sortByIndex());
1530 /* We regenerate symtab and symstr section. We do not
1531 maintain the order of the strings and symbols as it was in
1532 the original binary. Hence, the strings in symstr have new order and
1534 On the other hand, we do not regenerate dynsym and dynstr section. We copy over
1535 old symbols and string in the original order as it was in the
1536 original binary. We preserve sh_index of Elf symbols (from Symbol's strIndex). We append
1537 new symbols and string that we create for the new binary (targ*, versions etc).
1540 for(i=0; i<allSymSymbols.size();i++) {
1541 //allSymSymbols[i]->setStrIndex(symbolNamesLength);
1542 createElfSymbol(allSymSymbols[i], symbolNamesLength, symbols);
1543 symbolStrs.push_back(allSymSymbols[i]->getName());
1544 symbolNamesLength += allSymSymbols[i]->getName().length()+1;
1546 for(i=0; i<allDynSymbols.size();i++) {
1547 createElfSymbol(allDynSymbols[i], allDynSymbols[i]->getStrIndex(), dynsymbols, true);
1548 dynSymNameMapping[allDynSymbols[i]->getName().c_str()] = allDynSymbols[i]->getIndex();
1549 dynsymVector.push_back(allDynSymbols[i]);
1552 //reconstruct .symtab section
1553 Elf64_Sym *syms = (Elf64_Sym *)malloc(symbols.size()* sizeof(Elf64_Sym));
1554 for(i=0;i<symbols.size();i++)
1555 syms[i] = *(symbols[i]);
1557 --symbolNamesLength;
1558 char *str = (char *)malloc(symbolNamesLength+1);
1560 for(i=0;i<symbolStrs.size();i++)
1562 strcpy(&str[cur],symbolStrs[i].c_str());
1563 cur+=symbolStrs[i].length()+1;
1569 if (obj->findRegion(sec,".symtab"))
1570 sec->setPtrToRawData(syms, symbols.size()*sizeof(Elf64_Sym));
1572 obj->addRegion(0, syms, symbols.size()*sizeof(Elf64_Sym), ".symtab", Region::RT_SYMTAB);
1575 obj->addRegion(0, syms, symbols.size()*sizeof(Elf64_Sym), ".symtab", Region::RT_SYMTAB);
1577 //reconstruct .strtab section
1581 if (obj->findRegion(sec,".strtab"))
1582 sec->setPtrToRawData(str, symbolNamesLength);
1584 obj->addRegion(0, str, symbolNamesLength , ".strtab", Region::RT_STRTAB);
1587 obj->addRegion(0, str, symbolNamesLength , ".strtab", Region::RT_STRTAB);
1589 if(!obj->getAllNewRegions(newSecs))
1590 log_elferror(err_func_, "No new sections to add");
1592 if(dynsymbols.size() == 1)
1595 if (!obj->isStaticBinary()) {
1596 //reconstruct .dynsym section
1597 Elf64_Sym *dynsyms = (Elf64_Sym *)malloc(dynsymbols.size()* sizeof(Elf64_Sym));
1598 for(i=0;i<dynsymbols.size();i++)
1599 dynsyms[i] = *(dynsymbols[i]);
1601 #if !defined(os_solaris)
1602 Elf64_Half *symVers;
1603 char *verneedSecData, *verdefSecData;
1604 unsigned verneedSecSize = 0, verdefSecSize = 0;
1606 createSymbolVersions(obj, symVers, verneedSecData, verneedSecSize, verdefSecData, verdefSecSize, dynsymbolNamesLength, dynsymbolStrs);
1607 // build new .hash section
1608 Elf64_Word *hashsecData;
1609 unsigned hashsecSize = 0;
1610 createHashSection(obj, hashsecData, hashsecSize, dynsymVector);
1613 if (secTagRegionMapping.find(DT_HASH) != secTagRegionMapping.end()) {
1614 name = secTagRegionMapping[DT_HASH]->getRegionName();
1615 obj->addRegion(0, hashsecData, hashsecSize*sizeof(Elf64_Word), name, Region::RT_HASH, true);
1616 } else if (secTagRegionMapping.find(0x6ffffef5) != secTagRegionMapping.end()) {
1617 name = secTagRegionMapping[0x6ffffef5]->getRegionName();
1618 obj->addRegion(0, hashsecData, hashsecSize*sizeof(Elf64_Word), name, Region::RT_HASH, true);
1621 obj->addRegion(0, hashsecData, hashsecSize*sizeof(Elf64_Word), name, Region::RT_HASH, true);
1625 Elf64_Dyn *dynsecData;
1626 unsigned dynsecSize = 0;
1627 if(obj->findRegion(sec, ".dynamic")) {
1628 createDynamicSection(sec->getPtrToRawData(), sec->getDiskSize(), dynsecData, dynsecSize, dynsymbolNamesLength, dynsymbolStrs);
1632 if(!dynsymbolNamesLength)
1635 char *dynstr = (char *)malloc(dynsymbolNamesLength);
1636 memcpy((void *)dynstr, (void *)olddynStrData, olddynStrSize);
1637 cur = olddynStrSize+1;
1638 for(i=0;i<dynsymbolStrs.size();i++)
1640 strcpy(&dynstr[cur],dynsymbolStrs[i].c_str());
1641 cur+=dynsymbolStrs[i].length()+1;
1642 if ( dynSymNameMapping.find(dynsymbolStrs[i]) == dynSymNameMapping.end()) {
1643 dynSymNameMapping[dynsymbolStrs[i]] = allDynSymbols.size()+i;
1648 if (secTagRegionMapping.find(DT_SYMTAB) != secTagRegionMapping.end()) {
1649 name = secTagRegionMapping[DT_SYMTAB]->getRegionName();
1653 obj->addRegion(0, dynsyms, dynsymbols.size()*sizeof(Elf64_Sym), name, Region::RT_SYMTAB, true);
1655 if (secTagRegionMapping.find(DT_STRTAB) != secTagRegionMapping.end()) {
1656 name = secTagRegionMapping[DT_STRTAB]->getRegionName();
1660 obj->addRegion(0, dynstr, dynsymbolNamesLength , name, Region::RT_STRTAB, true);
1662 #if !defined(os_solaris)
1663 //add .gnu.version, .gnu.version_r, and .gnu.version_d sections
1664 if (secTagRegionMapping.find(DT_VERSYM) != secTagRegionMapping.end()) {
1665 name = secTagRegionMapping[DT_VERSYM]->getRegionName();
1667 name = ".gnu.version";
1669 obj->addRegion(0, symVers, versionSymTable.size() * sizeof(Elf64_Half), name, Region::RT_SYMVERSIONS, true);
1671 if(verneedSecSize) {
1672 if (secTagRegionMapping.find(DT_VERNEED) != secTagRegionMapping.end()) {
1673 name = secTagRegionMapping[DT_VERNEED]->getRegionName();
1675 name = ".gnu.version_r";
1677 obj->addRegion(0, verneedSecData, verneedSecSize, name, Region::RT_SYMVERNEEDED, true);
1681 obj->addRegion(0, verdefSecData, verdefSecSize, ".gnu.version_d", Region::RT_SYMVERDEF, true);
1685 //Always create a dyn section, it may get our new relocations.
1686 //If both exist, then just try to maintain order.
1687 bool has_plt = object->hasRelaplt() || object->hasRelplt();
1688 bool has_dyn = object->hasReladyn() || object->hasReladyn();
1690 createRelocationSections(obj, object->getDynRelocs(), true, dynSymNameMapping);
1692 else if (!has_dyn) {
1693 createRelocationSections(obj, object->getPLTRelocs(), false, dynSymNameMapping);
1694 createRelocationSections(obj, object->getDynRelocs(), true, dynSymNameMapping);
1696 else if (object->getRelPLTAddr() < object->getRelDynAddr()) {
1697 createRelocationSections(obj, object->getPLTRelocs(), false, dynSymNameMapping);
1698 createRelocationSections(obj, object->getDynRelocs(), true, dynSymNameMapping);
1701 createRelocationSections(obj, object->getDynRelocs(), true, dynSymNameMapping);
1702 createRelocationSections(obj, object->getPLTRelocs(), false, dynSymNameMapping);
1705 #if !defined(os_solaris)
1706 //add .dynamic section
1708 obj->addRegion(0, dynsecData, dynsecSize*sizeof(Elf64_Dyn), ".dynamic", Region::RT_DYNAMIC, true);
1711 // Static binary case
1712 vector<Region *> newRegs;
1713 obj->getAllNewRegions(newRegs);
1714 if( newRegs.size() ) {
1715 emitElfStatic linker(obj->getAddressWidth(), isStripped);
1717 emitElfStatic::StaticLinkError err;
1719 linkedStaticData = linker.linkStatic(obj, err, errMsg);
1720 if ( !linkedStaticData ) {
1721 fprintf(stderr, "Failed to link in static library code: %s = %s\n",
1722 emitElfStatic::printStaticLinkError(err).c_str(), errMsg.c_str());
1723 log_elferror(err_func_, "Failed to link in static library code.");
1727 hasRewrittenTLS = linker.hasRewrittenTLS();
1731 if(!obj->getAllNewRegions(newSecs))
1732 log_elferror(err_func_, "No new sections to add");
1737 void emitElf64::createRelocationSections(Symtab *obj, std::vector<relocationEntry> &relocation_table, bool isDynRelocs, dyn_hash_map<std::string, unsigned> &dynSymNameMapping) {
1738 vector<relocationEntry> newRels;
1739 if(isDynRelocs && newSecs.size()) {
1740 std::vector<Region *>::iterator i;
1741 for (i = newSecs.begin(); i != newSecs.end(); i++) {
1742 std::copy((*i)->getRelocations().begin(),
1743 (*i)->getRelocations().end(),
1744 std::back_inserter(newRels));
1750 Elf64_Rel *rels = (Elf64_Rel *)malloc(sizeof(Elf64_Rel) * (relocation_table.size()+newRels.size()));
1751 Elf64_Rela *relas = (Elf64_Rela *)malloc(sizeof(Elf64_Rela) * (relocation_table.size()+newRels.size()));
1754 for(i=0;i<relocation_table.size();i++)
1756 if (relocation_table[i].regionType() == Region::RT_REL) {
1757 rels[j].r_offset = relocation_table[i].rel_addr() + library_adjust;
1758 if(relocation_table[i].name().length() &&
1759 dynSymNameMapping.find(relocation_table[i].name()) != dynSymNameMapping.end()) {
1760 rels[j].r_info = ELF64_R_INFO(dynSymNameMapping[relocation_table[i].name()], relocation_table[i].getRelType());
1762 rels[j].r_info = ELF64_R_INFO(STN_UNDEF, relocation_table[i].getRelType());
1766 relas[k].r_offset = relocation_table[i].rel_addr() + library_adjust;
1767 relas[k].r_addend = relocation_table[i].addend();
1768 if (relas[k].r_addend)
1769 relas[k].r_addend += library_adjust;
1770 if(relocation_table[i].name().length() &&
1771 dynSymNameMapping.find(relocation_table[i].name()) != dynSymNameMapping.end()) {
1772 relas[k].r_info = ELF64_R_INFO(dynSymNameMapping[relocation_table[i].name()], relocation_table[i].getRelType());
1774 relas[k].r_info = ELF64_R_INFO(STN_UNDEF, relocation_table[i].getRelType());
1779 for(i=0;i<newRels.size();i++)
1781 if (newRels[i].regionType() == Region::RT_REL) {
1782 rels[j].r_offset = newRels[i].rel_addr();
1783 if(dynSymNameMapping.find(newRels[i].name()) != dynSymNameMapping.end()) {
1784 #if defined(arch_x86)
1785 rels[j].r_info = ELF64_R_INFO(dynSymNameMapping[newRels[i].name()], R_386_GLOB_DAT);
1786 #elif defined(arch_sparc)
1787 // rels[j].r_info = ELF64_R_INFO(dynSymNameMapping[newRels[i].name()], R_SPARC_GLOB_DAT);
1788 #elif defined(arch_x86_64)
1789 rels[j].r_info = ELF64_R_INFO(dynSymNameMapping[newRels[i].name()], R_X86_64_GLOB_DAT);
1790 #elif defined(arch_power)
1791 rels[j].r_info = ELF64_R_INFO(dynSymNameMapping[newRels[i].name()], R_PPC_GLOB_DAT);
1794 #if defined(arch_x86)
1795 rels[j].r_info = ELF64_R_INFO(STN_UNDEF, R_386_GLOB_DAT);
1796 #elif defined(arch_sparc)
1797 // rels[j].r_info = ELF64_R_INFO(STN_UNDEF, R_SPARC_GLOB_DAT);
1798 #elif defined(arch_x86_64)
1799 rels[j].r_info = ELF64_R_INFO(STN_UNDEF, R_X86_64_GLOB_DAT);
1800 #elif defined(arch_power)
1801 rels[j].r_info = ELF64_R_INFO(STN_UNDEF, R_PPC_GLOB_DAT);
1807 relas[k].r_offset = newRels[i].rel_addr();
1808 relas[k].r_addend = newRels[i].addend();
1809 if(dynSymNameMapping.find(newRels[i].name()) != dynSymNameMapping.end()) {
1810 #if defined(arch_x86)
1811 relas[k].r_info = ELF64_R_INFO(dynSymNameMapping[newRels[i].name()], R_386_GLOB_DAT);
1812 #elif defined(arch_sparc)
1813 // relas[k].r_info = ELF64_R_INFO(dynSymNameMapping[newRels[i].name()], R_SPARC_GLOB_DAT);
1814 #elif defined(arch_x86_64)
1815 relas[k].r_info = ELF64_R_INFO(dynSymNameMapping[newRels[i].name()], R_X86_64_GLOB_DAT);
1816 #elif defined(arch_power)
1817 relas[k].r_info = ELF64_R_INFO(dynSymNameMapping[newRels[i].name()], R_PPC_GLOB_DAT);
1820 #if defined(arch_x86)
1821 relas[k].r_info = ELF64_R_INFO(STN_UNDEF, R_386_GLOB_DAT);
1822 #elif defined(arch_sparc)
1823 // relas[k].r_info = ELF64_R_INFO(STN_UNDEF, R_SPARC_GLOB_DAT);
1824 #elif defined(arch_x86_64)
1825 relas[k].r_info = ELF64_R_INFO(STN_UNDEF, R_X86_64_GLOB_DAT);
1826 #elif defined(arch_power)
1827 relas[k].r_info = ELF64_R_INFO(STN_UNDEF, R_PPC_GLOB_DAT);
1835 #if defined (os_solaris)
1836 fprintf(stderr, "%s[%d]: FIXME: This does not work on solaris\n", FILE__, __LINE__);
1838 dyn_hash_map<int, Region*> secTagRegionMapping = obj->getObject()->getTagRegionMapping();
1839 int reloc_size, old_reloc_size, dynamic_reloc_size;
1840 const char *new_name;
1841 Region::RegionType rtype;
1844 void *buffer = NULL;
1846 reloc_size = j*sizeof(Elf64_Rel)+k*sizeof(Elf64_Rela);
1850 if (isDynRelocs && obj->hasReldyn()) {
1851 new_name = ".rel.dyn";
1853 rtype = Region::RT_REL;
1854 dsize_type = DT_RELSZ;
1857 if (isDynRelocs && obj->hasReladyn()) {
1858 new_name = ".rela.dyn";
1860 rtype = Region::RT_RELA;
1861 dsize_type = DT_RELASZ;
1864 if (!isDynRelocs && obj->hasReldyn()) {
1865 new_name = ".rel.plt";
1867 rtype = Region::RT_PLTREL;
1868 dsize_type = DT_PLTRELSZ;
1871 if (!isDynRelocs && obj->hasReladyn()) {
1872 new_name = ".rela.plt";
1874 rtype = Region::RT_PLTRELA;
1875 dsize_type = DT_PLTRELSZ;
1878 old_reloc_size = dynamicSecData[dsize_type][0]->d_un.d_val;
1879 dynamic_reloc_size = old_reloc_size+ l*sizeof(Elf64_Rel)+ m*sizeof(Elf64_Rela);
1881 if (secTagRegionMapping.find(dtype) != secTagRegionMapping.end())
1882 name = secTagRegionMapping[dtype]->getRegionName();
1884 name = std::string(new_name);
1885 obj->addRegion(0, buffer, reloc_size, name, rtype, true);
1886 updateDynamic(dsize_type, dynamic_reloc_size);
1890 #if !defined(os_solaris)
1891 void emitElf64::createSymbolVersions(Symtab *obj, Elf64_Half *&symVers, char*&verneedSecData, unsigned &verneedSecSize, char *&verdefSecData, unsigned &verdefSecSize, unsigned &dynSymbolNamesLength, vector<string> &dynStrs){
1893 //Add all names to the new .dynstr section
1894 map<string, unsigned>::iterator iter = versionNames.begin();
1895 for(;iter!=versionNames.end();iter++){
1896 iter->second = dynSymbolNamesLength;
1897 dynStrs.push_back(iter->first);
1898 dynSymbolNamesLength+= iter->first.size()+1;
1901 //reconstruct .gnu_version section
1902 symVers = (Elf64_Half *)malloc(versionSymTable.size() * sizeof(Elf64_Half));
1903 for(unsigned i=0; i<versionSymTable.size(); i++)
1904 symVers[i] = versionSymTable[i];
1906 //reconstruct .gnu.version_r section
1908 map<string, map<string, unsigned> >::iterator it = verneedEntries.begin();
1909 for(; it != verneedEntries.end(); it++)
1910 verneedSecSize += sizeof(Elf64_Verneed) + sizeof(Elf64_Vernaux) * it->second.size();
1912 verneedSecData = (char *)malloc(verneedSecSize);
1913 unsigned curpos = 0;
1915 std::vector<std::string>::iterator dit;
1916 for(dit = unversionedNeededEntries.begin(); dit != unversionedNeededEntries.end(); dit++) {
1917 // account for any substitutions due to rewriting a shared lib
1918 std::string name = obj->getDynLibSubstitution(*dit);
1919 // no need for self-references
1920 if (!(obj->name() == name)) {
1921 versionNames[name] = dynSymbolNamesLength;
1922 dynStrs.push_back(name);
1923 dynSymbolNamesLength+= (name).size()+1;
1924 if(find(DT_NEEDEDEntries.begin(), DT_NEEDEDEntries.end(), name) == DT_NEEDEDEntries.end())
1925 DT_NEEDEDEntries.push_back(name);
1928 for(it = verneedEntries.begin(); it != verneedEntries.end(); it++){
1929 Elf64_Verneed *verneed = (Elf64_Verneed *)(void*)(verneedSecData+curpos);
1930 verneed->vn_version = 1;
1931 verneed->vn_cnt = it->second.size();
1932 verneed->vn_file = dynSymbolNamesLength;
1933 versionNames[it->first] = dynSymbolNamesLength;
1934 dynStrs.push_back(it->first);
1935 dynSymbolNamesLength+= it->first.size()+1;
1936 if(find(DT_NEEDEDEntries.begin(), DT_NEEDEDEntries.end(), it->first) == DT_NEEDEDEntries.end())
1937 DT_NEEDEDEntries.push_back(it->first);
1938 verneed->vn_aux = sizeof(Elf64_Verneed);
1939 verneed->vn_next = sizeof(Elf64_Verneed) + it->second.size()*sizeof(Elf64_Vernaux);
1940 if(curpos + verneed->vn_next == verneedSecSize)
1941 verneed->vn_next = 0;
1944 for(iter = it->second.begin(); iter!= it->second.end(); iter++){
1945 Elf64_Vernaux *vernaux = (Elf64_Vernaux *)(void*)(verneedSecData + curpos + verneed->vn_aux + i*sizeof(Elf64_Vernaux));
1946 vernaux->vna_hash = elfHash(iter->first.c_str());
1947 vernaux->vna_flags = 0;
1948 vernaux->vna_other = iter->second;
1949 vernaux->vna_name = versionNames[iter->first];
1950 if(i == verneed->vn_cnt-1)
1951 vernaux->vna_next = 0;
1953 vernaux->vna_next = sizeof(Elf64_Vernaux);
1956 curpos += verneed->vn_next;
1959 //reconstruct .gnu.version_d section
1961 for(iter = verdefEntries.begin(); iter != verdefEntries.end(); iter++)
1962 verdefSecSize += sizeof(Elf64_Verdef) + sizeof(Elf64_Verdaux) * verdauxEntries[iter->second].size();
1964 verdefSecData = (char *)malloc(verdefSecSize);
1967 for(iter = verdefEntries.begin(); iter != verdefEntries.end(); iter++){
1968 Elf64_Verdef *verdef = (Elf64_Verdef *)(void*)(verdefSecData+curpos);
1969 verdef->vd_version = 1;
1970 verdef->vd_flags = 0;
1971 verdef->vd_ndx = iter->second;
1972 verdef->vd_cnt = verdauxEntries[iter->second].size();
1973 verdef->vd_hash = elfHash(iter->first.c_str());
1974 verdef->vd_aux = sizeof(Elf64_Verdef);
1975 verdef->vd_next = sizeof(Elf64_Verdef) + verdauxEntries[iter->second].size()*sizeof(Elf64_Verdaux);
1976 if(curpos + verdef->vd_next == verdefSecSize)
1977 verdef->vd_next = 0;
1979 for(unsigned i = 0; i< verdauxEntries[iter->second].size(); i++){
1980 Elf64_Verdaux *verdaux = (Elf64_Verdaux *)(void*)(verdefSecData + curpos + verdef->vd_aux + i*sizeof(Elf64_Verdaux));
1981 verdaux->vda_name = versionNames[verdauxEntries[iter->second][0]];
1982 if((signed) i == verdef->vd_cnt-1)
1983 verdaux->vda_next = 0;
1985 verdaux->vda_next = sizeof(Elf64_Verdaux);
1987 curpos += verdef->vd_next;
1992 void emitElf64::createHashSection(Symtab *obj, Elf64_Word *&hashsecData, unsigned &hashsecSize, vector<Symbol *>&dynSymbols)
1995 /* Save the original hash table entries */
1996 std::vector<unsigned> originalHashEntries;
1997 unsigned dynsymSize = obj->getObject()->getDynsymSize();
1999 Elf_Scn *scn = NULL;
2000 Elf64_Shdr *shdr = NULL;
2001 for (unsigned scncount = 0; (scn = elf_nextscn(oldElf, scn)); scncount++) {
2002 shdr = elf64_getshdr(scn);
2003 if(obj->getObject()->getElfHashAddr() != 0 &&
2004 obj->getObject()->getElfHashAddr() == shdr->sh_addr){
2005 Elf_Data *hashData = elf_getdata(scn,NULL);
2006 Elf64_Word *oldHashSec = (Elf64_Word *) hashData->d_buf;
2007 unsigned original_nbuckets, original_nchains;
2008 original_nbuckets = oldHashSec[0];
2009 original_nchains = oldHashSec[1];
2010 for (unsigned i = 0; i < original_nbuckets+original_nchains; i++) {
2011 if ( oldHashSec[2+i] != 0) {
2012 originalHashEntries.push_back( oldHashSec[2+i]);
2013 //printf(" ELF HASH pushing hash entry %d \n", oldHashSec[2+i] );
2018 if(obj->getObject()->getGnuHashAddr() != 0 &&
2019 obj->getObject()->getGnuHashAddr() == shdr->sh_addr){
2020 Elf_Data *hashData = elf_getdata(scn,NULL);
2021 Elf64_Word *oldHashSec = (Elf64_Word *) hashData->d_buf;
2022 unsigned symndx = oldHashSec[1];
2023 if (dynsymSize != 0)
2024 for (unsigned i = symndx; i < dynsymSize ; i++) {
2025 originalHashEntries.push_back(i);
2026 //printf(" GNU HASH pushing hash entry %d \n", i);
2031 vector<Symbol *>::iterator iter;
2032 dyn_hash_map<unsigned, unsigned> lastHash; // bucket number to symbol index
2033 unsigned nbuckets = (unsigned)dynSymbols.size()*2/3;
2034 if (nbuckets % 2 == 0)
2038 unsigned nchains = (unsigned)dynSymbols.size();
2039 hashsecSize = 2 + nbuckets + nchains;
2040 hashsecData = (Elf64_Word *)malloc(hashsecSize*sizeof(Elf64_Word));
2042 for (i=0; i<hashsecSize; i++) {
2043 hashsecData[i] = STN_UNDEF;
2045 hashsecData[0] = (Elf64_Word)nbuckets;
2046 hashsecData[1] = (Elf64_Word)nchains;
2048 for (iter = dynSymbols.begin(); iter != dynSymbols.end(); iter++, i++) {
2049 if((*iter)->getName().empty()) continue;
2050 unsigned index = (*iter)->getIndex();
2051 if ((find(originalHashEntries.begin(),originalHashEntries.end(),index) == originalHashEntries.end()) &&
2052 (index < obj->getObject()->getDynsymSize())) {
2055 key = elfHash((*iter)->getName().c_str()) % nbuckets;
2056 if (lastHash.find(key) != lastHash.end()) {
2057 hashsecData[2+nbuckets+lastHash[key]] = i;
2060 hashsecData[2+key] = i;
2063 hashsecData[2+nbuckets+i] = STN_UNDEF;
2067 void emitElf64::createDynamicSection(void *dynData, unsigned size, Elf64_Dyn *&dynsecData, unsigned &dynsecSize, unsigned &dynSymbolNamesLength, std::vector<std::string> &dynStrs) {
2068 dynamicSecData.clear();
2069 Elf64_Dyn *dyns = (Elf64_Dyn *)dynData;
2070 unsigned count = size/sizeof(Elf64_Dyn);
2071 dynsecSize = 2*(count + DT_NEEDEDEntries.size() + new_dynamic_entries.size());
2072 dynsecData = (Elf64_Dyn *)malloc(dynsecSize*sizeof(Elf64_Dyn));
2073 unsigned curpos = 0;
2075 for(unsigned i = 0; i< DT_NEEDEDEntries.size(); i++){
2076 dynsecData[curpos].d_tag = DT_NEEDED;
2077 dynStrs.push_back(DT_NEEDEDEntries[i]);
2078 dynsecData[curpos].d_un.d_val = dynSymbolNamesLength;
2079 dynSymbolNamesLength += DT_NEEDEDEntries[i].size()+1;
2080 dynamicSecData[DT_NEEDED].push_back(dynsecData+curpos);
2083 for (unsigned i = 0; i<new_dynamic_entries.size(); i++) {
2084 long name = new_dynamic_entries[i].first;
2085 long value = new_dynamic_entries[i].second;
2086 dynsecData[curpos].d_tag = name;
2087 dynsecData[curpos].d_un.d_val = value;
2088 dynamicSecData[name].push_back(dynsecData+curpos);
2092 // There may be multiple HASH (ELF, GNU etc) sections in the original binary. We consolidate all of them into one.
2093 bool foundHashSection = false;
2095 for(unsigned i = 0; i< count;i++){
2096 switch(dyns[i].d_tag){
2099 case 0x6ffffef5: // DT_GNU_HASH (not defined on all platforms)
2100 if (!foundHashSection) {
2101 dynsecData[curpos].d_tag = DT_HASH;
2102 dynsecData[curpos].d_un.d_ptr =dyns[i].d_un.d_ptr ;
2103 dynamicSecData[DT_HASH].push_back(dynsecData+curpos);
2105 foundHashSection = true;
2109 if (!foundHashSection) {
2110 dynsecData[curpos].d_tag = dyns[i].d_tag;
2111 dynsecData[curpos].d_un.d_ptr =dyns[i].d_un.d_ptr ;
2112 dynamicSecData[dyns[i].d_tag].push_back(dynsecData+curpos);
2114 foundHashSection = true;
2118 rpathstr = &olddynStrData[dyns[i].d_un.d_val];
2119 if(find(DT_NEEDEDEntries.begin(), DT_NEEDEDEntries.end(), rpathstr) != DT_NEEDEDEntries.end())
2121 dynsecData[curpos].d_tag = dyns[i].d_tag;
2122 dynsecData[curpos].d_un.d_val = dynSymbolNamesLength;
2123 dynStrs.push_back(rpathstr);
2124 dynSymbolNamesLength += rpathstr.size() + 1;
2125 dynamicSecData[dyns[i].d_tag].push_back(dynsecData+curpos);
2130 dynsecData[curpos].d_tag = dyns[i].d_tag;
2131 dynsecData[curpos].d_un.d_val = dynSymbolNamesLength;
2132 rpathstr = &olddynStrData[dyns[i].d_un.d_val];
2133 dynStrs.push_back(rpathstr);
2134 dynSymbolNamesLength += rpathstr.size() + 1;
2135 dynamicSecData[dyns[i].d_tag].push_back(dynsecData+curpos);
2140 case DT_GNU_CONFLICT:
2144 * List every dynamic entry that references an address and isn't already
2145 * updated here. library_adjust will be a page size if
2146 * we're dealing with a library without a fixed load address. We'll be shifting
2147 * the addresses of that library by a page.
2149 memcpy(dynsecData+curpos, dyns+i, sizeof(Elf64_Dyn));
2150 dynsecData[curpos].d_un.d_ptr += library_adjust;
2151 dynamicSecData[dyns[i].d_tag].push_back(dynsecData+curpos);
2155 memcpy(dynsecData+curpos, dyns+i, sizeof(Elf64_Dyn));
2156 dynamicSecData[dyns[i].d_tag].push_back(dynsecData+curpos);
2161 dynsecData[curpos].d_tag = DT_NULL;
2162 dynsecData[curpos].d_un.d_val = 0;
2164 dynsecSize = curpos+1; //assign size to the correct number of entries
2169 void emitElf64::log_elferror(void (*err_func)(const char *), const char* msg) {
2170 const char* err = elf_errmsg(elf_errno());
2171 err = err ? err: "(bad elf error)";
2172 string str = string(err)+string(msg);
2173 err_func(str.c_str());