headers/bsd: Add sys/queue.h.
[haiku.git] / src / system / kernel / arch / m68k / arch_elf.cpp
blob2a535546221a3bfc4d73db5ad127d73b034f2eff
1 /*
2 * Copyright 2007, François Revol, revol@free.fr.
3 * Distributed under the terms of the MIT License.
5 * Copyright 2005, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
6 * All rights reserved. Distributed under the terms of the MIT License.
9 * Copyright 2002, Travis Geiselbrecht. All rights reserved.
10 * Distributed under the terms of the NewOS License.
13 #ifdef _BOOT_MODE
14 #include <boot/arch.h>
15 #endif
17 #include <KernelExport.h>
19 #include <elf_priv.h>
20 #include <arch/elf.h>
23 //#define TRACE_ARCH_ELF
24 #ifdef TRACE_ARCH_ELF
25 # define TRACE(x) dprintf x
26 # define CHATTY 1
27 #else
28 # define TRACE(x) ;
29 # define CHATTY 0
30 #endif
33 #ifdef TRACE_ARCH_ELF
34 static const char *kRelocations[] = {
35 "R_68K_NONE",
36 "R_68K_32", /* Direct 32 bit */
37 "R_68K_16", /* Direct 16 bit */
38 "R_68K_8", /* Direct 8 bit */
39 "R_68K_PC32", /* PC relative 32 bit */
40 "R_68K_PC16", /* PC relative 16 bit */
41 "R_68K_PC8", /* PC relative 8 bit */
42 "R_68K_GOT32", /* 32 bit PC relative GOT entry */
43 "R_68K_GOT16", /* 16 bit PC relative GOT entry */
44 "R_68K_GOT8", /* 8 bit PC relative GOT entry */
45 "R_68K_GOT32O", /* 32 bit GOT offset */
46 "R_68K_GOT16O", /* 16 bit GOT offset */
47 "R_68K_GOT8O", /* 8 bit GOT offset */
48 "R_68K_PLT32", /* 32 bit PC relative PLT address */
49 "R_68K_PLT16", /* 16 bit PC relative PLT address */
50 "R_68K_PLT8", /* 8 bit PC relative PLT address */
51 "R_68K_PLT32O", /* 32 bit PLT offset */
52 "R_68K_PLT16O", /* 16 bit PLT offset */
53 "R_68K_PLT8O", /* 8 bit PLT offset */
54 "R_68K_COPY", /* Copy symbol at runtime */
55 "R_68K_GLOB_DAT", /* Create GOT entry */
56 "R_68K_JMP_SLOT", /* Create PLT entry */
57 "R_68K_RELATIVE", /* Adjust by program base */
58 /* These are GNU extensions to enable C++ vtable garbage collection. */
59 "R_68K_GNU_VTINHERIT",
60 "R_68K_GNU_VTENTRY",
61 #if 0
62 "R_386_NONE",
63 "R_386_32", /* add symbol value */
64 "R_386_PC32", /* add PC relative symbol value */
65 "R_386_GOT32", /* add PC relative GOT offset */
66 "R_386_PLT32", /* add PC relative PLT offset */
67 "R_386_COPY", /* copy data from shared object */
68 "R_386_GLOB_DAT", /* set GOT entry to data address */
69 "R_386_JMP_SLOT", /* set GOT entry to code address */
70 "R_386_RELATIVE", /* add load address of shared object */
71 "R_386_GOTOFF", /* add GOT relative symbol address */
72 "R_386_GOTPC", /* add PC relative GOT table address */
73 #endif
75 #endif
77 #ifdef _BOOT_MODE
78 status_t
79 boot_arch_elf_relocate_rel(struct preloaded_elf32_image *image, Elf32_Rel *rel,
80 int rel_len)
81 #else
82 int
83 arch_elf_relocate_rel(struct elf_image_info *image,
84 struct elf_image_info *resolve_image, Elf32_Rel *rel, int rel_len)
85 #endif
87 // there are no rel entries in M68K elf
88 return B_NO_ERROR;
92 static inline void
93 write_32(addr_t P, Elf32_Word value)
95 *(Elf32_Word*)P = value;
99 static inline void
100 write_16(addr_t P, Elf32_Word value)
102 // bits 16:29
103 *(Elf32_Half*)P = (Elf32_Half)value;
107 static inline bool
108 write_16_check(addr_t P, Elf32_Word value)
110 // bits 15:0
111 if ((value & 0xffff0000) && (~value & 0xffff8000))
112 return false;
113 *(Elf32_Half*)P = (Elf32_Half)value;
114 return true;
118 static inline bool
119 write_8(addr_t P, Elf32_Word value)
121 // bits 7:0
122 *(uint8 *)P = (uint8)value;
123 return true;
127 static inline bool
128 write_8_check(addr_t P, Elf32_Word value)
130 // bits 7:0
131 if ((value & 0xffffff00) && (~value & 0xffffff80))
132 return false;
133 *(uint8 *)P = (uint8)value;
134 return true;
138 #ifdef _BOOT_MODE
139 status_t
140 boot_arch_elf_relocate_rela(struct preloaded_elf32_image *image,
141 Elf32_Rela *rel, int rel_len)
142 #else
144 arch_elf_relocate_rela(struct elf_image_info *image,
145 struct elf_image_info *resolve_image, Elf32_Rela *rel, int rel_len)
146 #endif
148 int i;
149 Elf32_Sym *sym;
150 int vlErr;
151 addr_t S = 0; // symbol address
152 addr_t R = 0; // section relative symbol address
154 addr_t G = 0; // GOT address
155 addr_t L = 0; // PLT address
157 #define P ((addr_t)(image->text_region.delta + rel[i].r_offset))
158 #define A ((addr_t)rel[i].r_addend)
159 #define B (image->text_region.delta)
161 // TODO: Get the GOT address!
162 #define REQUIRE_GOT \
163 if (G == 0) { \
164 dprintf("arch_elf_relocate_rela(): Failed to get GOT address!\n"); \
165 return B_ERROR; \
168 // TODO: Get the PLT address!
169 #define REQUIRE_PLT \
170 if (L == 0) { \
171 dprintf("arch_elf_relocate_rela(): Failed to get PLT address!\n"); \
172 return B_ERROR; \
175 for (i = 0; i * (int)sizeof(Elf32_Rela) < rel_len; i++) {
176 #if CHATTY
177 dprintf("looking at rel type %d, offset 0x%lx, sym 0x%lx, addend 0x%lx\n",
178 ELF32_R_TYPE(rel[i].r_info), rel[i].r_offset, ELF32_R_SYM(rel[i].r_info), rel[i].r_addend);
179 #endif
180 switch (ELF32_R_TYPE(rel[i].r_info)) {
181 case R_68K_32:
182 case R_68K_16:
183 case R_68K_8:
184 case R_68K_PC32:
185 case R_68K_PC16:
186 case R_68K_PC8:
187 case R_68K_GLOB_DAT:
188 case R_68K_JMP_SLOT:
189 sym = SYMBOL(image, ELF32_R_SYM(rel[i].r_info));
191 #ifdef _BOOT_MODE
192 vlErr = boot_elf_resolve_symbol(image, sym, &S);
193 #else
194 vlErr = elf_resolve_symbol(image, sym, resolve_image, &S);
195 #endif
196 if (vlErr < 0) {
197 dprintf("%s(): Failed to relocate "
198 "entry index %d, rel type %d, offset 0x%lx, sym 0x%lx, "
199 "addend 0x%lx\n", __FUNCTION__, i, ELF32_R_TYPE(rel[i].r_info),
200 rel[i].r_offset, ELF32_R_SYM(rel[i].r_info),
201 rel[i].r_addend);
202 return vlErr;
204 break;
207 switch (ELF32_R_TYPE(rel[i].r_info)) {
208 case R_68K_NONE:
209 break;
211 case R_68K_COPY:
212 // TODO: Implement!
213 dprintf("arch_elf_relocate_rela(): R_68K_COPY not yet "
214 "supported!\n");
215 return B_ERROR;
217 case R_68K_32:
218 case R_68K_GLOB_DAT:
219 write_32(P, S + A);
220 break;
222 case R_68K_16:
223 if (write_16_check(P, S + A))
224 break;
225 dprintf("R_68K_16 overflow\n");
226 return B_BAD_DATA;
228 case R_68K_8:
229 if (write_8_check(P, S + A))
230 break;
231 dprintf("R_68K_8 overflow\n");
232 return B_BAD_DATA;
234 case R_68K_PC32:
235 write_32(P, (S + A - P));
236 break;
238 case R_68K_PC16:
239 if (write_16_check(P, (S + A - P)))
240 break;
241 dprintf("R_68K_PC16 overflow\n");
242 return B_BAD_DATA;
244 case R_68K_PC8:
245 if (write_8(P, (S + A - P)))
246 break;
247 dprintf("R_68K_PC8 overflow\n");
248 return B_BAD_DATA;
250 case R_68K_GOT32:
251 REQUIRE_GOT;
252 write_32(P, (G + A - P));
253 break;
255 case R_68K_GOT16:
256 REQUIRE_GOT;
257 if (write_16_check(P, (G + A - P)))
258 break;
259 dprintf("R_68K_GOT16 overflow\n");
260 return B_BAD_DATA;
262 case R_68K_GOT8:
263 REQUIRE_GOT;
264 if (write_8_check(P, (G + A - P)))
265 break;
266 dprintf("R_68K_GOT8 overflow\n");
267 return B_BAD_DATA;
269 case R_68K_GOT32O:
270 REQUIRE_GOT;
271 write_32(P, (G + A));
272 break;
274 case R_68K_GOT16O:
275 REQUIRE_GOT;
276 if (write_16_check(P, (G + A)))
277 break;
278 dprintf("R_68K_GOT16 overflow\n");
279 return B_BAD_DATA;
281 case R_68K_GOT8O:
282 REQUIRE_GOT;
283 if (write_8_check(P, (G + A)))
284 break;
285 dprintf("R_68K_GOT8 overflow\n");
286 return B_BAD_DATA;
288 case R_68K_JMP_SLOT:
289 write_32(P, (G + A));
290 break;
292 case R_68K_RELATIVE:
293 write_32(P, B + A);
294 break;
296 case R_68K_PLT32:
297 REQUIRE_PLT;
298 write_32(P, (L + A - P));
299 break;
301 case R_68K_PLT16:
302 REQUIRE_PLT;
303 if (write_16_check(P, (L + A - P)))
304 break;
305 dprintf("R_68K_PLT16 overflow\n");
306 return B_BAD_DATA;
308 case R_68K_PLT8:
309 REQUIRE_PLT;
310 if (write_8_check(P, (L + A - P)))
311 break;
312 dprintf("R_68K_PLT8 overflow\n");
313 return B_BAD_DATA;
315 case R_68K_PLT32O:
316 REQUIRE_PLT;
317 write_32(P, (L + A));
318 break;
320 case R_68K_PLT16O:
321 REQUIRE_PLT;
322 if (write_16_check(P, (L + A)))
323 break;
324 dprintf("R_68K_PLT16O overflow\n");
325 return B_BAD_DATA;
327 case R_68K_PLT8O:
328 REQUIRE_PLT;
329 if (write_8_check(P, (L + A)))
330 break;
331 dprintf("R_68K_PLT8O overflow\n");
332 return B_BAD_DATA;
334 default:
335 dprintf("arch_elf_relocate_rela: unhandled relocation type %d\n", ELF32_R_TYPE(rel[i].r_info));
336 return B_ERROR;
340 return B_NO_ERROR;