Update copyright to LGPL on all files
[dyninst.git] / dyninstAPI_RT / src / RTmutatedBinary_ELF.c
1 /*
2  * Copyright (c) 1996-2009 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31
32 /* $Id: RTmutatedBinary_ELF.c,v 1.29 2007/07/11 17:58:24 ssuen Exp $ */
33
34 /* this file contains the code to restore the necessary
35    data for a mutated binary 
36  */
37
38 #include <stdlib.h>
39 #include "dyninstAPI_RT/h/dyninstAPI_RT.h"
40 #include <unistd.h>
41 #include  <fcntl.h>
42 #include <string.h>
43
44 #include <libelf.h>
45
46
47
48 #if defined(sparc_sun_solaris2_4)
49 #include <procfs.h> /* ccw 12 mar 2004*/
50 #include <sys/types.h>
51 #include <sys/stat.h>
52 #endif
53
54
55
56 #if defined(i386_unknown_linux2_0) \
57  || (defined(arch_power) && defined(os_linux)) \
58  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
59 #define __USE_GNU
60 #endif
61
62 #include <sys/mman.h>
63 #include <dlfcn.h>
64 #include <link.h> /* ccw 23 jan 2002 */
65 #if defined(sparc_sun_solaris2_4) 
66
67 #include <sys/link.h>
68 #include <signal.h>
69 #endif
70 #include <limits.h>
71
72 #if defined(sparc_sun_solaris2_4)
73 extern void* _DYNAMIC;
74
75 #if defined(__arch64__)
76 #define __ELF_NATIVE_CLASS 64
77 #else
78 #define __ELF_NATIVE_CLASS 32
79 #endif
80
81 /* Borrowed from Linux's link.h:  Allows us to use data types
82    from libelf regardless of word size. */
83 #define ElfW(type)      _ElfW (Elf, __ELF_NATIVE_CLASS, type)
84 #define _ElfW(e,w,t)    _ElfW_1 (e, w, _##t)
85 #define _ElfW_1(e,w,t)  e##w##t
86
87
88 #elif defined(i386_unknown_linux2_0) \
89    || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
90 extern ElfW(Dyn) _DYNAMIC[];
91
92 #endif
93
94 /* Borrowed from Linux's link.h: Allows us to use functions from
95    libelf regardless of word size. */
96 //#define ELF_FUNC(type)      _ELF_FUNC (elf, __ELF_NATIVE_CLASS, type)
97 #define ELF_FUNC(type)      _ELF_FUNC (Elf, __ELF_NATIVE_CLASS, type)
98 #define _ELF_FUNC(e,w,t)    _ELF_FUNC_1 (e, w, _##t)
99 #define _ELF_FUNC_1(e,w,t)  e##w##t
100
101 typedef struct {
102       ElfW(Sword) d_tag;
103       union {
104           ElfW(Sword) d_val;
105           ElfW(Addr) d_ptr;
106       } d_un;
107   } __Elf_Dyn;
108
109 unsigned long checkAddr;
110 /*extern int isMutatedExec;
111 char *buffer;
112 */
113
114 struct link_map* map=NULL;
115
116 #if defined(sparc_sun_solaris2_4)
117
118 prmap_t *procMemMap=NULL;/* ccw 2 apr 2002 */
119 int procMemMapSize=0;
120
121 struct r_debug _r_debug; /* ccw 2 apr 2002 */
122 int r_debug_is_set = 0; 
123 extern unsigned int _dyninst_call_to_dlopen;
124 extern unsigned int __dyninst_jump_template__;
125 extern unsigned int __dyninst_jump_template__done__;
126 #endif
127
128 char *sharedLibraryInfo = NULL;
129 unsigned int originalInsnBkpt;
130 unsigned int addressBkpt;
131
132 #if defined(sparc_sun_solaris2_4)
133 /*      To help the RT shared lib to reload in the same location for the
134         mutated binaries we now use dldump to dump the rt lib back to the
135         directory that contains the mutated binary.  The LD_LIBRARY_PATH
136         MUST be set to find this new rt lib ONLY when running the mutated
137         binary.
138 */
139 extern char gLoadLibraryErrorString[ERROR_STRING_LENGTH];
140
141 int DYNINSTsaveRtSharedLibrary(char *rtSharedLibName, char *newName){
142
143         char *err_str;
144         gLoadLibraryErrorString[0]='\0';
145
146         /*fprintf(stderr," DLDUMP(%s,%s)\n",  rtSharedLibName, newName);*/
147
148         /* dldump returns 0 on success */
149         if ( dldump(rtSharedLibName, newName, RTLD_REL_RELATIVE) ) { 
150                 /* An error has occurred */
151                 perror( "DYNINSTsaveRtSharedLibrary -- dldump" );
152     
153                 if (NULL != (err_str = dlerror())){
154                         strncpy(gLoadLibraryErrorString, err_str, ERROR_STRING_LENGTH);
155                 }else{ 
156                         sprintf(gLoadLibraryErrorString,"unknown error with dldump");
157                 }
158     
159                 /*fprintf(stderr, "%s[%d]: %s\n",__FILE__,__LINE__,gLoadLibraryErrorString);*/
160                 return 0;  
161         } else{
162                 return 1;
163         }
164 }
165 #endif
166 /*      this is not misnamed.  In the future, this function will contain
167         code to patch the instrumentation of a shared library that has 
168         been loaded into a different place during a mutated binary run.
169
170         Now, it just exit()s, as you can see
171 */
172
173 void fixInstrumentation(char* soName, unsigned long currAddr, unsigned long oldAddr){
174         printf(" %s loaded at wrong address: 0x%lx (expected at 0x%lx) \n", soName, currAddr, oldAddr);
175         printf(" This is an unrecoverable error, the instrumentation will not");
176         printf("\n run correctly if shared libraries are loaded at a different address\n");
177         printf("\n Exiting.....\n");
178         fflush(stdout);
179         //while(1);
180         //exit(9);
181 }
182
183 /*      this function checks the shared library (soName) to see if it
184         is currently loaded (loadAddr) at the same place it was before (address).
185         If the shared library is not found in the list (sharedLibraryInfo) that
186         mean the shared library was *NOT* instrumented and can be loaded
187         anywhere
188 */
189 unsigned long checkSOLoadAddr(char *soName, unsigned long loadAddr){
190         unsigned long result=0, found = 0;
191         unsigned long address;
192         char *ptr = sharedLibraryInfo;
193         while(ptr &&  *ptr && !found ){
194                 /*fprintf(stderr," CHECKING FOR %s in %s\n", ptr, soName);*/
195
196                 if(strstr(soName, ptr) || strstr(ptr,soName)){
197                         found = 1;
198                         ptr += (strlen(ptr) +1);
199                         memcpy(&address, ptr, sizeof(unsigned long)); 
200                         /* previous line is done b/c of alignment issues on sparc*/
201                         if(loadAddr == address) {
202                                 result = 0;
203                         }else{
204                                 result = address;
205                         }       
206                 }
207
208                 ptr += (strlen(ptr) +1);
209                 ptr += sizeof(unsigned long);
210                 ptr += sizeof(unsigned long); /* for flag */
211
212
213         }
214         if(!found){
215                 result = 0;
216                 /*fprintf(stderr," NOT FOUND %s\n",soName);*/
217         }
218
219         /*fprintf(stderr," checkSOLoadAddr: %s %lx %lx\n", soName, loadAddr, result);*/
220         return result;
221 }
222 #if defined(sparc_sun_solaris2_4)
223 unsigned int register_o7;
224
225 unsigned long loadAddr;
226 /*      this function is not a signal handler. it was originally but now is 
227         not, it is called below in dyninst_jump_template
228 */ 
229 void pseudoSigHandler(int sig){
230
231         map = _r_debug.r_map; /* ccw 22 jul 2003*/
232         if(_r_debug.r_state == 0){
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
242                 }while(map->l_next);
243
244         }
245
246 }
247
248 void dyninst_jump_template(){
249 /* THE PLAN:
250
251         The Solaris loader/ELF file works as follows:
252         
253         A call to dlopen jumps to the Procedure Linking Table 
254         slot holding the dlopen information.  This slot consists of
255         three instructions:
256         
257         sethi r1, 0xb4
258         ba (to another PLT slot)
259         nop
260
261         The second PLT slot contains three instructions:
262         save
263         call (address of dlopen)
264         nop
265
266         dlopen returns directly to where it was called from, not to
267         either of the PLT slots.  The address from which it was called
268         is located in %o7 when the call to dlopen in the second PLT
269         slot is made. dlopen returns to %o7 +4.
270         
271
272         What our code does:
273
274         The goals is to intercept this call to dlopen by overwritting
275         the first PLT slot to jump to __dyninst_jump_template__ then we
276         can jump to code that will check the addresses of the loaded
277         shared libraries.
278
279         first we must preserver %o7 so we know where to go back to.
280         This is done with the first two instructions in __dyninst_jump_template__
281         These are written as nops BUT are overwritten in the SharedLibraries 
282         branch in checkElfFile.  %o7 is saved in register_o7 declared above.
283         This address is not available until run time so we generate these
284         instructions on the fly.
285
286         Next, we CALL the second PLT slot as normal.  We use the delay
287         slot to run the sethi instruction from the first PLT slot. These
288         instructions are generated at runtime. 
289
290         dlopen will eventually be called and will return to the nop after
291         the sethi.  Now we need to call our function to check the
292         shared library address.  This is pseudoSigHandler.  We must
293         preserve the data returned by dlopen so we do a save to
294         push the register onto the stack before we call our function.
295         We call our function, and then do a restore to retreive the 
296         saved information.
297
298         At __dyninst_jump_template__done__ we want to restore the
299         value in register_o7 to %o7 so when we do a retl we will
300         jump back to where the mutated binary originally called 
301         dlopen.
302         The sethi and ld instructions are generated on the fly just
303         as the first sethi and st pair that saved the value of %o7.
304         The retl used %o7 to jump back to the original place 
305         the mutatee called dlopen. We are done. Whew.
306
307         Note that I know the address of the first PLT slot because
308         the mutator found it and saved it in the mutated binary.
309         The address of the second PLT slot is determined by looking
310         at the instructions in the first PLT slot.
311 */
312         
313
314         asm("nop");
315         asm("__dyninst_jump_template__:");
316
317         asm("nop");     /*sethi hi(register_o7), %g1 GENERATED BELOW*/
318         asm("nop");     /*st %o7 GENERATED BELOW*/
319
320         asm("nop");     /*call/jmp plt GENERATED BELOW*/
321         asm("nop");    /*sethi r1, b4 GENERATED BELOW*/
322
323         asm("nop");
324         asm("save %sp, -104, %sp");
325         asm("nop");
326         pseudoSigHandler(0);
327         asm("nop");
328         asm("restore");
329         asm("nop");
330         asm("nop");
331         asm("__dyninst_jump_template__done__:");
332         asm("nop");     /*sethi hi(register_o7), %g1 GENERATED BELOW*/
333         asm("nop");     /* ld [register_o7], %o7 GENERATED BELOW*/
334         asm("retl");
335
336         asm("nop");     /* this will be filled in below */
337         asm("nop");
338
339 }
340
341 #endif
342
343 #if defined (sparc_sun_solaris2_4)
344 void findMap(){ /* ccw 12 mar 2004*/
345
346         Dl_info dlip;
347         int me = getpid();
348         char fileName[1024];
349         prmap_t mapEntry;
350         int fd;
351         int index = 0;
352         int offset = 0;
353         struct stat statInfo;
354
355         sprintf(fileName, "/proc/%d/map", me);
356         
357         stat(fileName, &statInfo);
358         if( procMemMap ) {
359                 free(procMemMap);
360         }
361         procMemMap = (prmap_t*) malloc(statInfo.st_size);
362
363         fd = open(fileName, O_RDONLY);
364
365         while( pread(fd, (void*)& (procMemMap[index]), sizeof(mapEntry), offset) ){
366                 offset += sizeof(prmap_t);
367                 index++;
368         }
369         close(fd);
370         procMemMapSize = index;
371
372 }
373
374 long checkMap(unsigned long addr){
375         int index=0;
376
377         findMap();      
378         while(index < procMemMapSize){
379                 if( procMemMap[index].pr_vaddr <= addr && (procMemMap[index].pr_vaddr + (unsigned int)procMemMap[index].pr_size) > addr){
380                         return 1;
381                 }
382                 index++;
383         }
384         return 0;
385 }
386 #endif
387
388 #if defined(i386_unknown_linux2_0) \
389  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
390 unsigned long loadAddr;
391 void (*dl_debug_state_func)(void);
392
393 void dyninst_dl_debug_state(){
394         asm("nop");
395         if(_r_debug.r_state == 1){
396         do {
397                         if(map->l_next){
398                                 map = map->l_next;
399                         }
400                         loadAddr = checkSOLoadAddr(map->l_name, (unsigned long)map->l_ld);/*l_addr*/
401                         if(loadAddr){
402                                 fixInstrumentation(map->l_name, (unsigned long)map->l_ld, loadAddr);/*l_addr*/
403                         }
404                 }while(map->l_next);
405
406         }
407
408         /* the following call is used to call
409          * _dl_debug_state to ensure correctness (if
410          * someone relies on it being called it is
411          * execuated after this function)
412          * The value stored in dl_debug_state_func is
413          * the address of the function _dl_debug_state
414          * and is set in checkElfFile
415          */
416         asm("nop");
417         asm("nop");
418         asm("nop");
419         (*dl_debug_state_func)();
420         asm("nop");
421
422 }
423
424 void hack_ld_linux_plt(unsigned long pltEntryAddr){ 
425 /* this is ugly.
426  * save the world needs to check each shared library
427  * that is loaded to ensure that it is loaded at the
428  * same base address it was loaded at when the mutator/mutatee
429  * pair ran.  
430  * So, we know dlopen calls _dl_debug_state per the r_debug
431  * interface to let the process know a shared library has changed
432  * state.
433  * with this function we change the Procedure Linkage Table (.plt)
434  * for ld-linux.so so that the entry that used to point to
435  * _dl_debug_state points to dyninst_dl_debug_state.
436  *
437  * dyninst_dl_debug_state then calls _dl_debug_state before
438  * exiting 
439  *
440  * dont try this at home
441  */
442         unsigned long mprotectAddr = pltEntryAddr - (pltEntryAddr % getpagesize());     
443         unsigned long newTarget = (unsigned long) &dyninst_dl_debug_state ;
444         
445         mprotect( (void*) mprotectAddr, pltEntryAddr - mprotectAddr + sizeof(long), 
446                                 PROT_READ|PROT_WRITE|PROT_EXEC);
447
448         memcpy( (void*) dl_debug_state_func, (void*) pltEntryAddr, sizeof(long)); 
449
450         memcpy( (void*) pltEntryAddr, &newTarget, sizeof(long));
451 }
452 #endif
453
454 unsigned (*Elf_version)(unsigned) = NULL;
455 Elf *(*Elf_begin)(int fildes, Elf_Cmd cmd, Elf *ref) = NULL;
456 Elf_Scn *(*Elf_getscn)(Elf *elf, size_t index) = NULL;
457 Elf_Data *(*Elf_getdata)(Elf_Scn *scn, Elf_Data *data) = NULL;
458 Elf_Scn *(*Elf_nextscn)(Elf *elf, Elf_Scn *scn) = NULL;
459 Elf32_Shdr *(*Elf32_getshdr)(Elf_Scn *scn) = NULL;
460 Elf32_Ehdr *(*Elf32_getehdr)(Elf *elf) = NULL;
461 Elf64_Shdr *(*Elf64_getshdr)(Elf_Scn *scn) = NULL;
462 Elf64_Ehdr *(*Elf64_getehdr)(Elf *elf) = NULL;
463 const char *(*Elf_errmsg)(int err) = NULL;
464 int (*Elf_errno)(void) = NULL;
465 int (*Elf_end)(Elf *elf) = NULL;
466
467
468 int checkSO(char* soName){
469         ElfW(Shdr) *shdr;
470         ElfW(Ehdr) *   ehdr;
471         Elf *          elf;
472         int       fd;
473         Elf_Data *strData;
474         Elf_Scn *scn;
475         int result = 0;
476
477         if((fd = (int) open(soName, O_RDONLY)) == -1){
478                 RTprintf("cannot open : %s\n",soName);
479                 fflush(stdout); 
480                 return result;
481         }
482         if((elf = Elf_begin(fd, ELF_C_READ, NULL)) ==NULL){
483                 RTprintf("%s %s \n",soName, Elf_errmsg(Elf_errno()));
484                 RTprintf("cannot elf_begin\n");
485                 fflush(stdout);
486                 close(fd);
487                 return result;
488         }
489
490         ehdr = ELF_FUNC( getehdr(elf) );
491         scn = Elf_getscn(elf, ehdr->e_shstrndx);
492         strData = Elf_getdata(scn,NULL);
493         for( scn = NULL; !result && (scn = Elf_nextscn(elf, scn)); ){
494                 shdr = ELF_FUNC( getshdr(scn) );
495                 if(!strcmp((char *)strData->d_buf + shdr->sh_name, ".dyninst_mutated")) {
496                         result = 1;
497                 }
498         }
499         Elf_end(elf);
500         close(fd);
501
502         return result;
503 }
504
505 int checkMutatedFile(){
506
507     /* Apparently a future section stomps on the tramp guard. Whoops. Instead,
508        we'll keep the address around and initialize the guard at the end. */
509     int *trampGuardBase_ = NULL;
510     int trampGuardSize_ = 0;
511
512         ElfW(Shdr) *shdr;
513         ElfW(Ehdr) *   ehdr;
514         Elf *          elf;
515         int       cnt,fd;
516         Elf_Data *elfData,*strData;
517         Elf_Scn *scn;
518         char *execStr;
519         int retVal = 0;
520         unsigned long mmapAddr;
521         int pageSize;
522         Address dataAddress;
523         int dataSize;
524         char* tmpPtr;
525         unsigned long updateAddress, updateSize, updateOffset;
526         unsigned long *dataPtr;
527         unsigned int numberUpdates,i ;
528         char* oldPageData;
529         Dl_info dlip;
530         int soError = 0; 
531
532      char * error_msg = NULL;
533      void * elfHandle = NULL;
534
535         //fprintf(stderr,"SBRK 0x%x\n",sbrk(1));;
536
537 //     elfHandle = dlopen("/usr/lib/libelf.so.1", RTLD_NOW);
538
539      elfHandle = dlopen("libelf.so", RTLD_NOW);
540      if(! elfHandle){
541         error_msg = dlerror();
542         if (error_msg) {
543           //fprintf(stderr,"Could not open lib: %s- %s\n","libelf",error_msg);
544         }
545         else{
546           //fprintf(stderr, "failure\n");
547         }
548         return 0;
549      }
550
551      Elf_version = (unsigned (*)(unsigned)) dlsym(elfHandle, "elf_version");
552      Elf_begin = (Elf *(*)(int,Elf_Cmd,Elf *)) dlsym(elfHandle, "elf_begin");
553      Elf_getscn = (Elf_Scn *(*)(Elf *, size_t)) dlsym(elfHandle, "elf_getscn");
554      Elf_nextscn = (Elf_Scn *(*)(Elf *, Elf_Scn *)) dlsym(elfHandle, "elf_nextscn");
555      Elf_getdata = (Elf_Data *(*)(Elf_Scn *, Elf_Data *)) dlsym(elfHandle, "elf_getdata");
556      Elf32_getehdr = (Elf32_Ehdr *(*)(Elf *)) dlsym(elfHandle, "elf32_getehdr");
557      Elf32_getshdr = (Elf32_Shdr *(*)(Elf_Scn *)) dlsym(elfHandle, "elf32_getshdr");
558      Elf64_getehdr = (Elf64_Ehdr *(*)(Elf *)) dlsym(elfHandle, "elf64_getehdr");
559      Elf64_getshdr = (Elf64_Shdr *(*)(Elf_Scn *)) dlsym(elfHandle, "elf64_getshdr");
560      Elf_errmsg = (const char *(*)(int)) dlsym(elfHandle, "elf_errmsg");
561      Elf_errno = (int (*)(void)) dlsym(elfHandle, "elf_errno");
562      Elf_end = (int (*)(Elf *)) dlsym(elfHandle, "elf_end");
563
564         Elf_version(EV_CURRENT);
565
566         execStr = (char*) malloc(1024);
567         memset(execStr,'\0',1024);
568
569 #if defined(sparc_sun_solaris2_4)
570         sprintf(execStr,"/proc/%d/object/a.out",getpid());
571 #elif defined(i386_unknown_linux2_0) \
572    || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */ \
573    || (defined(os_linux) && defined(arch_power))
574         sprintf(execStr,"/proc/%d/exe",getpid());
575 #endif
576
577         if((fd = (int) open(execStr, O_RDONLY)) == -1){
578                 printf("cannot open : %s\n",execStr);
579                 fflush(stdout); 
580                 return retVal;
581         }
582         if((elf = Elf_begin(fd, ELF_C_READ, NULL)) ==NULL){
583                 printf("%s %s \n",execStr, Elf_errmsg( Elf_errno()));
584                 printf("cannot Elf_begin\n");
585                 fflush(stdout);
586                 close(fd);
587                 return retVal;
588         }
589
590         ehdr = ELF_FUNC( getehdr(elf) );
591         scn = Elf_getscn(elf, ehdr->e_shstrndx);
592         strData = Elf_getdata(scn,NULL);
593         pageSize =  getpagesize();
594
595         /*fprintf(stderr,"IN MUTATED FILE\n");*/
596         for(cnt = 0, scn = NULL; !soError &&  (scn = Elf_nextscn(elf, scn));cnt++){
597                 shdr = ELF_FUNC( getshdr(scn) );
598                 if(!strncmp((char *)strData->d_buf + shdr->sh_name, "dyninstAPItrampgu", 17)) {
599                         dataAddress = shdr->sh_addr;
600                         elfData = Elf_getdata(scn, NULL);
601                         tmpPtr = elfData->d_buf;
602                         //fprintf(stderr,"tramp guard addr %x, tmpPtr %p (%d)\n", dataAddress, tmpPtr, *tmpPtr);
603                         trampGuardBase_ = (int *)dataAddress;
604                         trampGuardSize_ = *(int *)tmpPtr;
605
606
607                         /*      we already own it. 
608         
609                                 because we have moved the start of the heap beyond this address
610                         */
611
612                         /* set tramp guard to 1 */
613                         for(i=0;i<*(int*)tmpPtr;i++){
614                             ((unsigned*) dataAddress)[i]=1;
615                         }
616                         /* This may get reverted, so we'll re-do the work below. */
617
618                 }else if(!strncmp((char *)strData->d_buf + shdr->sh_name, "dyninstAPI_data", 15)) {
619                         elfData = Elf_getdata(scn, NULL);
620                         tmpPtr = elfData->d_buf;
621                         dataAddress = -1;
622                         while( dataAddress != 0 ) { 
623                                 /*tmpPtr may not be aligned on the correct boundry
624                                 so use memcpy to set dataSize
625                                 dataSize = *(int*) tmpPtr;*/
626                                 memcpy((char*) & dataSize, tmpPtr, sizeof(int));
627
628                                 tmpPtr+=sizeof(int);
629                                 memcpy( (char*) & dataAddress, tmpPtr, sizeof(Address));
630
631                                 tmpPtr += sizeof(Address);
632                                 if(dataAddress){
633                                         memcpy((char*) dataAddress, tmpPtr, dataSize);
634
635                                         tmpPtr += dataSize;
636                                 }
637                         }
638
639                 }else if(!strncmp((char *)strData->d_buf + shdr->sh_name, "dyninstAPI_",11)){ 
640                         char *tmpStr = strchr((char *)strData->d_buf + shdr->sh_name, (int)'_'); ;
641
642                         tmpStr ++;
643
644 #if defined(sparc_sun_solaris2_4)
645                         if( r_debug_is_set == 0 ) { 
646                                 /* this moved up incase there is no dyninstAPI_### section, map and
647                                 _r_debug are still set correctly. */
648                                 /* solaris does not make _r_debug available by
649                                 default, we have to find it in the _DYNAMIC table */
650
651                                 __Elf_Dyn *_dyn = (__Elf_Dyn*)& _DYNAMIC;       
652                                 while(_dyn && _dyn->d_tag != 0 && _dyn->d_tag != 21){
653                                         _dyn ++;
654                                 }
655                                 if(_dyn && _dyn->d_tag != 0){
656                                         _r_debug = *(struct r_debug*) _dyn->d_un.d_ptr;
657                                 }
658                                 map = _r_debug.r_map;
659                                 r_debug_is_set = 1;
660                         }else{
661                                 map = _r_debug.r_map;
662                         }
663
664 #endif
665                         if( *tmpStr>=0x30 && *tmpStr <= 0x39 ) {
666                                 /* we dont want to do this unless this is a dyninstAPI_### section
667                                         specifically, dont do this for dyninstAPI_SharedLibraries*/
668                                 retVal = 1; /* this is a restored run */
669
670                                 if( *tmpStr>=0x30 && *tmpStr <= 0x39 ) {
671                                         /* this is a heap tramp section */
672
673                                         /*      the new starting address of the heap is immediately AFTER the last
674                                                 dyninstAPI_### section, so we can ALWAYS memcpy the data into place
675                                                 see the value of newHeapAddr in writeBackElf.C
676                                         */
677                                         elfData = Elf_getdata(scn, NULL);
678                                         memcpy((void*)shdr->sh_addr, elfData->d_buf, shdr->sh_size);
679                                 }
680                         }
681                 }
682                 if(!strcmp((char *)strData->d_buf + shdr->sh_name, "dyninstAPI_mutatedSO")){
683                         /* make sure the mutated SOs are loaded, not the original ones */
684                         char *soNames;
685                         int mutatedFlag = 0;
686                         int totallen=0;
687 #if defined(sparc_sun_solaris2_4)
688                         Link_map *lmap=0;
689 #elif defined(i386_unknown_linux2_0) \
690    || (defined(arch_power) && defined(os_linux)) \
691    || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
692                         struct link_map *lmap=0;
693 #endif
694                         char *loadedname, *dyninstname;
695
696                         elfData = Elf_getdata(scn, NULL);
697
698                         sharedLibraryInfo = (char*) malloc(elfData->d_size);
699                         memcpy(sharedLibraryInfo, elfData->d_buf, elfData->d_size);
700                         lmap = _r_debug.r_map;
701
702                         for(soNames = (char*) elfData->d_buf ; totallen<elfData->d_size; 
703                                 soNames = &((char*) elfData->d_buf)[strlen(soNames)+1+sizeof(unsigned int) +sizeof(unsigned int)]){
704                                 /* added a +sizeof(unsigned int) above for flag */
705                                 totallen += strlen(soNames) + 1 + sizeof(unsigned int) +sizeof(unsigned int); /*for flag*/
706                                 memcpy(&mutatedFlag, &((char*) elfData->d_buf)[totallen-sizeof(unsigned int)], sizeof(unsigned int));
707                                 lmap = _r_debug.r_map;
708                                 while(lmap){
709                                         loadedname = strrchr(lmap->l_name,'/');
710                                         dyninstname =  strrchr((const char *)soNames,(int)'/');
711                                         if(loadedname == 0){
712                                                 loadedname = lmap->l_name;
713                                         }
714                                         if(dyninstname == 0){
715                                                 dyninstname = soNames;
716                                         }       
717                                         if(mutatedFlag && !strcmp(loadedname, dyninstname)) {
718                                                 if(!checkSO(lmap->l_name)){
719                         printf("ERROR: %s was mutated during saveworld and",lmap->l_name);
720                         printf(" the currently loaded %s has not been mutated\n", lmap->l_name);
721                         printf(" check your LD path to be sure the mutated %s is visible\n", soNames);
722                                                         soError = 1;
723                 
724                                                 }
725
726                 
727                                         }
728                                         lmap = lmap->l_next;
729                                 }
730                         }
731                 }
732                 if(!strcmp((char *)strData->d_buf + shdr->sh_name, "rtlib_addr")){
733                         unsigned int ptr;
734                         int done = 0;
735
736
737                         elfData = Elf_getdata(scn, NULL);
738
739                         /*ptr = elfData->d_buf;*/
740                         /* use memcpy because of alignment issues on sparc */   
741                         memcpy(&ptr,elfData->d_buf,sizeof(unsigned int));
742
743 #if defined(sparc_sun_solaris2_4)
744                         if( r_debug_is_set == 0 ) {
745                                 /* this moved up incase there is no dyninstAPI_### section, map and
746                                         _r_debug are still set correctly. */
747                                 /* solaris does not make _r_debug available by
748                                         default, we have to find it in the _DYNAMIC table */
749
750                                 __Elf_Dyn *_dyn = (__Elf_Dyn*)& _DYNAMIC;
751                                 while(_dyn && _dyn->d_tag != 0 && _dyn->d_tag != 21){
752                                         _dyn ++;
753                                 }
754                                 if(_dyn && _dyn->d_tag != 0){
755                                         _r_debug = *(struct r_debug*) _dyn->d_un.d_ptr;
756                                 }
757                                 map = _r_debug.r_map;
758                                 r_debug_is_set = 1;
759                         }else{
760                                 map = _r_debug.r_map;
761                         }
762 #endif
763         
764                         map = _r_debug.r_map;
765
766                         while(map && !done){
767                                 /*fprintf(stderr,"CHECKING %s 0x%x\n", map->l_name,map->l_addr);*/
768                                 if( * map->l_name  && strstr(map->l_name, "libdyninstAPI_RT")){
769                                         unsigned long loadaddr = (unsigned long)map->l_addr;
770
771                                         /*      LINUX PROBLEM. in the link_map structure the map->l_addr field is NOT
772                                                 the load address of the dynamic object, as the documentation says.  It is the
773                                                 RELOCATED address of the object. If the object was not relocated then the
774                                                 value is ZERO.
775
776                                                 So, on LINUX we check the address of the dynamic section, map->l_ld, which is
777                                                 correct.
778                                         */
779 #if defined(i386_unknown_linux2_0) || defined(x86_64_unknown_linux2_4)
780                                         loadaddr = (unsigned long)map->l_ld;
781 #endif
782
783                                         /*fprintf(stderr," loadadd %x ptr %x\n", loadaddr, ptr);*/
784                                         if( loadaddr !=  (ptr)){
785                                                 fixInstrumentation(map->l_name, loadaddr,  (ptr));
786                                         }
787                                 }
788                                 /* check every loaded SO but leave map such that map->l_next == NULL.
789                                         The next time a SO is loaded it will be placed at 
790                                         map->l_next, so keep a tail pointer such that we 
791                                         dont need to loop through the entire list again
792                                 */
793                                 if(map->l_next){
794                                         map = map->l_next;
795                                 }else{
796                                         done = 1;
797                                 }
798                         }
799                 }
800                 if(!strcmp((char *)strData->d_buf + shdr->sh_name, "dyninstAPI_SharedLibraries")){
801                         unsigned long diffAddr;
802                         unsigned long ld_linuxBaseAddr;
803 #if defined(sparc_sun_solaris2_4)
804                         unsigned long baseAddr, size;
805                         unsigned int *overWriteInsn;
806                         unsigned int *pltEntry, *PLTEntry, *dyninst_jump_templatePtr, pltInsn, tmpAddr;
807                         unsigned int BA_MASK=0x30800000;
808                         unsigned int BA_IMM=0x003fffff;
809                         unsigned int SETHI_IMM=0x003fffff;
810                         unsigned int JMP_IMM =0x00001fff;
811                         unsigned int offset, callInsn;
812                         struct sigaction  mysigact, oldsigact;
813                         int result;
814 #endif
815                         char *ptr;
816                         int done = 0;
817
818
819                         elfData = Elf_getdata(scn, NULL);
820
821                         ptr = elfData->d_buf;
822                 
823                         map = _r_debug.r_map;
824
825                         while(map && !done){
826                                 if( map->l_name && * map->l_name ){
827                                         unsigned int loadaddr = map->l_addr;
828
829                                         /*      LINUX PROBLEM. in the link_map structure the map->l_addr field is NOT
830                                                 the load address of the dynamic object, as the documentation says.  It is the
831                                                 RELOCATED address of the object. If the object was not relocated then the
832                                                 value is ZERO.
833
834                                                 So, on LINUX we check the address of the dynamic section, map->l_ld, which is
835                                                 correct.
836                                         */
837 #if defined(i386_unknown_linux2_0) || defined(x86_64_unknown_linux2_4)
838                                         loadaddr = (unsigned long)map->l_ld;
839 #endif
840
841                                         /*fprintf(stderr," CHECKING: %s %x\n",map->l_name, map->l_addr);*/
842                                         diffAddr = checkSOLoadAddr(map->l_name, loadaddr);
843                                         if(diffAddr){
844                                                 fixInstrumentation(map->l_name, loadaddr, diffAddr);
845                                         }
846 #if defined(i386_unknown_linux2_0) \
847  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
848                                         /* ld-linux.so will never be hand relocated so l_addr should be correct. right? */
849                                         if(strstr(map->l_name, "ld-linux.so")){
850                                                 ld_linuxBaseAddr = map->l_addr;
851                                         }       
852 #endif
853                                 }
854                                 /* check every loaded SO but leave map such that map->l_next == NULL.
855                                         The next time a SO is loaded it will be placed at 
856                                         map->l_next, so keep a tail pointer such that we 
857                                         dont need to loop through the entire list again
858                                 */
859                                 if(map->l_next){
860                                         map = map->l_next;
861                                 }else{
862                                         done = 1;
863                                 }
864                         }
865                         if( shdr->sh_addr != 0){
866                                 /* if the addr is zero, then there is 
867                                         no PLT entry for dlopen.  if there is
868                                         no entry for dlopen the mutatee must not
869                                         call it.  -- what about calling it from
870                                         a shared lib that is statically loaded?
871                                 */
872
873                         /* WHY IS THERE A POUND DEFINE HERE? 
874
875                                 well, we need to intercept the dlopen calls from the mutated binary
876                                 because our trampolines expect the shared libraries to be in
877                                 a particular location and if they are not where they are expected
878                                 our trampolines can jump off into nothingness, or even worse, some
879                                 random bit of executable code.  
880
881                                 So we must intercept the dlopen call and then check to be sure
882                                 the shared libraries are loaded in the same place as before.  If
883                                 they are not we exit with a message to the user saying this is
884                                 a fatal error.
885                 
886                                 Note, only shared libraries that have been instrumented are checked
887                                 here.  
888                         */
889
890 #if defined(sparc_sun_solaris2_4) 
891                         /* 
892                                 For a description of what is going on here read
893                                 the comment in dyninst_jump_template above.
894
895                                 This code generated all the instructions refered
896                                 to in that comment as "GENERATED BELOW".
897
898                         */
899
900                         pltEntry = (unsigned int*) shdr->sh_addr;
901                         pltInsn = *pltEntry; /* save insn for later */
902                         pltEntry += 1;
903
904                         /* The PLT entry may look like:
905                                 sethi
906                                 ba,a
907                                 nop
908
909                            or
910                         
911                                 sethi
912                                 sethi
913                                 jmp
914
915                         */
916                         if( (*pltEntry & (BA_MASK)) == (BA_MASK) ){
917                                 /* we have the sethi/ba,a/nop type */
918
919                                 offset = (*pltEntry) & BA_IMM;
920                                 if(offset & 0x00200000){
921                                         /* negative so sign extend */
922                                         offset = 0xffc00000 | offset;
923                                 }
924                                 PLTEntry = pltEntry;
925                         
926                                 PLTEntry += (offset*4)/sizeof(PLTEntry); /* move PLTEntry offset*4 bytes!*/
927
928                         }else{
929                                 /* we have the sethi/sethi/jmp type */
930                                 tmpAddr = ((*pltEntry) & SETHI_IMM)<<10;
931                                 pltEntry ++;
932                                 tmpAddr += ((*pltEntry) & JMP_IMM);
933                                 PLTEntry = (unsigned int *) tmpAddr;
934                                 pltEntry --;
935                         }
936
937                         dyninst_jump_templatePtr = (unsigned int*) & __dyninst_jump_template__;
938
939                         baseAddr = ((unsigned int) dyninst_jump_templatePtr)  -
940                                 ( ((unsigned int) dyninst_jump_templatePtr)% getpagesize());
941                         size =  (unsigned int) dyninst_jump_templatePtr  - baseAddr + 80;
942                         result = mprotect((void*)baseAddr , size, 
943                            PROT_READ|PROT_WRITE|PROT_EXEC);
944
945                         /* build sethi hi(register_o7), %g1 */
946                         *dyninst_jump_templatePtr = 0x03000000;
947                         *dyninst_jump_templatePtr |= ( (((unsigned int ) & register_o7)& 0xfffffc00) >> 10); /*0xffffe000 */
948
949                         dyninst_jump_templatePtr ++;
950
951                         /* build st %o7, &register_o7 */
952                         *dyninst_jump_templatePtr = 0xde206000;
953                         *dyninst_jump_templatePtr |=  ( ((unsigned int ) & register_o7) & 0x000003ff ); /*0x00001fff*/
954
955                         dyninst_jump_templatePtr ++;
956
957                         /* build call PLTEntry */
958                         *dyninst_jump_templatePtr = 0x40000000;
959                         *dyninst_jump_templatePtr |= ( ((unsigned int) (PLTEntry)-  ((unsigned int) dyninst_jump_templatePtr)) >>2);
960                         dyninst_jump_templatePtr ++;
961
962                         /* copy from plt */
963                         *dyninst_jump_templatePtr = pltInsn;
964                         dyninst_jump_templatePtr ++;
965
966
967                         /* advance past call to pseudoSigHandler */
968                         dyninst_jump_templatePtr = (unsigned int*) &__dyninst_jump_template__done__ ;
969         
970                         /* build sethi hi(register_o7), %g1 */
971                         *dyninst_jump_templatePtr = 0x03000000;
972                         *dyninst_jump_templatePtr |= ( (((unsigned int ) & register_o7)& 0xfffffc00) >> 10); /*0xffffe000*/
973
974                         dyninst_jump_templatePtr ++;
975
976                         /* build ld %o7, register_o7 */
977                         *dyninst_jump_templatePtr = 0xde006000;
978                         *dyninst_jump_templatePtr |=  ( ((unsigned int ) & register_o7) & 0x000003ff );  /*0x00001fff*/
979
980
981                         /* THIS ENABLES THE JUMP */
982                         /* edit plt to jump to __dyninst_jump_template__ */
983                         baseAddr = ((unsigned int) pltEntry)  -
984                                 ( ((unsigned int) pltEntry)% getpagesize());
985                         size =  (unsigned int) pltEntry  - baseAddr + 8;
986                         result = mprotect((void*)baseAddr , size,
987                            PROT_READ|PROT_WRITE|PROT_EXEC);
988
989                         /* build sethi hi(&__dyninst_jump_template__), %g1 */
990                         pltEntry --;
991                         *pltEntry = 0x03000000;
992                         *pltEntry |= ( (((unsigned int ) &__dyninst_jump_template__) )>> 10);
993                         pltEntry ++;
994         
995                         /* build jmpl %g1, %r0 */       
996                         *pltEntry = 0x81c06000;
997                         *pltEntry |=  ( ((unsigned int ) &__dyninst_jump_template__ ) & 0x00003ff );
998
999                         pltEntry ++;
1000                         *pltEntry = 0x01000000;
1001 #elif defined(i386_unknown_linux2_0) \
1002    || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
1003                         /* install jump to catch call to _dl_debug_state */
1004                         /* see comment int hack_ld_linux_plt for explainations */
1005                         hack_ld_linux_plt(ld_linuxBaseAddr + shdr->sh_addr); 
1006 #endif
1007                 }/* shdr->sh_addr != 0 */ 
1008                 }
1009                 if( !strncmp((char *)strData->d_buf + shdr->sh_name, "dyninstAPIhighmem_",18)){
1010                         /*the layout of dyninstAPIhighmem_ is:
1011                         pageData
1012                         address of update
1013                         size of update
1014                         ...     
1015                         address of update
1016                         size of update  
1017                         number of updates
1018         
1019                         we must ONLY overwrite the updates, the other
1020                         areas of the page may be important (and different than
1021                         the saved data in the file.  we first copy out the
1022                         page, the apply the updates to it, and then
1023                         write it back.
1024                         */
1025
1026                         int oldPageDataSize;
1027                         int count =0;
1028
1029                         retVal = 1; /* just to be sure */
1030                         elfData = Elf_getdata(scn, NULL);
1031                         numberUpdates = 0;
1032                         
1033                         /*this section may be padded out with zeros to align the next section
1034                           so we need to look backwards until we find a nonzero value */
1035                         while(numberUpdates == 0){
1036                                 count++;
1037                                 numberUpdates = (unsigned int) ( ((unsigned int*) elfData->d_buf)[
1038                                         (elfData->d_size - (sizeof(unsigned int)*count))/ sizeof(unsigned int) ]);
1039                         }
1040
1041                         /*fprintf(stderr," numberUpdates: %d :: (%d - 4) / 4  %x\n", numberUpdates, elfData->d_size, (unsigned int*) &elfData->d_buf );*/
1042
1043                         oldPageDataSize = shdr->sh_size-(((2*numberUpdates)* sizeof(unsigned int)) +((sizeof(unsigned int)*count))) ;
1044
1045
1046                         oldPageData = (char*) malloc(oldPageDataSize+sizeof(unsigned long));
1047                         /*fprintf(stderr,"oldpagedatasize %d datasize %d \n",oldPageDataSize,elfData->d_size);
1048                         perror("malloc");*/
1049                         /*copy old page data */
1050
1051
1052                         /* probe memory to see if we own it */
1053 #if defined(sparc_sun_solaris2_4)
1054
1055                         /* dladdr does not work here with all patchlevels of solaris 2.8
1056                            so we use the /proc file system to read in the /proc/pid/map file
1057                            and determine for our selves if the memory belongs to us yet or not*/
1058                         findMap();
1059                         checkAddr = checkMap((unsigned long)shdr->sh_addr);
1060 #else
1061                         checkAddr = dladdr((void*)shdr->sh_addr, &dlip);
1062 #endif
1063
1064
1065                         updateSize  = shdr->sh_size-((2*numberUpdates)* (sizeof(unsigned int)) -(count* (sizeof(unsigned int))));
1066                         /*fprintf(stderr," updateSize : %d-((2 * %d + 1) * 4))",shdr->sh_size, numberUpdates);*/
1067         
1068                         if(!checkAddr){ 
1069                                 /* we dont own it,mmap it!*/
1070
1071                                 mmapAddr = shdr->sh_offset;
1072                                 mmapAddr =(unsigned long) mmap((void*) shdr->sh_addr,oldPageDataSize,
1073                                         PROT_READ|PROT_WRITE|PROT_EXEC,MAP_FIXED|MAP_PRIVATE,fd,mmapAddr);
1074                                         /*fprintf(stderr,"MMAP %x %d %x size: %x\n",shdr->sh_addr, mmapAddr,shdr->sh_offset,oldPageDataSize);*/
1075                                         
1076
1077                         }else{
1078                                 /*we own it, finish the memcpy */
1079                                 mmapAddr = (unsigned long) memcpy((void*) oldPageData, 
1080                                       (const void*) shdr->sh_addr, oldPageDataSize);
1081                                 /*fprintf(stderr,"memcpy %x %d\n",shdr->sh_addr, updateSize);*/
1082
1083                         }
1084
1085                         dataPtr =(unsigned long *) &(((char*)  elfData->d_buf)[oldPageDataSize]);       
1086                         /*apply updates*/
1087                         for(i = 0; i< numberUpdates; i++){
1088                                 updateAddress = *dataPtr; 
1089                                 updateSize = *(++dataPtr);
1090
1091                                 updateOffset = updateAddress - shdr->sh_addr;
1092                                 /*do update*/   
1093                                 /*fprintf(stderr,"updateAddress %x : %x %x %d %d\n",updateAddress,&( oldPageData[updateOffset]), &(((char*)elfData->d_buf)[updateOffset]) , updateSize,updateOffset);*/
1094                                 memcpy(&( oldPageData[updateOffset]),
1095                                                 &(((char*)elfData->d_buf)[updateOffset]) , updateSize); 
1096
1097                                 dataPtr ++;
1098
1099                         
1100                         } 
1101                         if(!checkAddr){
1102                                 mmapAddr = shdr->sh_offset ;
1103
1104                                 mmapAddr =(unsigned long) mmap((void*) shdr->sh_addr,oldPageDataSize, 
1105                                         PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED| MAP_PRIVATE,fd,mmapAddr);
1106
1107                                         /*fprintf(stderr,"2MMAP %x %d\n",shdr->sh_addr, mmapAddr);*/
1108
1109
1110                         }else{
1111
1112                                 memcpy((void*) shdr->sh_addr, oldPageData,oldPageDataSize );
1113                                 /*fprintf(stderr,"2memcpy %x %d\n",shdr->sh_addr, oldPageDataSize);*/
1114
1115                         }
1116                 }
1117                 if(!strcmp((char *)strData->d_buf + shdr->sh_name, "dyninstAPI_loadLib")){
1118                         /* ccw 14 may 2002 */
1119                         /* this section loads shared libraries into the mutated binary
1120                                 that were loaded by BPatch_thread::loadLibrary */
1121                         void * handle =NULL;
1122 #if defined(sparc_sun_solaris2_4)
1123                         Dl_info p;
1124                         unsigned long loadAddr;
1125 #endif
1126                         elfData = Elf_getdata(scn, NULL);
1127                         tmpPtr = elfData->d_buf;
1128
1129                         while(*tmpPtr) { 
1130                                 handle = dlopen(tmpPtr, RTLD_LAZY);
1131                                 if(handle){
1132 #if defined(sparc_sun_solaris2_4)
1133                                         dlinfo(handle, RTLD_DI_CONFIGADDR,(void*) &p);
1134                                         loadAddr = checkSOLoadAddr(tmpPtr,(unsigned long)p.dli_fbase);
1135                                         if(loadAddr){
1136                                                 fixInstrumentation(tmpPtr,(unsigned long)p.dli_fbase, loadAddr);
1137                                         }
1138 #endif
1139
1140                                 }else{
1141
1142                                         printf(" %s cannot be loaded at the correct address\n", tmpPtr );
1143                                         printf(" This is an unrecoverable error, the instrumentation will not");
1144                                         printf("\n run correctly if shared libraries are loaded at a different address\n");
1145                                         printf("\n Exiting.....\n");
1146
1147                                         printf("\n%s\n",dlerror());
1148                                         fflush(stdout);
1149                                         exit(9);
1150
1151                                 }
1152                                 /* brk ptr not used for ELF */
1153                                 tmpPtr += (strlen(tmpPtr) +1 + sizeof(void *)); 
1154
1155                         }
1156
1157                 }
1158         }
1159
1160 #if defined(sparc_sun_solaris2_4)
1161         if(procMemMap){
1162                 free(procMemMap);
1163         }
1164 #endif
1165
1166         Elf_end(elf);
1167         close(fd);
1168
1169         free(execStr);
1170
1171         if(soError){
1172                 exit(2);
1173         }
1174
1175         for(i=0;i < trampGuardSize_; i++){
1176             trampGuardBase_[i]=1;
1177         }
1178         
1179         return retVal;
1180 }
1181 /* vim:set ts=5: */