]> git.ipfire.org Git - thirdparty/glibc.git/blame - elf/do-rel.h
install.texi: Build was tested with binutils 2.41 (just released)
[thirdparty/glibc.git] / elf / do-rel.h
CommitLineData
421f82e5 1/* Do relocations for ELF dynamic linking.
6d7e8eda 2 Copyright (C) 1995-2023 Free Software Foundation, Inc.
afd4eb37 3 This file is part of the GNU C Library.
421f82e5 4
afd4eb37 5 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
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.
421f82e5 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
41bdb6e2 13 Lesser General Public License for more details.
421f82e5 14
41bdb6e2 15 You should have received a copy of the GNU Lesser General Public
59ba27a6 16 License along with the GNU C Library; if not, see
5a82c748 17 <https://www.gnu.org/licenses/>. */
421f82e5 18
32612615
AZ
19#include <ldsodefs.h>
20
421f82e5
RM
21/* This file may be included twice, to define both
22 `elf_dynamic_do_rel' and `elf_dynamic_do_rela'. */
23
24#ifdef DO_RELA
e453f6cd 25# define elf_dynamic_do_Rel elf_dynamic_do_Rela
1f2a1df3
UD
26# define Rel Rela
27# define elf_machine_rel elf_machine_rela
28# define elf_machine_rel_relative elf_machine_rela_relative
421f82e5
RM
29#endif
30
0e312a82
UD
31#ifndef DO_ELF_MACHINE_REL_RELATIVE
32# define DO_ELF_MACHINE_REL_RELATIVE(map, l_addr, relative) \
33 elf_machine_rel_relative (l_addr, relative, \
34 (void *) (l_addr + relative->r_offset))
35#endif
36
421f82e5 37/* Perform the relocations in MAP on the running program image as specified
f51d1dfd
RM
38 by RELTAG, SZTAG. If LAZY is nonzero, this is the first pass on PLT
39 relocations; they should be set up to call _dl_runtime_resolve, rather
40 than fully resolved now. */
421f82e5 41
490e6c62
FS
42static inline void __attribute__ ((always_inline))
43elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[],
ca34d7a7 44 ElfW(Addr) reladdr, ElfW(Addr) relsize,
aac13307
UD
45 __typeof (((ElfW(Dyn) *) 0)->d_un.d_val) nrelative,
46 int lazy, int skip_ifunc)
421f82e5 47{
84e02af1
FS
48 const ElfW(Rel) *relative = (const void *) reladdr;
49 const ElfW(Rel) *r = relative + nrelative;
f420344c 50 const ElfW(Rel) *end = (const void *) (reladdr + relsize);
c65c9d8b 51 ElfW(Addr) l_addr = map->l_addr;
84e02af1
FS
52 const ElfW(Sym) *const symtab
53 = (const void *) D_PTR (map, l_info[DT_SYMTAB]);
54
55#ifdef RTLD_BOOTSTRAP
56 for (; relative < r; ++relative)
57 DO_ELF_MACHINE_REL_RELATIVE (map, l_addr, relative);
58
59 const ElfW (Half) *const version
60 = (const void *) D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
61 for (; r < end; ++r)
62 {
63 ElfW (Half) ndx = version[ELFW (R_SYM) (r->r_info)] & 0x7fff;
64 const ElfW (Sym) *sym = &symtab[ELFW (R_SYM) (r->r_info)];
65 void *const r_addr_arg = (void *) (l_addr + r->r_offset);
66 const struct r_found_version *rversion = &map->l_versions[ndx];
67
68 elf_machine_rel (map, scope, r, sym, rversion, r_addr_arg, skip_ifunc);
69 }
70#else /* !RTLD_BOOTSTRAP */
71# if defined ELF_MACHINE_IRELATIVE
ad0f5cad
UD
72 const ElfW(Rel) *r2 = NULL;
73 const ElfW(Rel) *end2 = NULL;
74# endif
421f82e5 75
84e02af1 76#if !defined DO_RELA || !defined ELF_MACHINE_PLT_REL
43a80540
UD
77 /* We never bind lazily during ld.so bootstrap. Unfortunately gcc is
78 not clever enough to see through all the function calls to realize
79 that. */
a1a9d215 80 if (lazy)
b0cf070b
UD
81 {
82 /* Doing lazy PLT relocations; they need very little info. */
b0cf070b 83 for (; r < end; ++r)
ad0f5cad
UD
84# ifdef ELF_MACHINE_IRELATIVE
85 if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_IRELATIVE)
86 {
87 if (r2 == NULL)
88 r2 = r;
89 end2 = r;
90 }
91 else
92# endif
490e6c62 93 elf_machine_lazy_rel (map, scope, l_addr, r, skip_ifunc);
ad0f5cad
UD
94
95# ifdef ELF_MACHINE_IRELATIVE
96 if (r2 != NULL)
97 for (; r2 <= end2; ++r2)
98 if (ELFW(R_TYPE) (r2->r_info) == ELF_MACHINE_IRELATIVE)
490e6c62 99 elf_machine_lazy_rel (map, scope, l_addr, r2, skip_ifunc);
ad0f5cad 100# endif
b0cf070b 101 }
a1a9d215 102 else
43a80540 103#endif
c84142e8 104 {
ad427d6e
UD
105 /* This is defined in rtld.c, but nowhere in the static libc.a; make
106 the reference weak so static programs can still link. This
107 declaration cannot be done when compiling rtld.c (i.e. #ifdef
108 RTLD_BOOTSTRAP) because rtld.c contains the common defn for
109 _dl_rtld_map, which is incompatible with a weak decl in the same
110 file. */
d6b5d570
UD
111# ifndef SHARED
112 weak_extern (GL(dl_rtld_map));
113# endif
114 if (map != &GL(dl_rtld_map)) /* Already done in rtld itself. */
6736e93b 115# if !defined DO_RELA || defined ELF_MACHINE_REL_RELATIVE
95c78350
UD
116 /* Rela platforms get the offset from r_addend and this must
117 be copied in the relocation address. Therefore we can skip
118 the relative relocations only if this is for rel
6736e93b
UD
119 relocations or rela relocations if they are computed as
120 memory_loc += l_addr... */
95c78350
UD
121 if (l_addr != 0)
122# endif
95c78350 123 for (; relative < r; ++relative)
0e312a82 124 DO_ELF_MACHINE_REL_RELATIVE (map, l_addr, relative);
c84142e8 125
d705269e 126 if (map->l_info[VERSYMIDX (DT_VERSYM)])
c84142e8
UD
127 {
128 const ElfW(Half) *const version =
a42195db 129 (const void *) D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
c84142e8
UD
130
131 for (; r < end; ++r)
132 {
32612615
AZ
133 ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff;
134 const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (r->r_info)];
135 void *const r_addr_arg = (void *) (l_addr + r->r_offset);
136 const struct r_found_version *rversion = &map->l_versions[ndx];
84e02af1 137#if defined ELF_MACHINE_IRELATIVE
ad0f5cad
UD
138 if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_IRELATIVE)
139 {
140 if (r2 == NULL)
141 r2 = r;
142 end2 = r;
143 continue;
144 }
145#endif
146
32612615
AZ
147 elf_machine_rel (map, scope, r, sym, rversion, r_addr_arg,
148 skip_ifunc);
84e02af1 149#if defined SHARED
32612615
AZ
150 if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_JMP_SLOT
151 && GLRO(dl_naudit) > 0)
152 {
153 struct link_map *sym_map
154 = RESOLVE_MAP (map, scope, &sym, rversion,
155 ELF_MACHINE_JMP_SLOT);
156 if (sym != NULL)
dddc8858
AZ
157 _dl_audit_symbind (map, NULL, r, sym, r_addr_arg, sym_map,
158 false);
32612615
AZ
159 }
160#endif
c84142e8 161 }
ad0f5cad 162
84e02af1 163#if defined ELF_MACHINE_IRELATIVE
ad0f5cad
UD
164 if (r2 != NULL)
165 for (; r2 <= end2; ++r2)
166 if (ELFW(R_TYPE) (r2->r_info) == ELF_MACHINE_IRELATIVE)
167 {
168 ElfW(Half) ndx
169 = version[ELFW(R_SYM) (r2->r_info)] & 0x7fff;
490e6c62 170 elf_machine_rel (map, scope, r2,
ad0f5cad
UD
171 &symtab[ELFW(R_SYM) (r2->r_info)],
172 &map->l_versions[ndx],
173 (void *) (l_addr + r2->r_offset),
174 skip_ifunc);
175 }
176#endif
c84142e8
UD
177 }
178 else
ad0f5cad
UD
179 {
180 for (; r < end; ++r)
32612615
AZ
181 {
182 const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (r->r_info)];
183 void *const r_addr_arg = (void *) (l_addr + r->r_offset);
ad0f5cad 184# ifdef ELF_MACHINE_IRELATIVE
32612615
AZ
185 if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_IRELATIVE)
186 {
187 if (r2 == NULL)
188 r2 = r;
189 end2 = r;
190 continue;
191 }
ad0f5cad 192# endif
32612615
AZ
193 elf_machine_rel (map, scope, r, sym, NULL, r_addr_arg,
194 skip_ifunc);
84e02af1 195# if defined SHARED
32612615
AZ
196 if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_JMP_SLOT
197 && GLRO(dl_naudit) > 0)
198 {
199 struct link_map *sym_map
200 = RESOLVE_MAP (map, scope, &sym,
201 (struct r_found_version *) NULL,
202 ELF_MACHINE_JMP_SLOT);
203 if (sym != NULL)
dddc8858
AZ
204 _dl_audit_symbind (map, NULL, r, sym,r_addr_arg, sym_map,
205 false);
32612615
AZ
206 }
207# endif
208 }
ad0f5cad
UD
209
210# ifdef ELF_MACHINE_IRELATIVE
211 if (r2 != NULL)
212 for (; r2 <= end2; ++r2)
213 if (ELFW(R_TYPE) (r2->r_info) == ELF_MACHINE_IRELATIVE)
490e6c62 214 elf_machine_rel (map, scope, r2, &symtab[ELFW(R_SYM) (r2->r_info)],
ad0f5cad
UD
215 NULL, (void *) (l_addr + r2->r_offset),
216 skip_ifunc);
217# endif
218 }
c84142e8 219 }
84e02af1 220#endif /* !RTLD_BOOTSTRAP */
421f82e5
RM
221}
222
e453f6cd 223#undef elf_dynamic_do_Rel
266180eb 224#undef Rel
421f82e5 225#undef elf_machine_rel
1f2a1df3 226#undef elf_machine_rel_relative
0e312a82 227#undef DO_ELF_MACHINE_REL_RELATIVE
e453f6cd 228#undef DO_RELA