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 for (srcobj = dstobj->next; srcobj != NULL;
55 srcobj = srcobj->next) {
56 res = symlook_obj(&req, srcobj);
59 defobj = req.defobj_out;
65 "Undefined symbol \"%s\" referenced from COPY relocation in %s",
70 srcaddr = (const void *)(defobj->relocbase +
72 memcpy(dstaddr, srcaddr, size);
78 void _rtld_bind_start(void);
79 void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr);
84 _rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase)
86 const Elf_Rel *rel = 0, *rellim;
91 for (; dynp->d_tag != DT_NULL; dynp++) {
92 switch (dynp->d_tag) {
94 rel = (const Elf_Rel *)(relocbase + dynp->d_un.d_ptr);
97 relsz = dynp->d_un.d_val;
101 rellim = (const Elf_Rel *)((caddr_t)rel + relsz);
102 size = (rellim - 1)->r_offset - rel->r_offset;
103 for (; rel < rellim; rel++) {
104 where = (Elf_Addr *)(relocbase + rel->r_offset);
106 *where += (Elf_Addr)relocbase;
110 * It is possible for the compiler to emit relocations for unaligned data.
111 * We handle this situation with these inlines.
113 #define RELOC_ALIGNED_P(x) \
114 (((uintptr_t)(x) & (sizeof(void *) - 1)) == 0)
116 static __inline Elf_Addr
117 load_ptr(void *where)
121 memcpy(&res, where, sizeof(res));
127 store_ptr(void *where, Elf_Addr val)
130 memcpy(where, &val, sizeof(val));
134 reloc_nonplt_object(Obj_Entry *obj, const Elf_Rel *rel, SymCache *cache,
135 RtldLockState *lockstate)
139 const Obj_Entry *defobj;
141 unsigned long symnum;
143 where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
144 symnum = ELF_R_SYM(rel->r_info);
146 switch (ELF_R_TYPE(rel->r_info)) {
150 #if 1 /* XXX should not occur */
151 case R_ARM_PC24: { /* word32 S - P + A */
155 * Extract addend and sign-extend if needed.
158 if (addend & 0x00800000)
159 addend |= 0xff000000;
161 def = find_symdef(symnum, obj, &defobj, false, cache,
165 tmp = (Elf_Addr)obj->relocbase + def->st_value
166 - (Elf_Addr)where + (addend << 2);
167 if ((tmp & 0xfe000000) != 0xfe000000 &&
168 (tmp & 0xfe000000) != 0) {
170 "%s: R_ARM_PC24 relocation @ %p to %s failed "
171 "(displacement %ld (%#lx) out of range)",
173 obj->strtab + obj->symtab[symnum].st_name,
174 (long) tmp, (long) tmp);
178 *where = (*where & 0xff000000) | (tmp & 0x00ffffff);
179 dbg("PC24 %s in %s --> %p @ %p in %s",
180 obj->strtab + obj->symtab[symnum].st_name,
181 obj->path, (void *)*where, where, defobj->path);
186 case R_ARM_ABS32: /* word32 B + S + A */
187 case R_ARM_GLOB_DAT: /* word32 B + S */
188 def = find_symdef(symnum, obj, &defobj, false, cache,
192 if (__predict_true(RELOC_ALIGNED_P(where))) {
193 tmp = *where + (Elf_Addr)defobj->relocbase +
197 tmp = load_ptr(where) +
198 (Elf_Addr)defobj->relocbase +
200 store_ptr(where, tmp);
202 dbg("ABS32/GLOB_DAT %s in %s --> %p @ %p in %s",
203 obj->strtab + obj->symtab[symnum].st_name,
204 obj->path, (void *)tmp, where, defobj->path);
207 case R_ARM_RELATIVE: /* word32 B + A */
208 if (__predict_true(RELOC_ALIGNED_P(where))) {
209 tmp = *where + (Elf_Addr)obj->relocbase;
212 tmp = load_ptr(where) +
213 (Elf_Addr)obj->relocbase;
214 store_ptr(where, tmp);
216 dbg("RELATIVE in %s --> %p", obj->path,
222 * These are deferred until all other relocations have
223 * been done. All we do here is make sure that the
224 * COPY relocation is not in a shared library. They
225 * are allowed only in executable files.
227 if (!obj->mainprog) {
229 "%s: Unexpected R_COPY relocation in shared library",
233 dbg("COPY (avoid in main)");
237 dbg("sym = %lu, type = %lu, offset = %p, "
238 "contents = %p, symbol = %s",
239 symnum, (u_long)ELF_R_TYPE(rel->r_info),
240 (void *)rel->r_offset, (void *)load_ptr(where),
241 obj->strtab + obj->symtab[symnum].st_name);
242 _rtld_error("%s: Unsupported relocation type %ld "
243 "in non-PLT relocations\n",
244 obj->path, (u_long) ELF_R_TYPE(rel->r_info));
251 * * Process non-PLT relocations
254 reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, RtldLockState *lockstate)
256 const Elf_Rel *rellim;
261 /* The relocation for the dynamic loader has already been done. */
265 * The dynamic loader may be called from a thread, we have
266 * limited amounts of stack available so we cannot use alloca().
268 cache = calloc(obj->nchains, sizeof(SymCache));
269 /* No need to check for NULL here */
271 rellim = (const Elf_Rel *)((caddr_t)obj->rel + obj->relsize);
272 for (rel = obj->rel; rel < rellim; rel++) {
273 if (reloc_nonplt_object(obj, rel, cache, lockstate) < 0)
284 * * Process the PLT relocations.
287 reloc_plt(Obj_Entry *obj)
289 const Elf_Rel *rellim;
292 rellim = (const Elf_Rel *)((char *)obj->pltrel +
294 for (rel = obj->pltrel; rel < rellim; rel++) {
297 assert(ELF_R_TYPE(rel->r_info) == R_ARM_JUMP_SLOT);
299 where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
300 *where += (Elf_Addr )obj->relocbase;
307 * * LD_BIND_NOW was set - force relocation for all jump slots
310 reloc_jmpslots(Obj_Entry *obj, RtldLockState *lockstate)
312 const Obj_Entry *defobj;
313 const Elf_Rel *rellim;
319 rellim = (const Elf_Rel *)((char *)obj->pltrel + obj->pltrelsize);
320 for (rel = obj->pltrel; rel < rellim; rel++) {
321 assert(ELF_R_TYPE(rel->r_info) == R_ARM_JUMP_SLOT);
322 where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
323 def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
324 true, NULL, lockstate);
326 dbg("reloc_jmpslots: sym not found");
330 target = (Elf_Addr)(defobj->relocbase + def->st_value);
331 reloc_jmpslot(where, target, defobj, obj,
332 (const Elf_Rel *) rel);
335 obj->jmpslots_done = true;
341 reloc_iresolve(Obj_Entry *obj, struct Struct_RtldLockState *lockstate)
344 /* XXX not implemented */
349 reloc_gnu_ifunc(Obj_Entry *obj, struct Struct_RtldLockState *lockstate)
352 /* XXX not implemented */
357 reloc_jmpslot(Elf_Addr *where, Elf_Addr target, const Obj_Entry *defobj,
358 const Obj_Entry *obj, const Elf_Rel *rel)
361 assert(ELF_R_TYPE(rel->r_info) == R_ARM_JUMP_SLOT);
363 if (*where != target)
370 allocate_initial_tls(Obj_Entry *objs)
376 __tls_get_addr(tls_index* ti)