1/* 2 * Copyright 2005, Ingo Weinhold <bonefish@cs.tu-berlin.de>. 3 * All rights reserved. Distributed under the terms of the MIT License. 4 * 5 * 6 * Copyright 2002, Travis Geiselbrecht. All rights reserved. 7 * Distributed under the terms of the NewOS License. 8 */ 9 10#ifdef _BOOT_MODE 11#include <boot/arch.h> 12#endif 13 14#include <KernelExport.h> 15 16#include <elf_priv.h> 17#include <arch/elf.h> 18 19 20#define CHATTY 0 21 22#ifdef _BOOT_MODE 23bool boot_arch_elf_arch_compat(struct elf_image_arch* hostArch, 24 struct elf_image_arch* imageArch) 25#else 26bool arch_elf_arch_compat(struct elf_image_arch* hostArch, 27 struct elf_image_arch* imageArch) 28#endif 29{ 30 if (hostArch->osabi != imageArch->osabi) 31 return false; 32 33 if (hostArch->osabi_version != imageArch->osabi_version) 34 return false; 35 36 if (hostArch->word_size != imageArch->word_size) 37 return false; 38 39 if (hostArch->byte_order != imageArch->byte_order) 40 return false; 41 42 if (hostArch->machine == imageArch->machine) 43 return false; 44 45 return true; 46} 47 48 49#ifdef _BOOT_MODE 50uint32_t boot_arch_elf_score_image_arch(struct elf_image_arch *arch) 51#else 52uint32_t arch_elf_score_image_arch(struct elf_image_arch *arch) 53#endif 54{ 55 if (arch->osabi != ELFOSABI_HAIKU) 56 return 0; 57 58 if (arch->osabi_version != 0) 59 return 0; 60 61 if (arch->word_size != ELF_CLASS) 62 return 0; 63 64 if (arch->byte_order != ELF_DATA) 65 return 0; 66 67 if (!ELF_MACHINE_OK(arch->machine)) 68 return 0; 69} 70 71 72#ifdef _BOOT_MODE 73status_t 74boot_arch_elf_relocate_rel(struct preloaded_elf32_image *image, 75 struct Elf32_Rel *rel, int rel_len) 76#else 77int 78arch_elf_relocate_rel(struct elf_image_info *image, 79 struct elf_image_info *resolve_image, struct Elf32_Rel *rel, int rel_len) 80#endif 81{ 82 // there are no rel entries in PPC elf 83 return B_NO_ERROR; 84} 85 86 87static inline void 88write_word32(addr_t P, Elf32_Word value) 89{ 90 *(Elf32_Word*)P = value; 91} 92 93 94static inline void 95write_word30(addr_t P, Elf32_Word value) 96{ 97 // bits 0:29 98 *(Elf32_Word*)P = (*(Elf32_Word*)P & 0x3) | (value << 2); 99} 100 101 102static inline bool 103write_low24_check(addr_t P, Elf32_Word value) 104{ 105 // bits 6:29 106 if ((value & 0x3f000000) && (~value & 0x3f800000)) 107 return false; 108 *(Elf32_Word*)P = (*(Elf32_Word*)P & 0xfc000003) 109 | ((value & 0x00ffffff) << 2); 110 return true; 111} 112 113 114static inline bool 115write_low14_check(addr_t P, Elf32_Word value) 116{ 117 // bits 16:29 118 if ((value & 0x3fffc000) && (~value & 0x3fffe000)) 119 return false; 120 *(Elf32_Word*)P = (*(Elf32_Word*)P & 0xffff0003) 121 | ((value & 0x00003fff) << 2); 122 return true; 123} 124 125 126static inline void 127write_half16(addr_t P, Elf32_Word value) 128{ 129 // bits 16:29 130 *(Elf32_Half*)P = (Elf32_Half)value; 131} 132 133 134static inline bool 135write_half16_check(addr_t P, Elf32_Word value) 136{ 137 // bits 16:29 138 if ((value & 0xffff0000) && (~value & 0xffff8000)) 139 return false; 140 *(Elf32_Half*)P = (Elf32_Half)value; 141 return true; 142} 143 144 145static inline Elf32_Word 146lo(Elf32_Word value) 147{ 148 return (value & 0xffff); 149} 150 151 152static inline Elf32_Word 153hi(Elf32_Word value) 154{ 155 return ((value >> 16) & 0xffff); 156} 157 158 159static inline Elf32_Word 160ha(Elf32_Word value) 161{ 162 return (((value >> 16) + (value & 0x8000 ? 1 : 0)) & 0xffff); 163} 164 165 166#ifdef _BOOT_MODE 167status_t 168boot_arch_elf_relocate_rela(struct preloaded_elf32_image *image, 169 struct Elf32_Rela *rel, int rel_len) 170#else 171int 172arch_elf_relocate_rela(struct elf_image_info *image, 173 struct elf_image_info *resolve_image, struct Elf32_Rela *rel, int rel_len) 174#endif 175{ 176 int i; 177 struct Elf32_Sym *sym; 178 int vlErr; 179 addr_t S = 0; // symbol address 180 addr_t R = 0; // section relative symbol address 181 182 addr_t G = 0; // GOT address 183 addr_t L = 0; // PLT address 184 185 #define P ((addr_t)(image->text_region.delta + rel[i].r_offset)) 186 #define A ((addr_t)rel[i].r_addend) 187 #define B (image->text_region.delta) 188 189 // TODO: Get the GOT address! 190 #define REQUIRE_GOT \ 191 if (G == 0) { \ 192 dprintf("arch_elf_relocate_rela(): Failed to get GOT address!\n"); \ 193 return B_ERROR; \ 194 } 195 196 // TODO: Get the PLT address! 197 #define REQUIRE_PLT \ 198 if (L == 0) { \ 199 dprintf("arch_elf_relocate_rela(): Failed to get PLT address!\n"); \ 200 return B_ERROR; \ 201 } 202 203 for (i = 0; i * (int)sizeof(struct Elf32_Rela) < rel_len; i++) { 204#if CHATTY 205 dprintf("looking at rel type %d, offset 0x%lx, sym 0x%lx, addend 0x%lx\n", 206 ELF32_R_TYPE(rel[i].r_info), rel[i].r_offset, ELF32_R_SYM(rel[i].r_info), rel[i].r_addend); 207#endif 208 switch (ELF32_R_TYPE(rel[i].r_info)) { 209 case R_PPC_SECTOFF: 210 case R_PPC_SECTOFF_LO: 211 case R_PPC_SECTOFF_HI: 212 case R_PPC_SECTOFF_HA: 213 dprintf("arch_elf_relocate_rela(): Getting section relative " 214 "symbol addresses not yet supported!\n"); 215 return B_ERROR; 216 217 case R_PPC_ADDR32: 218 case R_PPC_ADDR24: 219 case R_PPC_ADDR16: 220 case R_PPC_ADDR16_LO: 221 case R_PPC_ADDR16_HI: 222 case R_PPC_ADDR16_HA: 223 case R_PPC_ADDR14: 224 case R_PPC_ADDR14_BRTAKEN: 225 case R_PPC_ADDR14_BRNTAKEN: 226 case R_PPC_REL24: 227 case R_PPC_REL14: 228 case R_PPC_REL14_BRTAKEN: 229 case R_PPC_REL14_BRNTAKEN: 230 case R_PPC_GLOB_DAT: 231 case R_PPC_UADDR32: 232 case R_PPC_UADDR16: 233 case R_PPC_REL32: 234 case R_PPC_SDAREL16: 235 case R_PPC_ADDR30: 236 case R_PPC_JMP_SLOT: 237 sym = SYMBOL(image, ELF32_R_SYM(rel[i].r_info)); 238 239#ifdef _BOOT_MODE 240 vlErr = boot_elf_resolve_symbol(image, sym, &S); 241#else 242 vlErr = elf_resolve_symbol(image, sym, resolve_image, &S); 243#endif 244 if (vlErr < 0) { 245 dprintf("%s(): Failed to relocate " 246 "entry index %d, rel type %d, offset 0x%lx, sym 0x%lx, " 247 "addend 0x%lx\n", __FUNCTION__, i, ELF32_R_TYPE(rel[i].r_info), 248 rel[i].r_offset, ELF32_R_SYM(rel[i].r_info), 249 rel[i].r_addend); 250 return vlErr; 251 } 252 break; 253 } 254 255 switch (ELF32_R_TYPE(rel[i].r_info)) { 256 case R_PPC_NONE: 257 break; 258 259 case R_PPC_COPY: 260 // TODO: Implement! 261 dprintf("arch_elf_relocate_rela(): R_PPC_COPY not yet " 262 "supported!\n"); 263 return B_ERROR; 264 265 case R_PPC_ADDR32: 266 case R_PPC_GLOB_DAT: 267 case R_PPC_UADDR32: 268 write_word32(P, S + A); 269 break; 270 271 case R_PPC_ADDR24: 272 if (write_low24_check(P, (S + A) >> 2)) 273 break; 274dprintf("R_PPC_ADDR24 overflow\n"); 275 return B_BAD_DATA; 276 277 case R_PPC_ADDR16: 278 case R_PPC_UADDR16: 279 if (write_half16_check(P, S + A)) 280 break; 281dprintf("R_PPC_ADDR16 overflow\n"); 282 return B_BAD_DATA; 283 284 case R_PPC_ADDR16_LO: 285 write_half16(P, lo(S + A)); 286 break; 287 288 case R_PPC_ADDR16_HI: 289 write_half16(P, hi(S + A)); 290 break; 291 292 case R_PPC_ADDR16_HA: 293 write_half16(P, ha(S + A)); 294 break; 295 296 case R_PPC_ADDR14: 297 case R_PPC_ADDR14_BRTAKEN: 298 case R_PPC_ADDR14_BRNTAKEN: 299 if (write_low14_check(P, (S + A) >> 2)) 300 break; 301dprintf("R_PPC_ADDR14 overflow\n"); 302 return B_BAD_DATA; 303 304 case R_PPC_REL24: 305 if (write_low24_check(P, (S + A - P) >> 2)) 306 break; 307dprintf("R_PPC_REL24 overflow: 0x%lx\n", (S + A - P) >> 2); 308 return B_BAD_DATA; 309 310 case R_PPC_REL14: 311 case R_PPC_REL14_BRTAKEN: 312 case R_PPC_REL14_BRNTAKEN: 313 if (write_low14_check(P, (S + A - P) >> 2)) 314 break; 315dprintf("R_PPC_REL14 overflow\n"); 316 return B_BAD_DATA; 317 318 case R_PPC_GOT16: 319 REQUIRE_GOT; 320 if (write_half16_check(P, G + A)) 321 break; 322dprintf("R_PPC_GOT16 overflow\n"); 323 return B_BAD_DATA; 324 325 case R_PPC_GOT16_LO: 326 REQUIRE_GOT; 327 write_half16(P, lo(G + A)); 328 break; 329 330 case R_PPC_GOT16_HI: 331 REQUIRE_GOT; 332 write_half16(P, hi(G + A)); 333 break; 334 335 case R_PPC_GOT16_HA: 336 REQUIRE_GOT; 337 write_half16(P, ha(G + A)); 338 break; 339 340 case R_PPC_JMP_SLOT: 341 { 342 // If the relative offset is small enough, we fabricate a 343 // relative branch instruction ("b <addr>"). 344 addr_t jumpOffset = S - P; 345 if ((jumpOffset & 0xfc000000) != 0 346 && (~jumpOffset & 0xfe000000) != 0) { 347 // Offset > 24 bit. 348 // TODO: Implement! 349 // See System V PPC ABI supplement, p. 5-6! 350 dprintf("arch_elf_relocate_rela(): R_PPC_JMP_SLOT: " 351 "Offsets > 24 bit currently not supported!\n"); 352dprintf("jumpOffset: %p\n", (void*)jumpOffset); 353 return B_ERROR; 354 } else { 355 // Offset <= 24 bit 356 // 0:5 opcode (= 18), 6:29 address, 30 AA, 31 LK 357 // "b" instruction: opcode = 18, AA = 0, LK = 0 358 // address: 24 high-order bits of 26 bit offset 359 *(uint32*)P = 0x48000000 | ((jumpOffset) & 0x03fffffc); 360 } 361 break; 362 } 363 364 case R_PPC_RELATIVE: 365 write_word32(P, B + A); 366 break; 367 368 case R_PPC_LOCAL24PC: 369// TODO: Implement! 370// low24* 371// if (write_low24_check(P, ?) 372// break; 373// return B_BAD_DATA; 374 dprintf("arch_elf_relocate_rela(): R_PPC_LOCAL24PC not yet " 375 "supported!\n"); 376 return B_ERROR; 377 378 case R_PPC_REL32: 379 write_word32(P, S + A - P); 380 break; 381 382 case R_PPC_PLTREL24: 383 REQUIRE_PLT; 384 if (write_low24_check(P, (L + A - P) >> 2)) 385 break; 386dprintf("R_PPC_PLTREL24 overflow\n"); 387 return B_BAD_DATA; 388 389 case R_PPC_PLT32: 390 REQUIRE_PLT; 391 write_word32(P, L + A); 392 break; 393 394 case R_PPC_PLTREL32: 395 REQUIRE_PLT; 396 write_word32(P, L + A - P); 397 break; 398 399 case R_PPC_PLT16_LO: 400 REQUIRE_PLT; 401 write_half16(P, lo(L + A)); 402 break; 403 404 case R_PPC_PLT16_HI: 405 REQUIRE_PLT; 406 write_half16(P, hi(L + A)); 407 break; 408 409 case R_PPC_PLT16_HA: 410 write_half16(P, ha(L + A)); 411 break; 412 413 case R_PPC_SDAREL16: 414// TODO: Implement! 415// if (write_half16_check(P, S + A - _SDA_BASE_)) 416// break; 417// return B_BAD_DATA; 418 dprintf("arch_elf_relocate_rela(): R_PPC_SDAREL16 not yet " 419 "supported!\n"); 420 return B_ERROR; 421 422 case R_PPC_SECTOFF: 423 if (write_half16_check(P, R + A)) 424 break; 425dprintf("R_PPC_SECTOFF overflow\n"); 426 return B_BAD_DATA; 427 428 case R_PPC_SECTOFF_LO: 429 write_half16(P, lo(R + A)); 430 break; 431 432 case R_PPC_SECTOFF_HI: 433 write_half16(P, hi(R + A)); 434 break; 435 436 case R_PPC_SECTOFF_HA: 437 write_half16(P, ha(R + A)); 438 break; 439 440 case R_PPC_ADDR30: 441 write_word30(P, (S + A - P) >> 2); 442 break; 443 444 default: 445 dprintf("arch_elf_relocate_rela: unhandled relocation type %d\n", ELF32_R_TYPE(rel[i].r_info)); 446 return B_ERROR; 447 } 448 } 449 450 return B_NO_ERROR; 451} 452 453