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;
42 const Elf_Sym *srcsym;
45 dstaddr = (void *) (dstobj->relocbase + rel->r_offset);
46 dstsym = dstobj->symtab + ELF_R_SYM(rel->r_info);
47 name = dstobj->strtab + dstsym->st_name;
48 hash = elf_hash(name);
49 size = dstsym->st_size;
51 for (srcobj = dstobj->next; srcobj != NULL; srcobj = srcobj->next)
52 if ((srcsym = symlook_obj(name, hash, srcobj, false)) != NULL)
56 _rtld_error("Undefined symbol \"%s\" referenced from COPY"
57 " relocation in %s", name, dstobj->path);
61 srcaddr = (const void *) (srcobj->relocbase + srcsym->st_value);
62 memcpy(dstaddr, srcaddr, size);
68 void _rtld_bind_start(void);
69 void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr);
74 _rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase)
76 const Elf_Rel *rel = 0, *rellim;
81 for (; dynp->d_tag != DT_NULL; dynp++) {
82 switch (dynp->d_tag) {
84 rel = (const Elf_Rel *)(relocbase + dynp->d_un.d_ptr);
87 relsz = dynp->d_un.d_val;
91 rellim = (const Elf_Rel *)((caddr_t)rel + relsz);
92 size = (rellim - 1)->r_offset - rel->r_offset;
93 for (; rel < rellim; rel++) {
94 where = (Elf_Addr *)(relocbase + rel->r_offset);
96 *where += (Elf_Addr)relocbase;
100 * It is possible for the compiler to emit relocations for unaligned data.
101 * We handle this situation with these inlines.
103 #define RELOC_ALIGNED_P(x) \
104 (((uintptr_t)(x) & (sizeof(void *) - 1)) == 0)
106 static __inline Elf_Addr
107 load_ptr(void *where)
111 memcpy(&res, where, sizeof(res));
117 store_ptr(void *where, Elf_Addr val)
120 memcpy(where, &val, sizeof(val));
124 reloc_nonplt_object(Obj_Entry *obj, const Elf_Rel *rel, SymCache *cache)
128 const Obj_Entry *defobj;
130 unsigned long symnum;
132 where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
133 symnum = ELF_R_SYM(rel->r_info);
135 switch (ELF_R_TYPE(rel->r_info)) {
139 #if 1 /* XXX should not occur */
140 case R_ARM_PC24: { /* word32 S - P + A */
144 * Extract addend and sign-extend if needed.
147 if (addend & 0x00800000)
148 addend |= 0xff000000;
150 def = find_symdef(symnum, obj, &defobj, false, cache);
153 tmp = (Elf_Addr)obj->relocbase + def->st_value
154 - (Elf_Addr)where + (addend << 2);
155 if ((tmp & 0xfe000000) != 0xfe000000 &&
156 (tmp & 0xfe000000) != 0) {
158 "%s: R_ARM_PC24 relocation @ %p to %s failed "
159 "(displacement %ld (%#lx) out of range)",
161 obj->strtab + obj->symtab[symnum].st_name,
162 (long) tmp, (long) tmp);
166 *where = (*where & 0xff000000) | (tmp & 0x00ffffff);
167 dbg("PC24 %s in %s --> %p @ %p in %s",
168 obj->strtab + obj->symtab[symnum].st_name,
169 obj->path, (void *)*where, where, defobj->path);
174 case R_ARM_ABS32: /* word32 B + S + A */
175 case R_ARM_GLOB_DAT: /* word32 B + S */
176 def = find_symdef(symnum, obj, &defobj, false, cache);
179 if (__predict_true(RELOC_ALIGNED_P(where))) {
180 tmp = *where + (Elf_Addr)defobj->relocbase +
184 tmp = load_ptr(where) +
185 (Elf_Addr)defobj->relocbase +
187 store_ptr(where, tmp);
189 dbg("ABS32/GLOB_DAT %s in %s --> %p @ %p in %s",
190 obj->strtab + obj->symtab[symnum].st_name,
191 obj->path, (void *)tmp, where, defobj->path);
194 case R_ARM_RELATIVE: /* word32 B + A */
195 if (__predict_true(RELOC_ALIGNED_P(where))) {
196 tmp = *where + (Elf_Addr)obj->relocbase;
199 tmp = load_ptr(where) +
200 (Elf_Addr)obj->relocbase;
201 store_ptr(where, tmp);
203 dbg("RELATIVE in %s --> %p", obj->path,
209 * These are deferred until all other relocations have
210 * been done. All we do here is make sure that the
211 * COPY relocation is not in a shared library. They
212 * are allowed only in executable files.
214 if (!obj->mainprog) {
216 "%s: Unexpected R_COPY relocation in shared library",
220 dbg("COPY (avoid in main)");
224 dbg("sym = %lu, type = %lu, offset = %p, "
225 "contents = %p, symbol = %s",
226 symnum, (u_long)ELF_R_TYPE(rel->r_info),
227 (void *)rel->r_offset, (void *)load_ptr(where),
228 obj->strtab + obj->symtab[symnum].st_name);
229 _rtld_error("%s: Unsupported relocation type %ld "
230 "in non-PLT relocations\n",
231 obj->path, (u_long) ELF_R_TYPE(rel->r_info));
238 * * Process non-PLT relocations
241 reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld)
243 const Elf_Rel *rellim;
246 int bytes = obj->nchains * sizeof(SymCache);
249 /* The relocation for the dynamic loader has already been done. */
253 * The dynamic loader may be called from a thread, we have
254 * limited amounts of stack available so we cannot use alloca().
256 cache = mmap(NULL, bytes, PROT_READ|PROT_WRITE, MAP_ANON, -1, 0);
257 if (cache == MAP_FAILED)
260 rellim = (const Elf_Rel *)((caddr_t)obj->rel + obj->relsize);
261 for (rel = obj->rel; rel < rellim; rel++) {
262 if (reloc_nonplt_object(obj, rel, cache) < 0)
268 munmap(cache, bytes);
274 * * Process the PLT relocations.
277 reloc_plt(Obj_Entry *obj)
279 const Elf_Rel *rellim;
282 rellim = (const Elf_Rel *)((char *)obj->pltrel +
284 for (rel = obj->pltrel; rel < rellim; rel++) {
287 assert(ELF_R_TYPE(rel->r_info) == R_ARM_JUMP_SLOT);
289 where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
290 *where += (Elf_Addr )obj->relocbase;
297 * * LD_BIND_NOW was set - force relocation for all jump slots
300 reloc_jmpslots(Obj_Entry *obj)
302 const Obj_Entry *defobj;
303 const Elf_Rel *rellim;
309 rellim = (const Elf_Rel *)((char *)obj->pltrel + obj->pltrelsize);
310 for (rel = obj->pltrel; rel < rellim; rel++) {
311 assert(ELF_R_TYPE(rel->r_info) == R_ARM_JUMP_SLOT);
312 where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
313 def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
316 dbg("reloc_jmpslots: sym not found");
320 target = (Elf_Addr)(defobj->relocbase + def->st_value);
321 reloc_jmpslot(where, target, defobj, obj,
322 (const Elf_Rel *) rel);
325 obj->jmpslots_done = true;
331 reloc_jmpslot(Elf_Addr *where, Elf_Addr target, const Obj_Entry *defobj,
332 const Obj_Entry *obj, const Elf_Rel *rel)
335 assert(ELF_R_TYPE(rel->r_info) == R_ARM_JUMP_SLOT);
337 if (*where != target)
344 allocate_initial_tls(Obj_Entry *objs)
350 __tls_get_addr(tls_index* ti)