]> git.ipfire.org Git - thirdparty/glibc.git/blame - elf/dynamic-link.h
Define ISO 639-3 "ltg" (Latgalian) and add ltg_LV locale
[thirdparty/glibc.git] / elf / dynamic-link.h
CommitLineData
d66e34cd 1/* Inline functions for dynamic linking.
dff8da6b 2 Copyright (C) 1995-2024 Free Software Foundation, Inc.
afd4eb37
UD
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
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.
afd4eb37
UD
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
41bdb6e2 13 Lesser General Public License for more details.
afd4eb37 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/>. */
d66e34cd 18
d6d89608 19#include <dl-machine.h>
d66e34cd 20#include <elf.h>
d66e34cd 21
9dcafc55 22#ifdef RESOLVE_MAP
87d254a7
AO
23/* We pass reloc_addr as a pointer to void, as opposed to a pointer to
24 ElfW(Addr), because not all architectures can assume that the
25 relocated address is properly aligned, whereas the compiler is
26 entitled to assume that a pointer to a type is properly aligned for
27 the type. Even if we cast the pointer back to some other type with
28 less strict alignment requirements, the compiler might still
29 remember that the pointer was originally more aligned, thereby
30 optimizing away alignment tests or using word instructions for
31 copying memory, breaking the very code written to handle the
32 unaligned cases. */
9cfe5381 33# if ! ELF_MACHINE_NO_REL
490e6c62
FS
34static inline void __attribute__((always_inline))
35elf_machine_rel (struct link_map *map, struct r_scope_elem *scope[],
36 const ElfW(Rel) *reloc, const ElfW(Sym) *sym,
37 const struct r_found_version *version,
3a62d00d 38 void *const reloc_addr, int skip_ifunc);
490e6c62 39static inline void __attribute__((always_inline))
9cfe5381
RM
40elf_machine_rel_relative (ElfW(Addr) l_addr, const ElfW(Rel) *reloc,
41 void *const reloc_addr);
42# endif
43# if ! ELF_MACHINE_NO_RELA
490e6c62
FS
44static inline void __attribute__((always_inline))
45elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
46 const ElfW(Rela) *reloc, const ElfW(Sym) *sym,
47 const struct r_found_version *version, void *const reloc_addr,
48 int skip_ifunc);
49static inline void __attribute__((always_inline))
567678b6 50elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
87d254a7 51 void *const reloc_addr);
9cfe5381 52# endif
567678b6 53# if ELF_MACHINE_NO_RELA || defined ELF_MACHINE_PLT_REL
490e6c62
FS
54static inline void __attribute__((always_inline))
55elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
3a62d00d
AS
56 ElfW(Addr) l_addr, const ElfW(Rel) *reloc,
57 int skip_ifunc);
567678b6 58# else
490e6c62
FS
59static inline void __attribute__((always_inline))
60elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
3a62d00d
AS
61 ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
62 int skip_ifunc);
567678b6
UD
63# endif
64#endif
65
9dcafc55 66#ifdef RESOLVE_MAP
f51d1dfd 67
421f82e5
RM
68/* Get the definitions of `elf_dynamic_do_rel' and `elf_dynamic_do_rela'.
69 These functions are almost identical, so we use cpp magic to avoid
70 duplicating their code. It cannot be done in a more general function
71 because we must be able to completely inline. */
72
f420344c 73/* On some machines, notably SPARC, DT_REL* includes DT_JMPREL in its
ca34d7a7 74 range. Note that according to the ELF spec, this is completely legal!
ca34d7a7 75
630da022 76 We are guaranteed that we have one of three situations. Either DT_JMPREL
993eb054 77 comes immediately after DT_REL*, or there is overlap and DT_JMPREL
d7dd4413
DM
78 consumes precisely the very end of the DT_REL*, or DT_JMPREL and DT_REL*
79 are completely separate and there is a gap between them. */
993eb054 80
490e6c62 81# define _ELF_DYNAMIC_DO_RELOC(RELOC, reloc, map, scope, do_lazy, skip_ifunc, test_rel) \
ca34d7a7 82 do { \
aac13307
UD
83 struct { ElfW(Addr) start, size; \
84 __typeof (((ElfW(Dyn) *) 0)->d_un.d_val) nrelative; int lazy; } \
e453f6cd 85 ranges[2] = { { 0, 0, 0, 0 }, { 0, 0, 0, 0 } }; \
052b6a6c 86 \
60196d2e
L
87 /* With DT_RELR, DT_RELA/DT_REL can have zero value. */ \
88 if ((map)->l_info[DT_##RELOC] != NULL \
89 && (map)->l_info[DT_##RELOC]->d_un.d_ptr != 0) \
ca34d7a7 90 { \
32e6df36
UD
91 ranges[0].start = D_PTR ((map), l_info[DT_##RELOC]); \
92 ranges[0].size = (map)->l_info[DT_##RELOC##SZ]->d_un.d_val; \
e453f6cd
UD
93 if (map->l_info[VERSYMIDX (DT_##RELOC##COUNT)] != NULL) \
94 ranges[0].nrelative \
585d9c18 95 = map->l_info[VERSYMIDX (DT_##RELOC##COUNT)]->d_un.d_val; \
ca34d7a7 96 } \
f420344c
UD
97 if ((map)->l_info[DT_PLTREL] \
98 && (!test_rel || (map)->l_info[DT_PLTREL]->d_un.d_val == DT_##RELOC)) \
ca34d7a7 99 { \
a42195db 100 ElfW(Addr) start = D_PTR ((map), l_info[DT_JMPREL]); \
d7dd4413 101 ElfW(Addr) size = (map)->l_info[DT_PLTRELSZ]->d_un.d_val; \
052b6a6c 102 \
60196d2e
L
103 if (ranges[0].start == 0) \
104 ranges[0].start = start; \
d7dd4413
DM
105 if (ranges[0].start + ranges[0].size == (start + size)) \
106 ranges[0].size -= size; \
f64f4ce0
AZ
107 if (!(do_lazy) \
108 && (ranges[0].start + ranges[0].size) == start) \
052b6a6c 109 { \
fa19d5c4
PJ
110 /* Combine processing the sections. */ \
111 ranges[0].size += size; \
052b6a6c
UD
112 } \
113 else \
e0f41886 114 { \
fa19d5c4
PJ
115 ranges[1].start = start; \
116 ranges[1].size = size; \
117 ranges[1].lazy = (do_lazy); \
e0f41886 118 } \
ca34d7a7 119 } \
052b6a6c 120 \
f64f4ce0
AZ
121 for (int ranges_index = 0; ranges_index < 2; ++ranges_index) \
122 elf_dynamic_do_##reloc ((map), scope, \
123 ranges[ranges_index].start, \
124 ranges[ranges_index].size, \
125 ranges[ranges_index].nrelative, \
126 ranges[ranges_index].lazy, \
127 skip_ifunc); \
ca34d7a7 128 } while (0)
f420344c
UD
129
130# if ELF_MACHINE_NO_REL || ELF_MACHINE_NO_RELA
131# define _ELF_CHECK_REL 0
132# else
133# define _ELF_CHECK_REL 1
134# endif
135
136# if ! ELF_MACHINE_NO_REL
137# include "do-rel.h"
490e6c62
FS
138# define ELF_DYNAMIC_DO_REL(map, scope, lazy, skip_ifunc) \
139 _ELF_DYNAMIC_DO_RELOC (REL, Rel, map, scope, lazy, skip_ifunc, _ELF_CHECK_REL)
f420344c 140# else
490e6c62 141# define ELF_DYNAMIC_DO_REL(map, scope, lazy, skip_ifunc) /* Nothing to do. */
f420344c
UD
142# endif
143
144# if ! ELF_MACHINE_NO_RELA
145# define DO_RELA
146# include "do-rel.h"
490e6c62
FS
147# define ELF_DYNAMIC_DO_RELA(map, scope, lazy, skip_ifunc) \
148 _ELF_DYNAMIC_DO_RELOC (RELA, Rela, map, scope, lazy, skip_ifunc, _ELF_CHECK_REL)
f420344c 149# else
490e6c62 150# define ELF_DYNAMIC_DO_RELA(map, scope, lazy, skip_ifunc) /* Nothing to do. */
f420344c 151# endif
421f82e5 152
e895cff5
FS
153# define ELF_DYNAMIC_DO_RELR(map) \
154 do { \
155 ElfW(Addr) l_addr = (map)->l_addr, *where = 0; \
156 const ElfW(Relr) *r, *end; \
157 if ((map)->l_info[DT_RELR] == NULL) \
158 break; \
159 r = (const ElfW(Relr) *)D_PTR((map), l_info[DT_RELR]); \
160 end = (const ElfW(Relr) *)((const char *)r + \
161 (map)->l_info[DT_RELRSZ]->d_un.d_val); \
162 for (; r < end; r++) \
163 { \
164 ElfW(Relr) entry = *r; \
165 if ((entry & 1) == 0) \
166 { \
167 where = (ElfW(Addr) *)(l_addr + entry); \
168 *where++ += l_addr; \
169 } \
170 else \
171 { \
172 for (long int i = 0; (entry >>= 1) != 0; i++) \
173 if ((entry & 1) != 0) \
174 where[i] += l_addr; \
175 where += CHAR_BIT * sizeof(ElfW(Relr)) - 1; \
176 } \
177 } \
178 } while (0);
179
848746e8
L
180# ifndef ELF_DYNAMIC_AFTER_RELOC
181# define ELF_DYNAMIC_AFTER_RELOC(map, lazy)
182# endif
183
421f82e5
RM
184/* This can't just be an inline function because GCC is too dumb
185 to inline functions containing inlines themselves. */
e895cff5
FS
186# ifdef RTLD_BOOTSTRAP
187# define DO_RTLD_BOOTSTRAP 1
188# else
189# define DO_RTLD_BOOTSTRAP 0
190# endif
490e6c62 191# define ELF_DYNAMIC_RELOCATE(map, scope, lazy, consider_profile, skip_ifunc) \
3996f34b 192 do { \
490e6c62 193 int edr_lazy = elf_machine_runtime_setup ((map), (scope), (lazy), \
c0fb8a56 194 (consider_profile)); \
e895cff5
FS
195 if (((map) != &GL(dl_rtld_map) || DO_RTLD_BOOTSTRAP)) \
196 ELF_DYNAMIC_DO_RELR (map); \
490e6c62
FS
197 ELF_DYNAMIC_DO_REL ((map), (scope), edr_lazy, skip_ifunc); \
198 ELF_DYNAMIC_DO_RELA ((map), (scope), edr_lazy, skip_ifunc); \
848746e8 199 ELF_DYNAMIC_AFTER_RELOC ((map), (edr_lazy)); \
0501d603 200 } while (0)
f51d1dfd
RM
201
202#endif