reloc.c (208256) | reloc.c (216695) |
---|---|
1/*- 2 * Copyright 1996, 1997, 1998, 1999 John D. Polstra. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 8 unchanged lines hidden (view full) --- 17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 * | 1/*- 2 * Copyright 1996, 1997, 1998, 1999 John D. Polstra. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 8 unchanged lines hidden (view full) --- 17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 * |
25 * $FreeBSD: head/libexec/rtld-elf/i386/reloc.c 208256 2010-05-18 08:55:23Z rdivacky $ | 25 * $FreeBSD: head/libexec/rtld-elf/i386/reloc.c 216695 2010-12-25 08:51:20Z kib $ |
26 */ 27 28/* 29 * Dynamic linker for ELF. 30 * 31 * John Polstra <jdp@polstra.com>. 32 */ 33 --- 31 unchanged lines hidden (view full) --- 65 assert(dstobj->mainprog); /* COPY relocations are invalid elsewhere */ 66 67 rellim = (const Elf_Rel *) ((caddr_t) dstobj->rel + dstobj->relsize); 68 for (rel = dstobj->rel; rel < rellim; rel++) { 69 if (ELF_R_TYPE(rel->r_info) == R_386_COPY) { 70 void *dstaddr; 71 const Elf_Sym *dstsym; 72 const char *name; | 26 */ 27 28/* 29 * Dynamic linker for ELF. 30 * 31 * John Polstra <jdp@polstra.com>. 32 */ 33 --- 31 unchanged lines hidden (view full) --- 65 assert(dstobj->mainprog); /* COPY relocations are invalid elsewhere */ 66 67 rellim = (const Elf_Rel *) ((caddr_t) dstobj->rel + dstobj->relsize); 68 for (rel = dstobj->rel; rel < rellim; rel++) { 69 if (ELF_R_TYPE(rel->r_info) == R_386_COPY) { 70 void *dstaddr; 71 const Elf_Sym *dstsym; 72 const char *name; |
73 unsigned long hash; | |
74 size_t size; 75 const void *srcaddr; 76 const Elf_Sym *srcsym; | 73 size_t size; 74 const void *srcaddr; 75 const Elf_Sym *srcsym; |
77 const Ver_Entry *ve; 78 Obj_Entry *srcobj; | 76 const Obj_Entry *srcobj, *defobj; 77 SymLook req; 78 int res; |
79 80 dstaddr = (void *) (dstobj->relocbase + rel->r_offset); 81 dstsym = dstobj->symtab + ELF_R_SYM(rel->r_info); 82 name = dstobj->strtab + dstsym->st_name; | 79 80 dstaddr = (void *) (dstobj->relocbase + rel->r_offset); 81 dstsym = dstobj->symtab + ELF_R_SYM(rel->r_info); 82 name = dstobj->strtab + dstsym->st_name; |
83 hash = elf_hash(name); | |
84 size = dstsym->st_size; | 83 size = dstsym->st_size; |
85 ve = fetch_ventry(dstobj, ELF_R_SYM(rel->r_info)); | 84 symlook_init(&req, name); 85 req.ventry = fetch_ventry(dstobj, ELF_R_SYM(rel->r_info)); |
86 | 86 |
87 for (srcobj = dstobj->next; srcobj != NULL; srcobj = srcobj->next) 88 if ((srcsym = symlook_obj(name, hash, srcobj, ve, 0)) != NULL) | 87 for (srcobj = dstobj->next; srcobj != NULL; srcobj = srcobj->next) { 88 res = symlook_obj(&req, srcobj); 89 if (res == 0) { 90 srcsym = req.sym_out; 91 defobj = req.defobj_out; |
89 break; | 92 break; |
93 } 94 } |
|
90 91 if (srcobj == NULL) { 92 _rtld_error("Undefined symbol \"%s\" referenced from COPY" 93 " relocation in %s", name, dstobj->path); 94 return -1; 95 } 96 | 95 96 if (srcobj == NULL) { 97 _rtld_error("Undefined symbol \"%s\" referenced from COPY" 98 " relocation in %s", name, dstobj->path); 99 return -1; 100 } 101 |
97 srcaddr = (const void *) (srcobj->relocbase + srcsym->st_value); | 102 srcaddr = (const void *) (defobj->relocbase + srcsym->st_value); |
98 memcpy(dstaddr, srcaddr, size); 99 } 100 } 101 102 return 0; 103} 104 105/* Initialize the special GOT entries. */ 106void 107init_pltgot(Obj_Entry *obj) 108{ 109 if (obj->pltgot != NULL) { 110 obj->pltgot[1] = (Elf_Addr) obj; 111 obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start; 112 } 113} 114 115/* Process the non-PLT relocations. */ 116int | 103 memcpy(dstaddr, srcaddr, size); 104 } 105 } 106 107 return 0; 108} 109 110/* Initialize the special GOT entries. */ 111void 112init_pltgot(Obj_Entry *obj) 113{ 114 if (obj->pltgot != NULL) { 115 obj->pltgot[1] = (Elf_Addr) obj; 116 obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start; 117 } 118} 119 120/* Process the non-PLT relocations. */ 121int |
117reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld) | 122reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, RtldLockState *lockstate) |
118{ 119 const Elf_Rel *rellim; 120 const Elf_Rel *rel; 121 SymCache *cache; 122 int r = -1; 123 124 /* 125 * The dynamic loader may be called from a thread, we have --- 15 unchanged lines hidden (view full) --- 141 break; 142 143 case R_386_32: 144 { 145 const Elf_Sym *def; 146 const Obj_Entry *defobj; 147 148 def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, | 123{ 124 const Elf_Rel *rellim; 125 const Elf_Rel *rel; 126 SymCache *cache; 127 int r = -1; 128 129 /* 130 * The dynamic loader may be called from a thread, we have --- 15 unchanged lines hidden (view full) --- 146 break; 147 148 case R_386_32: 149 { 150 const Elf_Sym *def; 151 const Obj_Entry *defobj; 152 153 def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, |
149 false, cache); | 154 false, cache, lockstate); |
150 if (def == NULL) 151 goto done; 152 153 *where += (Elf_Addr) (defobj->relocbase + def->st_value); 154 } 155 break; 156 157 case R_386_PC32: 158 /* 159 * I don't think the dynamic linker should ever see this 160 * type of relocation. But the binutils-2.6 tools sometimes 161 * generate it. 162 */ 163 { 164 const Elf_Sym *def; 165 const Obj_Entry *defobj; 166 167 def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, | 155 if (def == NULL) 156 goto done; 157 158 *where += (Elf_Addr) (defobj->relocbase + def->st_value); 159 } 160 break; 161 162 case R_386_PC32: 163 /* 164 * I don't think the dynamic linker should ever see this 165 * type of relocation. But the binutils-2.6 tools sometimes 166 * generate it. 167 */ 168 { 169 const Elf_Sym *def; 170 const Obj_Entry *defobj; 171 172 def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, |
168 false, cache); | 173 false, cache, lockstate); |
169 if (def == NULL) 170 goto done; 171 172 *where += 173 (Elf_Addr) (defobj->relocbase + def->st_value) - 174 (Elf_Addr) where; 175 } 176 break; --- 13 unchanged lines hidden (view full) --- 190 break; 191 192 case R_386_GLOB_DAT: 193 { 194 const Elf_Sym *def; 195 const Obj_Entry *defobj; 196 197 def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, | 174 if (def == NULL) 175 goto done; 176 177 *where += 178 (Elf_Addr) (defobj->relocbase + def->st_value) - 179 (Elf_Addr) where; 180 } 181 break; --- 13 unchanged lines hidden (view full) --- 195 break; 196 197 case R_386_GLOB_DAT: 198 { 199 const Elf_Sym *def; 200 const Obj_Entry *defobj; 201 202 def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, |
198 false, cache); | 203 false, cache, lockstate); |
199 if (def == NULL) 200 goto done; 201 202 *where = (Elf_Addr) (defobj->relocbase + def->st_value); 203 } 204 break; 205 206 case R_386_RELATIVE: 207 *where += (Elf_Addr) obj->relocbase; 208 break; 209 210 case R_386_TLS_TPOFF: 211 { 212 const Elf_Sym *def; 213 const Obj_Entry *defobj; 214 215 def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, | 204 if (def == NULL) 205 goto done; 206 207 *where = (Elf_Addr) (defobj->relocbase + def->st_value); 208 } 209 break; 210 211 case R_386_RELATIVE: 212 *where += (Elf_Addr) obj->relocbase; 213 break; 214 215 case R_386_TLS_TPOFF: 216 { 217 const Elf_Sym *def; 218 const Obj_Entry *defobj; 219 220 def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, |
216 false, cache); | 221 false, cache, lockstate); |
217 if (def == NULL) 218 goto done; 219 220 /* 221 * We lazily allocate offsets for static TLS as we 222 * see the first relocation that references the 223 * TLS block. This allows us to support (small 224 * amounts of) static TLS in dynamically loaded --- 13 unchanged lines hidden (view full) --- 238 break; 239 240 case R_386_TLS_DTPMOD32: 241 { 242 const Elf_Sym *def; 243 const Obj_Entry *defobj; 244 245 def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, | 222 if (def == NULL) 223 goto done; 224 225 /* 226 * We lazily allocate offsets for static TLS as we 227 * see the first relocation that references the 228 * TLS block. This allows us to support (small 229 * amounts of) static TLS in dynamically loaded --- 13 unchanged lines hidden (view full) --- 243 break; 244 245 case R_386_TLS_DTPMOD32: 246 { 247 const Elf_Sym *def; 248 const Obj_Entry *defobj; 249 250 def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, |
246 false, cache); | 251 false, cache, lockstate); |
247 if (def == NULL) 248 goto done; 249 250 *where += (Elf_Addr) defobj->tlsindex; 251 } 252 break; 253 254 case R_386_TLS_DTPOFF32: 255 { 256 const Elf_Sym *def; 257 const Obj_Entry *defobj; 258 259 def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, | 252 if (def == NULL) 253 goto done; 254 255 *where += (Elf_Addr) defobj->tlsindex; 256 } 257 break; 258 259 case R_386_TLS_DTPOFF32: 260 { 261 const Elf_Sym *def; 262 const Obj_Entry *defobj; 263 264 def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, |
260 false, cache); | 265 false, cache, lockstate); |
261 if (def == NULL) 262 goto done; 263 264 *where += (Elf_Addr) def->st_value; 265 } 266 break; 267 268 default: --- 27 unchanged lines hidden (view full) --- 296 where = (Elf_Addr *)(obj->relocbase + rel->r_offset); 297 *where += (Elf_Addr)obj->relocbase; 298 } 299 return 0; 300} 301 302/* Relocate the jump slots in an object. */ 303int | 266 if (def == NULL) 267 goto done; 268 269 *where += (Elf_Addr) def->st_value; 270 } 271 break; 272 273 default: --- 27 unchanged lines hidden (view full) --- 301 where = (Elf_Addr *)(obj->relocbase + rel->r_offset); 302 *where += (Elf_Addr)obj->relocbase; 303 } 304 return 0; 305} 306 307/* Relocate the jump slots in an object. */ 308int |
304reloc_jmpslots(Obj_Entry *obj) | 309reloc_jmpslots(Obj_Entry *obj, RtldLockState *lockstate) |
305{ 306 const Elf_Rel *rellim; 307 const Elf_Rel *rel; 308 309 if (obj->jmpslots_done) 310 return 0; 311 rellim = (const Elf_Rel *)((char *)obj->pltrel + obj->pltrelsize); 312 for (rel = obj->pltrel; rel < rellim; rel++) { 313 Elf_Addr *where, target; 314 const Elf_Sym *def; 315 const Obj_Entry *defobj; 316 317 assert(ELF_R_TYPE(rel->r_info) == R_386_JMP_SLOT); 318 where = (Elf_Addr *)(obj->relocbase + rel->r_offset); | 310{ 311 const Elf_Rel *rellim; 312 const Elf_Rel *rel; 313 314 if (obj->jmpslots_done) 315 return 0; 316 rellim = (const Elf_Rel *)((char *)obj->pltrel + obj->pltrelsize); 317 for (rel = obj->pltrel; rel < rellim; rel++) { 318 Elf_Addr *where, target; 319 const Elf_Sym *def; 320 const Obj_Entry *defobj; 321 322 assert(ELF_R_TYPE(rel->r_info) == R_386_JMP_SLOT); 323 where = (Elf_Addr *)(obj->relocbase + rel->r_offset); |
319 def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, true, NULL); | 324 def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, true, NULL, 325 lockstate); |
320 if (def == NULL) 321 return -1; 322 target = (Elf_Addr)(defobj->relocbase + def->st_value); 323 reloc_jmpslot(where, target, defobj, obj, rel); 324 } 325 obj->jmpslots_done = true; 326 return 0; 327} --- 40 unchanged lines hidden --- | 326 if (def == NULL) 327 return -1; 328 target = (Elf_Addr)(defobj->relocbase + def->st_value); 329 reloc_jmpslot(where, target, defobj, obj, rel); 330 } 331 obj->jmpslots_done = true; 332 return 0; 333} --- 40 unchanged lines hidden --- |