1 /* $NetBSD: mdreloc.c,v 1.23 2003/07/26 15:04:38 mrg Exp $ */
15 #include "machine/sysarch.h"
23 * On processors that have hard floating point supported, we also support
24 * running soft float binaries. If we're being built with hard float support,
25 * check the ELF headers to make sure that this is a hard float binary. If it is
26 * a soft float binary, force the dynamic linker to use the alternative soft
30 arm_abi_variant_hook(Elf_Auxinfo **aux_info)
35 * If we're running an old kernel that doesn't provide any data fail
36 * safe by doing nothing.
38 if (aux_info[AT_EHDRFLAGS] == NULL)
40 ehdr = aux_info[AT_EHDRFLAGS]->a_un.a_val;
43 * Hard float ABI binaries are the default, and use the default paths
46 if ((ehdr & EF_ARM_VFP_FLOAT) != 0)
50 * This is a soft float ABI binary. We need to use the soft float
53 ld_elf_hints_default = _PATH_SOFT_ELF_HINTS;
54 ld_path_libmap_conf = _PATH_SOFT_LIBMAP_CONF;
55 ld_path_rtld = _PATH_SOFT_RTLD;
56 ld_standard_library_path = SOFT_STANDARD_LIBRARY_PATH;
57 ld_env_prefix = LD_SOFT_;
62 init_pltgot(Obj_Entry *obj)
64 if (obj->pltgot != NULL) {
65 obj->pltgot[1] = (Elf_Addr) obj;
66 obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start;
71 do_copy_relocations(Obj_Entry *dstobj)
73 const Elf_Rel *rellim;
76 assert(dstobj->mainprog); /* COPY relocations are invalid elsewhere */
78 rellim = (const Elf_Rel *)((const char *) dstobj->rel + dstobj->relsize);
79 for (rel = dstobj->rel; rel < rellim; rel++) {
80 if (ELF_R_TYPE(rel->r_info) == R_ARM_COPY) {
82 const Elf_Sym *dstsym;
86 const Elf_Sym *srcsym;
87 const Obj_Entry *srcobj, *defobj;
91 dstaddr = (void *)(dstobj->relocbase + rel->r_offset);
92 dstsym = dstobj->symtab + ELF_R_SYM(rel->r_info);
93 name = dstobj->strtab + dstsym->st_name;
94 size = dstsym->st_size;
96 symlook_init(&req, name);
97 req.ventry = fetch_ventry(dstobj,
98 ELF_R_SYM(rel->r_info));
99 req.flags = SYMLOOK_EARLY;
101 for (srcobj = globallist_next(dstobj); srcobj != NULL;
102 srcobj = globallist_next(srcobj)) {
103 res = symlook_obj(&req, srcobj);
105 srcsym = req.sym_out;
106 defobj = req.defobj_out;
110 if (srcobj == NULL) {
112 "Undefined symbol \"%s\" referenced from COPY relocation in %s",
117 srcaddr = (const void *)(defobj->relocbase +
119 memcpy(dstaddr, srcaddr, size);
125 void _rtld_bind_start(void);
126 void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr);
129 _rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase)
131 const Elf_Rel *rel = NULL, *rellim;
136 for (; dynp->d_tag != DT_NULL; dynp++) {
137 switch (dynp->d_tag) {
139 rel = (const Elf_Rel *)(relocbase + dynp->d_un.d_ptr);
142 relsz = dynp->d_un.d_val;
146 rellim = (const Elf_Rel *)((const char *)rel + relsz);
147 size = (rellim - 1)->r_offset - rel->r_offset;
148 for (; rel < rellim; rel++) {
149 where = (Elf_Addr *)(relocbase + rel->r_offset);
151 *where += (Elf_Addr)relocbase;
155 * It is possible for the compiler to emit relocations for unaligned data.
156 * We handle this situation with these inlines.
158 #define RELOC_ALIGNED_P(x) \
159 (((uintptr_t)(x) & (sizeof(void *) - 1)) == 0)
161 static __inline Elf_Addr
162 load_ptr(void *where)
166 memcpy(&res, where, sizeof(res));
172 store_ptr(void *where, Elf_Addr val)
175 memcpy(where, &val, sizeof(val));
179 reloc_nonplt_object(Obj_Entry *obj, const Elf_Rel *rel, SymCache *cache,
180 int flags, RtldLockState *lockstate)
184 const Obj_Entry *defobj;
186 unsigned long symnum;
188 where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
189 symnum = ELF_R_SYM(rel->r_info);
191 switch (ELF_R_TYPE(rel->r_info)) {
195 #if 1 /* XXX should not occur */
196 case R_ARM_PC24: { /* word32 S - P + A */
200 * Extract addend and sign-extend if needed.
203 if (addend & 0x00800000)
204 addend |= 0xff000000;
206 def = find_symdef(symnum, obj, &defobj, flags, cache,
210 tmp = (Elf_Addr)obj->relocbase + def->st_value
211 - (Elf_Addr)where + (addend << 2);
212 if ((tmp & 0xfe000000) != 0xfe000000 &&
213 (tmp & 0xfe000000) != 0) {
215 "%s: R_ARM_PC24 relocation @ %p to %s failed "
216 "(displacement %ld (%#lx) out of range)",
218 obj->strtab + obj->symtab[symnum].st_name,
219 (long) tmp, (long) tmp);
223 *where = (*where & 0xff000000) | (tmp & 0x00ffffff);
224 dbg("PC24 %s in %s --> %p @ %p in %s",
225 obj->strtab + obj->symtab[symnum].st_name,
226 obj->path, (void *)*where, where, defobj->path);
231 case R_ARM_ABS32: /* word32 B + S + A */
232 case R_ARM_GLOB_DAT: /* word32 B + S */
233 def = find_symdef(symnum, obj, &defobj, flags, cache,
237 if (__predict_true(RELOC_ALIGNED_P(where))) {
238 tmp = *where + (Elf_Addr)defobj->relocbase +
242 tmp = load_ptr(where) +
243 (Elf_Addr)defobj->relocbase +
245 store_ptr(where, tmp);
247 dbg("ABS32/GLOB_DAT %s in %s --> %p @ %p in %s",
248 obj->strtab + obj->symtab[symnum].st_name,
249 obj->path, (void *)tmp, where, defobj->path);
252 case R_ARM_RELATIVE: /* word32 B + A */
253 if (__predict_true(RELOC_ALIGNED_P(where))) {
254 tmp = *where + (Elf_Addr)obj->relocbase;
257 tmp = load_ptr(where) +
258 (Elf_Addr)obj->relocbase;
259 store_ptr(where, tmp);
261 dbg("RELATIVE in %s --> %p", obj->path,
267 * These are deferred until all other relocations have
268 * been done. All we do here is make sure that the
269 * COPY relocation is not in a shared library. They
270 * are allowed only in executable files.
272 if (!obj->mainprog) {
274 "%s: Unexpected R_COPY relocation in shared library",
278 dbg("COPY (avoid in main)");
281 case R_ARM_TLS_DTPOFF32:
282 def = find_symdef(symnum, obj, &defobj, flags, cache,
287 tmp = (Elf_Addr)(def->st_value);
288 if (__predict_true(RELOC_ALIGNED_P(where)))
291 store_ptr(where, tmp);
293 dbg("TLS_DTPOFF32 %s in %s --> %p",
294 obj->strtab + obj->symtab[symnum].st_name,
295 obj->path, (void *)tmp);
298 case R_ARM_TLS_DTPMOD32:
299 def = find_symdef(symnum, obj, &defobj, flags, cache,
304 tmp = (Elf_Addr)(defobj->tlsindex);
305 if (__predict_true(RELOC_ALIGNED_P(where)))
308 store_ptr(where, tmp);
310 dbg("TLS_DTPMOD32 %s in %s --> %p",
311 obj->strtab + obj->symtab[symnum].st_name,
312 obj->path, (void *)tmp);
316 case R_ARM_TLS_TPOFF32:
317 def = find_symdef(symnum, obj, &defobj, flags, cache,
322 if (!defobj->tls_done && !allocate_tls_offset(obj))
325 tmp = (Elf_Addr)def->st_value + defobj->tlsoffset;
326 if (__predict_true(RELOC_ALIGNED_P(where)))
329 store_ptr(where, tmp);
330 dbg("TLS_TPOFF32 %s in %s --> %p",
331 obj->strtab + obj->symtab[symnum].st_name,
332 obj->path, (void *)tmp);
337 dbg("sym = %lu, type = %lu, offset = %p, "
338 "contents = %p, symbol = %s",
339 symnum, (u_long)ELF_R_TYPE(rel->r_info),
340 (void *)rel->r_offset, (void *)load_ptr(where),
341 obj->strtab + obj->symtab[symnum].st_name);
342 _rtld_error("%s: Unsupported relocation type %ld "
343 "in non-PLT relocations\n",
344 obj->path, (u_long) ELF_R_TYPE(rel->r_info));
351 * * Process non-PLT relocations
354 reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags,
355 RtldLockState *lockstate)
357 const Elf_Rel *rellim;
362 /* The relocation for the dynamic loader has already been done. */
365 if ((flags & SYMLOOK_IFUNC) != 0)
366 /* XXX not implemented */
370 * The dynamic loader may be called from a thread, we have
371 * limited amounts of stack available so we cannot use alloca().
373 cache = calloc(obj->dynsymcount, sizeof(SymCache));
374 /* No need to check for NULL here */
376 rellim = (const Elf_Rel *)((const char *)obj->rel + obj->relsize);
377 for (rel = obj->rel; rel < rellim; rel++) {
378 if (reloc_nonplt_object(obj, rel, cache, flags, lockstate) < 0)
389 * * Process the PLT relocations.
392 reloc_plt(Obj_Entry *obj, int flags __unused, RtldLockState *lockstate __unused)
394 const Elf_Rel *rellim;
397 rellim = (const Elf_Rel *)((const char *)obj->pltrel +
399 for (rel = obj->pltrel; rel < rellim; rel++) {
402 assert(ELF_R_TYPE(rel->r_info) == R_ARM_JUMP_SLOT);
404 where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
405 *where += (Elf_Addr )obj->relocbase;
412 * * LD_BIND_NOW was set - force relocation for all jump slots
415 reloc_jmpslots(Obj_Entry *obj, int flags, RtldLockState *lockstate)
417 const Obj_Entry *defobj;
418 const Elf_Rel *rellim;
424 rellim = (const Elf_Rel *)((const char *)obj->pltrel + obj->pltrelsize);
425 for (rel = obj->pltrel; rel < rellim; rel++) {
426 assert(ELF_R_TYPE(rel->r_info) == R_ARM_JUMP_SLOT);
427 where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
428 def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
429 SYMLOOK_IN_PLT | flags, NULL, lockstate);
431 dbg("reloc_jmpslots: sym not found");
435 target = (Elf_Addr)(defobj->relocbase + def->st_value);
436 reloc_jmpslot(where, target, defobj, obj,
437 (const Elf_Rel *) rel);
440 obj->jmpslots_done = true;
446 reloc_iresolve(Obj_Entry *obj __unused,
447 struct Struct_RtldLockState *lockstate __unused)
450 /* XXX not implemented */
455 reloc_iresolve_nonplt(Obj_Entry *obj __unused,
456 struct Struct_RtldLockState *lockstate __unused)
459 /* XXX not implemented */
464 reloc_gnu_ifunc(Obj_Entry *obj __unused, int flags __unused,
465 struct Struct_RtldLockState *lockstate __unused)
468 /* XXX not implemented */
473 reloc_jmpslot(Elf_Addr *where, Elf_Addr target,
474 const Obj_Entry *defobj __unused, const Obj_Entry *obj __unused,
478 assert(ELF_R_TYPE(rel->r_info) == R_ARM_JUMP_SLOT);
480 if (*where != target && !ld_bind_not)
486 ifunc_init(Elf_Auxinfo aux_info[__min_size(AT_COUNT)] __unused)
492 allocate_initial_tls(Obj_Entry *objs)
494 #ifdef ARM_TP_ADDRESS
495 void **_tp = (void **)ARM_TP_ADDRESS;
499 * Fix the size of the static TLS block by using the maximum
500 * offset allocated so far and adding a bit for dynamic modules to
504 tls_static_space = tls_last_offset + tls_last_size + RTLD_STATIC_TLS_EXTRA;
506 #ifdef ARM_TP_ADDRESS
507 (*_tp) = (void *) allocate_tls(objs, NULL, TLS_TCB_SIZE, 8);
509 sysarch(ARM_SET_TP, allocate_tls(objs, NULL, TLS_TCB_SIZE, 8));
514 __tls_get_addr(tls_index* ti)
517 #ifdef ARM_TP_ADDRESS
518 void **_tp = (void **)ARM_TP_ADDRESS;
520 p = tls_get_addr_common((Elf_Addr **)(*_tp), ti->ti_module, ti->ti_offset);
523 __asm __volatile("mrc p15, 0, %0, c13, c0, 3" \
525 p = tls_get_addr_common((Elf_Addr **)(_tp), ti->ti_module, ti->ti_offset);