1 /* 2 * Copyright 2004-2018 Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * Copyright 2002, Travis Geiselbrecht. All rights reserved. 5 * Distributed under the terms of the NewOS License. 6 */ 7 8 9 #ifdef _BOOT_MODE 10 # include <boot/arch.h> 11 #endif 12 13 #include <KernelExport.h> 14 15 #include <elf_priv.h> 16 #include <arch/elf.h> 17 18 19 //#define TRACE_ARCH_ELF 20 #ifdef TRACE_ARCH_ELF 21 # define TRACE(x) dprintf x 22 #else 23 # define TRACE(x) ; 24 #endif 25 26 27 #ifndef _BOOT_MODE 28 static bool 29 is_in_image(struct elf_image_info *image, addr_t address) 30 { 31 return (address >= image->text_region.start 32 && address < image->text_region.start 33 + image->text_region.size) 34 || (address >= image->data_region.start 35 && address < image->data_region.start 36 + image->data_region.size); 37 } 38 #endif // !_BOOT_MODE 39 40 41 #ifdef _BOOT_MODE 42 status_t 43 boot_arch_elf_relocate_rel(preloaded_elf64_image* image, Elf64_Rel* rel, 44 int relLength) 45 #else 46 int 47 arch_elf_relocate_rel(struct elf_image_info *image, 48 struct elf_image_info *resolveImage, Elf64_Rel *rel, int relLength) 49 #endif 50 { 51 dprintf("arch_elf_relocate_rel: not supported on riscv64\n"); 52 return B_ERROR; 53 } 54 55 56 #ifdef _BOOT_MODE 57 status_t 58 boot_arch_elf_relocate_rela(preloaded_elf64_image* image, Elf64_Rela* rel, 59 int relLength) 60 #else 61 int 62 arch_elf_relocate_rela(struct elf_image_info *image, 63 struct elf_image_info *resolveImage, Elf64_Rela *rel, int relLength) 64 #endif 65 { 66 for (int i = 0; i < relLength / (int)sizeof(Elf64_Rela); i++) { 67 int type = ELF64_R_TYPE(rel[i].r_info); 68 int symIndex = ELF64_R_SYM(rel[i].r_info); 69 Elf64_Addr symAddr = 0; 70 71 // Resolve the symbol, if any. 72 if (symIndex != 0) { 73 Elf64_Sym* symbol = SYMBOL(image, symIndex); 74 75 status_t status; 76 #ifdef _BOOT_MODE 77 status = boot_elf_resolve_symbol(image, symbol, 78 &symAddr); 79 #else 80 status = elf_resolve_symbol(image, symbol, resolveImage, 81 &symAddr); 82 #endif 83 if (status < B_OK) 84 return status; 85 } 86 87 // Address of the relocation. 88 Elf64_Addr relocAddr = image->text_region.delta 89 + rel[i].r_offset; 90 91 // Calculate the relocation value. 92 Elf64_Addr relocValue; 93 switch (type) { 94 case R_RISCV_NONE: 95 continue; 96 case R_RISCV_64: 97 case R_RISCV_JUMP_SLOT: 98 relocValue = symAddr + rel[i].r_addend; 99 break; 100 case R_RISCV_RELATIVE: 101 relocValue = image->text_region.delta 102 + rel[i].r_addend; 103 break; 104 default: 105 dprintf("arch_elf_relocate_rela: unhandled" 106 "relocation type %d\n", type); 107 return B_BAD_DATA; 108 } 109 #ifdef _BOOT_MODE 110 boot_elf64_set_relocation(relocAddr, relocValue); 111 #else 112 if (!is_in_image(image, relocAddr)) { 113 dprintf("arch_elf_relocate_rela: invalid offset %#lx\n", 114 rel[i].r_offset); 115 return B_BAD_ADDRESS; 116 } 117 *(Elf64_Addr *)relocAddr = relocValue; 118 #endif 119 } 120 121 return B_OK; 122 } 123