1 /* $NetBSD: mdreloc.c,v 1.23 2003/07/26 15:04:38 mrg Exp $ */
15 #include "machine/sysarch.h"
19 #include "rtld_paths.h"
22 init_pltgot(Obj_Entry *obj)
24 if (obj->pltgot != NULL) {
25 obj->pltgot[1] = (Elf_Addr) obj;
26 obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start;
31 do_copy_relocations(Obj_Entry *dstobj)
33 const Elf_Rel *rellim;
36 assert(dstobj->mainprog); /* COPY relocations are invalid elsewhere */
38 rellim = (const Elf_Rel *)((const char *) dstobj->rel + dstobj->relsize);
39 for (rel = dstobj->rel; rel < rellim; rel++) {
40 if (ELF_R_TYPE(rel->r_info) == R_ARM_COPY) {
42 const Elf_Sym *dstsym;
46 const Elf_Sym *srcsym;
47 const Obj_Entry *srcobj, *defobj;
51 dstaddr = (void *)(dstobj->relocbase + rel->r_offset);
52 dstsym = dstobj->symtab + ELF_R_SYM(rel->r_info);
53 name = dstobj->strtab + dstsym->st_name;
54 size = dstsym->st_size;
56 symlook_init(&req, name);
57 req.ventry = fetch_ventry(dstobj,
58 ELF_R_SYM(rel->r_info));
59 req.flags = SYMLOOK_EARLY;
61 for (srcobj = globallist_next(dstobj); srcobj != NULL;
62 srcobj = globallist_next(srcobj)) {
63 res = symlook_obj(&req, srcobj);
66 defobj = req.defobj_out;
72 "Undefined symbol \"%s\" referenced from COPY relocation in %s",
77 srcaddr = (const void *)(defobj->relocbase +
79 memcpy(dstaddr, srcaddr, size);
85 void _rtld_bind_start(void);
86 void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr);
89 _rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase)
91 const Elf_Rel *rel = NULL, *rellim;
96 for (; dynp->d_tag != DT_NULL; dynp++) {
97 switch (dynp->d_tag) {
99 rel = (const Elf_Rel *)(relocbase + dynp->d_un.d_ptr);
102 relsz = dynp->d_un.d_val;
106 rellim = (const Elf_Rel *)((const char *)rel + relsz);
107 size = (rellim - 1)->r_offset - rel->r_offset;
108 for (; rel < rellim; rel++) {
109 where = (Elf_Addr *)(relocbase + rel->r_offset);
111 *where += (Elf_Addr)relocbase;
115 * It is possible for the compiler to emit relocations for unaligned data.
116 * We handle this situation with these inlines.
118 #define RELOC_ALIGNED_P(x) \
119 (((uintptr_t)(x) & (sizeof(void *) - 1)) == 0)
121 static __inline Elf_Addr
122 load_ptr(void *where)
126 memcpy(&res, where, sizeof(res));
132 store_ptr(void *where, Elf_Addr val)
135 memcpy(where, &val, sizeof(val));
139 reloc_nonplt_object(Obj_Entry *obj, const Elf_Rel *rel, SymCache *cache,
140 int flags, RtldLockState *lockstate)
144 const Obj_Entry *defobj;
146 unsigned long symnum;
148 where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
149 symnum = ELF_R_SYM(rel->r_info);
151 switch (ELF_R_TYPE(rel->r_info)) {
155 #if 1 /* XXX should not occur */
156 case R_ARM_PC24: { /* word32 S - P + A */
160 * Extract addend and sign-extend if needed.
163 if (addend & 0x00800000)
164 addend |= 0xff000000;
166 def = find_symdef(symnum, obj, &defobj, flags, cache,
170 tmp = (Elf_Addr)obj->relocbase + def->st_value
171 - (Elf_Addr)where + (addend << 2);
172 if ((tmp & 0xfe000000) != 0xfe000000 &&
173 (tmp & 0xfe000000) != 0) {
175 "%s: R_ARM_PC24 relocation @ %p to %s failed "
176 "(displacement %ld (%#lx) out of range)",
178 obj->strtab + obj->symtab[symnum].st_name,
179 (long) tmp, (long) tmp);
183 *where = (*where & 0xff000000) | (tmp & 0x00ffffff);
184 dbg("PC24 %s in %s --> %p @ %p in %s",
185 obj->strtab + obj->symtab[symnum].st_name,
186 obj->path, (void *)*where, where, defobj->path);
191 case R_ARM_ABS32: /* word32 B + S + A */
192 case R_ARM_GLOB_DAT: /* word32 B + S */
193 def = find_symdef(symnum, obj, &defobj, flags, cache,
197 if (__predict_true(RELOC_ALIGNED_P(where))) {
198 tmp = *where + (Elf_Addr)defobj->relocbase +
202 tmp = load_ptr(where) +
203 (Elf_Addr)defobj->relocbase +
205 store_ptr(where, tmp);
207 dbg("ABS32/GLOB_DAT %s in %s --> %p @ %p in %s",
208 obj->strtab + obj->symtab[symnum].st_name,
209 obj->path, (void *)tmp, where, defobj->path);
212 case R_ARM_RELATIVE: /* word32 B + A */
213 if (__predict_true(RELOC_ALIGNED_P(where))) {
214 tmp = *where + (Elf_Addr)obj->relocbase;
217 tmp = load_ptr(where) +
218 (Elf_Addr)obj->relocbase;
219 store_ptr(where, tmp);
221 dbg("RELATIVE in %s --> %p", obj->path,
227 * These are deferred until all other relocations have
228 * been done. All we do here is make sure that the
229 * COPY relocation is not in a shared library. They
230 * are allowed only in executable files.
232 if (!obj->mainprog) {
234 "%s: Unexpected R_COPY relocation in shared library",
238 dbg("COPY (avoid in main)");
241 case R_ARM_TLS_DTPOFF32:
242 def = find_symdef(symnum, obj, &defobj, flags, cache,
247 tmp = (Elf_Addr)(def->st_value);
248 if (__predict_true(RELOC_ALIGNED_P(where)))
251 store_ptr(where, tmp);
253 dbg("TLS_DTPOFF32 %s in %s --> %p",
254 obj->strtab + obj->symtab[symnum].st_name,
255 obj->path, (void *)tmp);
258 case R_ARM_TLS_DTPMOD32:
259 def = find_symdef(symnum, obj, &defobj, flags, cache,
264 tmp = (Elf_Addr)(defobj->tlsindex);
265 if (__predict_true(RELOC_ALIGNED_P(where)))
268 store_ptr(where, tmp);
270 dbg("TLS_DTPMOD32 %s in %s --> %p",
271 obj->strtab + obj->symtab[symnum].st_name,
272 obj->path, (void *)tmp);
276 case R_ARM_TLS_TPOFF32:
277 def = find_symdef(symnum, obj, &defobj, flags, cache,
282 if (!defobj->tls_done && !allocate_tls_offset(obj))
285 tmp = (Elf_Addr)def->st_value + defobj->tlsoffset;
286 if (__predict_true(RELOC_ALIGNED_P(where)))
289 store_ptr(where, tmp);
290 dbg("TLS_TPOFF32 %s in %s --> %p",
291 obj->strtab + obj->symtab[symnum].st_name,
292 obj->path, (void *)tmp);
297 dbg("sym = %lu, type = %lu, offset = %p, "
298 "contents = %p, symbol = %s",
299 symnum, (u_long)ELF_R_TYPE(rel->r_info),
300 (void *)rel->r_offset, (void *)load_ptr(where),
301 obj->strtab + obj->symtab[symnum].st_name);
302 _rtld_error("%s: Unsupported relocation type %ld "
303 "in non-PLT relocations\n",
304 obj->path, (u_long) ELF_R_TYPE(rel->r_info));
311 * * Process non-PLT relocations
314 reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags,
315 RtldLockState *lockstate)
317 const Elf_Rel *rellim;
322 /* The relocation for the dynamic loader has already been done. */
325 if ((flags & SYMLOOK_IFUNC) != 0)
326 /* XXX not implemented */
330 * The dynamic loader may be called from a thread, we have
331 * limited amounts of stack available so we cannot use alloca().
333 cache = calloc(obj->dynsymcount, sizeof(SymCache));
334 /* No need to check for NULL here */
336 rellim = (const Elf_Rel *)((const char *)obj->rel + obj->relsize);
337 for (rel = obj->rel; rel < rellim; rel++) {
338 if (reloc_nonplt_object(obj, rel, cache, flags, lockstate) < 0)
349 * * Process the PLT relocations.
352 reloc_plt(Obj_Entry *obj, int flags __unused, RtldLockState *lockstate __unused)
354 const Elf_Rel *rellim;
357 rellim = (const Elf_Rel *)((const char *)obj->pltrel +
359 for (rel = obj->pltrel; rel < rellim; rel++) {
362 assert(ELF_R_TYPE(rel->r_info) == R_ARM_JUMP_SLOT);
364 where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
365 *where += (Elf_Addr )obj->relocbase;
372 * * LD_BIND_NOW was set - force relocation for all jump slots
375 reloc_jmpslots(Obj_Entry *obj, int flags, RtldLockState *lockstate)
377 const Obj_Entry *defobj;
378 const Elf_Rel *rellim;
384 rellim = (const Elf_Rel *)((const char *)obj->pltrel + obj->pltrelsize);
385 for (rel = obj->pltrel; rel < rellim; rel++) {
386 assert(ELF_R_TYPE(rel->r_info) == R_ARM_JUMP_SLOT);
387 where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
388 def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
389 SYMLOOK_IN_PLT | flags, NULL, lockstate);
391 dbg("reloc_jmpslots: sym not found");
395 target = (Elf_Addr)(defobj->relocbase + def->st_value);
396 reloc_jmpslot(where, target, defobj, obj,
397 (const Elf_Rel *) rel);
400 obj->jmpslots_done = true;
406 reloc_iresolve(Obj_Entry *obj __unused,
407 struct Struct_RtldLockState *lockstate __unused)
410 /* XXX not implemented */
415 reloc_iresolve_nonplt(Obj_Entry *obj __unused,
416 struct Struct_RtldLockState *lockstate __unused)
419 /* XXX not implemented */
424 reloc_gnu_ifunc(Obj_Entry *obj __unused, int flags __unused,
425 struct Struct_RtldLockState *lockstate __unused)
428 /* XXX not implemented */
433 reloc_jmpslot(Elf_Addr *where, Elf_Addr target,
434 const Obj_Entry *defobj __unused, const Obj_Entry *obj __unused,
438 assert(ELF_R_TYPE(rel->r_info) == R_ARM_JUMP_SLOT);
440 if (*where != target && !ld_bind_not)
446 ifunc_init(Elf_Auxinfo aux_info[__min_size(AT_COUNT)] __unused)
452 allocate_initial_tls(Obj_Entry *objs)
455 * Fix the size of the static TLS block by using the maximum
456 * offset allocated so far and adding a bit for dynamic modules to
460 tls_static_space = tls_last_offset + tls_last_size + RTLD_STATIC_TLS_EXTRA;
462 _tcb_set(allocate_tls(objs, NULL, TLS_TCB_SIZE, TLS_TCB_ALIGN));
466 __tls_get_addr(tls_index* ti)
470 dtvp = &_tcb_get()->tcb_dtv;
471 return (tls_get_addr_common(dtvp, ti->ti_module, ti->ti_offset));