1 /* Run an ELF binary on a linux system.
3 Copyright (C) 1993, Eric Youngdale.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19 #ifndef VERBOSE_DLINKER
20 #define VERBOSE_DLINKER
22 #ifdef VERBOSE_DLINKER
23 static char *_dl_reltypes[] =
24 { "R_386_NONE", "R_386_32", "R_386_PC32", "R_386_GOT32",
25 "R_386_PLT32", "R_386_COPY", "R_386_GLOB_DAT",
26 "R_386_JMP_SLOT", "R_386_RELATIVE", "R_386_GOTOFF",
27 "R_386_GOTPC", "R_386_NUM"
31 /* Program to load an ELF binary on a linux system, and run it.
32 References to symbols in sharable libraries can be resolved by either
33 an ELF sharable library or a linux style of shared library. */
35 /* Disclaimer: I have never seen any AT&T source code for SVr4, nor have
36 I ever taken any courses on internals. This program was developed using
37 information available through the book "UNIX SYSTEM V RELEASE 4,
38 Programmers guide: Ansi C and Programming Support Tools", which did
39 a more than adequate job of explaining everything required to get this
42 extern int _dl_linux_resolve(void);
44 unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
47 Elf32_Rel *this_reloc;
54 unsigned long instr_addr;
56 rel_addr = (Elf32_Rel *) (tpnt->dynamic_info[DT_JMPREL] + tpnt->loadaddr);
58 this_reloc = rel_addr + (reloc_entry >> 3);
59 reloc_type = ELF32_R_TYPE(this_reloc->r_info);
60 symtab_index = ELF32_R_SYM(this_reloc->r_info);
62 symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
63 strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
66 if (reloc_type != R_386_JMP_SLOT) {
67 _dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n",
72 /* Address of jump instruction to fix up */
73 instr_addr = ((unsigned long) this_reloc->r_offset +
74 (unsigned long) tpnt->loadaddr);
75 got_addr = (char **) instr_addr;
78 _dl_dprintf(2, "Resolving symbol %s\n",
79 strtab + symtab[symtab_index].st_name);
82 /* Get the address of the GOT entry */
83 new_addr = _dl_find_hash(strtab + symtab[symtab_index].st_name,
84 tpnt->symbol_scope, (unsigned long) got_addr, tpnt, 0);
86 _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
87 _dl_progname, strtab + symtab[symtab_index].st_name);
91 if ((unsigned long) got_addr < 0x40000000) {
92 _dl_dprintf(2, "Calling library function: %s\n",
93 strtab + symtab[symtab_index].st_name);
100 return (unsigned long) new_addr;
103 void _dl_parse_lazy_relocation_information(struct elf_resolve *tpnt,
104 unsigned long rel_addr, unsigned long rel_size, int type)
112 unsigned long *reloc_addr;
114 /* Now parse the relocation information */
115 rpnt = (Elf32_Rel *) (rel_addr + tpnt->loadaddr);
116 rel_size = rel_size / sizeof(Elf32_Rel);
119 (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
120 strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
122 for (i = 0; i < rel_size; i++, rpnt++) {
123 reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
124 reloc_type = ELF32_R_TYPE(rpnt->r_info);
125 symtab_index = ELF32_R_SYM(rpnt->r_info);
127 /* When the dynamic linker bootstrapped itself, it resolved some symbols.
128 Make sure we do not do them again */
129 if (!symtab_index && tpnt->libtype == program_interpreter)
131 if (symtab_index && tpnt->libtype == program_interpreter &&
132 _dl_symbol(strtab + symtab[symtab_index].st_name))
135 switch (reloc_type) {
139 *reloc_addr += (unsigned long) tpnt->loadaddr;
142 _dl_dprintf(2, "%s: (LAZY) can't handle reloc type ",
144 #ifdef VERBOSE_DLINKER
145 _dl_dprintf(2, "%s ", _dl_reltypes[reloc_type]);
148 _dl_dprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name);
154 int _dl_parse_relocation_information(struct elf_resolve *tpnt,
155 unsigned long rel_addr, unsigned long rel_size, int type)
163 unsigned long *reloc_addr;
164 unsigned long symbol_addr;
167 /* Now parse the relocation information */
169 rpnt = (Elf32_Rel *) (rel_addr + tpnt->loadaddr);
170 rel_size = rel_size / sizeof(Elf32_Rel);
172 symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
173 strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
175 for (i = 0; i < rel_size; i++, rpnt++) {
176 reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
177 reloc_type = ELF32_R_TYPE(rpnt->r_info);
178 symtab_index = ELF32_R_SYM(rpnt->r_info);
181 if (!symtab_index && tpnt->libtype == program_interpreter)
186 if (tpnt->libtype == program_interpreter &&
187 _dl_symbol(strtab + symtab[symtab_index].st_name))
190 symbol_addr = (unsigned long) _dl_find_hash(strtab + symtab[symtab_index].st_name,
191 tpnt->symbol_scope, (unsigned long) reloc_addr,
192 (reloc_type == R_386_JMP_SLOT ? tpnt : NULL), 0);
195 * We want to allow undefined references to weak symbols - this might
196 * have been intentional. We should not be linking local symbols
197 * here, so all bases should be covered.
200 ELF32_ST_BIND(symtab[symtab_index].st_info) == STB_GLOBAL) {
201 _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
202 _dl_progname, strtab + symtab[symtab_index].st_name);
206 switch (reloc_type) {
210 *reloc_addr += symbol_addr;
213 *reloc_addr += symbol_addr - (unsigned long) reloc_addr;
217 *reloc_addr = symbol_addr;
220 *reloc_addr += (unsigned long) tpnt->loadaddr;
225 _dl_dprintf(2, "Doing copy for symbol ");
226 if (symtab_index) _dl_dprintf(2, strtab + symtab[symtab_index].st_name);
227 _dl_dprintf(2, "\n");
228 _dl_memcpy((void *) symtab[symtab_index].st_value,
229 (void *) symbol_addr, symtab[symtab_index].st_size);
233 _dl_dprintf(2, "%s: can't handle reloc type ", _dl_progname);
234 #ifdef VERBOSE_DLINKER
235 _dl_dprintf(2, "%s ", _dl_reltypes[reloc_type]);
238 _dl_dprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name);
247 /* This is done as a separate step, because there are cases where
248 information is first copied and later initialized. This results in
249 the wrong information being copied. Someone at Sun was complaining about
250 a bug in the handling of _COPY by SVr4, and this may in fact be what he
251 was talking about. Sigh. */
253 /* No, there are cases where the SVr4 linker fails to emit COPY relocs
256 int _dl_parse_copy_information(struct dyn_elf *xpnt, unsigned long rel_addr,
257 unsigned long rel_size, int type)
265 unsigned long *reloc_addr;
266 unsigned long symbol_addr;
267 struct elf_resolve *tpnt;
270 /* Now parse the relocation information */
274 rpnt = (Elf32_Rel *) (rel_addr + tpnt->loadaddr);
275 rel_size = rel_size / sizeof(Elf32_Rel);
277 symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
278 strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
280 for (i = 0; i < rel_size; i++, rpnt++) {
281 reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
282 reloc_type = ELF32_R_TYPE(rpnt->r_info);
283 if (reloc_type != R_386_COPY)
285 symtab_index = ELF32_R_SYM(rpnt->r_info);
287 if (!symtab_index && tpnt->libtype == program_interpreter)
291 if (tpnt->libtype == program_interpreter &&
292 _dl_symbol(strtab + symtab[symtab_index].st_name))
295 symbol_addr = (unsigned long) _dl_find_hash(strtab +
296 symtab[symtab_index].st_name, xpnt->next,
297 (unsigned long) reloc_addr, NULL, 1);
299 _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
300 _dl_progname, strtab + symtab[symtab_index].st_name);
305 _dl_memcpy((char *) symtab[symtab_index].st_value,
306 (char *) symbol_addr, symtab[symtab_index].st_size);