]> git.ipfire.org Git - thirdparty/glibc.git/blame - elf/dynamic-link.h
test-container: Fix "unused code" warnings on HURD
[thirdparty/glibc.git] / elf / dynamic-link.h
CommitLineData
d66e34cd 1/* Inline functions for dynamic linking.
581c785b 2 Copyright (C) 1995-2022 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
d7dd4413 76 We are guarenteed 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 \
ca34d7a7
UD
87 if ((map)->l_info[DT_##RELOC]) \
88 { \
32e6df36
UD
89 ranges[0].start = D_PTR ((map), l_info[DT_##RELOC]); \
90 ranges[0].size = (map)->l_info[DT_##RELOC##SZ]->d_un.d_val; \
e453f6cd
UD
91 if (map->l_info[VERSYMIDX (DT_##RELOC##COUNT)] != NULL) \
92 ranges[0].nrelative \
585d9c18 93 = map->l_info[VERSYMIDX (DT_##RELOC##COUNT)]->d_un.d_val; \
ca34d7a7 94 } \
f420344c
UD
95 if ((map)->l_info[DT_PLTREL] \
96 && (!test_rel || (map)->l_info[DT_PLTREL]->d_un.d_val == DT_##RELOC)) \
ca34d7a7 97 { \
a42195db 98 ElfW(Addr) start = D_PTR ((map), l_info[DT_JMPREL]); \
d7dd4413 99 ElfW(Addr) size = (map)->l_info[DT_PLTRELSZ]->d_un.d_val; \
052b6a6c 100 \
d7dd4413
DM
101 if (ranges[0].start + ranges[0].size == (start + size)) \
102 ranges[0].size -= size; \
f64f4ce0
AZ
103 if (!(do_lazy) \
104 && (ranges[0].start + ranges[0].size) == start) \
052b6a6c 105 { \
fa19d5c4
PJ
106 /* Combine processing the sections. */ \
107 ranges[0].size += size; \
052b6a6c
UD
108 } \
109 else \
e0f41886 110 { \
fa19d5c4
PJ
111 ranges[1].start = start; \
112 ranges[1].size = size; \
113 ranges[1].lazy = (do_lazy); \
e0f41886 114 } \
ca34d7a7 115 } \
052b6a6c 116 \
f64f4ce0
AZ
117 for (int ranges_index = 0; ranges_index < 2; ++ranges_index) \
118 elf_dynamic_do_##reloc ((map), scope, \
119 ranges[ranges_index].start, \
120 ranges[ranges_index].size, \
121 ranges[ranges_index].nrelative, \
122 ranges[ranges_index].lazy, \
123 skip_ifunc); \
ca34d7a7 124 } while (0)
f420344c
UD
125
126# if ELF_MACHINE_NO_REL || ELF_MACHINE_NO_RELA
127# define _ELF_CHECK_REL 0
128# else
129# define _ELF_CHECK_REL 1
130# endif
131
132# if ! ELF_MACHINE_NO_REL
133# include "do-rel.h"
490e6c62
FS
134# define ELF_DYNAMIC_DO_REL(map, scope, lazy, skip_ifunc) \
135 _ELF_DYNAMIC_DO_RELOC (REL, Rel, map, scope, lazy, skip_ifunc, _ELF_CHECK_REL)
f420344c 136# else
490e6c62 137# define ELF_DYNAMIC_DO_REL(map, scope, lazy, skip_ifunc) /* Nothing to do. */
f420344c
UD
138# endif
139
140# if ! ELF_MACHINE_NO_RELA
141# define DO_RELA
142# include "do-rel.h"
490e6c62
FS
143# define ELF_DYNAMIC_DO_RELA(map, scope, lazy, skip_ifunc) \
144 _ELF_DYNAMIC_DO_RELOC (RELA, Rela, map, scope, lazy, skip_ifunc, _ELF_CHECK_REL)
f420344c 145# else
490e6c62 146# define ELF_DYNAMIC_DO_RELA(map, scope, lazy, skip_ifunc) /* Nothing to do. */
f420344c 147# endif
421f82e5
RM
148
149/* This can't just be an inline function because GCC is too dumb
150 to inline functions containing inlines themselves. */
490e6c62 151# define ELF_DYNAMIC_RELOCATE(map, scope, lazy, consider_profile, skip_ifunc) \
3996f34b 152 do { \
490e6c62 153 int edr_lazy = elf_machine_runtime_setup ((map), (scope), (lazy), \
c0fb8a56 154 (consider_profile)); \
490e6c62
FS
155 ELF_DYNAMIC_DO_REL ((map), (scope), edr_lazy, skip_ifunc); \
156 ELF_DYNAMIC_DO_RELA ((map), (scope), edr_lazy, skip_ifunc); \
0501d603 157 } while (0)
f51d1dfd
RM
158
159#endif