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_image *image, 80 struct Elf32_Rel *rel, int rel_len) 81 #else 82 int 83 arch_elf_relocate_rel(struct elf_image_info *image, const char *sym_prepend, 84 struct elf_image_info *resolve_image, struct 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_image *image, 141 struct Elf32_Rela *rel, int rel_len) 142 #else 143 int 144 arch_elf_relocate_rela(struct elf_image_info *image, const char *sym_prepend, 145 struct elf_image_info *resolve_image, struct Elf32_Rela *rel, int rel_len) 146 #endif 147 { 148 int i; 149 struct Elf32_Sym *sym; 150 int vlErr; 151 addr_t 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(struct 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, 195 sym_prepend, &S); 196 #endif 197 if (vlErr < 0) { 198 dprintf("%s(): Failed to relocate " 199 "entry index %d, rel type %d, offset 0x%lx, sym 0x%lx, " 200 "addend 0x%lx\n", __FUNCTION__, i, ELF32_R_TYPE(rel[i].r_info), 201 rel[i].r_offset, ELF32_R_SYM(rel[i].r_info), 202 rel[i].r_addend); 203 return vlErr; 204 } 205 break; 206 } 207 208 switch (ELF32_R_TYPE(rel[i].r_info)) { 209 case R_68K_NONE: 210 break; 211 212 case R_68K_COPY: 213 // TODO: Implement! 214 dprintf("arch_elf_relocate_rela(): R_68K_COPY not yet " 215 "supported!\n"); 216 return B_ERROR; 217 218 case R_68K_32: 219 case R_68K_GLOB_DAT: 220 write_32(P, S + A); 221 break; 222 223 case R_68K_16: 224 if (write_16_check(P, S + A)) 225 break; 226 dprintf("R_68K_16 overflow\n"); 227 return B_BAD_DATA; 228 229 case R_68K_8: 230 if (write_8_check(P, S + A)) 231 break; 232 dprintf("R_68K_8 overflow\n"); 233 return B_BAD_DATA; 234 235 case R_68K_PC32: 236 write_32(P, (S + A - P)); 237 break; 238 239 case R_68K_PC16: 240 if (write_16_check(P, (S + A - P))) 241 break; 242 dprintf("R_68K_PC16 overflow\n"); 243 return B_BAD_DATA; 244 245 case R_68K_PC8: 246 if (write_8(P, (S + A - P))) 247 break; 248 dprintf("R_68K_PC8 overflow\n"); 249 return B_BAD_DATA; 250 251 case R_68K_GOT32: 252 REQUIRE_GOT; 253 write_32(P, (G + A - P)); 254 break; 255 256 case R_68K_GOT16: 257 REQUIRE_GOT; 258 if (write_16_check(P, (G + A - P))) 259 break; 260 dprintf("R_68K_GOT16 overflow\n"); 261 return B_BAD_DATA; 262 263 case R_68K_GOT8: 264 REQUIRE_GOT; 265 if (write_8_check(P, (G + A - P))) 266 break; 267 dprintf("R_68K_GOT8 overflow\n"); 268 return B_BAD_DATA; 269 270 case R_68K_GOT32O: 271 REQUIRE_GOT; 272 write_32(P, (G + A)); 273 break; 274 275 case R_68K_GOT16O: 276 REQUIRE_GOT; 277 if (write_16_check(P, (G + A))) 278 break; 279 dprintf("R_68K_GOT16 overflow\n"); 280 return B_BAD_DATA; 281 282 case R_68K_GOT8O: 283 REQUIRE_GOT; 284 if (write_8_check(P, (G + A))) 285 break; 286 dprintf("R_68K_GOT8 overflow\n"); 287 return B_BAD_DATA; 288 289 case R_68K_JMP_SLOT: 290 write_32(P, (G + A)); 291 break; 292 293 case R_68K_RELATIVE: 294 write_32(P, B + A); 295 break; 296 297 case R_68K_PLT32: 298 REQUIRE_PLT; 299 write_32(P, (L + A - P)); 300 break; 301 302 case R_68K_PLT16: 303 REQUIRE_PLT; 304 if (write_16_check(P, (L + A - P))) 305 break; 306 dprintf("R_68K_PLT16 overflow\n"); 307 return B_BAD_DATA; 308 309 case R_68K_PLT8: 310 REQUIRE_PLT; 311 if (write_8_check(P, (L + A - P))) 312 break; 313 dprintf("R_68K_PLT8 overflow\n"); 314 return B_BAD_DATA; 315 316 case R_68K_PLT32O: 317 REQUIRE_PLT; 318 write_32(P, (L + A)); 319 break; 320 321 case R_68K_PLT16O: 322 REQUIRE_PLT; 323 if (write_16_check(P, (L + A))) 324 break; 325 dprintf("R_68K_PLT16O overflow\n"); 326 return B_BAD_DATA; 327 328 case R_68K_PLT8O: 329 REQUIRE_PLT; 330 if (write_8_check(P, (L + A))) 331 break; 332 dprintf("R_68K_PLT8O overflow\n"); 333 return B_BAD_DATA; 334 335 default: 336 dprintf("arch_elf_relocate_rela: unhandled relocation type %d\n", ELF32_R_TYPE(rel[i].r_info)); 337 return B_ERROR; 338 } 339 } 340 341 return B_NO_ERROR; 342 } 343 344 345 346