1 /* $NetBSD: mdreloc.c,v 1.23 2003/07/26 15:04:38 mrg Exp $ */
17 init_pltgot(Obj_Entry *obj)
19 if (obj->pltgot != NULL) {
20 obj->pltgot[1] = (Elf_Addr) obj;
21 obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start;
26 do_copy_relocations(Obj_Entry *dstobj)
28 const Elf_Rel *rellim;
31 assert(dstobj->mainprog); /* COPY relocations are invalid elsewhere */
33 rellim = (const Elf_Rel *) ((caddr_t) dstobj->rel + dstobj->relsize);
34 for (rel = dstobj->rel; rel < rellim; rel++) {
35 if (ELF_R_TYPE(rel->r_info) == R_ARM_COPY) {
37 const Elf_Sym *dstsym;
41 const Elf_Sym *srcsym;
42 const Obj_Entry *srcobj, *defobj;
46 dstaddr = (void *) (dstobj->relocbase + rel->r_offset);
47 dstsym = dstobj->symtab + ELF_R_SYM(rel->r_info);
48 name = dstobj->strtab + dstsym->st_name;
49 size = dstsym->st_size;
51 symlook_init(&req, name);
52 req.ventry = fetch_ventry(dstobj,
53 ELF_R_SYM(rel->r_info));
54 req.flags = SYMLOOK_EARLY;
56 for (srcobj = dstobj->next; srcobj != NULL;
57 srcobj = srcobj->next) {
58 res = symlook_obj(&req, srcobj);
61 defobj = req.defobj_out;
67 "Undefined symbol \"%s\" referenced from COPY relocation in %s",
72 srcaddr = (const void *)(defobj->relocbase +
74 memcpy(dstaddr, srcaddr, size);
80 void _rtld_bind_start(void);
81 void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr);
86 _rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase)
88 const Elf_Rel *rel = 0, *rellim;
93 for (; dynp->d_tag != DT_NULL; dynp++) {
94 switch (dynp->d_tag) {
96 rel = (const Elf_Rel *)(relocbase + dynp->d_un.d_ptr);
99 relsz = dynp->d_un.d_val;
103 rellim = (const Elf_Rel *)((caddr_t)rel + relsz);
104 size = (rellim - 1)->r_offset - rel->r_offset;
105 for (; rel < rellim; rel++) {
106 where = (Elf_Addr *)(relocbase + rel->r_offset);
108 *where += (Elf_Addr)relocbase;
112 * It is possible for the compiler to emit relocations for unaligned data.
113 * We handle this situation with these inlines.
115 #define RELOC_ALIGNED_P(x) \
116 (((uintptr_t)(x) & (sizeof(void *) - 1)) == 0)
118 static __inline Elf_Addr
119 load_ptr(void *where)
123 memcpy(&res, where, sizeof(res));
129 store_ptr(void *where, Elf_Addr val)
132 memcpy(where, &val, sizeof(val));
136 reloc_nonplt_object(Obj_Entry *obj, const Elf_Rel *rel, SymCache *cache,
137 int flags, RtldLockState *lockstate)
141 const Obj_Entry *defobj;
143 unsigned long symnum;
145 where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
146 symnum = ELF_R_SYM(rel->r_info);
148 switch (ELF_R_TYPE(rel->r_info)) {
152 #if 1 /* XXX should not occur */
153 case R_ARM_PC24: { /* word32 S - P + A */
157 * Extract addend and sign-extend if needed.
160 if (addend & 0x00800000)
161 addend |= 0xff000000;
163 def = find_symdef(symnum, obj, &defobj, flags, cache,
167 tmp = (Elf_Addr)obj->relocbase + def->st_value
168 - (Elf_Addr)where + (addend << 2);
169 if ((tmp & 0xfe000000) != 0xfe000000 &&
170 (tmp & 0xfe000000) != 0) {
172 "%s: R_ARM_PC24 relocation @ %p to %s failed "
173 "(displacement %ld (%#lx) out of range)",
175 obj->strtab + obj->symtab[symnum].st_name,
176 (long) tmp, (long) tmp);
180 *where = (*where & 0xff000000) | (tmp & 0x00ffffff);
181 dbg("PC24 %s in %s --> %p @ %p in %s",
182 obj->strtab + obj->symtab[symnum].st_name,
183 obj->path, (void *)*where, where, defobj->path);
188 case R_ARM_ABS32: /* word32 B + S + A */
189 case R_ARM_GLOB_DAT: /* word32 B + S */
190 def = find_symdef(symnum, obj, &defobj, flags, cache,
194 if (__predict_true(RELOC_ALIGNED_P(where))) {
195 tmp = *where + (Elf_Addr)defobj->relocbase +
199 tmp = load_ptr(where) +
200 (Elf_Addr)defobj->relocbase +
202 store_ptr(where, tmp);
204 dbg("ABS32/GLOB_DAT %s in %s --> %p @ %p in %s",
205 obj->strtab + obj->symtab[symnum].st_name,
206 obj->path, (void *)tmp, where, defobj->path);
209 case R_ARM_RELATIVE: /* word32 B + A */
210 if (__predict_true(RELOC_ALIGNED_P(where))) {
211 tmp = *where + (Elf_Addr)obj->relocbase;
214 tmp = load_ptr(where) +
215 (Elf_Addr)obj->relocbase;
216 store_ptr(where, tmp);
218 dbg("RELATIVE in %s --> %p", obj->path,
224 * These are deferred until all other relocations have
225 * been done. All we do here is make sure that the
226 * COPY relocation is not in a shared library. They
227 * are allowed only in executable files.
229 if (!obj->mainprog) {
231 "%s: Unexpected R_COPY relocation in shared library",
235 dbg("COPY (avoid in main)");
239 dbg("sym = %lu, type = %lu, offset = %p, "
240 "contents = %p, symbol = %s",
241 symnum, (u_long)ELF_R_TYPE(rel->r_info),
242 (void *)rel->r_offset, (void *)load_ptr(where),
243 obj->strtab + obj->symtab[symnum].st_name);
244 _rtld_error("%s: Unsupported relocation type %ld "
245 "in non-PLT relocations\n",
246 obj->path, (u_long) ELF_R_TYPE(rel->r_info));
253 * * Process non-PLT relocations
256 reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags,
257 RtldLockState *lockstate)
259 const Elf_Rel *rellim;
264 /* The relocation for the dynamic loader has already been done. */
268 * The dynamic loader may be called from a thread, we have
269 * limited amounts of stack available so we cannot use alloca().
271 cache = calloc(obj->nchains, sizeof(SymCache));
272 /* No need to check for NULL here */
274 rellim = (const Elf_Rel *)((caddr_t)obj->rel + obj->relsize);
275 for (rel = obj->rel; rel < rellim; rel++) {
276 if (reloc_nonplt_object(obj, rel, cache, flags, lockstate) < 0)
287 * * Process the PLT relocations.
290 reloc_plt(Obj_Entry *obj)
292 const Elf_Rel *rellim;
295 rellim = (const Elf_Rel *)((char *)obj->pltrel +
297 for (rel = obj->pltrel; rel < rellim; rel++) {
300 assert(ELF_R_TYPE(rel->r_info) == R_ARM_JUMP_SLOT);
302 where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
303 *where += (Elf_Addr )obj->relocbase;
310 * * LD_BIND_NOW was set - force relocation for all jump slots
313 reloc_jmpslots(Obj_Entry *obj, int flags, RtldLockState *lockstate)
315 const Obj_Entry *defobj;
316 const Elf_Rel *rellim;
322 rellim = (const Elf_Rel *)((char *)obj->pltrel + obj->pltrelsize);
323 for (rel = obj->pltrel; rel < rellim; rel++) {
324 assert(ELF_R_TYPE(rel->r_info) == R_ARM_JUMP_SLOT);
325 where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
326 def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
327 SYMLOOK_IN_PLT | flags, NULL, lockstate);
329 dbg("reloc_jmpslots: sym not found");
333 target = (Elf_Addr)(defobj->relocbase + def->st_value);
334 reloc_jmpslot(where, target, defobj, obj,
335 (const Elf_Rel *) rel);
338 obj->jmpslots_done = true;
344 reloc_iresolve(Obj_Entry *obj, struct Struct_RtldLockState *lockstate)
347 /* XXX not implemented */
352 reloc_gnu_ifunc(Obj_Entry *obj, int flags,
353 struct Struct_RtldLockState *lockstate)
356 /* XXX not implemented */
361 reloc_jmpslot(Elf_Addr *where, Elf_Addr target, const Obj_Entry *defobj,
362 const Obj_Entry *obj, const Elf_Rel *rel)
365 assert(ELF_R_TYPE(rel->r_info) == R_ARM_JUMP_SLOT);
367 if (*where != target)
374 allocate_initial_tls(Obj_Entry *objs)
380 __tls_get_addr(tls_index* ti)