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/] [dl/] [dl-runtime.c] - Blame information for rev 438

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

Line No. Rev Author Line
1 148 jeremybenn
/* On-demand PLT fixup for shared objects.
2
   Copyright (C) 1995-1999, 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
#include <alloca.h>
21
#include <stdlib.h>
22
#include <unistd.h>
23
#include <ldsodefs.h>
24
#include "dynamic-link.h"
25
 
26
#ifndef __attribute_used__
27
#define __attribute_used__
28
#endif
29
 
30
#if !defined ELF_MACHINE_NO_RELA || ELF_MACHINE_NO_REL
31
# define PLTREL  ElfW(Rela)
32
#else
33
# define PLTREL  ElfW(Rel)
34
#endif
35
 
36
#ifndef VERSYMIDX
37
# define VERSYMIDX(sym) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (sym))
38
#endif
39
 
40
 
41
/* This function is called through a special trampoline from the PLT the
42
   first time each PLT entry is called.  We must perform the relocation
43
   specified in the PLT of the given shared object, and return the resolved
44
   function address to the trampoline, which will restart the original call
45
   to that address.  Future calls will bounce directly from the PLT to the
46
   function.  */
47
 
48
#ifndef ELF_MACHINE_NO_PLT
49
static ElfW(Addr) __attribute__ ((regparm (2), used))
50
fixup (
51
# ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
52
        ELF_MACHINE_RUNTIME_FIXUP_ARGS,
53
# endif
54
        /* GKM FIXME: Fix trampoline to pass bounds so we can do
55
           without the `__unbounded' qualifier.  */
56
       struct link_map *__unbounded l, ElfW(Word) reloc_offset)
57
{
58
  const ElfW(Sym) *const symtab
59
    = (const void *) D_PTR (l, l_info[DT_SYMTAB]);
60
  const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
61
 
62
  const PLTREL *const reloc
63
    = (const void *) (D_PTR (l, l_info[DT_JMPREL]) + reloc_offset);
64
  const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
65
  void *const rel_addr = (void *)(l->l_addr + reloc->r_offset);
66
  lookup_t result;
67
  ElfW(Addr) value;
68
 
69
  /* The use of `alloca' here looks ridiculous but it helps.  The goal is
70
     to prevent the function from being inlined and thus optimized out.
71
     There is no official way to do this so we use this trick.  gcc never
72
     inlines functions which use `alloca'.  */
73
  alloca (sizeof (int));
74
 
75
  /* Sanity check that we're really looking at a PLT relocation.  */
76
  assert (ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT);
77
 
78
   /* Look up the target symbol.  If the normal lookup rules are not
79
      used don't look in the global scope.  */
80
  if (__builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0)
81
    {
82
      switch (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
83
        {
84
        default:
85
          {
86
            const ElfW(Half) *vernum =
87
              (const void *) D_PTR (l, l_info[VERSYMIDX (DT_VERSYM)]);
88
            ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)];
89
            const struct r_found_version *version = &l->l_versions[ndx];
90
 
91
            if (version->hash != 0)
92
              {
93
                result = _dl_lookup_versioned_symbol (strtab + sym->st_name,
94
                                                      l, &sym, l->l_scope,
95
                                                      version,
96
                                                      ELF_RTYPE_CLASS_PLT, 0);
97
                break;
98
              }
99
          }
100
        case 0:
101
          result = _dl_lookup_symbol (strtab + sym->st_name, l, &sym,
102
                                      l->l_scope, ELF_RTYPE_CLASS_PLT, 0);
103
        }
104
 
105
      /* Currently result contains the base load address (or link map)
106
         of the object that defines sym.  Now add in the symbol
107
         offset.  */
108
      value = (sym ? LOOKUP_VALUE_ADDRESS (result) + sym->st_value : 0);
109
    }
110
  else
111
    {
112
      /* We already found the symbol.  The module (and therefore its load
113
         address) is also known.  */
114
      value = l->l_addr + sym->st_value;
115
#ifdef DL_LOOKUP_RETURNS_MAP
116
      result = l;
117
#endif
118
    }
119
 
120
  /* And now perhaps the relocation addend.  */
121
  value = elf_machine_plt_value (l, reloc, value);
122
 
123
  /* Finally, fix up the plt itself.  */
124
  if (__builtin_expect (_dl_bind_not, 0))
125
    return value;
126
 
127
  return elf_machine_fixup_plt (l, result, reloc, rel_addr, value);
128
}
129
#endif
130
 
131
#if !defined PROF && !defined ELF_MACHINE_NO_PLT && !__BOUNDED_POINTERS__
132
 
133
static ElfW(Addr) __attribute__ ((regparm (3), used))
134
profile_fixup (
135
#ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
136
       ELF_MACHINE_RUNTIME_FIXUP_ARGS,
137
#endif
138
       struct link_map *l, ElfW(Word) reloc_offset, ElfW(Addr) retaddr)
139
{
140
  void (*mcount_fct) (ElfW(Addr), ElfW(Addr)) = _dl_mcount;
141
  ElfW(Addr) *resultp;
142
  lookup_t result;
143
  ElfW(Addr) value;
144
 
145
  /* The use of `alloca' here looks ridiculous but it helps.  The goal is
146
     to prevent the function from being inlined, and thus optimized out.
147
     There is no official way to do this so we use this trick.  gcc never
148
     inlines functions which use `alloca'.  */
149
  alloca (sizeof (int));
150
 
151
  /* This is the address in the array where we store the result of previous
152
     relocations.  */
153
  resultp = &l->l_reloc_result[reloc_offset / sizeof (PLTREL)];
154
 
155
  value = *resultp;
156
  if (value == 0)
157
    {
158
      /* This is the first time we have to relocate this object.  */
159
      const ElfW(Sym) *const symtab
160
        = (const void *) D_PTR (l, l_info[DT_SYMTAB]);
161
      const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
162
 
163
      const PLTREL *const reloc
164
        = (const void *) (D_PTR (l, l_info[DT_JMPREL]) + reloc_offset);
165
      const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
166
 
167
      /* Sanity check that we're really looking at a PLT relocation.  */
168
      assert (ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT);
169
 
170
      /* Look up the target symbol.  If the symbol is marked STV_PROTECTED
171
         don't look in the global scope.  */
172
      if (__builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0)
173
        {
174
          switch (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
175
            {
176
            default:
177
              {
178
                const ElfW(Half) *vernum =
179
                  (const void *) D_PTR (l,l_info[VERSYMIDX (DT_VERSYM)]);
180
                ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)];
181
                const struct r_found_version *version = &l->l_versions[ndx];
182
 
183
                if (version->hash != 0)
184
                  {
185
                    result = _dl_lookup_versioned_symbol(strtab + sym->st_name,
186
                                                         l, &sym, l->l_scope,
187
                                                         version,
188
                                                         ELF_RTYPE_CLASS_PLT,
189
                                                         0);
190
                    break;
191
                  }
192
              }
193
            case 0:
194
              result = _dl_lookup_symbol (strtab + sym->st_name, l, &sym,
195
                                          l->l_scope, ELF_RTYPE_CLASS_PLT, 0);
196
            }
197
 
198
          /* Currently result contains the base load address (or link map)
199
             of the object that defines sym.  Now add in the symbol
200
             offset.  */
201
          value = (sym ? LOOKUP_VALUE_ADDRESS (result) + sym->st_value : 0);
202
        }
203
      else
204
        {
205
          /* We already found the symbol.  The module (and therefore its load
206
             address) is also known.  */
207
          value = l->l_addr + sym->st_value;
208
#ifdef DL_LOOKUP_RETURNS_MAP
209
          result = l;
210
#endif
211
        }
212
      /* And now perhaps the relocation addend.  */
213
      value = elf_machine_plt_value (l, reloc, value);
214
 
215
      /* Store the result for later runs.  */
216
      if (__builtin_expect (! _dl_bind_not, 1))
217
        *resultp = value;
218
    }
219
 
220
  (*mcount_fct) (retaddr, value);
221
 
222
  return value;
223
}
224
 
225
#endif /* PROF && ELF_MACHINE_NO_PLT */
226
 
227
 
228
/* This macro is defined in dl-machine.h to define the entry point called
229
   by the PLT.  The `fixup' function above does the real work, but a little
230
   more twiddling is needed to get the stack right and jump to the address
231
   finally resolved.  */
232
 
233
ELF_MACHINE_RUNTIME_TRAMPOLINE

powered by: WebSVN 2.1.0

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