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) || defined (LD_DEBUG_SYMBOLS)
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 >= (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\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";
80 #ifdef ELF_USES_RELOCA
81 _dl_dprintf(_dl_debug_file, "\n%s\toffset=%x\taddend=%x %s",
82 _dl_reltypes(ELF32_R_TYPE(rpnt->r_info)),
87 _dl_dprintf(_dl_debug_file, "\n%s\toffset=%x %s",
88 _dl_reltypes(ELF32_R_TYPE(rpnt->r_info)),
96 /* Program to load an ELF binary on a linux system, and run it.
97 References to symbols in sharable libraries can be resolved by either
98 an ELF sharable library or a linux style of shared library. */
100 /* Disclaimer: I have never seen any AT&T source code for SVr4, nor have
101 I ever taken any courses on internals. This program was developed using
102 information available through the book "UNIX SYSTEM V RELEASE 4,
103 Programmers guide: Ansi C and Programming Support Tools", which did
104 a more than adequate job of explaining everything required to get this
107 extern int _dl_linux_resolve(void);
109 unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
112 ELF_RELOC *this_reloc;
119 unsigned long instr_addr;
121 rel_addr = (ELF_RELOC *) (tpnt->dynamic_info[DT_JMPREL] + tpnt->loadaddr);
123 this_reloc = rel_addr + (reloc_entry >> 3);
124 reloc_type = ELF32_R_TYPE(this_reloc->r_info);
125 symtab_index = ELF32_R_SYM(this_reloc->r_info);
127 symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
128 strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
131 if (reloc_type != R_386_JMP_SLOT) {
132 _dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n",
137 /* Address of jump instruction to fix up */
138 instr_addr = ((unsigned long) this_reloc->r_offset +
139 (unsigned long) tpnt->loadaddr);
140 got_addr = (char **) instr_addr;
142 /* Get the address of the GOT entry */
143 new_addr = _dl_find_hash(strtab + symtab[symtab_index].st_name,
144 tpnt->symbol_scope, tpnt, resolver);
146 _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
147 _dl_progname, strtab + symtab[symtab_index].st_name);
150 #if defined (SUPPORT_LD_DEBUG) || defined (LD_NEVER_FIXUP_SYMBOLS)
151 if ((unsigned long) got_addr < 0x40000000)
153 #ifndef SUPPORT_LD_DEBUG
154 if (_dl_debug_bindings)
156 _dl_dprintf(_dl_debug_file, "\nresolve function: %s",
157 strtab + symtab[symtab_index].st_name);
158 if(_dl_debug_detail) _dl_dprintf(_dl_debug_file, "\tpatch %x ==> %x @ %x", *got_addr, new_addr, got_addr);
161 #ifndef LD_NEVER_FIXUP_SYMBOLS
162 *got_addr = new_addr;
165 *got_addr = new_addr;
168 *got_addr = new_addr;
171 return (unsigned long) new_addr;
175 _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
176 unsigned long rel_addr, unsigned long rel_size,
177 int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope,
178 ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab))
186 /* Now parse the relocation information */
188 rpnt = (ELF_RELOC *) (rel_addr + tpnt->loadaddr);
189 rel_size = rel_size / sizeof(ELF_RELOC);
191 symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
192 strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
194 for (i = 0; i < rel_size; i++, rpnt++) {
197 symtab_index = ELF32_R_SYM(rpnt->r_info);
199 /* When the dynamic linker bootstrapped itself, it resolved some symbols.
200 Make sure we do not do them again */
201 if (!symtab_index && tpnt->libtype == program_interpreter)
203 if (symtab_index && tpnt->libtype == program_interpreter &&
204 _dl_symbol(strtab + symtab[symtab_index].st_name))
207 #if defined (SUPPORT_LD_DEBUG) || defined (LD_DEBUG_SYMBOLS)
208 debug_sym(symtab,strtab,symtab_index);
209 debug_reloc(symtab,strtab,rpnt);
212 res = reloc_fnc (tpnt, scope, rpnt, symtab, strtab);
214 if (res==0) continue;
216 _dl_dprintf(2, "\n%s: ",_dl_progname);
219 _dl_dprintf(2, "symbol '%s': ", strtab + symtab[symtab_index].st_name);
223 int reloc_type = ELF32_R_TYPE(rpnt->r_info);
224 #if defined (SUPPORT_LD_DEBUG)
225 _dl_dprintf(2, "can't handle reloc type %s\n ", _dl_reltypes(reloc_type));
227 _dl_dprintf(2, "can't handle reloc type %x\n", reloc_type);
233 _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
234 _dl_progname, strtab + symtab[symtab_index].st_name);
242 _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
243 ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
247 unsigned long *reloc_addr;
248 unsigned long symbol_addr;
251 reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
252 reloc_type = ELF32_R_TYPE(rpnt->r_info);
253 symtab_index = ELF32_R_SYM(rpnt->r_info);
258 symbol_addr = (unsigned long) _dl_find_hash(strtab + symtab[symtab_index].st_name,
259 scope, (reloc_type == R_386_JMP_SLOT ? tpnt : NULL), symbolrel);
262 * We want to allow undefined references to weak symbols - this might
263 * have been intentional. We should not be linking local symbols
264 * here, so all bases should be covered.
266 if (!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) == STB_GLOBAL) {
271 #if defined (SUPPORT_LD_DEBUG)
273 unsigned long old_val = *reloc_addr;
275 switch (reloc_type) {
279 *reloc_addr += symbol_addr;
282 *reloc_addr += symbol_addr - (unsigned long) reloc_addr;
286 *reloc_addr = symbol_addr;
289 *reloc_addr += (unsigned long) tpnt->loadaddr;
294 _dl_dprintf(2, "Doing copy for symbol ");
295 if (symtab_index) _dl_dprintf(2, strtab + symtab[symtab_index].st_name);
296 _dl_dprintf(2, "\n");
297 _dl_memcpy((void *) symtab[symtab_index].st_value,
298 (void *) symbol_addr, symtab[symtab_index].st_size);
303 return -1; /*call _dl_exit(1) */
305 #if defined (SUPPORT_LD_DEBUG)
306 if(_dl_debug_reloc && _dl_debug_detail)
307 _dl_dprintf(_dl_debug_file, "\tpatch: %x ==> %x @ %x", old_val, *reloc_addr, reloc_addr);
316 _dl_do_lazy_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope,
317 ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
320 unsigned long *reloc_addr;
322 reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
323 reloc_type = ELF32_R_TYPE(rpnt->r_info);
325 #if defined (SUPPORT_LD_DEBUG)
327 unsigned long old_val = *reloc_addr;
329 switch (reloc_type) {
333 *reloc_addr += (unsigned long) tpnt->loadaddr;
337 return -1; /*call _dl_exit(1) */
339 #if defined (SUPPORT_LD_DEBUG)
340 if(_dl_debug_reloc && _dl_debug_detail)
341 _dl_dprintf(_dl_debug_file, "\tpatch: %x ==> %x @ %x", old_val, *reloc_addr, reloc_addr);
349 /* This is done as a separate step, because there are cases where
350 information is first copied and later initialized. This results in
351 the wrong information being copied. Someone at Sun was complaining about
352 a bug in the handling of _COPY by SVr4, and this may in fact be what he
353 was talking about. Sigh. */
355 /* No, there are cases where the SVr4 linker fails to emit COPY relocs
358 _dl_do_copy (struct elf_resolve *tpnt, struct dyn_elf *scope,
359 ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
363 unsigned long *reloc_addr;
364 unsigned long symbol_addr;
367 reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
368 reloc_type = ELF32_R_TYPE(rpnt->r_info);
369 if (reloc_type != R_386_COPY)
371 symtab_index = ELF32_R_SYM(rpnt->r_info);
376 symbol_addr = (unsigned long) _dl_find_hash(strtab +
377 symtab[symtab_index].st_name, scope,
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 strtab + symtab[symtab_index].st_name,
386 symtab[symtab_index].st_size,
387 symbol_addr, symtab[symtab_index].st_value);
389 _dl_memcpy((char *) symtab[symtab_index].st_value,
390 (char *) symbol_addr, symtab[symtab_index].st_size);
396 void _dl_parse_lazy_relocation_information(struct elf_resolve *tpnt,
397 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)
405 return _dl_parse(tpnt, tpnt->symbol_scope, rel_addr, rel_size, _dl_do_reloc);
408 int _dl_parse_copy_information(struct dyn_elf *xpnt, unsigned long rel_addr,
409 unsigned long rel_size, int type)
411 return _dl_parse(xpnt->dyn, xpnt->next, rel_addr, rel_size, _dl_do_copy);