boot/loader: relocate kernel to virtual address space on 32-bit architectures

Change-Id: Ic86ca6874f358df8755a0c691cccb155d145e06c
Reviewed-on: https://review.haiku-os.org/c/haiku/+/4675
Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org>
Reviewed-by: Fredrik Holmqvist <fredrik.holmqvist@gmail.com>
This commit is contained in:
David Karoly 2021-12-19 12:17:58 +01:00 committed by Adrien Destugues
parent abef198c1a
commit 6117e0c29c
4 changed files with 43 additions and 3 deletions

View File

@ -90,6 +90,9 @@ extern status_t boot_elf_resolve_symbol(preloaded_elf32_image* image,
Elf32_Sym* symbol, Elf32_Addr* symbolAddress); Elf32_Sym* symbol, Elf32_Addr* symbolAddress);
extern status_t boot_elf_resolve_symbol(preloaded_elf64_image* image, extern status_t boot_elf_resolve_symbol(preloaded_elf64_image* image,
Elf64_Sym* symbol, Elf64_Addr* symbolAddress); Elf64_Sym* symbol, Elf64_Addr* symbolAddress);
extern Elf32_Addr boot_elf32_get_relocation(Elf32_Addr resolveAddress);
extern void boot_elf32_set_relocation(Elf32_Addr resolveAddress,
Elf32_Addr finalAddress);
extern void boot_elf64_set_relocation(Elf64_Addr resolveAddress, extern void boot_elf64_set_relocation(Elf64_Addr resolveAddress,
Elf64_Addr finalAddress); Elf64_Addr finalAddress);
#endif #endif

View File

@ -86,13 +86,24 @@ struct ELF32Class {
return status; return status;
*_mappedAddress = (void*)*_address; *_mappedAddress = (void*)*_address;
addr_t res;
platform_bootloader_address_to_kernel_address((void*)*_address, &res);
*_address = res;
return B_OK; return B_OK;
} }
static inline void* static inline void*
Map(AddrType address) Map(AddrType address)
{ {
return (void*)address; void *result = NULL;
if (platform_kernel_address_to_bootloader_address(address, &result) != B_OK) {
panic("Couldn't convert address 0x%08x", (uint32_t)address);
}
return result;
} }
}; };
@ -742,6 +753,20 @@ boot_elf_resolve_symbol(preloaded_elf32_image* image, Elf32_Sym* symbol,
{ {
return ELF32Loader::Resolve(image, symbol, symbolAddress); return ELF32Loader::Resolve(image, symbol, symbolAddress);
} }
Elf32_Addr
boot_elf32_get_relocation(Elf32_Addr resolveAddress)
{
Elf32_Addr* src = (Elf32_Addr*)ELF32Class::Map(resolveAddress);
return *src;
}
void
boot_elf32_set_relocation(Elf32_Addr resolveAddress, Elf32_Addr finalAddress)
{
Elf32_Addr* dest = (Elf32_Addr*)ELF32Class::Map(resolveAddress);
*dest = finalAddress;
}
#endif #endif

View File

@ -220,7 +220,11 @@ arch_elf_relocate_rel(struct elf_image_info *image,
switch (ELF32_R_TYPE(rel[i].r_info)) { switch (ELF32_R_TYPE(rel[i].r_info)) {
case R_ARM_ABS32: case R_ARM_ABS32:
case R_ARM_RELATIVE: case R_ARM_RELATIVE:
#ifndef _BOOT_MODE
A = *(addr_t *)(image->text_region.delta + rel[i].r_offset); A = *(addr_t *)(image->text_region.delta + rel[i].r_offset);
#else
A = boot_elf32_get_relocation(image->text_region.delta + rel[i].r_offset);
#endif
TRACE(("A %p\n", (void *)A)); TRACE(("A %p\n", (void *)A));
break; break;
} }
@ -252,8 +256,10 @@ arch_elf_relocate_rel(struct elf_image_info *image,
rel[i].r_offset); rel[i].r_offset);
return B_BAD_ADDRESS; return B_BAD_ADDRESS;
} }
#endif
*resolveAddress = finalAddress; *resolveAddress = finalAddress;
#else
boot_elf32_set_relocation((Elf32_Addr)resolveAddress, finalAddress);
#endif
TRACE(("-> offset %#lx = %#lx\n", TRACE(("-> offset %#lx = %#lx\n",
(image->text_region.delta + rel[i].r_offset), finalAddress)); (image->text_region.delta + rel[i].r_offset), finalAddress));
} }

View File

@ -113,7 +113,11 @@ arch_elf_relocate_rel(struct elf_image_info *image,
case R_386_RELATIVE: case R_386_RELATIVE:
case R_386_GOTOFF: case R_386_GOTOFF:
case R_386_GOTPC: case R_386_GOTPC:
#ifndef _BOOT_MODE
A = *(uint32 *)(image->text_region.delta + rel[i].r_offset); A = *(uint32 *)(image->text_region.delta + rel[i].r_offset);
#else
A = boot_elf32_get_relocation(image->text_region.delta + rel[i].r_offset);
#endif
TRACE(("A %p\n", (void *)A)); TRACE(("A %p\n", (void *)A));
break; break;
} }
@ -159,8 +163,10 @@ arch_elf_relocate_rel(struct elf_image_info *image,
rel[i].r_offset); rel[i].r_offset);
return B_BAD_ADDRESS; return B_BAD_ADDRESS;
} }
#endif
*resolveAddress = finalAddress; *resolveAddress = finalAddress;
#else
boot_elf32_set_relocation((Elf32_Addr)resolveAddress, finalAddress);
#endif
TRACE(("-> offset %#lx (%#lx) = %#lx\n", TRACE(("-> offset %#lx (%#lx) = %#lx\n",
(image->text_region.delta + rel[i].r_offset), rel[i].r_offset, finalAddress)); (image->text_region.delta + rel[i].r_offset), rel[i].r_offset, finalAddress));
} }