Deleted Added
full compact
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 ---