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

Subversion Repositories or1k

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

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1325 phoenix
/* vi: set sw=4 ts=4: */
2
/* m68k 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
 * Adapted to ELF/68k by Andreas Schwab.
7
 *
8
 * All rights reserved.
9
 *
10
 * Redistribution and use in source and binary forms, with or without
11
 * modification, are permitted provided that the following conditions
12
 * are met:
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.
18
 *
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
29
 * SUCH DAMAGE.
30
 */
31
 
32
#if defined (__SUPPORT_LD_DEBUG__)
33
static const char *_dl_reltypes[] =
34
{
35
  "R_68K_NONE",
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",
43
  "R_68K_NUM"
44
};
45
#endif
46
 
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. */
50
 
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
56
   working. */
57
 
58
 
59
unsigned int _dl_linux_resolver (int dummy1, int dummy2,
60
        struct elf_resolve *tpnt, int reloc_entry)
61
{
62
  int reloc_type;
63
  Elf32_Rela *this_reloc;
64
  char *strtab;
65
  Elf32_Sym *symtab;
66
  char *rel_addr;
67
  int symtab_index;
68
  char *new_addr;
69
  char **got_addr;
70
  unsigned int instr_addr;
71
 
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);
76
 
77
  symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB]
78
                                 + tpnt->loadaddr);
79
  strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
80
 
81
 
82
  if (reloc_type != R_68K_JMP_SLOT)
83
    {
84
      _dl_dprintf (2, "%s: incorrect relocation type in jump relocations\n",
85
                    _dl_progname);
86
      _dl_exit (1);
87
    }
88
 
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;
92
 
93
#ifdef __SUPPORT_LD_DEBUG__
94
  if (_dl_debug_symbols) {
95
          _dl_dprintf (2, "Resolving symbol %s\n", strtab + symtab[symtab_index].st_name);
96
  }
97
#endif
98
 
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);
102
  if (!new_addr)
103
    {
104
      _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
105
                    _dl_progname, strtab + symtab[symtab_index].st_name);
106
      _dl_exit (1);
107
    }
108
#if defined (__SUPPORT_LD_DEBUG__)
109
        if ((unsigned long) got_addr < 0x40000000)
110
        {
111
                if (_dl_debug_bindings)
112
                {
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);
117
                }
118
        }
119
        if (!_dl_debug_nofixups) {
120
                *got_addr = new_addr;
121
        }
122
#else
123
        *got_addr = new_addr;
124
#endif
125
 
126
  return (unsigned int) new_addr;
127
}
128
 
129
void
130
_dl_parse_lazy_relocation_information (struct elf_resolve *tpnt,
131
                       unsigned long rel_addr, unsigned long rel_size, int type)
132
{
133
  int i;
134
  char *strtab;
135
  int reloc_type;
136
  int symtab_index;
137
  Elf32_Sym *symtab;
138
  Elf32_Rela *rpnt;
139
  unsigned int *reloc_addr;
140
 
141
  /* Now parse the relocation information.  */
142
  rpnt = (Elf32_Rela *) (rel_addr + tpnt->loadaddr);
143
  rel_size = rel_size / sizeof (Elf32_Rela);
144
 
145
  symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB]
146
                                 + tpnt->loadaddr);
147
  strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
148
 
149
  for (i = 0; i < rel_size; i++, rpnt++)
150
    {
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);
154
 
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
158
          && (!symtab_index
159
              || _dl_symbol (strtab + symtab[symtab_index].st_name)))
160
        continue;
161
 
162
      switch (reloc_type)
163
        {
164
        case R_68K_NONE:
165
          break;
166
        case R_68K_JMP_SLOT:
167
          *reloc_addr += (unsigned int) tpnt->loadaddr;
168
          break;
169
        default:
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]);
173
#endif
174
          if (symtab_index)
175
            _dl_dprintf (2, "'%s'", strtab + symtab[symtab_index].st_name);
176
          _dl_dprintf (2, "\n");
177
          _dl_exit (1);
178
        }
179
    }
180
}
181
 
182
int
183
_dl_parse_relocation_information (struct elf_resolve *tpnt,
184
                  unsigned long rel_addr, unsigned long rel_size, int type)
185
{
186
  int i;
187
  char *strtab;
188
  int reloc_type;
189
  int goof = 0;
190
  Elf32_Sym *symtab;
191
  Elf32_Rela *rpnt;
192
  unsigned int *reloc_addr;
193
  unsigned int symbol_addr;
194
  int symtab_index;
195
  /* Now parse the relocation information */
196
 
197
  rpnt = (Elf32_Rela *) (rel_addr + tpnt->loadaddr);
198
  rel_size = rel_size / sizeof (Elf32_Rela);
199
 
200
  symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB]
201
                                 + tpnt->loadaddr);
202
  strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
203
 
204
  for (i = 0; i < rel_size; i++, rpnt++)
205
    {
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);
209
      symbol_addr = 0;
210
 
211
      if (tpnt->libtype == program_interpreter
212
          && (!symtab_index
213
              || _dl_symbol (strtab + symtab[symtab_index].st_name)))
214
        continue;
215
 
216
      if (symtab_index)
217
        {
218
          symbol_addr = (unsigned int)
219
            _dl_find_hash (strtab + symtab[symtab_index].st_name,
220
                           tpnt->symbol_scope,
221
                           reloc_type == R_68K_JMP_SLOT ? tpnt : NULL, symbolrel);
222
 
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
226
             covered.  */
227
          if (!symbol_addr
228
              && ELF32_ST_BIND (symtab[symtab_index].st_info) == STB_GLOBAL)
229
            {
230
              _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
231
                            _dl_progname, strtab + symtab[symtab_index].st_name);
232
              goof++;
233
            }
234
        }
235
      switch (reloc_type)
236
        {
237
        case R_68K_NONE:
238
          break;
239
        case R_68K_8:
240
          *(char *) reloc_addr = symbol_addr + rpnt->r_addend;
241
          break;
242
        case R_68K_16:
243
          *(short *) reloc_addr = symbol_addr + rpnt->r_addend;
244
          break;
245
        case R_68K_32:
246
          *reloc_addr = symbol_addr + rpnt->r_addend;
247
          break;
248
        case R_68K_PC8:
249
          *(char *) reloc_addr = (symbol_addr + rpnt->r_addend
250
                                  - (unsigned int) reloc_addr);
251
          break;
252
        case R_68K_PC16:
253
          *(short *) reloc_addr = (symbol_addr + rpnt->r_addend
254
                                   - (unsigned int) reloc_addr);
255
          break;
256
        case R_68K_PC32:
257
          *reloc_addr = (symbol_addr + rpnt->r_addend
258
                         - (unsigned int) reloc_addr);
259
          break;
260
        case R_68K_GLOB_DAT:
261
        case R_68K_JMP_SLOT:
262
          *reloc_addr = symbol_addr;
263
          break;
264
        case R_68K_RELATIVE:
265
          *reloc_addr = ((unsigned int) tpnt->loadaddr
266
                         /* Compatibility kludge.  */
267
                         + (rpnt->r_addend ? : *reloc_addr));
268
          break;
269
        case R_68K_COPY:
270
#if 0 /* Do this later.  */
271
          _dl_dprintf (2, "Doing copy");
272
          if (symtab_index)
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);
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'", strtab + symtab[symtab_index].st_name);
288
          _dl_dprintf (2, "\n");
289
          _dl_exit (1);
290
        }
291
 
292
    }
293
  return goof;
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
306
_dl_parse_copy_information (struct dyn_elf *xpnt, unsigned long rel_addr,
307
                            unsigned long rel_size, int type)
308
{
309
  int i;
310
  char *strtab;
311
  int reloc_type;
312
  int goof = 0;
313
  Elf32_Sym *symtab;
314
  Elf32_Rela *rpnt;
315
  unsigned int *reloc_addr;
316
  unsigned int symbol_addr;
317
  struct elf_resolve *tpnt;
318
  int symtab_index;
319
  /* Now parse the relocation information */
320
 
321
  tpnt = xpnt->dyn;
322
 
323
  rpnt = (Elf32_Rela *) (rel_addr + tpnt->loadaddr);
324
  rel_size = rel_size / sizeof (Elf32_Rela);
325
 
326
  symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB]
327
                                 + tpnt->loadaddr);
328
  strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
329
 
330
  for (i = 0; i < rel_size; i++, rpnt++)
331
    {
332
      reloc_addr = (int *) (tpnt->loadaddr + (int) rpnt->r_offset);
333
      reloc_type = ELF32_R_TYPE (rpnt->r_info);
334
      if (reloc_type != R_68K_COPY)
335
        continue;
336
      symtab_index = ELF32_R_SYM (rpnt->r_info);
337
      symbol_addr = 0;
338
      if (tpnt->libtype == program_interpreter
339
          && (!symtab_index
340
              || _dl_symbol (strtab + symtab[symtab_index].st_name)))
341
        continue;
342
      if (symtab_index)
343
        {
344
          symbol_addr = (unsigned int)
345
            _dl_find_hash (strtab + symtab[symtab_index].st_name,
346
                           xpnt->next, NULL, copyrel);
347
          if (!symbol_addr)
348
            {
349
              _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
350
                            _dl_progname, strtab + symtab[symtab_index].st_name);
351
              goof++;
352
            }
353
        }
354
      if (!goof)
355
      _dl_memcpy ((void *) symtab[symtab_index].st_value, (void *) symbol_addr,
356
                  symtab[symtab_index].st_size);
357
    }
358
  return goof;
359
}

powered by: WebSVN 2.1.0

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