diff --git a/src/system/runtime_loader/arch/arm/arch_relocate.cpp b/src/system/runtime_loader/arch/arm/arch_relocate.cpp index d3dea465ae..a14b3b8a93 100644 --- a/src/system/runtime_loader/arch/arm/arch_relocate.cpp +++ b/src/system/runtime_loader/arch/arm/arch_relocate.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2012, Haiku, Inc. + * Copyright 2012-2022, Haiku, Inc. * Distributed under the terms of the MIT License. * * Authors: @@ -16,15 +16,92 @@ //#define TRACE_RLD #ifdef TRACE_RLD -# define TRACE(x) dprintf x +# define TRACE(x...) dprintf(x) #else -# define TRACE(x) ; +# define TRACE(x...) ; #endif + +static int +relocate_rel(image_t *rootImage, image_t *image, Elf32_Rel *rel, int rel_len, + SymbolLookupCache* cache) +{ +# define P ((addr_t *)(image->regions[0].delta + rel[i].r_offset)) +# define A (*(P)) +# define B (image->regions[0].delta) + + for (int i = 0; i * (int)sizeof(Elf32_Rel) < rel_len; i++) { + unsigned type = ELF32_R_TYPE(rel[i].r_info); + unsigned symbolIndex = ELF32_R_SYM(rel[i].r_info); + addr_t final_val; + addr_t S; + + image_t* symbolImage = NULL; + if (symbolIndex != 0) { + Elf32_Sym* sym = SYMBOL(image, symbolIndex); + status_t status = resolve_symbol(rootImage, image, sym, cache, &S, + &symbolImage); + if (status < B_OK) { + TRACE("resolve symbol \"%s\" returned: %ld\n", + SYMNAME(image, sym), status); + return status; + } + } + + switch (type) { + case R_ARM_NONE: + continue; + case R_ARM_RELATIVE: + final_val = B + A; + break; + case R_ARM_JMP_SLOT: + case R_ARM_GLOB_DAT: + final_val = S; + break; + case R_ARM_ABS32: + final_val = S + A; + break; + 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; +} + + status_t arch_relocate_image(image_t *rootImage, image_t *image, SymbolLookupCache* cache) { - debugger("arch_relocate_image: Not Yet Implemented!"); + status_t status; + + // deal with the rels first + if (image->rel) { + status = relocate_rel(rootImage, image, image->rel, image->rel_len, + cache); + if (status < B_OK) + return status; + } + + if (image->pltrel) { + status = relocate_rel(rootImage, image, image->pltrel, + image->pltrel_len, cache); + if (status < B_OK) + return status; + } + + if (image->rela) { + TRACE("RELA relocations not supported\n"); + return EOPNOTSUPP; + } + return B_OK; }