rebased to master after sw 3rd party completed
[dyninst.git] / dyninstAPI_RT / src / RTmutatedBinary_ELF.c
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  * 
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  * 
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  * 
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  * 
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  * 
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30
31 /* $Id: RTmutatedBinary_ELF.c,v 1.29 2007/07/11 17:58:24 ssuen Exp $ */
32
33 /* this file contains the code to restore the necessary
34    data for a mutated binary 
35  */
36
37 #include <stdlib.h>
38 #include "dyninstAPI_RT/h/dyninstAPI_RT.h"
39 #include <unistd.h>
40 #include  <fcntl.h>
41 #include <string.h>
42
43 #include <libelf.h>
44
45
46
47 #if defined(i386_unknown_linux2_0) \
48  || (defined(arch_power) && defined(os_linux)) \
49  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
50 #define __USE_GNU
51 #endif
52
53 #include <sys/mman.h>
54 #include <dlfcn.h>
55 #include <link.h> /* ccw 23 jan 2002 */
56 #include <limits.h>
57
58 #if defined(i386_unknown_linux2_0) \
59    || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
60 extern ElfW(Dyn) _DYNAMIC[];
61
62 #endif
63
64 /* Borrowed from Linux's link.h: Allows us to use functions from
65    libelf regardless of word size. */
66 //#define ELF_FUNC(type)      _ELF_FUNC (elf, __ELF_NATIVE_CLASS, type)
67 #define ELF_FUNC(type)      _ELF_FUNC (Elf, __ELF_NATIVE_CLASS, type)
68 #define _ELF_FUNC(e,w,t)    _ELF_FUNC_1 (e, w, _##t)
69 #define _ELF_FUNC_1(e,w,t)  e##w##t
70
71 typedef struct {
72       ElfW(Sword) d_tag;
73       union {
74           ElfW(Sword) d_val;
75           ElfW(Addr) d_ptr;
76       } d_un;
77   } __Elf_Dyn;
78
79 unsigned long checkAddr;
80 /*extern int isMutatedExec;
81 char *buffer;
82 */
83
84 struct link_map* map=NULL;
85
86 char *sharedLibraryInfo = NULL;
87 unsigned int originalInsnBkpt;
88 unsigned int addressBkpt;
89
90 /*      this is not misnamed.  In the future, this function will contain
91         code to patch the instrumentation of a shared library that has 
92         been loaded into a different place during a mutated binary run.
93
94         Now, it just exit()s, as you can see
95 */
96
97 void fixInstrumentation(char* soName, unsigned long currAddr, unsigned long oldAddr){
98         printf(" %s loaded at wrong address: 0x%lx (expected at 0x%lx) \n", soName, currAddr, oldAddr);
99         printf(" This is an unrecoverable error, the instrumentation will not");
100         printf("\n run correctly if shared libraries are loaded at a different address\n");
101         printf("\n Exiting.....\n");
102         fflush(stdout);
103         //while(1);
104         //exit(9);
105 }
106
107 /*      this function checks the shared library (soName) to see if it
108         is currently loaded (loadAddr) at the same place it was before (address).
109         If the shared library is not found in the list (sharedLibraryInfo) that
110         mean the shared library was *NOT* instrumented and can be loaded
111         anywhere
112 */
113 unsigned long checkSOLoadAddr(char *soName, unsigned long loadAddr){
114         unsigned long result=0, found = 0;
115         unsigned long address;
116         char *ptr = sharedLibraryInfo;
117         while(ptr &&  *ptr && !found ){
118                 /*fprintf(stderr," CHECKING FOR %s in %s\n", ptr, soName);*/
119
120                 if(strstr(soName, ptr) || strstr(ptr,soName)){
121                         found = 1;
122                         ptr += (strlen(ptr) +1);
123                         memcpy(&address, ptr, sizeof(unsigned long)); 
124                         /* previous line is done b/c of alignment issues on sparc*/
125                         if(loadAddr == address) {
126                                 result = 0;
127                         }else{
128                                 result = address;
129                         }       
130                 }
131
132                 ptr += (strlen(ptr) +1);
133                 ptr += sizeof(unsigned long);
134                 ptr += sizeof(unsigned long); /* for flag */
135
136
137         }
138         if(!found){
139                 result = 0;
140                 /*fprintf(stderr," NOT FOUND %s\n",soName);*/
141         }
142
143         /*fprintf(stderr," checkSOLoadAddr: %s %lx %lx\n", soName, loadAddr, result);*/
144         return result;
145 }
146
147
148 #if defined(i386_unknown_linux2_0) \
149  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
150 unsigned long loadAddr;
151 void (*dl_debug_state_func)(void);
152
153 void dyninst_dl_debug_state(){
154         asm("nop");
155         if(_r_debug.r_state == 1){
156         do {
157                         if(map->l_next){
158                                 map = map->l_next;
159                         }
160                         loadAddr = checkSOLoadAddr(map->l_name, (unsigned long)map->l_ld);/*l_addr*/
161                         if(loadAddr){
162                                 fixInstrumentation(map->l_name, (unsigned long)map->l_ld, loadAddr);/*l_addr*/
163                         }
164                 }while(map->l_next);
165
166         }
167
168         /* the following call is used to call
169          * _dl_debug_state to ensure correctness (if
170          * someone relies on it being called it is
171          * execuated after this function)
172          * The value stored in dl_debug_state_func is
173          * the address of the function _dl_debug_state
174          * and is set in checkElfFile
175          */
176         asm("nop");
177         asm("nop");
178         asm("nop");
179         (*dl_debug_state_func)();
180         asm("nop");
181
182 }
183
184 void hack_ld_linux_plt(unsigned long pltEntryAddr){ 
185 /* this is ugly.
186  * save the world needs to check each shared library
187  * that is loaded to ensure that it is loaded at the
188  * same base address it was loaded at when the mutator/mutatee
189  * pair ran.  
190  * So, we know dlopen calls _dl_debug_state per the r_debug
191  * interface to let the process know a shared library has changed
192  * state.
193  * with this function we change the Procedure Linkage Table (.plt)
194  * for ld-linux.so so that the entry that used to point to
195  * _dl_debug_state points to dyninst_dl_debug_state.
196  *
197  * dyninst_dl_debug_state then calls _dl_debug_state before
198  * exiting 
199  *
200  * dont try this at home
201  */
202         unsigned long mprotectAddr = pltEntryAddr - (pltEntryAddr % getpagesize());     
203         unsigned long newTarget = (unsigned long) &dyninst_dl_debug_state ;
204         
205         mprotect( (void*) mprotectAddr, pltEntryAddr - mprotectAddr + sizeof(long), 
206                                 PROT_READ|PROT_WRITE|PROT_EXEC);
207
208         memcpy( (void*) dl_debug_state_func, (void*) pltEntryAddr, sizeof(long)); 
209
210         memcpy( (void*) pltEntryAddr, &newTarget, sizeof(long));
211 }
212 #endif
213
214 unsigned (*Elf_version)(unsigned) = NULL;
215 Elf *(*Elf_begin)(int fildes, Elf_Cmd cmd, Elf *ref) = NULL;
216 Elf_Scn *(*Elf_getscn)(Elf *elf, size_t index) = NULL;
217 Elf_Data *(*Elf_getdata)(Elf_Scn *scn, Elf_Data *data) = NULL;
218 Elf_Scn *(*Elf_nextscn)(Elf *elf, Elf_Scn *scn) = NULL;
219 Elf32_Shdr *(*Elf32_getshdr)(Elf_Scn *scn) = NULL;
220 Elf32_Ehdr *(*Elf32_getehdr)(Elf *elf) = NULL;
221 Elf64_Shdr *(*Elf64_getshdr)(Elf_Scn *scn) = NULL;
222 Elf64_Ehdr *(*Elf64_getehdr)(Elf *elf) = NULL;
223 const char *(*Elf_errmsg)(int err) = NULL;
224 int (*Elf_errno)(void) = NULL;
225 int (*Elf_end)(Elf *elf) = NULL;
226
227
228 int checkSO(char* soName){
229         ElfW(Shdr) *shdr;
230         ElfW(Ehdr) *   ehdr;
231         Elf *          elf;
232         int       fd;
233         Elf_Data *strData;
234         Elf_Scn *scn;
235         int result = 0;
236
237         if((fd = (int) open(soName, O_RDONLY)) == -1){
238                 RTprintf("cannot open : %s\n",soName);
239                 fflush(stdout); 
240                 return result;
241         }
242         if((elf = Elf_begin(fd, ELF_C_READ, NULL)) ==NULL){
243                 RTprintf("%s %s \n",soName, Elf_errmsg(Elf_errno()));
244                 RTprintf("cannot elf_begin\n");
245                 fflush(stdout);
246                 close(fd);
247                 return result;
248         }
249
250         ehdr = ELF_FUNC( getehdr(elf) );
251         scn = Elf_getscn(elf, ehdr->e_shstrndx);
252         strData = Elf_getdata(scn,NULL);
253         for( scn = NULL; !result && (scn = Elf_nextscn(elf, scn)); ){
254                 shdr = ELF_FUNC( getshdr(scn) );
255                 if(!strcmp((char *)strData->d_buf + shdr->sh_name, ".dyninst_mutated")) {
256                         result = 1;
257                 }
258         }
259         Elf_end(elf);
260         close(fd);
261
262         return result;
263 }
264
265 int checkMutatedFile(){
266
267     /* Apparently a future section stomps on the tramp guard. Whoops. Instead,
268        we'll keep the address around and initialize the guard at the end. */
269     int *trampGuardBase_ = NULL;
270     int trampGuardSize_ = 0;
271
272         ElfW(Shdr) *shdr;
273         ElfW(Ehdr) *   ehdr;
274         Elf *          elf;
275         int       cnt,fd;
276         Elf_Data *elfData,*strData;
277         Elf_Scn *scn;
278         char *execStr;
279         int retVal = 0;
280         unsigned long mmapAddr;
281         int pageSize;
282         Address dataAddress;
283         int dataSize;
284         char* tmpPtr;
285         unsigned long updateAddress, updateSize, updateOffset;
286         unsigned long *dataPtr;
287         unsigned int numberUpdates,i ;
288         char* oldPageData;
289         Dl_info dlip;
290         int soError = 0; 
291
292      char * error_msg = NULL;
293      void * elfHandle = NULL;
294
295         //fprintf(stderr,"SBRK 0x%x\n",sbrk(1));;
296
297 //     elfHandle = dlopen("/usr/lib/libelf.so.1", RTLD_NOW);
298
299      elfHandle = dlopen("libelf.so", RTLD_NOW);
300      if(! elfHandle){
301         error_msg = dlerror();
302         if (error_msg) {
303           //fprintf(stderr,"Could not open lib: %s- %s\n","libelf",error_msg);
304         }
305         else{
306           //fprintf(stderr, "failure\n");
307         }
308         return 0;
309      }
310
311      Elf_version = (unsigned (*)(unsigned)) dlsym(elfHandle, "elf_version");
312      Elf_begin = (Elf *(*)(int,Elf_Cmd,Elf *)) dlsym(elfHandle, "elf_begin");
313      Elf_getscn = (Elf_Scn *(*)(Elf *, size_t)) dlsym(elfHandle, "elf_getscn");
314      Elf_nextscn = (Elf_Scn *(*)(Elf *, Elf_Scn *)) dlsym(elfHandle, "elf_nextscn");
315      Elf_getdata = (Elf_Data *(*)(Elf_Scn *, Elf_Data *)) dlsym(elfHandle, "elf_getdata");
316      Elf32_getehdr = (Elf32_Ehdr *(*)(Elf *)) dlsym(elfHandle, "elf32_getehdr");
317      Elf32_getshdr = (Elf32_Shdr *(*)(Elf_Scn *)) dlsym(elfHandle, "elf32_getshdr");
318      Elf64_getehdr = (Elf64_Ehdr *(*)(Elf *)) dlsym(elfHandle, "elf64_getehdr");
319      Elf64_getshdr = (Elf64_Shdr *(*)(Elf_Scn *)) dlsym(elfHandle, "elf64_getshdr");
320      Elf_errmsg = (const char *(*)(int)) dlsym(elfHandle, "elf_errmsg");
321      Elf_errno = (int (*)(void)) dlsym(elfHandle, "elf_errno");
322      Elf_end = (int (*)(Elf *)) dlsym(elfHandle, "elf_end");
323
324         Elf_version(EV_CURRENT);
325
326         execStr = (char*) malloc(1024);
327         memset(execStr,'\0',1024);
328
329 #if defined(i386_unknown_linux2_0) \
330    || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */ \
331    || (defined(os_linux) && defined(arch_power))
332         sprintf(execStr,"/proc/%d/exe",getpid());
333 #endif
334
335         if((fd = (int) open(execStr, O_RDONLY)) == -1){
336                 printf("cannot open : %s\n",execStr);
337                 fflush(stdout); 
338                 return retVal;
339         }
340         if((elf = Elf_begin(fd, ELF_C_READ, NULL)) ==NULL){
341                 printf("%s %s \n",execStr, Elf_errmsg( Elf_errno()));
342                 printf("cannot Elf_begin\n");
343                 fflush(stdout);
344                 close(fd);
345                 return retVal;
346         }
347
348         ehdr = ELF_FUNC( getehdr(elf) );
349         scn = Elf_getscn(elf, ehdr->e_shstrndx);
350         strData = Elf_getdata(scn,NULL);
351         pageSize =  getpagesize();
352
353         /*fprintf(stderr,"IN MUTATED FILE\n");*/
354         for(cnt = 0, scn = NULL; !soError &&  (scn = Elf_nextscn(elf, scn));cnt++){
355                 shdr = ELF_FUNC( getshdr(scn) );
356                 if(!strncmp((char *)strData->d_buf + shdr->sh_name, "dyninstAPItrampgu", 17)) {
357                         dataAddress = shdr->sh_addr;
358                         elfData = Elf_getdata(scn, NULL);
359                         tmpPtr = elfData->d_buf;
360                         //fprintf(stderr,"tramp guard addr %x, tmpPtr %p (%d)\n", dataAddress, tmpPtr, *tmpPtr);
361                         trampGuardBase_ = (int *)dataAddress;
362                         trampGuardSize_ = *(int *)tmpPtr;
363
364
365                         /*      we already own it. 
366         
367                                 because we have moved the start of the heap beyond this address
368                         */
369
370                         /* set tramp guard to 1 */
371                         for(i=0;i<*(int*)tmpPtr;i++){
372                             ((unsigned*) dataAddress)[i]=1;
373                         }
374                         /* This may get reverted, so we'll re-do the work below. */
375
376                 }else if(!strncmp((char *)strData->d_buf + shdr->sh_name, "dyninstAPI_data", 15)) {
377                         elfData = Elf_getdata(scn, NULL);
378                         tmpPtr = elfData->d_buf;
379                         dataAddress = -1;
380                         while( dataAddress != 0 ) { 
381                                 /*tmpPtr may not be aligned on the correct boundry
382                                 so use memcpy to set dataSize
383                                 dataSize = *(int*) tmpPtr;*/
384                                 memcpy((char*) & dataSize, tmpPtr, sizeof(int));
385
386                                 tmpPtr+=sizeof(int);
387                                 memcpy( (char*) & dataAddress, tmpPtr, sizeof(Address));
388
389                                 tmpPtr += sizeof(Address);
390                                 if(dataAddress){
391                                         memcpy((char*) dataAddress, tmpPtr, dataSize);
392
393                                         tmpPtr += dataSize;
394                                 }
395                         }
396
397                 }else if(!strncmp((char *)strData->d_buf + shdr->sh_name, "dyninstAPI_",11)){ 
398                         char *tmpStr = strchr((char *)strData->d_buf + shdr->sh_name, (int)'_'); ;
399
400                         tmpStr ++;
401
402                         if( *tmpStr>=0x30 && *tmpStr <= 0x39 ) {
403                                 /* we dont want to do this unless this is a dyninstAPI_### section
404                                         specifically, dont do this for dyninstAPI_SharedLibraries*/
405                                 retVal = 1; /* this is a restored run */
406
407                                 if( *tmpStr>=0x30 && *tmpStr <= 0x39 ) {
408                                         /* this is a heap tramp section */
409
410                                         /*      the new starting address of the heap is immediately AFTER the last
411                                                 dyninstAPI_### section, so we can ALWAYS memcpy the data into place
412                                                 see the value of newHeapAddr in writeBackElf.C
413                                         */
414                                         elfData = Elf_getdata(scn, NULL);
415                                         memcpy((void*)shdr->sh_addr, elfData->d_buf, shdr->sh_size);
416                                 }
417                         }
418                 }
419                 if(!strcmp((char *)strData->d_buf + shdr->sh_name, "dyninstAPI_mutatedSO")){
420                         /* make sure the mutated SOs are loaded, not the original ones */
421                         char *soNames;
422                         int mutatedFlag = 0;
423                         int totallen=0;
424 #if defined(i386_unknown_linux2_0) \
425    || (defined(arch_power) && defined(os_linux)) \
426    || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
427                         struct link_map *lmap=0;
428 #endif
429                         char *loadedname, *dyninstname;
430
431                         elfData = Elf_getdata(scn, NULL);
432
433                         sharedLibraryInfo = (char*) malloc(elfData->d_size);
434                         memcpy(sharedLibraryInfo, elfData->d_buf, elfData->d_size);
435                         lmap = _r_debug.r_map;
436
437                         for(soNames = (char*) elfData->d_buf ; totallen<elfData->d_size; 
438                                 soNames = &((char*) elfData->d_buf)[strlen(soNames)+1+sizeof(unsigned int) +sizeof(unsigned int)]){
439                                 /* added a +sizeof(unsigned int) above for flag */
440                                 totallen += strlen(soNames) + 1 + sizeof(unsigned int) +sizeof(unsigned int); /*for flag*/
441                                 memcpy(&mutatedFlag, &((char*) elfData->d_buf)[totallen-sizeof(unsigned int)], sizeof(unsigned int));
442                                 lmap = _r_debug.r_map;
443                                 while(lmap){
444                                         loadedname = strrchr(lmap->l_name,'/');
445                                         dyninstname =  strrchr((const char *)soNames,(int)'/');
446                                         if(loadedname == 0){
447                                                 loadedname = lmap->l_name;
448                                         }
449                                         if(dyninstname == 0){
450                                                 dyninstname = soNames;
451                                         }       
452                                         if(mutatedFlag && !strcmp(loadedname, dyninstname)) {
453                                                 if(!checkSO(lmap->l_name)){
454                         printf("ERROR: %s was mutated during saveworld and",lmap->l_name);
455                         printf(" the currently loaded %s has not been mutated\n", lmap->l_name);
456                         printf(" check your LD path to be sure the mutated %s is visible\n", soNames);
457                                                         soError = 1;
458                 
459                                                 }
460
461                 
462                                         }
463                                         lmap = lmap->l_next;
464                                 }
465                         }
466                 }
467                 if(!strcmp((char *)strData->d_buf + shdr->sh_name, "rtlib_addr")){
468                         unsigned int ptr;
469                         int done = 0;
470
471
472                         elfData = Elf_getdata(scn, NULL);
473
474                         /*ptr = elfData->d_buf;*/
475                         /* use memcpy because of alignment issues on sparc */   
476                         memcpy(&ptr,elfData->d_buf,sizeof(unsigned int));
477
478         
479                         map = _r_debug.r_map;
480
481                         while(map && !done){
482                                 /*fprintf(stderr,"CHECKING %s 0x%x\n", map->l_name,map->l_addr);*/
483                                 if( * map->l_name  && strstr(map->l_name, "libdyninstAPI_RT")){
484                                         unsigned long loadaddr = (unsigned long)map->l_addr;
485
486                                         /*      LINUX PROBLEM. in the link_map structure the map->l_addr field is NOT
487                                                 the load address of the dynamic object, as the documentation says.  It is the
488                                                 RELOCATED address of the object. If the object was not relocated then the
489                                                 value is ZERO.
490
491                                                 So, on LINUX we check the address of the dynamic section, map->l_ld, which is
492                                                 correct.
493                                         */
494 #if defined(i386_unknown_linux2_0) || defined(x86_64_unknown_linux2_4)
495                                         loadaddr = (unsigned long)map->l_ld;
496 #endif
497
498                                         /*fprintf(stderr," loadadd %x ptr %x\n", loadaddr, ptr);*/
499                                         if( loadaddr !=  (ptr)){
500                                                 fixInstrumentation(map->l_name, loadaddr,  (ptr));
501                                         }
502                                 }
503                                 /* check every loaded SO but leave map such that map->l_next == NULL.
504                                         The next time a SO is loaded it will be placed at 
505                                         map->l_next, so keep a tail pointer such that we 
506                                         dont need to loop through the entire list again
507                                 */
508                                 if(map->l_next){
509                                         map = map->l_next;
510                                 }else{
511                                         done = 1;
512                                 }
513                         }
514                 }
515                 if(!strcmp((char *)strData->d_buf + shdr->sh_name, "dyninstAPI_SharedLibraries")){
516                         unsigned long diffAddr;
517                         unsigned long ld_linuxBaseAddr;
518                         char *ptr;
519                         int done = 0;
520
521
522                         elfData = Elf_getdata(scn, NULL);
523
524                         ptr = elfData->d_buf;
525                 
526                         map = _r_debug.r_map;
527
528                         while(map && !done){
529                                 if( map->l_name && * map->l_name ){
530                                         unsigned int loadaddr = map->l_addr;
531
532                                         /*      LINUX PROBLEM. in the link_map structure the map->l_addr field is NOT
533                                                 the load address of the dynamic object, as the documentation says.  It is the
534                                                 RELOCATED address of the object. If the object was not relocated then the
535                                                 value is ZERO.
536
537                                                 So, on LINUX we check the address of the dynamic section, map->l_ld, which is
538                                                 correct.
539                                         */
540 #if defined(i386_unknown_linux2_0) || defined(x86_64_unknown_linux2_4)
541                                         loadaddr = (unsigned long)map->l_ld;
542 #endif
543
544                                         /*fprintf(stderr," CHECKING: %s %x\n",map->l_name, map->l_addr);*/
545                                         diffAddr = checkSOLoadAddr(map->l_name, loadaddr);
546                                         if(diffAddr){
547                                                 fixInstrumentation(map->l_name, loadaddr, diffAddr);
548                                         }
549 #if defined(i386_unknown_linux2_0) \
550  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
551                                         /* ld-linux.so will never be hand relocated so l_addr should be correct. right? */
552                                         if(strstr(map->l_name, "ld-linux.so")){
553                                                 ld_linuxBaseAddr = map->l_addr;
554                                         }       
555 #endif
556                                 }
557                                 /* check every loaded SO but leave map such that map->l_next == NULL.
558                                         The next time a SO is loaded it will be placed at 
559                                         map->l_next, so keep a tail pointer such that we 
560                                         dont need to loop through the entire list again
561                                 */
562                                 if(map->l_next){
563                                         map = map->l_next;
564                                 }else{
565                                         done = 1;
566                                 }
567                         }
568                         if( shdr->sh_addr != 0){
569                                 /* if the addr is zero, then there is 
570                                         no PLT entry for dlopen.  if there is
571                                         no entry for dlopen the mutatee must not
572                                         call it.  -- what about calling it from
573                                         a shared lib that is statically loaded?
574                                 */
575
576                         /* WHY IS THERE A POUND DEFINE HERE? 
577
578                                 well, we need to intercept the dlopen calls from the mutated binary
579                                 because our trampolines expect the shared libraries to be in
580                                 a particular location and if they are not where they are expected
581                                 our trampolines can jump off into nothingness, or even worse, some
582                                 random bit of executable code.  
583
584                                 So we must intercept the dlopen call and then check to be sure
585                                 the shared libraries are loaded in the same place as before.  If
586                                 they are not we exit with a message to the user saying this is
587                                 a fatal error.
588                 
589                                 Note, only shared libraries that have been instrumented are checked
590                                 here.  
591                         */
592
593 #if defined(i386_unknown_linux2_0) \
594    || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
595                         /* install jump to catch call to _dl_debug_state */
596                         /* see comment int hack_ld_linux_plt for explainations */
597                         hack_ld_linux_plt(ld_linuxBaseAddr + shdr->sh_addr); 
598 #endif
599                 }/* shdr->sh_addr != 0 */ 
600                 }
601                 if( !strncmp((char *)strData->d_buf + shdr->sh_name, "dyninstAPIhighmem_",18)){
602                         /*the layout of dyninstAPIhighmem_ is:
603                         pageData
604                         address of update
605                         size of update
606                         ...     
607                         address of update
608                         size of update  
609                         number of updates
610         
611                         we must ONLY overwrite the updates, the other
612                         areas of the page may be important (and different than
613                         the saved data in the file.  we first copy out the
614                         page, the apply the updates to it, and then
615                         write it back.
616                         */
617
618                         int oldPageDataSize;
619                         int count =0;
620
621                         retVal = 1; /* just to be sure */
622                         elfData = Elf_getdata(scn, NULL);
623                         numberUpdates = 0;
624                         
625                         /*this section may be padded out with zeros to align the next section
626                           so we need to look backwards until we find a nonzero value */
627                         while(numberUpdates == 0){
628                                 count++;
629                                 numberUpdates = (unsigned int) ( ((unsigned int*) elfData->d_buf)[
630                                         (elfData->d_size - (sizeof(unsigned int)*count))/ sizeof(unsigned int) ]);
631                         }
632
633                         /*fprintf(stderr," numberUpdates: %d :: (%d - 4) / 4  %x\n", numberUpdates, elfData->d_size, (unsigned int*) &elfData->d_buf );*/
634
635                         oldPageDataSize = shdr->sh_size-(((2*numberUpdates)* sizeof(unsigned int)) +((sizeof(unsigned int)*count))) ;
636
637
638                         oldPageData = (char*) malloc(oldPageDataSize+sizeof(unsigned long));
639                         /*fprintf(stderr,"oldpagedatasize %d datasize %d \n",oldPageDataSize,elfData->d_size);
640                         perror("malloc");*/
641                         /*copy old page data */
642
643
644                         /* probe memory to see if we own it */
645                         checkAddr = dladdr((void*)shdr->sh_addr, &dlip);
646
647
648                         updateSize  = shdr->sh_size-((2*numberUpdates)* (sizeof(unsigned int)) -(count* (sizeof(unsigned int))));
649                         /*fprintf(stderr," updateSize : %d-((2 * %d + 1) * 4))",shdr->sh_size, numberUpdates);*/
650         
651                         if(!checkAddr){ 
652                                 /* we dont own it,mmap it!*/
653
654                                 mmapAddr = shdr->sh_offset;
655                                 mmapAddr =(unsigned long) mmap((void*) shdr->sh_addr,oldPageDataSize,
656                                         PROT_READ|PROT_WRITE|PROT_EXEC,MAP_FIXED|MAP_PRIVATE,fd,mmapAddr);
657                                         /*fprintf(stderr,"MMAP %x %d %x size: %x\n",shdr->sh_addr, mmapAddr,shdr->sh_offset,oldPageDataSize);*/
658                                         
659
660                         }else{
661                                 /*we own it, finish the memcpy */
662                                 mmapAddr = (unsigned long) memcpy((void*) oldPageData, 
663                                       (const void*) shdr->sh_addr, oldPageDataSize);
664                                 /*fprintf(stderr,"memcpy %x %d\n",shdr->sh_addr, updateSize);*/
665
666                         }
667
668                         dataPtr =(unsigned long *) &(((char*)  elfData->d_buf)[oldPageDataSize]);       
669                         /*apply updates*/
670                         for(i = 0; i< numberUpdates; i++){
671                                 updateAddress = *dataPtr; 
672                                 updateSize = *(++dataPtr);
673
674                                 updateOffset = updateAddress - shdr->sh_addr;
675                                 /*do update*/   
676                                 /*fprintf(stderr,"updateAddress %x : %x %x %d %d\n",updateAddress,&( oldPageData[updateOffset]), &(((char*)elfData->d_buf)[updateOffset]) , updateSize,updateOffset);*/
677                                 memcpy(&( oldPageData[updateOffset]),
678                                                 &(((char*)elfData->d_buf)[updateOffset]) , updateSize); 
679
680                                 dataPtr ++;
681
682                         
683                         } 
684                         if(!checkAddr){
685                                 mmapAddr = shdr->sh_offset ;
686
687                                 mmapAddr =(unsigned long) mmap((void*) shdr->sh_addr,oldPageDataSize, 
688                                         PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED| MAP_PRIVATE,fd,mmapAddr);
689
690                                         /*fprintf(stderr,"2MMAP %x %d\n",shdr->sh_addr, mmapAddr);*/
691
692
693                         }else{
694
695                                 memcpy((void*) shdr->sh_addr, oldPageData,oldPageDataSize );
696                                 /*fprintf(stderr,"2memcpy %x %d\n",shdr->sh_addr, oldPageDataSize);*/
697
698                         }
699                 }
700                 if(!strcmp((char *)strData->d_buf + shdr->sh_name, "dyninstAPI_loadLib")){
701                         /* ccw 14 may 2002 */
702                         /* this section loads shared libraries into the mutated binary
703                                 that were loaded by BPatch_thread::loadLibrary */
704                         void * handle =NULL;
705                         elfData = Elf_getdata(scn, NULL);
706                         tmpPtr = elfData->d_buf;
707
708                         while(*tmpPtr) { 
709                                 handle = dlopen(tmpPtr, RTLD_LAZY);
710                                 if(handle){
711
712                                 }else{
713
714                                         printf(" %s cannot be loaded at the correct address\n", tmpPtr );
715                                         printf(" This is an unrecoverable error, the instrumentation will not");
716                                         printf("\n run correctly if shared libraries are loaded at a different address\n");
717                                         printf("\n Exiting.....\n");
718
719                                         printf("\n%s\n",dlerror());
720                                         fflush(stdout);
721                                         exit(9);
722
723                                 }
724                                 /* brk ptr not used for ELF */
725                                 tmpPtr += (strlen(tmpPtr) +1 + sizeof(void *)); 
726
727                         }
728
729                 }
730         }
731
732
733         Elf_end(elf);
734         close(fd);
735
736         free(execStr);
737
738         if(soError){
739                 exit(2);
740         }
741
742         for(i=0;i < trampGuardSize_; i++){
743             trampGuardBase_[i]=1;
744         }
745         
746         return retVal;
747 }
748 /* vim:set ts=5: */