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/amd64/reloc.c 208256 2010-05-18 08:55:23Z rdivacky $ | 25 * $FreeBSD: head/libexec/rtld-elf/amd64/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 --- 30 unchanged lines hidden (view full) --- 64 assert(dstobj->mainprog); /* COPY relocations are invalid elsewhere */ 65 66 relalim = (const Elf_Rela *) ((caddr_t) dstobj->rela + dstobj->relasize); 67 for (rela = dstobj->rela; rela < relalim; rela++) { 68 if (ELF_R_TYPE(rela->r_info) == R_X86_64_COPY) { 69 void *dstaddr; 70 const Elf_Sym *dstsym; 71 const char *name; | 26 */ 27 28/* 29 * Dynamic linker for ELF. 30 * 31 * John Polstra <jdp@polstra.com>. 32 */ 33 --- 30 unchanged lines hidden (view full) --- 64 assert(dstobj->mainprog); /* COPY relocations are invalid elsewhere */ 65 66 relalim = (const Elf_Rela *) ((caddr_t) dstobj->rela + dstobj->relasize); 67 for (rela = dstobj->rela; rela < relalim; rela++) { 68 if (ELF_R_TYPE(rela->r_info) == R_X86_64_COPY) { 69 void *dstaddr; 70 const Elf_Sym *dstsym; 71 const char *name; |
72 unsigned long hash; | |
73 size_t size; 74 const void *srcaddr; 75 const Elf_Sym *srcsym; | 72 size_t size; 73 const void *srcaddr; 74 const Elf_Sym *srcsym; |
76 Obj_Entry *srcobj; 77 const Ver_Entry *ve; | 75 const Obj_Entry *srcobj, *defobj; 76 SymLook req; 77 int res; |
78 79 dstaddr = (void *) (dstobj->relocbase + rela->r_offset); 80 dstsym = dstobj->symtab + ELF_R_SYM(rela->r_info); 81 name = dstobj->strtab + dstsym->st_name; | 78 79 dstaddr = (void *) (dstobj->relocbase + rela->r_offset); 80 dstsym = dstobj->symtab + ELF_R_SYM(rela->r_info); 81 name = dstobj->strtab + dstsym->st_name; |
82 hash = elf_hash(name); | |
83 size = dstsym->st_size; | 82 size = dstsym->st_size; |
84 ve = fetch_ventry(dstobj, ELF_R_SYM(rela->r_info)); | 83 symlook_init(&req, name); 84 req.ventry = fetch_ventry(dstobj, ELF_R_SYM(rela->r_info)); |
85 | 85 |
86 for (srcobj = dstobj->next; srcobj != NULL; srcobj = srcobj->next) 87 if ((srcsym = symlook_obj(name, hash, srcobj, ve, 0)) != NULL) | 86 for (srcobj = dstobj->next; srcobj != NULL; srcobj = srcobj->next) { 87 res = symlook_obj(&req, srcobj); 88 if (res == 0) { 89 srcsym = req.sym_out; 90 defobj = req.defobj_out; |
88 break; | 91 break; |
92 } 93 } |
|
89 90 if (srcobj == NULL) { 91 _rtld_error("Undefined symbol \"%s\" referenced from COPY" 92 " relocation in %s", name, dstobj->path); 93 return -1; 94 } 95 | 94 95 if (srcobj == NULL) { 96 _rtld_error("Undefined symbol \"%s\" referenced from COPY" 97 " relocation in %s", name, dstobj->path); 98 return -1; 99 } 100 |
96 srcaddr = (const void *) (srcobj->relocbase + srcsym->st_value); | 101 srcaddr = (const void *) (defobj->relocbase + srcsym->st_value); |
97 memcpy(dstaddr, srcaddr, size); 98 } 99 } 100 101 return 0; 102} 103 104/* Initialize the special GOT entries. */ 105void 106init_pltgot(Obj_Entry *obj) 107{ 108 if (obj->pltgot != NULL) { 109 obj->pltgot[1] = (Elf_Addr) obj; 110 obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start; 111 } 112} 113 114/* Process the non-PLT relocations. */ 115int | 102 memcpy(dstaddr, srcaddr, size); 103 } 104 } 105 106 return 0; 107} 108 109/* Initialize the special GOT entries. */ 110void 111init_pltgot(Obj_Entry *obj) 112{ 113 if (obj->pltgot != NULL) { 114 obj->pltgot[1] = (Elf_Addr) obj; 115 obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start; 116 } 117} 118 119/* Process the non-PLT relocations. */ 120int |
116reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld) | 121reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, RtldLockState *lockstate) |
117{ 118 const Elf_Rela *relalim; 119 const Elf_Rela *rela; 120 SymCache *cache; 121 int r = -1; 122 123 /* 124 * The dynamic loader may be called from a thread, we have --- 16 unchanged lines hidden (view full) --- 141 break; 142 143 case R_X86_64_64: 144 { 145 const Elf_Sym *def; 146 const Obj_Entry *defobj; 147 148 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, | 122{ 123 const Elf_Rela *relalim; 124 const Elf_Rela *rela; 125 SymCache *cache; 126 int r = -1; 127 128 /* 129 * The dynamic loader may be called from a thread, we have --- 16 unchanged lines hidden (view full) --- 146 break; 147 148 case R_X86_64_64: 149 { 150 const Elf_Sym *def; 151 const Obj_Entry *defobj; 152 153 def = find_symdef(ELF_R_SYM(rela->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 + rela->r_addend); 154 } 155 break; 156 157 case R_X86_64_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(rela->r_info), obj, &defobj, | 155 if (def == NULL) 156 goto done; 157 158 *where = (Elf_Addr) (defobj->relocbase + def->st_value + rela->r_addend); 159 } 160 break; 161 162 case R_X86_64_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(rela->r_info), obj, &defobj, |
168 false, cache); | 173 false, cache, lockstate); |
169 if (def == NULL) 170 goto done; 171 172 *where32 = (Elf32_Addr) (unsigned long) (defobj->relocbase + 173 def->st_value + rela->r_addend - (Elf_Addr) where); 174 } 175 break; 176 /* missing: R_X86_64_GOT32 R_X86_64_PLT32 */ --- 13 unchanged lines hidden (view full) --- 190 break; 191 192 case R_X86_64_GLOB_DAT: 193 { 194 const Elf_Sym *def; 195 const Obj_Entry *defobj; 196 197 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, | 174 if (def == NULL) 175 goto done; 176 177 *where32 = (Elf32_Addr) (unsigned long) (defobj->relocbase + 178 def->st_value + rela->r_addend - (Elf_Addr) where); 179 } 180 break; 181 /* missing: R_X86_64_GOT32 R_X86_64_PLT32 */ --- 13 unchanged lines hidden (view full) --- 195 break; 196 197 case R_X86_64_GLOB_DAT: 198 { 199 const Elf_Sym *def; 200 const Obj_Entry *defobj; 201 202 def = find_symdef(ELF_R_SYM(rela->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_X86_64_TPOFF64: 207 { 208 const Elf_Sym *def; 209 const Obj_Entry *defobj; 210 211 def = find_symdef(ELF_R_SYM(rela->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_X86_64_TPOFF64: 212 { 213 const Elf_Sym *def; 214 const Obj_Entry *defobj; 215 216 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, |
212 false, cache); | 217 false, cache, lockstate); |
213 if (def == NULL) 214 goto done; 215 216 /* 217 * We lazily allocate offsets for static TLS as we 218 * see the first relocation that references the 219 * TLS block. This allows us to support (small 220 * amounts of) static TLS in dynamically loaded --- 14 unchanged lines hidden (view full) --- 235 break; 236 237 case R_X86_64_TPOFF32: 238 { 239 const Elf_Sym *def; 240 const Obj_Entry *defobj; 241 242 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, | 218 if (def == NULL) 219 goto done; 220 221 /* 222 * We lazily allocate offsets for static TLS as we 223 * see the first relocation that references the 224 * TLS block. This allows us to support (small 225 * amounts of) static TLS in dynamically loaded --- 14 unchanged lines hidden (view full) --- 240 break; 241 242 case R_X86_64_TPOFF32: 243 { 244 const Elf_Sym *def; 245 const Obj_Entry *defobj; 246 247 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, |
243 false, cache); | 248 false, cache, lockstate); |
244 if (def == NULL) 245 goto done; 246 247 /* 248 * We lazily allocate offsets for static TLS as we 249 * see the first relocation that references the 250 * TLS block. This allows us to support (small 251 * amounts of) static TLS in dynamically loaded --- 15 unchanged lines hidden (view full) --- 267 break; 268 269 case R_X86_64_DTPMOD64: 270 { 271 const Elf_Sym *def; 272 const Obj_Entry *defobj; 273 274 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, | 249 if (def == NULL) 250 goto done; 251 252 /* 253 * We lazily allocate offsets for static TLS as we 254 * see the first relocation that references the 255 * TLS block. This allows us to support (small 256 * amounts of) static TLS in dynamically loaded --- 15 unchanged lines hidden (view full) --- 272 break; 273 274 case R_X86_64_DTPMOD64: 275 { 276 const Elf_Sym *def; 277 const Obj_Entry *defobj; 278 279 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, |
275 false, cache); | 280 false, cache, lockstate); |
276 if (def == NULL) 277 goto done; 278 279 *where += (Elf_Addr) defobj->tlsindex; 280 } 281 break; 282 283 case R_X86_64_DTPOFF64: 284 { 285 const Elf_Sym *def; 286 const Obj_Entry *defobj; 287 288 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, | 281 if (def == NULL) 282 goto done; 283 284 *where += (Elf_Addr) defobj->tlsindex; 285 } 286 break; 287 288 case R_X86_64_DTPOFF64: 289 { 290 const Elf_Sym *def; 291 const Obj_Entry *defobj; 292 293 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, |
289 false, cache); | 294 false, cache, lockstate); |
290 if (def == NULL) 291 goto done; 292 293 *where += (Elf_Addr) (def->st_value + rela->r_addend); 294 } 295 break; 296 297 case R_X86_64_DTPOFF32: 298 { 299 const Elf_Sym *def; 300 const Obj_Entry *defobj; 301 302 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, | 295 if (def == NULL) 296 goto done; 297 298 *where += (Elf_Addr) (def->st_value + rela->r_addend); 299 } 300 break; 301 302 case R_X86_64_DTPOFF32: 303 { 304 const Elf_Sym *def; 305 const Obj_Entry *defobj; 306 307 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, |
303 false, cache); | 308 false, cache, lockstate); |
304 if (def == NULL) 305 goto done; 306 307 *where32 += (Elf32_Addr) (def->st_value + rela->r_addend); 308 } 309 break; 310 311 case R_X86_64_RELATIVE: --- 33 unchanged lines hidden (view full) --- 345 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 346 *where += (Elf_Addr)obj->relocbase; 347 } 348 return 0; 349} 350 351/* Relocate the jump slots in an object. */ 352int | 309 if (def == NULL) 310 goto done; 311 312 *where32 += (Elf32_Addr) (def->st_value + rela->r_addend); 313 } 314 break; 315 316 case R_X86_64_RELATIVE: --- 33 unchanged lines hidden (view full) --- 350 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); 351 *where += (Elf_Addr)obj->relocbase; 352 } 353 return 0; 354} 355 356/* Relocate the jump slots in an object. */ 357int |
353reloc_jmpslots(Obj_Entry *obj) | 358reloc_jmpslots(Obj_Entry *obj, RtldLockState *lockstate) |
354{ 355 const Elf_Rela *relalim; 356 const Elf_Rela *rela; 357 358 if (obj->jmpslots_done) 359 return 0; 360 relalim = (const Elf_Rela *)((char *)obj->pltrela + obj->pltrelasize); 361 for (rela = obj->pltrela; rela < relalim; rela++) { 362 Elf_Addr *where, target; 363 const Elf_Sym *def; 364 const Obj_Entry *defobj; 365 366 assert(ELF_R_TYPE(rela->r_info) == R_X86_64_JMP_SLOT); 367 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); | 359{ 360 const Elf_Rela *relalim; 361 const Elf_Rela *rela; 362 363 if (obj->jmpslots_done) 364 return 0; 365 relalim = (const Elf_Rela *)((char *)obj->pltrela + obj->pltrelasize); 366 for (rela = obj->pltrela; rela < relalim; rela++) { 367 Elf_Addr *where, target; 368 const Elf_Sym *def; 369 const Obj_Entry *defobj; 370 371 assert(ELF_R_TYPE(rela->r_info) == R_X86_64_JMP_SLOT); 372 where = (Elf_Addr *)(obj->relocbase + rela->r_offset); |
368 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, true, NULL); | 373 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, true, NULL, 374 lockstate); |
369 if (def == NULL) 370 return -1; 371 target = (Elf_Addr)(defobj->relocbase + def->st_value + rela->r_addend); 372 reloc_jmpslot(where, target, defobj, obj, (const Elf_Rel *)rela); 373 } 374 obj->jmpslots_done = true; 375 return 0; 376} --- 24 unchanged lines hidden --- | 375 if (def == NULL) 376 return -1; 377 target = (Elf_Addr)(defobj->relocbase + def->st_value + rela->r_addend); 378 reloc_jmpslot(where, target, defobj, obj, (const Elf_Rel *)rela); 379 } 380 obj->jmpslots_done = true; 381 return 0; 382} --- 24 unchanged lines hidden --- |