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