vfs: check userland buffers before reading them.
[haiku.git] / src / system / runtime_loader / arch / m68k / arch_relocate.cpp
blobae8510ee295dec63eaa4a9b108df036b8a6c4f5a
1 /*
2 * Copyright 2003-2006, Axel Dörfler, axeld@pinc-software.de
3 * Distributed under the terms of the MIT License.
5 * Copyright 2001, Travis Geiselbrecht. All rights reserved.
6 * Copyright 2002, Manuel J. Petit. All rights reserved.
7 * Distributed under the terms of the NewOS License.
8 */
11 #include "runtime_loader_private.h"
13 #include <runtime_loader.h>
15 #include <string.h>
16 #include <stdio.h>
17 #include <stdlib.h>
20 //#define TRACE_RLD
21 #ifdef TRACE_RLD
22 # define TRACE(x) dprintf x
23 #else
24 # define TRACE(x) ;
25 #endif
28 static inline void
29 write_32(addr_t *P, Elf32_Word value)
31 *(Elf32_Word*)P = value;
35 static inline void
36 write_16(addr_t *P, Elf32_Word value)
38 // bits 16:29
39 *(Elf32_Half*)P = (Elf32_Half)value;
43 static inline bool
44 write_16_check(addr_t *P, Elf32_Word value)
46 // bits 15:0
47 if ((value & 0xffff0000) && (~value & 0xffff8000))
48 return false;
49 *(Elf32_Half*)P = (Elf32_Half)value;
50 return true;
54 static inline bool
55 write_8(addr_t *P, Elf32_Word value)
57 // bits 7:0
58 *(uint8 *)P = (uint8)value;
59 return true;
63 static inline bool
64 write_8_check(addr_t *P, Elf32_Word value)
66 // bits 7:0
67 if ((value & 0xffffff00) && (~value & 0xffffff80))
68 return false;
69 *(uint8 *)P = (uint8)value;
70 return true;
74 static int
75 relocate_rela(image_t *rootImage, image_t *image, Elf32_Rela *rel, int rel_len,
76 SymbolLookupCache* cache)
78 int i;
79 addr_t S;
80 addr_t final_val;
82 # define P ((addr_t *)(image->regions[0].delta + rel[i].r_offset))
83 //# define A (*(P))
84 #define A ((addr_t)rel[i].r_addend)
85 # define B (image->regions[0].delta)
87 for (i = 0; i * (int)sizeof(Elf32_Rel) < rel_len; i++) {
88 unsigned type = ELF32_R_TYPE(rel[i].r_info);
90 switch (type) {
91 case R_68K_32:
92 case R_68K_16:
93 case R_68K_8:
94 case R_68K_PC32:
95 case R_68K_PC16:
96 case R_68K_PC8:
97 case R_68K_GLOB_DAT:
98 case R_68K_JMP_SLOT:
100 Elf32_Sym *sym;
101 status_t status;
102 sym = SYMBOL(image, ELF32_R_SYM(rel[i].r_info));
104 status = resolve_symbol(rootImage, image, sym, cache, &S);
105 if (status < B_OK) {
106 TRACE(("resolve symbol \"%s\" returned: %ld\n",
107 SYMNAME(image, sym), status));
108 printf("resolve symbol \"%s\" returned: %ld\n",
109 SYMNAME(image, sym), status);
110 return status;
114 switch (type) {
115 case R_68K_NONE:
116 continue;
117 case R_68K_32:
118 write_32(P, S + A);
119 break;
120 case R_68K_16:
121 if (write_16_check(P, S + A))
122 break;
123 TRACE(("R_68K_16 overflow\n"));
124 return B_BAD_DATA;
126 case R_68K_8:
127 if (write_8_check(P, S + A))
128 break;
129 TRACE(("R_68K_8 overflow\n"));
130 return B_BAD_DATA;
132 case R_68K_PC32:
133 write_32(P, (S + A - (addr_t)P));
134 break;
136 #if 0
137 case R_68K_PC16:
138 if (write_16_check(P, (S + A - P)))
139 break;
140 TRACE(("R_68K_PC16 overflow\n"));
141 return B_BAD_DATA;
143 case R_68K_PC8:
144 if (write_8(P, (S + A - P)))
145 break;
146 TRACE(("R_68K_PC8 overflow\n"));
147 return B_BAD_DATA;
149 case R_68K_GOT32:
150 REQUIRE_GOT;
151 write_32(P, (G + A - P));
152 break;
154 case R_68K_GOT16:
155 REQUIRE_GOT;
156 if (write_16_check(P, (G + A - P)))
157 break;
158 TRACE(("R_68K_GOT16 overflow\n"));
159 return B_BAD_DATA;
161 case R_68K_GOT8:
162 REQUIRE_GOT;
163 if (write_8_check(P, (G + A - P)))
164 break;
165 TRACE(("R_68K_GOT8 overflow\n"));
166 return B_BAD_DATA;
168 case R_68K_GOT32O:
169 REQUIRE_GOT;
170 write_32(P, (G + A));
171 break;
173 case R_68K_GOT16O:
174 REQUIRE_GOT;
175 if (write_16_check(P, (G + A)))
176 break;
177 TRACE(("R_68K_GOT16 overflow\n"));
178 return B_BAD_DATA;
180 case R_68K_GOT8O:
181 REQUIRE_GOT;
182 if (write_8_check(P, (G + A)))
183 break;
184 TRACE(("R_68K_GOT8 overflow\n"));
185 return B_BAD_DATA;
187 case R_68K_PLT32:
188 REQUIRE_PLT;
189 write_32(P, (L + A - P));
190 break;
192 case R_68K_PLT16:
193 REQUIRE_PLT;
194 if (write_16_check(P, (L + A - P)))
195 break;
196 TRACE(("R_68K_PLT16 overflow\n"));
197 return B_BAD_DATA;
199 case R_68K_PLT8:
200 REQUIRE_PLT;
201 if (write_8_check(P, (L + A - P)))
202 break;
203 TRACE(("R_68K_PLT8 overflow\n"));
204 return B_BAD_DATA;
206 case R_68K_PLT32O:
207 REQUIRE_PLT;
208 write_32(P, (L + A));
209 break;
211 case R_68K_PLT16O:
212 REQUIRE_PLT;
213 if (write_16_check(P, (L + A)))
214 break;
215 TRACE(("R_68K_PLT16O overflow\n"));
216 return B_BAD_DATA;
218 case R_68K_PLT8O:
219 REQUIRE_PLT;
220 if (write_8_check(P, (L + A)))
221 break;
222 TRACE(("R_68K_PLT8O overflow\n"));
223 return B_BAD_DATA;
224 case R_386_GOT32:
225 final_val = G + A;
226 break;
227 case R_386_PLT32:
228 final_val = L + A - (addr_t)P;
229 break;
230 #endif
231 case R_68K_COPY:
232 /* what ? */
233 continue;
234 case R_68K_GLOB_DAT:
235 write_32(P, S/* + A*/);
236 break;
237 case R_68K_JMP_SLOT:
238 //XXX ? write_32(P, (G + A));
239 write_32(P, S);
240 break;
241 #if 0
242 case R_386_JMP_SLOT:
243 write_32(P, S);
244 break;
245 #endif
246 case R_68K_RELATIVE:
247 write_32(P, B + A);
248 break;
250 #if 0
251 case R_386_GOTOFF:
252 final_val = S + A - GOT;
253 break;
254 case R_386_GOTPC:
255 final_val = GOT + A - P;
256 break;
257 #endif
258 default:
259 TRACE(("unhandled relocation type %d\n", ELF32_R_TYPE(rel[i].r_info)));
260 return B_NOT_ALLOWED;
263 *P = final_val;
266 # undef P
267 # undef A
268 # undef B
270 return B_NO_ERROR;
274 status_t
275 arch_relocate_image(image_t *rootImage, image_t *image,
276 SymbolLookupCache* cache)
278 status_t status;
280 // deal with the rels first
281 if (image->rel) {
282 TRACE(("RELA relocations not supported\n"));
283 return EOPNOTSUPP;
286 if (image->pltrel) {
287 TRACE(("RELA relocations not supported\n"));
288 return EOPNOTSUPP;
289 #if 0
290 status = relocate_rel(rootImage, image, image->pltrel,
291 image->pltrel_len);
292 if (status < B_OK)
293 return status;
294 #endif
297 if (image->rela) {
298 status = relocate_rela(rootImage, image, image->rela, image->rela_len,
299 cache);
300 //int i;
301 if (status < B_OK)
302 return status;
303 //TRACE(("RELA relocations not supported\n"));
304 //return EOPNOTSUPP;
306 //for (i = 1; i * (int)sizeof(Elf32_Rela) < image->rela_len; i++) {
307 // printf("rela: type %d\n", ELF32_R_TYPE(image->rela[i].r_info));
311 #if 0
312 if (image->pltrela) {
313 status = relocate_rela(rootImage, image, image->pltrela,
314 image->pltrela_len);
315 if (status < B_OK)
316 return status;
318 #endif
320 return B_OK;