Fix const issues (cast const pointers to "const uint8_t *" instead of "caddr_t") NOTE: change based on ../i386/mdreloc.c 1.27 XXX: not compile testeddiff -r1.28 -r1.29 src/libexec/ld.elf_so/arch/arm/mdreloc.c
(lukem)
--- src/libexec/ld.elf_so/arch/arm/mdreloc.c 2008/07/24 04:39:25 1.28
+++ src/libexec/ld.elf_so/arch/arm/mdreloc.c 2009/03/16 02:46:47 1.29
@@ -1,275 +1,275 @@ | @@ -1,275 +1,275 @@ | |||
1 | /* $NetBSD: mdreloc.c,v 1.28 2008/07/24 04:39:25 matt Exp $ */ | 1 | /* $NetBSD: mdreloc.c,v 1.29 2009/03/16 02:46:47 lukem Exp $ */ | |
2 | 2 | |||
3 | #include <sys/cdefs.h> | 3 | #include <sys/cdefs.h> | |
4 | #ifndef lint | 4 | #ifndef lint | |
5 | __RCSID("$NetBSD: mdreloc.c,v 1.28 2008/07/24 04:39:25 matt Exp $"); | 5 | __RCSID("$NetBSD: mdreloc.c,v 1.29 2009/03/16 02:46:47 lukem Exp $"); | |
6 | #endif /* not lint */ | 6 | #endif /* not lint */ | |
7 | 7 | |||
8 | #include <sys/types.h> | 8 | #include <sys/types.h> | |
9 | #include <sys/stat.h> | 9 | #include <sys/stat.h> | |
10 | 10 | |||
11 | #include <string.h> | 11 | #include <string.h> | |
12 | 12 | |||
13 | #include "debug.h" | 13 | #include "debug.h" | |
14 | #include "rtld.h" | 14 | #include "rtld.h" | |
15 | 15 | |||
16 | void _rtld_bind_start(void); | 16 | void _rtld_bind_start(void); | |
17 | void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr); | 17 | void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr); | |
18 | caddr_t _rtld_bind(const Obj_Entry *, Elf_Word); | 18 | caddr_t _rtld_bind(const Obj_Entry *, Elf_Word); | |
19 | 19 | |||
20 | void | 20 | void | |
21 | _rtld_setup_pltgot(const Obj_Entry *obj) | 21 | _rtld_setup_pltgot(const Obj_Entry *obj) | |
22 | { | 22 | { | |
23 | obj->pltgot[1] = (Elf_Addr) obj; | 23 | obj->pltgot[1] = (Elf_Addr) obj; | |
24 | obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start; | 24 | obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start; | |
25 | } | 25 | } | |
26 | 26 | |||
27 | void | 27 | void | |
28 | _rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase) | 28 | _rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase) | |
29 | { | 29 | { | |
30 | const Elf_Rel *rel = 0, *rellim; | 30 | const Elf_Rel *rel = 0, *rellim; | |
31 | Elf_Addr relsz = 0; | 31 | Elf_Addr relsz = 0; | |
32 | Elf_Addr *where; | 32 | Elf_Addr *where; | |
33 | 33 | |||
34 | for (; dynp->d_tag != DT_NULL; dynp++) { | 34 | for (; dynp->d_tag != DT_NULL; dynp++) { | |
35 | switch (dynp->d_tag) { | 35 | switch (dynp->d_tag) { | |
36 | case DT_REL: | 36 | case DT_REL: | |
37 | rel = (const Elf_Rel *)(relocbase + dynp->d_un.d_ptr); | 37 | rel = (const Elf_Rel *)(relocbase + dynp->d_un.d_ptr); | |
38 | break; | 38 | break; | |
39 | case DT_RELSZ: | 39 | case DT_RELSZ: | |
40 | relsz = dynp->d_un.d_val; | 40 | relsz = dynp->d_un.d_val; | |
41 | break; | 41 | break; | |
42 | } | 42 | } | |
43 | } | 43 | } | |
44 | rellim = (const Elf_Rel *)((caddr_t)rel + relsz); | 44 | rellim = (const Elf_Rel *)((const uint8_t *)rel + relsz); | |
45 | for (; rel < rellim; rel++) { | 45 | for (; rel < rellim; rel++) { | |
46 | where = (Elf_Addr *)(relocbase + rel->r_offset); | 46 | where = (Elf_Addr *)(relocbase + rel->r_offset); | |
47 | *where += (Elf_Addr)relocbase; | 47 | *where += (Elf_Addr)relocbase; | |
48 | } | 48 | } | |
49 | } | 49 | } | |
50 | 50 | |||
51 | /* | 51 | /* | |
52 | * It is possible for the compiler to emit relocations for unaligned data. | 52 | * It is possible for the compiler to emit relocations for unaligned data. | |
53 | * We handle this situation with these inlines. | 53 | * We handle this situation with these inlines. | |
54 | */ | 54 | */ | |
55 | #define RELOC_ALIGNED_P(x) \ | 55 | #define RELOC_ALIGNED_P(x) \ | |
56 | (((uintptr_t)(x) & (sizeof(void *) - 1)) == 0) | 56 | (((uintptr_t)(x) & (sizeof(void *) - 1)) == 0) | |
57 | 57 | |||
58 | static inline Elf_Addr | 58 | static inline Elf_Addr | |
59 | load_ptr(void *where) | 59 | load_ptr(void *where) | |
60 | { | 60 | { | |
61 | Elf_Addr res; | 61 | Elf_Addr res; | |
62 | 62 | |||
63 | memcpy(&res, where, sizeof(res)); | 63 | memcpy(&res, where, sizeof(res)); | |
64 | 64 | |||
65 | return (res); | 65 | return (res); | |
66 | } | 66 | } | |
67 | 67 | |||
68 | static inline void | 68 | static inline void | |
69 | store_ptr(void *where, Elf_Addr val) | 69 | store_ptr(void *where, Elf_Addr val) | |
70 | { | 70 | { | |
71 | 71 | |||
72 | memcpy(where, &val, sizeof(val)); | 72 | memcpy(where, &val, sizeof(val)); | |
73 | } | 73 | } | |
74 | 74 | |||
75 | int | 75 | int | |
76 | _rtld_relocate_nonplt_objects(const Obj_Entry *obj) | 76 | _rtld_relocate_nonplt_objects(const Obj_Entry *obj) | |
77 | { | 77 | { | |
78 | const Elf_Rel *rel; | 78 | const Elf_Rel *rel; | |
79 | 79 | |||
80 | for (rel = obj->rel; rel < obj->rellim; rel++) { | 80 | for (rel = obj->rel; rel < obj->rellim; rel++) { | |
81 | Elf_Addr *where; | 81 | Elf_Addr *where; | |
82 | const Elf_Sym *def; | 82 | const Elf_Sym *def; | |
83 | const Obj_Entry *defobj; | 83 | const Obj_Entry *defobj; | |
84 | Elf_Addr tmp; | 84 | Elf_Addr tmp; | |
85 | unsigned long symnum; | 85 | unsigned long symnum; | |
86 | 86 | |||
87 | where = (Elf_Addr *)(obj->relocbase + rel->r_offset); | 87 | where = (Elf_Addr *)(obj->relocbase + rel->r_offset); | |
88 | symnum = ELF_R_SYM(rel->r_info); | 88 | symnum = ELF_R_SYM(rel->r_info); | |
89 | 89 | |||
90 | switch (ELF_R_TYPE(rel->r_info)) { | 90 | switch (ELF_R_TYPE(rel->r_info)) { | |
91 | case R_TYPE(NONE): | 91 | case R_TYPE(NONE): | |
92 | break; | 92 | break; | |
93 | 93 | |||
94 | #if 1 /* XXX should not occur */ | 94 | #if 1 /* XXX should not occur */ | |
95 | case R_TYPE(PC24): { /* word32 S - P + A */ | 95 | case R_TYPE(PC24): { /* word32 S - P + A */ | |
96 | Elf32_Sword addend; | 96 | Elf32_Sword addend; | |
97 | 97 | |||
98 | /* | 98 | /* | |
99 | * Extract addend and sign-extend if needed. | 99 | * Extract addend and sign-extend if needed. | |
100 | */ | 100 | */ | |
101 | addend = *where; | 101 | addend = *where; | |
102 | if (addend & 0x00800000) | 102 | if (addend & 0x00800000) | |
103 | addend |= 0xff000000; | 103 | addend |= 0xff000000; | |
104 | 104 | |||
105 | def = _rtld_find_symdef(symnum, obj, &defobj, false); | 105 | def = _rtld_find_symdef(symnum, obj, &defobj, false); | |
106 | if (def == NULL) | 106 | if (def == NULL) | |
107 | return -1; | 107 | return -1; | |
108 | tmp = (Elf_Addr)obj->relocbase + def->st_value | 108 | tmp = (Elf_Addr)obj->relocbase + def->st_value | |
109 | - (Elf_Addr)where + (addend << 2); | 109 | - (Elf_Addr)where + (addend << 2); | |
110 | if ((tmp & 0xfe000000) != 0xfe000000 && | 110 | if ((tmp & 0xfe000000) != 0xfe000000 && | |
111 | (tmp & 0xfe000000) != 0) { | 111 | (tmp & 0xfe000000) != 0) { | |
112 | _rtld_error( | 112 | _rtld_error( | |
113 | "%s: R_ARM_PC24 relocation @ %p to %s failed " | 113 | "%s: R_ARM_PC24 relocation @ %p to %s failed " | |
114 | "(displacement %ld (%#lx) out of range)", | 114 | "(displacement %ld (%#lx) out of range)", | |
115 | obj->path, where, | 115 | obj->path, where, | |
116 | obj->strtab + obj->symtab[symnum].st_name, | 116 | obj->strtab + obj->symtab[symnum].st_name, | |
117 | (long) tmp, (long) tmp); | 117 | (long) tmp, (long) tmp); | |
118 | return -1; | 118 | return -1; | |
119 | } | 119 | } | |
120 | tmp >>= 2; | 120 | tmp >>= 2; | |
121 | *where = (*where & 0xff000000) | (tmp & 0x00ffffff); | 121 | *where = (*where & 0xff000000) | (tmp & 0x00ffffff); | |
122 | rdbg(("PC24 %s in %s --> %p @ %p in %s", | 122 | rdbg(("PC24 %s in %s --> %p @ %p in %s", | |
123 | obj->strtab + obj->symtab[symnum].st_name, | 123 | obj->strtab + obj->symtab[symnum].st_name, | |
124 | obj->path, (void *)*where, where, defobj->path)); | 124 | obj->path, (void *)*where, where, defobj->path)); | |
125 | break; | 125 | break; | |
126 | } | 126 | } | |
127 | #endif | 127 | #endif | |
128 | 128 | |||
129 | case R_TYPE(ABS32): /* word32 B + S + A */ | 129 | case R_TYPE(ABS32): /* word32 B + S + A */ | |
130 | case R_TYPE(GLOB_DAT): /* word32 B + S */ | 130 | case R_TYPE(GLOB_DAT): /* word32 B + S */ | |
131 | def = _rtld_find_symdef(symnum, obj, &defobj, false); | 131 | def = _rtld_find_symdef(symnum, obj, &defobj, false); | |
132 | if (def == NULL) | 132 | if (def == NULL) | |
133 | return -1; | 133 | return -1; | |
134 | if (__predict_true(RELOC_ALIGNED_P(where))) { | 134 | if (__predict_true(RELOC_ALIGNED_P(where))) { | |
135 | tmp = *where + (Elf_Addr)defobj->relocbase + | 135 | tmp = *where + (Elf_Addr)defobj->relocbase + | |
136 | def->st_value; | 136 | def->st_value; | |
137 | /* Set the Thumb bit, if needed. */ | 137 | /* Set the Thumb bit, if needed. */ | |
138 | if (ELF_ST_TYPE(def->st_info) == STT_ARM_TFUNC) | 138 | if (ELF_ST_TYPE(def->st_info) == STT_ARM_TFUNC) | |
139 | tmp |= 1; | 139 | tmp |= 1; | |
140 | *where = tmp; | 140 | *where = tmp; | |
141 | } else { | 141 | } else { | |
142 | tmp = load_ptr(where) + | 142 | tmp = load_ptr(where) + | |
143 | (Elf_Addr)defobj->relocbase + | 143 | (Elf_Addr)defobj->relocbase + | |
144 | def->st_value; | 144 | def->st_value; | |
145 | /* Set the Thumb bit, if needed. */ | 145 | /* Set the Thumb bit, if needed. */ | |
146 | if (ELF_ST_TYPE(def->st_info) == STT_ARM_TFUNC) | 146 | if (ELF_ST_TYPE(def->st_info) == STT_ARM_TFUNC) | |
147 | tmp |= 1; | 147 | tmp |= 1; | |
148 | store_ptr(where, tmp); | 148 | store_ptr(where, tmp); | |
149 | } | 149 | } | |
150 | rdbg(("ABS32/GLOB_DAT %s in %s --> %p @ %p in %s", | 150 | rdbg(("ABS32/GLOB_DAT %s in %s --> %p @ %p in %s", | |
151 | obj->strtab + obj->symtab[symnum].st_name, | 151 | obj->strtab + obj->symtab[symnum].st_name, | |
152 | obj->path, (void *)tmp, where, defobj->path)); | 152 | obj->path, (void *)tmp, where, defobj->path)); | |
153 | break; | 153 | break; | |
154 | 154 | |||
155 | case R_TYPE(RELATIVE): /* word32 B + A */ | 155 | case R_TYPE(RELATIVE): /* word32 B + A */ | |
156 | if (__predict_true(RELOC_ALIGNED_P(where))) { | 156 | if (__predict_true(RELOC_ALIGNED_P(where))) { | |
157 | tmp = *where + (Elf_Addr)obj->relocbase; | 157 | tmp = *where + (Elf_Addr)obj->relocbase; | |
158 | *where = tmp; | 158 | *where = tmp; | |
159 | } else { | 159 | } else { | |
160 | tmp = load_ptr(where) + | 160 | tmp = load_ptr(where) + | |
161 | (Elf_Addr)obj->relocbase; | 161 | (Elf_Addr)obj->relocbase; | |
162 | store_ptr(where, tmp); | 162 | store_ptr(where, tmp); | |
163 | } | 163 | } | |
164 | rdbg(("RELATIVE in %s --> %p", obj->path, | 164 | rdbg(("RELATIVE in %s --> %p", obj->path, | |
165 | (void *)tmp)); | 165 | (void *)tmp)); | |
166 | break; | 166 | break; | |
167 | 167 | |||
168 | case R_TYPE(COPY): | 168 | case R_TYPE(COPY): | |
169 | /* | 169 | /* | |
170 | * These are deferred until all other relocations have | 170 | * These are deferred until all other relocations have | |
171 | * been done. All we do here is make sure that the | 171 | * been done. All we do here is make sure that the | |
172 | * COPY relocation is not in a shared library. They | 172 | * COPY relocation is not in a shared library. They | |
173 | * are allowed only in executable files. | 173 | * are allowed only in executable files. | |
174 | */ | 174 | */ | |
175 | if (obj->isdynamic) { | 175 | if (obj->isdynamic) { | |
176 | _rtld_error( | 176 | _rtld_error( | |
177 | "%s: Unexpected R_COPY relocation in shared library", | 177 | "%s: Unexpected R_COPY relocation in shared library", | |
178 | obj->path); | 178 | obj->path); | |
179 | return -1; | 179 | return -1; | |
180 | } | 180 | } | |
181 | rdbg(("COPY (avoid in main)")); | 181 | rdbg(("COPY (avoid in main)")); | |
182 | break; | 182 | break; | |
183 | 183 | |||
184 | default: | 184 | default: | |
185 | rdbg(("sym = %lu, type = %lu, offset = %p, " | 185 | rdbg(("sym = %lu, type = %lu, offset = %p, " | |
186 | "contents = %p, symbol = %s", | 186 | "contents = %p, symbol = %s", | |
187 | symnum, (u_long)ELF_R_TYPE(rel->r_info), | 187 | symnum, (u_long)ELF_R_TYPE(rel->r_info), | |
188 | (void *)rel->r_offset, (void *)load_ptr(where), | 188 | (void *)rel->r_offset, (void *)load_ptr(where), | |
189 | obj->strtab + obj->symtab[symnum].st_name)); | 189 | obj->strtab + obj->symtab[symnum].st_name)); | |
190 | _rtld_error("%s: Unsupported relocation type %ld " | 190 | _rtld_error("%s: Unsupported relocation type %ld " | |
191 | "in non-PLT relocations\n", | 191 | "in non-PLT relocations\n", | |
192 | obj->path, (u_long) ELF_R_TYPE(rel->r_info)); | 192 | obj->path, (u_long) ELF_R_TYPE(rel->r_info)); | |
193 | return -1; | 193 | return -1; | |
194 | } | 194 | } | |
195 | } | 195 | } | |
196 | return 0; | 196 | return 0; | |
197 | } | 197 | } | |
198 | 198 | |||
199 | int | 199 | int | |
200 | _rtld_relocate_plt_lazy(const Obj_Entry *obj) | 200 | _rtld_relocate_plt_lazy(const Obj_Entry *obj) | |
201 | { | 201 | { | |
202 | const Elf_Rel *rel; | 202 | const Elf_Rel *rel; | |
203 | 203 | |||
204 | if (!obj->relocbase) | 204 | if (!obj->relocbase) | |
205 | return 0; | 205 | return 0; | |
206 | 206 | |||
207 | for (rel = obj->pltrel; rel < obj->pltrellim; rel++) { | 207 | for (rel = obj->pltrel; rel < obj->pltrellim; rel++) { | |
208 | Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rel->r_offset); | 208 | Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rel->r_offset); | |
209 | 209 | |||
210 | assert(ELF_R_TYPE(rel->r_info) == R_TYPE(JUMP_SLOT)); | 210 | assert(ELF_R_TYPE(rel->r_info) == R_TYPE(JUMP_SLOT)); | |
211 | 211 | |||
212 | /* Just relocate the GOT slots pointing into the PLT */ | 212 | /* Just relocate the GOT slots pointing into the PLT */ | |
213 | *where += (Elf_Addr)obj->relocbase; | 213 | *where += (Elf_Addr)obj->relocbase; | |
214 | rdbg(("fixup !main in %s --> %p", obj->path, (void *)*where)); | 214 | rdbg(("fixup !main in %s --> %p", obj->path, (void *)*where)); | |
215 | } | 215 | } | |
216 | 216 | |||
217 | return 0; | 217 | return 0; | |
218 | } | 218 | } | |
219 | 219 | |||
220 | static int | 220 | static int | |
221 | _rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rel *rel, | 221 | _rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rel *rel, | |
222 | Elf_Addr *tp) | 222 | Elf_Addr *tp) | |
223 | { | 223 | { | |
224 | Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rel->r_offset); | 224 | Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rel->r_offset); | |
225 | Elf_Addr new_value; | 225 | Elf_Addr new_value; | |
226 | const Elf_Sym *def; | 226 | const Elf_Sym *def; | |
227 | const Obj_Entry *defobj; | 227 | const Obj_Entry *defobj; | |
228 | 228 | |||
229 | assert(ELF_R_TYPE(rel->r_info) == R_TYPE(JUMP_SLOT)); | 229 | assert(ELF_R_TYPE(rel->r_info) == R_TYPE(JUMP_SLOT)); | |
230 | 230 | |||
231 | def = _rtld_find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, true); | 231 | def = _rtld_find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, true); | |
232 | if (def == NULL) | 232 | if (def == NULL) | |
233 | return -1; | 233 | return -1; | |
234 | 234 | |||
235 | new_value = (Elf_Addr)(defobj->relocbase + def->st_value); | 235 | new_value = (Elf_Addr)(defobj->relocbase + def->st_value); | |
236 | /* Set the Thumb bit, if needed. */ | 236 | /* Set the Thumb bit, if needed. */ | |
237 | if (ELF_ST_TYPE(def->st_info) == STT_ARM_TFUNC) | 237 | if (ELF_ST_TYPE(def->st_info) == STT_ARM_TFUNC) | |
238 | new_value |= 1; | 238 | new_value |= 1; | |
239 | rdbg(("bind now/fixup in %s --> old=%p new=%p", | 239 | rdbg(("bind now/fixup in %s --> old=%p new=%p", | |
240 | defobj->strtab + def->st_name, (void *)*where, (void *)new_value)); | 240 | defobj->strtab + def->st_name, (void *)*where, (void *)new_value)); | |
241 | if (*where != new_value) | 241 | if (*where != new_value) | |
242 | *where = new_value; | 242 | *where = new_value; | |
243 | if (tp) | 243 | if (tp) | |
244 | *tp = new_value; | 244 | *tp = new_value; | |
245 | 245 | |||
246 | return 0; | 246 | return 0; | |
247 | } | 247 | } | |
248 | 248 | |||
249 | caddr_t | 249 | caddr_t | |
250 | _rtld_bind(const Obj_Entry *obj, Elf_Word reloff) | 250 | _rtld_bind(const Obj_Entry *obj, Elf_Word reloff) | |
251 | { | 251 | { | |
252 | const Elf_Rel *rel = (const Elf_Rel *)((caddr_t)obj->pltrel + reloff); | 252 | const Elf_Rel *rel = (const Elf_Rel *)((const uint8_t *)obj->pltrel + reloff); | |
253 | Elf_Addr new_value; | 253 | Elf_Addr new_value; | |
254 | int err; | 254 | int err; | |
255 | 255 | |||
256 | err = _rtld_relocate_plt_object(obj, rel, &new_value); | 256 | err = _rtld_relocate_plt_object(obj, rel, &new_value); | |
257 | if (err || new_value == 0) | 257 | if (err || new_value == 0) | |
258 | _rtld_die(); | 258 | _rtld_die(); | |
259 | 259 | |||
260 | return (caddr_t)new_value; | 260 | return (caddr_t)new_value; | |
261 | } | 261 | } | |
262 | int | 262 | int | |
263 | _rtld_relocate_plt_objects(const Obj_Entry *obj) | 263 | _rtld_relocate_plt_objects(const Obj_Entry *obj) | |
264 | { | 264 | { | |
265 | const Elf_Rel *rel; | 265 | const Elf_Rel *rel; | |
266 | int err = 0; | 266 | int err = 0; | |
267 | 267 | |||
268 | for (rel = obj->pltrel; rel < obj->pltrellim; rel++) { | 268 | for (rel = obj->pltrel; rel < obj->pltrellim; rel++) { | |
269 | err = _rtld_relocate_plt_object(obj, rel, NULL); | 269 | err = _rtld_relocate_plt_object(obj, rel, NULL); | |
270 | if (err) | 270 | if (err) | |
271 | break; | 271 | break; | |
272 | } | 272 | } | |
273 | 273 | |||
274 | return err; | 274 | return err; | |
275 | } | 275 | } |
--- src/libexec/ld.elf_so/arch/m68k/mdreloc.c 2008/07/24 06:51:58 1.22
+++ src/libexec/ld.elf_so/arch/m68k/mdreloc.c 2009/03/16 02:46:47 1.23
@@ -1,221 +1,221 @@ | @@ -1,221 +1,221 @@ | |||
1 | /* $NetBSD: mdreloc.c,v 1.22 2008/07/24 06:51:58 skrll Exp $ */ | 1 | /* $NetBSD: mdreloc.c,v 1.23 2009/03/16 02:46:47 lukem Exp $ */ | |
2 | 2 | |||
3 | #include <sys/cdefs.h> | 3 | #include <sys/cdefs.h> | |
4 | #ifndef lint | 4 | #ifndef lint | |
5 | __RCSID("$NetBSD: mdreloc.c,v 1.22 2008/07/24 06:51:58 skrll Exp $"); | 5 | __RCSID("$NetBSD: mdreloc.c,v 1.23 2009/03/16 02:46:47 lukem Exp $"); | |
6 | #endif /* not lint */ | 6 | #endif /* not lint */ | |
7 | 7 | |||
8 | #include <sys/cdefs.h> | 8 | #include <sys/cdefs.h> | |
9 | #ifndef lint | 9 | #ifndef lint | |
10 | __RCSID("$NetBSD: mdreloc.c,v 1.22 2008/07/24 06:51:58 skrll Exp $"); | 10 | __RCSID("$NetBSD: mdreloc.c,v 1.23 2009/03/16 02:46:47 lukem Exp $"); | |
11 | #endif /* not lint */ | 11 | #endif /* not lint */ | |
12 | 12 | |||
13 | #include <sys/types.h> | 13 | #include <sys/types.h> | |
14 | #include <sys/stat.h> | 14 | #include <sys/stat.h> | |
15 | 15 | |||
16 | #include "debug.h" | 16 | #include "debug.h" | |
17 | #include "rtld.h" | 17 | #include "rtld.h" | |
18 | 18 | |||
19 | void _rtld_bind_start(void); | 19 | void _rtld_bind_start(void); | |
20 | void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr); | 20 | void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr); | |
21 | caddr_t _rtld_bind(const Obj_Entry *, Elf_Word); | 21 | caddr_t _rtld_bind(const Obj_Entry *, Elf_Word); | |
22 | static inline int _rtld_relocate_plt_object(const Obj_Entry *, | 22 | static inline int _rtld_relocate_plt_object(const Obj_Entry *, | |
23 | const Elf_Rela *, Elf_Addr *); | 23 | const Elf_Rela *, Elf_Addr *); | |
24 | 24 | |||
25 | 25 | |||
26 | void | 26 | void | |
27 | _rtld_setup_pltgot(const Obj_Entry *obj) | 27 | _rtld_setup_pltgot(const Obj_Entry *obj) | |
28 | { | 28 | { | |
29 | obj->pltgot[1] = (Elf_Addr) obj; | 29 | obj->pltgot[1] = (Elf_Addr) obj; | |
30 | obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start; | 30 | obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start; | |
31 | } | 31 | } | |
32 | 32 | |||
33 | void | 33 | void | |
34 | _rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase) | 34 | _rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase) | |
35 | { | 35 | { | |
36 | const Elf_Rela *rela = 0, *relalim; | 36 | const Elf_Rela *rela = 0, *relalim; | |
37 | Elf_Addr relasz = 0; | 37 | Elf_Addr relasz = 0; | |
38 | Elf_Addr *where; | 38 | Elf_Addr *where; | |
39 | 39 | |||
40 | for (; dynp->d_tag != DT_NULL; dynp++) { | 40 | for (; dynp->d_tag != DT_NULL; dynp++) { | |
41 | switch (dynp->d_tag) { | 41 | switch (dynp->d_tag) { | |
42 | case DT_RELA: | 42 | case DT_RELA: | |
43 | rela = (const Elf_Rela *)(relocbase + dynp->d_un.d_ptr); | 43 | rela = (const Elf_Rela *)(relocbase + dynp->d_un.d_ptr); | |
44 | break; | 44 | break; | |
45 | case DT_RELASZ: | 45 | case DT_RELASZ: | |
46 | relasz = dynp->d_un.d_val; | 46 | relasz = dynp->d_un.d_val; | |
47 | break; | 47 | break; | |
48 | } | 48 | } | |
49 | } | 49 | } | |
50 | relalim = (const Elf_Rela *)((caddr_t)rela + relasz); | 50 | relalim = (const Elf_Rela *)((const uint8_t *)rela + relasz); | |
51 | for (; rela < relalim; rela++) { | 51 | for (; rela < relalim; rela++) { | |
52 | where = (Elf_Addr *)(relocbase + rela->r_offset); | 52 | where = (Elf_Addr *)(relocbase + rela->r_offset); | |
53 | *where += (Elf_Addr)relocbase; | 53 | *where += (Elf_Addr)relocbase; | |
54 | } | 54 | } | |
55 | } | 55 | } | |
56 | 56 | |||
57 | int | 57 | int | |
58 | _rtld_relocate_nonplt_objects(const Obj_Entry *obj) | 58 | _rtld_relocate_nonplt_objects(const Obj_Entry *obj) | |
59 | { | 59 | { | |
60 | const Elf_Rela *rela; | 60 | const Elf_Rela *rela; | |
61 | 61 | |||
62 | for (rela = obj->rela; rela < obj->relalim; rela++) { | 62 | for (rela = obj->rela; rela < obj->relalim; rela++) { | |
63 | Elf_Addr *where; | 63 | Elf_Addr *where; | |
64 | const Elf_Sym *def; | 64 | const Elf_Sym *def; | |
65 | const Obj_Entry *defobj; | 65 | const Obj_Entry *defobj; | |
66 | Elf_Addr tmp; | 66 | Elf_Addr tmp; | |
67 | unsigned long symnum; | 67 | unsigned long symnum; | |
68 | 68 | |||
69 | where = (Elf_Addr *)(obj->relocbase + rela->r_offset); | 69 | where = (Elf_Addr *)(obj->relocbase + rela->r_offset); | |
70 | symnum = ELF_R_SYM(rela->r_info); | 70 | symnum = ELF_R_SYM(rela->r_info); | |
71 | 71 | |||
72 | switch (ELF_R_TYPE(rela->r_info)) { | 72 | switch (ELF_R_TYPE(rela->r_info)) { | |
73 | case R_TYPE(NONE): | 73 | case R_TYPE(NONE): | |
74 | break; | 74 | break; | |
75 | 75 | |||
76 | #if 1 /* XXX should not occur */ | 76 | #if 1 /* XXX should not occur */ | |
77 | case R_TYPE(PC32): | 77 | case R_TYPE(PC32): | |
78 | def = _rtld_find_symdef(symnum, obj, &defobj, false); | 78 | def = _rtld_find_symdef(symnum, obj, &defobj, false); | |
79 | if (def == NULL) | 79 | if (def == NULL) | |
80 | return -1; | 80 | return -1; | |
81 | 81 | |||
82 | tmp = (Elf_Addr)(defobj->relocbase + def->st_value + | 82 | tmp = (Elf_Addr)(defobj->relocbase + def->st_value + | |
83 | rela->r_addend) - (Elf_Addr)where; | 83 | rela->r_addend) - (Elf_Addr)where; | |
84 | if (*where != tmp) | 84 | if (*where != tmp) | |
85 | *where = tmp; | 85 | *where = tmp; | |
86 | rdbg(("PC32 %s in %s --> %p in %s", | 86 | rdbg(("PC32 %s in %s --> %p in %s", | |
87 | obj->strtab + obj->symtab[symnum].st_name, | 87 | obj->strtab + obj->symtab[symnum].st_name, | |
88 | obj->path, (void *)*where, defobj->path)); | 88 | obj->path, (void *)*where, defobj->path)); | |
89 | break; | 89 | break; | |
90 | 90 | |||
91 | case R_TYPE(GOT32): | 91 | case R_TYPE(GOT32): | |
92 | #endif | 92 | #endif | |
93 | case R_TYPE(32): | 93 | case R_TYPE(32): | |
94 | case R_TYPE(GLOB_DAT): | 94 | case R_TYPE(GLOB_DAT): | |
95 | def = _rtld_find_symdef(symnum, obj, &defobj, false); | 95 | def = _rtld_find_symdef(symnum, obj, &defobj, false); | |
96 | if (def == NULL) | 96 | if (def == NULL) | |
97 | return -1; | 97 | return -1; | |
98 | 98 | |||
99 | tmp = (Elf_Addr)(defobj->relocbase + def->st_value + | 99 | tmp = (Elf_Addr)(defobj->relocbase + def->st_value + | |
100 | rela->r_addend); | 100 | rela->r_addend); | |
101 | if (*where != tmp) | 101 | if (*where != tmp) | |
102 | *where = tmp; | 102 | *where = tmp; | |
103 | rdbg(("32/GLOB_DAT %s in %s --> %p in %s", | 103 | rdbg(("32/GLOB_DAT %s in %s --> %p in %s", | |
104 | obj->strtab + obj->symtab[symnum].st_name, | 104 | obj->strtab + obj->symtab[symnum].st_name, | |
105 | obj->path, (void *)*where, defobj->path)); | 105 | obj->path, (void *)*where, defobj->path)); | |
106 | break; | 106 | break; | |
107 | 107 | |||
108 | case R_TYPE(RELATIVE): | 108 | case R_TYPE(RELATIVE): | |
109 | *where += (Elf_Addr)obj->relocbase; | 109 | *where += (Elf_Addr)obj->relocbase; | |
110 | rdbg(("RELATIVE in %s --> %p", obj->path, | 110 | rdbg(("RELATIVE in %s --> %p", obj->path, | |
111 | (void *)*where)); | 111 | (void *)*where)); | |
112 | break; | 112 | break; | |
113 | 113 | |||
114 | case R_TYPE(COPY): | 114 | case R_TYPE(COPY): | |
115 | /* | 115 | /* | |
116 | * These are deferred until all other relocations have | 116 | * These are deferred until all other relocations have | |
117 | * been done. All we do here is make sure that the | 117 | * been done. All we do here is make sure that the | |
118 | * COPY relocation is not in a shared library. They | 118 | * COPY relocation is not in a shared library. They | |
119 | * are allowed only in executable files. | 119 | * are allowed only in executable files. | |
120 | */ | 120 | */ | |
121 | if (obj->isdynamic) { | 121 | if (obj->isdynamic) { | |
122 | _rtld_error( | 122 | _rtld_error( | |
123 | "%s: Unexpected R_COPY relocation in shared library", | 123 | "%s: Unexpected R_COPY relocation in shared library", | |
124 | obj->path); | 124 | obj->path); | |
125 | return -1; | 125 | return -1; | |
126 | } | 126 | } | |
127 | rdbg(("COPY (avoid in main)")); | 127 | rdbg(("COPY (avoid in main)")); | |
128 | break; | 128 | break; | |
129 | 129 | |||
130 | default: | 130 | default: | |
131 | rdbg(("sym = %lu, type = %lu, offset = %p, " | 131 | rdbg(("sym = %lu, type = %lu, offset = %p, " | |
132 | "addend = %p, contents = %p, symbol = %s", | 132 | "addend = %p, contents = %p, symbol = %s", | |
133 | symnum, (u_long)ELF_R_TYPE(rela->r_info), | 133 | symnum, (u_long)ELF_R_TYPE(rela->r_info), | |
134 | (void *)rela->r_offset, (void *)rela->r_addend, | 134 | (void *)rela->r_offset, (void *)rela->r_addend, | |
135 | (void *)*where, | 135 | (void *)*where, | |
136 | obj->strtab + obj->symtab[symnum].st_name)); | 136 | obj->strtab + obj->symtab[symnum].st_name)); | |
137 | _rtld_error("%s: Unsupported relocation type %ld " | 137 | _rtld_error("%s: Unsupported relocation type %ld " | |
138 | "in non-PLT relocations\n", | 138 | "in non-PLT relocations\n", | |
139 | obj->path, (u_long) ELF_R_TYPE(rela->r_info)); | 139 | obj->path, (u_long) ELF_R_TYPE(rela->r_info)); | |
140 | return -1; | 140 | return -1; | |
141 | } | 141 | } | |
142 | } | 142 | } | |
143 | return 0; | 143 | return 0; | |
144 | } | 144 | } | |
145 | 145 | |||
146 | int | 146 | int | |
147 | _rtld_relocate_plt_lazy(const Obj_Entry *obj) | 147 | _rtld_relocate_plt_lazy(const Obj_Entry *obj) | |
148 | { | 148 | { | |
149 | const Elf_Rela *rela; | 149 | const Elf_Rela *rela; | |
150 | 150 | |||
151 | if (!obj->relocbase) | 151 | if (!obj->relocbase) | |
152 | return 0; | 152 | return 0; | |
153 | 153 | |||
154 | for (rela = obj->pltrela; rela < obj->pltrelalim; rela++) { | 154 | for (rela = obj->pltrela; rela < obj->pltrelalim; rela++) { | |
155 | Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); | 155 | Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); | |
156 | 156 | |||
157 | assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT)); | 157 | assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT)); | |
158 | 158 | |||
159 | /* Just relocate the GOT slots pointing into the PLT */ | 159 | /* Just relocate the GOT slots pointing into the PLT */ | |
160 | *where += (Elf_Addr)obj->relocbase; | 160 | *where += (Elf_Addr)obj->relocbase; | |
161 | rdbg(("fixup !main in %s --> %p", obj->path, (void *)*where)); | 161 | rdbg(("fixup !main in %s --> %p", obj->path, (void *)*where)); | |
162 | } | 162 | } | |
163 | 163 | |||
164 | return 0; | 164 | return 0; | |
165 | } | 165 | } | |
166 | 166 | |||
167 | static inline int | 167 | static inline int | |
168 | _rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, Elf_Addr *tp) | 168 | _rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, Elf_Addr *tp) | |
169 | { | 169 | { | |
170 | Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); | 170 | Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); | |
171 | Elf_Addr new_value; | 171 | Elf_Addr new_value; | |
172 | const Elf_Sym *def; | 172 | const Elf_Sym *def; | |
173 | const Obj_Entry *defobj; | 173 | const Obj_Entry *defobj; | |
174 | 174 | |||
175 | assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT)); | 175 | assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT)); | |
176 | 176 | |||
177 | def = _rtld_find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, true); | 177 | def = _rtld_find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, true); | |
178 | if (def == NULL) | 178 | if (def == NULL) | |
179 | return -1; | 179 | return -1; | |
180 | 180 | |||
181 | assert(rela->r_addend == 0); | 181 | assert(rela->r_addend == 0); | |
182 | new_value = (Elf_Addr)(defobj->relocbase + def->st_value + | 182 | new_value = (Elf_Addr)(defobj->relocbase + def->st_value + | |
183 | rela->r_addend); | 183 | rela->r_addend); | |
184 | rdbg(("bind now/fixup in %s --> old=%p new=%p", | 184 | rdbg(("bind now/fixup in %s --> old=%p new=%p", | |
185 | defobj->strtab + def->st_name, (void *)*where, (void *)new_value)); | 185 | defobj->strtab + def->st_name, (void *)*where, (void *)new_value)); | |
186 | if (*where != new_value) | 186 | if (*where != new_value) | |
187 | *where = new_value; | 187 | *where = new_value; | |
188 | 188 | |||
189 | if (tp) | 189 | if (tp) | |
190 | *tp = new_value - rela->r_addend; | 190 | *tp = new_value - rela->r_addend; | |
191 | 191 | |||
192 | return 0; | 192 | return 0; | |
193 | } | 193 | } | |
194 | 194 | |||
195 | caddr_t | 195 | caddr_t | |
196 | _rtld_bind(const Obj_Entry *obj, Elf_Word reloff) | 196 | _rtld_bind(const Obj_Entry *obj, Elf_Word reloff) | |
197 | { | 197 | { | |
198 | const Elf_Rela *rela = (const Elf_Rela *)((caddr_t)obj->pltrela + reloff); | 198 | const Elf_Rela *rela = (const Elf_Rela *)((const uint8_t *)obj->pltrela + reloff); | |
199 | Elf_Addr result; | 199 | Elf_Addr result; | |
200 | int err; | 200 | int err; | |
201 | 201 | |||
202 | result = 0; /* XXX gcc */ | 202 | result = 0; /* XXX gcc */ | |
203 | 203 | |||
204 | err = _rtld_relocate_plt_object(obj, rela, &result); | 204 | err = _rtld_relocate_plt_object(obj, rela, &result); | |
205 | if (err || result == 0) | 205 | if (err || result == 0) | |
206 | _rtld_die(); | 206 | _rtld_die(); | |
207 | 207 | |||
208 | return (caddr_t)result; | 208 | return (caddr_t)result; | |
209 | } | 209 | } | |
210 | 210 | |||
211 | int | 211 | int | |
212 | _rtld_relocate_plt_objects(const Obj_Entry *obj) | 212 | _rtld_relocate_plt_objects(const Obj_Entry *obj) | |
213 | { | 213 | { | |
214 | const Elf_Rela *rela; | 214 | const Elf_Rela *rela; | |
215 | 215 | |||
216 | for (rela = obj->pltrela; rela < obj->pltrelalim; rela++) | 216 | for (rela = obj->pltrela; rela < obj->pltrelalim; rela++) | |
217 | if (_rtld_relocate_plt_object(obj, rela, NULL) < 0) | 217 | if (_rtld_relocate_plt_object(obj, rela, NULL) < 0) | |
218 | return -1; | 218 | return -1; | |
219 | 219 | |||
220 | return 0; | 220 | return 0; | |
221 | } | 221 | } |
--- src/libexec/ld.elf_so/arch/sh3/mdreloc.c 2008/07/24 06:51:58 1.24
+++ src/libexec/ld.elf_so/arch/sh3/mdreloc.c 2009/03/16 02:46:47 1.25
@@ -1,247 +1,247 @@ | @@ -1,247 +1,247 @@ | |||
1 | /* $NetBSD: mdreloc.c,v 1.24 2008/07/24 06:51:58 skrll Exp $ */ | 1 | /* $NetBSD: mdreloc.c,v 1.25 2009/03/16 02:46:47 lukem Exp $ */ | |
2 | 2 | |||
3 | #include <sys/cdefs.h> | 3 | #include <sys/cdefs.h> | |
4 | #ifndef lint | 4 | #ifndef lint | |
5 | __RCSID("$NetBSD: mdreloc.c,v 1.24 2008/07/24 06:51:58 skrll Exp $"); | 5 | __RCSID("$NetBSD: mdreloc.c,v 1.25 2009/03/16 02:46:47 lukem Exp $"); | |
6 | #endif /* not lint */ | 6 | #endif /* not lint */ | |
7 | 7 | |||
8 | #include <sys/cdefs.h> | 8 | #include <sys/cdefs.h> | |
9 | #ifndef lint | 9 | #ifndef lint | |
10 | __RCSID("$NetBSD: mdreloc.c,v 1.24 2008/07/24 06:51:58 skrll Exp $"); | 10 | __RCSID("$NetBSD: mdreloc.c,v 1.25 2009/03/16 02:46:47 lukem Exp $"); | |
11 | #endif /* not lint */ | 11 | #endif /* not lint */ | |
12 | 12 | |||
13 | #include <sys/types.h> | 13 | #include <sys/types.h> | |
14 | #include <sys/stat.h> | 14 | #include <sys/stat.h> | |
15 | 15 | |||
16 | #include "debug.h" | 16 | #include "debug.h" | |
17 | #include "rtld.h" | 17 | #include "rtld.h" | |
18 | 18 | |||
19 | void _rtld_bind_start(void); | 19 | void _rtld_bind_start(void); | |
20 | void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr); | 20 | void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr); | |
21 | caddr_t _rtld_bind(const Obj_Entry *, Elf_Word); | 21 | caddr_t _rtld_bind(const Obj_Entry *, Elf_Word); | |
22 | static inline int _rtld_relocate_plt_object(const Obj_Entry *, | 22 | static inline int _rtld_relocate_plt_object(const Obj_Entry *, | |
23 | const Elf_Rela *, Elf_Addr *); | 23 | const Elf_Rela *, Elf_Addr *); | |
24 | 24 | |||
25 | void | 25 | void | |
26 | _rtld_setup_pltgot(const Obj_Entry *obj) | 26 | _rtld_setup_pltgot(const Obj_Entry *obj) | |
27 | { | 27 | { | |
28 | obj->pltgot[1] = (Elf_Addr) obj; | 28 | obj->pltgot[1] = (Elf_Addr) obj; | |
29 | obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start; | 29 | obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start; | |
30 | } | 30 | } | |
31 | 31 | |||
32 | void | 32 | void | |
33 | _rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase) | 33 | _rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase) | |
34 | { | 34 | { | |
35 | const Elf_Rela *rela = 0, *relalim; | 35 | const Elf_Rela *rela = 0, *relalim; | |
36 | Elf_Addr relasz = 0; | 36 | Elf_Addr relasz = 0; | |
37 | Elf_Addr *where; | 37 | Elf_Addr *where; | |
38 | 38 | |||
39 | for (; dynp->d_tag != DT_NULL; dynp++) { | 39 | for (; dynp->d_tag != DT_NULL; dynp++) { | |
40 | switch (dynp->d_tag) { | 40 | switch (dynp->d_tag) { | |
41 | case DT_RELA: | 41 | case DT_RELA: | |
42 | rela = (const Elf_Rela *)(relocbase + dynp->d_un.d_ptr); | 42 | rela = (const Elf_Rela *)(relocbase + dynp->d_un.d_ptr); | |
43 | break; | 43 | break; | |
44 | case DT_RELASZ: | 44 | case DT_RELASZ: | |
45 | relasz = dynp->d_un.d_val; | 45 | relasz = dynp->d_un.d_val; | |
46 | break; | 46 | break; | |
47 | } | 47 | } | |
48 | } | 48 | } | |
49 | relalim = (const Elf_Rela *)((caddr_t)rela + relasz); | 49 | relalim = (const Elf_Rela *)((const uint8_t *)rela + relasz); | |
50 | for (; rela < relalim; rela++) { | 50 | for (; rela < relalim; rela++) { | |
51 | where = (Elf_Addr *)(relocbase + rela->r_offset); | 51 | where = (Elf_Addr *)(relocbase + rela->r_offset); | |
52 | *where = (Elf_Addr)(relocbase + rela->r_addend); | 52 | *where = (Elf_Addr)(relocbase + rela->r_addend); | |
53 | } | 53 | } | |
54 | } | 54 | } | |
55 | 55 | |||
56 | int | 56 | int | |
57 | _rtld_relocate_nonplt_objects(const Obj_Entry *obj) | 57 | _rtld_relocate_nonplt_objects(const Obj_Entry *obj) | |
58 | { | 58 | { | |
59 | const Elf_Rela *rela; | 59 | const Elf_Rela *rela; | |
60 | 60 | |||
61 | for (rela = obj->rela; rela < obj->relalim; rela++) { | 61 | for (rela = obj->rela; rela < obj->relalim; rela++) { | |
62 | Elf_Addr *where; | 62 | Elf_Addr *where; | |
63 | const Elf_Sym *def; | 63 | const Elf_Sym *def; | |
64 | const Obj_Entry *defobj; | 64 | const Obj_Entry *defobj; | |
65 | Elf_Addr tmp; | 65 | Elf_Addr tmp; | |
66 | unsigned long symnum; | 66 | unsigned long symnum; | |
67 | 67 | |||
68 | where = (Elf_Addr *)(obj->relocbase + rela->r_offset); | 68 | where = (Elf_Addr *)(obj->relocbase + rela->r_offset); | |
69 | symnum = ELF_R_SYM(rela->r_info); | 69 | symnum = ELF_R_SYM(rela->r_info); | |
70 | 70 | |||
71 | switch (ELF_R_TYPE(rela->r_info)) { | 71 | switch (ELF_R_TYPE(rela->r_info)) { | |
72 | case R_TYPE(NONE): | 72 | case R_TYPE(NONE): | |
73 | break; | 73 | break; | |
74 | 74 | |||
75 | #if 1 /* XXX should not occur */ | 75 | #if 1 /* XXX should not occur */ | |
76 | case R_TYPE(GOT32): | 76 | case R_TYPE(GOT32): | |
77 | def = _rtld_find_symdef(symnum, obj, &defobj, false); | 77 | def = _rtld_find_symdef(symnum, obj, &defobj, false); | |
78 | if (def == NULL) | 78 | if (def == NULL) | |
79 | return -1; | 79 | return -1; | |
80 | 80 | |||
81 | tmp = (Elf_Addr)(defobj->relocbase + def->st_value + | 81 | tmp = (Elf_Addr)(defobj->relocbase + def->st_value + | |
82 | rela->r_addend); | 82 | rela->r_addend); | |
83 | if (*where != tmp) | 83 | if (*where != tmp) | |
84 | *where = tmp; | 84 | *where = tmp; | |
85 | rdbg(("GOT32 %s in %s --> %p in %s", | 85 | rdbg(("GOT32 %s in %s --> %p in %s", | |
86 | obj->strtab + obj->symtab[symnum].st_name, | 86 | obj->strtab + obj->symtab[symnum].st_name, | |
87 | obj->path, (void *)*where, defobj->path)); | 87 | obj->path, (void *)*where, defobj->path)); | |
88 | break; | 88 | break; | |
89 | 89 | |||
90 | case R_TYPE(REL32): | 90 | case R_TYPE(REL32): | |
91 | def = _rtld_find_symdef(symnum, obj, &defobj, false); | 91 | def = _rtld_find_symdef(symnum, obj, &defobj, false); | |
92 | if (def == NULL) | 92 | if (def == NULL) | |
93 | return -1; | 93 | return -1; | |
94 | 94 | |||
95 | tmp = (Elf_Addr)(defobj->relocbase + def->st_value + | 95 | tmp = (Elf_Addr)(defobj->relocbase + def->st_value + | |
96 | rela->r_addend) - (Elf_Addr)where; | 96 | rela->r_addend) - (Elf_Addr)where; | |
97 | if (*where != tmp) | 97 | if (*where != tmp) | |
98 | *where = tmp; | 98 | *where = tmp; | |
99 | rdbg(("PC32 %s in %s --> %p in %s", | 99 | rdbg(("PC32 %s in %s --> %p in %s", | |
100 | obj->strtab + obj->symtab[symnum].st_name, | 100 | obj->strtab + obj->symtab[symnum].st_name, | |
101 | obj->path, (void *)*where, defobj->path)); | 101 | obj->path, (void *)*where, defobj->path)); | |
102 | break; | 102 | break; | |
103 | #endif | 103 | #endif | |
104 | 104 | |||
105 | case R_TYPE(DIR32): | 105 | case R_TYPE(DIR32): | |
106 | def = _rtld_find_symdef(symnum, obj, &defobj, false); | 106 | def = _rtld_find_symdef(symnum, obj, &defobj, false); | |
107 | if (def == NULL) | 107 | if (def == NULL) | |
108 | return -1; | 108 | return -1; | |
109 | 109 | |||
110 | tmp = (Elf_Addr)(defobj->relocbase + def->st_value + | 110 | tmp = (Elf_Addr)(defobj->relocbase + def->st_value + | |
111 | rela->r_addend); | 111 | rela->r_addend); | |
112 | if (*where != tmp) | 112 | if (*where != tmp) | |
113 | *where = tmp; | 113 | *where = tmp; | |
114 | rdbg(("32 %s in %s --> %p in %s", | 114 | rdbg(("32 %s in %s --> %p in %s", | |
115 | obj->strtab + obj->symtab[symnum].st_name, | 115 | obj->strtab + obj->symtab[symnum].st_name, | |
116 | obj->path, (void *)*where, defobj->path)); | 116 | obj->path, (void *)*where, defobj->path)); | |
117 | break; | 117 | break; | |
118 | 118 | |||
119 | case R_TYPE(GLOB_DAT): | 119 | case R_TYPE(GLOB_DAT): | |
120 | def = _rtld_find_symdef(symnum, obj, &defobj, false); | 120 | def = _rtld_find_symdef(symnum, obj, &defobj, false); | |
121 | if (def == NULL) | 121 | if (def == NULL) | |
122 | return -1; | 122 | return -1; | |
123 | 123 | |||
124 | tmp = (Elf_Addr)(defobj->relocbase + def->st_value) + | 124 | tmp = (Elf_Addr)(defobj->relocbase + def->st_value) + | |
125 | rela->r_addend; | 125 | rela->r_addend; | |
126 | if (*where != tmp) | 126 | if (*where != tmp) | |
127 | *where = tmp; | 127 | *where = tmp; | |
128 | rdbg(("GLOB_DAT %s in %s --> %p in %s", | 128 | rdbg(("GLOB_DAT %s in %s --> %p in %s", | |
129 | obj->strtab + obj->symtab[symnum].st_name, | 129 | obj->strtab + obj->symtab[symnum].st_name, | |
130 | obj->path, (void *)*where, defobj->path)); | 130 | obj->path, (void *)*where, defobj->path)); | |
131 | break; | 131 | break; | |
132 | 132 | |||
133 | case R_TYPE(RELATIVE): | 133 | case R_TYPE(RELATIVE): | |
134 | if (rela->r_addend) | 134 | if (rela->r_addend) | |
135 | *where = (Elf_Addr)obj->relocbase + rela->r_addend; | 135 | *where = (Elf_Addr)obj->relocbase + rela->r_addend; | |
136 | else | 136 | else | |
137 | *where += (Elf_Addr)obj->relocbase; | 137 | *where += (Elf_Addr)obj->relocbase; | |
138 | rdbg(("RELATIVE in %s --> %p", obj->path, | 138 | rdbg(("RELATIVE in %s --> %p", obj->path, | |
139 | (void *)*where)); | 139 | (void *)*where)); | |
140 | break; | 140 | break; | |
141 | 141 | |||
142 | case R_TYPE(COPY): | 142 | case R_TYPE(COPY): | |
143 | /* | 143 | /* | |
144 | * These are deferred until all other relocations have | 144 | * These are deferred until all other relocations have | |
145 | * been done. All we do here is make sure that the | 145 | * been done. All we do here is make sure that the | |
146 | * COPY relocation is not in a shared library. They | 146 | * COPY relocation is not in a shared library. They | |
147 | * are allowed only in executable files. | 147 | * are allowed only in executable files. | |
148 | */ | 148 | */ | |
149 | if (obj->isdynamic) { | 149 | if (obj->isdynamic) { | |
150 | _rtld_error( | 150 | _rtld_error( | |
151 | "%s: Unexpected R_COPY relocation in shared library", | 151 | "%s: Unexpected R_COPY relocation in shared library", | |
152 | obj->path); | 152 | obj->path); | |
153 | return -1; | 153 | return -1; | |
154 | } | 154 | } | |
155 | rdbg(("COPY (avoid in main)")); | 155 | rdbg(("COPY (avoid in main)")); | |
156 | break; | 156 | break; | |
157 | 157 | |||
158 | default: | 158 | default: | |
159 | rdbg(("sym = %lu, type = %lu, offset = %p, " | 159 | rdbg(("sym = %lu, type = %lu, offset = %p, " | |
160 | "addend = %p, contents = %p, symbol = %s", | 160 | "addend = %p, contents = %p, symbol = %s", | |
161 | symnum, (u_long)ELF_R_TYPE(rela->r_info), | 161 | symnum, (u_long)ELF_R_TYPE(rela->r_info), | |
162 | (void *)rela->r_offset, (void *)rela->r_addend, | 162 | (void *)rela->r_offset, (void *)rela->r_addend, | |
163 | (void *)*where, | 163 | (void *)*where, | |
164 | obj->strtab + obj->symtab[symnum].st_name)); | 164 | obj->strtab + obj->symtab[symnum].st_name)); | |
165 | _rtld_error("%s: Unsupported relocation type %ld " | 165 | _rtld_error("%s: Unsupported relocation type %ld " | |
166 | "in non-PLT relocations\n", | 166 | "in non-PLT relocations\n", | |
167 | obj->path, (u_long) ELF_R_TYPE(rela->r_info)); | 167 | obj->path, (u_long) ELF_R_TYPE(rela->r_info)); | |
168 | return -1; | 168 | return -1; | |
169 | } | 169 | } | |
170 | } | 170 | } | |
171 | return 0; | 171 | return 0; | |
172 | } | 172 | } | |
173 | 173 | |||
174 | int | 174 | int | |
175 | _rtld_relocate_plt_lazy(const Obj_Entry *obj) | 175 | _rtld_relocate_plt_lazy(const Obj_Entry *obj) | |
176 | { | 176 | { | |
177 | const Elf_Rela *rela; | 177 | const Elf_Rela *rela; | |
178 | 178 | |||
179 | if (!obj->relocbase) | 179 | if (!obj->relocbase) | |
180 | return 0; | 180 | return 0; | |
181 | 181 | |||
182 | for (rela = obj->pltrela; rela < obj->pltrelalim; rela++) { | 182 | for (rela = obj->pltrela; rela < obj->pltrelalim; rela++) { | |
183 | Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); | 183 | Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); | |
184 | 184 | |||
185 | assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT)); | 185 | assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT)); | |
186 | 186 | |||
187 | /* Just relocate the GOT slots pointing into the PLT */ | 187 | /* Just relocate the GOT slots pointing into the PLT */ | |
188 | *where += (Elf_Addr)obj->relocbase; | 188 | *where += (Elf_Addr)obj->relocbase; | |
189 | rdbg(("fixup !main in %s --> %p", obj->path, (void *)*where)); | 189 | rdbg(("fixup !main in %s --> %p", obj->path, (void *)*where)); | |
190 | } | 190 | } | |
191 | 191 | |||
192 | return 0; | 192 | return 0; | |
193 | } | 193 | } | |
194 | 194 | |||
195 | caddr_t | 195 | caddr_t | |
196 | _rtld_bind(const Obj_Entry *obj, Elf_Word reloff) | 196 | _rtld_bind(const Obj_Entry *obj, Elf_Word reloff) | |
197 | { | 197 | { | |
198 | const Elf_Rela *rela = (const Elf_Rela *)((caddr_t)obj->pltrela + reloff); | 198 | const Elf_Rela *rela = (const Elf_Rela *)((const uint8_t *)obj->pltrela + reloff); | |
199 | Elf_Addr new_value; | 199 | Elf_Addr new_value; | |
200 | int err; | 200 | int err; | |
201 | 201 | |||
202 | new_value = 0; /* XXX gcc */ | 202 | new_value = 0; /* XXX gcc */ | |
203 | 203 | |||
204 | err = _rtld_relocate_plt_object(obj, rela, &new_value); | 204 | err = _rtld_relocate_plt_object(obj, rela, &new_value); | |
205 | if (err || new_value == 0) | 205 | if (err || new_value == 0) | |
206 | _rtld_die(); | 206 | _rtld_die(); | |
207 | 207 | |||
208 | return (caddr_t)new_value; | 208 | return (caddr_t)new_value; | |
209 | } | 209 | } | |
210 | 210 | |||
211 | int | 211 | int | |
212 | _rtld_relocate_plt_objects(const Obj_Entry *obj) | 212 | _rtld_relocate_plt_objects(const Obj_Entry *obj) | |
213 | { | 213 | { | |
214 | const Elf_Rela *rela = obj->pltrela; | 214 | const Elf_Rela *rela = obj->pltrela; | |
215 | 215 | |||
216 | for (; rela < obj->pltrelalim; rela++) | 216 | for (; rela < obj->pltrelalim; rela++) | |
217 | if (_rtld_relocate_plt_object(obj, rela, NULL) < 0) | 217 | if (_rtld_relocate_plt_object(obj, rela, NULL) < 0) | |
218 | return -1; | 218 | return -1; | |
219 | 219 | |||
220 | return 0; | 220 | return 0; | |
221 | } | 221 | } | |
222 | 222 | |||
223 | static inline int | 223 | static inline int | |
224 | _rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, Elf_Addr *tp) | 224 | _rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, Elf_Addr *tp) | |
225 | { | 225 | { | |
226 | Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); | 226 | Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); | |
227 | Elf_Addr new_value; | 227 | Elf_Addr new_value; | |
228 | const Elf_Sym *def; | 228 | const Elf_Sym *def; | |
229 | const Obj_Entry *defobj; | 229 | const Obj_Entry *defobj; | |
230 | 230 | |||
231 | assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT)); | 231 | assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT)); | |
232 | 232 | |||
233 | def = _rtld_find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, true); | 233 | def = _rtld_find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, true); | |
234 | if (def == NULL) | 234 | if (def == NULL) | |
235 | return -1; | 235 | return -1; | |
236 | 236 | |||
237 | new_value = (Elf_Addr)(defobj->relocbase + def->st_value); | 237 | new_value = (Elf_Addr)(defobj->relocbase + def->st_value); | |
238 | rdbg(("bind now/fixup in %s --> old=%p new=%p", | 238 | rdbg(("bind now/fixup in %s --> old=%p new=%p", | |
239 | defobj->strtab + def->st_name, (void *)*where, (void *)new_value)); | 239 | defobj->strtab + def->st_name, (void *)*where, (void *)new_value)); | |
240 | if (*where != new_value) | 240 | if (*where != new_value) | |
241 | *where = new_value; | 241 | *where = new_value; | |
242 | 242 | |||
243 | if (tp) | 243 | if (tp) | |
244 | *tp = new_value; | 244 | *tp = new_value; | |
245 | 245 | |||
246 | return 0; | 246 | return 0; | |
247 | } | 247 | } |
--- src/libexec/ld.elf_so/arch/sparc/mdreloc.c 2008/07/24 04:39:25 1.41
+++ src/libexec/ld.elf_so/arch/sparc/mdreloc.c 2009/03/16 02:46:47 1.42
@@ -1,394 +1,394 @@ | @@ -1,394 +1,394 @@ | |||
1 | /* $NetBSD: mdreloc.c,v 1.41 2008/07/24 04:39:25 matt Exp $ */ | 1 | /* $NetBSD: mdreloc.c,v 1.42 2009/03/16 02:46:47 lukem Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 1999, 2002 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 1999, 2002 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Paul Kranenburg and by Charles M. Hannum. | 8 | * by Paul Kranenburg and by Charles M. Hannum. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | 15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in the | 16 | * notice, this list of conditions and the following disclaimer in the | |
17 | * documentation and/or other materials provided with the distribution. | 17 | * documentation and/or other materials provided with the distribution. | |
18 | * | 18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | #include <sys/cdefs.h> | 32 | #include <sys/cdefs.h> | |
33 | #ifndef lint | 33 | #ifndef lint | |
34 | __RCSID("$NetBSD: mdreloc.c,v 1.41 2008/07/24 04:39:25 matt Exp $"); | 34 | __RCSID("$NetBSD: mdreloc.c,v 1.42 2009/03/16 02:46:47 lukem Exp $"); | |
35 | #endif /* not lint */ | 35 | #endif /* not lint */ | |
36 | 36 | |||
37 | #include <errno.h> | 37 | #include <errno.h> | |
38 | #include <stdio.h> | 38 | #include <stdio.h> | |
39 | #include <stdlib.h> | 39 | #include <stdlib.h> | |
40 | #include <string.h> | 40 | #include <string.h> | |
41 | #include <unistd.h> | 41 | #include <unistd.h> | |
42 | #include <sys/stat.h> | 42 | #include <sys/stat.h> | |
43 | 43 | |||
44 | #include "rtldenv.h" | 44 | #include "rtldenv.h" | |
45 | #include "debug.h" | 45 | #include "debug.h" | |
46 | #include "rtld.h" | 46 | #include "rtld.h" | |
47 | 47 | |||
48 | /* | 48 | /* | |
49 | * The following table holds for each relocation type: | 49 | * The following table holds for each relocation type: | |
50 | * - the width in bits of the memory location the relocation | 50 | * - the width in bits of the memory location the relocation | |
51 | * applies to (not currently used) | 51 | * applies to (not currently used) | |
52 | * - the number of bits the relocation value must be shifted to the | 52 | * - the number of bits the relocation value must be shifted to the | |
53 | * right (i.e. discard least significant bits) to fit into | 53 | * right (i.e. discard least significant bits) to fit into | |
54 | * the appropriate field in the instruction word. | 54 | * the appropriate field in the instruction word. | |
55 | * - flags indicating whether | 55 | * - flags indicating whether | |
56 | * * the relocation involves a symbol | 56 | * * the relocation involves a symbol | |
57 | * * the relocation is relative to the current position | 57 | * * the relocation is relative to the current position | |
58 | * * the relocation is for a GOT entry | 58 | * * the relocation is for a GOT entry | |
59 | * * the relocation is relative to the load address | 59 | * * the relocation is relative to the load address | |
60 | * | 60 | * | |
61 | */ | 61 | */ | |
62 | #define _RF_S 0x80000000 /* Resolve symbol */ | 62 | #define _RF_S 0x80000000 /* Resolve symbol */ | |
63 | #define _RF_A 0x40000000 /* Use addend */ | 63 | #define _RF_A 0x40000000 /* Use addend */ | |
64 | #define _RF_P 0x20000000 /* Location relative */ | 64 | #define _RF_P 0x20000000 /* Location relative */ | |
65 | #define _RF_G 0x10000000 /* GOT offset */ | 65 | #define _RF_G 0x10000000 /* GOT offset */ | |
66 | #define _RF_B 0x08000000 /* Load address relative */ | 66 | #define _RF_B 0x08000000 /* Load address relative */ | |
67 | #define _RF_U 0x04000000 /* Unaligned */ | 67 | #define _RF_U 0x04000000 /* Unaligned */ | |
68 | #define _RF_SZ(s) (((s) & 0xff) << 8) /* memory target size */ | 68 | #define _RF_SZ(s) (((s) & 0xff) << 8) /* memory target size */ | |
69 | #define _RF_RS(s) ( (s) & 0xff) /* right shift */ | 69 | #define _RF_RS(s) ( (s) & 0xff) /* right shift */ | |
70 | static const int reloc_target_flags[] = { | 70 | static const int reloc_target_flags[] = { | |
71 | 0, /* NONE */ | 71 | 0, /* NONE */ | |
72 | _RF_S|_RF_A| _RF_SZ(8) | _RF_RS(0), /* RELOC_8 */ | 72 | _RF_S|_RF_A| _RF_SZ(8) | _RF_RS(0), /* RELOC_8 */ | |
73 | _RF_S|_RF_A| _RF_SZ(16) | _RF_RS(0), /* RELOC_16 */ | 73 | _RF_S|_RF_A| _RF_SZ(16) | _RF_RS(0), /* RELOC_16 */ | |
74 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* RELOC_32 */ | 74 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* RELOC_32 */ | |
75 | _RF_S|_RF_A|_RF_P| _RF_SZ(8) | _RF_RS(0), /* DISP_8 */ | 75 | _RF_S|_RF_A|_RF_P| _RF_SZ(8) | _RF_RS(0), /* DISP_8 */ | |
76 | _RF_S|_RF_A|_RF_P| _RF_SZ(16) | _RF_RS(0), /* DISP_16 */ | 76 | _RF_S|_RF_A|_RF_P| _RF_SZ(16) | _RF_RS(0), /* DISP_16 */ | |
77 | _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(0), /* DISP_32 */ | 77 | _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(0), /* DISP_32 */ | |
78 | _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WDISP_30 */ | 78 | _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WDISP_30 */ | |
79 | _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WDISP_22 */ | 79 | _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WDISP_22 */ | |
80 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(10), /* HI22 */ | 80 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(10), /* HI22 */ | |
81 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 22 */ | 81 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 22 */ | |
82 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 13 */ | 82 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 13 */ | |
83 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* LO10 */ | 83 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* LO10 */ | |
84 | _RF_G| _RF_SZ(32) | _RF_RS(0), /* GOT10 */ | 84 | _RF_G| _RF_SZ(32) | _RF_RS(0), /* GOT10 */ | |
85 | _RF_G| _RF_SZ(32) | _RF_RS(0), /* GOT13 */ | 85 | _RF_G| _RF_SZ(32) | _RF_RS(0), /* GOT13 */ | |
86 | _RF_G| _RF_SZ(32) | _RF_RS(10), /* GOT22 */ | 86 | _RF_G| _RF_SZ(32) | _RF_RS(10), /* GOT22 */ | |
87 | _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(0), /* PC10 */ | 87 | _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(0), /* PC10 */ | |
88 | _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(10), /* PC22 */ | 88 | _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(10), /* PC22 */ | |
89 | _RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WPLT30 */ | 89 | _RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WPLT30 */ | |
90 | _RF_SZ(32) | _RF_RS(0), /* COPY */ | 90 | _RF_SZ(32) | _RF_RS(0), /* COPY */ | |
91 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* GLOB_DAT */ | 91 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* GLOB_DAT */ | |
92 | _RF_SZ(32) | _RF_RS(0), /* JMP_SLOT */ | 92 | _RF_SZ(32) | _RF_RS(0), /* JMP_SLOT */ | |
93 | _RF_A| _RF_B| _RF_SZ(32) | _RF_RS(0), /* RELATIVE */ | 93 | _RF_A| _RF_B| _RF_SZ(32) | _RF_RS(0), /* RELATIVE */ | |
94 | _RF_S|_RF_A| _RF_U| _RF_SZ(32) | _RF_RS(0), /* UA_32 */ | 94 | _RF_S|_RF_A| _RF_U| _RF_SZ(32) | _RF_RS(0), /* UA_32 */ | |
95 | }; | 95 | }; | |
96 | 96 | |||
97 | #ifdef RTLD_DEBUG_RELOC | 97 | #ifdef RTLD_DEBUG_RELOC | |
98 | static const char *reloc_names[] = { | 98 | static const char *reloc_names[] = { | |
99 | "NONE", "RELOC_8", "RELOC_16", "RELOC_32", "DISP_8", | 99 | "NONE", "RELOC_8", "RELOC_16", "RELOC_32", "DISP_8", | |
100 | "DISP_16", "DISP_32", "WDISP_30", "WDISP_22", "HI22", | 100 | "DISP_16", "DISP_32", "WDISP_30", "WDISP_22", "HI22", | |
101 | "22", "13", "LO10", "GOT10", "GOT13", | 101 | "22", "13", "LO10", "GOT10", "GOT13", | |
102 | "GOT22", "PC10", "PC22", "WPLT30", "COPY", | 102 | "GOT22", "PC10", "PC22", "WPLT30", "COPY", | |
103 | "GLOB_DAT", "JMP_SLOT", "RELATIVE", "UA_32" | 103 | "GLOB_DAT", "JMP_SLOT", "RELATIVE", "UA_32" | |
104 | }; | 104 | }; | |
105 | #endif | 105 | #endif | |
106 | 106 | |||
107 | #define RELOC_RESOLVE_SYMBOL(t) ((reloc_target_flags[t] & _RF_S) != 0) | 107 | #define RELOC_RESOLVE_SYMBOL(t) ((reloc_target_flags[t] & _RF_S) != 0) | |
108 | #define RELOC_PC_RELATIVE(t) ((reloc_target_flags[t] & _RF_P) != 0) | 108 | #define RELOC_PC_RELATIVE(t) ((reloc_target_flags[t] & _RF_P) != 0) | |
109 | #define RELOC_BASE_RELATIVE(t) ((reloc_target_flags[t] & _RF_B) != 0) | 109 | #define RELOC_BASE_RELATIVE(t) ((reloc_target_flags[t] & _RF_B) != 0) | |
110 | #define RELOC_UNALIGNED(t) ((reloc_target_flags[t] & _RF_U) != 0) | 110 | #define RELOC_UNALIGNED(t) ((reloc_target_flags[t] & _RF_U) != 0) | |
111 | #define RELOC_USE_ADDEND(t) ((reloc_target_flags[t] & _RF_A) != 0) | 111 | #define RELOC_USE_ADDEND(t) ((reloc_target_flags[t] & _RF_A) != 0) | |
112 | #define RELOC_TARGET_SIZE(t) ((reloc_target_flags[t] >> 8) & 0xff) | 112 | #define RELOC_TARGET_SIZE(t) ((reloc_target_flags[t] >> 8) & 0xff) | |
113 | #define RELOC_VALUE_RIGHTSHIFT(t) (reloc_target_flags[t] & 0xff) | 113 | #define RELOC_VALUE_RIGHTSHIFT(t) (reloc_target_flags[t] & 0xff) | |
114 | 114 | |||
115 | static const int reloc_target_bitmask[] = { | 115 | static const int reloc_target_bitmask[] = { | |
116 | #define _BM(x) (~(-(1ULL << (x)))) | 116 | #define _BM(x) (~(-(1ULL << (x)))) | |
117 | 0, /* NONE */ | 117 | 0, /* NONE */ | |
118 | _BM(8), _BM(16), _BM(32), /* RELOC_8, _16, _32 */ | 118 | _BM(8), _BM(16), _BM(32), /* RELOC_8, _16, _32 */ | |
119 | _BM(8), _BM(16), _BM(32), /* DISP8, DISP16, DISP32 */ | 119 | _BM(8), _BM(16), _BM(32), /* DISP8, DISP16, DISP32 */ | |
120 | _BM(30), _BM(22), /* WDISP30, WDISP22 */ | 120 | _BM(30), _BM(22), /* WDISP30, WDISP22 */ | |
121 | _BM(22), _BM(22), /* HI22, _22 */ | 121 | _BM(22), _BM(22), /* HI22, _22 */ | |
122 | _BM(13), _BM(10), /* RELOC_13, _LO10 */ | 122 | _BM(13), _BM(10), /* RELOC_13, _LO10 */ | |
123 | _BM(10), _BM(13), _BM(22), /* GOT10, GOT13, GOT22 */ | 123 | _BM(10), _BM(13), _BM(22), /* GOT10, GOT13, GOT22 */ | |
124 | _BM(10), _BM(22), /* _PC10, _PC22 */ | 124 | _BM(10), _BM(22), /* _PC10, _PC22 */ | |
125 | _BM(30), 0, /* _WPLT30, _COPY */ | 125 | _BM(30), 0, /* _WPLT30, _COPY */ | |
126 | -1, -1, -1, /* _GLOB_DAT, JMP_SLOT, _RELATIVE */ | 126 | -1, -1, -1, /* _GLOB_DAT, JMP_SLOT, _RELATIVE */ | |
127 | _BM(32) /* _UA32 */ | 127 | _BM(32) /* _UA32 */ | |
128 | #undef _BM | 128 | #undef _BM | |
129 | }; | 129 | }; | |
130 | #define RELOC_VALUE_BITMASK(t) (reloc_target_bitmask[t]) | 130 | #define RELOC_VALUE_BITMASK(t) (reloc_target_bitmask[t]) | |
131 | 131 | |||
132 | void _rtld_bind_start(void); | 132 | void _rtld_bind_start(void); | |
133 | void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr); | 133 | void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr); | |
134 | caddr_t _rtld_bind(const Obj_Entry *, Elf_Word); | 134 | caddr_t _rtld_bind(const Obj_Entry *, Elf_Word); | |
135 | static inline int _rtld_relocate_plt_object(const Obj_Entry *, | 135 | static inline int _rtld_relocate_plt_object(const Obj_Entry *, | |
136 | const Elf_Rela *, Elf_Addr *); | 136 | const Elf_Rela *, Elf_Addr *); | |
137 | 137 | |||
138 | void | 138 | void | |
139 | _rtld_setup_pltgot(const Obj_Entry *obj) | 139 | _rtld_setup_pltgot(const Obj_Entry *obj) | |
140 | { | 140 | { | |
141 | /* | 141 | /* | |
142 | * PLTGOT is the PLT on the sparc. | 142 | * PLTGOT is the PLT on the sparc. | |
143 | * The first entry holds the call the dynamic linker. | 143 | * The first entry holds the call the dynamic linker. | |
144 | * We construct a `call' sequence that transfers | 144 | * We construct a `call' sequence that transfers | |
145 | * to `_rtld_bind_start()'. | 145 | * to `_rtld_bind_start()'. | |
146 | * The second entry holds the object identification. | 146 | * The second entry holds the object identification. | |
147 | * Note: each PLT entry is three words long. | 147 | * Note: each PLT entry is three words long. | |
148 | */ | 148 | */ | |
149 | #define SAVE 0x9de3bfa0 /* i.e. `save %sp,-96,%sp' */ | 149 | #define SAVE 0x9de3bfa0 /* i.e. `save %sp,-96,%sp' */ | |
150 | #define CALL 0x40000000 | 150 | #define CALL 0x40000000 | |
151 | #define NOP 0x01000000 | 151 | #define NOP 0x01000000 | |
152 | obj->pltgot[0] = SAVE; | 152 | obj->pltgot[0] = SAVE; | |
153 | obj->pltgot[1] = CALL | | 153 | obj->pltgot[1] = CALL | | |
154 | ((Elf_Addr) &_rtld_bind_start - (Elf_Addr) &obj->pltgot[1]) >> 2; | 154 | ((Elf_Addr) &_rtld_bind_start - (Elf_Addr) &obj->pltgot[1]) >> 2; | |
155 | obj->pltgot[2] = NOP; | 155 | obj->pltgot[2] = NOP; | |
156 | obj->pltgot[3] = (Elf_Addr) obj; | 156 | obj->pltgot[3] = (Elf_Addr) obj; | |
157 | } | 157 | } | |
158 | 158 | |||
159 | void | 159 | void | |
160 | _rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase) | 160 | _rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase) | |
161 | { | 161 | { | |
162 | const Elf_Rela *rela = 0, *relalim; | 162 | const Elf_Rela *rela = 0, *relalim; | |
163 | Elf_Addr relasz = 0; | 163 | Elf_Addr relasz = 0; | |
164 | Elf_Addr *where; | 164 | Elf_Addr *where; | |
165 | 165 | |||
166 | for (; dynp->d_tag != DT_NULL; dynp++) { | 166 | for (; dynp->d_tag != DT_NULL; dynp++) { | |
167 | switch (dynp->d_tag) { | 167 | switch (dynp->d_tag) { | |
168 | case DT_RELA: | 168 | case DT_RELA: | |
169 | rela = (const Elf_Rela *)(relocbase + dynp->d_un.d_ptr); | 169 | rela = (const Elf_Rela *)(relocbase + dynp->d_un.d_ptr); | |
170 | break; | 170 | break; | |
171 | case DT_RELASZ: | 171 | case DT_RELASZ: | |
172 | relasz = dynp->d_un.d_val; | 172 | relasz = dynp->d_un.d_val; | |
173 | break; | 173 | break; | |
174 | } | 174 | } | |
175 | } | 175 | } | |
176 | relalim = (const Elf_Rela *)((caddr_t)rela + relasz); | 176 | relalim = (const Elf_Rela *)((const uint8_t *)rela + relasz); | |
177 | for (; rela < relalim; rela++) { | 177 | for (; rela < relalim; rela++) { | |
178 | where = (Elf_Addr *)(relocbase + rela->r_offset); | 178 | where = (Elf_Addr *)(relocbase + rela->r_offset); | |
179 | *where += (Elf_Addr)(relocbase + rela->r_addend); | 179 | *where += (Elf_Addr)(relocbase + rela->r_addend); | |
180 | } | 180 | } | |
181 | } | 181 | } | |
182 | 182 | |||
183 | int | 183 | int | |
184 | _rtld_relocate_nonplt_objects(const Obj_Entry *obj) | 184 | _rtld_relocate_nonplt_objects(const Obj_Entry *obj) | |
185 | { | 185 | { | |
186 | const Elf_Rela *rela; | 186 | const Elf_Rela *rela; | |
187 | 187 | |||
188 | for (rela = obj->rela; rela < obj->relalim; rela++) { | 188 | for (rela = obj->rela; rela < obj->relalim; rela++) { | |
189 | Elf_Addr *where; | 189 | Elf_Addr *where; | |
190 | Elf_Word type, value, mask; | 190 | Elf_Word type, value, mask; | |
191 | const Elf_Sym *def = NULL; | 191 | const Elf_Sym *def = NULL; | |
192 | const Obj_Entry *defobj = NULL; | 192 | const Obj_Entry *defobj = NULL; | |
193 | unsigned long symnum; | 193 | unsigned long symnum; | |
194 | 194 | |||
195 | where = (Elf_Addr *) (obj->relocbase + rela->r_offset); | 195 | where = (Elf_Addr *) (obj->relocbase + rela->r_offset); | |
196 | symnum = ELF_R_SYM(rela->r_info); | 196 | symnum = ELF_R_SYM(rela->r_info); | |
197 | 197 | |||
198 | type = ELF_R_TYPE(rela->r_info); | 198 | type = ELF_R_TYPE(rela->r_info); | |
199 | if (type == R_TYPE(NONE)) | 199 | if (type == R_TYPE(NONE)) | |
200 | continue; | 200 | continue; | |
201 | 201 | |||
202 | /* We do JMP_SLOTs in _rtld_bind() below */ | 202 | /* We do JMP_SLOTs in _rtld_bind() below */ | |
203 | if (type == R_TYPE(JMP_SLOT)) | 203 | if (type == R_TYPE(JMP_SLOT)) | |
204 | continue; | 204 | continue; | |
205 | 205 | |||
206 | /* COPY relocs are also handled elsewhere */ | 206 | /* COPY relocs are also handled elsewhere */ | |
207 | if (type == R_TYPE(COPY)) | 207 | if (type == R_TYPE(COPY)) | |
208 | continue; | 208 | continue; | |
209 | 209 | |||
210 | /* | 210 | /* | |
211 | * We use the fact that relocation types are an `enum' | 211 | * We use the fact that relocation types are an `enum' | |
212 | * Note: R_SPARC_6 is currently numerically largest. | 212 | * Note: R_SPARC_6 is currently numerically largest. | |
213 | */ | 213 | */ | |
214 | if (type > R_TYPE(6)) | 214 | if (type > R_TYPE(6)) | |
215 | return (-1); | 215 | return (-1); | |
216 | 216 | |||
217 | value = rela->r_addend; | 217 | value = rela->r_addend; | |
218 | 218 | |||
219 | /* | 219 | /* | |
220 | * Handle relative relocs here, as an optimization. | 220 | * Handle relative relocs here, as an optimization. | |
221 | */ | 221 | */ | |
222 | if (type == R_TYPE(RELATIVE)) { | 222 | if (type == R_TYPE(RELATIVE)) { | |
223 | *where += (Elf_Addr)(obj->relocbase + value); | 223 | *where += (Elf_Addr)(obj->relocbase + value); | |
224 | rdbg(("RELATIVE in %s --> %p", obj->path, | 224 | rdbg(("RELATIVE in %s --> %p", obj->path, | |
225 | (void *)*where)); | 225 | (void *)*where)); | |
226 | continue; | 226 | continue; | |
227 | } | 227 | } | |
228 | 228 | |||
229 | if (RELOC_RESOLVE_SYMBOL(type)) { | 229 | if (RELOC_RESOLVE_SYMBOL(type)) { | |
230 | 230 | |||
231 | /* Find the symbol */ | 231 | /* Find the symbol */ | |
232 | def = _rtld_find_symdef(symnum, obj, &defobj, false); | 232 | def = _rtld_find_symdef(symnum, obj, &defobj, false); | |
233 | if (def == NULL) | 233 | if (def == NULL) | |
234 | return (-1); | 234 | return (-1); | |
235 | 235 | |||
236 | /* Add in the symbol's absolute address */ | 236 | /* Add in the symbol's absolute address */ | |
237 | value += (Elf_Word)(defobj->relocbase + def->st_value); | 237 | value += (Elf_Word)(defobj->relocbase + def->st_value); | |
238 | } | 238 | } | |
239 | 239 | |||
240 | if (RELOC_PC_RELATIVE(type)) { | 240 | if (RELOC_PC_RELATIVE(type)) { | |
241 | value -= (Elf_Word)where; | 241 | value -= (Elf_Word)where; | |
242 | } | 242 | } | |
243 | 243 | |||
244 | if (RELOC_BASE_RELATIVE(type)) { | 244 | if (RELOC_BASE_RELATIVE(type)) { | |
245 | /* | 245 | /* | |
246 | * Note that even though sparcs use `Elf_rela' | 246 | * Note that even though sparcs use `Elf_rela' | |
247 | * exclusively we still need the implicit memory addend | 247 | * exclusively we still need the implicit memory addend | |
248 | * in relocations referring to GOT entries. | 248 | * in relocations referring to GOT entries. | |
249 | * Undoubtedly, someone f*cked this up in the distant | 249 | * Undoubtedly, someone f*cked this up in the distant | |
250 | * past, and now we're stuck with it in the name of | 250 | * past, and now we're stuck with it in the name of | |
251 | * compatibility for all eternity.. | 251 | * compatibility for all eternity.. | |
252 | * | 252 | * | |
253 | * In any case, the implicit and explicit should be | 253 | * In any case, the implicit and explicit should be | |
254 | * mutually exclusive. We provide a check for that | 254 | * mutually exclusive. We provide a check for that | |
255 | * here. | 255 | * here. | |
256 | */ | 256 | */ | |
257 | #define DIAGNOSTIC | 257 | #define DIAGNOSTIC | |
258 | #ifdef DIAGNOSTIC | 258 | #ifdef DIAGNOSTIC | |
259 | if (value != 0 && *where != 0) { | 259 | if (value != 0 && *where != 0) { | |
260 | xprintf("BASE_REL(%s): where=%p, *where 0x%x, " | 260 | xprintf("BASE_REL(%s): where=%p, *where 0x%x, " | |
261 | "addend=0x%x, base %p\n", | 261 | "addend=0x%x, base %p\n", | |
262 | obj->path, where, *where, | 262 | obj->path, where, *where, | |
263 | rela->r_addend, obj->relocbase); | 263 | rela->r_addend, obj->relocbase); | |
264 | } | 264 | } | |
265 | #endif | 265 | #endif | |
266 | value += (Elf_Word)(obj->relocbase + *where); | 266 | value += (Elf_Word)(obj->relocbase + *where); | |
267 | } | 267 | } | |
268 | 268 | |||
269 | mask = RELOC_VALUE_BITMASK(type); | 269 | mask = RELOC_VALUE_BITMASK(type); | |
270 | value >>= RELOC_VALUE_RIGHTSHIFT(type); | 270 | value >>= RELOC_VALUE_RIGHTSHIFT(type); | |
271 | value &= mask; | 271 | value &= mask; | |
272 | 272 | |||
273 | if (RELOC_UNALIGNED(type)) { | 273 | if (RELOC_UNALIGNED(type)) { | |
274 | /* Handle unaligned relocations. */ | 274 | /* Handle unaligned relocations. */ | |
275 | Elf_Addr tmp = 0; | 275 | Elf_Addr tmp = 0; | |
276 | char *ptr = (char *)where; | 276 | char *ptr = (char *)where; | |
277 | int i, size = RELOC_TARGET_SIZE(type)/8; | 277 | int i, size = RELOC_TARGET_SIZE(type)/8; | |
278 | 278 | |||
279 | /* Read it in one byte at a time. */ | 279 | /* Read it in one byte at a time. */ | |
280 | for (i=0; i<size; i++) | 280 | for (i=0; i<size; i++) | |
281 | tmp = (tmp << 8) | ptr[i]; | 281 | tmp = (tmp << 8) | ptr[i]; | |
282 | 282 | |||
283 | tmp &= ~mask; | 283 | tmp &= ~mask; | |
284 | tmp |= value; | 284 | tmp |= value; | |
285 | 285 | |||
286 | /* Write it back out. */ | 286 | /* Write it back out. */ | |
287 | for (i=0; i<size; i++) | 287 | for (i=0; i<size; i++) | |
288 | ptr[i] = ((tmp >> (8*i)) & 0xff); | 288 | ptr[i] = ((tmp >> (8*i)) & 0xff); | |
289 | #ifdef RTLD_DEBUG_RELOC | 289 | #ifdef RTLD_DEBUG_RELOC | |
290 | value = (Elf_Word)tmp; | 290 | value = (Elf_Word)tmp; | |
291 | #endif | 291 | #endif | |
292 | 292 | |||
293 | } else { | 293 | } else { | |
294 | *where &= ~mask; | 294 | *where &= ~mask; | |
295 | *where |= value; | 295 | *where |= value; | |
296 | #ifdef RTLD_DEBUG_RELOC | 296 | #ifdef RTLD_DEBUG_RELOC | |
297 | value = (Elf_Word)*where; | 297 | value = (Elf_Word)*where; | |
298 | #endif | 298 | #endif | |
299 | } | 299 | } | |
300 | #ifdef RTLD_DEBUG_RELOC | 300 | #ifdef RTLD_DEBUG_RELOC | |
301 | if (RELOC_RESOLVE_SYMBOL(type)) { | 301 | if (RELOC_RESOLVE_SYMBOL(type)) { | |
302 | rdbg(("%s %s in %s --> %p in %s", reloc_names[type], | 302 | rdbg(("%s %s in %s --> %p in %s", reloc_names[type], | |
303 | obj->strtab + obj->symtab[symnum].st_name, | 303 | obj->strtab + obj->symtab[symnum].st_name, | |
304 | obj->path, (void *)value, defobj->path)); | 304 | obj->path, (void *)value, defobj->path)); | |
305 | } else { | 305 | } else { | |
306 | rdbg(("%s in %s --> %p", reloc_names[type], | 306 | rdbg(("%s in %s --> %p", reloc_names[type], | |
307 | obj->path, (void *)value)); | 307 | obj->path, (void *)value)); | |
308 | } | 308 | } | |
309 | #endif | 309 | #endif | |
310 | } | 310 | } | |
311 | return (0); | 311 | return (0); | |
312 | } | 312 | } | |
313 | 313 | |||
314 | int | 314 | int | |
315 | _rtld_relocate_plt_lazy(const Obj_Entry *obj) | 315 | _rtld_relocate_plt_lazy(const Obj_Entry *obj) | |
316 | { | 316 | { | |
317 | return (0); | 317 | return (0); | |
318 | } | 318 | } | |
319 | 319 | |||
320 | caddr_t | 320 | caddr_t | |
321 | _rtld_bind(const Obj_Entry *obj, Elf_Word reloff) | 321 | _rtld_bind(const Obj_Entry *obj, Elf_Word reloff) | |
322 | { | 322 | { | |
323 | const Elf_Rela *rela = (const Elf_Rela *)((caddr_t)obj->pltrela + reloff); | 323 | const Elf_Rela *rela = (const Elf_Rela *)((const uint8_t *)obj->pltrela + reloff); | |
324 | Elf_Addr value; | 324 | Elf_Addr value; | |
325 | int err; | 325 | int err; | |
326 | 326 | |||
327 | value = 0; /* XXX gcc */ | 327 | value = 0; /* XXX gcc */ | |
328 | 328 | |||
329 | err = _rtld_relocate_plt_object(obj, rela, &value); | 329 | err = _rtld_relocate_plt_object(obj, rela, &value); | |
330 | if (err || value == 0) | 330 | if (err || value == 0) | |
331 | _rtld_die(); | 331 | _rtld_die(); | |
332 | 332 | |||
333 | return (caddr_t)value; | 333 | return (caddr_t)value; | |
334 | } | 334 | } | |
335 | 335 | |||
336 | int | 336 | int | |
337 | _rtld_relocate_plt_objects(const Obj_Entry *obj) | 337 | _rtld_relocate_plt_objects(const Obj_Entry *obj) | |
338 | { | 338 | { | |
339 | const Elf_Rela *rela = obj->pltrela; | 339 | const Elf_Rela *rela = obj->pltrela; | |
340 | 340 | |||
341 | for (; rela < obj->pltrelalim; rela++) | 341 | for (; rela < obj->pltrelalim; rela++) | |
342 | if (_rtld_relocate_plt_object(obj, rela, NULL) < 0) | 342 | if (_rtld_relocate_plt_object(obj, rela, NULL) < 0) | |
343 | return -1; | 343 | return -1; | |
344 | 344 | |||
345 | return 0; | 345 | return 0; | |
346 | } | 346 | } | |
347 | 347 | |||
348 | static inline int | 348 | static inline int | |
349 | _rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, Elf_Addr *tp) | 349 | _rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, Elf_Addr *tp) | |
350 | { | 350 | { | |
351 | const Elf_Sym *def; | 351 | const Elf_Sym *def; | |
352 | const Obj_Entry *defobj; | 352 | const Obj_Entry *defobj; | |
353 | Elf_Word *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); | 353 | Elf_Word *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); | |
354 | Elf_Addr value; | 354 | Elf_Addr value; | |
355 | 355 | |||
356 | /* Fully resolve procedure addresses now */ | 356 | /* Fully resolve procedure addresses now */ | |
357 | 357 | |||
358 | assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT)); | 358 | assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT)); | |
359 | 359 | |||
360 | def = _rtld_find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, true); | 360 | def = _rtld_find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, true); | |
361 | if (def == NULL) | 361 | if (def == NULL) | |
362 | return -1; | 362 | return -1; | |
363 | 363 | |||
364 | value = (Elf_Addr)(defobj->relocbase + def->st_value); | 364 | value = (Elf_Addr)(defobj->relocbase + def->st_value); | |
365 | rdbg(("bind now/fixup in %s --> new=%p", | 365 | rdbg(("bind now/fixup in %s --> new=%p", | |
366 | defobj->strtab + def->st_name, (void *)value)); | 366 | defobj->strtab + def->st_name, (void *)value)); | |
367 | 367 | |||
368 | /* | 368 | /* | |
369 | * At the PLT entry pointed at by `where', we now construct | 369 | * At the PLT entry pointed at by `where', we now construct | |
370 | * a direct transfer to the now fully resolved function | 370 | * a direct transfer to the now fully resolved function | |
371 | * address. The resulting code in the jump slot is: | 371 | * address. The resulting code in the jump slot is: | |
372 | * | 372 | * | |
373 | * sethi %hi(roffset), %g1 | 373 | * sethi %hi(roffset), %g1 | |
374 | * sethi %hi(addr), %g1 | 374 | * sethi %hi(addr), %g1 | |
375 | * jmp %g1+%lo(addr) | 375 | * jmp %g1+%lo(addr) | |
376 | * | 376 | * | |
377 | * We write the third instruction first, since that leaves the | 377 | * We write the third instruction first, since that leaves the | |
378 | * previous `b,a' at the second word in place. Hence the whole | 378 | * previous `b,a' at the second word in place. Hence the whole | |
379 | * PLT slot can be atomically change to the new sequence by | 379 | * PLT slot can be atomically change to the new sequence by | |
380 | * writing the `sethi' instruction at word 2. | 380 | * writing the `sethi' instruction at word 2. | |
381 | */ | 381 | */ | |
382 | #define SETHI 0x03000000 | 382 | #define SETHI 0x03000000 | |
383 | #define JMP 0x81c06000 | 383 | #define JMP 0x81c06000 | |
384 | #define NOP 0x01000000 | 384 | #define NOP 0x01000000 | |
385 | where[2] = JMP | (value & 0x000003ff); | 385 | where[2] = JMP | (value & 0x000003ff); | |
386 | where[1] = SETHI | ((value >> 10) & 0x003fffff); | 386 | where[1] = SETHI | ((value >> 10) & 0x003fffff); | |
387 | __asm volatile("iflush %0+8" : : "r" (where)); | 387 | __asm volatile("iflush %0+8" : : "r" (where)); | |
388 | __asm volatile("iflush %0+4" : : "r" (where)); | 388 | __asm volatile("iflush %0+4" : : "r" (where)); | |
389 | 389 | |||
390 | if (tp) | 390 | if (tp) | |
391 | *tp = value; | 391 | *tp = value; | |
392 | 392 | |||
393 | return 0; | 393 | return 0; | |
394 | } | 394 | } |
--- src/libexec/ld.elf_so/arch/sparc64/mdreloc.c 2008/07/24 04:39:25 1.43
+++ src/libexec/ld.elf_so/arch/sparc64/mdreloc.c 2009/03/16 02:46:48 1.44
@@ -1,733 +1,733 @@ | @@ -1,733 +1,733 @@ | |||
1 | /* $NetBSD: mdreloc.c,v 1.43 2008/07/24 04:39:25 matt Exp $ */ | 1 | /* $NetBSD: mdreloc.c,v 1.44 2009/03/16 02:46:48 lukem Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2000 Eduardo Horvath. | 4 | * Copyright (c) 2000 Eduardo Horvath. | |
5 | * Copyright (c) 1999, 2002 The NetBSD Foundation, Inc. | 5 | * Copyright (c) 1999, 2002 The NetBSD Foundation, Inc. | |
6 | * All rights reserved. | 6 | * All rights reserved. | |
7 | * | 7 | * | |
8 | * This code is derived from software contributed to The NetBSD Foundation | 8 | * This code is derived from software contributed to The NetBSD Foundation | |
9 | * by Paul Kranenburg and by Charles M. Hannum. | 9 | * by Paul Kranenburg and by Charles M. Hannum. | |
10 | * | 10 | * | |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without | |
12 | * modification, are permitted provided that the following conditions | 12 | * modification, are permitted provided that the following conditions | |
13 | * are met: | 13 | * are met: | |
14 | * 1. Redistributions of source code must retain the above copyright | 14 | * 1. Redistributions of source code must retain the above copyright | |
15 | * notice, this list of conditions and the following disclaimer. | 15 | * notice, this list of conditions and the following disclaimer. | |
16 | * 2. Redistributions in binary form must reproduce the above copyright | 16 | * 2. Redistributions in binary form must reproduce the above copyright | |
17 | * notice, this list of conditions and the following disclaimer in the | 17 | * notice, this list of conditions and the following disclaimer in the | |
18 | * documentation and/or other materials provided with the distribution. | 18 | * documentation and/or other materials provided with the distribution. | |
19 | * | 19 | * | |
20 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 20 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
30 | * POSSIBILITY OF SUCH DAMAGE. | 30 | * POSSIBILITY OF SUCH DAMAGE. | |
31 | */ | 31 | */ | |
32 | 32 | |||
33 | #include <sys/cdefs.h> | 33 | #include <sys/cdefs.h> | |
34 | #ifndef lint | 34 | #ifndef lint | |
35 | __RCSID("$NetBSD: mdreloc.c,v 1.43 2008/07/24 04:39:25 matt Exp $"); | 35 | __RCSID("$NetBSD: mdreloc.c,v 1.44 2009/03/16 02:46:48 lukem Exp $"); | |
36 | #endif /* not lint */ | 36 | #endif /* not lint */ | |
37 | 37 | |||
38 | #include <errno.h> | 38 | #include <errno.h> | |
39 | #include <stdio.h> | 39 | #include <stdio.h> | |
40 | #include <stdlib.h> | 40 | #include <stdlib.h> | |
41 | #include <string.h> | 41 | #include <string.h> | |
42 | #include <unistd.h> | 42 | #include <unistd.h> | |
43 | #include <sys/stat.h> | 43 | #include <sys/stat.h> | |
44 | 44 | |||
45 | #include "rtldenv.h" | 45 | #include "rtldenv.h" | |
46 | #include "debug.h" | 46 | #include "debug.h" | |
47 | #include "rtld.h" | 47 | #include "rtld.h" | |
48 | 48 | |||
49 | /* | 49 | /* | |
50 | * The following table holds for each relocation type: | 50 | * The following table holds for each relocation type: | |
51 | * - the width in bits of the memory location the relocation | 51 | * - the width in bits of the memory location the relocation | |
52 | * applies to (not currently used) | 52 | * applies to (not currently used) | |
53 | * - the number of bits the relocation value must be shifted to the | 53 | * - the number of bits the relocation value must be shifted to the | |
54 | * right (i.e. discard least significant bits) to fit into | 54 | * right (i.e. discard least significant bits) to fit into | |
55 | * the appropriate field in the instruction word. | 55 | * the appropriate field in the instruction word. | |
56 | * - flags indicating whether | 56 | * - flags indicating whether | |
57 | * * the relocation involves a symbol | 57 | * * the relocation involves a symbol | |
58 | * * the relocation is relative to the current position | 58 | * * the relocation is relative to the current position | |
59 | * * the relocation is for a GOT entry | 59 | * * the relocation is for a GOT entry | |
60 | * * the relocation is relative to the load address | 60 | * * the relocation is relative to the load address | |
61 | * | 61 | * | |
62 | */ | 62 | */ | |
63 | #define _RF_S 0x80000000 /* Resolve symbol */ | 63 | #define _RF_S 0x80000000 /* Resolve symbol */ | |
64 | #define _RF_A 0x40000000 /* Use addend */ | 64 | #define _RF_A 0x40000000 /* Use addend */ | |
65 | #define _RF_P 0x20000000 /* Location relative */ | 65 | #define _RF_P 0x20000000 /* Location relative */ | |
66 | #define _RF_G 0x10000000 /* GOT offset */ | 66 | #define _RF_G 0x10000000 /* GOT offset */ | |
67 | #define _RF_B 0x08000000 /* Load address relative */ | 67 | #define _RF_B 0x08000000 /* Load address relative */ | |
68 | #define _RF_U 0x04000000 /* Unaligned */ | 68 | #define _RF_U 0x04000000 /* Unaligned */ | |
69 | #define _RF_SZ(s) (((s) & 0xff) << 8) /* memory target size */ | 69 | #define _RF_SZ(s) (((s) & 0xff) << 8) /* memory target size */ | |
70 | #define _RF_RS(s) ( (s) & 0xff) /* right shift */ | 70 | #define _RF_RS(s) ( (s) & 0xff) /* right shift */ | |
71 | static const int reloc_target_flags[] = { | 71 | static const int reloc_target_flags[] = { | |
72 | 0, /* NONE */ | 72 | 0, /* NONE */ | |
73 | _RF_S|_RF_A| _RF_SZ(8) | _RF_RS(0), /* RELOC_8 */ | 73 | _RF_S|_RF_A| _RF_SZ(8) | _RF_RS(0), /* RELOC_8 */ | |
74 | _RF_S|_RF_A| _RF_SZ(16) | _RF_RS(0), /* RELOC_16 */ | 74 | _RF_S|_RF_A| _RF_SZ(16) | _RF_RS(0), /* RELOC_16 */ | |
75 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* RELOC_32 */ | 75 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* RELOC_32 */ | |
76 | _RF_S|_RF_A|_RF_P| _RF_SZ(8) | _RF_RS(0), /* DISP_8 */ | 76 | _RF_S|_RF_A|_RF_P| _RF_SZ(8) | _RF_RS(0), /* DISP_8 */ | |
77 | _RF_S|_RF_A|_RF_P| _RF_SZ(16) | _RF_RS(0), /* DISP_16 */ | 77 | _RF_S|_RF_A|_RF_P| _RF_SZ(16) | _RF_RS(0), /* DISP_16 */ | |
78 | _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(0), /* DISP_32 */ | 78 | _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(0), /* DISP_32 */ | |
79 | _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WDISP_30 */ | 79 | _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WDISP_30 */ | |
80 | _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WDISP_22 */ | 80 | _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WDISP_22 */ | |
81 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(10), /* HI22 */ | 81 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(10), /* HI22 */ | |
82 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 22 */ | 82 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 22 */ | |
83 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 13 */ | 83 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 13 */ | |
84 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* LO10 */ | 84 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* LO10 */ | |
85 | _RF_G| _RF_SZ(32) | _RF_RS(0), /* GOT10 */ | 85 | _RF_G| _RF_SZ(32) | _RF_RS(0), /* GOT10 */ | |
86 | _RF_G| _RF_SZ(32) | _RF_RS(0), /* GOT13 */ | 86 | _RF_G| _RF_SZ(32) | _RF_RS(0), /* GOT13 */ | |
87 | _RF_G| _RF_SZ(32) | _RF_RS(10), /* GOT22 */ | 87 | _RF_G| _RF_SZ(32) | _RF_RS(10), /* GOT22 */ | |
88 | _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(0), /* PC10 */ | 88 | _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(0), /* PC10 */ | |
89 | _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(10), /* PC22 */ | 89 | _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(10), /* PC22 */ | |
90 | _RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WPLT30 */ | 90 | _RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WPLT30 */ | |
91 | _RF_SZ(32) | _RF_RS(0), /* COPY */ | 91 | _RF_SZ(32) | _RF_RS(0), /* COPY */ | |
92 | _RF_S|_RF_A| _RF_SZ(64) | _RF_RS(0), /* GLOB_DAT */ | 92 | _RF_S|_RF_A| _RF_SZ(64) | _RF_RS(0), /* GLOB_DAT */ | |
93 | _RF_SZ(32) | _RF_RS(0), /* JMP_SLOT */ | 93 | _RF_SZ(32) | _RF_RS(0), /* JMP_SLOT */ | |
94 | _RF_A| _RF_B| _RF_SZ(64) | _RF_RS(0), /* RELATIVE */ | 94 | _RF_A| _RF_B| _RF_SZ(64) | _RF_RS(0), /* RELATIVE */ | |
95 | _RF_S|_RF_A| _RF_U| _RF_SZ(32) | _RF_RS(0), /* UA_32 */ | 95 | _RF_S|_RF_A| _RF_U| _RF_SZ(32) | _RF_RS(0), /* UA_32 */ | |
96 | 96 | |||
97 | _RF_A| _RF_SZ(32) | _RF_RS(0), /* PLT32 */ | 97 | _RF_A| _RF_SZ(32) | _RF_RS(0), /* PLT32 */ | |
98 | _RF_A| _RF_SZ(32) | _RF_RS(10), /* HIPLT22 */ | 98 | _RF_A| _RF_SZ(32) | _RF_RS(10), /* HIPLT22 */ | |
99 | _RF_A| _RF_SZ(32) | _RF_RS(0), /* LOPLT10 */ | 99 | _RF_A| _RF_SZ(32) | _RF_RS(0), /* LOPLT10 */ | |
100 | _RF_A|_RF_P| _RF_SZ(32) | _RF_RS(0), /* PCPLT32 */ | 100 | _RF_A|_RF_P| _RF_SZ(32) | _RF_RS(0), /* PCPLT32 */ | |
101 | _RF_A|_RF_P| _RF_SZ(32) | _RF_RS(10), /* PCPLT22 */ | 101 | _RF_A|_RF_P| _RF_SZ(32) | _RF_RS(10), /* PCPLT22 */ | |
102 | _RF_A|_RF_P| _RF_SZ(32) | _RF_RS(0), /* PCPLT10 */ | 102 | _RF_A|_RF_P| _RF_SZ(32) | _RF_RS(0), /* PCPLT10 */ | |
103 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 10 */ | 103 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 10 */ | |
104 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 11 */ | 104 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 11 */ | |
105 | _RF_S|_RF_A| _RF_SZ(64) | _RF_RS(0), /* 64 */ | 105 | _RF_S|_RF_A| _RF_SZ(64) | _RF_RS(0), /* 64 */ | |
106 | _RF_S|_RF_A|/*extra*/ _RF_SZ(32) | _RF_RS(0), /* OLO10 */ | 106 | _RF_S|_RF_A|/*extra*/ _RF_SZ(32) | _RF_RS(0), /* OLO10 */ | |
107 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(42), /* HH22 */ | 107 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(42), /* HH22 */ | |
108 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(32), /* HM10 */ | 108 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(32), /* HM10 */ | |
109 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(10), /* LM22 */ | 109 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(10), /* LM22 */ | |
110 | _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(42), /* PC_HH22 */ | 110 | _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(42), /* PC_HH22 */ | |
111 | _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(32), /* PC_HM10 */ | 111 | _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(32), /* PC_HM10 */ | |
112 | _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(10), /* PC_LM22 */ | 112 | _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(10), /* PC_LM22 */ | |
113 | _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WDISP16 */ | 113 | _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WDISP16 */ | |
114 | _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WDISP19 */ | 114 | _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WDISP19 */ | |
115 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* GLOB_JMP */ | 115 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* GLOB_JMP */ | |
116 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 7 */ | 116 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 7 */ | |
117 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 5 */ | 117 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 5 */ | |
118 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 6 */ | 118 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 6 */ | |
119 | _RF_S|_RF_A|_RF_P| _RF_SZ(64) | _RF_RS(0), /* DISP64 */ | 119 | _RF_S|_RF_A|_RF_P| _RF_SZ(64) | _RF_RS(0), /* DISP64 */ | |
120 | _RF_A| _RF_SZ(64) | _RF_RS(0), /* PLT64 */ | 120 | _RF_A| _RF_SZ(64) | _RF_RS(0), /* PLT64 */ | |
121 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(10), /* HIX22 */ | 121 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(10), /* HIX22 */ | |
122 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* LOX10 */ | 122 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* LOX10 */ | |
123 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(22), /* H44 */ | 123 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(22), /* H44 */ | |
124 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(12), /* M44 */ | 124 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(12), /* M44 */ | |
125 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* L44 */ | 125 | _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* L44 */ | |
126 | _RF_S|_RF_A| _RF_SZ(64) | _RF_RS(0), /* REGISTER */ | 126 | _RF_S|_RF_A| _RF_SZ(64) | _RF_RS(0), /* REGISTER */ | |
127 | _RF_S|_RF_A| _RF_U| _RF_SZ(64) | _RF_RS(0), /* UA64 */ | 127 | _RF_S|_RF_A| _RF_U| _RF_SZ(64) | _RF_RS(0), /* UA64 */ | |
128 | _RF_S|_RF_A| _RF_U| _RF_SZ(16) | _RF_RS(0), /* UA16 */ | 128 | _RF_S|_RF_A| _RF_U| _RF_SZ(16) | _RF_RS(0), /* UA16 */ | |
129 | }; | 129 | }; | |
130 | 130 | |||
131 | #ifdef RTLD_DEBUG_RELOC | 131 | #ifdef RTLD_DEBUG_RELOC | |
132 | static const char *reloc_names[] = { | 132 | static const char *reloc_names[] = { | |
133 | "NONE", "RELOC_8", "RELOC_16", "RELOC_32", "DISP_8", | 133 | "NONE", "RELOC_8", "RELOC_16", "RELOC_32", "DISP_8", | |
134 | "DISP_16", "DISP_32", "WDISP_30", "WDISP_22", "HI22", | 134 | "DISP_16", "DISP_32", "WDISP_30", "WDISP_22", "HI22", | |
135 | "22", "13", "LO10", "GOT10", "GOT13", | 135 | "22", "13", "LO10", "GOT10", "GOT13", | |
136 | "GOT22", "PC10", "PC22", "WPLT30", "COPY", | 136 | "GOT22", "PC10", "PC22", "WPLT30", "COPY", | |
137 | "GLOB_DAT", "JMP_SLOT", "RELATIVE", "UA_32", "PLT32", | 137 | "GLOB_DAT", "JMP_SLOT", "RELATIVE", "UA_32", "PLT32", | |
138 | "HIPLT22", "LOPLT10", "LOPLT10", "PCPLT22", "PCPLT32", | 138 | "HIPLT22", "LOPLT10", "LOPLT10", "PCPLT22", "PCPLT32", | |
139 | "10", "11", "64", "OLO10", "HH22", | 139 | "10", "11", "64", "OLO10", "HH22", | |
140 | "HM10", "LM22", "PC_HH22", "PC_HM10", "PC_LM22", | 140 | "HM10", "LM22", "PC_HH22", "PC_HM10", "PC_LM22", | |
141 | "WDISP16", "WDISP19", "GLOB_JMP", "7", "5", "6", | 141 | "WDISP16", "WDISP19", "GLOB_JMP", "7", "5", "6", | |
142 | "DISP64", "PLT64", "HIX22", "LOX10", "H44", "M44", | 142 | "DISP64", "PLT64", "HIX22", "LOX10", "H44", "M44", | |
143 | "L44", "REGISTER", "UA64", "UA16" | 143 | "L44", "REGISTER", "UA64", "UA16" | |
144 | }; | 144 | }; | |
145 | #endif | 145 | #endif | |
146 | 146 | |||
147 | #define RELOC_RESOLVE_SYMBOL(t) ((reloc_target_flags[t] & _RF_S) != 0) | 147 | #define RELOC_RESOLVE_SYMBOL(t) ((reloc_target_flags[t] & _RF_S) != 0) | |
148 | #define RELOC_PC_RELATIVE(t) ((reloc_target_flags[t] & _RF_P) != 0) | 148 | #define RELOC_PC_RELATIVE(t) ((reloc_target_flags[t] & _RF_P) != 0) | |
149 | #define RELOC_BASE_RELATIVE(t) ((reloc_target_flags[t] & _RF_B) != 0) | 149 | #define RELOC_BASE_RELATIVE(t) ((reloc_target_flags[t] & _RF_B) != 0) | |
150 | #define RELOC_UNALIGNED(t) ((reloc_target_flags[t] & _RF_U) != 0) | 150 | #define RELOC_UNALIGNED(t) ((reloc_target_flags[t] & _RF_U) != 0) | |
151 | #define RELOC_USE_ADDEND(t) ((reloc_target_flags[t] & _RF_A) != 0) | 151 | #define RELOC_USE_ADDEND(t) ((reloc_target_flags[t] & _RF_A) != 0) | |
152 | #define RELOC_TARGET_SIZE(t) ((reloc_target_flags[t] >> 8) & 0xff) | 152 | #define RELOC_TARGET_SIZE(t) ((reloc_target_flags[t] >> 8) & 0xff) | |
153 | #define RELOC_VALUE_RIGHTSHIFT(t) (reloc_target_flags[t] & 0xff) | 153 | #define RELOC_VALUE_RIGHTSHIFT(t) (reloc_target_flags[t] & 0xff) | |
154 | 154 | |||
155 | static const long reloc_target_bitmask[] = { | 155 | static const long reloc_target_bitmask[] = { | |
156 | #define _BM(x) (~(-(1ULL << (x)))) | 156 | #define _BM(x) (~(-(1ULL << (x)))) | |
157 | 0, /* NONE */ | 157 | 0, /* NONE */ | |
158 | _BM(8), _BM(16), _BM(32), /* RELOC_8, _16, _32 */ | 158 | _BM(8), _BM(16), _BM(32), /* RELOC_8, _16, _32 */ | |
159 | _BM(8), _BM(16), _BM(32), /* DISP8, DISP16, DISP32 */ | 159 | _BM(8), _BM(16), _BM(32), /* DISP8, DISP16, DISP32 */ | |
160 | _BM(30), _BM(22), /* WDISP30, WDISP22 */ | 160 | _BM(30), _BM(22), /* WDISP30, WDISP22 */ | |
161 | _BM(22), _BM(22), /* HI22, _22 */ | 161 | _BM(22), _BM(22), /* HI22, _22 */ | |
162 | _BM(13), _BM(10), /* RELOC_13, _LO10 */ | 162 | _BM(13), _BM(10), /* RELOC_13, _LO10 */ | |
163 | _BM(10), _BM(13), _BM(22), /* GOT10, GOT13, GOT22 */ | 163 | _BM(10), _BM(13), _BM(22), /* GOT10, GOT13, GOT22 */ | |
164 | _BM(10), _BM(22), /* _PC10, _PC22 */ | 164 | _BM(10), _BM(22), /* _PC10, _PC22 */ | |
165 | _BM(30), 0, /* _WPLT30, _COPY */ | 165 | _BM(30), 0, /* _WPLT30, _COPY */ | |
166 | _BM(32), _BM(32), _BM(32), /* _GLOB_DAT, JMP_SLOT, _RELATIVE */ | 166 | _BM(32), _BM(32), _BM(32), /* _GLOB_DAT, JMP_SLOT, _RELATIVE */ | |
167 | _BM(32), _BM(32), /* _UA32, PLT32 */ | 167 | _BM(32), _BM(32), /* _UA32, PLT32 */ | |
168 | _BM(22), _BM(10), /* _HIPLT22, LOPLT10 */ | 168 | _BM(22), _BM(10), /* _HIPLT22, LOPLT10 */ | |
169 | _BM(32), _BM(22), _BM(10), /* _PCPLT32, _PCPLT22, _PCPLT10 */ | 169 | _BM(32), _BM(22), _BM(10), /* _PCPLT32, _PCPLT22, _PCPLT10 */ | |
170 | _BM(10), _BM(11), -1, /* _10, _11, _64 */ | 170 | _BM(10), _BM(11), -1, /* _10, _11, _64 */ | |
171 | _BM(10), _BM(22), /* _OLO10, _HH22 */ | 171 | _BM(10), _BM(22), /* _OLO10, _HH22 */ | |
172 | _BM(10), _BM(22), /* _HM10, _LM22 */ | 172 | _BM(10), _BM(22), /* _HM10, _LM22 */ | |
173 | _BM(22), _BM(10), _BM(22), /* _PC_HH22, _PC_HM10, _PC_LM22 */ | 173 | _BM(22), _BM(10), _BM(22), /* _PC_HH22, _PC_HM10, _PC_LM22 */ | |
174 | _BM(16), _BM(19), /* _WDISP16, _WDISP19 */ | 174 | _BM(16), _BM(19), /* _WDISP16, _WDISP19 */ | |
175 | -1, /* GLOB_JMP */ | 175 | -1, /* GLOB_JMP */ | |
176 | _BM(7), _BM(5), _BM(6) /* _7, _5, _6 */ | 176 | _BM(7), _BM(5), _BM(6) /* _7, _5, _6 */ | |
177 | -1, -1, /* DISP64, PLT64 */ | 177 | -1, -1, /* DISP64, PLT64 */ | |
178 | _BM(22), _BM(13), /* HIX22, LOX10 */ | 178 | _BM(22), _BM(13), /* HIX22, LOX10 */ | |
179 | _BM(22), _BM(10), _BM(13), /* H44, M44, L44 */ | 179 | _BM(22), _BM(10), _BM(13), /* H44, M44, L44 */ | |
180 | -1, -1, _BM(16), /* REGISTER, UA64, UA16 */ | 180 | -1, -1, _BM(16), /* REGISTER, UA64, UA16 */ | |
181 | #undef _BM | 181 | #undef _BM | |
182 | }; | 182 | }; | |
183 | #define RELOC_VALUE_BITMASK(t) (reloc_target_bitmask[t]) | 183 | #define RELOC_VALUE_BITMASK(t) (reloc_target_bitmask[t]) | |
184 | 184 | |||
185 | /* | 185 | /* | |
186 | * Instruction templates: | 186 | * Instruction templates: | |
187 | */ | 187 | */ | |
188 | #define BAA 0x10400000 /* ba,a %xcc, 0 */ | 188 | #define BAA 0x10400000 /* ba,a %xcc, 0 */ | |
189 | #define SETHI 0x03000000 /* sethi %hi(0), %g1 */ | 189 | #define SETHI 0x03000000 /* sethi %hi(0), %g1 */ | |
190 | #define JMP 0x81c06000 /* jmpl %g1+%lo(0), %g0 */ | 190 | #define JMP 0x81c06000 /* jmpl %g1+%lo(0), %g0 */ | |
191 | #define NOP 0x01000000 /* sethi %hi(0), %g0 */ | 191 | #define NOP 0x01000000 /* sethi %hi(0), %g0 */ | |
192 | #define OR 0x82806000 /* or %g1, 0, %g1 */ | 192 | #define OR 0x82806000 /* or %g1, 0, %g1 */ | |
193 | #define XOR 0x82c06000 /* xor %g1, 0, %g1 */ | 193 | #define XOR 0x82c06000 /* xor %g1, 0, %g1 */ | |
194 | #define MOV71 0x8283a000 /* or %o7, 0, %g1 */ | 194 | #define MOV71 0x8283a000 /* or %o7, 0, %g1 */ | |
195 | #define MOV17 0x9c806000 /* or %g1, 0, %o7 */ | 195 | #define MOV17 0x9c806000 /* or %g1, 0, %o7 */ | |
196 | #define CALL 0x40000000 /* call 0 */ | 196 | #define CALL 0x40000000 /* call 0 */ | |
197 | #define SLLX 0x8b407000 /* sllx %g1, 0, %g1 */ | 197 | #define SLLX 0x8b407000 /* sllx %g1, 0, %g1 */ | |
198 | #define SETHIG5 0x0b000000 /* sethi %hi(0), %g5 */ | 198 | #define SETHIG5 0x0b000000 /* sethi %hi(0), %g5 */ | |
199 | #define ORG5 0x82804005 /* or %g1, %g5, %g1 */ | 199 | #define ORG5 0x82804005 /* or %g1, %g5, %g1 */ | |
200 | 200 | |||
201 | 201 | |||
202 | /* %hi(v)/%lo(v) with variable shift */ | 202 | /* %hi(v)/%lo(v) with variable shift */ | |
203 | #define HIVAL(v, s) (((v) >> (s)) & 0x003fffff) | 203 | #define HIVAL(v, s) (((v) >> (s)) & 0x003fffff) | |
204 | #define LOVAL(v, s) (((v) >> (s)) & 0x000003ff) | 204 | #define LOVAL(v, s) (((v) >> (s)) & 0x000003ff) | |
205 | 205 | |||
206 | void _rtld_bind_start_0(long, long); | 206 | void _rtld_bind_start_0(long, long); | |
207 | void _rtld_bind_start_1(long, long); | 207 | void _rtld_bind_start_1(long, long); | |
208 | void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr); | 208 | void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr); | |
209 | caddr_t _rtld_bind(const Obj_Entry *, Elf_Word); | 209 | caddr_t _rtld_bind(const Obj_Entry *, Elf_Word); | |
210 | 210 | |||
211 | /* | 211 | /* | |
212 | * Install rtld function call into this PLT slot. | 212 | * Install rtld function call into this PLT slot. | |
213 | */ | 213 | */ | |
214 | #define SAVE 0x9de3bf50 /* i.e. `save %sp,-176,%sp' */ | 214 | #define SAVE 0x9de3bf50 /* i.e. `save %sp,-176,%sp' */ | |
215 | #define SETHI_l0 0x21000000 | 215 | #define SETHI_l0 0x21000000 | |
216 | #define SETHI_l1 0x23000000 | 216 | #define SETHI_l1 0x23000000 | |
217 | #define OR_l0_l0 0xa0142000 | 217 | #define OR_l0_l0 0xa0142000 | |
218 | #define SLLX_l0_32_l0 0xa12c3020 | 218 | #define SLLX_l0_32_l0 0xa12c3020 | |
219 | #define OR_l0_l1_l0 0xa0140011 | 219 | #define OR_l0_l1_l0 0xa0140011 | |
220 | #define JMPL_l0_o0 0x91c42000 | 220 | #define JMPL_l0_o0 0x91c42000 | |
221 | #define MOV_g1_o1 0x92100001 | 221 | #define MOV_g1_o1 0x92100001 | |
222 | 222 | |||
223 | void _rtld_install_plt(Elf_Word *, Elf_Addr); | 223 | void _rtld_install_plt(Elf_Word *, Elf_Addr); | |
224 | static inline int _rtld_relocate_plt_object(const Obj_Entry *, | 224 | static inline int _rtld_relocate_plt_object(const Obj_Entry *, | |
225 | const Elf_Rela *, Elf_Addr *); | 225 | const Elf_Rela *, Elf_Addr *); | |
226 | 226 | |||
227 | void | 227 | void | |
228 | _rtld_install_plt(Elf_Word *pltgot, Elf_Addr proc) | 228 | _rtld_install_plt(Elf_Word *pltgot, Elf_Addr proc) | |
229 | { | 229 | { | |
230 | pltgot[0] = SAVE; | 230 | pltgot[0] = SAVE; | |
231 | pltgot[1] = SETHI_l0 | HIVAL(proc, 42); | 231 | pltgot[1] = SETHI_l0 | HIVAL(proc, 42); | |
232 | pltgot[2] = SETHI_l1 | HIVAL(proc, 10); | 232 | pltgot[2] = SETHI_l1 | HIVAL(proc, 10); | |
233 | pltgot[3] = OR_l0_l0 | LOVAL(proc, 32); | 233 | pltgot[3] = OR_l0_l0 | LOVAL(proc, 32); | |
234 | pltgot[4] = SLLX_l0_32_l0; | 234 | pltgot[4] = SLLX_l0_32_l0; | |
235 | pltgot[5] = OR_l0_l1_l0; | 235 | pltgot[5] = OR_l0_l1_l0; | |
236 | pltgot[6] = JMPL_l0_o0 | LOVAL(proc, 0); | 236 | pltgot[6] = JMPL_l0_o0 | LOVAL(proc, 0); | |
237 | pltgot[7] = MOV_g1_o1; | 237 | pltgot[7] = MOV_g1_o1; | |
238 | } | 238 | } | |
239 | 239 | |||
240 | void | 240 | void | |
241 | _rtld_setup_pltgot(const Obj_Entry *obj) | 241 | _rtld_setup_pltgot(const Obj_Entry *obj) | |
242 | { | 242 | { | |
243 | /* | 243 | /* | |
244 | * On sparc64 we got troubles. | 244 | * On sparc64 we got troubles. | |
245 | * | 245 | * | |
246 | * Instructions are 4 bytes long. | 246 | * Instructions are 4 bytes long. | |
247 | * Elf[64]_Addr is 8 bytes long, so are our pltglot[] | 247 | * Elf[64]_Addr is 8 bytes long, so are our pltglot[] | |
248 | * array entries. | 248 | * array entries. | |
249 | * Each PLT entry jumps to PLT0 to enter the dynamic | 249 | * Each PLT entry jumps to PLT0 to enter the dynamic | |
250 | * linker. | 250 | * linker. | |
251 | * Loading an arbitrary 64-bit pointer takes 6 | 251 | * Loading an arbitrary 64-bit pointer takes 6 | |
252 | * instructions and 2 registers. | 252 | * instructions and 2 registers. | |
253 | * | 253 | * | |
254 | * Somehow we need to issue a save to get a new stack | 254 | * Somehow we need to issue a save to get a new stack | |
255 | * frame, load the address of the dynamic linker, and | 255 | * frame, load the address of the dynamic linker, and | |
256 | * jump there, in 8 instructions or less. | 256 | * jump there, in 8 instructions or less. | |
257 | * | 257 | * | |
258 | * Oh, we need to fill out both PLT0 and PLT1. | 258 | * Oh, we need to fill out both PLT0 and PLT1. | |
259 | */ | 259 | */ | |
260 | { | 260 | { | |
261 | Elf_Word *entry = (Elf_Word *)obj->pltgot; | 261 | Elf_Word *entry = (Elf_Word *)obj->pltgot; | |
262 | 262 | |||
263 | /* Install in entries 0 and 1 */ | 263 | /* Install in entries 0 and 1 */ | |
264 | _rtld_install_plt(&entry[0], (Elf_Addr) &_rtld_bind_start_0); | 264 | _rtld_install_plt(&entry[0], (Elf_Addr) &_rtld_bind_start_0); | |
265 | _rtld_install_plt(&entry[8], (Elf_Addr) &_rtld_bind_start_1); | 265 | _rtld_install_plt(&entry[8], (Elf_Addr) &_rtld_bind_start_1); | |
266 | 266 | |||
267 | /* | 267 | /* | |
268 | * Install the object reference in first slot | 268 | * Install the object reference in first slot | |
269 | * of entry 2. | 269 | * of entry 2. | |
270 | */ | 270 | */ | |
271 | obj->pltgot[8] = (Elf_Addr) obj; | 271 | obj->pltgot[8] = (Elf_Addr) obj; | |
272 | } | 272 | } | |
273 | } | 273 | } | |
274 | 274 | |||
275 | void | 275 | void | |
276 | _rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase) | 276 | _rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase) | |
277 | { | 277 | { | |
278 | const Elf_Rela *rela = 0, *relalim; | 278 | const Elf_Rela *rela = 0, *relalim; | |
279 | Elf_Addr relasz = 0; | 279 | Elf_Addr relasz = 0; | |
280 | Elf_Addr *where; | 280 | Elf_Addr *where; | |
281 | 281 | |||
282 | for (; dynp->d_tag != DT_NULL; dynp++) { | 282 | for (; dynp->d_tag != DT_NULL; dynp++) { | |
283 | switch (dynp->d_tag) { | 283 | switch (dynp->d_tag) { | |
284 | case DT_RELA: | 284 | case DT_RELA: | |
285 | rela = (const Elf_Rela *)(relocbase + dynp->d_un.d_ptr); | 285 | rela = (const Elf_Rela *)(relocbase + dynp->d_un.d_ptr); | |
286 | break; | 286 | break; | |
287 | case DT_RELASZ: | 287 | case DT_RELASZ: | |
288 | relasz = dynp->d_un.d_val; | 288 | relasz = dynp->d_un.d_val; | |
289 | break; | 289 | break; | |
290 | } | 290 | } | |
291 | } | 291 | } | |
292 | relalim = (const Elf_Rela *)((caddr_t)rela + relasz); | 292 | relalim = (const Elf_Rela *)((const uint8_t *)rela + relasz); | |
293 | for (; rela < relalim; rela++) { | 293 | for (; rela < relalim; rela++) { | |
294 | where = (Elf_Addr *)(relocbase + rela->r_offset); | 294 | where = (Elf_Addr *)(relocbase + rela->r_offset); | |
295 | *where = (Elf_Addr)(relocbase + rela->r_addend); | 295 | *where = (Elf_Addr)(relocbase + rela->r_addend); | |
296 | } | 296 | } | |
297 | } | 297 | } | |
298 | 298 | |||
299 | int | 299 | int | |
300 | _rtld_relocate_nonplt_objects(const Obj_Entry *obj) | 300 | _rtld_relocate_nonplt_objects(const Obj_Entry *obj) | |
301 | { | 301 | { | |
302 | const Elf_Rela *rela; | 302 | const Elf_Rela *rela; | |
303 | const Elf_Sym *def = NULL; | 303 | const Elf_Sym *def = NULL; | |
304 | const Obj_Entry *defobj = NULL; | 304 | const Obj_Entry *defobj = NULL; | |
305 | 305 | |||
306 | for (rela = obj->rela; rela < obj->relalim; rela++) { | 306 | for (rela = obj->rela; rela < obj->relalim; rela++) { | |
307 | Elf_Addr *where; | 307 | Elf_Addr *where; | |
308 | Elf_Word type; | 308 | Elf_Word type; | |
309 | Elf_Addr value = 0, mask; | 309 | Elf_Addr value = 0, mask; | |
310 | unsigned long symnum; | 310 | unsigned long symnum; | |
311 | 311 | |||
312 | where = (Elf_Addr *) (obj->relocbase + rela->r_offset); | 312 | where = (Elf_Addr *) (obj->relocbase + rela->r_offset); | |
313 | symnum = ELF_R_SYM(rela->r_info); | 313 | symnum = ELF_R_SYM(rela->r_info); | |
314 | 314 | |||
315 | type = ELF_R_TYPE(rela->r_info); | 315 | type = ELF_R_TYPE(rela->r_info); | |
316 | if (type == R_TYPE(NONE)) | 316 | if (type == R_TYPE(NONE)) | |
317 | continue; | 317 | continue; | |
318 | 318 | |||
319 | /* We do JMP_SLOTs in _rtld_bind() below */ | 319 | /* We do JMP_SLOTs in _rtld_bind() below */ | |
320 | if (type == R_TYPE(JMP_SLOT)) | 320 | if (type == R_TYPE(JMP_SLOT)) | |
321 | continue; | 321 | continue; | |
322 | 322 | |||
323 | /* COPY relocs are also handled elsewhere */ | 323 | /* COPY relocs are also handled elsewhere */ | |
324 | if (type == R_TYPE(COPY)) | 324 | if (type == R_TYPE(COPY)) | |
325 | continue; | 325 | continue; | |
326 | 326 | |||
327 | /* | 327 | /* | |
328 | * We use the fact that relocation types are an `enum' | 328 | * We use the fact that relocation types are an `enum' | |
329 | * Note: R_SPARC_UA16 is currently numerically largest. | 329 | * Note: R_SPARC_UA16 is currently numerically largest. | |
330 | */ | 330 | */ | |
331 | if (type > R_TYPE(UA16)) | 331 | if (type > R_TYPE(UA16)) | |
332 | return (-1); | 332 | return (-1); | |
333 | 333 | |||
334 | value = rela->r_addend; | 334 | value = rela->r_addend; | |
335 | 335 | |||
336 | /* | 336 | /* | |
337 | * Handle relative relocs here, as an optimization. | 337 | * Handle relative relocs here, as an optimization. | |
338 | */ | 338 | */ | |
339 | if (type == R_TYPE(RELATIVE)) { | 339 | if (type == R_TYPE(RELATIVE)) { | |
340 | *where = (Elf_Addr)(obj->relocbase + value); | 340 | *where = (Elf_Addr)(obj->relocbase + value); | |
341 | rdbg(("RELATIVE in %s --> %p", obj->path, | 341 | rdbg(("RELATIVE in %s --> %p", obj->path, | |
342 | (void *)*where)); | 342 | (void *)*where)); | |
343 | continue; | 343 | continue; | |
344 | } | 344 | } | |
345 | 345 | |||
346 | if (RELOC_RESOLVE_SYMBOL(type)) { | 346 | if (RELOC_RESOLVE_SYMBOL(type)) { | |
347 | 347 | |||
348 | /* Find the symbol */ | 348 | /* Find the symbol */ | |
349 | def = _rtld_find_symdef(symnum, obj, &defobj, | 349 | def = _rtld_find_symdef(symnum, obj, &defobj, | |
350 | false); | 350 | false); | |
351 | if (def == NULL) | 351 | if (def == NULL) | |
352 | return -1; | 352 | return -1; | |
353 | 353 | |||
354 | /* Add in the symbol's absolute address */ | 354 | /* Add in the symbol's absolute address */ | |
355 | value += (Elf_Addr)(defobj->relocbase + def->st_value); | 355 | value += (Elf_Addr)(defobj->relocbase + def->st_value); | |
356 | } | 356 | } | |
357 | 357 | |||
358 | if (RELOC_PC_RELATIVE(type)) { | 358 | if (RELOC_PC_RELATIVE(type)) { | |
359 | value -= (Elf_Addr)where; | 359 | value -= (Elf_Addr)where; | |
360 | } | 360 | } | |
361 | 361 | |||
362 | if (RELOC_BASE_RELATIVE(type)) { | 362 | if (RELOC_BASE_RELATIVE(type)) { | |
363 | /* | 363 | /* | |
364 | * Note that even though sparcs use `Elf_rela' | 364 | * Note that even though sparcs use `Elf_rela' | |
365 | * exclusively we still need the implicit memory addend | 365 | * exclusively we still need the implicit memory addend | |
366 | * in relocations referring to GOT entries. | 366 | * in relocations referring to GOT entries. | |
367 | * Undoubtedly, someone f*cked this up in the distant | 367 | * Undoubtedly, someone f*cked this up in the distant | |
368 | * past, and now we're stuck with it in the name of | 368 | * past, and now we're stuck with it in the name of | |
369 | * compatibility for all eternity.. | 369 | * compatibility for all eternity.. | |
370 | * | 370 | * | |
371 | * In any case, the implicit and explicit should be | 371 | * In any case, the implicit and explicit should be | |
372 | * mutually exclusive. We provide a check for that | 372 | * mutually exclusive. We provide a check for that | |
373 | * here. | 373 | * here. | |
374 | */ | 374 | */ | |
375 | #ifdef DIAGNOSTIC | 375 | #ifdef DIAGNOSTIC | |
376 | if (value != 0 && *where != 0) { | 376 | if (value != 0 && *where != 0) { | |
377 | xprintf("BASE_REL(%s): where=%p, *where 0x%lx, " | 377 | xprintf("BASE_REL(%s): where=%p, *where 0x%lx, " | |
378 | "addend=0x%lx, base %p\n", | 378 | "addend=0x%lx, base %p\n", | |
379 | obj->path, where, *where, | 379 | obj->path, where, *where, | |
380 | rela->r_addend, obj->relocbase); | 380 | rela->r_addend, obj->relocbase); | |
381 | } | 381 | } | |
382 | #endif | 382 | #endif | |
383 | /* XXXX -- apparently we ignore the preexisting value */ | 383 | /* XXXX -- apparently we ignore the preexisting value */ | |
384 | value += (Elf_Addr)(obj->relocbase); | 384 | value += (Elf_Addr)(obj->relocbase); | |
385 | } | 385 | } | |
386 | 386 | |||
387 | mask = RELOC_VALUE_BITMASK(type); | 387 | mask = RELOC_VALUE_BITMASK(type); | |
388 | value >>= RELOC_VALUE_RIGHTSHIFT(type); | 388 | value >>= RELOC_VALUE_RIGHTSHIFT(type); | |
389 | value &= mask; | 389 | value &= mask; | |
390 | 390 | |||
391 | if (RELOC_UNALIGNED(type)) { | 391 | if (RELOC_UNALIGNED(type)) { | |
392 | /* Handle unaligned relocations. */ | 392 | /* Handle unaligned relocations. */ | |
393 | Elf_Addr tmp = 0; | 393 | Elf_Addr tmp = 0; | |
394 | char *ptr = (char *)where; | 394 | char *ptr = (char *)where; | |
395 | int i, size = RELOC_TARGET_SIZE(type)/8; | 395 | int i, size = RELOC_TARGET_SIZE(type)/8; | |
396 | 396 | |||
397 | /* Read it in one byte at a time. */ | 397 | /* Read it in one byte at a time. */ | |
398 | for (i=0; i<size; i++) | 398 | for (i=0; i<size; i++) | |
399 | tmp = (tmp << 8) | ptr[i]; | 399 | tmp = (tmp << 8) | ptr[i]; | |
400 | 400 | |||
401 | tmp &= ~mask; | 401 | tmp &= ~mask; | |
402 | tmp |= value; | 402 | tmp |= value; | |
403 | 403 | |||
404 | /* Write it back out. */ | 404 | /* Write it back out. */ | |
405 | for (i=0; i<size; i++) | 405 | for (i=0; i<size; i++) | |
406 | ptr[i] = ((tmp >> (8*i)) & 0xff); | 406 | ptr[i] = ((tmp >> (8*i)) & 0xff); | |
407 | #ifdef RTLD_DEBUG_RELOC | 407 | #ifdef RTLD_DEBUG_RELOC | |
408 | value = (Elf_Addr)tmp; | 408 | value = (Elf_Addr)tmp; | |
409 | #endif | 409 | #endif | |
410 | 410 | |||
411 | } else if (RELOC_TARGET_SIZE(type) > 32) { | 411 | } else if (RELOC_TARGET_SIZE(type) > 32) { | |
412 | *where &= ~mask; | 412 | *where &= ~mask; | |
413 | *where |= value; | 413 | *where |= value; | |
414 | #ifdef RTLD_DEBUG_RELOC | 414 | #ifdef RTLD_DEBUG_RELOC | |
415 | value = (Elf_Addr)*where; | 415 | value = (Elf_Addr)*where; | |
416 | #endif | 416 | #endif | |
417 | } else { | 417 | } else { | |
418 | Elf32_Addr *where32 = (Elf32_Addr *)where; | 418 | Elf32_Addr *where32 = (Elf32_Addr *)where; | |
419 | 419 | |||
420 | *where32 &= ~mask; | 420 | *where32 &= ~mask; | |
421 | *where32 |= value; | 421 | *where32 |= value; | |
422 | #ifdef RTLD_DEBUG_RELOC | 422 | #ifdef RTLD_DEBUG_RELOC | |
423 | value = (Elf_Addr)*where32; | 423 | value = (Elf_Addr)*where32; | |
424 | #endif | 424 | #endif | |
425 | } | 425 | } | |
426 | 426 | |||
427 | #ifdef RTLD_DEBUG_RELOC | 427 | #ifdef RTLD_DEBUG_RELOC | |
428 | if (RELOC_RESOLVE_SYMBOL(type)) { | 428 | if (RELOC_RESOLVE_SYMBOL(type)) { | |
429 | rdbg(("%s %s in %s --> %p in %s", reloc_names[type], | 429 | rdbg(("%s %s in %s --> %p in %s", reloc_names[type], | |
430 | obj->strtab + obj->symtab[symnum].st_name, | 430 | obj->strtab + obj->symtab[symnum].st_name, | |
431 | obj->path, (void *)value, defobj->path)); | 431 | obj->path, (void *)value, defobj->path)); | |
432 | } else { | 432 | } else { | |
433 | rdbg(("%s in %s --> %p", reloc_names[type], | 433 | rdbg(("%s in %s --> %p", reloc_names[type], | |
434 | obj->path, (void *)value)); | 434 | obj->path, (void *)value)); | |
435 | } | 435 | } | |
436 | #endif | 436 | #endif | |
437 | } | 437 | } | |
438 | return (0); | 438 | return (0); | |
439 | } | 439 | } | |
440 | 440 | |||
441 | int | 441 | int | |
442 | _rtld_relocate_plt_lazy(const Obj_Entry *obj) | 442 | _rtld_relocate_plt_lazy(const Obj_Entry *obj) | |
443 | { | 443 | { | |
444 | return (0); | 444 | return (0); | |
445 | } | 445 | } | |
446 | 446 | |||
447 | caddr_t | 447 | caddr_t | |
448 | _rtld_bind(const Obj_Entry *obj, Elf_Word reloff) | 448 | _rtld_bind(const Obj_Entry *obj, Elf_Word reloff) | |
449 | { | 449 | { | |
450 | const Elf_Rela *rela = obj->pltrela + reloff; | 450 | const Elf_Rela *rela = obj->pltrela + reloff; | |
451 | Elf_Addr result; | 451 | Elf_Addr result; | |
452 | int err; | 452 | int err; | |
453 | 453 | |||
454 | result = 0; /* XXX gcc */ | 454 | result = 0; /* XXX gcc */ | |
455 | 455 | |||
456 | if (ELF_R_TYPE(obj->pltrela->r_info) == R_TYPE(JMP_SLOT)) { | 456 | if (ELF_R_TYPE(obj->pltrela->r_info) == R_TYPE(JMP_SLOT)) { | |
457 | /* | 457 | /* | |
458 | * XXXX | 458 | * XXXX | |
459 | * | 459 | * | |
460 | * The first four PLT entries are reserved. There is some | 460 | * The first four PLT entries are reserved. There is some | |
461 | * disagreement whether they should have associated relocation | 461 | * disagreement whether they should have associated relocation | |
462 | * entries. Both the SPARC 32-bit and 64-bit ELF | 462 | * entries. Both the SPARC 32-bit and 64-bit ELF | |
463 | * specifications say that they should have relocation entries, | 463 | * specifications say that they should have relocation entries, | |
464 | * but the 32-bit SPARC binutils do not generate them, and now | 464 | * but the 32-bit SPARC binutils do not generate them, and now | |
465 | * the 64-bit SPARC binutils have stopped generating them too. | 465 | * the 64-bit SPARC binutils have stopped generating them too. | |
466 | * | 466 | * | |
467 | * So, to provide binary compatibility, we will check the first | 467 | * So, to provide binary compatibility, we will check the first | |
468 | * entry, if it is reserved it should not be of the type | 468 | * entry, if it is reserved it should not be of the type | |
469 | * JMP_SLOT. If it is JMP_SLOT, then the 4 reserved entries | 469 | * JMP_SLOT. If it is JMP_SLOT, then the 4 reserved entries | |
470 | * were not generated and our index is 4 entries too far. | 470 | * were not generated and our index is 4 entries too far. | |
471 | */ | 471 | */ | |
472 | rela -= 4; | 472 | rela -= 4; | |
473 | } | 473 | } | |
474 | 474 | |||
475 | err = _rtld_relocate_plt_object(obj, rela, &result); | 475 | err = _rtld_relocate_plt_object(obj, rela, &result); | |
476 | if (err || result == 0) | 476 | if (err || result == 0) | |
477 | _rtld_die(); | 477 | _rtld_die(); | |
478 | 478 | |||
479 | return (caddr_t)result; | 479 | return (caddr_t)result; | |
480 | } | 480 | } | |
481 | 481 | |||
482 | int | 482 | int | |
483 | _rtld_relocate_plt_objects(const Obj_Entry *obj) | 483 | _rtld_relocate_plt_objects(const Obj_Entry *obj) | |
484 | { | 484 | { | |
485 | const Elf_Rela *rela; | 485 | const Elf_Rela *rela; | |
486 | 486 | |||
487 | rela = obj->pltrela; | 487 | rela = obj->pltrela; | |
488 | 488 | |||
489 | /* | 489 | /* | |
490 | * Check for first four reserved entries - and skip them. | 490 | * Check for first four reserved entries - and skip them. | |
491 | * See above for details. | 491 | * See above for details. | |
492 | */ | 492 | */ | |
493 | if (ELF_R_TYPE(obj->pltrela->r_info) != R_TYPE(JMP_SLOT)) | 493 | if (ELF_R_TYPE(obj->pltrela->r_info) != R_TYPE(JMP_SLOT)) | |
494 | rela += 4; | 494 | rela += 4; | |
495 | 495 | |||
496 | for (; rela < obj->pltrelalim; rela++) | 496 | for (; rela < obj->pltrelalim; rela++) | |
497 | if (_rtld_relocate_plt_object(obj, rela, NULL) < 0) | 497 | if (_rtld_relocate_plt_object(obj, rela, NULL) < 0) | |
498 | return -1; | 498 | return -1; | |
499 | 499 | |||
500 | return 0; | 500 | return 0; | |
501 | } | 501 | } | |
502 | 502 | |||
503 | /* | 503 | /* | |
504 | * New inline function that is called by _rtld_relocate_plt_object and | 504 | * New inline function that is called by _rtld_relocate_plt_object and | |
505 | * _rtld_bind | 505 | * _rtld_bind | |
506 | */ | 506 | */ | |
507 | static inline int | 507 | static inline int | |
508 | _rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, Elf_Addr *tp) | 508 | _rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, Elf_Addr *tp) | |
509 | { | 509 | { | |
510 | Elf_Word *where = (Elf_Word *)(obj->relocbase + rela->r_offset); | 510 | Elf_Word *where = (Elf_Word *)(obj->relocbase + rela->r_offset); | |
511 | const Elf_Sym *def; | 511 | const Elf_Sym *def; | |
512 | const Obj_Entry *defobj; | 512 | const Obj_Entry *defobj; | |
513 | Elf_Addr value, offset; | 513 | Elf_Addr value, offset; | |
514 | 514 | |||
515 | /* Fully resolve procedure addresses now */ | 515 | /* Fully resolve procedure addresses now */ | |
516 | 516 | |||
517 | assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT)); | 517 | assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT)); | |
518 | 518 | |||
519 | def = _rtld_find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, true); | 519 | def = _rtld_find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, true); | |
520 | if (def == NULL) | 520 | if (def == NULL) | |
521 | return -1; | 521 | return -1; | |
522 | 522 | |||
523 | value = (Elf_Addr)(defobj->relocbase + def->st_value); | 523 | value = (Elf_Addr)(defobj->relocbase + def->st_value); | |
524 | rdbg(("bind now/fixup in %s --> new=%p", | 524 | rdbg(("bind now/fixup in %s --> new=%p", | |
525 | defobj->strtab + def->st_name, (void *)value)); | 525 | defobj->strtab + def->st_name, (void *)value)); | |
526 | 526 | |||
527 | /* | 527 | /* | |
528 | * At the PLT entry pointed at by `where', we now construct | 528 | * At the PLT entry pointed at by `where', we now construct | |
529 | * a direct transfer to the now fully resolved function | 529 | * a direct transfer to the now fully resolved function | |
530 | * address. | 530 | * address. | |
531 | * | 531 | * | |
532 | * A PLT entry is supposed to start by looking like this: | 532 | * A PLT entry is supposed to start by looking like this: | |
533 | * | 533 | * | |
534 | * sethi %hi(. - .PLT0), %g1 | 534 | * sethi %hi(. - .PLT0), %g1 | |
535 | * ba,a %xcc, .PLT1 | 535 | * ba,a %xcc, .PLT1 | |
536 | * nop | 536 | * nop | |
537 | * nop | 537 | * nop | |
538 | * nop | 538 | * nop | |
539 | * nop | 539 | * nop | |
540 | * nop | 540 | * nop | |
541 | * nop | 541 | * nop | |
542 | * | 542 | * | |
543 | * When we replace these entries we start from the second | 543 | * When we replace these entries we start from the second | |
544 | * entry and do it in reverse order so the last thing we | 544 | * entry and do it in reverse order so the last thing we | |
545 | * do is replace the branch. That allows us to change this | 545 | * do is replace the branch. That allows us to change this | |
546 | * atomically. | 546 | * atomically. | |
547 | * | 547 | * | |
548 | * We now need to find out how far we need to jump. We | 548 | * We now need to find out how far we need to jump. We | |
549 | * have a choice of several different relocation techniques | 549 | * have a choice of several different relocation techniques | |
550 | * which are increasingly expensive. | 550 | * which are increasingly expensive. | |
551 | */ | 551 | */ | |
552 | 552 | |||
553 | offset = ((Elf_Addr)where) - value; | 553 | offset = ((Elf_Addr)where) - value; | |
554 | if (rela->r_addend) { | 554 | if (rela->r_addend) { | |
555 | Elf_Addr *ptr = (Elf_Addr *)where; | 555 | Elf_Addr *ptr = (Elf_Addr *)where; | |
556 | /* | 556 | /* | |
557 | * This entry is >=32768. The relocations points to a | 557 | * This entry is >=32768. The relocations points to a | |
558 | * PC-relative pointer to the bind_0 stub at the top of the | 558 | * PC-relative pointer to the bind_0 stub at the top of the | |
559 | * PLT section. Update it to point to the target function. | 559 | * PLT section. Update it to point to the target function. | |
560 | */ | 560 | */ | |
561 | ptr[0] += value - (Elf_Addr)obj->pltgot; | 561 | ptr[0] += value - (Elf_Addr)obj->pltgot; | |
562 | 562 | |||
563 | } else if (offset <= (1L<<20) && offset >= -(1L<<20)) { | 563 | } else if (offset <= (1L<<20) && offset >= -(1L<<20)) { | |
564 | /* | 564 | /* | |
565 | * We're within 1MB -- we can use a direct branch insn. | 565 | * We're within 1MB -- we can use a direct branch insn. | |
566 | * | 566 | * | |
567 | * We can generate this pattern: | 567 | * We can generate this pattern: | |
568 | * | 568 | * | |
569 | * sethi %hi(. - .PLT0), %g1 | 569 | * sethi %hi(. - .PLT0), %g1 | |
570 | * ba,a %xcc, addr | 570 | * ba,a %xcc, addr | |
571 | * nop | 571 | * nop | |
572 | * nop | 572 | * nop | |
573 | * nop | 573 | * nop | |
574 | * nop | 574 | * nop | |
575 | * nop | 575 | * nop | |
576 | * nop | 576 | * nop | |
577 | * | 577 | * | |
578 | */ | 578 | */ | |
579 | where[1] = BAA | ((offset >> 2) &0x3fffff); | 579 | where[1] = BAA | ((offset >> 2) &0x3fffff); | |
580 | __asm volatile("iflush %0+4" : : "r" (where)); | 580 | __asm volatile("iflush %0+4" : : "r" (where)); | |
581 | } else if (value >= 0 && value < (1L<<32)) { | 581 | } else if (value >= 0 && value < (1L<<32)) { | |
582 | /* | 582 | /* | |
583 | * We're within 32-bits of address zero. | 583 | * We're within 32-bits of address zero. | |
584 | * | 584 | * | |
585 | * The resulting code in the jump slot is: | 585 | * The resulting code in the jump slot is: | |
586 | * | 586 | * | |
587 | * sethi %hi(. - .PLT0), %g1 | 587 | * sethi %hi(. - .PLT0), %g1 | |
588 | * sethi %hi(addr), %g1 | 588 | * sethi %hi(addr), %g1 | |
589 | * jmp %g1+%lo(addr) | 589 | * jmp %g1+%lo(addr) | |
590 | * nop | 590 | * nop | |
591 | * nop | 591 | * nop | |
592 | * nop | 592 | * nop | |
593 | * nop | 593 | * nop | |
594 | * nop | 594 | * nop | |
595 | * | 595 | * | |
596 | */ | 596 | */ | |
597 | where[2] = JMP | LOVAL(value, 0); | 597 | where[2] = JMP | LOVAL(value, 0); | |
598 | where[1] = SETHI | HIVAL(value, 10); | 598 | where[1] = SETHI | HIVAL(value, 10); | |
599 | __asm volatile("iflush %0+8" : : "r" (where)); | 599 | __asm volatile("iflush %0+8" : : "r" (where)); | |
600 | __asm volatile("iflush %0+4" : : "r" (where)); | 600 | __asm volatile("iflush %0+4" : : "r" (where)); | |
601 | 601 | |||
602 | } else if (value <= 0 && value > -(1L<<32)) { | 602 | } else if (value <= 0 && value > -(1L<<32)) { | |
603 | /* | 603 | /* | |
604 | * We're within 32-bits of address -1. | 604 | * We're within 32-bits of address -1. | |
605 | * | 605 | * | |
606 | * The resulting code in the jump slot is: | 606 | * The resulting code in the jump slot is: | |
607 | * | 607 | * | |
608 | * sethi %hi(. - .PLT0), %g1 | 608 | * sethi %hi(. - .PLT0), %g1 | |
609 | * sethi %hix(addr), %g1 | 609 | * sethi %hix(addr), %g1 | |
610 | * xor %g1, %lox(addr), %g1 | 610 | * xor %g1, %lox(addr), %g1 | |
611 | * jmp %g1 | 611 | * jmp %g1 | |
612 | * nop | 612 | * nop | |
613 | * nop | 613 | * nop | |
614 | * nop | 614 | * nop | |
615 | * nop | 615 | * nop | |
616 | * | 616 | * | |
617 | */ | 617 | */ | |
618 | where[3] = JMP; | 618 | where[3] = JMP; | |
619 | where[2] = XOR | ((~value) & 0x00001fff); | 619 | where[2] = XOR | ((~value) & 0x00001fff); | |
620 | where[1] = SETHI | HIVAL(~value, 10); | 620 | where[1] = SETHI | HIVAL(~value, 10); | |
621 | __asm volatile("iflush %0+12" : : "r" (where)); | 621 | __asm volatile("iflush %0+12" : : "r" (where)); | |
622 | __asm volatile("iflush %0+8" : : "r" (where)); | 622 | __asm volatile("iflush %0+8" : : "r" (where)); | |
623 | __asm volatile("iflush %0+4" : : "r" (where)); | 623 | __asm volatile("iflush %0+4" : : "r" (where)); | |
624 | 624 | |||
625 | } else if (offset <= (1L<<32) && offset >= -((1L<<32) - 4)) { | 625 | } else if (offset <= (1L<<32) && offset >= -((1L<<32) - 4)) { | |
626 | /* | 626 | /* | |
627 | * We're within 32-bits -- we can use a direct call insn | 627 | * We're within 32-bits -- we can use a direct call insn | |
628 | * | 628 | * | |
629 | * The resulting code in the jump slot is: | 629 | * The resulting code in the jump slot is: | |
630 | * | 630 | * | |
631 | * sethi %hi(. - .PLT0), %g1 | 631 | * sethi %hi(. - .PLT0), %g1 | |
632 | * mov %o7, %g1 | 632 | * mov %o7, %g1 | |
633 | * call (.+offset) | 633 | * call (.+offset) | |
634 | * mov %g1, %o7 | 634 | * mov %g1, %o7 | |
635 | * nop | 635 | * nop | |
636 | * nop | 636 | * nop | |
637 | * nop | 637 | * nop | |
638 | * nop | 638 | * nop | |
639 | * | 639 | * | |
640 | */ | 640 | */ | |
641 | where[3] = MOV17; | 641 | where[3] = MOV17; | |
642 | where[2] = CALL | ((offset >> 4) & 0x3fffffff); | 642 | where[2] = CALL | ((offset >> 4) & 0x3fffffff); | |
643 | where[1] = MOV71; | 643 | where[1] = MOV71; | |
644 | __asm volatile("iflush %0+12" : : "r" (where)); | 644 | __asm volatile("iflush %0+12" : : "r" (where)); | |
645 | __asm volatile("iflush %0+8" : : "r" (where)); | 645 | __asm volatile("iflush %0+8" : : "r" (where)); | |
646 | __asm volatile("iflush %0+4" : : "r" (where)); | 646 | __asm volatile("iflush %0+4" : : "r" (where)); | |
647 | 647 | |||
648 | } else if (offset >= 0 && offset < (1L<<44)) { | 648 | } else if (offset >= 0 && offset < (1L<<44)) { | |
649 | /* | 649 | /* | |
650 | * We're within 44 bits. We can generate this pattern: | 650 | * We're within 44 bits. We can generate this pattern: | |
651 | * | 651 | * | |
652 | * The resulting code in the jump slot is: | 652 | * The resulting code in the jump slot is: | |
653 | * | 653 | * | |
654 | * sethi %hi(. - .PLT0), %g1 | 654 | * sethi %hi(. - .PLT0), %g1 | |
655 | * sethi %h44(addr), %g1 | 655 | * sethi %h44(addr), %g1 | |
656 | * or %g1, %m44(addr), %g1 | 656 | * or %g1, %m44(addr), %g1 | |
657 | * sllx %g1, 12, %g1 | 657 | * sllx %g1, 12, %g1 | |
658 | * jmp %g1+%l44(addr) | 658 | * jmp %g1+%l44(addr) | |
659 | * nop | 659 | * nop | |
660 | * nop | 660 | * nop | |
661 | * nop | 661 | * nop | |
662 | * | 662 | * | |
663 | */ | 663 | */ | |
664 | where[4] = JMP | LOVAL(offset, 0); | 664 | where[4] = JMP | LOVAL(offset, 0); | |
665 | where[3] = SLLX | 12; | 665 | where[3] = SLLX | 12; | |
666 | where[2] = OR | (((offset) >> 12) & 0x00001fff); | 666 | where[2] = OR | (((offset) >> 12) & 0x00001fff); | |
667 | where[1] = SETHI | HIVAL(offset, 22); | 667 | where[1] = SETHI | HIVAL(offset, 22); | |
668 | __asm volatile("iflush %0+16" : : "r" (where)); | 668 | __asm volatile("iflush %0+16" : : "r" (where)); | |
669 | __asm volatile("iflush %0+12" : : "r" (where)); | 669 | __asm volatile("iflush %0+12" : : "r" (where)); | |
670 | __asm volatile("iflush %0+8" : : "r" (where)); | 670 | __asm volatile("iflush %0+8" : : "r" (where)); | |
671 | __asm volatile("iflush %0+4" : : "r" (where)); | 671 | __asm volatile("iflush %0+4" : : "r" (where)); | |
672 | 672 | |||
673 | } else if (offset < 0 && offset > -(1L<<44)) { | 673 | } else if (offset < 0 && offset > -(1L<<44)) { | |
674 | /* | 674 | /* | |
675 | * We're within 44 bits. We can generate this pattern: | 675 | * We're within 44 bits. We can generate this pattern: | |
676 | * | 676 | * | |
677 | * The resulting code in the jump slot is: | 677 | * The resulting code in the jump slot is: | |
678 | * | 678 | * | |
679 | * sethi %hi(. - .PLT0), %g1 | 679 | * sethi %hi(. - .PLT0), %g1 | |
680 | * sethi %h44(-addr), %g1 | 680 | * sethi %h44(-addr), %g1 | |
681 | * xor %g1, %m44(-addr), %g1 | 681 | * xor %g1, %m44(-addr), %g1 | |
682 | * sllx %g1, 12, %g1 | 682 | * sllx %g1, 12, %g1 | |
683 | * jmp %g1+%l44(addr) | 683 | * jmp %g1+%l44(addr) | |
684 | * nop | 684 | * nop | |
685 | * nop | 685 | * nop | |
686 | * nop | 686 | * nop | |
687 | * | 687 | * | |
688 | */ | 688 | */ | |
689 | where[4] = JMP | LOVAL(offset, 0); | 689 | where[4] = JMP | LOVAL(offset, 0); | |
690 | where[3] = SLLX | 12; | 690 | where[3] = SLLX | 12; | |
691 | where[2] = XOR | (((~offset) >> 12) & 0x00001fff); | 691 | where[2] = XOR | (((~offset) >> 12) & 0x00001fff); | |
692 | where[1] = SETHI | HIVAL(~offset, 22); | 692 | where[1] = SETHI | HIVAL(~offset, 22); | |
693 | __asm volatile("iflush %0+16" : : "r" (where)); | 693 | __asm volatile("iflush %0+16" : : "r" (where)); | |
694 | __asm volatile("iflush %0+12" : : "r" (where)); | 694 | __asm volatile("iflush %0+12" : : "r" (where)); | |
695 | __asm volatile("iflush %0+8" : : "r" (where)); | 695 | __asm volatile("iflush %0+8" : : "r" (where)); | |
696 | __asm volatile("iflush %0+4" : : "r" (where)); | 696 | __asm volatile("iflush %0+4" : : "r" (where)); | |
697 | 697 | |||
698 | } else { | 698 | } else { | |
699 | /* | 699 | /* | |
700 | * We need to load all 64-bits | 700 | * We need to load all 64-bits | |
701 | * | 701 | * | |
702 | * The resulting code in the jump slot is: | 702 | * The resulting code in the jump slot is: | |
703 | * | 703 | * | |
704 | * sethi %hi(. - .PLT0), %g1 | 704 | * sethi %hi(. - .PLT0), %g1 | |
705 | * sethi %hh(addr), %g1 | 705 | * sethi %hh(addr), %g1 | |
706 | * sethi %lm(addr), %g5 | 706 | * sethi %lm(addr), %g5 | |
707 | * or %g1, %hm(addr), %g1 | 707 | * or %g1, %hm(addr), %g1 | |
708 | * sllx %g1, 32, %g1 | 708 | * sllx %g1, 32, %g1 | |
709 | * or %g1, %g5, %g1 | 709 | * or %g1, %g5, %g1 | |
710 | * jmp %g1+%lo(addr) | 710 | * jmp %g1+%lo(addr) | |
711 | * nop | 711 | * nop | |
712 | * | 712 | * | |
713 | */ | 713 | */ | |
714 | where[6] = JMP | LOVAL(value, 0); | 714 | where[6] = JMP | LOVAL(value, 0); | |
715 | where[5] = ORG5; | 715 | where[5] = ORG5; | |
716 | where[4] = SLLX | 32; | 716 | where[4] = SLLX | 32; | |
717 | where[3] = OR | LOVAL(value, 32); | 717 | where[3] = OR | LOVAL(value, 32); | |
718 | where[2] = SETHIG5 | HIVAL(value, 10); | 718 | where[2] = SETHIG5 | HIVAL(value, 10); | |
719 | where[1] = SETHI | HIVAL(value, 42); | 719 | where[1] = SETHI | HIVAL(value, 42); | |
720 | __asm volatile("iflush %0+24" : : "r" (where)); | 720 | __asm volatile("iflush %0+24" : : "r" (where)); | |
721 | __asm volatile("iflush %0+20" : : "r" (where)); | 721 | __asm volatile("iflush %0+20" : : "r" (where)); | |
722 | __asm volatile("iflush %0+16" : : "r" (where)); | 722 | __asm volatile("iflush %0+16" : : "r" (where)); | |
723 | __asm volatile("iflush %0+12" : : "r" (where)); | 723 | __asm volatile("iflush %0+12" : : "r" (where)); | |
724 | __asm volatile("iflush %0+8" : : "r" (where)); | 724 | __asm volatile("iflush %0+8" : : "r" (where)); | |
725 | __asm volatile("iflush %0+4" : : "r" (where)); | 725 | __asm volatile("iflush %0+4" : : "r" (where)); | |
726 | 726 | |||
727 | } | 727 | } | |
728 | 728 | |||
729 | if (tp) | 729 | if (tp) | |
730 | *tp = value; | 730 | *tp = value; | |
731 | 731 | |||
732 | return 0; | 732 | return 0; | |
733 | } | 733 | } |
--- src/libexec/ld.elf_so/arch/vax/mdreloc.c 2008/07/24 06:51:59 1.23
+++ src/libexec/ld.elf_so/arch/vax/mdreloc.c 2009/03/16 02:46:48 1.24
@@ -1,205 +1,205 @@ | @@ -1,205 +1,205 @@ | |||
1 | /* $NetBSD: mdreloc.c,v 1.23 2008/07/24 06:51:59 skrll Exp $ */ | 1 | /* $NetBSD: mdreloc.c,v 1.24 2009/03/16 02:46:48 lukem Exp $ */ | |
2 | 2 | |||
3 | #include <sys/cdefs.h> | 3 | #include <sys/cdefs.h> | |
4 | #ifndef lint | 4 | #ifndef lint | |
5 | __RCSID("$NetBSD: mdreloc.c,v 1.23 2008/07/24 06:51:59 skrll Exp $"); | 5 | __RCSID("$NetBSD: mdreloc.c,v 1.24 2009/03/16 02:46:48 lukem Exp $"); | |
6 | #endif /* not lint */ | 6 | #endif /* not lint */ | |
7 | 7 | |||
8 | #include <sys/cdefs.h> | 8 | #include <sys/cdefs.h> | |
9 | #ifndef lint | 9 | #ifndef lint | |
10 | __RCSID("$NetBSD: mdreloc.c,v 1.23 2008/07/24 06:51:59 skrll Exp $"); | 10 | __RCSID("$NetBSD: mdreloc.c,v 1.24 2009/03/16 02:46:48 lukem Exp $"); | |
11 | #endif /* not lint */ | 11 | #endif /* not lint */ | |
12 | 12 | |||
13 | #include <sys/types.h> | 13 | #include <sys/types.h> | |
14 | #include <sys/stat.h> | 14 | #include <sys/stat.h> | |
15 | 15 | |||
16 | #include "debug.h" | 16 | #include "debug.h" | |
17 | #include "rtld.h" | 17 | #include "rtld.h" | |
18 | 18 | |||
19 | void _rtld_bind_start(void); | 19 | void _rtld_bind_start(void); | |
20 | void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr); | 20 | void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr); | |
21 | caddr_t _rtld_bind(const Obj_Entry *, Elf_Word); | 21 | caddr_t _rtld_bind(const Obj_Entry *, Elf_Word); | |
22 | static inline int _rtld_relocate_plt_object(const Obj_Entry *, | 22 | static inline int _rtld_relocate_plt_object(const Obj_Entry *, | |
23 | const Elf_Rela *, Elf_Addr *); | 23 | const Elf_Rela *, Elf_Addr *); | |
24 | 24 | |||
25 | void | 25 | void | |
26 | _rtld_setup_pltgot(const Obj_Entry *obj) | 26 | _rtld_setup_pltgot(const Obj_Entry *obj) | |
27 | { | 27 | { | |
28 | obj->pltgot[1] = (Elf_Addr) obj; | 28 | obj->pltgot[1] = (Elf_Addr) obj; | |
29 | obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start; | 29 | obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start; | |
30 | } | 30 | } | |
31 | 31 | |||
32 | void | 32 | void | |
33 | _rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase) | 33 | _rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase) | |
34 | { | 34 | { | |
35 | const Elf_Rela *rela = 0, *relalim; | 35 | const Elf_Rela *rela = 0, *relalim; | |
36 | Elf_Addr relasz = 0; | 36 | Elf_Addr relasz = 0; | |
37 | Elf_Addr *where; | 37 | Elf_Addr *where; | |
38 | 38 | |||
39 | for (; dynp->d_tag != DT_NULL; dynp++) { | 39 | for (; dynp->d_tag != DT_NULL; dynp++) { | |
40 | switch (dynp->d_tag) { | 40 | switch (dynp->d_tag) { | |
41 | case DT_RELA: | 41 | case DT_RELA: | |
42 | rela = (const Elf_Rela *)(relocbase + dynp->d_un.d_ptr); | 42 | rela = (const Elf_Rela *)(relocbase + dynp->d_un.d_ptr); | |
43 | break; | 43 | break; | |
44 | case DT_RELASZ: | 44 | case DT_RELASZ: | |
45 | relasz = dynp->d_un.d_val; | 45 | relasz = dynp->d_un.d_val; | |
46 | break; | 46 | break; | |
47 | } | 47 | } | |
48 | } | 48 | } | |
49 | relalim = (const Elf_Rela *)((caddr_t)rela + relasz); | 49 | relalim = (const Elf_Rela *)((const uint8_t *)rela + relasz); | |
50 | for (; rela < relalim; rela++) { | 50 | for (; rela < relalim; rela++) { | |
51 | where = (Elf_Addr *)(relocbase + rela->r_offset); | 51 | where = (Elf_Addr *)(relocbase + rela->r_offset); | |
52 | *where = (Elf_Addr)(relocbase + rela->r_addend); | 52 | *where = (Elf_Addr)(relocbase + rela->r_addend); | |
53 | } | 53 | } | |
54 | } | 54 | } | |
55 | 55 | |||
56 | int | 56 | int | |
57 | _rtld_relocate_nonplt_objects(const Obj_Entry *obj) | 57 | _rtld_relocate_nonplt_objects(const Obj_Entry *obj) | |
58 | { | 58 | { | |
59 | const Elf_Rela *rela; | 59 | const Elf_Rela *rela; | |
60 | 60 | |||
61 | for (rela = obj->rela; rela < obj->relalim; rela++) { | 61 | for (rela = obj->rela; rela < obj->relalim; rela++) { | |
62 | Elf_Addr *where; | 62 | Elf_Addr *where; | |
63 | const Elf_Sym *def; | 63 | const Elf_Sym *def; | |
64 | const Obj_Entry *defobj; | 64 | const Obj_Entry *defobj; | |
65 | Elf_Addr tmp; | 65 | Elf_Addr tmp; | |
66 | unsigned long symnum; | 66 | unsigned long symnum; | |
67 | 67 | |||
68 | where = (Elf_Addr *)(obj->relocbase + rela->r_offset); | 68 | where = (Elf_Addr *)(obj->relocbase + rela->r_offset); | |
69 | symnum = ELF_R_SYM(rela->r_info); | 69 | symnum = ELF_R_SYM(rela->r_info); | |
70 | 70 | |||
71 | switch (ELF_R_TYPE(rela->r_info)) { | 71 | switch (ELF_R_TYPE(rela->r_info)) { | |
72 | case R_TYPE(NONE): | 72 | case R_TYPE(NONE): | |
73 | break; | 73 | break; | |
74 | 74 | |||
75 | case R_TYPE(32): /* word32 S + A */ | 75 | case R_TYPE(32): /* word32 S + A */ | |
76 | case R_TYPE(GLOB_DAT): /* word32 S + A */ | 76 | case R_TYPE(GLOB_DAT): /* word32 S + A */ | |
77 | def = _rtld_find_symdef(symnum, obj, &defobj, false); | 77 | def = _rtld_find_symdef(symnum, obj, &defobj, false); | |
78 | if (def == NULL) | 78 | if (def == NULL) | |
79 | return -1; | 79 | return -1; | |
80 | 80 | |||
81 | tmp = (Elf_Addr)(defobj->relocbase + def->st_value + | 81 | tmp = (Elf_Addr)(defobj->relocbase + def->st_value + | |
82 | rela->r_addend); | 82 | rela->r_addend); | |
83 | 83 | |||
84 | if (*where != tmp) | 84 | if (*where != tmp) | |
85 | *where = tmp; | 85 | *where = tmp; | |
86 | rdbg(("32/GLOB_DAT %s in %s --> %p in %s", | 86 | rdbg(("32/GLOB_DAT %s in %s --> %p in %s", | |
87 | obj->strtab + obj->symtab[symnum].st_name, | 87 | obj->strtab + obj->symtab[symnum].st_name, | |
88 | obj->path, (void *)*where, defobj->path)); | 88 | obj->path, (void *)*where, defobj->path)); | |
89 | break; | 89 | break; | |
90 | 90 | |||
91 | case R_TYPE(RELATIVE): /* word32 B + A */ | 91 | case R_TYPE(RELATIVE): /* word32 B + A */ | |
92 | tmp = (Elf_Addr)(obj->relocbase + rela->r_addend); | 92 | tmp = (Elf_Addr)(obj->relocbase + rela->r_addend); | |
93 | if (*where != tmp) | 93 | if (*where != tmp) | |
94 | *where = tmp; | 94 | *where = tmp; | |
95 | rdbg(("RELATIVE in %s --> %p", obj->path, | 95 | rdbg(("RELATIVE in %s --> %p", obj->path, | |
96 | (void *)*where)); | 96 | (void *)*where)); | |
97 | break; | 97 | break; | |
98 | 98 | |||
99 | case R_TYPE(COPY): | 99 | case R_TYPE(COPY): | |
100 | /* | 100 | /* | |
101 | * These are deferred until all other relocations have | 101 | * These are deferred until all other relocations have | |
102 | * been done. All we do here is make sure that the | 102 | * been done. All we do here is make sure that the | |
103 | * COPY relocation is not in a shared library. They | 103 | * COPY relocation is not in a shared library. They | |
104 | * are allowed only in executable files. | 104 | * are allowed only in executable files. | |
105 | */ | 105 | */ | |
106 | if (obj->isdynamic) { | 106 | if (obj->isdynamic) { | |
107 | _rtld_error( | 107 | _rtld_error( | |
108 | "%s: Unexpected R_COPY relocation in shared library", | 108 | "%s: Unexpected R_COPY relocation in shared library", | |
109 | obj->path); | 109 | obj->path); | |
110 | return -1; | 110 | return -1; | |
111 | } | 111 | } | |
112 | rdbg(("COPY (avoid in main)")); | 112 | rdbg(("COPY (avoid in main)")); | |
113 | break; | 113 | break; | |
114 | 114 | |||
115 | default: | 115 | default: | |
116 | rdbg(("sym = %lu, type = %lu, offset = %p, " | 116 | rdbg(("sym = %lu, type = %lu, offset = %p, " | |
117 | "addend = %p, contents = %p, symbol = %s", | 117 | "addend = %p, contents = %p, symbol = %s", | |
118 | symnum, (u_long)ELF_R_TYPE(rela->r_info), | 118 | symnum, (u_long)ELF_R_TYPE(rela->r_info), | |
119 | (void *)rela->r_offset, (void *)rela->r_addend, | 119 | (void *)rela->r_offset, (void *)rela->r_addend, | |
120 | (void *)*where, | 120 | (void *)*where, | |
121 | obj->strtab + obj->symtab[symnum].st_name)); | 121 | obj->strtab + obj->symtab[symnum].st_name)); | |
122 | _rtld_error("%s: Unsupported relocation type %ld " | 122 | _rtld_error("%s: Unsupported relocation type %ld " | |
123 | "in non-PLT relocations\n", | 123 | "in non-PLT relocations\n", | |
124 | obj->path, (u_long) ELF_R_TYPE(rela->r_info)); | 124 | obj->path, (u_long) ELF_R_TYPE(rela->r_info)); | |
125 | return -1; | 125 | return -1; | |
126 | } | 126 | } | |
127 | } | 127 | } | |
128 | return 0; | 128 | return 0; | |
129 | } | 129 | } | |
130 | 130 | |||
131 | int | 131 | int | |
132 | _rtld_relocate_plt_lazy(const Obj_Entry *obj) | 132 | _rtld_relocate_plt_lazy(const Obj_Entry *obj) | |
133 | { | 133 | { | |
134 | const Elf_Rela *rela; | 134 | const Elf_Rela *rela; | |
135 | 135 | |||
136 | if (!obj->relocbase) | 136 | if (!obj->relocbase) | |
137 | return 0; | 137 | return 0; | |
138 | 138 | |||
139 | for (rela = obj->pltrela; rela < obj->pltrelalim; rela++) { | 139 | for (rela = obj->pltrela; rela < obj->pltrelalim; rela++) { | |
140 | Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); | 140 | Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); | |
141 | 141 | |||
142 | assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT)); | 142 | assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT)); | |
143 | 143 | |||
144 | /* Just relocate the GOT slots pointing into the PLT */ | 144 | /* Just relocate the GOT slots pointing into the PLT */ | |
145 | *where += (Elf_Addr)obj->relocbase; | 145 | *where += (Elf_Addr)obj->relocbase; | |
146 | rdbg(("fixup !main in %s --> %p", obj->path, (void *)*where)); | 146 | rdbg(("fixup !main in %s --> %p", obj->path, (void *)*where)); | |
147 | } | 147 | } | |
148 | 148 | |||
149 | return 0; | 149 | return 0; | |
150 | } | 150 | } | |
151 | 151 | |||
152 | static inline int | 152 | static inline int | |
153 | _rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, Elf_Addr *tp) | 153 | _rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, Elf_Addr *tp) | |
154 | { | 154 | { | |
155 | Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); | 155 | Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); | |
156 | Elf_Addr new_value; | 156 | Elf_Addr new_value; | |
157 | const Elf_Sym *def; | 157 | const Elf_Sym *def; | |
158 | const Obj_Entry *defobj; | 158 | const Obj_Entry *defobj; | |
159 | 159 | |||
160 | assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT)); | 160 | assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT)); | |
161 | 161 | |||
162 | def = _rtld_find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, true); | 162 | def = _rtld_find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, true); | |
163 | if (def == NULL) | 163 | if (def == NULL) | |
164 | return -1; | 164 | return -1; | |
165 | 165 | |||
166 | new_value = (Elf_Addr)(defobj->relocbase + def->st_value + | 166 | new_value = (Elf_Addr)(defobj->relocbase + def->st_value + | |
167 | rela->r_addend); | 167 | rela->r_addend); | |
168 | rdbg(("bind now/fixup in %s --> old=%p new=%p", | 168 | rdbg(("bind now/fixup in %s --> old=%p new=%p", | |
169 | defobj->strtab + def->st_name, (void *)*where, (void *)new_value)); | 169 | defobj->strtab + def->st_name, (void *)*where, (void *)new_value)); | |
170 | if (*where != new_value) | 170 | if (*where != new_value) | |
171 | *where = new_value; | 171 | *where = new_value; | |
172 | 172 | |||
173 | if (tp) | 173 | if (tp) | |
174 | *tp = new_value - rela->r_addend; | 174 | *tp = new_value - rela->r_addend; | |
175 | 175 | |||
176 | return 0; | 176 | return 0; | |
177 | } | 177 | } | |
178 | 178 | |||
179 | caddr_t | 179 | caddr_t | |
180 | _rtld_bind(const Obj_Entry *obj, Elf_Word reloff) | 180 | _rtld_bind(const Obj_Entry *obj, Elf_Word reloff) | |
181 | { | 181 | { | |
182 | const Elf_Rela *rela = (const Elf_Rela *)((caddr_t)obj->pltrela + reloff); | 182 | const Elf_Rela *rela = (const Elf_Rela *)((const uint8_t *)obj->pltrela + reloff); | |
183 | Elf_Addr result; | 183 | Elf_Addr result; | |
184 | int err; | 184 | int err; | |
185 | 185 | |||
186 | result = 0; /* XXX gcc */ | 186 | result = 0; /* XXX gcc */ | |
187 | 187 | |||
188 | err = _rtld_relocate_plt_object(obj, rela, &result); | 188 | err = _rtld_relocate_plt_object(obj, rela, &result); | |
189 | if (err || result == 0) | 189 | if (err || result == 0) | |
190 | _rtld_die(); | 190 | _rtld_die(); | |
191 | 191 | |||
192 | return (caddr_t)result; | 192 | return (caddr_t)result; | |
193 | } | 193 | } | |
194 | 194 | |||
195 | int | 195 | int | |
196 | _rtld_relocate_plt_objects(const Obj_Entry *obj) | 196 | _rtld_relocate_plt_objects(const Obj_Entry *obj) | |
197 | { | 197 | { | |
198 | const Elf_Rela *rela; | 198 | const Elf_Rela *rela; | |
199 | 199 | |||
200 | for (rela = obj->pltrela; rela < obj->pltrelalim; rela++) | 200 | for (rela = obj->pltrela; rela < obj->pltrelalim; rela++) | |
201 | if (_rtld_relocate_plt_object(obj, rela, NULL) < 0) | 201 | if (_rtld_relocate_plt_object(obj, rela, NULL) < 0) | |
202 | return -1; | 202 | return -1; | |
203 | 203 | |||
204 | return 0; | 204 | return 0; | |
205 | } | 205 | } |