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