2 * Copyright (c) 1996-2004 Barton P. Miller
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.
11 * This license is for research uses. For such uses, there is no
12 * charge. We define "research use" to mean you may freely use it
13 * inside your organization for whatever purposes you see fit. But you
14 * may not re-distribute Paradyn or parts of Paradyn, in any form
15 * source or binary (including derivatives), electronic or otherwise,
16 * to any other organization or entity without our permission.
18 * (for other uses, please contact us at paradyn@cs.wisc.edu)
20 * All warranties, including without limitation, any warranty of
21 * merchantability or fitness for a particular purpose, are hereby
24 * By your use of Paradyn, you understand and agree that we (or any
25 * other person or entity with proprietary rights in Paradyn) are
26 * under no obligation to provide either maintenance services,
27 * update services, notices of latent defects, or correction of
28 * defects for Paradyn.
30 * Even if advised of the possibility of such damages, under no
31 * circumstances shall we (or any other person or entity with
32 * proprietary rights in the software licensed hereunder) be liable
33 * to you or any third party for direct, indirect, or consequential
34 * damages of any character regardless of type of action, including,
35 * without limitation, loss of profits, loss of use, loss of good
36 * will, or computer failure or malfunction. You agree to indemnify
37 * us (and any other person or entity with proprietary rights in the
38 * software licensed hereunder) for any and all liability it may
39 * incur to third parties resulting from your use of Paradyn.
42 /* $Id: RTmutatedBinary_ELF.c,v 1.21 2006/01/13 00:00:48 jodom Exp $ */
44 /* this file contains the code to restore the necessary
45 data for a mutated binary
49 #include "dyninstAPI_RT/h/dyninstAPI_RT.h"
58 #if defined(sparc_sun_solaris2_4)
59 #include <procfs.h> /* ccw 12 mar 2004*/
60 #include <sys/types.h>
66 #if defined(i386_unknown_linux2_0) \
67 || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
73 #include <link.h> /* ccw 23 jan 2002 */
74 #if defined(sparc_sun_solaris2_4)
81 #if defined(sparc_sun_solaris2_4)
82 extern void* _DYNAMIC;
84 #if defined(__arch64__)
85 #define __ELF_NATIVE_CLASS 64
87 #define __ELF_NATIVE_CLASS 32
90 /* Borrowed from Linux's link.h: Allows us to use data types
91 from libelf regardless of word size. */
92 #define ElfW(type) _ElfW (Elf, __ELF_NATIVE_CLASS, type)
93 #define _ElfW(e,w,t) _ElfW_1 (e, w, _##t)
94 #define _ElfW_1(e,w,t) e##w##t
97 #elif defined(i386_unknown_linux2_0) \
98 || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
99 extern ElfW(Dyn) _DYNAMIC[];
103 /* Borrowed from Linux's link.h: Allows us to use functions from
104 libelf regardless of word size. */
105 //#define ELF_FUNC(type) _ELF_FUNC (elf, __ELF_NATIVE_CLASS, type)
106 #define ELF_FUNC(type) _ELF_FUNC (Elf, __ELF_NATIVE_CLASS, type)
107 #define _ELF_FUNC(e,w,t) _ELF_FUNC_1 (e, w, _##t)
108 #define _ELF_FUNC_1(e,w,t) e##w##t
118 unsigned long checkAddr;
119 /*extern int isMutatedExec;
123 struct link_map* map=NULL;
125 #if defined(sparc_sun_solaris2_4)
127 prmap_t *procMemMap=NULL;/* ccw 2 apr 2002 */
128 int procMemMapSize=0;
130 struct r_debug _r_debug; /* ccw 2 apr 2002 */
131 int r_debug_is_set = 0;
132 extern unsigned int _dyninst_call_to_dlopen;
133 extern unsigned int __dyninst_jump_template__;
134 extern unsigned int __dyninst_jump_template__done__;
137 char *sharedLibraryInfo = NULL;
138 unsigned int originalInsnBkpt;
139 unsigned int addressBkpt;
141 #if defined(sparc_sun_solaris2_4)
142 /* To help the RT shared lib to reload in the same location for the
143 mutated binaries we now use dldump to dump the rt lib back to the
144 directory that contains the mutated binary. The LD_LIBRARY_PATH
145 MUST be set to find this new rt lib ONLY when running the mutated
148 extern char gLoadLibraryErrorString[ERROR_STRING_LENGTH];
150 int DYNINSTsaveRtSharedLibrary(char *rtSharedLibName, char *newName){
153 gLoadLibraryErrorString[0]='\0';
155 /*fprintf(stderr," DLDUMP(%s,%s)\n", rtSharedLibName, newName);*/
157 /* dldump returns 0 on success */
158 if ( dldump(rtSharedLibName, newName, RTLD_REL_RELATIVE) ) {
159 /* An error has occurred */
160 perror( "DYNINSTsaveRtSharedLibrary -- dldump" );
162 if (NULL != (err_str = dlerror())){
163 strncpy(gLoadLibraryErrorString, err_str, ERROR_STRING_LENGTH);
165 sprintf(gLoadLibraryErrorString,"unknown error with dldump");
168 /*fprintf(stderr, "%s[%d]: %s\n",__FILE__,__LINE__,gLoadLibraryErrorString);*/
175 /* this is not misnamed. In the future, this function will contain
176 code to patch the instrumentation of a shared library that has
177 been loaded into a different place during a mutated binary run.
179 Now, it just exit()s, as you can see
182 void fixInstrumentation(char* soName, unsigned long currAddr, unsigned long oldAddr){
183 printf(" %s loaded at wrong address: 0x%lx (expected at 0x%lx) \n", soName, currAddr, oldAddr);
184 printf(" This is an unrecoverable error, the instrumentation will not");
185 printf("\n run correctly if shared libraries are loaded at a different address\n");
186 printf("\n Exiting.....\n");
191 /* this function checks the shared library (soName) to see if it
192 is currently loaded (loadAddr) at the same place it was before (address).
193 If the shared library is not found in the list (sharedLibraryInfo) that
194 mean the shared library was *NOT* instrumented and can be loaded
197 unsigned long checkSOLoadAddr(char *soName, unsigned long loadAddr){
198 unsigned long result=0, found = 0;
199 unsigned long address;
200 char *ptr = sharedLibraryInfo;
201 while(ptr && *ptr && !found ){
202 /*fprintf(stderr," CHECKING FOR %s in %s\n", ptr, soName);*/
204 if(strstr(soName, ptr) || strstr(ptr,soName)){
206 ptr += (strlen(ptr) +1);
207 memcpy(&address, ptr, sizeof(unsigned long));
208 /* previous line is done b/c of alignment issues on sparc*/
209 if(loadAddr == address) {
216 ptr += (strlen(ptr) +1);
217 ptr += sizeof(unsigned long);
218 ptr += sizeof(unsigned long); /* for flag */
224 /*fprintf(stderr," NOT FOUND %s\n",soName);*/
227 /*fprintf(stderr," checkSOLoadAddr: %s %lx %lx\n", soName, loadAddr, result);*/
230 #if defined(sparc_sun_solaris2_4)
231 unsigned int register_o7;
233 unsigned long loadAddr;
234 /* this function is not a signal handler. it was originally but now is
235 not, it is called below in dyninst_jump_template
237 void pseudoSigHandler(int sig){
239 map = _r_debug.r_map; /* ccw 22 jul 2003*/
240 if(_r_debug.r_state == 0){
245 loadAddr = checkSOLoadAddr(map->l_name, map->l_addr);
247 fixInstrumentation(map->l_name, map->l_addr, loadAddr);
256 void dyninst_jump_template(){
259 The Solaris loader/ELF file works as follows:
261 A call to dlopen jumps to the Procedure Linking Table
262 slot holding the dlopen information. This slot consists of
266 ba (to another PLT slot)
269 The second PLT slot contains three instructions:
271 call (address of dlopen)
274 dlopen returns directly to where it was called from, not to
275 either of the PLT slots. The address from which it was called
276 is located in %o7 when the call to dlopen in the second PLT
277 slot is made. dlopen returns to %o7 +4.
282 The goals is to intercept this call to dlopen by overwritting
283 the first PLT slot to jump to __dyninst_jump_template__ then we
284 can jump to code that will check the addresses of the loaded
287 first we must preserver %o7 so we know where to go back to.
288 This is done with the first two instructions in __dyninst_jump_template__
289 These are written as nops BUT are overwritten in the SharedLibraries
290 branch in checkElfFile. %o7 is saved in register_o7 declared above.
291 This address is not available until run time so we generate these
292 instructions on the fly.
294 Next, we CALL the second PLT slot as normal. We use the delay
295 slot to run the sethi instruction from the first PLT slot. These
296 instructions are generated at runtime.
298 dlopen will eventually be called and will return to the nop after
299 the sethi. Now we need to call our function to check the
300 shared library address. This is pseudoSigHandler. We must
301 preserve the data returned by dlopen so we do a save to
302 push the register onto the stack before we call our function.
303 We call our function, and then do a restore to retreive the
306 At __dyninst_jump_template__done__ we want to restore the
307 value in register_o7 to %o7 so when we do a retl we will
308 jump back to where the mutated binary originally called
310 The sethi and ld instructions are generated on the fly just
311 as the first sethi and st pair that saved the value of %o7.
312 The retl used %o7 to jump back to the original place
313 the mutatee called dlopen. We are done. Whew.
315 Note that I know the address of the first PLT slot because
316 the mutator found it and saved it in the mutated binary.
317 The address of the second PLT slot is determined by looking
318 at the instructions in the first PLT slot.
323 asm("__dyninst_jump_template__:");
325 asm("nop"); /*sethi hi(register_o7), %g1 GENERATED BELOW*/
326 asm("nop"); /*st %o7 GENERATED BELOW*/
328 asm("nop"); /*call/jmp plt GENERATED BELOW*/
329 asm("nop"); /*sethi r1, b4 GENERATED BELOW*/
332 asm("save %sp, -104, %sp");
339 asm("__dyninst_jump_template__done__:");
340 asm("nop"); /*sethi hi(register_o7), %g1 GENERATED BELOW*/
341 asm("nop"); /* ld [register_o7], %o7 GENERATED BELOW*/
344 asm("nop"); /* this will be filled in below */
351 #if defined (sparc_sun_solaris2_4)
352 void findMap(){ /* ccw 12 mar 2004*/
361 struct stat statInfo;
363 sprintf(fileName, "/proc/%d/map", me);
365 stat(fileName, &statInfo);
369 procMemMap = (prmap_t*) malloc(statInfo.st_size);
371 fd = open(fileName, O_RDONLY);
373 while( pread(fd, (void*)& (procMemMap[index]), sizeof(mapEntry), offset) ){
374 offset += sizeof(prmap_t);
378 procMemMapSize = index;
382 long checkMap(unsigned long addr){
386 while(index < procMemMapSize){
387 if( procMemMap[index].pr_vaddr <= addr && (procMemMap[index].pr_vaddr + (unsigned int)procMemMap[index].pr_size) > addr){
396 #if defined(i386_unknown_linux2_0) \
397 || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
398 unsigned long loadAddr;
399 void (*dl_debug_state_func)(void);
401 void dyninst_dl_debug_state(){
403 if(_r_debug.r_state == 1){
408 loadAddr = checkSOLoadAddr(map->l_name, (unsigned long)map->l_ld);/*l_addr*/
410 fixInstrumentation(map->l_name, (unsigned long)map->l_ld, loadAddr);/*l_addr*/
416 /* the following call is used to call
417 * _dl_debug_state to ensure correctness (if
418 * someone relies on it being called it is
419 * execuated after this function)
420 * The value stored in dl_debug_state_func is
421 * the address of the function _dl_debug_state
422 * and is set in checkElfFile
427 (*dl_debug_state_func)();
432 void hack_ld_linux_plt(unsigned long pltEntryAddr){
434 * save the world needs to check each shared library
435 * that is loaded to ensure that it is loaded at the
436 * same base address it was loaded at when the mutator/mutatee
438 * So, we know dlopen calls _dl_debug_state per the r_debug
439 * interface to let the process know a shared library has changed
441 * with this function we change the Procedure Linkage Table (.plt)
442 * for ld-linux.so so that the entry that used to point to
443 * _dl_debug_state points to dyninst_dl_debug_state.
445 * dyninst_dl_debug_state then calls _dl_debug_state before
448 * dont try this at home
450 unsigned long mprotectAddr = pltEntryAddr - (pltEntryAddr % getpagesize());
451 unsigned long newTarget = (unsigned long) &dyninst_dl_debug_state ;
453 mprotect( (void*) mprotectAddr, pltEntryAddr - mprotectAddr + sizeof(long),
454 PROT_READ|PROT_WRITE|PROT_EXEC);
456 memcpy( (void*) dl_debug_state_func, (void*) pltEntryAddr, sizeof(long));
458 memcpy( (void*) pltEntryAddr, &newTarget, sizeof(long));
462 unsigned (*Elf_version)(unsigned) = NULL;
463 Elf *(*Elf_begin)(int fildes, Elf_Cmd cmd, Elf *ref) = NULL;
464 Elf_Scn *(*Elf_getscn)(Elf *elf, size_t index) = NULL;
465 Elf_Data *(*Elf_getdata)(Elf_Scn *scn, Elf_Data *data) = NULL;
466 Elf_Scn *(*Elf_nextscn)(Elf *elf, Elf_Scn *scn) = NULL;
467 Elf32_Shdr *(*Elf32_getshdr)(Elf_Scn *scn) = NULL;
468 Elf32_Ehdr *(*Elf32_getehdr)(Elf *elf) = NULL;
469 Elf64_Shdr *(*Elf64_getshdr)(Elf_Scn *scn) = NULL;
470 Elf64_Ehdr *(*Elf64_getehdr)(Elf *elf) = NULL;
471 const char *(*Elf_errmsg)(int err) = NULL;
472 int (*Elf_errno)(void) = NULL;
473 int (*Elf_end)(Elf *elf) = NULL;
476 int checkSO(char* soName){
485 if((fd = (int) open(soName, O_RDONLY)) == -1){
486 RTprintf("cannot open : %s\n",soName);
490 if((elf = Elf_begin(fd, ELF_C_READ, NULL)) ==NULL){
491 RTprintf("%s %s \n",soName, Elf_errmsg(Elf_errno()));
492 RTprintf("cannot elf_begin\n");
498 ehdr = ELF_FUNC( getehdr(elf) );
499 scn = Elf_getscn(elf, ehdr->e_shstrndx);
500 strData = Elf_getdata(scn,NULL);
501 for( scn = NULL; !result && (scn = Elf_nextscn(elf, scn)); ){
502 shdr = ELF_FUNC( getshdr(scn) );
503 if(!strcmp((char *)strData->d_buf + shdr->sh_name, ".dyninst_mutated")) {
513 int checkMutatedFile(){
520 Elf_Data *elfData,*strData;
523 int retVal = 0, result;
524 unsigned long mmapAddr;
529 unsigned long updateAddress, updateSize, updateOffset;
530 unsigned long *dataPtr;
531 unsigned int numberUpdates,i ;
536 char * error_msg = NULL;
537 void * elfHandle = NULL;
541 // elfHandle = dlopen("/usr/lib/libelf.so.1", RTLD_NOW);
543 elfHandle = dlopen("libelf.so", RTLD_NOW);
545 error_msg = dlerror();
547 fprintf(stderr,"Could not open lib: %s- %s\n","libelf",error_msg);
550 fprintf(stderr, "failure\n");
555 Elf_version = dlsym(elfHandle, "elf_version");
556 Elf_begin = dlsym(elfHandle, "elf_begin");
557 Elf_getscn = dlsym(elfHandle, "elf_getscn");
558 Elf_nextscn = dlsym(elfHandle, "elf_nextscn");
559 Elf_getdata = dlsym(elfHandle, "elf_getdata");
560 Elf32_getehdr = dlsym(elfHandle, "elf32_getehdr");
561 Elf32_getshdr = dlsym(elfHandle, "elf32_getshdr");
562 Elf64_getehdr = dlsym(elfHandle, "elf64_getehdr");
563 Elf64_getshdr = dlsym(elfHandle, "elf64_getshdr");
564 Elf_errmsg = dlsym(elfHandle, "elf_errmsg");
565 Elf_errno = dlsym(elfHandle, "elf_errno");
566 Elf_end = dlsym(elfHandle, "elf_end");
568 Elf_version(EV_CURRENT);
570 execStr = (char*) malloc(1024);
571 memset(execStr,'\0',1024);
573 #if defined(sparc_sun_solaris2_4)
574 sprintf(execStr,"/proc/%d/object/a.out",getpid());
575 #elif defined(i386_unknown_linux2_0) \
576 || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
577 sprintf(execStr,"/proc/%d/exe",getpid());
580 if((fd = (int) open(execStr, O_RDONLY)) == -1){
581 printf("cannot open : %s\n",execStr);
585 if((elf = Elf_begin(fd, ELF_C_READ, NULL)) ==NULL){
586 printf("%s %s \n",execStr, Elf_errmsg( Elf_errno()));
587 printf("cannot Elf_begin\n");
593 ehdr = ELF_FUNC( getehdr(elf) );
594 scn = Elf_getscn(elf, ehdr->e_shstrndx);
595 strData = Elf_getdata(scn,NULL);
596 pageSize = getpagesize();
598 /*fprintf(stderr,"IN MUTATED FILE\n");*/
599 for(cnt = 0, scn = NULL; !soError && (scn = Elf_nextscn(elf, scn));cnt++){
600 shdr = ELF_FUNC( getshdr(scn) );
601 if(!strncmp((char *)strData->d_buf + shdr->sh_name, "dyninstAPItrampgu", 17)) {
602 dataAddress = shdr->sh_addr;
603 elfData = Elf_getdata(scn, NULL);
604 tmpPtr = elfData->d_buf;
605 /*fprintf(stderr,"tramp guard addr %x %d\n", dataAddress,*(int*)tmpPtr);*/
608 #if defined(sparc_sun_solaris2_4)
610 checkAddr = checkMap((unsigned long)shdr->sh_addr);
612 checkAddr = dladdr((void*)shdr->sh_addr, &dlip);
615 /* we do not own it. mmap it */
617 /* this is the usual case on Linux */
619 mmapAddr = shdr->sh_addr;
620 mmapAddr = mmapAddr % pageSize;
621 mmapAddr = shdr->sh_addr - mmapAddr;
623 #if defined(sparc_sun_solaris2_4)
624 checkAddr = checkMap((unsigned long)mmapAddr);
626 checkAddr = dladdr((void*) mmapAddr, &dlip);
629 mmapAddr =(unsigned long) mmap((void*)mmapAddr ,((*(int*)tmpPtr)+1)*sizeof(unsigned),
630 PROT_READ|PROT_WRITE,MAP_FIXED|MAP_PRIVATE,fd,0);
632 if( mmapAddr == ( shdr->sh_addr - (shdr->sh_addr % pageSize ) )){
633 /* set tramp guard to 1 */
634 for(i=0;i<*(int*)tmpPtr;i++){
635 ((unsigned*) dataAddress)[i]=1;
640 /* we already own it.
641 this probably means something else is using this memory.
647 #if defined(sparc_sun_solaris2_4)
649 /* this is the usual case on Solaris */
651 /* set tramp guard to 1 */
652 for(i=0;i<*(int*)tmpPtr;i++){
653 ((unsigned*) dataAddress)[i]=1;
657 fprintf(stderr,"ERROR: Could not reload DYNINST_tramp_guards\n\n");
658 fprintf(stderr,"terminating .... \n");
666 }else if(!strncmp((char *)strData->d_buf + shdr->sh_name, "dyninstAPI_data", 15)) {
667 elfData = Elf_getdata(scn, NULL);
668 tmpPtr = elfData->d_buf;
670 while( dataAddress != 0 ) {
671 /*tmpPtr may not be aligned on the correct boundry
672 so use memcpy to set dataSize
673 dataSize = *(int*) tmpPtr;*/
674 memcpy((char*) & dataSize, tmpPtr, sizeof(int));
677 memcpy( (char*) & dataAddress, tmpPtr, sizeof(Address));
679 tmpPtr += sizeof(Address);
681 memcpy((char*) dataAddress, tmpPtr, dataSize);
687 }else if(!strncmp((char *)strData->d_buf + shdr->sh_name, "dyninstAPI_",11)){
688 char *tmpStr = strchr((char *)strData->d_buf + shdr->sh_name, (int)'_'); ;
692 #if defined(sparc_sun_solaris2_4)
693 if( r_debug_is_set == 0 ) {
694 /* this moved up incase there is no dyninstAPI_### section, map and
695 _r_debug are still set correctly. */
696 /* solaris does not make _r_debug available by
697 default, we have to find it in the _DYNAMIC table */
699 __Elf_Dyn *_dyn = (__Elf_Dyn*)& _DYNAMIC;
700 while(_dyn && _dyn->d_tag != 0 && _dyn->d_tag != 21){
703 if(_dyn && _dyn->d_tag != 0){
704 _r_debug = *(struct r_debug*) _dyn->d_un.d_ptr;
706 map = _r_debug.r_map;
709 map = _r_debug.r_map;
713 if( *tmpStr>=0x30 && *tmpStr <= 0x39 ) {
714 /* we dont want to do this unless this is a dyninstAPI_### section
715 specifically, dont do this for dyninstAPI_SharedLibraries*/
716 retVal = 1; /* this is a restored run */
718 if( *tmpStr>=0x30 && *tmpStr <= 0x39 ) {
719 /* this is a heap tramp section */
721 /* the new starting address of the heap is immediately AFTER the last
722 dyninstAPI_### section, so we can ALWAYS memcpy the data into place
723 see the value of newHeapAddr in writeBackElf.C
725 elfData = Elf_getdata(scn, NULL);
726 memcpy((void*)shdr->sh_addr, elfData->d_buf, shdr->sh_size);
730 if(!strcmp((char *)strData->d_buf + shdr->sh_name, "dyninstAPI_mutatedSO")){
731 /* make sure the mutated SOs are loaded, not the original ones */
735 __Elf_Dyn *_dyn = (__Elf_Dyn*)& _DYNAMIC;
736 #if defined(sparc_sun_solaris2_4)
738 #elif defined(i386_unknown_linux2_0) \
739 || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
740 struct link_map *lmap=0;
742 char *loadedname, *dyninstname;
744 elfData = Elf_getdata(scn, NULL);
746 sharedLibraryInfo = (char*) malloc(elfData->d_size);
747 memcpy(sharedLibraryInfo, elfData->d_buf, elfData->d_size);
748 lmap = _r_debug.r_map;
750 for(soNames = (char*) elfData->d_buf ; totallen<elfData->d_size;
751 soNames = &((char*) elfData->d_buf)[strlen(soNames)+1+sizeof(unsigned int) +sizeof(unsigned int)]){
752 /* added a +sizeof(unsigned int) above for flag */
753 totallen += strlen(soNames) + 1 + sizeof(unsigned int) +sizeof(unsigned int); /*for flag*/
754 memcpy(&mutatedFlag, &((char*) elfData->d_buf)[totallen-sizeof(unsigned int)], sizeof(unsigned int));
755 lmap = _r_debug.r_map;
757 loadedname = strrchr(lmap->l_name,'/');
758 dyninstname = strrchr((const char *)soNames,(int)'/');
760 loadedname = lmap->l_name;
762 if(dyninstname == 0){
763 dyninstname = soNames;
765 if(mutatedFlag && !strcmp(loadedname, dyninstname)) {
766 if(!checkSO(lmap->l_name)){
767 printf("ERROR: %s was mutated during saveworld and",lmap->l_name);
768 printf(" the currently loaded %s has not been mutated\n", lmap->l_name);
769 printf(" check your LD path to be sure the mutated %s is visible\n", soNames);
780 if(!strcmp((char *)strData->d_buf + shdr->sh_name, "rtlib_addr")){
782 int foundLib = 0, result;
786 elfData = Elf_getdata(scn, NULL);
788 /*ptr = elfData->d_buf;*/
789 /* use memcpy because of alignment issues on sparc */
790 memcpy(&ptr,elfData->d_buf,sizeof(unsigned int));
792 #if defined(sparc_sun_solaris2_4)
793 if( r_debug_is_set == 0 ) {
794 /* this moved up incase there is no dyninstAPI_### section, map and
795 _r_debug are still set correctly. */
796 /* solaris does not make _r_debug available by
797 default, we have to find it in the _DYNAMIC table */
799 __Elf_Dyn *_dyn = (__Elf_Dyn*)& _DYNAMIC;
800 while(_dyn && _dyn->d_tag != 0 && _dyn->d_tag != 21){
803 if(_dyn && _dyn->d_tag != 0){
804 _r_debug = *(struct r_debug*) _dyn->d_un.d_ptr;
806 map = _r_debug.r_map;
809 map = _r_debug.r_map;
813 map = _r_debug.r_map;
816 /*fprintf(stderr,"CHECKING %s 0x%x\n", map->l_name,map->l_addr);*/
817 if( * map->l_name && strstr(map->l_name, "libdyninstAPI_RT")){
818 unsigned long loadaddr = (unsigned long)map->l_addr;
820 /* LINUX PROBLEM. in the link_map structure the map->l_addr field is NOT
821 the load address of the dynamic object, as the documentation says. It is the
822 RELOCATED address of the object. If the object was not relocated then the
825 So, on LINUX we check the address of the dynamic section, map->l_ld, which is
828 #if defined(i386_unknown_linux2_0) || defined(x86_64_unknown_linux2_4)
829 loadaddr = (unsigned long)map->l_ld;
832 /*fprintf(stderr," loadadd %x ptr %x\n", loadaddr, ptr);*/
833 if( loadaddr != (ptr)){
834 fixInstrumentation(map->l_name, loadaddr, (ptr));
837 /* check every loaded SO but leave map such that map->l_next == NULL.
838 The next time a SO is loaded it will be placed at
839 map->l_next, so keep a tail pointer such that we
840 dont need to loop through the entire list again
849 if(!strcmp((char *)strData->d_buf + shdr->sh_name, "dyninstAPI_SharedLibraries")){
850 unsigned long diffAddr;
851 unsigned long ld_linuxBaseAddr, baseAddr, size;
852 #if defined(sparc_sun_solaris2_4)
853 unsigned int *overWriteInsn;
854 unsigned int *pltEntry, *PLTEntry, *dyninst_jump_templatePtr, pltInsn, tmpAddr;
855 unsigned int BA_MASK=0x30800000;
856 unsigned int BA_IMM=0x003fffff;
857 unsigned int SETHI_IMM=0x003fffff;
858 unsigned int JMP_IMM =0x00001fff;
859 unsigned int offset, callInsn;
860 struct sigaction mysigact, oldsigact;
863 int foundLib = 0, result;
867 elfData = Elf_getdata(scn, NULL);
869 ptr = elfData->d_buf;
871 map = _r_debug.r_map;
875 unsigned int loadaddr = map->l_addr;
877 /* LINUX PROBLEM. in the link_map structure the map->l_addr field is NOT
878 the load address of the dynamic object, as the documentation says. It is the
879 RELOCATED address of the object. If the object was not relocated then the
882 So, on LINUX we check the address of the dynamic section, map->l_ld, which is
885 #if defined(i386_unknown_linux2_0) || defined(x86_64_unknown_linux2_4)
886 loadaddr = (unsigned long)map->l_ld;
889 /*fprintf(stderr," CHECKING: %s %x\n",map->l_name, map->l_addr);*/
890 diffAddr = checkSOLoadAddr(map->l_name, loadaddr);
892 fixInstrumentation(map->l_name, loadaddr, diffAddr);
894 #if defined(i386_unknown_linux2_0) \
895 || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
896 /* ld-linux.so will never be hand relocated so l_addr should be correct. right? */
897 if(strstr(map->l_name, "ld-linux.so")){
898 ld_linuxBaseAddr = map->l_addr;
902 /* check every loaded SO but leave map such that map->l_next == NULL.
903 The next time a SO is loaded it will be placed at
904 map->l_next, so keep a tail pointer such that we
905 dont need to loop through the entire list again
913 if( shdr->sh_addr != 0){
914 /* if the addr is zero, then there is
915 no PLT entry for dlopen. if there is
916 no entry for dlopen the mutatee must not
917 call it. -- what about calling it from
918 a shared lib that is statically loaded?
921 /* WHY IS THERE A POUND DEFINE HERE?
923 well, we need to intercept the dlopen calls from the mutated binary
924 because our trampolines expect the shared libraries to be in
925 a particular location and if they are not where they are expected
926 our trampolines can jump off into nothingness, or even worse, some
927 random bit of executable code.
929 So we must intercept the dlopen call and then check to be sure
930 the shared libraries are loaded in the same place as before. If
931 they are not we exit with a message to the user saying this is
934 Note, only shared libraries that have been instrumented are checked
938 #if defined(sparc_sun_solaris2_4)
940 For a description of what is going on here read
941 the comment in dyninst_jump_template above.
943 This code generated all the instructions refered
944 to in that comment as "GENERATED BELOW".
948 pltEntry = (unsigned int*) shdr->sh_addr;
949 pltInsn = *pltEntry; /* save insn for later */
952 /* The PLT entry may look like:
964 if( (*pltEntry & (BA_MASK)) == (BA_MASK) ){
965 /* we have the sethi/ba,a/nop type */
967 offset = (*pltEntry) & BA_IMM;
968 if(offset & 0x00200000){
969 /* negative so sign extend */
970 offset = 0xffc00000 | offset;
974 PLTEntry += (offset*4)/sizeof(PLTEntry); /* move PLTEntry offset*4 bytes!*/
977 /* we have the sethi/sethi/jmp type */
978 tmpAddr = ((*pltEntry) & SETHI_IMM)<<10;
980 tmpAddr += ((*pltEntry) & JMP_IMM);
985 dyninst_jump_templatePtr = (unsigned int*) & __dyninst_jump_template__;
987 baseAddr = ((unsigned int) dyninst_jump_templatePtr) -
988 ( ((unsigned int) dyninst_jump_templatePtr)% getpagesize());
989 size = (unsigned int) dyninst_jump_templatePtr - baseAddr + 80;
990 result = mprotect((void*)baseAddr , size,
991 PROT_READ|PROT_WRITE|PROT_EXEC);
993 /* build sethi hi(register_o7), %g1 */
994 *dyninst_jump_templatePtr = 0x03000000;
995 *dyninst_jump_templatePtr |= ( (((unsigned int ) & register_o7)& 0xfffffc00) >> 10); /*0xffffe000 */
997 dyninst_jump_templatePtr ++;
999 /* build st %o7, ®ister_o7 */
1000 *dyninst_jump_templatePtr = 0xde206000;
1001 *dyninst_jump_templatePtr |= ( ((unsigned int ) & register_o7) & 0x000003ff ); /*0x00001fff*/
1003 dyninst_jump_templatePtr ++;
1005 /* build call PLTEntry */
1006 *dyninst_jump_templatePtr = 0x40000000;
1007 *dyninst_jump_templatePtr |= ( ((unsigned int) (PLTEntry)- ((unsigned int) dyninst_jump_templatePtr)) >>2);
1008 dyninst_jump_templatePtr ++;
1011 *dyninst_jump_templatePtr = pltInsn;
1012 dyninst_jump_templatePtr ++;
1015 /* advance past call to pseudoSigHandler */
1016 dyninst_jump_templatePtr = (unsigned int*) &__dyninst_jump_template__done__ ;
1018 /* build sethi hi(register_o7), %g1 */
1019 *dyninst_jump_templatePtr = 0x03000000;
1020 *dyninst_jump_templatePtr |= ( (((unsigned int ) & register_o7)& 0xfffffc00) >> 10); /*0xffffe000*/
1022 dyninst_jump_templatePtr ++;
1024 /* build ld %o7, register_o7 */
1025 *dyninst_jump_templatePtr = 0xde006000;
1026 *dyninst_jump_templatePtr |= ( ((unsigned int ) & register_o7) & 0x000003ff ); /*0x00001fff*/
1029 /* THIS ENABLES THE JUMP */
1030 /* edit plt to jump to __dyninst_jump_template__ */
1031 baseAddr = ((unsigned int) pltEntry) -
1032 ( ((unsigned int) pltEntry)% getpagesize());
1033 size = (unsigned int) pltEntry - baseAddr + 8;
1034 result = mprotect((void*)baseAddr , size,
1035 PROT_READ|PROT_WRITE|PROT_EXEC);
1037 /* build sethi hi(&__dyninst_jump_template__), %g1 */
1039 *pltEntry = 0x03000000;
1040 *pltEntry |= ( (((unsigned int ) &__dyninst_jump_template__) )>> 10);
1043 /* build jmpl %g1, %r0 */
1044 *pltEntry = 0x81c06000;
1045 *pltEntry |= ( ((unsigned int ) &__dyninst_jump_template__ ) & 0x00003ff );
1048 *pltEntry = 0x01000000;
1049 #elif defined(i386_unknown_linux2_0) \
1050 || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */
1051 /* install jump to catch call to _dl_debug_state */
1052 /* see comment int hack_ld_linux_plt for explainations */
1053 hack_ld_linux_plt(ld_linuxBaseAddr + shdr->sh_addr);
1055 }/* shdr->sh_addr != 0 */
1057 if( !strncmp((char *)strData->d_buf + shdr->sh_name, "dyninstAPIhighmem_",18)){
1058 /*the layout of dyninstAPIhighmem_ is:
1067 we must ONLY overwrite the updates, the other
1068 areas of the page may be important (and different than
1069 the saved data in the file. we first copy out the
1070 page, the apply the updates to it, and then
1074 int oldPageDataSize;
1077 retVal = 1; /* just to be sure */
1078 elfData = Elf_getdata(scn, NULL);
1081 /*this section may be padded out with zeros to align the next section
1082 so we need to look backwards until we find a nonzero value */
1083 while(numberUpdates == 0){
1085 numberUpdates = (unsigned int) ( ((unsigned int*) elfData->d_buf)[
1086 (elfData->d_size - (sizeof(unsigned int)*count))/ sizeof(unsigned int) ]);
1089 /*fprintf(stderr," numberUpdates: %d :: (%d - 4) / 4 %x\n", numberUpdates, elfData->d_size, (unsigned int*) &elfData->d_buf );*/
1091 oldPageDataSize = shdr->sh_size-(((2*numberUpdates)* sizeof(unsigned int)) +((sizeof(unsigned int)*count))) ;
1094 oldPageData = (char*) malloc(oldPageDataSize+sizeof(unsigned long));
1095 /*fprintf(stderr,"oldpagedatasize %d datasize %d\n",oldPageDataSize,elfData->d_size);*/
1096 /*copy old page data */
1099 /* probe memory to see if we own it */
1100 #if defined(sparc_sun_solaris2_4)
1102 /* dladdr does not work here with all patchlevels of solaris 2.8
1103 so we use the /proc file system to read in the /proc/pid/map file
1104 and determine for our selves if the memory belongs to us yet or not*/
1106 checkAddr = checkMap((unsigned long)shdr->sh_addr);
1108 checkAddr = dladdr((void*)shdr->sh_addr, &dlip);
1112 updateSize = shdr->sh_size-((2*numberUpdates)* (sizeof(unsigned int)) -(count* (sizeof(unsigned int))));
1113 /*fprintf(stderr," updateSize : %d-((2 * %d + 1) * 4))",shdr->sh_size, numberUpdates);*/
1116 /* we dont own it,mmap it!*/
1118 mmapAddr = shdr->sh_offset;
1119 mmapAddr =(unsigned long) mmap((void*) shdr->sh_addr,oldPageDataSize,
1120 PROT_READ|PROT_WRITE|PROT_EXEC,MAP_FIXED|MAP_PRIVATE,fd,mmapAddr);
1121 /*fprintf(stderr,"MMAP %x %d %x size: %x\n",shdr->sh_addr, mmapAddr,shdr->sh_offset,oldPageDataSize);*/
1125 /*we own it, finish the memcpy */
1126 mmapAddr = (unsigned long) memcpy((void*) oldPageData,
1127 (const void*) shdr->sh_addr, oldPageDataSize);
1128 /*fprintf(stderr,"memcpy %x %d\n",shdr->sh_addr, updateSize);*/
1132 dataPtr =(unsigned long *) &(((char*) elfData->d_buf)[oldPageDataSize]);
1134 for(i = 0; i< numberUpdates; i++){
1135 updateAddress = *dataPtr;
1136 updateSize = *(++dataPtr);
1138 updateOffset = updateAddress - shdr->sh_addr;
1140 /*fprintf(stderr,"updateAddress %x : %x %x %d %d\n",updateAddress,&( oldPageData[updateOffset]), &(((char*)elfData->d_buf)[updateOffset]) , updateSize,updateOffset);*/
1141 memcpy(&( oldPageData[updateOffset]),
1142 &(((char*)elfData->d_buf)[updateOffset]) , updateSize);
1149 mmapAddr = shdr->sh_offset ;
1151 mmapAddr =(unsigned long) mmap((void*) shdr->sh_addr,oldPageDataSize,
1152 PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED| MAP_PRIVATE,fd,mmapAddr);
1154 /*fprintf(stderr,"2MMAP %x %d\n",shdr->sh_addr, mmapAddr);*/
1159 memcpy((void*) shdr->sh_addr, oldPageData,oldPageDataSize );
1160 /*fprintf(stderr,"2memcpy %x %d\n",shdr->sh_addr, oldPageDataSize);*/
1164 if(!strcmp((char *)strData->d_buf + shdr->sh_name, "dyninstAPI_loadLib")){
1165 /* ccw 14 may 2002 */
1166 /* this section loads shared libraries into the mutated binary
1167 that were loaded by BPatch_thread::loadLibrary */
1168 void * handle =NULL;
1170 unsigned long loadAddr;
1171 elfData = Elf_getdata(scn, NULL);
1172 tmpPtr = elfData->d_buf;
1175 handle = dlopen(tmpPtr, RTLD_LAZY);
1177 dlinfo(handle, RTLD_DI_CONFIGADDR,(void*) &p);
1178 #if defined(sparc_sun_solaris2_4)
1179 loadAddr = checkSOLoadAddr(tmpPtr,(unsigned long)p.dli_fbase);
1181 fixInstrumentation(tmpPtr,(unsigned long)p.dli_fbase, loadAddr);
1187 printf(" %s cannot be loaded at the correct address\n", tmpPtr );
1188 printf(" This is an unrecoverable error, the instrumentation will not");
1189 printf("\n run correctly if shared libraries are loaded at a different address\n");
1190 printf("\n Exiting.....\n");
1192 printf("\n%s\n",dlerror());
1197 /* brk ptr not used for ELF */
1198 tmpPtr += (strlen(tmpPtr) +1 + sizeof(void *));
1204 #if defined(sparc_sun_solaris2_4)