]> sourceware.org Git - glibc.git/blame - elf/dl-runtime.c
* elf/dl-runtime.c (fixup, profile_fixup): The final arg to _dl_looku...
[glibc.git] / elf / dl-runtime.c
CommitLineData
38334018 1/* On-demand PLT fixup for shared objects.
ea7eb7e3 2 Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
afd4eb37 3 This file is part of the GNU C Library.
d66e34cd 4
afd4eb37
UD
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
d66e34cd 9
afd4eb37
UD
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 Library General Public License for more details.
d66e34cd 14
afd4eb37
UD
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
d66e34cd 19
3db52d94 20#include <unistd.h>
a853022c 21#include <elf/ldsodefs.h>
d66e34cd 22
ba79d61b
RM
23
24/* The global scope we will use for symbol lookups.
25 This will be modified by _dl_open if RTLD_GLOBAL is used. */
26struct link_map **_dl_global_scope = _dl_default_scope;
27struct link_map **_dl_global_scope_end = &_dl_default_scope[3];
28
29
30/* Hack _dl_global_scope[0] and [1] as necessary, and return a pointer into
31 _dl_global_scope that should be passed to _dl_lookup_symbol for symbol
32 references made in the object L's relocations. */
33inline struct link_map **
d0fc4041 34internal_function
ba79d61b
RM
35_dl_object_relocation_scope (struct link_map *l)
36{
37 if (l->l_info[DT_SYMBOLIC])
38 {
39 /* This object's global references are to be resolved first
40 in the object itself, and only secondarily in more global
41 scopes. */
42
43 if (! l->l_searchlist)
44 /* We must construct the searchlist for this object. */
46ec036d 45 _dl_map_object_deps (l, NULL, 0, 0);
ba79d61b
RM
46
47 /* The primary scope is this object itself and its
48 dependencies. */
49 _dl_global_scope[0] = l;
50
51 /* Secondary is the dependency tree that reached L; the object
52 requested directly by the user is at the root of that tree. */
53 while (l->l_loader)
54 l = l->l_loader;
55 _dl_global_scope[1] = l;
56
57 /* Finally, the global scope follows. */
58
59 return _dl_global_scope;
60 }
61 else
62 {
63 /* Use first the global scope, and then the scope of the root of the
64 dependency tree that first caused this object to be loaded. */
65 while (l->l_loader)
66 l = l->l_loader;
67 *_dl_global_scope_end = l;
68 return &_dl_global_scope[2];
69 }
70}
71\f
f51d1dfd
RM
72#include "dynamic-link.h"
73
a2b08ee5
UD
74#if !defined ELF_MACHINE_NO_RELA || ELF_MACHINE_NO_REL
75# define PLTREL ElfW(Rela)
38334018 76#else
a2b08ee5 77# define PLTREL ElfW(Rel)
38334018 78#endif
38334018 79
c84142e8
UD
80#ifndef VERSYMIDX
81# define VERSYMIDX(sym) (DT_NUM + DT_PROCNUM + DT_VERSIONTAGIDX (sym))
82#endif
83
38334018
RM
84
85/* This function is called through a special trampoline from the PLT the
86 first time each PLT entry is called. We must perform the relocation
87 specified in the PLT of the given shared object, and return the resolved
88 function address to the trampoline, which will restart the original call
89 to that address. Future calls will bounce directly from the PLT to the
90 function. */
91
a2b08ee5 92static ElfW(Addr) __attribute__ ((unused))
01f3e03b
RM
93fixup (
94#ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
95 ELF_MACHINE_RUNTIME_FIXUP_ARGS,
96#endif
266180eb 97 struct link_map *l, ElfW(Word) reloc_offset)
d66e34cd 98{
266180eb
RM
99 const ElfW(Sym) *const symtab
100 = (const ElfW(Sym) *) (l->l_addr + l->l_info[DT_SYMTAB]->d_un.d_ptr);
a1a9d215
RM
101 const char *strtab =
102 (const char *) (l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);
d66e34cd 103
38334018 104 const PLTREL *const reloc
a1a9d215
RM
105 = (const void *) (l->l_addr + l->l_info[DT_JMPREL]->d_un.d_ptr +
106 reloc_offset);
a2b08ee5
UD
107 const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
108 void *const rel_addr = (void *)(l->l_addr + reloc->r_offset);
109 ElfW(Addr) value;
d66e34cd 110
ba79d61b
RM
111 /* Set up the scope to find symbols referenced by this object. */
112 struct link_map **scope = _dl_object_relocation_scope (l);
113
a2b08ee5
UD
114 /* Sanity check that we're really looking at a PLT relocation. */
115 assert (ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT);
f51d1dfd 116
a2b08ee5
UD
117 /* Look up the target symbol. */
118 switch (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
119 {
120 default:
c84142e8 121 {
a2b08ee5
UD
122 const ElfW(Half) *vernum = (const ElfW(Half) *)
123 (l->l_addr + l->l_info[VERSYMIDX (DT_VERSYM)]->d_un.d_ptr);
124 ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)];
125 const struct r_found_version *version = &l->l_versions[ndx];
126
127 if (version->hash != 0)
128 {
129 value = _dl_lookup_versioned_symbol(strtab + sym->st_name,
130 &sym, scope, l->l_name,
4194bc66 131 version, DL_LOOKUP_NOPLT);
a2b08ee5
UD
132 break;
133 }
c84142e8 134 }
a2b08ee5
UD
135 case 0:
136 value = _dl_lookup_symbol (strtab + sym->st_name, &sym, scope,
4194bc66 137 l->l_name, DL_LOOKUP_NOPLT);
a2b08ee5
UD
138 }
139
140 /* Currently value contains the base load address of the object
141 that defines sym. Now add in the symbol offset. */
142 value = (sym ? value + sym->st_value : 0);
143
dfd2257a
UD
144 /* And now perhaps the relocation addend. */
145 value = elf_machine_plt_value (l, reloc, value);
650425ce 146
a2b08ee5
UD
147 /* Finally, fix up the plt itself. */
148 elf_machine_fixup_plt (l, reloc, rel_addr, value);
d66e34cd 149
ba79d61b
RM
150 *_dl_global_scope_end = NULL;
151
a2b08ee5 152 return value;
38334018 153}
d66e34cd 154
d66e34cd 155
3996f34b 156#ifndef PROF
8f2ece69 157
a2b08ee5 158static ElfW(Addr) __attribute__ ((unused))
3996f34b
UD
159profile_fixup (
160#ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
161 ELF_MACHINE_RUNTIME_FIXUP_ARGS,
162#endif
163 struct link_map *l, ElfW(Word) reloc_offset, ElfW(Addr) retaddr)
164{
165 void (*mcount_fct) (ElfW(Addr), ElfW(Addr)) = _dl_mcount;
ea7eb7e3 166 ElfW(Addr) *resultp;
a2b08ee5 167 ElfW(Addr) value;
3996f34b 168
ea7eb7e3
UD
169 /* This is the address in the array where we store the result of previous
170 relocations. */
171 resultp = &l->l_reloc_result[reloc_offset / sizeof (PLTREL)];
3996f34b 172
ea7eb7e3
UD
173 value = *resultp;
174 if (value == 0)
a2b08ee5 175 {
ea7eb7e3
UD
176 /* This is the first time we have to relocate this object. */
177 const ElfW(Sym) *const symtab
178 = (const ElfW(Sym) *) (l->l_addr + l->l_info[DT_SYMTAB]->d_un.d_ptr);
179 const char *strtab =
180 (const char *) (l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);
181
182 const PLTREL *const reloc
183 = (const void *) (l->l_addr + l->l_info[DT_JMPREL]->d_un.d_ptr +
184 reloc_offset);
185 const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
186
187 /* Set up the scope to find symbols referenced by this object. */
188 struct link_map **scope = _dl_object_relocation_scope (l);
189
190 /* Sanity check that we're really looking at a PLT relocation. */
191 assert (ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT);
192
193 /* Look up the target symbol. */
194 switch (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
195 {
196 default:
a2b08ee5 197 {
ea7eb7e3
UD
198 const ElfW(Half) *vernum = (const ElfW(Half) *)
199 (l->l_addr + l->l_info[VERSYMIDX (DT_VERSYM)]->d_un.d_ptr);
200 ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)];
201 const struct r_found_version *version = &l->l_versions[ndx];
202
203 if (version->hash != 0)
204 {
205 value = _dl_lookup_versioned_symbol(strtab + sym->st_name,
206 &sym, scope, l->l_name,
207 version,
4194bc66 208 DL_LOOKUP_NOPLT);
ea7eb7e3
UD
209 break;
210 }
a2b08ee5 211 }
ea7eb7e3
UD
212 case 0:
213 value = _dl_lookup_symbol (strtab + sym->st_name, &sym, scope,
4194bc66 214 l->l_name, DL_LOOKUP_NOPLT);
ea7eb7e3 215 }
a2b08ee5 216
ea7eb7e3
UD
217 /* Currently value contains the base load address of the object
218 that defines sym. Now add in the symbol offset. */
219 value = (sym ? value + sym->st_value : 0);
650425ce 220
ea7eb7e3
UD
221 /* And now perhaps the relocation addend. */
222 value = elf_machine_plt_value (l, reloc, value);
223
224 *_dl_global_scope_end = NULL;
225
226 /* Store the result for later runs. */
227 *resultp = value;
228 }
3996f34b 229
a2b08ee5 230 (*mcount_fct) (retaddr, value);
3996f34b 231
a2b08ee5 232 return value;
3996f34b 233}
a2b08ee5
UD
234
235#endif /* PROF */
3996f34b
UD
236
237
38334018
RM
238/* This macro is defined in dl-machine.h to define the entry point called
239 by the PLT. The `fixup' function above does the real work, but a little
240 more twiddling is needed to get the stack right and jump to the address
241 finally resolved. */
d66e34cd 242
38334018 243ELF_MACHINE_RUNTIME_TRAMPOLINE
This page took 0.079614 seconds and 5 git commands to generate.