1 /* Run an ELF binary on a linux system.
3 Copyright (C) 1993, Eric Youngdale.
4 Copyright (C) 1995, Andreas Schwab.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
20 /* Adapted to ELF/68k by Andreas Schwab. */
22 #ifndef VERBOSE_DLINKER
23 #define VERBOSE_DLINKER
25 #ifdef VERBOSE_DLINKER
26 static char *_dl_reltypes[] =
29 "R_68K_32", "R_68K_16", "R_68K_8",
30 "R_68K_PC32", "R_68K_PC16", "R_68K_PC8",
31 "R_68K_GOT32", "R_68K_GOT16", "R_68K_GOT8",
32 "R_68K_GOT32O", "R_68K_GOT16O", "R_68K_GOT8O",
33 "R_68K_PLT32", "R_68K_PLT16", "R_68K_PLT8",
34 "R_68K_PLT32O", "R_68K_PLT16O", "R_68K_PLT8O",
35 "R_68K_COPY", "R_68K_GLOB_DAT", "R_68K_JMP_SLOT", "R_68K_RELATIVE",
40 /* Program to load an ELF binary on a linux system, and run it.
41 References to symbols in sharable libraries can be resolved by either
42 an ELF sharable library or a linux style of shared library. */
44 /* Disclaimer: I have never seen any AT&T source code for SVr4, nor have
45 I ever taken any courses on internals. This program was developed using
46 information available through the book "UNIX SYSTEM V RELEASE 4,
47 Programmers guide: Ansi C and Programming Support Tools", which did
48 a more than adequate job of explaining everything required to get this
52 unsigned int _dl_linux_resolver (int dummy1, int dummy2,
53 struct elf_resolve *tpnt, int reloc_entry)
56 Elf32_Rela *this_reloc;
63 unsigned int instr_addr;
65 rel_addr = tpnt->loadaddr + tpnt->dynamic_info[DT_JMPREL];
66 this_reloc = (Elf32_Rela *) (rel_addr + reloc_entry);
67 reloc_type = ELF32_R_TYPE (this_reloc->r_info);
68 symtab_index = ELF32_R_SYM (this_reloc->r_info);
70 symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB]
72 strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
75 if (reloc_type != R_68K_JMP_SLOT)
77 _dl_dprintf (2, "%s: incorrect relocation type in jump relocations\n",
82 /* Address of jump instruction to fix up. */
83 instr_addr = (int) this_reloc->r_offset + (int) tpnt->loadaddr;
84 got_addr = (char **) instr_addr;
87 _dl_dprintf (2, "Resolving symbol %s\n",
88 strtab + symtab[symtab_index].st_name);
91 /* Get the address of the GOT entry. */
92 new_addr = _dl_find_hash (strtab + symtab[symtab_index].st_name,
93 tpnt->symbol_scope, (int) got_addr, tpnt, 0);
96 _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
97 _dl_progname, strtab + symtab[symtab_index].st_name);
100 /* #define DEBUG_LIBRARY */
102 if ((unsigned int) got_addr < 0x40000000)
103 _dl_dprintf (2, "Calling library function: %s\n",
104 strtab + symtab[symtab_index].st_name);
107 *got_addr = new_addr;
108 return (unsigned int) new_addr;
112 _dl_parse_lazy_relocation_information (struct elf_resolve *tpnt,
113 unsigned long rel_addr, unsigned long rel_size, int type)
121 unsigned int *reloc_addr;
123 /* Now parse the relocation information. */
124 rpnt = (Elf32_Rela *) (rel_addr + tpnt->loadaddr);
125 rel_size = rel_size / sizeof (Elf32_Rela);
127 symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB]
129 strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
131 for (i = 0; i < rel_size; i++, rpnt++)
133 reloc_addr = (int *) (tpnt->loadaddr + (int) rpnt->r_offset);
134 reloc_type = ELF32_R_TYPE (rpnt->r_info);
135 symtab_index = ELF32_R_SYM (rpnt->r_info);
137 /* When the dynamic linker bootstrapped itself, it resolved some symbols.
138 Make sure we do not do them again. */
139 if (tpnt->libtype == program_interpreter
141 || _dl_symbol (strtab + symtab[symtab_index].st_name)))
149 *reloc_addr += (unsigned int) tpnt->loadaddr;
152 _dl_dprintf (2, "%s: (LAZY) can't handle reloc type ", _dl_progname);
153 #ifdef VERBOSE_DLINKER
154 _dl_dprintf (2, "%s ", _dl_reltypes[reloc_type]);
157 _dl_dprintf (2, "'%s'", strtab + symtab[symtab_index].st_name);
158 _dl_dprintf (2, "\n");
165 _dl_parse_relocation_information (struct elf_resolve *tpnt,
166 unsigned long rel_addr, unsigned long rel_size, int type)
174 unsigned int *reloc_addr;
175 unsigned int symbol_addr;
177 /* Now parse the relocation information */
179 rpnt = (Elf32_Rela *) (rel_addr + tpnt->loadaddr);
180 rel_size = rel_size / sizeof (Elf32_Rela);
182 symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB]
184 strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
186 for (i = 0; i < rel_size; i++, rpnt++)
188 reloc_addr = (int *) (tpnt->loadaddr + (int) rpnt->r_offset);
189 reloc_type = ELF32_R_TYPE (rpnt->r_info);
190 symtab_index = ELF32_R_SYM (rpnt->r_info);
193 if (tpnt->libtype == program_interpreter
195 || _dl_symbol (strtab + symtab[symtab_index].st_name)))
200 symbol_addr = (unsigned int)
201 _dl_find_hash (strtab + symtab[symtab_index].st_name,
202 tpnt->symbol_scope, (int) reloc_addr,
203 reloc_type == R_68K_JMP_SLOT ? tpnt : NULL, 0);
205 /* We want to allow undefined references to weak symbols -
206 this might have been intentional. We should not be
207 linking local symbols here, so all bases should be
210 && ELF32_ST_BIND (symtab[symtab_index].st_info) == STB_GLOBAL)
212 _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
213 _dl_progname, strtab + symtab[symtab_index].st_name);
222 *(char *) reloc_addr = symbol_addr + rpnt->r_addend;
225 *(short *) reloc_addr = symbol_addr + rpnt->r_addend;
228 *reloc_addr = symbol_addr + rpnt->r_addend;
231 *(char *) reloc_addr = (symbol_addr + rpnt->r_addend
232 - (unsigned int) reloc_addr);
235 *(short *) reloc_addr = (symbol_addr + rpnt->r_addend
236 - (unsigned int) reloc_addr);
239 *reloc_addr = (symbol_addr + rpnt->r_addend
240 - (unsigned int) reloc_addr);
244 *reloc_addr = symbol_addr;
247 *reloc_addr = ((unsigned int) tpnt->loadaddr
248 /* Compatibility kludge. */
249 + (rpnt->r_addend ? : *reloc_addr));
252 #if 0 /* Do this later. */
253 _dl_dprintf (2, "Doing copy");
255 _dl_dprintf (2, " for symbol %s",
256 strtab + symtab[symtab_index].st_name);
257 _dl_dprintf (2, "\n");
258 _dl_memcpy ((void *) symtab[symtab_index].st_value,
259 (void *) symbol_addr,
260 symtab[symtab_index].st_size);
264 _dl_dprintf (2, "%s: can't handle reloc type ", _dl_progname);
265 #ifdef VERBOSE_DLINKER
266 _dl_dprintf (2, "%s ", _dl_reltypes[reloc_type]);
269 _dl_dprintf (2, "'%s'", strtab + symtab[symtab_index].st_name);
270 _dl_dprintf (2, "\n");
278 /* This is done as a separate step, because there are cases where
279 information is first copied and later initialized. This results in
280 the wrong information being copied. Someone at Sun was complaining about
281 a bug in the handling of _COPY by SVr4, and this may in fact be what he
282 was talking about. Sigh. */
284 /* No, there are cases where the SVr4 linker fails to emit COPY relocs
288 _dl_parse_copy_information (struct dyn_elf *xpnt, unsigned long rel_addr,
289 unsigned long rel_size, int type)
297 unsigned int *reloc_addr;
298 unsigned int symbol_addr;
299 struct elf_resolve *tpnt;
301 /* Now parse the relocation information */
305 rpnt = (Elf32_Rela *) (rel_addr + tpnt->loadaddr);
306 rel_size = rel_size / sizeof (Elf32_Rela);
308 symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB]
310 strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
312 for (i = 0; i < rel_size; i++, rpnt++)
314 reloc_addr = (int *) (tpnt->loadaddr + (int) rpnt->r_offset);
315 reloc_type = ELF32_R_TYPE (rpnt->r_info);
316 if (reloc_type != R_68K_COPY)
318 symtab_index = ELF32_R_SYM (rpnt->r_info);
320 if (tpnt->libtype == program_interpreter
322 || _dl_symbol (strtab + symtab[symtab_index].st_name)))
326 symbol_addr = (unsigned int)
327 _dl_find_hash (strtab + symtab[symtab_index].st_name,
328 xpnt->next, (int) reloc_addr, NULL, 1);
331 _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
332 _dl_progname, strtab + symtab[symtab_index].st_name);
337 _dl_memcpy ((void *) symtab[symtab_index].st_value, (void *) symbol_addr,
338 symtab[symtab_index].st_size);