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