static int relocate_rela(image_t *rootImage, image_t *image, Elf32_Rela *rel, int rel_len, SymbolLookupCache* cache) { int i; addr_t S; addr_t final_val; # define P ((addr_t *)(image->regions[0].delta + rel[i].r_offset)) //# define A (*(P)) #define A ((addr_t)rel[i].r_addend) # define B (image->regions[0].delta) for (i = 0; i * (int)sizeof(Elf32_Rel) < rel_len; i++) { unsigned type = ELF32_R_TYPE(rel[i].r_info); switch (type) { case R_68K_32: case R_68K_16: case R_68K_8: case R_68K_PC32: case R_68K_PC16: case R_68K_PC8: case R_68K_GLOB_DAT: case R_68K_JMP_SLOT: { Elf32_Sym *sym; status_t status; sym = SYMBOL(image, ELF32_R_SYM(rel[i].r_info)); status = resolve_symbol(rootImage, image, sym, cache, &S); if (status < B_OK) { TRACE(("resolve symbol \"%s\" returned: %ld\n", SYMNAME(image, sym), status)); printf("resolve symbol \"%s\" returned: %ld\n", SYMNAME(image, sym), status); return status; } } } switch (type) { case R_68K_NONE: continue; case R_68K_32: write_32(P, S + A); break; case R_68K_16: if (write_16_check(P, S + A)) break; TRACE(("R_68K_16 overflow\n")); return B_BAD_DATA; case R_68K_8: if (write_8_check(P, S + A)) break; TRACE(("R_68K_8 overflow\n")); return B_BAD_DATA; case R_68K_PC32: write_32(P, (S + A - (addr_t)P)); break; #if 0 case R_68K_PC16: if (write_16_check(P, (S + A - P))) break; TRACE(("R_68K_PC16 overflow\n")); return B_BAD_DATA; case R_68K_PC8: if (write_8(P, (S + A - P))) break; TRACE(("R_68K_PC8 overflow\n")); return B_BAD_DATA; case R_68K_GOT32: REQUIRE_GOT; write_32(P, (G + A - P)); break; case R_68K_GOT16: REQUIRE_GOT; if (write_16_check(P, (G + A - P))) break; TRACE(("R_68K_GOT16 overflow\n")); return B_BAD_DATA; case R_68K_GOT8: REQUIRE_GOT; if (write_8_check(P, (G + A - P))) break; TRACE(("R_68K_GOT8 overflow\n")); return B_BAD_DATA; case R_68K_GOT32O: REQUIRE_GOT; write_32(P, (G + A)); break; case R_68K_GOT16O: REQUIRE_GOT; if (write_16_check(P, (G + A))) break; TRACE(("R_68K_GOT16 overflow\n")); return B_BAD_DATA; case R_68K_GOT8O: REQUIRE_GOT; if (write_8_check(P, (G + A))) break; TRACE(("R_68K_GOT8 overflow\n")); return B_BAD_DATA; case R_68K_PLT32: REQUIRE_PLT; write_32(P, (L + A - P)); break; case R_68K_PLT16: REQUIRE_PLT; if (write_16_check(P, (L + A - P))) break; TRACE(("R_68K_PLT16 overflow\n")); return B_BAD_DATA; case R_68K_PLT8: REQUIRE_PLT; if (write_8_check(P, (L + A - P))) break; TRACE(("R_68K_PLT8 overflow\n")); return B_BAD_DATA; case R_68K_PLT32O: REQUIRE_PLT; write_32(P, (L + A)); break; case R_68K_PLT16O: REQUIRE_PLT; if (write_16_check(P, (L + A))) break; TRACE(("R_68K_PLT16O overflow\n")); return B_BAD_DATA; case R_68K_PLT8O: REQUIRE_PLT; if (write_8_check(P, (L + A))) break; TRACE(("R_68K_PLT8O overflow\n")); return B_BAD_DATA; case R_386_GOT32: final_val = G + A; break; case R_386_PLT32: final_val = L + A - (addr_t)P; break; #endif case R_68K_COPY: /* what ? */ continue; case R_68K_GLOB_DAT: write_32(P, S/* + A*/); break; case R_68K_JMP_SLOT: //XXX ? write_32(P, (G + A)); write_32(P, S); break; #if 0 case R_386_JMP_SLOT: write_32(P, S); break; #endif case R_68K_RELATIVE: write_32(P, B + A); break; #if 0 case R_386_GOTOFF: final_val = S + A - GOT; break; case R_386_GOTPC: final_val = GOT + A - P; break; #endif default: TRACE(("unhandled relocation type %d\n", ELF32_R_TYPE(rel[i].r_info))); return B_NOT_ALLOWED; } *P = final_val; } # undef P # undef A # undef B return B_NO_ERROR; }
int arch_elf_relocate_rela(struct elf_image_info *image, struct elf_image_info *resolve_image, struct Elf32_Rela *rel, int rel_len) #endif { int i; struct Elf32_Sym *sym; int vlErr; addr_t S = 0; // symbol address addr_t R = 0; // section relative symbol address addr_t G = 0; // GOT address addr_t L = 0; // PLT address #define P ((addr_t)(image->text_region.delta + rel[i].r_offset)) #define A ((addr_t)rel[i].r_addend) #define B (image->text_region.delta) // TODO: Get the GOT address! #define REQUIRE_GOT \ if (G == 0) { \ dprintf("arch_elf_relocate_rela(): Failed to get GOT address!\n"); \ return B_ERROR; \ } // TODO: Get the PLT address! #define REQUIRE_PLT \ if (L == 0) { \ dprintf("arch_elf_relocate_rela(): Failed to get PLT address!\n"); \ return B_ERROR; \ } for (i = 0; i * (int)sizeof(struct Elf32_Rela) < rel_len; i++) { #if CHATTY dprintf("looking at rel type %d, offset 0x%lx, sym 0x%lx, addend 0x%lx\n", ELF32_R_TYPE(rel[i].r_info), rel[i].r_offset, ELF32_R_SYM(rel[i].r_info), rel[i].r_addend); #endif switch (ELF32_R_TYPE(rel[i].r_info)) { case R_68K_32: case R_68K_16: case R_68K_8: case R_68K_PC32: case R_68K_PC16: case R_68K_PC8: case R_68K_GLOB_DAT: case R_68K_JMP_SLOT: sym = SYMBOL(image, ELF32_R_SYM(rel[i].r_info)); #ifdef _BOOT_MODE vlErr = boot_elf_resolve_symbol(image, sym, &S); #else vlErr = elf_resolve_symbol(image, sym, resolve_image, &S); #endif if (vlErr < 0) { dprintf("%s(): Failed to relocate " "entry index %d, rel type %d, offset 0x%lx, sym 0x%lx, " "addend 0x%lx\n", __FUNCTION__, i, ELF32_R_TYPE(rel[i].r_info), rel[i].r_offset, ELF32_R_SYM(rel[i].r_info), rel[i].r_addend); return vlErr; } break; } switch (ELF32_R_TYPE(rel[i].r_info)) { case R_68K_NONE: break; case R_68K_COPY: // TODO: Implement! dprintf("arch_elf_relocate_rela(): R_68K_COPY not yet " "supported!\n"); return B_ERROR; case R_68K_32: case R_68K_GLOB_DAT: write_32(P, S + A); break; case R_68K_16: if (write_16_check(P, S + A)) break; dprintf("R_68K_16 overflow\n"); return B_BAD_DATA; case R_68K_8: if (write_8_check(P, S + A)) break; dprintf("R_68K_8 overflow\n"); return B_BAD_DATA; case R_68K_PC32: write_32(P, (S + A - P)); break; case R_68K_PC16: if (write_16_check(P, (S + A - P))) break; dprintf("R_68K_PC16 overflow\n"); return B_BAD_DATA; case R_68K_PC8: if (write_8(P, (S + A - P))) break; dprintf("R_68K_PC8 overflow\n"); return B_BAD_DATA; case R_68K_GOT32: REQUIRE_GOT; write_32(P, (G + A - P)); break; case R_68K_GOT16: REQUIRE_GOT; if (write_16_check(P, (G + A - P))) break; dprintf("R_68K_GOT16 overflow\n"); return B_BAD_DATA; case R_68K_GOT8: REQUIRE_GOT; if (write_8_check(P, (G + A - P))) break; dprintf("R_68K_GOT8 overflow\n"); return B_BAD_DATA; case R_68K_GOT32O: REQUIRE_GOT; write_32(P, (G + A)); break; case R_68K_GOT16O: REQUIRE_GOT; if (write_16_check(P, (G + A))) break; dprintf("R_68K_GOT16 overflow\n"); return B_BAD_DATA; case R_68K_GOT8O: REQUIRE_GOT; if (write_8_check(P, (G + A))) break; dprintf("R_68K_GOT8 overflow\n"); return B_BAD_DATA; case R_68K_JMP_SLOT: write_32(P, (G + A)); break; case R_68K_RELATIVE: write_32(P, B + A); break; case R_68K_PLT32: REQUIRE_PLT; write_32(P, (L + A - P)); break; case R_68K_PLT16: REQUIRE_PLT; if (write_16_check(P, (L + A - P))) break; dprintf("R_68K_PLT16 overflow\n"); return B_BAD_DATA; case R_68K_PLT8: REQUIRE_PLT; if (write_8_check(P, (L + A - P))) break; dprintf("R_68K_PLT8 overflow\n"); return B_BAD_DATA; case R_68K_PLT32O: REQUIRE_PLT; write_32(P, (L + A)); break; case R_68K_PLT16O: REQUIRE_PLT; if (write_16_check(P, (L + A))) break; dprintf("R_68K_PLT16O overflow\n"); return B_BAD_DATA; case R_68K_PLT8O: REQUIRE_PLT; if (write_8_check(P, (L + A))) break; dprintf("R_68K_PLT8O overflow\n"); return B_BAD_DATA; default: dprintf("arch_elf_relocate_rela: unhandled relocation type %d\n", ELF32_R_TYPE(rel[i].r_info)); return B_ERROR; } } return B_NO_ERROR; }