1 /* vi: set sw=4 ts=4: */
2 /* m68k ELF shared library loader suppport
4 * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
5 * David Engel, Hongjiu Lu and Mitch D'Souza
6 * Adapted to ELF/68k by Andreas Schwab.
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[] =
36 "R_68K_32", "R_68K_16", "R_68K_8",
37 "R_68K_PC32", "R_68K_PC16", "R_68K_PC8",
38 "R_68K_GOT32", "R_68K_GOT16", "R_68K_GOT8",
39 "R_68K_GOT32O", "R_68K_GOT16O", "R_68K_GOT8O",
40 "R_68K_PLT32", "R_68K_PLT16", "R_68K_PLT8",
41 "R_68K_PLT32O", "R_68K_PLT16O", "R_68K_PLT8O",
42 "R_68K_COPY", "R_68K_GLOB_DAT", "R_68K_JMP_SLOT", "R_68K_RELATIVE",
47 /* Program to load an ELF binary on a linux system, and run it.
48 References to symbols in sharable libraries can be resolved by either
49 an ELF sharable library or a linux style of shared library. */
51 /* Disclaimer: I have never seen any AT&T source code for SVr4, nor have
52 I ever taken any courses on internals. This program was developed using
53 information available through the book "UNIX SYSTEM V RELEASE 4,
54 Programmers guide: Ansi C and Programming Support Tools", which did
55 a more than adequate job of explaining everything required to get this
59 unsigned int _dl_linux_resolver (int dummy1, int dummy2,
60 struct elf_resolve *tpnt, int reloc_entry)
63 Elf32_Rela *this_reloc;
70 unsigned int instr_addr;
72 rel_addr = tpnt->loadaddr + tpnt->dynamic_info[DT_JMPREL];
73 this_reloc = (Elf32_Rela *) (rel_addr + reloc_entry);
74 reloc_type = ELF32_R_TYPE (this_reloc->r_info);
75 symtab_index = ELF32_R_SYM (this_reloc->r_info);
77 symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB]
79 strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
82 if (reloc_type != R_68K_JMP_SLOT)
84 _dl_dprintf (2, "%s: incorrect relocation type in jump relocations\n",
89 /* Address of jump instruction to fix up. */
90 instr_addr = (int) this_reloc->r_offset + (int) tpnt->loadaddr;
91 got_addr = (char **) instr_addr;
93 #ifdef __SUPPORT_LD_DEBUG__
94 if (_dl_debug_symbols) {
95 _dl_dprintf (2, "Resolving symbol %s\n", strtab + symtab[symtab_index].st_name);
99 /* Get the address of the GOT entry. */
100 new_addr = _dl_find_hash (strtab + symtab[symtab_index].st_name,
101 tpnt->symbol_scope, tpnt, resolver);
104 _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
105 _dl_progname, strtab + symtab[symtab_index].st_name);
108 #if defined (__SUPPORT_LD_DEBUG__)
109 if ((unsigned long) got_addr < 0x40000000)
111 if (_dl_debug_bindings)
113 _dl_dprintf(_dl_debug_file, "\nresolve function: %s",
114 strtab + symtab[symtab_index].st_name);
115 if(_dl_debug_detail) _dl_dprintf(_dl_debug_file,
116 "\tpatch %x ==> %x @ %x", *got_addr, new_addr, got_addr);
119 if (!_dl_debug_nofixups) {
120 *got_addr = new_addr;
123 *got_addr = new_addr;
126 return (unsigned int) new_addr;
129 void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
130 unsigned long rel_addr, unsigned long rel_size, int type)
138 unsigned int *reloc_addr;
139 struct elf_resolve *tpnt = rpnt->dyn;
141 /* Now parse the relocation information. */
142 rpnt = (Elf32_Rela *) (rel_addr + tpnt->loadaddr);
143 rel_size = rel_size / sizeof (Elf32_Rela);
145 symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB]
147 strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
149 for (i = 0; i < rel_size; i++, rpnt++)
151 reloc_addr = (int *) (tpnt->loadaddr + (int) rpnt->r_offset);
152 reloc_type = ELF32_R_TYPE (rpnt->r_info);
153 symtab_index = ELF32_R_SYM (rpnt->r_info);
155 /* When the dynamic linker bootstrapped itself, it resolved some symbols.
156 Make sure we do not do them again. */
157 if (tpnt->libtype == program_interpreter
159 || _dl_symbol (strtab + symtab[symtab_index].st_name)))
167 *reloc_addr += (unsigned int) tpnt->loadaddr;
170 _dl_dprintf (2, "%s: (LAZY) can't handle reloc type ", _dl_progname);
171 #if defined (__SUPPORT_LD_DEBUG__)
172 _dl_dprintf (2, "%s ", _dl_reltypes[reloc_type]);
175 _dl_dprintf (2, "'%s'", strtab + symtab[symtab_index].st_name);
176 _dl_dprintf (2, "\n");
182 int _dl_parse_relocation_information(struct dyn_elf *rpnt,
183 unsigned long rel_addr, unsigned long rel_size, int type)
191 unsigned int *reloc_addr;
192 unsigned int symbol_addr;
194 struct elf_resolve *tpnt = rpnt->dyn;
195 /* Now parse the relocation information */
197 rpnt = (Elf32_Rela *) (rel_addr + tpnt->loadaddr);
198 rel_size = rel_size / sizeof (Elf32_Rela);
200 symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB]
202 strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
204 for (i = 0; i < rel_size; i++, rpnt++)
206 reloc_addr = (int *) (tpnt->loadaddr + (int) rpnt->r_offset);
207 reloc_type = ELF32_R_TYPE (rpnt->r_info);
208 symtab_index = ELF32_R_SYM (rpnt->r_info);
211 if (tpnt->libtype == program_interpreter
213 || _dl_symbol (strtab + symtab[symtab_index].st_name)))
218 symbol_addr = (unsigned int)
219 _dl_find_hash (strtab + symtab[symtab_index].st_name,
221 reloc_type == R_68K_JMP_SLOT ? tpnt : NULL, symbolrel);
223 /* We want to allow undefined references to weak symbols -
224 this might have been intentional. We should not be
225 linking local symbols here, so all bases should be
228 && ELF32_ST_BIND (symtab[symtab_index].st_info) == STB_GLOBAL)
230 _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
231 _dl_progname, strtab + symtab[symtab_index].st_name);
240 *(char *) reloc_addr = symbol_addr + rpnt->r_addend;
243 *(short *) reloc_addr = symbol_addr + rpnt->r_addend;
246 *reloc_addr = symbol_addr + rpnt->r_addend;
249 *(char *) reloc_addr = (symbol_addr + rpnt->r_addend
250 - (unsigned int) reloc_addr);
253 *(short *) reloc_addr = (symbol_addr + rpnt->r_addend
254 - (unsigned int) reloc_addr);
257 *reloc_addr = (symbol_addr + rpnt->r_addend
258 - (unsigned int) reloc_addr);
262 *reloc_addr = symbol_addr;
265 *reloc_addr = ((unsigned int) tpnt->loadaddr
266 /* Compatibility kludge. */
267 + (rpnt->r_addend ? : *reloc_addr));
270 #if 0 /* Do this later. */
271 _dl_dprintf (2, "Doing copy");
273 _dl_dprintf (2, " for symbol %s",
274 strtab + symtab[symtab_index].st_name);
275 _dl_dprintf (2, "\n");
276 _dl_memcpy ((void *) symtab[symtab_index].st_value,
277 (void *) symbol_addr,
278 symtab[symtab_index].st_size);
282 _dl_dprintf (2, "%s: can't handle reloc type ", _dl_progname);
283 #if defined (__SUPPORT_LD_DEBUG__)
284 _dl_dprintf (2, "%s ", _dl_reltypes[reloc_type]);
287 _dl_dprintf (2, "'%s'", strtab + symtab[symtab_index].st_name);
288 _dl_dprintf (2, "\n");
296 /* This is done as a separate step, because there are cases where
297 information is first copied and later initialized. This results in
298 the wrong information being copied. Someone at Sun was complaining about
299 a bug in the handling of _COPY by SVr4, and this may in fact be what he
300 was talking about. Sigh. */
302 /* No, there are cases where the SVr4 linker fails to emit COPY relocs
305 int _dl_parse_copy_information(struct dyn_elf *xpnt,
306 unsigned long rel_addr, unsigned long rel_size, int type)
314 unsigned int *reloc_addr;
315 unsigned int symbol_addr;
316 struct elf_resolve *tpnt;
318 /* Now parse the relocation information */
322 rpnt = (Elf32_Rela *) (rel_addr + tpnt->loadaddr);
323 rel_size = rel_size / sizeof (Elf32_Rela);
325 symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB]
327 strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
329 for (i = 0; i < rel_size; i++, rpnt++)
331 reloc_addr = (int *) (tpnt->loadaddr + (int) rpnt->r_offset);
332 reloc_type = ELF32_R_TYPE (rpnt->r_info);
333 if (reloc_type != R_68K_COPY)
335 symtab_index = ELF32_R_SYM (rpnt->r_info);
337 if (tpnt->libtype == program_interpreter
339 || _dl_symbol (strtab + symtab[symtab_index].st_name)))
343 symbol_addr = (unsigned int)
344 _dl_find_hash (strtab + symtab[symtab_index].st_name,
345 xpnt->next, NULL, copyrel);
348 _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
349 _dl_progname, strtab + symtab[symtab_index].st_name);
354 _dl_memcpy ((void *) symtab[symtab_index].st_value, (void *) symbol_addr,
355 symtab[symtab_index].st_size);