Update.
[glibc.git] / elf / do-rel.h
blob5f07544369030c3b50ad20595228f2883ad5bcbb
1 /* Do relocations for ELF dynamic linking.
2 Copyright (C) 1995,96,97,98,99,2000,2001,2002 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
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. */
20 /* This file may be included twice, to define both
21 `elf_dynamic_do_rel' and `elf_dynamic_do_rela'. */
23 #ifdef DO_RELA
24 # define elf_dynamic_do_rel elf_dynamic_do_rela
25 # define RELCOUNT_IDX VERSYMIDX (DT_RELACOUNT)
26 # define Rel Rela
27 # define elf_machine_rel elf_machine_rela
28 # define elf_machine_rel_relative elf_machine_rela_relative
29 #else
30 # define RELCOUNT_IDX VERSYMIDX (DT_RELCOUNT)
31 #endif
33 #ifndef VERSYMIDX
34 # define VERSYMIDX(sym) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (sym))
35 #endif
36 #ifndef VALIDX
37 # define VALIDX(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM \
38 + DT_EXTRANUM + DT_VALTAGIDX (tag))
39 #endif
41 /* Perform the relocations in MAP on the running program image as specified
42 by RELTAG, SZTAG. If LAZY is nonzero, this is the first pass on PLT
43 relocations; they should be set up to call _dl_runtime_resolve, rather
44 than fully resolved now. */
46 static inline void
47 elf_dynamic_do_rel (struct link_map *map,
48 ElfW(Addr) reladdr, ElfW(Addr) relsize,
49 int lazy)
51 const ElfW(Rel) *r = (const void *) reladdr;
52 const ElfW(Rel) *end = (const void *) (reladdr + relsize);
53 ElfW(Addr) l_addr = map->l_addr;
55 #if (!defined DO_RELA || !defined ELF_MACHINE_PLT_REL) && !defined RTLD_BOOTSTRAP
56 /* We never bind lazily during ld.so bootstrap. Unfortunately gcc is
57 not clever enough to see through all the function calls to realize
58 that. */
59 if (lazy)
61 /* Doing lazy PLT relocations; they need very little info. */
62 for (; r < end; ++r)
63 elf_machine_lazy_rel (map, l_addr, r);
65 else
66 #endif
68 const ElfW(Sym) *const symtab =
69 (const void *) D_PTR (map, l_info[DT_SYMTAB]);
70 ElfW(Word) nrelative = (map->l_info[RELCOUNT_IDX] == NULL
71 ? 0 : map->l_info[RELCOUNT_IDX]->d_un.d_val);
72 const ElfW(Rel) *relative = r;
73 r = MIN (r + nrelative, end);
75 #ifndef RTLD_BOOTSTRAP
76 /* This is defined in rtld.c, but nowhere in the static libc.a; make
77 the reference weak so static programs can still link. This
78 declaration cannot be done when compiling rtld.c (i.e. #ifdef
79 RTLD_BOOTSTRAP) because rtld.c contains the common defn for
80 _dl_rtld_map, which is incompatible with a weak decl in the same
81 file. */
82 # ifndef SHARED
83 weak_extern (GL(dl_rtld_map));
84 # endif
85 if (map != &GL(dl_rtld_map)) /* Already done in rtld itself. */
86 # ifndef DO_RELA
87 /* Rela platforms get the offset from r_addend and this must
88 be copied in the relocation address. Therefore we can skip
89 the relative relocations only if this is for rel
90 relocations... */
91 if (l_addr != 0)
92 # else
93 /* ...or we know the object has been prelinked. */
94 if (l_addr != 0 || ! map->l_info[VALIDX(DT_GNU_PRELINKED)])
95 # endif
96 #endif
97 for (; relative < r; ++relative)
98 elf_machine_rel_relative (l_addr, relative,
99 (void *) (l_addr + relative->r_offset));
101 #ifdef RTLD_BOOTSTRAP
102 /* The dynamic linker always uses versioning. */
103 assert (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL);
104 #else
105 if (map->l_info[VERSYMIDX (DT_VERSYM)])
106 #endif
108 const ElfW(Half) *const version =
109 (const void *) D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
111 for (; r < end; ++r)
113 ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)];
114 elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)],
115 &map->l_versions[ndx],
116 (void *) (l_addr + r->r_offset));
119 #ifndef RTLD_BOOTSTRAP
120 else
121 for (; r < end; ++r)
122 elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL,
123 (void *) (l_addr + r->r_offset));
124 #endif
128 #undef elf_dynamic_do_rel
129 #undef Rel
130 #undef elf_machine_rel
131 #undef elf_machine_rel_relative
132 #undef RELCOUNT_IDX