Folks:
[dyninst.git] / dyninstAPI_RT / src / RTmutatedBinary.c
1 /* $Id: RTmutatedBinary.c,v 1.1 2002/04/15 21:48:43 chadd Exp $ */
2
3 /* this file contains the code to restore the necessary
4    data for a mutated binary 
5  */
6
7
8 #include "dyninstAPI_RT/h/dyninstAPI_RT.h"
9 #include <unistd.h>
10 #include  <fcntl.h>
11
12 #if defined(sparc_sun_solaris2_4)
13 #include  <libelf.h>
14 #elif defined(i386_unknown_linux2_0)
15 #include <libelf/libelf.h>
16 #define __USE_GNU
17 #endif
18
19 #include <sys/mman.h>
20 #include <dlfcn.h>
21 #include <link.h> /* ccw 23 jan 2002 */
22 #if defined(sparc_sun_solaris2_4) 
23 #include <sys/link.h>
24 #include <signal.h>
25 #endif
26 #include <limits.h>
27
28 #if defined(sparc_sun_solaris2_4)
29 extern void* _DYNAMIC;
30 #elif defined(i386_unknown_linux2_0)
31 extern ElfW(Dyn) _DYNAMIC[];
32
33 #endif
34 typedef struct {
35       Elf32_Sword d_tag;
36       union {
37           Elf32_Sword d_val;
38           Elf32_Addr d_ptr;
39       } d_un;
40   } __Elf32_Dyn;
41
42
43
44 unsigned int checkAddr;
45 int isElfFile=0;
46 char *buffer;
47 struct link_map* map;
48 unsigned int dl_debug_state_addr;
49
50 #if defined(sparc_sun_solaris2_4)
51 struct r_debug _r_debug; /* ccw 2 apr 2002 */
52 extern unsigned int _dyninst_call_to_dlopen;
53 extern unsigned int __dyninst_jump_template__;
54 extern unsigned int __dyninst_jump_template__done__;
55 #endif
56
57 char *sharedLibraryInfo = NULL;
58 unsigned int originalInsnBkpt;
59 unsigned int addressBkpt;
60
61 /*      this is not misnamed.  In the future, this function will contain
62         code to patch the instrumentation of a shared library that has 
63         been loaded into a different place during a mutated binary run.
64
65         Now, it just exit()s, as you can see
66 */
67
68 void fixInstrumentation(char* soName, unsigned int currAddr, unsigned int oldAddr){
69         printf(" %s loaded at wrong address: 0x%x (expected at 0x%x) \n", soName, currAddr, oldAddr);
70         printf(" This is an unrecoverable error, the instrumentation will not");
71         printf("\n run correctly if shared libraries are loaded at a different address\n");
72         printf("\n Exiting.....\n");
73         fflush(stdout);
74         exit(9);
75 }
76
77 /*      this function checks the shared library (soName) to see if it
78         is currently loaded (loadAddr) at the same place it was before (address).
79         If the shared library is not found in the list (sharedLibraryInfo) that
80         mean the shared library was *NOT* instrumented and can be loaded
81         anywhere
82 */
83 unsigned int checkSOLoadAddr(char *soName, unsigned int loadAddr){
84         unsigned int result=0, found = 0;
85         unsigned int address;
86         char *ptr = sharedLibraryInfo;
87         while(ptr &&  *ptr && !found ){
88                 if(strstr(soName, ptr)){
89                         found = 1;
90                         ptr += (strlen(ptr) +1);
91                         memcpy(&address, ptr, sizeof(unsigned int)); 
92                         /* previous line is done b/c of alignment issues on sparc*/
93                         if(loadAddr == address) {
94                                 result = 0;
95                         }else{
96                                 result = address;
97                         }       
98                 }
99
100                 ptr += (strlen(ptr) +1);
101                 ptr += sizeof(unsigned int);
102
103         }
104         if(!found){
105                 result = 0;
106         }
107         return result;
108 }
109 #if defined(sparc_sun_solaris2_4)
110 unsigned int register_o7;
111
112 unsigned int loadAddr;
113 /*      this function is not a signal handler. it was originally but now is 
114         not, it is called below in dyninst_jump_template
115 */ 
116 void pseudoSigHandler(int sig){
117
118         if(_r_debug.r_state == 0){
119                 do{
120                         if(map->l_next){
121                                 map = map->l_next;
122                         }
123                         loadAddr = checkSOLoadAddr(map->l_name, map->l_addr);
124                         if(loadAddr){
125                                 fixInstrumentation(map->l_name, map->l_addr, loadAddr);
126                         }
127
128                 }while(map->l_next);
129
130         }
131 }
132
133 unsigned int loadAddr;
134 void dyninst_jump_template(){
135 /* THE PLAN:
136
137         The Solaris loader/ELF file works as follows:
138         
139         A call to dlopen jumps to the Procedure Linking Table 
140         slot holding the dlopen information.  This slot consists of
141         three instructions:
142         
143         sethi r1, 0xb4
144         ba (to another PLT slot)
145         nop
146
147         The second PLT slot contains three instructions:
148         save
149         call (address of dlopen)
150         nop
151
152         dlopen returns directly to where it was called from, not to
153         either of the PLT slots.  The address from which it was called
154         is located in %o7 when the call to dlopen in the second PLT
155         slot is made. dlopen returns to %o7 +4.
156         
157
158         What our code does:
159
160         The goals is to intercept this call to dlopen by overwritting
161         the first PLT slot to jump to __dyninst_jump_template__ then we
162         can jump to code that will check the addresses of the loaded
163         shared libraries.
164
165         first we must preserver %o7 so we know where to go back to.
166         This is done with the first two instructions in __dyninst_jump_template__
167         These are written as nops BUT are overwritten in the SharedLibraries 
168         branch in checkElfFile.  %o7 is saved in register_o7 declared above.
169         This address is not available until run time so we generate these
170         instructions on the fly.
171
172         Next, we CALL the second PLT slot as normal.  We use the delay
173         slot to run the sethi instruction from the first PLT slot. These
174         instructions are generated at runtime. 
175
176         dlopen will eventually be called and will return to the nop after
177         the sethi.  Now we need to call our function to check the
178         shared library address.  This is pseudoSigHandler.  We must
179         preserve the data returned by dlopen so we do a save to
180         push the register onto the stack before we call our function.
181         We call our function, and then do a restore to retreive the 
182         saved information.
183
184         At __dyninst_jump_template__done__ we want to restore the
185         value in register_o7 to %o7 so when we do a retl we will
186         jump back to where the mutated binary originally called 
187         dlopen.
188         The sethi and ld instructions are generated on the fly just
189         as the first sethi and st pair that saved the value of %o7.
190         The retl used %o7 to jump back to the original place 
191         the mutatee called dlopen. We are done. Whew.
192
193         Note that I know the address of the first PLT slot because
194         the mutator found it and saved it in the mutated binary.
195         The address of the second PLT slot is determined by looking
196         at the instructions in the first PLT slot.
197 */
198         
199
200         asm("nop");
201         asm("__dyninst_jump_template__:");
202
203         asm("nop");     /*sethi hi(register_o7), %g1 GENERATED BELOW*/
204         asm("nop");     /*st %o7 GENERATED BELOW*/
205         asm("nop");     /*call plt GENERATED BELOW*/
206         asm("nop");     /*sethi r1, b4 GENERATED BELOW*/
207
208         asm("nop");
209         asm("save %sp, -104, %sp");
210         asm("nop");
211         pseudoSigHandler(0);
212         asm("nop");
213         asm("restore");
214         asm("nop");
215         asm("nop");
216         asm("__dyninst_jump_template__done__:");
217         asm("nop");     /*sethi hi(register_o7), %g1 GENERATED BELOW*/
218         asm("nop");     /* ld [register_o7], %o7 GENERATED BELOW*/
219         asm("retl");
220
221         asm("nop");     /* this will be filled in below */
222         asm("nop");
223
224 }
225
226 #endif
227
228 #if defined(i386_unknown_linux2_0)
229 unsigned int loadAddr;
230 void dyninst_dl_debug_state(){
231         asm("nop");
232         if(_r_debug.r_state == 1){
233         do {
234                         if(map->l_next){
235                                 map = map->l_next;
236                         }
237                         loadAddr = checkSOLoadAddr(map->l_name, map->l_addr);
238                         if(loadAddr){
239                                 fixInstrumentation(map->l_name, map->l_addr, loadAddr);
240                         }
241                 }while(map->l_next);
242
243         }
244
245         /* the following call is used to call
246          * _dl_debug_state to ensure correctness (if
247          * someone relies on it being called it is
248          * execuated after this function)
249          * The value stored in dl_debug_state_addr is
250          * the address of the function _dl_debug_state
251          * and is set in checkElfFile
252          */
253         asm("nop");
254         asm("nop");
255         asm("nop");
256         asm("call *dl_debug_state_addr");
257         asm("nop");
258
259 }
260
261 void hack_ld_linux_plt(unsigned int pltEntryAddr){ 
262 /* this is ugly.
263  * save the world needs to check each shared library
264  * that is loaded to ensure that it is loaded at the
265  * same base address it was loaded at when the mutator/mutatee
266  * pair ran.  
267  * So, we know dlopen calls _dl_debug_state per the r_debug
268  * interface to let the process know a shared library has changed
269  * state.
270  * with this function we change the Procedure Linkage Table (.plt)
271  * for ld-linux.so so that the entry that used to point to
272  * _dl_debug_state points to dyninst_dl_debug_state.
273  *
274  * dyninst_dl_debug_state then calls _dl_debug_state before
275  * exiting 
276  *
277  * dont try this at home
278  */
279         unsigned int mprotectAddr = pltEntryAddr - (pltEntryAddr % getpagesize());      
280         unsigned int newTarget = (unsigned int) &dyninst_dl_debug_state ;
281         
282         mprotect( (void*) mprotectAddr, pltEntryAddr - mprotectAddr + 4, 
283                                 PROT_READ|PROT_WRITE|PROT_EXEC);
284
285         memcpy( (void*) &dl_debug_state_addr, (void*) pltEntryAddr, 4); 
286
287         memcpy( (void*) pltEntryAddr, &newTarget, 4);
288 }
289 #endif
290
291
292 int checkSO(char* soName){
293         Elf32_Shdr *shdr;
294         Elf32_Ehdr *   ehdr;
295         Elf *          elf;
296         int       fd;
297         Elf_Data *strData;
298         Elf_Scn *scn;
299         int result = 0;
300
301         if((fd = (int) open(soName, O_RDONLY)) == -1){
302                 RTprintf("cannot open : %s\n",soName);
303                 fflush(stdout); 
304                 return;
305         }
306         if((elf = elf_begin(fd, ELF_C_READ, NULL)) ==NULL){
307                 RTprintf("%s %s \n",soName, elf_errmsg(elf_errno()));
308                 RTprintf("cannot elf_begin\n");
309                 fflush(stdout);
310                 close(fd);
311                 return;
312         }
313
314         ehdr = elf32_getehdr(elf);
315         scn = elf_getscn(elf, ehdr->e_shstrndx);
316         strData = elf_getdata(scn,NULL);
317         for( scn = NULL; !result && (scn = elf_nextscn(elf, scn)); ){
318                 shdr = elf32_getshdr(scn);
319                 if(!strcmp((char *)strData->d_buf + shdr->sh_name, ".dyninst_mutated")) {
320                         result = 1;
321                 }
322         }
323         elf_end(elf);
324         close(fd);
325
326         return result;
327 }
328
329 int checkElfFile(){
330
331
332         Elf32_Shdr *shdr;
333         Elf32_Ehdr *   ehdr;
334         Elf *          elf;
335         int       cnt,fd;
336         Elf_Data *elfData,*strData;
337         Elf_Scn *scn;
338         char execStr[256];
339         int retVal = 0, result;
340         unsigned int mmapAddr;
341         int pageSize;
342         Address dataAddress;
343         int dataSize;
344         char* tmpPtr;
345         unsigned int updateAddress, updateSize, updateOffset;
346         unsigned int *dataPtr;
347         unsigned int numberUpdates,i ;
348         char* oldPageData;
349         Dl_info dlip;
350         int soError = 0; 
351         int sawFirstHeapTrampSection = 0;
352         elf_version(EV_CURRENT);
353
354 #if defined(sparc_sun_solaris2_4)
355         sprintf(execStr,"/proc/%d/object/a.out",getpid());
356 #elif defined(i386_unknown_linux2_0)
357         sprintf(execStr,"/proc/%d/exe",getpid());
358 #endif
359
360         if((fd = (int) open(execStr, O_RDONLY)) == -1){
361                 printf("cannot open : %s\n",execStr);
362                 fflush(stdout); 
363                 return;
364         }
365         if((elf = elf_begin(fd, ELF_C_READ, NULL)) ==NULL){
366                 printf("%s %s \n",execStr, elf_errmsg(elf_errno()));
367                 printf("cannot elf_begin\n");
368                 fflush(stdout);
369                 close(fd);
370                 return;
371         }
372
373         ehdr = elf32_getehdr(elf);
374         scn = elf_getscn(elf, ehdr->e_shstrndx);
375         strData = elf_getdata(scn,NULL);
376         pageSize =  getpagesize();
377         for(cnt = 0, scn = NULL; !soError &&  (scn = elf_nextscn(elf, scn));cnt++){
378                 shdr = elf32_getshdr(scn);
379                 if(!strncmp((char *)strData->d_buf + shdr->sh_name, "dyninstAPI_data", 15)) {
380                         elfData = elf_getdata(scn, NULL);
381                         tmpPtr = elfData->d_buf;
382                         dataAddress = -1;
383                         while( dataAddress != 0 ) { 
384                                 dataSize = *(int*) tmpPtr;
385                                 tmpPtr+=sizeof(int);
386                                 dataAddress = *(Address*) tmpPtr;
387                                 tmpPtr += sizeof(Address);
388                                 if(dataAddress){
389                                         memcpy((char*) dataAddress, tmpPtr, dataSize);
390                                         tmpPtr += dataSize;
391                                 }
392                         }
393
394                 }else if(!strncmp((char *)strData->d_buf + shdr->sh_name, "dyninstAPI_",11)){
395                         char *tmpStr;
396 #if defined(sparc_sun_solaris2_4)
397                         /* solaris does not make _r_debug available by
398                                 default, we have to find it in the 
399                                 _DYNAMIC table */
400
401                         __Elf32_Dyn *_dyn = (__Elf32_Dyn*)& _DYNAMIC;   
402
403                         while(_dyn && _dyn->d_tag != 0 && _dyn->d_tag != 21){
404                                 _dyn ++;
405                         }
406                         if(_dyn && _dyn->d_tag != 0){
407                                 _r_debug = *(struct r_debug*) _dyn->d_un.d_ptr;
408                         }
409                         map = _r_debug.r_map;
410
411 #endif
412                         retVal = 1; /* this is a restored run */
413                         tmpStr = strchr((char *)strData->d_buf + shdr->sh_name,'_'); 
414                         tmpStr ++;
415                         if( *tmpStr>=0x30 && *tmpStr <= 0x39 ) {
416                                 /* this is a heap tramp section */
417                                 if( sawFirstHeapTrampSection ){
418                                         result = mmap((void*) shdr->sh_addr, shdr->sh_size, 
419                                         PROT_READ|PROT_WRITE|PROT_EXEC,
420                                         MAP_FIXED|MAP_PRIVATE,fd,shdr->sh_offset);
421                                 }else{
422                                         elfData = elf_getdata(scn, NULL);
423                                         memcpy((void*)shdr->sh_addr, elfData->d_buf, shdr->sh_size);
424                                         sawFirstHeapTrampSection = 1;
425                                 }
426                         }
427                 }
428                 if(!strcmp((char *)strData->d_buf + shdr->sh_name, "dyninstAPI_mutatedSO")){
429                         /* make sure the mutated SOs are loaded, not the original ones */
430                         char *soNames;
431                         int totallen=0;
432                         __Elf32_Dyn *_dyn = (__Elf32_Dyn*)& _DYNAMIC;   
433 #if defined(sparc_sun_solaris2_4)
434                         Link_map *lmap=0;
435 #elif defined(i386_unknown_linux2_0)
436                         struct link_map *lmap=0;
437 #endif
438                         char *loadedname, *dyninstname;
439
440                         elfData = elf_getdata(scn, NULL);
441
442                         sharedLibraryInfo = (char*) malloc(elfData->d_size);
443                         memcpy(sharedLibraryInfo, elfData->d_buf, elfData->d_size);
444                         lmap = _r_debug.r_map;
445                 
446                         for(soNames = (char*) elfData->d_buf ; totallen<elfData->d_size; 
447                                 soNames = &((char*) elfData->d_buf)[strlen(soNames)+1+sizeof(unsigned int)] ){
448                                 totallen += strlen(soNames) + 1 + sizeof(unsigned int);
449                                 lmap = _r_debug.r_map;
450                                 while(lmap){
451                                         loadedname = strrchr(lmap->l_name,'/');
452                                         dyninstname =  strrchr(soNames,'/');
453                                         if(loadedname == 0){
454                                                 loadedname = lmap->l_name;
455                                         }
456                                         if(dyninstname == 0){
457                                                 dyninstname = soNames;
458                                         }       
459                                         if(!strcmp(loadedname, dyninstname)) {
460                                                 if(!checkSO(lmap->l_name)){
461                         printf("ERROR: %s was mutated during saveworld and",lmap->l_name);
462                         printf(" the currently loaded %s has not been mutated\n", lmap->l_name);
463                         printf(" check your LD path to be sure the mutated %s is visible\n", soNames);
464                                                         soError = 1;
465                 
466                                                 }
467
468                 
469                                         }
470                                         lmap = lmap->l_next;
471                                 }
472                         }
473                 }
474                 if(!strcmp((char *)strData->d_buf + shdr->sh_name, "dyninstAPI_SharedLibraries")){
475                         unsigned int diffAddr;
476                         unsigned int ld_linuxBaseAddr, baseAddr, size;
477 #if defined(sparc_sun_solaris2_4)
478                         unsigned int *overWriteInsn;
479                         unsigned int *pltEntry, *PLTEntry, *dyninst_jump_templatePtr, pltInsn;
480                         unsigned int BA_MASK = 0x003fffff;
481                         unsigned int offset, callInsn;
482                         struct sigaction  mysigact, oldsigact;
483 #endif
484                         char *ptr;
485                         int foundLib = 0, result;
486                         int done = 0;
487                         elfData = elf_getdata(scn, NULL);
488
489                         ptr = elfData->d_buf;
490                 
491                         map = _r_debug.r_map;
492
493                         while(map && !done){
494                                 if( * map->l_name ){
495                                         diffAddr = checkSOLoadAddr(map->l_name, map->l_addr);
496                                         if(diffAddr){
497                                                 fixInstrumentation(map->l_name, map->l_addr, diffAddr);
498                                         }
499 #if defined(i386_unknown_linux2_0)
500                                         if(strstr(map->l_name, "ld-linux.so")){
501                                                 ld_linuxBaseAddr =map->l_addr;
502                                         }       
503 #endif
504                                 }
505                                 /* check every loaded SO but leave map such that map->l_next == NULL.
506                                         The next time a SO is loaded it will be placed at 
507                                         map->l_next, so keep a tail pointer such that we 
508                                         dont need to loop through the entire list again
509                                 */
510                                 if(map->l_next){
511                                         map = map->l_next;
512                                 }else{
513                                         done = 1;
514                                 }
515                         }
516
517                         /* WHY IS THERE A POUND DEFINE HERE? 
518                                 
519                                 well, we need to intercept the dlopen calls from the mutated binary
520                                 because our trampolines expect the shared libraries to be in
521                                 a particular location and if they are not where they are expected
522                                 our trampolines can jump off into nothingness, or even worse, some
523                                 random bit of executable code.  
524
525                                 So we must intercept the dlopen call and then check to be sure
526                                 the shared libraries are loaded in the same place as before.  If
527                                 they are not we exit with a message to the user saying this is
528                                 a fatal error.
529                 
530                                 Note, only shared libraries that have been instrumented are checked
531                                 here.  
532                         */
533
534 #if defined(sparc_sun_solaris2_4)
535                         /* 
536                                 For a description of what is going on here read
537                                 the comment in dyninst_jump_template above.
538
539                                 This code generated all the instructions refered
540                                 to in that comment as "GENERATED BELOW".
541
542                         */
543                         pltEntry = (unsigned int*) shdr->sh_addr;
544                         pltInsn = *pltEntry; /* save insn for later */
545                         pltEntry += 1;
546                         offset = (*pltEntry) & BA_MASK;
547                         if(offset & 0x00200000){
548                                 /* negative so sign extend */
549                                 offset = 0xffc00000 | offset;
550                         }
551                         PLTEntry = pltEntry;
552                         
553                         PLTEntry += (offset*4)/sizeof(PLTEntry); /* move PLTEntry offset*4 bytes!*/
554                         dyninst_jump_templatePtr = (unsigned int*) & __dyninst_jump_template__;
555
556                         baseAddr = ((unsigned int) dyninst_jump_templatePtr)  -
557                                 ( ((unsigned int) dyninst_jump_templatePtr)% getpagesize());
558                         size =  (unsigned int) dyninst_jump_templatePtr  - baseAddr + 80;
559                         result = mprotect(baseAddr , size, PROT_READ|PROT_WRITE|PROT_EXEC);
560
561                         /* build sethi hi(register_o7), %g1 */
562                         *dyninst_jump_templatePtr = 0x03000000;
563                         *dyninst_jump_templatePtr |= ( (((unsigned int ) & register_o7)& 0xffffe000) >> 10);
564
565                         dyninst_jump_templatePtr ++;
566
567                         /* build st %o7, &register_o7 */
568                         *dyninst_jump_templatePtr = 0xde206000;
569                         *dyninst_jump_templatePtr |=  ( ((unsigned int ) & register_o7) & 0x00001fff );
570
571                         dyninst_jump_templatePtr ++;
572
573                         /* build call PLTEntry */
574                         *dyninst_jump_templatePtr = 0x40000000;
575                         *dyninst_jump_templatePtr |= ( ((unsigned int) (PLTEntry)-  ((unsigned int) dyninst_jump_templatePtr)) >>2);
576                         
577                         dyninst_jump_templatePtr ++;
578
579                         /* copy from plt */
580                         *dyninst_jump_templatePtr = pltInsn;
581                         dyninst_jump_templatePtr ++;
582
583
584                         /* advance past call to pseudoSigHandler */
585                         dyninst_jump_templatePtr = (unsigned int) &__dyninst_jump_template__done__ ;
586         
587                         /* build sethi hi(register_o7), %g1 */
588                         *dyninst_jump_templatePtr = 0x03000000;
589                         *dyninst_jump_templatePtr |= ( (((unsigned int ) & register_o7)& 0xffffe000) >> 10);
590
591                         dyninst_jump_templatePtr ++;
592
593                         /* build ld %o7, register_o7 */
594                         *dyninst_jump_templatePtr = 0xde006000;
595                         *dyninst_jump_templatePtr |=  ( ((unsigned int ) & register_o7) & 0x00001fff );
596
597
598                         /* THIS ENABLES THE JUMP */
599                         /* edit plt to jump to __dyninst_jump_template__ */
600                         baseAddr = ((unsigned int) pltEntry)  -
601                                 ( ((unsigned int) pltEntry)% getpagesize());
602                         size =  (unsigned int) pltEntry  - baseAddr + 8;
603                         result = mprotect(baseAddr , size, PROT_READ|PROT_WRITE|PROT_EXEC);
604
605                         /* build sethi hi(&__dyninst_jump_template__), %g1 */
606                         pltEntry --;
607
608                         *pltEntry = 0x03000000;
609                         *pltEntry |= ( (((unsigned int ) &__dyninst_jump_template__) )>> 10);
610                         pltEntry ++;
611         
612                         /* build jmpl %g1, %r0 */       
613                         *pltEntry = 0x81c06000;
614                         *pltEntry |=  ( ((unsigned int ) &__dyninst_jump_template__ ) & 0x00003ff );
615
616 #elif defined(i386_unknown_linux2_0)
617                         /* install jump to catch call to _dl_debug_state */
618                         /* see comment int hack_ld_linux_plt for explainations */
619                         hack_ld_linux_plt(ld_linuxBaseAddr + shdr->sh_addr); 
620 #endif
621                 }
622                 if(!strncmp((char *)strData->d_buf + shdr->sh_name, "dyninstAPIhighmem_",18)){
623                         /*the layout of dyninstAPIhighmem_ is:
624                         pageData
625                         address of update
626                         size of update
627                         ...     
628                         address of update
629                         size of update  
630                         number of updates
631         
632                         we must ONLY overwrite the updates, the other
633                         areas of the page may be important (and different than
634                         the saved data in the file.  we first copy out the
635                         page, the apply the updates to it, and then
636                         write it back.
637                         */
638
639                         int oldPageDataSize;
640                         retVal = 1; /* just to be sure */
641                         elfData = elf_getdata(scn, NULL);
642                         numberUpdates = (unsigned int) ( ((unsigned int*) elfData->d_buf)[
643                                 (elfData->d_size - sizeof(unsigned int))/ sizeof(unsigned int) ]);
644                         oldPageDataSize = shdr->sh_size-((2*numberUpdates+1)*
645                                 sizeof(unsigned int)) ;
646                         oldPageData = (char*) malloc(oldPageDataSize);
647                         /*copy old page data */
648
649                         /* probe memory to see if we own it */
650                         checkAddr = dladdr((void*)shdr->sh_addr, &dlip); 
651
652                         updateSize  = shdr->sh_size-((2*numberUpdates+1)* sizeof(unsigned int));
653                 
654                         if(!checkAddr){ 
655                                 /* we dont own it,mmap it!*/
656
657                                 mmapAddr = shdr->sh_offset;
658                                 mmapAddr =(unsigned int) mmap((void*) shdr->sh_addr,oldPageDataSize,
659                                         PROT_READ|PROT_WRITE|PROT_EXEC,MAP_FIXED|MAP_PRIVATE,fd,mmapAddr);
660                         }else{
661                                 /*we own it, finish the memcpy */
662                                 mmapAddr = memcpy(oldPageData, (void*) shdr->sh_addr, updateSize);
663
664                         }
665         
666                         dataPtr =(unsigned int*) &(((char*)  elfData->d_buf)[oldPageDataSize]); 
667                         /*apply updates*/
668                         for(i = 0; i< numberUpdates; i++){
669                                 updateAddress = *dataPtr; 
670                                 updateSize = *(++dataPtr);
671
672                                 updateOffset = updateAddress - shdr->sh_addr;
673                                 /*do update*/   
674                                 memcpy(&( oldPageData[updateOffset]),
675                                                 &(((char*)elfData->d_buf)[updateOffset]) , updateSize); 
676                                 dataPtr ++;
677                         } 
678                         if(!checkAddr){
679                                 mmapAddr = shdr->sh_offset ;
680                                 mmapAddr =(unsigned int) mmap((void*) shdr->sh_addr,oldPageDataSize, 
681                                         PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED| MAP_PRIVATE,fd,mmapAddr);
682
683                         }else{
684                                 memcpy((void*) shdr->sh_addr, oldPageData,oldPageDataSize );
685
686                         }
687                 }
688
689         }
690
691
692         elf_end(elf);
693         close(fd);
694
695         if(soError){
696                 exit(2);
697         }
698         return retVal;
699 }
700
701
702 /* with solaris, the mutatee has a jump from
703  * main() to a trampoline that calls DYNINSTinit() the
704  * trampoline resides in the area that was previously
705  * the heap, this trampoline is loaded as part of the
706  * data segment
707  * UPDATE: now the heap tramps are not loaded by the loader
708  * but rather this file so _init is necessary
709  * UPDATE: gcc handles the _init fine, but
710  * cc chokes on it.  There seems to be no compiler
711  * independent way to have my code called correctly
712  * at load time so i have defined _NATIVESO_ in
713  * the sparc Makefile for cc only.  The #pragma
714  * forces the my_init function to be called 
715  * correctly upon load of the library.
716  * Building with gcc is the same as before. 
717  * THIS NEEDS TO BE FIXED 
718  * 
719  * with linux the trampolines are ALL in the big
720  * array at the top of this file and so are not loaded
721  * by the loader as part of the data segment. this
722  * needs to be called to map in everything before
723  * main() jumps to the big array
724  */ 
725
726 #if defined(_NATIVESO_)
727
728 #pragma init (my_init) 
729 void my_init(){
730 #else 
731 void _init(){
732
733 #endif
734
735 /* this buffer is allocated to clear
736    the first page on the heap. This is necessary
737    because loading the heap tramps uses mmap, which
738    is going to eat the heap if the heap begins on 
739    the same page the heap tramps end on (almost certain)
740 */
741         buffer = (char*) malloc(getpagesize());
742         isElfFile =checkElfFile();
743         free(buffer);
744 }