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];
72 * Generate the correct relocation index into the .rela.plt section.
74 reloc_entry = (reloc_entry >> 10) - 0xc;
76 this_reloc = (Elf32_Rela *) ((char *) rel_addr + reloc_entry);
78 reloc_type = ELF32_R_TYPE(this_reloc->r_info);
79 symtab_index = ELF32_R_SYM(this_reloc->r_info);
81 symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB];
82 strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
84 #ifdef __SUPPORT_LD_DEBUG__
85 if (_dl_debug_symbols) {
86 _dl_dprintf(2, "tpnt = %x\n", tpnt);
87 _dl_dprintf(2, "reloc = %x\n", this_reloc);
88 _dl_dprintf(2, "symtab = %x\n", symtab);
89 _dl_dprintf(2, "strtab = %x\n", strtab);
94 if (unlikely(reloc_type != R_SPARC_JMP_SLOT)) {
95 _dl_dprintf(2, "%s: incorrect relocation type in jump relocations (%d)\n",
96 _dl_progname, reloc_type);
100 /* Address of jump instruction to fix up */
101 instr_addr = ((int)this_reloc->r_offset + (int)tpnt->loadaddr);
102 got_addr = (char **) instr_addr;
104 #ifdef __SUPPORT_LD_DEBUG__
105 if (_dl_debug_symbols) {
106 _dl_dprintf(2, "symtab_index %x\n", symtab_index);
108 _dl_dprintf(2, "Resolving symbol %s\n",
109 strtab + symtab[symtab_index].st_name);
113 /* Get the address of the GOT entry */
114 new_addr = _dl_find_hash(strtab + symtab[symtab_index].st_name,
115 tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT);
116 if(unlikely(!new_addr)) {
117 _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
118 _dl_progname, strtab + symtab[symtab_index].st_name);
122 #if defined (__SUPPORT_LD_DEBUG__)
123 if ((unsigned long) got_addr < 0x40000000)
125 if (_dl_debug_bindings)
127 _dl_dprintf(_dl_debug_file, "\nresolve function: %s",
128 strtab + symtab[symtab_index].st_name);
129 if(_dl_debug_detail) _dl_dprintf(_dl_debug_file,
130 "\tpatch %x ==> %x @ %x", *got_addr, new_addr, got_addr);
133 if (!_dl_debug_nofixups) {
134 got_addr[1] = (char *) (0x03000000 | (((unsigned int) new_addr >> 10) & 0x3fffff));
135 got_addr[2] = (char *) (0x81c06000 | ((unsigned int) new_addr & 0x3ff));
138 got_addr[1] = (char *) (0x03000000 | (((unsigned int) new_addr >> 10) & 0x3fffff));
139 got_addr[2] = (char *) (0x81c06000 | ((unsigned int) new_addr & 0x3ff));
142 _dl_dprintf(2, "Address = %x\n",new_addr);
145 return (unsigned int) new_addr;
148 void _dl_parse_lazy_relocation_information(struct dyn_elf *arg_rpnt,
149 unsigned long rel_addr, unsigned long rel_size)
157 unsigned int * reloc_addr;
158 struct elf_resolve * tpnt = arg_rpnt->dyn;
160 /* Now parse the relocation information */
161 rpnt = (Elf32_Rela *)rel_addr;
163 symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB];
164 strtab = ( char *)tpnt->dynamic_info[DT_STRTAB];
166 for(i=0; i< rel_size; i += sizeof(Elf32_Rela), rpnt++){
167 reloc_addr = (int *) (tpnt->loadaddr + (int)rpnt->r_offset);
168 reloc_type = ELF32_R_TYPE(rpnt->r_info);
169 symtab_index = ELF32_R_SYM(rpnt->r_info);
174 case R_SPARC_JMP_SLOT:
177 _dl_dprintf(2, "%s: (LAZY) can't handle reloc type ", _dl_progname);
178 #if defined (__SUPPORT_LD_DEBUG__)
179 _dl_dprintf(2, "%s ", _dl_reltypes[reloc_type]);
181 if(symtab_index) _dl_dprintf(2, "'%s'\n",
182 strtab + symtab[symtab_index].st_name);
188 int _dl_parse_relocation_information(struct dyn_elf *arg_rpnt,
189 unsigned long rel_addr, unsigned long rel_size)
197 unsigned int * reloc_addr;
198 unsigned int symbol_addr;
200 struct elf_resolve * tpnt = arg_rpnt->dyn;
201 /* Now parse the relocation information */
203 rpnt = (Elf32_Rela *)rel_addr;
205 symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB];
206 strtab = ( char *)tpnt->dynamic_info[DT_STRTAB];
208 for(i=0; i< rel_size; i+= sizeof(Elf32_Rela), rpnt++){
209 reloc_addr = (int *) (tpnt->loadaddr + (int)rpnt->r_offset);
210 reloc_type = ELF32_R_TYPE(rpnt->r_info);
211 symtab_index = ELF32_R_SYM(rpnt->r_info);
216 symbol_addr = (unsigned int)
217 _dl_find_hash(strtab + symtab[symtab_index].st_name,
218 tpnt->symbol_scope, tpnt, elf_machine_type_class(reloc_type));
221 ELF32_ST_BIND(symtab [symtab_index].st_info) != STB_WEAK) {
222 _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
223 _dl_progname, strtab + symtab[symtab_index].st_name);
231 *reloc_addr = symbol_addr + rpnt->r_addend;
234 *reloc_addr = symbol_addr + rpnt->r_addend - (unsigned int) reloc_addr;
236 case R_SPARC_GLOB_DAT:
237 *reloc_addr = symbol_addr + rpnt->r_addend;
239 case R_SPARC_JMP_SLOT:
240 reloc_addr[1] = 0x03000000 | ((symbol_addr >> 10) & 0x3fffff);
241 reloc_addr[2] = 0x81c06000 | (symbol_addr & 0x3ff);
243 case R_SPARC_RELATIVE:
244 *reloc_addr += (unsigned int) tpnt->loadaddr + rpnt->r_addend;
248 symbol_addr = tpnt->loadaddr + rpnt->r_addend;
250 symbol_addr += rpnt->r_addend;
251 *reloc_addr = (*reloc_addr & 0xffc00000)|(symbol_addr >> 10);
255 symbol_addr = tpnt->loadaddr + rpnt->r_addend;
257 symbol_addr += rpnt->r_addend;
258 *reloc_addr = (*reloc_addr & ~0x3ff)|(symbol_addr & 0x3ff);
260 case R_SPARC_WDISP30:
261 *reloc_addr = (*reloc_addr & 0xc0000000)|
262 ((symbol_addr - (unsigned int) reloc_addr) >> 2);
265 _dl_memcpy((void *) reloc_addr, (void *) symbol_addr, symtab[symtab_index].st_size);
268 _dl_dprintf(2, "%s: can't handle reloc type ", _dl_progname);
269 #if defined (__SUPPORT_LD_DEBUG__)
270 _dl_dprintf(2, "%s ", _dl_reltypes[reloc_type]);
273 _dl_dprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name);