1 /* 2 * Copyright 2007, François Revol, revol@free.fr. 3 * Distributed under the terms of the MIT License. 4 * 5 * Copyright 2005, Ingo Weinhold <bonefish@cs.tu-berlin.de>. 6 * All rights reserved. Distributed under the terms of the MIT License. 7 * 8 * 9 * Copyright 2002, Travis Geiselbrecht. All rights reserved. 10 * Distributed under the terms of the NewOS License. 11 */ 12 13 #ifdef _BOOT_MODE 14 #include <boot/arch.h> 15 #endif 16 17 #include <KernelExport.h> 18 19 #include <elf_priv.h> 20 #include <arch/elf.h> 21 22 23 //#define TRACE_ARCH_ELF 24 #ifdef TRACE_ARCH_ELF 25 # define TRACE(x) dprintf x 26 # define CHATTY 1 27 #else 28 # define TRACE(x) ; 29 # define CHATTY 0 30 #endif 31 32 33 #ifdef TRACE_ARCH_ELF 34 static const char *kRelocations[] = { 35 "R_68K_NONE", 36 "R_68K_32", /* Direct 32 bit */ 37 "R_68K_16", /* Direct 16 bit */ 38 "R_68K_8", /* Direct 8 bit */ 39 "R_68K_PC32", /* PC relative 32 bit */ 40 "R_68K_PC16", /* PC relative 16 bit */ 41 "R_68K_PC8", /* PC relative 8 bit */ 42 "R_68K_GOT32", /* 32 bit PC relative GOT entry */ 43 "R_68K_GOT16", /* 16 bit PC relative GOT entry */ 44 "R_68K_GOT8", /* 8 bit PC relative GOT entry */ 45 "R_68K_GOT32O", /* 32 bit GOT offset */ 46 "R_68K_GOT16O", /* 16 bit GOT offset */ 47 "R_68K_GOT8O", /* 8 bit GOT offset */ 48 "R_68K_PLT32", /* 32 bit PC relative PLT address */ 49 "R_68K_PLT16", /* 16 bit PC relative PLT address */ 50 "R_68K_PLT8", /* 8 bit PC relative PLT address */ 51 "R_68K_PLT32O", /* 32 bit PLT offset */ 52 "R_68K_PLT16O", /* 16 bit PLT offset */ 53 "R_68K_PLT8O", /* 8 bit PLT offset */ 54 "R_68K_COPY", /* Copy symbol at runtime */ 55 "R_68K_GLOB_DAT", /* Create GOT entry */ 56 "R_68K_JMP_SLOT", /* Create PLT entry */ 57 "R_68K_RELATIVE", /* Adjust by program base */ 58 /* These are GNU extensions to enable C++ vtable garbage collection. */ 59 "R_68K_GNU_VTINHERIT", 60 "R_68K_GNU_VTENTRY", 61 #if 0 62 "R_386_NONE", 63 "R_386_32", /* add symbol value */ 64 "R_386_PC32", /* add PC relative symbol value */ 65 "R_386_GOT32", /* add PC relative GOT offset */ 66 "R_386_PLT32", /* add PC relative PLT offset */ 67 "R_386_COPY", /* copy data from shared object */ 68 "R_386_GLOB_DAT", /* set GOT entry to data address */ 69 "R_386_JMP_SLOT", /* set GOT entry to code address */ 70 "R_386_RELATIVE", /* add load address of shared object */ 71 "R_386_GOTOFF", /* add GOT relative symbol address */ 72 "R_386_GOTPC", /* add PC relative GOT table address */ 73 #endif 74 }; 75 #endif 76 77 #ifdef _BOOT_MODE 78 status_t 79 boot_arch_elf_relocate_rel(struct preloaded_elf32_image *image, Elf32_Rel *rel, 80 int rel_len) 81 #else 82 int 83 arch_elf_relocate_rel(struct elf_image_info *image, 84 struct elf_image_info *resolve_image, Elf32_Rel *rel, int rel_len) 85 #endif 86 { 87 // there are no rel entries in M68K elf 88 return B_NO_ERROR; 89 } 90 91 92 static inline void 93 write_32(addr_t P, Elf32_Word value) 94 { 95 *(Elf32_Word*)P = value; 96 } 97 98 99 static inline void 100 write_16(addr_t P, Elf32_Word value) 101 { 102 // bits 16:29 103 *(Elf32_Half*)P = (Elf32_Half)value; 104 } 105 106 107 static inline bool 108 write_16_check(addr_t P, Elf32_Word value) 109 { 110 // bits 15:0 111 if ((value & 0xffff0000) && (~value & 0xffff8000)) 112 return false; 113 *(Elf32_Half*)P = (Elf32_Half)value; 114 return true; 115 } 116 117 118 static inline bool 119 write_8(addr_t P, Elf32_Word value) 120 { 121 // bits 7:0 122 *(uint8 *)P = (uint8)value; 123 return true; 124 } 125 126 127 static inline bool 128 write_8_check(addr_t P, Elf32_Word value) 129 { 130 // bits 7:0 131 if ((value & 0xffffff00) && (~value & 0xffffff80)) 132 return false; 133 *(uint8 *)P = (uint8)value; 134 return true; 135 } 136 137 138 #ifdef _BOOT_MODE 139 status_t 140 boot_arch_elf_relocate_rela(struct preloaded_elf32_image *image, 141 Elf32_Rela *rel, int rel_len) 142 #else 143 int 144 arch_elf_relocate_rela(struct elf_image_info *image, 145 struct elf_image_info *resolve_image, Elf32_Rela *rel, int rel_len) 146 #endif 147 { 148 int i; 149 Elf32_Sym *sym; 150 int vlErr; 151 elf_addr S = 0; // symbol address 152 addr_t R = 0; // section relative symbol address 153 154 addr_t G = 0; // GOT address 155 addr_t L = 0; // PLT address 156 157 #define P ((addr_t)(image->text_region.delta + rel[i].r_offset)) 158 #define A ((addr_t)rel[i].r_addend) 159 #define B (image->text_region.delta) 160 161 // TODO: Get the GOT address! 162 #define REQUIRE_GOT \ 163 if (G == 0) { \ 164 dprintf("arch_elf_relocate_rela(): Failed to get GOT address!\n"); \ 165 return B_ERROR; \ 166 } 167 168 // TODO: Get the PLT address! 169 #define REQUIRE_PLT \ 170 if (L == 0) { \ 171 dprintf("arch_elf_relocate_rela(): Failed to get PLT address!\n"); \ 172 return B_ERROR; \ 173 } 174 175 for (i = 0; i * (int)sizeof(Elf32_Rela) < rel_len; i++) { 176 #if CHATTY 177 dprintf("looking at rel type %d, offset 0x%lx, sym 0x%lx, addend 0x%lx\n", 178 ELF32_R_TYPE(rel[i].r_info), rel[i].r_offset, ELF32_R_SYM(rel[i].r_info), rel[i].r_addend); 179 #endif 180 switch (ELF32_R_TYPE(rel[i].r_info)) { 181 case R_68K_32: 182 case R_68K_16: 183 case R_68K_8: 184 case R_68K_PC32: 185 case R_68K_PC16: 186 case R_68K_PC8: 187 case R_68K_GLOB_DAT: 188 case R_68K_JMP_SLOT: 189 sym = SYMBOL(image, ELF32_R_SYM(rel[i].r_info)); 190 191 #ifdef _BOOT_MODE 192 vlErr = boot_elf_resolve_symbol(image, sym, &S); 193 #else 194 vlErr = elf_resolve_symbol(image, sym, resolve_image, &S); 195 #endif 196 if (vlErr < 0) { 197 dprintf("%s(): Failed to relocate " 198 "entry index %d, rel type %d, offset 0x%lx, sym 0x%lx, " 199 "addend 0x%lx\n", __FUNCTION__, i, ELF32_R_TYPE(rel[i].r_info), 200 rel[i].r_offset, ELF32_R_SYM(rel[i].r_info), 201 rel[i].r_addend); 202 return vlErr; 203 } 204 break; 205 } 206 207 switch (ELF32_R_TYPE(rel[i].r_info)) { 208 case R_68K_NONE: 209 break; 210 211 case R_68K_COPY: 212 // TODO: Implement! 213 dprintf("arch_elf_relocate_rela(): R_68K_COPY not yet " 214 "supported!\n"); 215 return B_ERROR; 216 217 case R_68K_32: 218 case R_68K_GLOB_DAT: 219 write_32(P, S + A); 220 break; 221 222 case R_68K_16: 223 if (write_16_check(P, S + A)) 224 break; 225 dprintf("R_68K_16 overflow\n"); 226 return B_BAD_DATA; 227 228 case R_68K_8: 229 if (write_8_check(P, S + A)) 230 break; 231 dprintf("R_68K_8 overflow\n"); 232 return B_BAD_DATA; 233 234 case R_68K_PC32: 235 write_32(P, (S + A - P)); 236 break; 237 238 case R_68K_PC16: 239 if (write_16_check(P, (S + A - P))) 240 break; 241 dprintf("R_68K_PC16 overflow\n"); 242 return B_BAD_DATA; 243 244 case R_68K_PC8: 245 if (write_8(P, (S + A - P))) 246 break; 247 dprintf("R_68K_PC8 overflow\n"); 248 return B_BAD_DATA; 249 250 case R_68K_GOT32: 251 REQUIRE_GOT; 252 write_32(P, (G + A - P)); 253 break; 254 255 case R_68K_GOT16: 256 REQUIRE_GOT; 257 if (write_16_check(P, (G + A - P))) 258 break; 259 dprintf("R_68K_GOT16 overflow\n"); 260 return B_BAD_DATA; 261 262 case R_68K_GOT8: 263 REQUIRE_GOT; 264 if (write_8_check(P, (G + A - P))) 265 break; 266 dprintf("R_68K_GOT8 overflow\n"); 267 return B_BAD_DATA; 268 269 case R_68K_GOT32O: 270 REQUIRE_GOT; 271 write_32(P, (G + A)); 272 break; 273 274 case R_68K_GOT16O: 275 REQUIRE_GOT; 276 if (write_16_check(P, (G + A))) 277 break; 278 dprintf("R_68K_GOT16 overflow\n"); 279 return B_BAD_DATA; 280 281 case R_68K_GOT8O: 282 REQUIRE_GOT; 283 if (write_8_check(P, (G + A))) 284 break; 285 dprintf("R_68K_GOT8 overflow\n"); 286 return B_BAD_DATA; 287 288 case R_68K_JMP_SLOT: 289 write_32(P, S + A); 290 break; 291 292 case R_68K_RELATIVE: 293 write_32(P, B + A); 294 break; 295 296 case R_68K_PLT32: 297 REQUIRE_PLT; 298 write_32(P, (L + A - P)); 299 break; 300 301 case R_68K_PLT16: 302 REQUIRE_PLT; 303 if (write_16_check(P, (L + A - P))) 304 break; 305 dprintf("R_68K_PLT16 overflow\n"); 306 return B_BAD_DATA; 307 308 case R_68K_PLT8: 309 REQUIRE_PLT; 310 if (write_8_check(P, (L + A - P))) 311 break; 312 dprintf("R_68K_PLT8 overflow\n"); 313 return B_BAD_DATA; 314 315 case R_68K_PLT32O: 316 REQUIRE_PLT; 317 write_32(P, (L + A)); 318 break; 319 320 case R_68K_PLT16O: 321 REQUIRE_PLT; 322 if (write_16_check(P, (L + A))) 323 break; 324 dprintf("R_68K_PLT16O overflow\n"); 325 return B_BAD_DATA; 326 327 case R_68K_PLT8O: 328 REQUIRE_PLT; 329 if (write_8_check(P, (L + A))) 330 break; 331 dprintf("R_68K_PLT8O overflow\n"); 332 return B_BAD_DATA; 333 334 default: 335 dprintf("arch_elf_relocate_rela: unhandled relocation type %d\n", ELF32_R_TYPE(rel[i].r_info)); 336 return B_ERROR; 337 } 338 } 339 340 return B_NO_ERROR; 341 } 342 343 344 345