]>
Commit | Line | Data |
---|---|---|
421f82e5 | 1 | /* Do relocations for ELF dynamic linking. |
688903eb | 2 | Copyright (C) 1995-2018 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 PE |
16 | License along with the GNU C Library; if not, see |
17 | <http://www.gnu.org/licenses/>. */ | |
421f82e5 RM |
18 | |
19 | /* This file may be included twice, to define both | |
20 | `elf_dynamic_do_rel' and `elf_dynamic_do_rela'. */ | |
21 | ||
22 | #ifdef DO_RELA | |
e453f6cd | 23 | # define elf_dynamic_do_Rel elf_dynamic_do_Rela |
1f2a1df3 UD |
24 | # define Rel Rela |
25 | # define elf_machine_rel elf_machine_rela | |
26 | # define elf_machine_rel_relative elf_machine_rela_relative | |
421f82e5 RM |
27 | #endif |
28 | ||
0e312a82 UD |
29 | #ifndef DO_ELF_MACHINE_REL_RELATIVE |
30 | # define DO_ELF_MACHINE_REL_RELATIVE(map, l_addr, relative) \ | |
31 | elf_machine_rel_relative (l_addr, relative, \ | |
32 | (void *) (l_addr + relative->r_offset)) | |
33 | #endif | |
34 | ||
421f82e5 | 35 | /* Perform the relocations in MAP on the running program image as specified |
f51d1dfd RM |
36 | by RELTAG, SZTAG. If LAZY is nonzero, this is the first pass on PLT |
37 | relocations; they should be set up to call _dl_runtime_resolve, rather | |
38 | than fully resolved now. */ | |
421f82e5 | 39 | |
7090d3ca | 40 | auto inline void __attribute__ ((always_inline)) |
e453f6cd | 41 | elf_dynamic_do_Rel (struct link_map *map, |
ca34d7a7 | 42 | ElfW(Addr) reladdr, ElfW(Addr) relsize, |
aac13307 UD |
43 | __typeof (((ElfW(Dyn) *) 0)->d_un.d_val) nrelative, |
44 | int lazy, int skip_ifunc) | |
421f82e5 | 45 | { |
f420344c UD |
46 | const ElfW(Rel) *r = (const void *) reladdr; |
47 | const ElfW(Rel) *end = (const void *) (reladdr + relsize); | |
c65c9d8b | 48 | ElfW(Addr) l_addr = map->l_addr; |
ad0f5cad UD |
49 | # if defined ELF_MACHINE_IRELATIVE && !defined RTLD_BOOTSTRAP |
50 | const ElfW(Rel) *r2 = NULL; | |
51 | const ElfW(Rel) *end2 = NULL; | |
52 | # endif | |
421f82e5 | 53 | |
32e6df36 | 54 | #if (!defined DO_RELA || !defined ELF_MACHINE_PLT_REL) && !defined RTLD_BOOTSTRAP |
43a80540 UD |
55 | /* We never bind lazily during ld.so bootstrap. Unfortunately gcc is |
56 | not clever enough to see through all the function calls to realize | |
57 | that. */ | |
a1a9d215 | 58 | if (lazy) |
b0cf070b UD |
59 | { |
60 | /* Doing lazy PLT relocations; they need very little info. */ | |
b0cf070b | 61 | for (; r < end; ++r) |
ad0f5cad UD |
62 | # ifdef ELF_MACHINE_IRELATIVE |
63 | if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_IRELATIVE) | |
64 | { | |
65 | if (r2 == NULL) | |
66 | r2 = r; | |
67 | end2 = r; | |
68 | } | |
69 | else | |
70 | # endif | |
71 | elf_machine_lazy_rel (map, l_addr, r, skip_ifunc); | |
72 | ||
73 | # ifdef ELF_MACHINE_IRELATIVE | |
74 | if (r2 != NULL) | |
75 | for (; r2 <= end2; ++r2) | |
76 | if (ELFW(R_TYPE) (r2->r_info) == ELF_MACHINE_IRELATIVE) | |
77 | elf_machine_lazy_rel (map, l_addr, r2, skip_ifunc); | |
78 | # endif | |
b0cf070b | 79 | } |
a1a9d215 | 80 | else |
43a80540 | 81 | #endif |
c84142e8 UD |
82 | { |
83 | const ElfW(Sym) *const symtab = | |
a42195db | 84 | (const void *) D_PTR (map, l_info[DT_SYMTAB]); |
95c78350 | 85 | const ElfW(Rel) *relative = r; |
e453f6cd | 86 | r += nrelative; |
ad427d6e UD |
87 | |
88 | #ifndef RTLD_BOOTSTRAP | |
89 | /* This is defined in rtld.c, but nowhere in the static libc.a; make | |
90 | the reference weak so static programs can still link. This | |
91 | declaration cannot be done when compiling rtld.c (i.e. #ifdef | |
92 | RTLD_BOOTSTRAP) because rtld.c contains the common defn for | |
93 | _dl_rtld_map, which is incompatible with a weak decl in the same | |
94 | file. */ | |
d6b5d570 UD |
95 | # ifndef SHARED |
96 | weak_extern (GL(dl_rtld_map)); | |
97 | # endif | |
98 | if (map != &GL(dl_rtld_map)) /* Already done in rtld itself. */ | |
6736e93b | 99 | # if !defined DO_RELA || defined ELF_MACHINE_REL_RELATIVE |
95c78350 UD |
100 | /* Rela platforms get the offset from r_addend and this must |
101 | be copied in the relocation address. Therefore we can skip | |
102 | the relative relocations only if this is for rel | |
6736e93b UD |
103 | relocations or rela relocations if they are computed as |
104 | memory_loc += l_addr... */ | |
95c78350 | 105 | if (l_addr != 0) |
32e6df36 UD |
106 | # else |
107 | /* ...or we know the object has been prelinked. */ | |
108 | if (l_addr != 0 || ! map->l_info[VALIDX(DT_GNU_PRELINKED)]) | |
95c78350 | 109 | # endif |
ad427d6e | 110 | #endif |
95c78350 | 111 | for (; relative < r; ++relative) |
0e312a82 | 112 | DO_ELF_MACHINE_REL_RELATIVE (map, l_addr, relative); |
c84142e8 | 113 | |
e0f41886 UD |
114 | #ifdef RTLD_BOOTSTRAP |
115 | /* The dynamic linker always uses versioning. */ | |
116 | assert (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL); | |
117 | #else | |
d705269e | 118 | if (map->l_info[VERSYMIDX (DT_VERSYM)]) |
e0f41886 | 119 | #endif |
c84142e8 UD |
120 | { |
121 | const ElfW(Half) *const version = | |
a42195db | 122 | (const void *) D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]); |
c84142e8 UD |
123 | |
124 | for (; r < end; ++r) | |
125 | { | |
ad0f5cad UD |
126 | #if defined ELF_MACHINE_IRELATIVE && !defined RTLD_BOOTSTRAP |
127 | if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_IRELATIVE) | |
128 | { | |
129 | if (r2 == NULL) | |
130 | r2 = r; | |
131 | end2 = r; | |
132 | continue; | |
133 | } | |
134 | #endif | |
135 | ||
0bc0e4dd | 136 | ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff; |
c84142e8 | 137 | elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], |
3996f34b | 138 | &map->l_versions[ndx], |
3a62d00d | 139 | (void *) (l_addr + r->r_offset), skip_ifunc); |
c84142e8 | 140 | } |
ad0f5cad UD |
141 | |
142 | #if defined ELF_MACHINE_IRELATIVE && !defined RTLD_BOOTSTRAP | |
143 | if (r2 != NULL) | |
144 | for (; r2 <= end2; ++r2) | |
145 | if (ELFW(R_TYPE) (r2->r_info) == ELF_MACHINE_IRELATIVE) | |
146 | { | |
147 | ElfW(Half) ndx | |
148 | = version[ELFW(R_SYM) (r2->r_info)] & 0x7fff; | |
149 | elf_machine_rel (map, r2, | |
150 | &symtab[ELFW(R_SYM) (r2->r_info)], | |
151 | &map->l_versions[ndx], | |
152 | (void *) (l_addr + r2->r_offset), | |
153 | skip_ifunc); | |
154 | } | |
155 | #endif | |
c84142e8 | 156 | } |
e0f41886 | 157 | #ifndef RTLD_BOOTSTRAP |
c84142e8 | 158 | else |
ad0f5cad UD |
159 | { |
160 | for (; r < end; ++r) | |
161 | # ifdef ELF_MACHINE_IRELATIVE | |
162 | if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_IRELATIVE) | |
163 | { | |
164 | if (r2 == NULL) | |
165 | r2 = r; | |
166 | end2 = r; | |
167 | } | |
168 | else | |
169 | # endif | |
170 | elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL, | |
171 | (void *) (l_addr + r->r_offset), skip_ifunc); | |
172 | ||
173 | # ifdef ELF_MACHINE_IRELATIVE | |
174 | if (r2 != NULL) | |
175 | for (; r2 <= end2; ++r2) | |
176 | if (ELFW(R_TYPE) (r2->r_info) == ELF_MACHINE_IRELATIVE) | |
177 | elf_machine_rel (map, r2, &symtab[ELFW(R_SYM) (r2->r_info)], | |
178 | NULL, (void *) (l_addr + r2->r_offset), | |
179 | skip_ifunc); | |
180 | # endif | |
181 | } | |
e0f41886 | 182 | #endif |
c84142e8 | 183 | } |
421f82e5 RM |
184 | } |
185 | ||
e453f6cd | 186 | #undef elf_dynamic_do_Rel |
266180eb | 187 | #undef Rel |
421f82e5 | 188 | #undef elf_machine_rel |
1f2a1df3 | 189 | #undef elf_machine_rel_relative |
0e312a82 | 190 | #undef DO_ELF_MACHINE_REL_RELATIVE |
e453f6cd | 191 | #undef DO_RELA |