| @@ -1,308 +1,307 @@ | | | @@ -1,308 +1,307 @@ |
1 | /* $NetBSD: mdreloc.c,v 1.32 2008/07/24 04:39:26 matt Exp $ */ | | 1 | /* $NetBSD: mdreloc.c,v 1.33 2009/03/15 23:53:03 lukem Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2001 Wasabi Systems, Inc. | | 4 | * Copyright (c) 2001 Wasabi Systems, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Written by Frank van der Linden for Wasabi Systems, Inc. | | 7 | * Written by Frank van der Linden for Wasabi Systems, Inc. |
8 | * | | 8 | * |
9 | * Redistribution and use in source and binary forms, with or without | | 9 | * Redistribution and use in source and binary forms, with or without |
10 | * modification, are permitted provided that the following conditions | | 10 | * modification, are permitted provided that the following conditions |
11 | * are met: | | 11 | * are met: |
12 | * 1. Redistributions of source code must retain the above copyright | | 12 | * 1. Redistributions of source code must retain the above copyright |
13 | * notice, this list of conditions and the following disclaimer. | | 13 | * notice, this list of conditions and the following disclaimer. |
14 | * 2. Redistributions in binary form must reproduce the above copyright | | 14 | * 2. Redistributions in binary form must reproduce the above copyright |
15 | * notice, this list of conditions and the following disclaimer in the | | 15 | * notice, this list of conditions and the following disclaimer in the |
16 | * documentation and/or other materials provided with the distribution. | | 16 | * documentation and/or other materials provided with the distribution. |
17 | * 3. All advertising materials mentioning features or use of this software | | 17 | * 3. All advertising materials mentioning features or use of this software |
18 | * must display the following acknowledgement: | | 18 | * must display the following acknowledgement: |
19 | * This product includes software developed for the NetBSD Project by | | 19 | * This product includes software developed for the NetBSD Project by |
20 | * Wasabi Systems, Inc. | | 20 | * Wasabi Systems, Inc. |
21 | * 4. The name of Wasabi Systems, Inc. may not be used to endorse | | 21 | * 4. The name of Wasabi Systems, Inc. may not be used to endorse |
22 | * or promote products derived from this software without specific prior | | 22 | * or promote products derived from this software without specific prior |
23 | * written permission. | | 23 | * written permission. |
24 | * | | 24 | * |
25 | * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND | | 25 | * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND |
26 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 26 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
27 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 27 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
28 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC | | 28 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC |
29 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 29 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
30 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 30 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
31 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 31 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
32 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 32 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
33 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 33 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
34 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 34 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
35 | * POSSIBILITY OF SUCH DAMAGE. | | 35 | * POSSIBILITY OF SUCH DAMAGE. |
36 | */ | | 36 | */ |
37 | | | 37 | |
38 | /* | | 38 | /* |
39 | * Copyright 1996 John D. Polstra. | | 39 | * Copyright 1996 John D. Polstra. |
40 | * Copyright 1996 Matt Thomas <matt@3am-software.com> | | 40 | * Copyright 1996 Matt Thomas <matt@3am-software.com> |
41 | * All rights reserved. | | 41 | * All rights reserved. |
42 | * | | 42 | * |
43 | * Redistribution and use in source and binary forms, with or without | | 43 | * Redistribution and use in source and binary forms, with or without |
44 | * modification, are permitted provided that the following conditions | | 44 | * modification, are permitted provided that the following conditions |
45 | * are met: | | 45 | * are met: |
46 | * 1. Redistributions of source code must retain the above copyright | | 46 | * 1. Redistributions of source code must retain the above copyright |
47 | * notice, this list of conditions and the following disclaimer. | | 47 | * notice, this list of conditions and the following disclaimer. |
48 | * 2. Redistributions in binary form must reproduce the above copyright | | 48 | * 2. Redistributions in binary form must reproduce the above copyright |
49 | * notice, this list of conditions and the following disclaimer in the | | 49 | * notice, this list of conditions and the following disclaimer in the |
50 | * documentation and/or other materials provided with the distribution. | | 50 | * documentation and/or other materials provided with the distribution. |
51 | * 3. All advertising materials mentioning features or use of this software | | 51 | * 3. All advertising materials mentioning features or use of this software |
52 | * must display the following acknowledgement: | | 52 | * must display the following acknowledgement: |
53 | * This product includes software developed by John Polstra. | | 53 | * This product includes software developed by John Polstra. |
54 | * 4. The name of the author may not be used to endorse or promote products | | 54 | * 4. The name of the author may not be used to endorse or promote products |
55 | * derived from this software without specific prior written permission. | | 55 | * derived from this software without specific prior written permission. |
56 | * | | 56 | * |
57 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | | 57 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
58 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | | 58 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
59 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | | 59 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
60 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | | 60 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
61 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | | 61 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
62 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | | 62 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
63 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | | 63 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
64 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | | 64 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
65 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | | 65 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
66 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | | 66 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
67 | */ | | 67 | */ |
68 | | | 68 | |
69 | #include <sys/cdefs.h> | | 69 | #include <sys/cdefs.h> |
70 | #ifndef lint | | 70 | #ifndef lint |
71 | __RCSID("$NetBSD: mdreloc.c,v 1.32 2008/07/24 04:39:26 matt Exp $"); | | 71 | __RCSID("$NetBSD: mdreloc.c,v 1.33 2009/03/15 23:53:03 lukem Exp $"); |
72 | #endif /* not lint */ | | 72 | #endif /* not lint */ |
73 | | | 73 | |
74 | #include <sys/types.h> | | 74 | #include <sys/types.h> |
75 | #include <sys/mman.h> | | 75 | #include <sys/mman.h> |
76 | #include <err.h> | | | |
77 | #include <errno.h> | | 76 | #include <errno.h> |
78 | #include <fcntl.h> | | 77 | #include <fcntl.h> |
79 | #include <stdarg.h> | | 78 | #include <stdarg.h> |
80 | #include <stdio.h> | | 79 | #include <stdio.h> |
81 | #include <stdlib.h> | | 80 | #include <stdlib.h> |
82 | #include <string.h> | | 81 | #include <string.h> |
83 | #include <unistd.h> | | 82 | #include <unistd.h> |
84 | #include <elf.h> | | 83 | #include <elf.h> |
85 | | | 84 | |
86 | #include "debug.h" | | 85 | #include "debug.h" |
87 | #include "rtld.h" | | 86 | #include "rtld.h" |
88 | | | 87 | |
89 | void _rtld_bind_start(void); | | 88 | void _rtld_bind_start(void); |
90 | void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr); | | 89 | void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr); |
91 | caddr_t _rtld_bind(const Obj_Entry *, Elf_Word); | | 90 | caddr_t _rtld_bind(const Obj_Entry *, Elf_Word); |
92 | static inline int _rtld_relocate_plt_object(const Obj_Entry *, | | 91 | static inline int _rtld_relocate_plt_object(const Obj_Entry *, |
93 | const Elf_Rela *, Elf_Addr *); | | 92 | const Elf_Rela *, Elf_Addr *); |
94 | | | 93 | |
95 | void | | 94 | void |
96 | _rtld_setup_pltgot(const Obj_Entry *obj) | | 95 | _rtld_setup_pltgot(const Obj_Entry *obj) |
97 | { | | 96 | { |
98 | obj->pltgot[1] = (Elf_Addr) obj; | | 97 | obj->pltgot[1] = (Elf_Addr) obj; |
99 | obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start; | | 98 | obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start; |
100 | } | | 99 | } |
101 | | | 100 | |
102 | void | | 101 | void |
103 | _rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase) | | 102 | _rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase) |
104 | { | | 103 | { |
105 | const Elf_Rela *rela = 0, *relalim; | | 104 | const Elf_Rela *rela = 0, *relalim; |
106 | Elf_Addr relasz = 0; | | 105 | Elf_Addr relasz = 0; |
107 | Elf_Addr *where; | | 106 | Elf_Addr *where; |
108 | | | 107 | |
109 | for (; dynp->d_tag != DT_NULL; dynp++) { | | 108 | for (; dynp->d_tag != DT_NULL; dynp++) { |
110 | switch (dynp->d_tag) { | | 109 | switch (dynp->d_tag) { |
111 | case DT_RELA: | | 110 | case DT_RELA: |
112 | rela = (const Elf_Rela *)(relocbase + dynp->d_un.d_ptr); | | 111 | rela = (const Elf_Rela *)(relocbase + dynp->d_un.d_ptr); |
113 | break; | | 112 | break; |
114 | case DT_RELASZ: | | 113 | case DT_RELASZ: |
115 | relasz = dynp->d_un.d_val; | | 114 | relasz = dynp->d_un.d_val; |
116 | break; | | 115 | break; |
117 | } | | 116 | } |
118 | } | | 117 | } |
119 | /* | | 118 | /* |
120 | * Assume only 64-bit relocations here, which should always | | 119 | * Assume only 64-bit relocations here, which should always |
121 | * be true for the dynamic linker. | | 120 | * be true for the dynamic linker. |
122 | */ | | 121 | */ |
123 | relalim = (const Elf_Rela *)((caddr_t)rela + relasz); | | 122 | relalim = (const Elf_Rela *)((caddr_t)rela + relasz); |
124 | for (; rela < relalim; rela++) { | | 123 | for (; rela < relalim; rela++) { |
125 | where = (Elf_Addr *)(relocbase + rela->r_offset); | | 124 | where = (Elf_Addr *)(relocbase + rela->r_offset); |
126 | *where = (Elf_Addr)(relocbase + rela->r_addend); | | 125 | *where = (Elf_Addr)(relocbase + rela->r_addend); |
127 | } | | 126 | } |
128 | } | | 127 | } |
129 | | | 128 | |
130 | int | | 129 | int |
131 | _rtld_relocate_nonplt_objects(const Obj_Entry *obj) | | 130 | _rtld_relocate_nonplt_objects(const Obj_Entry *obj) |
132 | { | | 131 | { |
133 | const Elf_Rela *rela; | | 132 | const Elf_Rela *rela; |
134 | const Elf_Sym *def = NULL; | | 133 | const Elf_Sym *def = NULL; |
135 | const Obj_Entry *defobj =NULL; | | 134 | const Obj_Entry *defobj =NULL; |
136 | | | 135 | |
137 | for (rela = obj->rela; rela < obj->relalim; rela++) { | | 136 | for (rela = obj->rela; rela < obj->relalim; rela++) { |
138 | Elf64_Addr *where64; | | 137 | Elf64_Addr *where64; |
139 | Elf32_Addr *where32; | | 138 | Elf32_Addr *where32; |
140 | Elf64_Addr tmp64; | | 139 | Elf64_Addr tmp64; |
141 | Elf32_Addr tmp32; | | 140 | Elf32_Addr tmp32; |
142 | unsigned long symnum; | | 141 | unsigned long symnum; |
143 | | | 142 | |
144 | where64 = (Elf64_Addr *)(obj->relocbase + rela->r_offset); | | 143 | where64 = (Elf64_Addr *)(obj->relocbase + rela->r_offset); |
145 | where32 = (Elf32_Addr *)where64; | | 144 | where32 = (Elf32_Addr *)where64; |
146 | symnum = ELF_R_SYM(rela->r_info); | | 145 | symnum = ELF_R_SYM(rela->r_info); |
147 | | | 146 | |
148 | switch (ELF_R_TYPE(rela->r_info)) { | | 147 | switch (ELF_R_TYPE(rela->r_info)) { |
149 | case R_TYPE(NONE): | | 148 | case R_TYPE(NONE): |
150 | break; | | 149 | break; |
151 | | | 150 | |
152 | case R_TYPE(32): /* word32 S + A, truncate */ | | 151 | case R_TYPE(32): /* word32 S + A, truncate */ |
153 | case R_TYPE(32S): /* word32 S + A, signed truncate */ | | 152 | case R_TYPE(32S): /* word32 S + A, signed truncate */ |
154 | case R_TYPE(GOT32): /* word32 G + A (XXX can we see these?) */ | | 153 | case R_TYPE(GOT32): /* word32 G + A (XXX can we see these?) */ |
155 | def = _rtld_find_symdef(symnum, obj, &defobj, false); | | 154 | def = _rtld_find_symdef(symnum, obj, &defobj, false); |
156 | if (def == NULL) | | 155 | if (def == NULL) |
157 | return -1; | | 156 | return -1; |
158 | tmp32 = (Elf32_Addr)(u_long)(defobj->relocbase + | | 157 | tmp32 = (Elf32_Addr)(u_long)(defobj->relocbase + |
159 | def->st_value + rela->r_addend); | | 158 | def->st_value + rela->r_addend); |
160 | | | 159 | |
161 | if (*where32 != tmp32) | | 160 | if (*where32 != tmp32) |
162 | *where32 = tmp32; | | 161 | *where32 = tmp32; |
163 | rdbg(("32/32S %s in %s --> %p in %s", | | 162 | rdbg(("32/32S %s in %s --> %p in %s", |
164 | obj->strtab + obj->symtab[symnum].st_name, | | 163 | obj->strtab + obj->symtab[symnum].st_name, |
165 | obj->path, (void *)(unsigned long)*where32, | | 164 | obj->path, (void *)(unsigned long)*where32, |
166 | defobj->path)); | | 165 | defobj->path)); |
167 | break; | | 166 | break; |
168 | case R_TYPE(64): /* word64 S + A */ | | 167 | case R_TYPE(64): /* word64 S + A */ |
169 | def = _rtld_find_symdef(symnum, obj, &defobj, false); | | 168 | def = _rtld_find_symdef(symnum, obj, &defobj, false); |
170 | if (def == NULL) | | 169 | if (def == NULL) |
171 | return -1; | | 170 | return -1; |
172 | tmp64 = (Elf64_Addr)(defobj->relocbase + def->st_value + | | 171 | tmp64 = (Elf64_Addr)(defobj->relocbase + def->st_value + |
173 | rela->r_addend); | | 172 | rela->r_addend); |
174 | | | 173 | |
175 | if (*where64 != tmp64) | | 174 | if (*where64 != tmp64) |
176 | *where64 = tmp64; | | 175 | *where64 = tmp64; |
177 | rdbg(("64 %s in %s --> %p in %s", | | 176 | rdbg(("64 %s in %s --> %p in %s", |
178 | obj->strtab + obj->symtab[symnum].st_name, | | 177 | obj->strtab + obj->symtab[symnum].st_name, |
179 | obj->path, (void *)*where64, defobj->path)); | | 178 | obj->path, (void *)*where64, defobj->path)); |
180 | break; | | 179 | break; |
181 | case R_TYPE(PC32): /* word32 S + A - P */ | | 180 | case R_TYPE(PC32): /* word32 S + A - P */ |
182 | def = _rtld_find_symdef(symnum, obj, &defobj, false); | | 181 | def = _rtld_find_symdef(symnum, obj, &defobj, false); |
183 | if (def == NULL) | | 182 | if (def == NULL) |
184 | return -1; | | 183 | return -1; |
185 | tmp32 = (Elf32_Addr)(u_long)(defobj->relocbase + | | 184 | tmp32 = (Elf32_Addr)(u_long)(defobj->relocbase + |
186 | def->st_value + rela->r_addend - | | 185 | def->st_value + rela->r_addend - |
187 | (Elf64_Addr)where64); | | 186 | (Elf64_Addr)where64); |
188 | if (*where32 != tmp32) | | 187 | if (*where32 != tmp32) |
189 | *where32 = tmp32; | | 188 | *where32 = tmp32; |
190 | rdbg(("PC32 %s in %s --> %p in %s", | | 189 | rdbg(("PC32 %s in %s --> %p in %s", |
191 | obj->strtab + obj->symtab[symnum].st_name, | | 190 | obj->strtab + obj->symtab[symnum].st_name, |
192 | obj->path, (void *)(unsigned long)*where32, | | 191 | obj->path, (void *)(unsigned long)*where32, |
193 | defobj->path)); | | 192 | defobj->path)); |
194 | break; | | 193 | break; |
195 | case R_TYPE(GLOB_DAT): /* word64 S */ | | 194 | case R_TYPE(GLOB_DAT): /* word64 S */ |
196 | def = _rtld_find_symdef(symnum, obj, &defobj, false); | | 195 | def = _rtld_find_symdef(symnum, obj, &defobj, false); |
197 | if (def == NULL) | | 196 | if (def == NULL) |
198 | return -1; | | 197 | return -1; |
199 | tmp64 = (Elf64_Addr)(defobj->relocbase + def->st_value); | | 198 | tmp64 = (Elf64_Addr)(defobj->relocbase + def->st_value); |
200 | | | 199 | |
201 | if (*where64 != tmp64) | | 200 | if (*where64 != tmp64) |
202 | *where64 = tmp64; | | 201 | *where64 = tmp64; |
203 | rdbg(("64 %s in %s --> %p in %s", | | 202 | rdbg(("64 %s in %s --> %p in %s", |
204 | obj->strtab + obj->symtab[symnum].st_name, | | 203 | obj->strtab + obj->symtab[symnum].st_name, |
205 | obj->path, (void *)*where64, defobj->path)); | | 204 | obj->path, (void *)*where64, defobj->path)); |
206 | break; | | 205 | break; |
207 | case R_TYPE(RELATIVE): /* word64 B + A */ | | 206 | case R_TYPE(RELATIVE): /* word64 B + A */ |
208 | tmp64 = (Elf64_Addr)(obj->relocbase + rela->r_addend); | | 207 | tmp64 = (Elf64_Addr)(obj->relocbase + rela->r_addend); |
209 | if (*where64 != tmp64) | | 208 | if (*where64 != tmp64) |
210 | *where64 = tmp64; | | 209 | *where64 = tmp64; |
211 | rdbg(("RELATIVE in %s --> %p", obj->path, | | 210 | rdbg(("RELATIVE in %s --> %p", obj->path, |
212 | (void *)*where64)); | | 211 | (void *)*where64)); |
213 | break; | | 212 | break; |
214 | | | 213 | |
215 | case R_TYPE(COPY): | | 214 | case R_TYPE(COPY): |
216 | rdbg(("COPY")); | | 215 | rdbg(("COPY")); |
217 | break; | | 216 | break; |
218 | | | 217 | |
219 | default: | | 218 | default: |
220 | rdbg(("sym = %lu, type = %lu, offset = %p, " | | 219 | rdbg(("sym = %lu, type = %lu, offset = %p, " |
221 | "addend = %p, contents = %p, symbol = %s", | | 220 | "addend = %p, contents = %p, symbol = %s", |
222 | symnum, (u_long)ELF_R_TYPE(rela->r_info), | | 221 | symnum, (u_long)ELF_R_TYPE(rela->r_info), |
223 | (void *)rela->r_offset, (void *)rela->r_addend, | | 222 | (void *)rela->r_offset, (void *)rela->r_addend, |
224 | (void *)*where64, | | 223 | (void *)*where64, |
225 | obj->strtab + obj->symtab[symnum].st_name)); | | 224 | obj->strtab + obj->symtab[symnum].st_name)); |
226 | _rtld_error("%s: Unsupported relocation type %ld " | | 225 | _rtld_error("%s: Unsupported relocation type %ld " |
227 | "in non-PLT relocations\n", | | 226 | "in non-PLT relocations\n", |
228 | obj->path, (u_long) ELF_R_TYPE(rela->r_info)); | | 227 | obj->path, (u_long) ELF_R_TYPE(rela->r_info)); |
229 | return -1; | | 228 | return -1; |
230 | } | | 229 | } |
231 | } | | 230 | } |
232 | return 0; | | 231 | return 0; |
233 | } | | 232 | } |
234 | | | 233 | |
235 | int | | 234 | int |
236 | _rtld_relocate_plt_lazy(const Obj_Entry *obj) | | 235 | _rtld_relocate_plt_lazy(const Obj_Entry *obj) |
237 | { | | 236 | { |
238 | const Elf_Rela *rela; | | 237 | const Elf_Rela *rela; |
239 | | | 238 | |
240 | if (!obj->relocbase) | | 239 | if (!obj->relocbase) |
241 | return 0; | | 240 | return 0; |
242 | | | 241 | |
243 | for (rela = obj->pltrela; rela < obj->pltrelalim; rela++) { | | 242 | for (rela = obj->pltrela; rela < obj->pltrelalim; rela++) { |
244 | Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); | | 243 | Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); |
245 | | | 244 | |
246 | assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JUMP_SLOT)); | | 245 | assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JUMP_SLOT)); |
247 | | | 246 | |
248 | /* Just relocate the GOT slots pointing into the PLT */ | | 247 | /* Just relocate the GOT slots pointing into the PLT */ |
249 | *where += (Elf_Addr)obj->relocbase; | | 248 | *where += (Elf_Addr)obj->relocbase; |
250 | rdbg(("fixup !main in %s --> %p", obj->path, (void *)*where)); | | 249 | rdbg(("fixup !main in %s --> %p", obj->path, (void *)*where)); |
251 | } | | 250 | } |
252 | | | 251 | |
253 | return 0; | | 252 | return 0; |
254 | } | | 253 | } |
255 | | | 254 | |
256 | static inline int | | 255 | static inline int |
257 | _rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, Elf_Addr *tp) | | 256 | _rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, Elf_Addr *tp) |
258 | { | | 257 | { |
259 | Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); | | 258 | Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); |
260 | Elf_Addr new_value; | | 259 | Elf_Addr new_value; |
261 | const Elf_Sym *def; | | 260 | const Elf_Sym *def; |
262 | const Obj_Entry *defobj; | | 261 | const Obj_Entry *defobj; |
263 | | | 262 | |
264 | assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JUMP_SLOT)); | | 263 | assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JUMP_SLOT)); |
265 | | | 264 | |
266 | def = _rtld_find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, true); | | 265 | def = _rtld_find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, true); |
267 | if (def == NULL) | | 266 | if (def == NULL) |
268 | return -1; | | 267 | return -1; |
269 | new_value = (Elf_Addr)(defobj->relocbase + def->st_value + | | 268 | new_value = (Elf_Addr)(defobj->relocbase + def->st_value + |
270 | rela->r_addend); | | 269 | rela->r_addend); |
271 | rdbg(("bind now/fixup in %s --> old=%p new=%p", | | 270 | rdbg(("bind now/fixup in %s --> old=%p new=%p", |
272 | defobj->strtab + def->st_name, (void *)*where, (void *)new_value)); | | 271 | defobj->strtab + def->st_name, (void *)*where, (void *)new_value)); |
273 | if (*where != new_value) | | 272 | if (*where != new_value) |
274 | *where = new_value; | | 273 | *where = new_value; |
275 | | | 274 | |
276 | if (tp) | | 275 | if (tp) |
277 | *tp = new_value - rela->r_addend; | | 276 | *tp = new_value - rela->r_addend; |
278 | | | 277 | |
279 | return 0; | | 278 | return 0; |
280 | } | | 279 | } |
281 | | | 280 | |
282 | caddr_t | | 281 | caddr_t |
283 | _rtld_bind(const Obj_Entry *obj, Elf_Word reloff) | | 282 | _rtld_bind(const Obj_Entry *obj, Elf_Word reloff) |
284 | { | | 283 | { |
285 | const Elf_Rela *rela = obj->pltrela + reloff; | | 284 | const Elf_Rela *rela = obj->pltrela + reloff; |
286 | Elf_Addr new_value; | | 285 | Elf_Addr new_value; |
287 | int err; | | 286 | int error; |
288 | | | 287 | |
289 | new_value = 0; /* XXX GCC4 */ | | 288 | new_value = 0; /* XXX GCC4 */ |
290 | | | 289 | |
291 | err = _rtld_relocate_plt_object(obj, rela, &new_value); | | 290 | error = _rtld_relocate_plt_object(obj, rela, &new_value); |
292 | if (err || new_value == 0) | | 291 | if (error || new_value == 0) |
293 | _rtld_die(); | | 292 | _rtld_die(); |
294 | | | 293 | |
295 | return (caddr_t)new_value; | | 294 | return (caddr_t)new_value; |
296 | } | | 295 | } |
297 | | | 296 | |
298 | int | | 297 | int |
299 | _rtld_relocate_plt_objects(const Obj_Entry *obj) | | 298 | _rtld_relocate_plt_objects(const Obj_Entry *obj) |
300 | { | | 299 | { |
301 | const Elf_Rela *rela; | | 300 | const Elf_Rela *rela; |
302 | | | 301 | |
303 | for (rela = obj->pltrela; rela < obj->pltrelalim; rela++) | | 302 | for (rela = obj->pltrela; rela < obj->pltrelalim; rela++) |
304 | if (_rtld_relocate_plt_object(obj, rela, NULL) < 0) | | 303 | if (_rtld_relocate_plt_object(obj, rela, NULL) < 0) |
305 | return -1; | | 304 | return -1; |
306 | | | 305 | |
307 | return 0; | | 306 | return 0; |
308 | } | | 307 | } |