OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [uClibc/] [ldso/] [ldso/] [sparc/] [elfinterp.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1325 phoenix
/* vi: set sw=4 ts=4: */
2
/* sparc ELF shared library loader suppport
3
 *
4
 * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
5
 *                              David Engel, Hongjiu Lu and Mitch D'Souza
6
 *
7
 * All rights reserved.
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
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.
17
 *
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
28
 * SUCH DAMAGE.
29
 */
30
 
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",
39
  "R_SPARC_UA32"};
40
#endif
41
 
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. */
45
 
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
51
   working. */
52
 
53
extern _dl_linux_resolve(void);
54
 
55
unsigned int _dl_linux_resolver(unsigned int reloc_entry, unsigned int * plt)
56
{
57
  int reloc_type;
58
  Elf32_Rela * this_reloc;
59
  char * strtab;
60
  Elf32_Sym * symtab;
61
  Elf32_Rela * rel_addr;
62
  struct elf_resolve * tpnt;
63
  int symtab_index;
64
  char * new_addr;
65
  char ** got_addr;
66
  unsigned int instr_addr;
67
  tpnt = (struct elf_resolve *) plt[2];
68
 
69
  rel_addr = (Elf32_Rela *) (tpnt->dynamic_info[DT_JMPREL] +
70
                                   tpnt->loadaddr);
71
 
72
  /*
73
   * Generate the correct relocation index into the .rela.plt section.
74
   */
75
  reloc_entry = (reloc_entry >> 12) - 0xc;
76
 
77
  this_reloc = (Elf32_Rela *) ((char *) rel_addr + reloc_entry);
78
 
79
  reloc_type = ELF32_R_TYPE(this_reloc->r_info);
80
  symtab_index = ELF32_R_SYM(this_reloc->r_info);
81
 
82
  symtab =  (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
83
  strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
84
 
85
  _dl_dprintf(2, "tpnt = %x\n", tpnt);
86
  _dl_dprintf(2, "reloc = %x\n", this_reloc);
87
  _dl_dprintf(2, "symtab = %x\n", symtab);
88
  _dl_dprintf(2, "strtab = %x\n", strtab);
89
 
90
 
91
  if (reloc_type != R_SPARC_JMP_SLOT) {
92
    _dl_dprintf(2, "%s: incorrect relocation type in jump relocations (%d)\n",
93
                  _dl_progname, reloc_type);
94
    _dl_exit(30);
95
  };
96
 
97
  /* Address of jump instruction to fix up */
98
  instr_addr  = ((int)this_reloc->r_offset  + (int)tpnt->loadaddr);
99
  got_addr = (char **) instr_addr;
100
 
101
  _dl_dprintf(2, "symtab_index %d\n", symtab_index);
102
 
103
#ifdef __SUPPORT_LD_DEBUG__
104
  if (_dl_debug_symbols) {
105
          _dl_dprintf(2, "Resolving symbol %s\n",
106
                          strtab + symtab[symtab_index].st_name);
107
  }
108
#endif
109
 
110
  /* Get the address of the GOT entry */
111
  new_addr = _dl_find_hash(strtab + symtab[symtab_index].st_name,
112
                        tpnt->symbol_scope, tpnt, resolver);
113
  if(!new_addr) {
114
    _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
115
               _dl_progname, strtab + symtab[symtab_index].st_name);
116
    _dl_exit(31);
117
  };
118
 
119
#if defined (__SUPPORT_LD_DEBUG__)
120
        if ((unsigned long) got_addr < 0x40000000)
121
        {
122
                if (_dl_debug_bindings)
123
                {
124
                        _dl_dprintf(_dl_debug_file, "\nresolve function: %s",
125
                                        strtab + symtab[symtab_index].st_name);
126
                        if(_dl_debug_detail) _dl_dprintf(_dl_debug_file,
127
                                        "\tpatch %x ==> %x @ %x", *got_addr, new_addr, got_addr);
128
                }
129
        }
130
        if (!_dl_debug_nofixups) {
131
                got_addr[1] = (char *) (0x03000000 | (((unsigned int) new_addr >> 10) & 0x3fffff));
132
                got_addr[2] = (char *) (0x81c06000 | ((unsigned int) new_addr & 0x3ff));
133
        }
134
#else
135
        got_addr[1] = (char *) (0x03000000 | (((unsigned int) new_addr >> 10) & 0x3fffff));
136
        got_addr[2] = (char *) (0x81c06000 | ((unsigned int) new_addr & 0x3ff));
137
#endif
138
 
139
        _dl_dprintf(2, "Address = %x\n",new_addr);
140
        _dl_exit(32);
141
 
142
  return (unsigned int) new_addr;
143
}
144
 
145
void _dl_parse_lazy_relocation_information(struct elf_resolve * tpnt, int rel_addr,
146
       int rel_size, int type){
147
  int i;
148
  char * strtab;
149
  int reloc_type;
150
  int symtab_index;
151
  Elf32_Sym * symtab;
152
  Elf32_Rela * rpnt;
153
  unsigned int * reloc_addr;
154
 
155
  /* Now parse the relocation information */
156
  rpnt = (Elf32_Rela *) (rel_addr + tpnt->loadaddr);
157
 
158
  symtab =  (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
159
  strtab = ( char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
160
 
161
  for(i=0; i< rel_size; i += sizeof(Elf32_Rela), rpnt++){
162
    reloc_addr = (int *) (tpnt->loadaddr + (int)rpnt->r_offset);
163
    reloc_type = ELF32_R_TYPE(rpnt->r_info);
164
    symtab_index = ELF32_R_SYM(rpnt->r_info);
165
 
166
    /* When the dynamic linker bootstrapped itself, it resolved some symbols.
167
       Make sure we do not do them again */
168
    if(!symtab_index && tpnt->libtype == program_interpreter) continue;
169
    if(symtab_index && tpnt->libtype == program_interpreter &&
170
       _dl_symbol(strtab + symtab[symtab_index].st_name))
171
      continue;
172
 
173
    switch(reloc_type){
174
    case R_SPARC_NONE:
175
      break;
176
    case R_SPARC_JMP_SLOT:
177
      break;
178
    default:
179
      _dl_dprintf(2, "%s: (LAZY) can't handle reloc type ", _dl_progname);
180
#if defined (__SUPPORT_LD_DEBUG__)
181
      _dl_dprintf(2, "%s ", _dl_reltypes[reloc_type]);
182
#endif
183
      if(symtab_index) _dl_dprintf(2, "'%s'\n",
184
                                  strtab + symtab[symtab_index].st_name);
185
      _dl_exit(33);
186
    };
187
  };
188
}
189
 
190
int _dl_parse_relocation_information(struct elf_resolve * tpnt, int rel_addr,
191
       int rel_size, int type){
192
  int i;
193
  char * strtab;
194
  int reloc_type;
195
  int goof = 0;
196
  Elf32_Sym * symtab;
197
  Elf32_Rela * rpnt;
198
  unsigned int * reloc_addr;
199
  unsigned int symbol_addr;
200
  int symtab_index;
201
  /* Now parse the relocation information */
202
 
203
  rpnt = (Elf32_Rela *) (rel_addr + tpnt->loadaddr);
204
 
205
  symtab =  (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
206
  strtab = ( char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
207
 
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);
212
    symbol_addr = 0;
213
 
214
    if(!symtab_index && tpnt->libtype == program_interpreter) continue;
215
 
216
    if(symtab_index) {
217
 
218
      if(tpnt->libtype == program_interpreter &&
219
         _dl_symbol(strtab + symtab[symtab_index].st_name))
220
        continue;
221
 
222
      symbol_addr = (unsigned int)
223
        _dl_find_hash(strtab + symtab[symtab_index].st_name,
224
                              tpnt->symbol_scope,
225
                      (reloc_type == R_SPARC_JMP_SLOT ? tpnt : NULL), symbolrel);
226
 
227
      if(!symbol_addr &&
228
         ELF32_ST_BIND(symtab [symtab_index].st_info) == STB_GLOBAL) {
229
        _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
230
                     _dl_progname, strtab + symtab[symtab_index].st_name);
231
        goof++;
232
      };
233
    };
234
    switch(reloc_type){
235
    case R_SPARC_NONE:
236
        break;
237
    case R_SPARC_32:
238
      *reloc_addr = symbol_addr + rpnt->r_addend;
239
      break;
240
    case R_SPARC_DISP32:
241
      *reloc_addr = symbol_addr + rpnt->r_addend - (unsigned int) reloc_addr;
242
      break;
243
    case R_SPARC_GLOB_DAT:
244
      *reloc_addr = symbol_addr + rpnt->r_addend;
245
      break;
246
    case R_SPARC_JMP_SLOT:
247
      reloc_addr[1] = 0x03000000 | ((symbol_addr >> 10) & 0x3fffff);
248
      reloc_addr[2] = 0x81c06000 | (symbol_addr & 0x3ff);
249
      break;
250
    case R_SPARC_RELATIVE:
251
      *reloc_addr += (unsigned int) tpnt->loadaddr + rpnt->r_addend;
252
      break;
253
    case R_SPARC_HI22:
254
      if (!symbol_addr)
255
        symbol_addr = tpnt->loadaddr + rpnt->r_addend;
256
      else
257
        symbol_addr += rpnt->r_addend;
258
      *reloc_addr = (*reloc_addr & 0xffc00000)|(symbol_addr >> 10);
259
      break;
260
    case R_SPARC_LO10:
261
      if (!symbol_addr)
262
        symbol_addr = tpnt->loadaddr + rpnt->r_addend;
263
      else
264
        symbol_addr += rpnt->r_addend;
265
      *reloc_addr = (*reloc_addr & ~0x3ff)|(symbol_addr & 0x3ff);
266
      break;
267
    case R_SPARC_WDISP30:
268
      *reloc_addr = (*reloc_addr & 0xc0000000)|
269
        ((symbol_addr - (unsigned int) reloc_addr) >> 2);
270
      break;
271
    case R_SPARC_COPY:
272
#if 0 /* This one is done later */
273
      _dl_dprintf(2, "Doing copy for symbol ");
274
      if(symtab_index) _dl_dprintf(2, 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);
279
#endif
280
      break;
281
    default:
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]);
285
#endif
286
      if (symtab_index)
287
        _dl_dprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name);
288
      _dl_exit(34);
289
    };
290
 
291
  };
292
  return goof;
293
}
294
 
295
 
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. */
301
 
302
/* No, there are cases where the SVr4 linker fails to emit COPY relocs
303
   at all */
304
 
305
int _dl_parse_copy_information(struct dyn_elf * xpnt, int rel_addr,
306
       int rel_size, int type)
307
{
308
  int i;
309
  char * strtab;
310
  int reloc_type;
311
  int goof = 0;
312
  Elf32_Sym * symtab;
313
  Elf32_Rela * rpnt;
314
  unsigned int * reloc_addr;
315
  unsigned int symbol_addr;
316
  struct elf_resolve *tpnt;
317
  int symtab_index;
318
  /* Now parse the relocation information */
319
 
320
  tpnt = xpnt->dyn;
321
 
322
  rpnt = (Elf32_Rela *) (rel_addr + tpnt->loadaddr);
323
 
324
  symtab =  (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
325
  strtab = ( char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
326
 
327
  for(i=0; i< rel_size; i+= sizeof(Elf32_Rela), rpnt++){
328
    reloc_addr = (int *) (tpnt->loadaddr + (int)rpnt->r_offset);
329
    reloc_type = ELF32_R_TYPE(rpnt->r_info);
330
    if(reloc_type != R_SPARC_COPY) continue;
331
    symtab_index = ELF32_R_SYM(rpnt->r_info);
332
    symbol_addr = 0;
333
    if(!symtab_index && tpnt->libtype == program_interpreter) continue;
334
    if(symtab_index) {
335
 
336
      if(tpnt->libtype == program_interpreter &&
337
         _dl_symbol(strtab + symtab[symtab_index].st_name))
338
        continue;
339
 
340
      symbol_addr = (unsigned int)
341
        _dl_find_hash(strtab + symtab[symtab_index].st_name,
342
                              xpnt->next, NULL, copyrel);
343
      if(!symbol_addr) {
344
        _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
345
                   _dl_progname, strtab + symtab[symtab_index].st_name);
346
        goof++;
347
      };
348
    };
349
    if (!goof)
350
      _dl_memcpy((char *) symtab[symtab_index].st_value,
351
                  (char *) symbol_addr,
352
                  symtab[symtab_index].st_size);
353
  };
354
  return goof;
355
}
356
 
357
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.