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;
86 #ifdef DL_DEBUG_SYMBOLS
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 #ifdef DL_NEVER_FIXUP_SYMBOLS
101 if ((unsigned int) got_addr < 0x40000000) {
102 _dl_dprintf (2, "Calling library function: %s\n",
103 strtab + symtab[symtab_index].st_name);
105 *got_addr = new_addr;
108 *got_addr = new_addr;
110 return (unsigned int) new_addr;
114 _dl_parse_lazy_relocation_information (struct elf_resolve *tpnt,
115 unsigned long rel_addr, unsigned long rel_size, int type)
123 unsigned int *reloc_addr;
125 /* Now parse the relocation information. */
126 rpnt = (Elf32_Rela *) (rel_addr + tpnt->loadaddr);
127 rel_size = rel_size / sizeof (Elf32_Rela);
129 symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB]
131 strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
133 for (i = 0; i < rel_size; i++, rpnt++)
135 reloc_addr = (int *) (tpnt->loadaddr + (int) rpnt->r_offset);
136 reloc_type = ELF32_R_TYPE (rpnt->r_info);
137 symtab_index = ELF32_R_SYM (rpnt->r_info);
139 /* When the dynamic linker bootstrapped itself, it resolved some symbols.
140 Make sure we do not do them again. */
141 if (tpnt->libtype == program_interpreter
143 || _dl_symbol (strtab + symtab[symtab_index].st_name)))
151 *reloc_addr += (unsigned int) tpnt->loadaddr;
154 _dl_dprintf (2, "%s: (LAZY) can't handle reloc type ", _dl_progname);
155 #ifdef VERBOSE_DLINKER
156 _dl_dprintf (2, "%s ", _dl_reltypes[reloc_type]);
159 _dl_dprintf (2, "'%s'", strtab + symtab[symtab_index].st_name);
160 _dl_dprintf (2, "\n");
167 _dl_parse_relocation_information (struct elf_resolve *tpnt,
168 unsigned long rel_addr, unsigned long rel_size, int type)
176 unsigned int *reloc_addr;
177 unsigned int symbol_addr;
179 /* Now parse the relocation information */
181 rpnt = (Elf32_Rela *) (rel_addr + tpnt->loadaddr);
182 rel_size = rel_size / sizeof (Elf32_Rela);
184 symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB]
186 strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
188 for (i = 0; i < rel_size; i++, rpnt++)
190 reloc_addr = (int *) (tpnt->loadaddr + (int) rpnt->r_offset);
191 reloc_type = ELF32_R_TYPE (rpnt->r_info);
192 symtab_index = ELF32_R_SYM (rpnt->r_info);
195 if (tpnt->libtype == program_interpreter
197 || _dl_symbol (strtab + symtab[symtab_index].st_name)))
202 symbol_addr = (unsigned int)
203 _dl_find_hash (strtab + symtab[symtab_index].st_name,
204 tpnt->symbol_scope, (int) reloc_addr,
205 reloc_type == R_68K_JMP_SLOT ? tpnt : NULL, 0);
207 /* We want to allow undefined references to weak symbols -
208 this might have been intentional. We should not be
209 linking local symbols here, so all bases should be
212 && ELF32_ST_BIND (symtab[symtab_index].st_info) == STB_GLOBAL)
214 _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
215 _dl_progname, strtab + symtab[symtab_index].st_name);
224 *(char *) reloc_addr = symbol_addr + rpnt->r_addend;
227 *(short *) reloc_addr = symbol_addr + rpnt->r_addend;
230 *reloc_addr = symbol_addr + rpnt->r_addend;
233 *(char *) reloc_addr = (symbol_addr + rpnt->r_addend
234 - (unsigned int) reloc_addr);
237 *(short *) reloc_addr = (symbol_addr + rpnt->r_addend
238 - (unsigned int) reloc_addr);
241 *reloc_addr = (symbol_addr + rpnt->r_addend
242 - (unsigned int) reloc_addr);
246 *reloc_addr = symbol_addr;
249 *reloc_addr = ((unsigned int) tpnt->loadaddr
250 /* Compatibility kludge. */
251 + (rpnt->r_addend ? : *reloc_addr));
254 #if 0 /* Do this later. */
255 _dl_dprintf (2, "Doing copy");
257 _dl_dprintf (2, " for symbol %s",
258 strtab + symtab[symtab_index].st_name);
259 _dl_dprintf (2, "\n");
260 _dl_memcpy ((void *) symtab[symtab_index].st_value,
261 (void *) symbol_addr,
262 symtab[symtab_index].st_size);
266 _dl_dprintf (2, "%s: can't handle reloc type ", _dl_progname);
267 #ifdef VERBOSE_DLINKER
268 _dl_dprintf (2, "%s ", _dl_reltypes[reloc_type]);
271 _dl_dprintf (2, "'%s'", strtab + symtab[symtab_index].st_name);
272 _dl_dprintf (2, "\n");
280 /* This is done as a separate step, because there are cases where
281 information is first copied and later initialized. This results in
282 the wrong information being copied. Someone at Sun was complaining about
283 a bug in the handling of _COPY by SVr4, and this may in fact be what he
284 was talking about. Sigh. */
286 /* No, there are cases where the SVr4 linker fails to emit COPY relocs
290 _dl_parse_copy_information (struct dyn_elf *xpnt, unsigned long rel_addr,
291 unsigned long rel_size, int type)
299 unsigned int *reloc_addr;
300 unsigned int symbol_addr;
301 struct elf_resolve *tpnt;
303 /* Now parse the relocation information */
307 rpnt = (Elf32_Rela *) (rel_addr + tpnt->loadaddr);
308 rel_size = rel_size / sizeof (Elf32_Rela);
310 symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB]
312 strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
314 for (i = 0; i < rel_size; i++, rpnt++)
316 reloc_addr = (int *) (tpnt->loadaddr + (int) rpnt->r_offset);
317 reloc_type = ELF32_R_TYPE (rpnt->r_info);
318 if (reloc_type != R_68K_COPY)
320 symtab_index = ELF32_R_SYM (rpnt->r_info);
322 if (tpnt->libtype == program_interpreter
324 || _dl_symbol (strtab + symtab[symtab_index].st_name)))
328 symbol_addr = (unsigned int)
329 _dl_find_hash (strtab + symtab[symtab_index].st_name,
330 xpnt->next, (int) reloc_addr, NULL, 1);
333 _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
334 _dl_progname, strtab + symtab[symtab_index].st_name);
339 _dl_memcpy ((void *) symtab[symtab_index].st_value, (void *) symbol_addr,
340 symtab[symtab_index].st_size);