1 /* vi: set sw=4 ts=4: */
2 /* sparc ELF shared library loader suppport
4 * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
5 * David Engel, Hongjiu Lu and Mitch D'Souza
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. The name of the above contributors may not be
15 * used to endorse or promote products derived from this software
16 * without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 #if defined (__SUPPORT_LD_DEBUG__)
32 static const char * _dl_reltypes[] = { "R_SPARC_NONE", "R_SPARC_8",
33 "R_SPARC_16", "R_SPARC_32", "R_SPARC_DISP8", "R_SPARC_DISP16",
34 "R_SPARC_DISP32", "R_SPARC_WDISP30", "R_SPARC_WDISP22",
35 "R_SPARC_HI22", "R_SPARC_22", "R_SPARC_13", "R_SPARC_LO10",
36 "R_SPARC_GOT10", "R_SPARC_GOT13", "R_SPARC_GOT22", "R_SPARC_PC10",
37 "R_SPARC_PC22", "R_SPARC_WPLT30", "R_SPARC_COPY",
38 "R_SPARC_GLOB_DAT", "R_SPARC_JMP_SLOT", "R_SPARC_RELATIVE",
42 /* Program to load an ELF binary on a linux system, and run it.
43 References to symbols in sharable libraries can be resolved by either
44 an ELF sharable library or a linux style of shared library. */
46 /* Disclaimer: I have never seen any AT&T source code for SVr4, nor have
47 I ever taken any courses on internals. This program was developed using
48 information available through the book "UNIX SYSTEM V RELEASE 4,
49 Programmers guide: Ansi C and Programming Support Tools", which did
50 a more than adequate job of explaining everything required to get this
53 extern int _dl_linux_resolve(void);
55 unsigned int _dl_linux_resolver(unsigned int reloc_entry, unsigned int * plt)
58 Elf32_Rela * this_reloc;
61 Elf32_Rela * rel_addr;
62 struct elf_resolve * tpnt;
66 unsigned int instr_addr;
67 tpnt = (struct elf_resolve *) plt[2];
69 rel_addr = (Elf32_Rela *) (tpnt->dynamic_info[DT_JMPREL] +
73 * Generate the correct relocation index into the .rela.plt section.
75 reloc_entry = (reloc_entry >> 10) - 0xc;
77 this_reloc = (Elf32_Rela *) ((char *) rel_addr + reloc_entry);
79 reloc_type = ELF32_R_TYPE(this_reloc->r_info);
80 symtab_index = ELF32_R_SYM(this_reloc->r_info);
82 symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
83 strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
85 #ifdef __SUPPORT_LD_DEBUG__
86 if (_dl_debug_symbols) {
87 _dl_dprintf(2, "tpnt = %x\n", tpnt);
88 _dl_dprintf(2, "reloc = %x\n", this_reloc);
89 _dl_dprintf(2, "symtab = %x\n", symtab);
90 _dl_dprintf(2, "strtab = %x\n", strtab);
95 if (unlikely(reloc_type != R_SPARC_JMP_SLOT)) {
96 _dl_dprintf(2, "%s: incorrect relocation type in jump relocations (%d)\n",
97 _dl_progname, reloc_type);
101 /* Address of jump instruction to fix up */
102 instr_addr = ((int)this_reloc->r_offset + (int)tpnt->loadaddr);
103 got_addr = (char **) instr_addr;
105 #ifdef __SUPPORT_LD_DEBUG__
106 if (_dl_debug_symbols) {
107 _dl_dprintf(2, "symtab_index %x\n", symtab_index);
109 _dl_dprintf(2, "Resolving symbol %s\n",
110 strtab + symtab[symtab_index].st_name);
114 /* Get the address of the GOT entry */
115 new_addr = _dl_find_hash(strtab + symtab[symtab_index].st_name,
116 tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT);
117 if(unlikely(!new_addr)) {
118 _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
119 _dl_progname, strtab + symtab[symtab_index].st_name);
123 #if defined (__SUPPORT_LD_DEBUG__)
124 if ((unsigned long) got_addr < 0x40000000)
126 if (_dl_debug_bindings)
128 _dl_dprintf(_dl_debug_file, "\nresolve function: %s",
129 strtab + symtab[symtab_index].st_name);
130 if(_dl_debug_detail) _dl_dprintf(_dl_debug_file,
131 "\tpatch %x ==> %x @ %x", *got_addr, new_addr, got_addr);
134 if (!_dl_debug_nofixups) {
135 got_addr[1] = (char *) (0x03000000 | (((unsigned int) new_addr >> 10) & 0x3fffff));
136 got_addr[2] = (char *) (0x81c06000 | ((unsigned int) new_addr & 0x3ff));
139 got_addr[1] = (char *) (0x03000000 | (((unsigned int) new_addr >> 10) & 0x3fffff));
140 got_addr[2] = (char *) (0x81c06000 | ((unsigned int) new_addr & 0x3ff));
143 _dl_dprintf(2, "Address = %x\n",new_addr);
146 return (unsigned int) new_addr;
149 void _dl_parse_lazy_relocation_information(struct dyn_elf *arg_rpnt,
150 unsigned long rel_addr, unsigned long rel_size)
158 unsigned int * reloc_addr;
159 struct elf_resolve * tpnt = arg_rpnt->dyn;
161 /* Now parse the relocation information */
162 rpnt = (Elf32_Rela *) (rel_addr + tpnt->loadaddr);
164 symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
165 strtab = ( char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
167 for(i=0; i< rel_size; i += sizeof(Elf32_Rela), rpnt++){
168 reloc_addr = (int *) (tpnt->loadaddr + (int)rpnt->r_offset);
169 reloc_type = ELF32_R_TYPE(rpnt->r_info);
170 symtab_index = ELF32_R_SYM(rpnt->r_info);
175 case R_SPARC_JMP_SLOT:
178 _dl_dprintf(2, "%s: (LAZY) can't handle reloc type ", _dl_progname);
179 #if defined (__SUPPORT_LD_DEBUG__)
180 _dl_dprintf(2, "%s ", _dl_reltypes[reloc_type]);
182 if(symtab_index) _dl_dprintf(2, "'%s'\n",
183 strtab + symtab[symtab_index].st_name);
189 int _dl_parse_relocation_information(struct dyn_elf *arg_rpnt,
190 unsigned long rel_addr, unsigned long rel_size)
198 unsigned int * reloc_addr;
199 unsigned int symbol_addr;
201 struct elf_resolve * tpnt = arg_rpnt->dyn;
202 /* Now parse the relocation information */
204 rpnt = (Elf32_Rela *) (rel_addr + tpnt->loadaddr);
206 symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
207 strtab = ( char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
209 for(i=0; i< rel_size; i+= sizeof(Elf32_Rela), rpnt++){
210 reloc_addr = (int *) (tpnt->loadaddr + (int)rpnt->r_offset);
211 reloc_type = ELF32_R_TYPE(rpnt->r_info);
212 symtab_index = ELF32_R_SYM(rpnt->r_info);
217 symbol_addr = (unsigned int)
218 _dl_find_hash(strtab + symtab[symtab_index].st_name,
219 tpnt->symbol_scope, tpnt, elf_machine_type_class(reloc_type));
222 ELF32_ST_BIND(symtab [symtab_index].st_info) != STB_WEAK) {
223 _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
224 _dl_progname, strtab + symtab[symtab_index].st_name);
232 *reloc_addr = symbol_addr + rpnt->r_addend;
235 *reloc_addr = symbol_addr + rpnt->r_addend - (unsigned int) reloc_addr;
237 case R_SPARC_GLOB_DAT:
238 *reloc_addr = symbol_addr + rpnt->r_addend;
240 case R_SPARC_JMP_SLOT:
241 reloc_addr[1] = 0x03000000 | ((symbol_addr >> 10) & 0x3fffff);
242 reloc_addr[2] = 0x81c06000 | (symbol_addr & 0x3ff);
244 case R_SPARC_RELATIVE:
245 *reloc_addr += (unsigned int) tpnt->loadaddr + rpnt->r_addend;
249 symbol_addr = tpnt->loadaddr + rpnt->r_addend;
251 symbol_addr += rpnt->r_addend;
252 *reloc_addr = (*reloc_addr & 0xffc00000)|(symbol_addr >> 10);
256 symbol_addr = tpnt->loadaddr + rpnt->r_addend;
258 symbol_addr += rpnt->r_addend;
259 *reloc_addr = (*reloc_addr & ~0x3ff)|(symbol_addr & 0x3ff);
261 case R_SPARC_WDISP30:
262 *reloc_addr = (*reloc_addr & 0xc0000000)|
263 ((symbol_addr - (unsigned int) reloc_addr) >> 2);
266 _dl_memcpy((void *) reloc_addr, (void *) symbol_addr, symtab[symtab_index].st_size);
269 _dl_dprintf(2, "%s: can't handle reloc type ", _dl_progname);
270 #if defined (__SUPPORT_LD_DEBUG__)
271 _dl_dprintf(2, "%s ", _dl_reltypes[reloc_type]);
274 _dl_dprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name);