2 * Copyright 1996, 1997, 1998, 1999 John D. Polstra.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
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.
29 * Dynamic linker for ELF.
31 * John Polstra <jdp@polstra.com>.
34 #include <sys/param.h>
50 extern Elf_Dyn _GOT_END_;
53 * Macros for loading/storing unaligned 64-bit values. These are
54 * needed because relocations can point to unaligned data. This
55 * occurs in the DWARF2 exception frame tables generated by the
56 * compiler, for instance.
58 * We don't use these when relocating jump slots and GOT entries,
59 * since they are guaranteed to be aligned.
63 Elf_Addr x __attribute__((packed));
66 #define load64(p) (((struct ualong *)(p))->x)
67 #define store64(p,v) (((struct ualong *)(p))->x = (v))
69 /* Relocate a non-PLT object with addend. */
71 reloc_non_plt_obj(Obj_Entry *obj_rtld, Obj_Entry *obj, const Elf_Rela *rela,
74 Elf_Addr *where = (Elf_Addr *) (obj->relocbase + rela->r_offset);
76 switch (ELF_R_TYPE(rela->r_info)) {
81 case R_ALPHA_REFQUAD: {
83 const Obj_Entry *defobj;
85 def = find_symdef(ELF_R_SYM(rela->r_info), obj,
86 &defobj, false, cache);
90 (Elf_Addr) (defobj->relocbase + def->st_value) +
91 load64(where) + rela->r_addend);
95 case R_ALPHA_GLOB_DAT: {
97 const Obj_Entry *defobj;
100 def = find_symdef(ELF_R_SYM(rela->r_info), obj,
101 &defobj, false, cache);
104 val = (Elf_Addr) (defobj->relocbase + def->st_value +
106 if (load64(where) != val)
111 case R_ALPHA_RELATIVE: {
112 if (obj != obj_rtld ||
113 (caddr_t)where < (caddr_t)_GLOBAL_OFFSET_TABLE_ ||
114 (caddr_t)where >= (caddr_t)&_GOT_END_)
116 load64(where) + (Elf_Addr) obj->relocbase);
122 * These are deferred until all other relocations
123 * have been done. All we do here is make sure
124 * that the COPY relocation is not in a shared
125 * library. They are allowed only in executable
128 if (!obj->mainprog) {
129 _rtld_error("%s: Unexpected R_COPY "
130 " relocation in shared library",
138 _rtld_error("%s: Unsupported relocation type %u"
139 " in non-PLT relocations\n", obj->path,
140 (unsigned int)ELF_R_TYPE(rela->r_info));
146 /* Process the non-PLT relocations. */
148 reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld)
150 const Elf_Rel *rellim;
152 const Elf_Rela *relalim;
153 const Elf_Rela *rela;
155 int bytes = obj->nchains * sizeof(SymCache);
159 * The dynamic loader may be called from a thread, we have
160 * limited amounts of stack available so we cannot use alloca().
162 cache = mmap(NULL, bytes, PROT_READ|PROT_WRITE, MAP_ANON, -1, 0);
163 if (cache == MAP_FAILED)
166 /* Perform relocations without addend if there are any: */
167 rellim = (const Elf_Rel *) ((caddr_t) obj->rel + obj->relsize);
168 for (rel = obj->rel; obj->rel != NULL && rel < rellim; rel++) {
171 locrela.r_info = rel->r_info;
172 locrela.r_offset = rel->r_offset;
173 locrela.r_addend = 0;
174 if (reloc_non_plt_obj(obj_rtld, obj, &locrela, cache))
178 /* Perform relocations with addend if there are any: */
179 relalim = (const Elf_Rela *) ((caddr_t) obj->rela + obj->relasize);
180 for (rela = obj->rela; obj->rela != NULL && rela < relalim; rela++) {
181 if (reloc_non_plt_obj(obj_rtld, obj, rela, cache))
187 munmap(cache, bytes);
191 /* Process the PLT relocations. */
193 reloc_plt(Obj_Entry *obj)
195 /* All PLT relocations are the same kind: either Elf_Rel or Elf_Rela. */
196 if (obj->pltrelsize != 0) {
197 const Elf_Rel *rellim;
200 rellim = (const Elf_Rel *)((char *)obj->pltrel + obj->pltrelsize);
201 for (rel = obj->pltrel; rel < rellim; rel++) {
204 assert(ELF_R_TYPE(rel->r_info) == R_ALPHA_JMP_SLOT);
206 /* Relocate the GOT slot pointing into the PLT. */
207 where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
208 *where += (Elf_Addr)obj->relocbase;
211 const Elf_Rela *relalim;
212 const Elf_Rela *rela;
214 relalim = (const Elf_Rela *)((char *)obj->pltrela + obj->pltrelasize);
215 for (rela = obj->pltrela; rela < relalim; rela++) {
218 assert(ELF_R_TYPE(rela->r_info) == R_ALPHA_JMP_SLOT);
220 /* Relocate the GOT slot pointing into the PLT. */
221 where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
222 *where += (Elf_Addr)obj->relocbase;
228 /* Relocate the jump slots in an object. */
230 reloc_jmpslots(Obj_Entry *obj)
232 if (obj->jmpslots_done)
234 /* All PLT relocations are the same kind: either Elf_Rel or Elf_Rela. */
235 if (obj->pltrelsize != 0) {
236 const Elf_Rel *rellim;
239 rellim = (const Elf_Rel *)((char *)obj->pltrel + obj->pltrelsize);
240 for (rel = obj->pltrel; rel < rellim; rel++) {
243 const Obj_Entry *defobj;
245 assert(ELF_R_TYPE(rel->r_info) == R_ALPHA_JMP_SLOT);
246 where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
247 def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, true,
252 (Elf_Addr)(defobj->relocbase + def->st_value),
256 const Elf_Rela *relalim;
257 const Elf_Rela *rela;
259 relalim = (const Elf_Rela *)((char *)obj->pltrela + obj->pltrelasize);
260 for (rela = obj->pltrela; rela < relalim; rela++) {
263 const Obj_Entry *defobj;
265 assert(ELF_R_TYPE(rela->r_info) == R_ALPHA_JMP_SLOT);
266 where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
267 def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, true,
272 (Elf_Addr)(defobj->relocbase + def->st_value),
273 defobj, obj, (Elf_Rel *)rela);
276 obj->jmpslots_done = true;
280 /* Fixup the jump slot at "where" to transfer control to "target". */
282 reloc_jmpslot(Elf_Addr *where, Elf_Addr target, const Obj_Entry *obj,
283 const Obj_Entry *refobj, const Elf_Rel *rel)
287 dbg(" reloc_jmpslot: where=%p, target=%p", (void *)where, (void *)target);
289 if (stubaddr != target) {
297 /* Point this GOT entry directly at the target. */
301 * There may be multiple GOT tables, each with an entry
302 * pointing to the stub in the PLT. But we can only find and
303 * fix up the first GOT entry. So we must rewrite the stub as
304 * well, to perform a call to the target if it is executed.
306 * When the stub gets control, register pv ($27) contains its
307 * address. We adjust its value so that it points to the
308 * target, and then jump indirect through it.
310 * Each PLT entry has room for 3 instructions. If the
311 * adjustment amount fits in a signed 32-bit integer, we can
312 * simply add it to register pv. Otherwise we must load the
313 * GOT entry itself into the pv register.
315 delta = target - stubaddr;
316 dbg(" stubaddr=%p, where-stubaddr=%ld, delta=%ld", (void *)stubaddr,
317 (long)where - (long)stubaddr, (long)delta);
319 if ((int32_t)delta == delta) {
321 * We can adjust pv with a LDA, LDAH sequence.
323 * First build an LDA instruction to adjust the low 16 bits.
325 inst[instct++] = 0x08 << 26 | 27 << 21 | 27 << 16 |
327 dbg(" LDA $27,%d($27)", (int16_t)delta);
329 * Adjust the delta to account for the effects of the LDA,
330 * including sign-extension.
332 delta -= (int16_t)delta;
334 /* Build an LDAH instruction to adjust the high 16 bits. */
335 inst[instct++] = 0x09 << 26 | 27 << 21 | 27 << 16 |
336 (delta >> 16 & 0xffff);
337 dbg(" LDAH $27,%d($27)", (int16_t)(delta >> 16));
342 /* We must load the GOT entry from memory. */
343 delta = (Elf_Addr)where - stubaddr;
345 * If the GOT entry is too far away from the PLT entry,
346 * then punt. This PLT entry will have to be looked up
347 * manually for all GOT entries except the first one.
348 * The program will still run, albeit very slowly. It's
349 * extremely unlikely that this case could ever arise in
350 * practice, but we might as well handle it correctly if
353 if ((int32_t)delta != delta) {
354 dbg(" PLT stub too far from GOT to relocate");
357 dhigh = delta - (int16_t)delta;
359 /* Build an LDAH instruction to adjust the high 16 bits. */
360 inst[instct++] = 0x09 << 26 | 27 << 21 | 27 << 16 |
361 (dhigh >> 16 & 0xffff);
362 dbg(" LDAH $27,%d($27)", (int16_t)(dhigh >> 16));
364 /* Build an LDQ to load the GOT entry. */
365 inst[instct++] = 0x29 << 26 | 27 << 21 | 27 << 16 |
367 dbg(" LDQ $27,%d($27)", (int16_t)delta);
371 * Build a JMP or BR instruction to jump to the target. If
372 * the instruction displacement fits in a sign-extended 21-bit
373 * field, we can use the more efficient BR instruction.
374 * Otherwise we have to jump indirect through the pv register.
376 pc = stubaddr + 4 * (instct + 1);
377 idisp = (int64_t)(target - pc) >> 2;
378 if (-0x100000 <= idisp && idisp < 0x100000) {
379 inst[instct++] = 0x30 << 26 | 31 << 21 | (idisp & 0x1fffff);
380 dbg(" BR $31,%p", (void *)target);
382 inst[instct++] = 0x1a << 26 | 31 << 21 | 27 << 16 |
384 dbg(" JMP $31,($27),%d", (int)(idisp & 0x3fff));
388 * Fill in the tail of the PLT entry first for reentrancy.
389 * Until we have overwritten the first instruction (an
390 * unconditional branch), the remaining instructions have no
393 stubptr = (u_int32_t *)stubaddr;
396 stubptr[instct] = inst[instct];
399 * Commit the tail of the instruction sequence to memory
400 * before overwriting the first instruction.
402 __asm__ __volatile__("wmb" : : : "memory");
403 stubptr[0] = inst[0];
409 /* Process an R_ALPHA_COPY relocation. */
411 do_copy_relocation(Obj_Entry *dstobj, const Elf_Rela *rela)
414 const Elf_Sym *dstsym;
419 const Elf_Sym *srcsym;
422 dstaddr = (void *) (dstobj->relocbase + rela->r_offset);
423 dstsym = dstobj->symtab + ELF_R_SYM(rela->r_info);
424 name = dstobj->strtab + dstsym->st_name;
425 hash = elf_hash(name);
426 size = dstsym->st_size;
428 for (srcobj = dstobj->next; srcobj != NULL; srcobj = srcobj->next)
429 if ((srcsym = symlook_obj(name, hash, srcobj, false)) != NULL)
432 if (srcobj == NULL) {
433 _rtld_error("Undefined symbol \"%s\" referenced from COPY"
434 " relocation in %s", name, dstobj->path);
438 srcaddr = (const void *) (srcobj->relocbase + srcsym->st_value);
439 memcpy(dstaddr, srcaddr, size);
444 * Process the special R_ALPHA_COPY relocations in the main program. These
445 * copy data from a shared object into a region in the main program's BSS
448 * Returns 0 on success, -1 on failure.
451 do_copy_relocations(Obj_Entry *dstobj)
453 const Elf_Rel *rellim;
455 const Elf_Rela *relalim;
456 const Elf_Rela *rela;
458 assert(dstobj->mainprog); /* COPY relocations are invalid elsewhere */
460 rellim = (const Elf_Rel *) ((caddr_t) dstobj->rel + dstobj->relsize);
461 for (rel = dstobj->rel; dstobj->rel != NULL && rel < rellim; rel++) {
462 if (ELF_R_TYPE(rel->r_info) == R_ALPHA_COPY) {
465 locrela.r_info = rel->r_info;
466 locrela.r_offset = rel->r_offset;
467 locrela.r_addend = 0;
468 if (do_copy_relocation(dstobj, &locrela))
473 relalim = (const Elf_Rela *) ((caddr_t) dstobj->rela +
475 for (rela = dstobj->rela; dstobj->rela != NULL && rela < relalim;
477 if (ELF_R_TYPE(rela->r_info) == R_ALPHA_COPY) {
478 if (do_copy_relocation(dstobj, rela))
486 /* Initialize the special PLT entries. */
488 init_pltgot(Obj_Entry *obj)
492 if (obj->pltgot != NULL &&
493 (obj->pltrelsize != 0 || obj->pltrelasize != 0)) {
495 * This function will be called to perform the relocation.
496 * Look for the ldah instruction from the old PLT format since
497 * that will tell us what format we are trying to relocate.
499 pltgot = (u_int32_t *) obj->pltgot;
500 if ((pltgot[8] & 0xffff0000) == 0x279f0000)
501 obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start_old;
503 obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start;
504 /* Identify this shared object */
505 obj->pltgot[3] = (Elf_Addr) obj;
510 allocate_initial_tls(Obj_Entry *list)
515 * Fix the size of the static TLS block by using the maximum
516 * offset allocated so far and adding a bit for dynamic modules to
519 tls_static_space = tls_last_offset + tls_last_size + RTLD_STATIC_TLS_EXTRA;
520 tls = allocate_tls(list, 0, 16, 16);
521 alpha_pal_wrunique((u_int64_t) tls);
524 void *__tls_get_addr(tls_index* ti)
526 Elf_Addr** tp = (Elf_Addr**) alpha_pal_rdunique();
528 return tls_get_addr_common(tp, ti->ti_module, ti->ti_offset);