1 /* vi: set sw=4 ts=4: */
2 /* i386 ELF shared library loader suppport
4 * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
5 * David Engel, Hongjiu Lu and Mitch D'Souza
6 * Copyright (C) 2001-2002, Erik Andersen
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. The name of the above contributors may not be
16 * used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #if defined (__SUPPORT_LD_DEBUG__)
33 static const char *_dl_reltypes_tab[] =
35 [0] "R_386_NONE", "R_386_32", "R_386_PC32", "R_386_GOT32",
36 [4] "R_386_PLT32", "R_386_COPY", "R_386_GLOB_DAT", "R_386_JMP_SLOT",
37 [8] "R_386_RELATIVE", "R_386_GOTOFF", "R_386_GOTPC",
41 _dl_reltypes(int type)
46 if (type >= (int)(sizeof (_dl_reltypes_tab)/sizeof(_dl_reltypes_tab[0])) ||
47 NULL == (str = _dl_reltypes_tab[type]))
49 str =_dl_simple_ltoa( buf, (unsigned long)(type));
55 void debug_sym(Elf32_Sym *symtab,char *strtab,int symtab_index)
60 _dl_dprintf(_dl_debug_file, "\n%s\n\tvalue=%x\tsize=%x\tinfo=%x\tother=%x\tshndx=%x",
61 strtab + symtab[symtab_index].st_name,
62 symtab[symtab_index].st_value,
63 symtab[symtab_index].st_size,
64 symtab[symtab_index].st_info,
65 symtab[symtab_index].st_other,
66 symtab[symtab_index].st_shndx);
71 static void debug_reloc(Elf32_Sym *symtab,char *strtab, ELF_RELOC *rpnt)
77 symtab_index = ELF32_R_SYM(rpnt->r_info);
78 sym = symtab_index ? strtab + symtab[symtab_index].st_name : "sym=0x0";
81 _dl_dprintf(_dl_debug_file, "\n\t");
83 _dl_dprintf(_dl_debug_file, "\n%s\n\t", sym);
84 #ifdef ELF_USES_RELOCA
85 _dl_dprintf(_dl_debug_file, "%s\toffset=%x\taddend=%x",
86 _dl_reltypes(ELF32_R_TYPE(rpnt->r_info)),
90 _dl_dprintf(_dl_debug_file, "%s\toffset=%x\n",
91 _dl_reltypes(ELF32_R_TYPE(rpnt->r_info)),
98 /* Program to load an ELF binary on a linux system, and run it.
99 References to symbols in sharable libraries can be resolved by either
100 an ELF sharable library or a linux style of shared library. */
102 /* Disclaimer: I have never seen any AT&T source code for SVr4, nor have
103 I ever taken any courses on internals. This program was developed using
104 information available through the book "UNIX SYSTEM V RELEASE 4,
105 Programmers guide: Ansi C and Programming Support Tools", which did
106 a more than adequate job of explaining everything required to get this
109 extern int _dl_linux_resolve(void);
111 unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
114 ELF_RELOC *this_reloc;
121 unsigned long instr_addr;
124 rel_addr = (char *) (tpnt->dynamic_info[DT_JMPREL] + tpnt->loadaddr);
126 this_reloc = (ELF_RELOC *)(intptr_t)(rel_addr + reloc_entry);
127 reloc_type = ELF32_R_TYPE(this_reloc->r_info);
128 symtab_index = ELF32_R_SYM(this_reloc->r_info);
130 symtab = (Elf32_Sym *)(intptr_t) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
131 strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
132 symname= strtab + symtab[symtab_index].st_name;
134 if (reloc_type != R_386_JMP_SLOT) {
135 _dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n",
140 /* Address of jump instruction to fix up */
141 instr_addr = ((unsigned long) this_reloc->r_offset +
142 (unsigned long) tpnt->loadaddr);
143 got_addr = (char **) instr_addr;
145 /* Get the address of the GOT entry */
146 new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, resolver);
148 new_addr = _dl_find_hash(symname, NULL, NULL, resolver);
150 return (unsigned long) new_addr;
152 _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname);
156 #if defined (__SUPPORT_LD_DEBUG__)
157 if ((unsigned long) got_addr < 0x40000000)
159 if (_dl_debug_bindings)
161 _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname);
162 if(_dl_debug_detail) _dl_dprintf(_dl_debug_file,
163 "\n\tpatched %x ==> %x @ %x\n", *got_addr, new_addr, got_addr);
166 if (!_dl_debug_nofixups) {
167 *got_addr = new_addr;
170 *got_addr = new_addr;
173 return (unsigned long) new_addr;
177 _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
178 unsigned long rel_addr, unsigned long rel_size,
179 int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope,
180 ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab))
188 /* Now parse the relocation information */
189 rpnt = (ELF_RELOC *)(intptr_t) (rel_addr + tpnt->loadaddr);
190 rel_size = rel_size / sizeof(ELF_RELOC);
192 symtab = (Elf32_Sym *)(intptr_t) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
193 strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
195 for (i = 0; i < rel_size; i++, rpnt++) {
198 symtab_index = ELF32_R_SYM(rpnt->r_info);
200 /* When the dynamic linker bootstrapped itself, it resolved some symbols.
201 Make sure we do not do them again */
202 if (!symtab_index && tpnt->libtype == program_interpreter)
204 if (symtab_index && tpnt->libtype == program_interpreter &&
205 _dl_symbol(strtab + symtab[symtab_index].st_name))
208 #if defined (__SUPPORT_LD_DEBUG__)
209 debug_sym(symtab,strtab,symtab_index);
210 debug_reloc(symtab,strtab,rpnt);
213 res = reloc_fnc (tpnt, scope, rpnt, symtab, strtab);
215 if (res==0) continue;
217 _dl_dprintf(2, "\n%s: ",_dl_progname);
220 _dl_dprintf(2, "symbol '%s': ", strtab + symtab[symtab_index].st_name);
224 int reloc_type = ELF32_R_TYPE(rpnt->r_info);
225 #if defined (__SUPPORT_LD_DEBUG__)
226 _dl_dprintf(2, "can't handle reloc type %s\n ", _dl_reltypes(reloc_type));
228 _dl_dprintf(2, "can't handle reloc type %x\n", reloc_type);
234 _dl_dprintf(2, "can't resolve symbol\n");
243 _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
244 ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
249 unsigned long *reloc_addr;
250 unsigned long symbol_addr;
251 #if defined (__SUPPORT_LD_DEBUG__)
252 unsigned long old_val;
255 reloc_addr = (unsigned long *)(intptr_t) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
256 reloc_type = ELF32_R_TYPE(rpnt->r_info);
257 symtab_index = ELF32_R_SYM(rpnt->r_info);
259 symname = strtab + symtab[symtab_index].st_name;
263 symbol_addr = (unsigned long) _dl_find_hash(symname, scope,
264 (reloc_type == R_386_JMP_SLOT ? tpnt : NULL), symbolrel);
267 * We want to allow undefined references to weak symbols - this might
268 * have been intentional. We should not be linking local symbols
269 * here, so all bases should be covered.
272 if (!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) == STB_GLOBAL) {
273 #if defined (__SUPPORT_LD_DEBUG__)
274 _dl_dprintf(2, "\tglobal symbol '%s' already defined in '%s'\n",
275 symname, tpnt->libname);
281 #if defined (__SUPPORT_LD_DEBUG__)
282 old_val = *reloc_addr;
284 switch (reloc_type) {
288 *reloc_addr += symbol_addr;
291 *reloc_addr += symbol_addr - (unsigned long) reloc_addr;
295 *reloc_addr = symbol_addr;
298 *reloc_addr += (unsigned long) tpnt->loadaddr;
301 /* handled later on */
304 return -1; /*call _dl_exit(1) */
306 #if defined (__SUPPORT_LD_DEBUG__)
307 if(_dl_debug_reloc && _dl_debug_detail)
308 _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x", old_val, *reloc_addr, reloc_addr);
315 _dl_do_lazy_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope,
316 ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
319 unsigned long *reloc_addr;
320 #if defined (__SUPPORT_LD_DEBUG__)
321 unsigned long old_val;
327 reloc_addr = (unsigned long *)(intptr_t) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
328 reloc_type = ELF32_R_TYPE(rpnt->r_info);
330 #if defined (__SUPPORT_LD_DEBUG__)
331 old_val = *reloc_addr;
333 switch (reloc_type) {
337 *reloc_addr += (unsigned long) tpnt->loadaddr;
340 return -1; /*call _dl_exit(1) */
342 #if defined (__SUPPORT_LD_DEBUG__)
343 if(_dl_debug_reloc && _dl_debug_detail)
344 _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x", old_val, *reloc_addr, reloc_addr);
350 /* This is done as a separate step, because there are cases where
351 information is first copied and later initialized. This results in
352 the wrong information being copied. Someone at Sun was complaining about
353 a bug in the handling of _COPY by SVr4, and this may in fact be what he
354 was talking about. Sigh. */
356 /* No, there are cases where the SVr4 linker fails to emit COPY relocs
359 _dl_do_copy (struct elf_resolve *tpnt, struct dyn_elf *scope,
360 ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
364 unsigned long *reloc_addr;
365 unsigned long symbol_addr;
369 reloc_addr = (unsigned long *)(intptr_t) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
370 reloc_type = ELF32_R_TYPE(rpnt->r_info);
371 if (reloc_type != R_386_COPY)
373 symtab_index = ELF32_R_SYM(rpnt->r_info);
375 symname = strtab + symtab[symtab_index].st_name;
378 symbol_addr = (unsigned long) _dl_find_hash(symname, scope, NULL, copyrel);
379 if (!symbol_addr) goof++;
382 #if defined (__SUPPORT_LD_DEBUG__)
384 _dl_dprintf(_dl_debug_file,"\n%s move %x bytes from %x to %x",
385 symname, symtab[symtab_index].st_size,
386 symbol_addr, symtab[symtab_index].st_value);
388 _dl_memcpy((char *) symtab[symtab_index].st_value,
389 (char *) symbol_addr, symtab[symtab_index].st_size);
395 void _dl_parse_lazy_relocation_information(struct elf_resolve *tpnt,
396 unsigned long rel_addr, unsigned long rel_size, int type)
399 (void)_dl_parse(tpnt, NULL, rel_addr, rel_size, _dl_do_lazy_reloc);
402 int _dl_parse_relocation_information(struct elf_resolve *tpnt,
403 unsigned long rel_addr, unsigned long rel_size, int type)
406 return _dl_parse(tpnt, tpnt->symbol_scope, rel_addr, rel_size, _dl_do_reloc);
409 int _dl_parse_copy_information(struct dyn_elf *xpnt, unsigned long rel_addr,
410 unsigned long rel_size, int type)
413 return _dl_parse(xpnt->dyn, xpnt->next, rel_addr, rel_size, _dl_do_copy);