This commit fixes bug 491, elfutils on redhat linux
[dyninst.git] / dyninstAPI / src / editSharedLibrary.C
1 /* $Id $ */
2 #include <editSharedLibrary.h>
3 #include "dyninstAPI/src/util.h"
4
5
6 /*      This function will open the shared library and remove the
7         padded out bss section.  The PHT will be updated, the data segment
8         filesz will be corrected.  The Ehdr section header index will also be
9         corrected
10 */
11 bool editSharedLibrary::removeBSSfromSharedLibrary(char *libName){
12
13         elf_version(EV_CURRENT);
14         if((fd = open(libName, O_RDWR)) == -1){
15                 bpfatal("cannot open Old SO: %s\n",libName);
16                 perror(" FAIL ");
17                 return false;
18         }
19         if((oldElf = elf_begin(fd, ELF_C_RDWR, NULL)) ==NULL){
20                 bpfatal("cannot open ELF %s \n", libName);
21                 return false;
22         }
23
24         bool res = removeBSS();
25
26         elf_update(oldElf, ELF_C_WRITE);
27         elf_end(oldElf);
28         close(fd);
29
30         return res;
31 }
32
33 bool editSharedLibrary::removeBSS(){
34
35         int bssSize;
36         bool bssFound=false;
37         int offsetMovement;
38
39         Elf32_Ehdr *ehdr = elf32_getehdr(oldElf);
40         Elf32_Phdr *phdr = elf32_getphdr(oldElf);
41
42         Elf32_Shdr *shdr;
43         Elf_Scn *scn; 
44         Elf_Data *strdata, *olddata;
45
46      if (((ehdr = elf32_getehdr(oldElf)) != NULL)){ 
47
48         if((scn = elf_getscn(oldElf, ehdr->e_shstrndx)) != NULL){
49
50                 if((strdata = elf_getdata(scn, NULL)) == NULL){
51                                 bperr(" Failed obtaining .shstrtab data buffer \n");
52                                 return false;
53                         }
54                 }else{
55                         bperr(" FAILED obtaining .shstrtab scn\n");             
56                         return false;
57                 }
58         }else{
59                 bperr(" FAILED obtaining .shstrtab ehdr\n");
60                 return false;
61         }
62
63         scn = NULL;
64
65         for (int cnt = 1; (scn = elf_nextscn(oldElf, scn)); cnt++) {
66         
67                 shdr = elf32_getshdr(scn);
68                 olddata = elf_getdata(scn,NULL);
69         
70                 if( bssFound ){
71                         shdr->sh_offset -= offsetMovement;      
72
73                         while( (shdr->sh_offset % shdr->sh_addralign) != 0){
74                                 shdr->sh_offset ++;
75                                 /* offsetMovement needs decreased everytime we move a section down b/c of alignment */
76                                 offsetMovement --;
77                         }
78                 }
79
80                 if(!strcmp( (char*) strdata->d_buf + shdr->sh_name, ".bss")){
81                         bssFound =true;
82                         bssSize = shdr->sh_size;
83                         /* we will shift every succeeding section up by offsetMovement */
84                         offsetMovement = bssSize;
85
86                         //delete [] (char*)olddata->d_buf;
87
88                         /* this should get deallocated by elf when the file is closed */
89                         /* insure gives errors if i try to delete it */
90                         olddata->d_buf = NULL;
91
92
93                         shdr->sh_type = SHT_NOBITS;
94         }
95         }
96
97         /*      the section header table has moved up by offsetMovement
98                 this takes into account the size of the bss and the shifts
99                 we needed to perform for alignment purposes
100         */
101         ehdr->e_shoff -= offsetMovement;        
102
103         /* the data segment will be the second loadable section*/
104         bool foundFirstLoadable=false;
105         for(int i=0;i<ehdr->e_phnum;i++){
106                 if(!foundFirstLoadable && phdr[i].p_type == PT_LOAD){
107                         foundFirstLoadable=true;
108                 }else if(foundFirstLoadable == true && phdr[i].p_type == PT_LOAD ){
109                         
110                         phdr[i].p_filesz -= bssSize;
111                         i=ehdr->e_phnum;
112                 }
113         }
114         if( !foundFirstLoadable ){
115                 bperr(" FAILED could not find the data segment in the shared library\n");
116                 return false;
117         }
118         return true;
119 }
120
121 // vim:ts=5: