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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [newlib-1.17.0/] [newlib/] [libc/] [sys/] [linux/] [machine/] [i386/] [dl-machine.h] - Blame information for rev 438

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

Line No. Rev Author Line
1 148 jeremybenn
/* Machine-dependent ELF dynamic relocation inline functions.  i386 version.
2
   Copyright (C) 1995,96,97,98,99,2000,2001 Free Software Foundation, Inc.
3
   This file is part of the GNU C Library.
4
 
5
   The GNU C Library is free software; you can redistribute it and/or
6
   modify it under the terms of the GNU Lesser General Public
7
   License as published by the Free Software Foundation; either
8
   version 2.1 of the License, or (at your option) any later version.
9
 
10
   The GNU C Library is distributed in the hope that it will be useful,
11
   but WITHOUT ANY WARRANTY; without even the implied warranty of
12
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
   Lesser General Public License for more details.
14
 
15
   You should have received a copy of the GNU Lesser General Public
16
   License along with the GNU C Library; if not, write to the Free
17
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18
   02111-1307 USA.  */
19
 
20
#ifndef dl_machine_h
21
#define dl_machine_h
22
 
23
#define ELF_MACHINE_NAME "i386"
24
 
25
#include <sys/param.h>
26
#include <machine/weakalias.h>
27
 
28
/* Return nonzero iff ELF header is compatible with the running host.  */
29
static inline int __attribute__ ((unused))
30
elf_machine_matches_host (const Elf32_Ehdr *ehdr)
31
{
32
  return ehdr->e_machine == EM_386;
33
}
34
 
35
 
36
/* Return the link-time address of _DYNAMIC.  Conveniently, this is the
37
   first element of the GOT.  This must be inlined in a function which
38
   uses global data.  */
39
static inline Elf32_Addr __attribute__ ((unused))
40
elf_machine_dynamic (void)
41
{
42
  register Elf32_Addr *got asm ("%ebx");
43
  return *got;
44
}
45
 
46
 
47
/* Return the run-time load address of the shared object.  */
48
static inline Elf32_Addr __attribute__ ((unused))
49
elf_machine_load_address (void)
50
{
51
  Elf32_Addr addr;
52
  asm ("leal _dl_start@GOTOFF(%%ebx), %0\n"
53
       "subl _dl_start@GOT(%%ebx), %0"
54
       : "=r" (addr) : : "cc");
55
  return addr;
56
}
57
 
58
#if !defined PROF && !__BOUNDED_POINTERS__
59
/* We add a declaration of this function here so that in dl-runtime.c
60
   the ELF_MACHINE_RUNTIME_TRAMPOLINE macro really can pass the parameters
61
   in registers.
62
 
63
   We cannot use this scheme for profiling because the _mcount call
64
   destroys the passed register information.  */
65
/* GKM FIXME: Fix trampoline to pass bounds so we can do
66
   without the `__unbounded' qualifier.  */
67
static ElfW(Addr) fixup (struct link_map *__unbounded l, ElfW(Word) reloc_offset)
68
     __attribute__ ((regparm (2), unused));
69
static ElfW(Addr) profile_fixup (struct link_map *l, ElfW(Word) reloc_offset,
70
                                 ElfW(Addr) retaddr)
71
     __attribute__ ((regparm (3), unused));
72
#endif
73
 
74
/* Set up the loaded object described by L so its unrelocated PLT
75
   entries will jump to the on-demand fixup code in dl-runtime.c.  */
76
 
77
static inline int __attribute__ ((unused))
78
elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
79
{
80
  Elf32_Addr *got;
81
  extern void _dl_runtime_resolve (Elf32_Word);
82
  extern void _dl_runtime_profile (Elf32_Word);
83
 
84
  if (l->l_info[DT_JMPREL] && lazy)
85
    {
86
      /* The GOT entries for functions in the PLT have not yet been filled
87
         in.  Their initial contents will arrange when called to push an
88
         offset into the .rel.plt section, push _GLOBAL_OFFSET_TABLE_[1],
89
         and then jump to _GLOBAL_OFFSET_TABLE[2].  */
90
      got = (Elf32_Addr *) D_PTR (l, l_info[DT_PLTGOT]);
91
      got[1] = (Elf32_Addr) l;  /* Identify this shared object.  */
92
 
93
      /* The got[2] entry contains the address of a function which gets
94
         called to get the address of a so far unresolved function and
95
         jump to it.  The profiling extension of the dynamic linker allows
96
         to intercept the calls to collect information.  In this case we
97
         don't store the address in the GOT so that all future calls also
98
         end in this function.  */
99
      if (__builtin_expect (profile, 0))
100
        {
101
          got[2] = (Elf32_Addr) &_dl_runtime_profile;
102
 
103
          if (_dl_name_match_p (_dl_profile, l))
104
            /* This is the object we are looking for.  Say that we really
105
               want profiling and the timers are started.  */
106
            _dl_profile_map = l;
107
        }
108
      else
109
        /* This function will get called to fix up the GOT entry indicated by
110
           the offset on the stack, and then jump to the resolved address.  */
111
        got[2] = (Elf32_Addr) &_dl_runtime_resolve;
112
    }
113
 
114
  return lazy;
115
}
116
 
117
/* This code is used in dl-runtime.c to call the `fixup' function
118
   and then redirect to the address it returns.  */
119
#if !defined PROF && !__BOUNDED_POINTERS__
120
# define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\
121
        .text\n\
122
        .globl _dl_runtime_resolve\n\
123
        .type _dl_runtime_resolve, @function\n\
124
        .align 16\n\
125
_dl_runtime_resolve:\n\
126
        pushl %eax              # Preserve registers otherwise clobbered.\n\
127
        pushl %ecx\n\
128
        pushl %edx\n\
129
        movl 16(%esp), %edx     # Copy args pushed by PLT in register.  Note\n\
130
        movl 12(%esp), %eax     # that `fixup' takes its parameters in regs.\n\
131
        call fixup              # Call resolver.\n\
132
        popl %edx               # Get register content back.\n\
133
        popl %ecx\n\
134
        xchgl %eax, (%esp)      # Get %eax contents end store function address.\n\
135
        ret $8                  # Jump to function address.\n\
136
        .size _dl_runtime_resolve, .-_dl_runtime_resolve\n\
137
\n\
138
        .globl _dl_runtime_profile\n\
139
        .type _dl_runtime_profile, @function\n\
140
        .align 16\n\
141
_dl_runtime_profile:\n\
142
        pushl %eax              # Preserve registers otherwise clobbered.\n\
143
        pushl %ecx\n\
144
        pushl %edx\n\
145
        movl 20(%esp), %ecx     # Load return address\n\
146
        movl 16(%esp), %edx     # Copy args pushed by PLT in register.  Note\n\
147
        movl 12(%esp), %eax     # that `fixup' takes its parameters in regs.\n\
148
        call profile_fixup      # Call resolver.\n\
149
        popl %edx               # Get register content back.\n\
150
        popl %ecx\n\
151
        xchgl %eax, (%esp)      # Get %eax contents end store function address.\n\
152
        ret $8                  # Jump to function address.\n\
153
        .size _dl_runtime_profile, .-_dl_runtime_profile\n\
154
        .previous\n\
155
");
156
#else
157
# define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\n\
158
        .text\n\
159
        .globl _dl_runtime_resolve\n\
160
        .globl _dl_runtime_profile\n\
161
        .type _dl_runtime_resolve, @function\n\
162
        .type _dl_runtime_profile, @function\n\
163
        .align 16\n\
164
_dl_runtime_resolve:\n\
165
_dl_runtime_profile:\n\
166
        pushl %eax              # Preserve registers otherwise clobbered.\n\
167
        pushl %ecx\n\
168
        pushl %edx\n\
169
        movl 16(%esp), %edx     # Push the arguments for `fixup'\n\
170
        movl 12(%esp), %eax\n\
171
        pushl %edx\n\
172
        pushl %eax\n\
173
        call fixup              # Call resolver.\n\
174
        popl %edx               # Pop the parameters\n\
175
        popl %ecx\n\
176
        popl %edx               # Get register content back.\n\
177
        popl %ecx\n\
178
        xchgl %eax, (%esp)      # Get %eax contents end store function address.\n\
179
        ret $8                  # Jump to function address.\n\
180
        .size _dl_runtime_resolve, .-_dl_runtime_resolve\n\
181
        .size _dl_runtime_profile, .-_dl_runtime_profile\n\
182
        .previous\n\
183
");
184
#endif
185
 
186
/* Mask identifying addresses reserved for the user program,
187
   where the dynamic linker should not map anything.  */
188
#define ELF_MACHINE_USER_ADDRESS_MASK   0xf8000000UL
189
 
190
/* Initial entry point code for the dynamic linker.
191
   The C function `_dl_start' is the real entry point;
192
   its return value is the user program's entry point.  */
193
 
194
#define RTLD_START asm ("\n\
195
        .text\n\
196
        .align 16\n\
197
0:       movl (%esp), %ebx\n\
198
        ret\n\
199
        .align 16\n\
200
.globl _start\n\
201
.globl _dl_start_user\n\
202
_start:\n\
203
        pushl %esp\n\
204
        call _dl_start\n\
205
        popl %ebx\n\
206
_dl_start_user:\n\
207
        # Save the user entry point address in %edi.\n\
208
        movl %eax, %edi\n\
209
        # Point %ebx at the GOT.\n\
210
        call 0b\n\
211
        addl $_GLOBAL_OFFSET_TABLE_, %ebx\n\
212
        # Store the highest stack address\n\
213
        movl __libc_stack_end@GOT(%ebx), %eax\n\
214
        movl %esp, (%eax)\n\
215
        # See if we were run as a command with the executable file\n\
216
        # name as an extra leading argument.\n\
217
        movl _dl_skip_args@GOT(%ebx), %eax\n\
218
        movl (%eax), %eax\n\
219
        # Pop the original argument count.\n\
220
        popl %edx\n\
221
        # Adjust the stack pointer to skip _dl_skip_args words.\n\
222
        leal (%esp,%eax,4), %esp\n\
223
        # Subtract _dl_skip_args from argc.\n\
224
        subl %eax, %edx\n\
225
        # Push argc back on the stack.\n\
226
        push %edx\n\
227
        # The special initializer gets called with the stack just\n\
228
        # as the application's entry point will see it; it can\n\
229
        # switch stacks if it moves these contents over.\n\
230
" RTLD_START_SPECIAL_INIT "\n\
231
        # Load the parameters again.\n\
232
        # (eax, edx, ecx, *--esp) = (_dl_loaded, argc, argv, envp)\n\
233
        movl _dl_loaded@GOT(%ebx), %esi\n\
234
        leal 8(%esp,%edx,4), %eax\n\
235
        leal 4(%esp), %ecx\n\
236
        pushl %eax\n\
237
        movl (%esi), %eax\n\
238
        # Call the function to run the initializers.\n\
239
        call _dl_init@PLT\n\
240
        # Pass our finalizer function to the user in %edx, as per ELF ABI.\n\
241
        movl _dl_fini@GOT(%ebx), %edx\n\
242
        # Jump to the user's entry point.\n\
243
        jmp *%edi\n\
244
        .previous\n\
245
");
246
 
247
#ifndef RTLD_START_SPECIAL_INIT
248
#define RTLD_START_SPECIAL_INIT /* nothing */
249
#endif
250
 
251
/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
252
   PLT entries should not be allowed to define the value.
253
   ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
254
   of the main executable's symbols, as for a COPY reloc.  */
255
#define elf_machine_type_class(type) \
256
  ((((type) == R_386_JMP_SLOT) * ELF_RTYPE_CLASS_PLT)   \
257
   | (((type) == R_386_COPY) * ELF_RTYPE_CLASS_COPY))
258
 
259
/* A reloc type used for ld.so cmdline arg lookups to reject PLT entries.  */
260
#define ELF_MACHINE_JMP_SLOT    R_386_JMP_SLOT
261
 
262
/* The i386 never uses Elf32_Rela relocations.  */
263
#define ELF_MACHINE_NO_RELA 1
264
 
265
/* We define an initialization functions.  This is called very early in
266
   _dl_sysdep_start.  */
267
#define DL_PLATFORM_INIT dl_platform_init ()
268
 
269
extern const char *_dl_platform;
270
 
271
static inline void __attribute__ ((unused))
272
dl_platform_init (void)
273
{
274
  if (_dl_platform != NULL && *_dl_platform == '\0')
275
    /* Avoid an empty string which would disturb us.  */
276
    _dl_platform = NULL;
277
}
278
 
279
static inline Elf32_Addr
280
elf_machine_fixup_plt (struct link_map *map, lookup_t t,
281
                       const Elf32_Rel *reloc,
282
                       Elf32_Addr *reloc_addr, Elf32_Addr value)
283
{
284
  return *reloc_addr = value;
285
}
286
 
287
/* Return the final value of a plt relocation.  */
288
static inline Elf32_Addr
289
elf_machine_plt_value (struct link_map *map, const Elf32_Rel *reloc,
290
                       Elf32_Addr value)
291
{
292
  return value;
293
}
294
 
295
static inline void __attribute__ ((unused))
296
elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
297
                 const Elf32_Sym *sym, const struct r_found_version *version,
298
                 Elf32_Addr *const reloc_addr,
299
                 struct r_scope_elem *scope[]);
300
 
301
static inline void __attribute__ ((unused))
302
elf_machine_rel_relative (Elf32_Addr l_addr, const Elf32_Rel *reloc,
303
                          Elf32_Addr *const reloc_addr);
304
 
305
static inline void
306
elf_machine_lazy_rel (struct link_map *map,
307
                      Elf32_Addr l_addr, const Elf32_Rel *reloc);
308
 
309
#endif /* !dl_machine_h */
310
 
311
#ifdef RESOLVE
312
 
313
/* Perform the relocation specified by RELOC and SYM (which is fully resolved).
314
   MAP is the object containing the reloc.  */
315
 
316
static inline void __attribute__ ((unused))
317
elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
318
                 const Elf32_Sym *sym, const struct r_found_version *version,
319
                 Elf32_Addr *const reloc_addr,
320
                 struct r_scope_elem *scope[])
321
{
322
  const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
323
 
324
#if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC
325
  if (__builtin_expect (r_type == R_386_RELATIVE, 0))
326
    {
327
# if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC
328
      /* This is defined in rtld.c, but nowhere in the static libc.a;
329
         make the reference weak so static programs can still link.
330
         This declaration cannot be done when compiling rtld.c
331
         (i.e. #ifdef RTLD_BOOTSTRAP) because rtld.c contains the
332
         common defn for _dl_rtld_map, which is incompatible with a
333
         weak decl in the same file.  */
334
      #pragma weak _dl_rtld_map
335
      if (map != &_dl_rtld_map) /* Already done in rtld itself.  */
336
# endif
337
        *reloc_addr += map->l_addr;
338
    }
339
# ifndef RTLD_BOOTSTRAP
340
  else if (__builtin_expect (r_type == R_386_NONE, 0))
341
    return;
342
# endif
343
  else
344
#endif
345
    {
346
#ifndef RTLD_BOOTSTRAP
347
      const Elf32_Sym *const refsym = sym;
348
#endif
349
      /* String table object symbols.  */
350
      const char *strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
351
      Elf32_Addr value = RESOLVE (&sym, version, r_type, scope);
352
      if (sym)
353
        value += sym->st_value;
354
 
355
#ifdef RTLD_BOOTSTRAP
356
      assert (r_type == R_386_GLOB_DAT || r_type == R_386_JMP_SLOT);
357
      *reloc_addr = value;
358
#else
359
      switch (r_type)
360
        {
361
        case R_386_GLOB_DAT:
362
        case R_386_JMP_SLOT:
363
          *reloc_addr = value;
364
          break;
365
        case R_386_32:
366
          *reloc_addr += value;
367
          break;
368
        case R_386_PC32:
369
          *reloc_addr += (value - (Elf32_Addr) reloc_addr);
370
          break;
371
        case R_386_COPY:
372
          if (sym == NULL)
373
            /* This can happen in trace mode if an object could not be
374
               found.  */
375
            break;
376
          if (__builtin_expect (sym->st_size > refsym->st_size, 0)
377
              || (__builtin_expect (sym->st_size < refsym->st_size, 0)
378
                  && _dl_verbose))
379
            {
380
              const char *strtab;
381
 
382
              strtab = (const char *) D_PTR (map, l_info[DT_STRTAB]);
383
              _dl_error_printf ("\
384
%s: Symbol `%s' has different size in shared object, consider re-linking\n",
385
                                _dl_argv[0] ?: "<program name unknown>",
386
                                strtab + refsym->st_name);
387
            }
388
          memcpy (reloc_addr, (void *) value, MIN (sym->st_size,
389
                                                   refsym->st_size));
390
          break;
391
        default:
392
          _dl_reloc_bad_type (map, r_type, 0);
393
          break;
394
        }
395
#endif
396
    }
397
}
398
 
399
static inline void __attribute__ ((unused))
400
elf_machine_rel_relative (Elf32_Addr l_addr, const Elf32_Rel *reloc,
401
                          Elf32_Addr *const reloc_addr)
402
{
403
  assert (ELF32_R_TYPE (reloc->r_info) == R_386_RELATIVE);
404
  *reloc_addr += l_addr;
405
}
406
 
407
static inline void
408
elf_machine_lazy_rel (struct link_map *map,
409
                      Elf32_Addr l_addr, const Elf32_Rel *reloc)
410
{
411
  Elf32_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
412
  const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
413
  /* Check for unexpected PLT reloc type.  */
414
  if (__builtin_expect (r_type == R_386_JMP_SLOT, 1))
415
    *reloc_addr += l_addr;
416
  else
417
    _dl_reloc_bad_type (map, r_type, 1);
418
}
419
 
420
#endif /* RESOLVE */

powered by: WebSVN 2.1.0

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