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 + image->text_region.size) 33 || (address >= image->data_region.start 34 && address < image->data_region.start + image->data_region.size); 35 } 36 #endif // !_BOOT_MODE 37 38 39 #ifdef _BOOT_MODE 40 status_t 41 boot_arch_elf_relocate_rel(preloaded_elf64_image* image, Elf64_Rel* rel, 42 int relLength) 43 #else 44 int 45 arch_elf_relocate_rel(struct elf_image_info *image, 46 struct elf_image_info *resolveImage, Elf64_Rel *rel, int relLength) 47 #endif 48 { 49 dprintf("arch_elf_relocate_rel: not supported on arm64\n"); 50 return B_ERROR; 51 } 52 53 54 #ifdef _BOOT_MODE 55 status_t 56 boot_arch_elf_relocate_rela(preloaded_elf64_image* image, Elf64_Rela* rel, 57 int relLength) 58 #else 59 int 60 arch_elf_relocate_rela(struct elf_image_info *image, 61 struct elf_image_info *resolveImage, Elf64_Rela *rel, int relLength) 62 #endif 63 { 64 for (int i = 0; i < relLength / (int)sizeof(Elf64_Rela); i++) { 65 int type = ELF64_R_TYPE(rel[i].r_info); 66 int symIndex = ELF64_R_SYM(rel[i].r_info); 67 Elf64_Addr symAddr = 0; 68 69 // Resolve the symbol, if any. 70 if (symIndex != 0) { 71 Elf64_Sym* symbol = SYMBOL(image, symIndex); 72 73 status_t status; 74 #ifdef _BOOT_MODE 75 status = boot_elf_resolve_symbol(image, symbol, &symAddr); 76 #else 77 status = elf_resolve_symbol(image, symbol, resolveImage, &symAddr); 78 #endif 79 if (status < B_OK) 80 return status; 81 } 82 83 // Address of the relocation. 84 Elf64_Addr relocAddr = image->text_region.delta + rel[i].r_offset; 85 86 // Calculate the relocation value. 87 Elf64_Addr relocValue; 88 switch (type) { 89 case R_AARCH64_NONE: 90 continue; 91 case R_AARCH64_ABS64: 92 relocValue = symAddr + rel[i].r_addend; 93 break; 94 case R_AARCH64_ABS32: 95 case R_AARCH64_ABS16: 96 case R_AARCH64_PREL64: 97 case R_AARCH64_PREL32: 98 case R_AARCH64_PREL16: 99 case R_AARCH64_TSTBR14: 100 case R_AARCH64_CONDBR19: 101 case R_AARCH64_JUMP26: 102 case R_AARCH64_CALL26: 103 case R_AARCH64_COPY: 104 dprintf("arch_elf_relocate_rela: unhandled relocation type %d\n", 105 type); 106 return B_BAD_DATA; 107 case R_AARCH64_GLOB_DAT: 108 case R_AARCH64_JUMP_SLOT: 109 relocValue = symAddr + rel[i].r_addend; 110 break; 111 case R_AARCH64_RELATIVE: 112 relocValue = image->text_region.delta + rel[i].r_addend; 113 break; 114 case R_AARCH64_TLS_DTPREL64: 115 case R_AARCH64_TLS_DTPMOD64: 116 case R_AARCH64_TLS_TPREL64: 117 case R_AARCH64_TLSDESC: 118 case R_AARCH64_IRELATIVE: 119 default: 120 dprintf("arch_elf_relocate_rela: unhandled relocation type %d\n", 121 type); 122 return B_BAD_DATA; 123 } 124 125 #ifdef _BOOT_MODE 126 boot_elf64_set_relocation(relocAddr, relocValue); 127 #else 128 if (!is_in_image(image, relocAddr)) { 129 dprintf("arch_elf_relocate_rela: invalid offset %#lx\n", 130 rel[i].r_offset); 131 return B_BAD_ADDRESS; 132 } 133 *(Elf64_Addr *)relocAddr = relocValue; 134 #endif 135 } 136 137 return B_OK; 138 } 139