mdreloc.c revision 1.11
1/* $NetBSD: mdreloc.c,v 1.11 2002/09/11 20:45:52 mycroft Exp $ */ 2 3#include <sys/types.h> 4#include <sys/stat.h> 5 6#include "debug.h" 7#include "rtld.h" 8 9void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr); 10 11void 12_rtld_setup_pltgot(const Obj_Entry *obj) 13{ 14 obj->pltgot[1] = (Elf_Addr) obj; 15 obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start; 16} 17 18void 19_rtld_relocate_nonplt_self(dynp, relocbase) 20 Elf_Dyn *dynp; 21 Elf_Addr relocbase; 22{ 23 const Elf_Rela *rela = 0, *relalim; 24 Elf_Addr relasz = 0; 25 Elf_Addr *where; 26 27 for (; dynp->d_tag != DT_NULL; dynp++) { 28 switch (dynp->d_tag) { 29 case DT_RELA: 30 rela = (const Elf_Rela *)(relocbase + dynp->d_un.d_ptr); 31 break; 32 case DT_RELASZ: 33 relasz = dynp->d_un.d_val; 34 break; 35 } 36 } 37 relalim = (const Elf_Rela *)((caddr_t)rela + relasz); 38 for (; rela < relalim; rela++) { 39 where = (Elf_Addr *)(relocbase + rela->r_offset); 40 *where += (Elf_Addr)relocbase; 41 } 42} 43 44int 45_rtld_relocate_nonplt_objects(obj, self, dodebug) 46 const Obj_Entry *obj; 47 bool self; 48 bool dodebug; 49{ 50 const Elf_Rela *rela; 51 52 if (self) 53 return 0; 54 55 for (rela = obj->rela; rela < obj->relalim; rela++) { 56 Elf_Addr *where; 57 const Elf_Sym *def; 58 const Obj_Entry *defobj; 59 Elf_Addr tmp; 60 unsigned long symnum; 61 62 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 63 symnum = ELF_R_SYM(rela->r_info); 64 65 switch (ELF_R_TYPE(rela->r_info)) { 66 case R_TYPE(NONE): 67 break; 68 69#if 1 /* XXX should not occur */ 70 case R_TYPE(PC32): 71 def = _rtld_find_symdef(symnum, obj, &defobj, false); 72 if (def == NULL) 73 return -1; 74 75 tmp = (Elf_Addr)(defobj->relocbase + def->st_value + 76 rela->r_addend) - (Elf_Addr)where; 77 if (*where != tmp) 78 *where = tmp; 79 rdbg(dodebug, ("PC32 %s in %s --> %p in %s", 80 obj->strtab + obj->symtab[symnum].st_name, 81 obj->path, (void *)*where, defobj->path)); 82 break; 83 84 case R_TYPE(GOT32): 85#endif 86 case R_TYPE(32): 87 case R_TYPE(GLOB_DAT): 88 def = _rtld_find_symdef(symnum, obj, &defobj, false); 89 if (def == NULL) 90 return -1; 91 92 tmp = (Elf_Addr)(defobj->relocbase + def->st_value + 93 rela->r_addend); 94 if (*where != tmp) 95 *where = tmp; 96 rdbg(dodebug, ("32/GLOB_DAT %s in %s --> %p in %s", 97 obj->strtab + obj->symtab[symnum].st_name, 98 obj->path, (void *)*where, defobj->path)); 99 break; 100 101 case R_TYPE(RELATIVE): 102 *where += (Elf_Addr)obj->relocbase; 103 rdbg(dodebug, ("RELATIVE in %s --> %p", obj->path, 104 (void *)*where)); 105 break; 106 107 case R_TYPE(COPY): 108 /* 109 * These are deferred until all other relocations have 110 * been done. All we do here is make sure that the 111 * COPY relocation is not in a shared library. They 112 * are allowed only in executable files. 113 */ 114 if (obj->isdynamic) { 115 _rtld_error( 116 "%s: Unexpected R_COPY relocation in shared library", 117 obj->path); 118 return -1; 119 } 120 rdbg(dodebug, ("COPY (avoid in main)")); 121 break; 122 123 default: 124 rdbg(dodebug, ("sym = %lu, type = %lu, offset = %p, " 125 "addend = %p, contents = %p, symbol = %s", 126 symnum, (u_long)ELF_R_TYPE(rela->r_info), 127 (void *)rela->r_offset, (void *)rela->r_addend, 128 (void *)*where, 129 obj->strtab + obj->symtab[symnum].st_name)); 130 _rtld_error("%s: Unsupported relocation type %ld " 131 "in non-PLT relocations\n", 132 obj->path, (u_long) ELF_R_TYPE(rela->r_info)); 133 return -1; 134 } 135 } 136 return 0; 137} 138 139int 140_rtld_relocate_plt_lazy(obj, dodebug) 141 const Obj_Entry *obj; 142 bool dodebug; 143{ 144 const Elf_Rela *rela; 145 146 if (!obj->isdynamic) 147 return 0; 148 149 for (rela = obj->pltrela; rela < obj->pltrelalim; rela++) { 150 Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 151 152 assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT)); 153 154 /* Just relocate the GOT slots pointing into the PLT */ 155 *where += (Elf_Addr)obj->relocbase; 156 rdbg(dodebug, ("fixup !main in %s --> %p", obj->path, 157 (void *)*where)); 158 } 159 160 return 0; 161} 162 163int 164_rtld_relocate_plt_object(obj, rela, addrp, dodebug) 165 const Obj_Entry *obj; 166 const Elf_Rela *rela; 167 caddr_t *addrp; 168 bool dodebug; 169{ 170 Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 171 Elf_Addr new_value; 172 const Elf_Sym *def; 173 const Obj_Entry *defobj; 174 175 assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT)); 176 177 def = _rtld_find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, true); 178 if (def == NULL) 179 return -1; 180 181 new_value = (Elf_Addr)(defobj->relocbase + def->st_value); 182 rdbg(dodebug, ("bind now/fixup in %s --> old=%p new=%p", 183 defobj->strtab + def->st_name, (void *)*where, (void *)new_value)); 184 if (*where != new_value) 185 *where = new_value; 186 187 *addrp = (caddr_t)new_value; 188 return 0; 189} 190