1 /* 2 * Copyright 2004-2008, Haiku Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT license. 4 * 5 * Copyright 2002, Travis Geiselbrecht. All rights reserved. 6 * Distributed under the terms of the NewOS License. 7 */ 8 9 10 #ifdef _BOOT_MODE 11 # include <boot/arch.h> 12 #endif 13 14 #include <KernelExport.h> 15 16 #include <elf_priv.h> 17 #include <arch/elf.h> 18 19 20 //#define TRACE_ARCH_ELF 21 #ifdef TRACE_ARCH_ELF 22 # define TRACE(x) dprintf x 23 #else 24 # define TRACE(x) ; 25 #endif 26 27 28 #ifdef TRACE_ARCH_ELF 29 static const char *kRelocations[] = { 30 "R_386_NONE", 31 "R_386_32", /* add symbol value */ 32 "R_386_PC32", /* add PC relative symbol value */ 33 "R_386_GOT32", /* add PC relative GOT offset */ 34 "R_386_PLT32", /* add PC relative PLT offset */ 35 "R_386_COPY", /* copy data from shared object */ 36 "R_386_GLOB_DAT", /* set GOT entry to data address */ 37 "R_386_JMP_SLOT", /* set GOT entry to code address */ 38 "R_386_RELATIVE", /* add load address of shared object */ 39 "R_386_GOTOFF", /* add GOT relative symbol address */ 40 "R_386_GOTPC", /* add PC relative GOT table address */ 41 }; 42 #endif 43 44 45 #ifndef _BOOT_MODE 46 static bool 47 is_in_image(struct elf_image_info *image, addr_t address) 48 { 49 return (address >= image->text_region.start 50 && address < image->text_region.start + image->text_region.size) 51 || (address >= image->data_region.start 52 && address < image->data_region.start + image->data_region.size); 53 } 54 #endif // !_BOOT_MODE 55 56 57 #ifdef _BOOT_MODE 58 status_t 59 boot_arch_elf_relocate_rel(struct preloaded_image *image, 60 struct Elf32_Rel *rel, int relLength) 61 #else 62 int 63 arch_elf_relocate_rel(struct elf_image_info *image, 64 struct elf_image_info *resolveImage, struct Elf32_Rel *rel, int relLength) 65 #endif 66 { 67 addr_t S; 68 addr_t A; 69 addr_t P; 70 addr_t finalAddress; 71 addr_t *resolveAddress; 72 int i; 73 74 S = A = P = 0; 75 76 for (i = 0; i * (int)sizeof(struct Elf32_Rel) < relLength; i++) { 77 TRACE(("looking at rel type %s, offset 0x%lx\n", 78 kRelocations[ELF32_R_TYPE(rel[i].r_info)], rel[i].r_offset)); 79 80 // calc S 81 switch (ELF32_R_TYPE(rel[i].r_info)) { 82 case R_386_32: 83 case R_386_PC32: 84 case R_386_GLOB_DAT: 85 case R_386_JMP_SLOT: 86 case R_386_GOTOFF: 87 { 88 struct Elf32_Sym *symbol; 89 status_t status; 90 91 symbol = SYMBOL(image, ELF32_R_SYM(rel[i].r_info)); 92 93 #ifdef _BOOT_MODE 94 status = boot_elf_resolve_symbol(image, symbol, &S); 95 #else 96 status = elf_resolve_symbol(image, symbol, resolveImage, &S); 97 #endif 98 if (status < B_OK) 99 return status; 100 TRACE(("S %p (%s)\n", (void *)S, SYMNAME(image, symbol))); 101 } 102 } 103 // calc A 104 switch (ELF32_R_TYPE(rel[i].r_info)) { 105 case R_386_32: 106 case R_386_PC32: 107 case R_386_GOT32: 108 case R_386_PLT32: 109 case R_386_RELATIVE: 110 case R_386_GOTOFF: 111 case R_386_GOTPC: 112 A = *(addr_t *)(image->text_region.delta + rel[i].r_offset); 113 TRACE(("A %p\n", (void *)A)); 114 break; 115 } 116 // calc P 117 switch (ELF32_R_TYPE(rel[i].r_info)) { 118 case R_386_PC32: 119 case R_386_GOT32: 120 case R_386_PLT32: 121 case R_386_GOTPC: 122 P = image->text_region.delta + rel[i].r_offset; 123 TRACE(("P %p\n", (void *)P)); 124 break; 125 } 126 127 switch (ELF32_R_TYPE(rel[i].r_info)) { 128 case R_386_NONE: 129 continue; 130 case R_386_32: 131 finalAddress = S + A; 132 break; 133 case R_386_PC32: 134 finalAddress = S + A - P; 135 break; 136 case R_386_RELATIVE: 137 // B + A; 138 finalAddress = image->text_region.delta + A; 139 break; 140 case R_386_JMP_SLOT: 141 case R_386_GLOB_DAT: 142 finalAddress = S; 143 break; 144 145 default: 146 dprintf("arch_elf_relocate_rel: unhandled relocation type %d\n", 147 ELF32_R_TYPE(rel[i].r_info)); 148 return B_BAD_DATA; 149 } 150 151 resolveAddress = (addr_t *)(image->text_region.delta + rel[i].r_offset); 152 #ifndef _BOOT_MODE 153 if (!is_in_image(image, (addr_t)resolveAddress)) { 154 dprintf("arch_elf_relocate_rel: invalid offset %#lx\n", 155 rel[i].r_offset); 156 return B_BAD_ADDRESS; 157 } 158 #endif 159 *resolveAddress = finalAddress; 160 TRACE(("-> offset %#lx = %#lx\n", 161 (image->text_region.delta + rel[i].r_offset), finalAddress)); 162 } 163 164 return B_NO_ERROR; 165 } 166 167 168 #ifdef _BOOT_MODE 169 status_t 170 boot_arch_elf_relocate_rela(struct preloaded_image *image, 171 struct Elf32_Rela *rel, int relLength) 172 #else 173 int 174 arch_elf_relocate_rela(struct elf_image_info *image, 175 struct elf_image_info *resolveImage, struct Elf32_Rela *rel, int relLength) 176 #endif 177 { 178 dprintf("arch_elf_relocate_rela: not supported on x86\n"); 179 return B_ERROR; 180 } 181 182