1/* 2 * Copyright 2007, François Revol, revol@free.fr. 3 * Distributed under the terms of the MIT License. 4 * 5 * Copyright 2005, Ingo Weinhold <bonefish@cs.tu-berlin.de>. 6 * All rights reserved. Distributed under the terms of the MIT License. 7 * 8 * 9 * Copyright 2002, Travis Geiselbrecht. All rights reserved. 10 * Distributed under the terms of the NewOS License. 11 */ 12 13#ifdef _BOOT_MODE 14#include <boot/arch.h> 15#endif 16 17#include <KernelExport.h> 18 19#include <elf_priv.h> 20#include <arch/elf.h> 21 22 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 31 32 33#ifdef TRACE_ARCH_ELF 34static 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 74}; 75#endif 76 77 78#ifdef _BOOT_MODE 79bool boot_arch_elf_arch_compat(struct elf_image_arch* hostArch, 80 struct elf_image_arch* imageArch) 81#else 82bool arch_elf_arch_compat(struct elf_image_arch* hostArch, 83 struct elf_image_arch* imageArch) 84#endif 85{ 86 if (hostArch->osabi != imageArch->osabi) 87 return false; 88 89 if (hostArch->osabi_version != imageArch->osabi_version) 90 return false; 91 92 if (hostArch->word_size != imageArch->word_size) 93 return false; 94 95 if (hostArch->byte_order != imageArch->byte_order) 96 return false; 97 98 if (hostArch->machine == imageArch->machine) 99 return false; 100 101 return true; 102} 103 104 105#ifdef _BOOT_MODE 106uint32_t boot_arch_elf_score_image_arch(struct elf_image_arch *arch) 107#else 108uint32_t arch_elf_score_image_arch(struct elf_image_arch *arch) 109#endif 110{ 111 if (arch->osabi != ELFOSABI_HAIKU) 112 return 0; 113 114 if (arch->osabi_version != 0) 115 return 0; 116 117 if (arch->word_size != ELF_CLASS) 118 return 0; 119 120 if (arch->byte_order != ELF_DATA) 121 return 0; 122 123 if (!ELF_MACHINE_OK(arch->machine)) 124 return 0; 125} 126 127 128#ifdef _BOOT_MODE 129status_t 130boot_arch_elf_relocate_rel(struct preloaded_elf32_image *image, 131 struct Elf32_Rel *rel, int rel_len) 132#else 133int 134arch_elf_relocate_rel(struct elf_image_info *image, 135 struct elf_image_info *resolve_image, struct Elf32_Rel *rel, int rel_len) 136#endif 137{ 138 // there are no rel entries in M68K elf 139 return B_NO_ERROR; 140} 141 142 143static inline void 144write_32(addr_t P, Elf32_Word value) 145{ 146 *(Elf32_Word*)P = value; 147} 148 149 150static inline void 151write_16(addr_t P, Elf32_Word value) 152{ 153 // bits 16:29 154 *(Elf32_Half*)P = (Elf32_Half)value; 155} 156 157 158static inline bool 159write_16_check(addr_t P, Elf32_Word value) 160{ 161 // bits 15:0 162 if ((value & 0xffff0000) && (~value & 0xffff8000)) 163 return false; 164 *(Elf32_Half*)P = (Elf32_Half)value; 165 return true; 166} 167 168 169static inline bool 170write_8(addr_t P, Elf32_Word value) 171{ 172 // bits 7:0 173 *(uint8 *)P = (uint8)value; 174 return true; 175} 176 177 178static inline bool 179write_8_check(addr_t P, Elf32_Word value) 180{ 181 // bits 7:0 182 if ((value & 0xffffff00) && (~value & 0xffffff80)) 183 return false; 184 *(uint8 *)P = (uint8)value; 185 return true; 186} 187 188 189#ifdef _BOOT_MODE 190status_t 191boot_arch_elf_relocate_rela(struct preloaded_elf32_image *image, 192 struct Elf32_Rela *rel, int rel_len) 193#else 194int 195arch_elf_relocate_rela(struct elf_image_info *image, 196 struct elf_image_info *resolve_image, struct Elf32_Rela *rel, int rel_len) 197#endif 198{ 199 int i; 200 struct Elf32_Sym *sym; 201 int vlErr; 202 addr_t S = 0; // symbol address 203 addr_t R = 0; // section relative symbol address 204 205 addr_t G = 0; // GOT address 206 addr_t L = 0; // PLT address 207 208 #define P ((addr_t)(image->text_region.delta + rel[i].r_offset)) 209 #define A ((addr_t)rel[i].r_addend) 210 #define B (image->text_region.delta) 211 212 // TODO: Get the GOT address! 213 #define REQUIRE_GOT \ 214 if (G == 0) { \ 215 dprintf("arch_elf_relocate_rela(): Failed to get GOT address!\n"); \ 216 return B_ERROR; \ 217 } 218 219 // TODO: Get the PLT address! 220 #define REQUIRE_PLT \ 221 if (L == 0) { \ 222 dprintf("arch_elf_relocate_rela(): Failed to get PLT address!\n"); \ 223 return B_ERROR; \ 224 } 225 226 for (i = 0; i * (int)sizeof(struct Elf32_Rela) < rel_len; i++) { 227#if CHATTY 228 dprintf("looking at rel type %d, offset 0x%lx, sym 0x%lx, addend 0x%lx\n", 229 ELF32_R_TYPE(rel[i].r_info), rel[i].r_offset, ELF32_R_SYM(rel[i].r_info), rel[i].r_addend); 230#endif 231 switch (ELF32_R_TYPE(rel[i].r_info)) { 232 case R_68K_32: 233 case R_68K_16: 234 case R_68K_8: 235 case R_68K_PC32: 236 case R_68K_PC16: 237 case R_68K_PC8: 238 case R_68K_GLOB_DAT: 239 case R_68K_JMP_SLOT: 240 sym = SYMBOL(image, ELF32_R_SYM(rel[i].r_info)); 241 242#ifdef _BOOT_MODE 243 vlErr = boot_elf_resolve_symbol(image, sym, &S); 244#else 245 vlErr = elf_resolve_symbol(image, sym, resolve_image, &S); 246#endif 247 if (vlErr < 0) { 248 dprintf("%s(): Failed to relocate " 249 "entry index %d, rel type %d, offset 0x%lx, sym 0x%lx, " 250 "addend 0x%lx\n", __FUNCTION__, i, ELF32_R_TYPE(rel[i].r_info), 251 rel[i].r_offset, ELF32_R_SYM(rel[i].r_info), 252 rel[i].r_addend); 253 return vlErr; 254 } 255 break; 256 } 257 258 switch (ELF32_R_TYPE(rel[i].r_info)) { 259 case R_68K_NONE: 260 break; 261 262 case R_68K_COPY: 263 // TODO: Implement! 264 dprintf("arch_elf_relocate_rela(): R_68K_COPY not yet " 265 "supported!\n"); 266 return B_ERROR; 267 268 case R_68K_32: 269 case R_68K_GLOB_DAT: 270 write_32(P, S + A); 271 break; 272 273 case R_68K_16: 274 if (write_16_check(P, S + A)) 275 break; 276dprintf("R_68K_16 overflow\n"); 277 return B_BAD_DATA; 278 279 case R_68K_8: 280 if (write_8_check(P, S + A)) 281 break; 282dprintf("R_68K_8 overflow\n"); 283 return B_BAD_DATA; 284 285 case R_68K_PC32: 286 write_32(P, (S + A - P)); 287 break; 288 289 case R_68K_PC16: 290 if (write_16_check(P, (S + A - P))) 291 break; 292dprintf("R_68K_PC16 overflow\n"); 293 return B_BAD_DATA; 294 295 case R_68K_PC8: 296 if (write_8(P, (S + A - P))) 297 break; 298dprintf("R_68K_PC8 overflow\n"); 299 return B_BAD_DATA; 300 301 case R_68K_GOT32: 302 REQUIRE_GOT; 303 write_32(P, (G + A - P)); 304 break; 305 306 case R_68K_GOT16: 307 REQUIRE_GOT; 308 if (write_16_check(P, (G + A - P))) 309 break; 310dprintf("R_68K_GOT16 overflow\n"); 311 return B_BAD_DATA; 312 313 case R_68K_GOT8: 314 REQUIRE_GOT; 315 if (write_8_check(P, (G + A - P))) 316 break; 317dprintf("R_68K_GOT8 overflow\n"); 318 return B_BAD_DATA; 319 320 case R_68K_GOT32O: 321 REQUIRE_GOT; 322 write_32(P, (G + A)); 323 break; 324 325 case R_68K_GOT16O: 326 REQUIRE_GOT; 327 if (write_16_check(P, (G + A))) 328 break; 329dprintf("R_68K_GOT16 overflow\n"); 330 return B_BAD_DATA; 331 332 case R_68K_GOT8O: 333 REQUIRE_GOT; 334 if (write_8_check(P, (G + A))) 335 break; 336dprintf("R_68K_GOT8 overflow\n"); 337 return B_BAD_DATA; 338 339 case R_68K_JMP_SLOT: 340 write_32(P, (G + A)); 341 break; 342 343 case R_68K_RELATIVE: 344 write_32(P, B + A); 345 break; 346 347 case R_68K_PLT32: 348 REQUIRE_PLT; 349 write_32(P, (L + A - P)); 350 break; 351 352 case R_68K_PLT16: 353 REQUIRE_PLT; 354 if (write_16_check(P, (L + A - P))) 355 break; 356dprintf("R_68K_PLT16 overflow\n"); 357 return B_BAD_DATA; 358 359 case R_68K_PLT8: 360 REQUIRE_PLT; 361 if (write_8_check(P, (L + A - P))) 362 break; 363dprintf("R_68K_PLT8 overflow\n"); 364 return B_BAD_DATA; 365 366 case R_68K_PLT32O: 367 REQUIRE_PLT; 368 write_32(P, (L + A)); 369 break; 370 371 case R_68K_PLT16O: 372 REQUIRE_PLT; 373 if (write_16_check(P, (L + A))) 374 break; 375dprintf("R_68K_PLT16O overflow\n"); 376 return B_BAD_DATA; 377 378 case R_68K_PLT8O: 379 REQUIRE_PLT; 380 if (write_8_check(P, (L + A))) 381 break; 382dprintf("R_68K_PLT8O overflow\n"); 383 return B_BAD_DATA; 384 385 default: 386 dprintf("arch_elf_relocate_rela: unhandled relocation type %d\n", ELF32_R_TYPE(rel[i].r_info)); 387 return B_ERROR; 388 } 389 } 390 391 return B_NO_ERROR; 392} 393 394 395 396