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