1 /* 2 * Copyright 2003-2006, Axel Dörfler, axeld@pinc-software.de 3 * Distributed under the terms of the MIT License. 4 * 5 * Copyright 2001, Travis Geiselbrecht. All rights reserved. 6 * Copyright 2002, Manuel J. Petit. All rights reserved. 7 * Distributed under the terms of the NewOS License. 8 */ 9 10 11 #include "runtime_loader_private.h" 12 13 #include <runtime_loader.h> 14 15 #include <string.h> 16 #include <stdio.h> 17 #include <stdlib.h> 18 19 20 //#define TRACE_RLD 21 #ifdef TRACE_RLD 22 # define TRACE(x) dprintf x 23 #else 24 # define TRACE(x) ; 25 #endif 26 27 28 static inline void 29 write_32(addr_t *P, Elf32_Word value) 30 { 31 *(Elf32_Word*)P = value; 32 } 33 34 35 static inline void 36 write_16(addr_t *P, Elf32_Word value) 37 { 38 // bits 16:29 39 *(Elf32_Half*)P = (Elf32_Half)value; 40 } 41 42 43 static inline bool 44 write_16_check(addr_t *P, Elf32_Word value) 45 { 46 // bits 15:0 47 if ((value & 0xffff0000) && (~value & 0xffff8000)) 48 return false; 49 *(Elf32_Half*)P = (Elf32_Half)value; 50 return true; 51 } 52 53 54 static inline bool 55 write_8(addr_t *P, Elf32_Word value) 56 { 57 // bits 7:0 58 *(uint8 *)P = (uint8)value; 59 return true; 60 } 61 62 63 static inline bool 64 write_8_check(addr_t *P, Elf32_Word value) 65 { 66 // bits 7:0 67 if ((value & 0xffffff00) && (~value & 0xffffff80)) 68 return false; 69 *(uint8 *)P = (uint8)value; 70 return true; 71 } 72 73 74 static int 75 relocate_rela(image_t *rootImage, image_t *image, struct Elf32_Rela *rel, 76 int rel_len) 77 { 78 int i; 79 addr_t S; 80 addr_t final_val; 81 82 # define P ((addr_t *)(image->regions[0].delta + rel[i].r_offset)) 83 //# define A (*(P)) 84 #define A ((addr_t)rel[i].r_addend) 85 # define B (image->regions[0].delta) 86 87 for (i = 0; i * (int)sizeof(struct Elf32_Rel) < rel_len; i++) { 88 unsigned type = ELF32_R_TYPE(rel[i].r_info); 89 90 switch (type) { 91 case R_68K_32: 92 case R_68K_16: 93 case R_68K_8: 94 case R_68K_PC32: 95 case R_68K_PC16: 96 case R_68K_PC8: 97 case R_68K_GLOB_DAT: 98 case R_68K_JMP_SLOT: 99 { 100 struct Elf32_Sym *sym; 101 status_t status; 102 sym = SYMBOL(image, ELF32_R_SYM(rel[i].r_info)); 103 104 status = resolve_symbol(rootImage, image, sym, &S); 105 if (status < B_OK) { 106 TRACE(("resolve symbol \"%s\" returned: %ld\n", 107 SYMNAME(image, sym), status)); 108 printf("resolve symbol \"%s\" returned: %ld\n", 109 SYMNAME(image, sym), status); 110 return status; 111 } 112 } 113 } 114 switch (type) { 115 case R_68K_NONE: 116 continue; 117 case R_68K_32: 118 write_32(P, S + A); 119 break; 120 case R_68K_16: 121 if (write_16_check(P, S + A)) 122 break; 123 TRACE(("R_68K_16 overflow\n")); 124 return B_BAD_DATA; 125 126 case R_68K_8: 127 if (write_8_check(P, S + A)) 128 break; 129 TRACE(("R_68K_8 overflow\n")); 130 return B_BAD_DATA; 131 132 case R_68K_PC32: 133 write_32(P, (S + A - (addr_t)P)); 134 break; 135 136 #if 0 137 case R_68K_PC16: 138 if (write_16_check(P, (S + A - P))) 139 break; 140 TRACE(("R_68K_PC16 overflow\n")); 141 return B_BAD_DATA; 142 143 case R_68K_PC8: 144 if (write_8(P, (S + A - P))) 145 break; 146 TRACE(("R_68K_PC8 overflow\n")); 147 return B_BAD_DATA; 148 149 case R_68K_GOT32: 150 REQUIRE_GOT; 151 write_32(P, (G + A - P)); 152 break; 153 154 case R_68K_GOT16: 155 REQUIRE_GOT; 156 if (write_16_check(P, (G + A - P))) 157 break; 158 TRACE(("R_68K_GOT16 overflow\n")); 159 return B_BAD_DATA; 160 161 case R_68K_GOT8: 162 REQUIRE_GOT; 163 if (write_8_check(P, (G + A - P))) 164 break; 165 TRACE(("R_68K_GOT8 overflow\n")); 166 return B_BAD_DATA; 167 168 case R_68K_GOT32O: 169 REQUIRE_GOT; 170 write_32(P, (G + A)); 171 break; 172 173 case R_68K_GOT16O: 174 REQUIRE_GOT; 175 if (write_16_check(P, (G + A))) 176 break; 177 TRACE(("R_68K_GOT16 overflow\n")); 178 return B_BAD_DATA; 179 180 case R_68K_GOT8O: 181 REQUIRE_GOT; 182 if (write_8_check(P, (G + A))) 183 break; 184 TRACE(("R_68K_GOT8 overflow\n")); 185 return B_BAD_DATA; 186 187 case R_68K_PLT32: 188 REQUIRE_PLT; 189 write_32(P, (L + A - P)); 190 break; 191 192 case R_68K_PLT16: 193 REQUIRE_PLT; 194 if (write_16_check(P, (L + A - P))) 195 break; 196 TRACE(("R_68K_PLT16 overflow\n")); 197 return B_BAD_DATA; 198 199 case R_68K_PLT8: 200 REQUIRE_PLT; 201 if (write_8_check(P, (L + A - P))) 202 break; 203 TRACE(("R_68K_PLT8 overflow\n")); 204 return B_BAD_DATA; 205 206 case R_68K_PLT32O: 207 REQUIRE_PLT; 208 write_32(P, (L + A)); 209 break; 210 211 case R_68K_PLT16O: 212 REQUIRE_PLT; 213 if (write_16_check(P, (L + A))) 214 break; 215 TRACE(("R_68K_PLT16O overflow\n")); 216 return B_BAD_DATA; 217 218 case R_68K_PLT8O: 219 REQUIRE_PLT; 220 if (write_8_check(P, (L + A))) 221 break; 222 TRACE(("R_68K_PLT8O overflow\n")); 223 return B_BAD_DATA; 224 case R_386_GOT32: 225 final_val = G + A; 226 break; 227 case R_386_PLT32: 228 final_val = L + A - (addr_t)P; 229 break; 230 #endif 231 case R_68K_COPY: 232 /* what ? */ 233 continue; 234 case R_68K_GLOB_DAT: 235 write_32(P, S/* + A*/); 236 break; 237 case R_68K_JMP_SLOT: 238 //XXX ? write_32(P, (G + A)); 239 write_32(P, S); 240 break; 241 #if 0 242 case R_386_JMP_SLOT: 243 write_32(P, S); 244 break; 245 #endif 246 case R_68K_RELATIVE: 247 write_32(P, B + A); 248 break; 249 250 #if 0 251 case R_386_GOTOFF: 252 final_val = S + A - GOT; 253 break; 254 case R_386_GOTPC: 255 final_val = GOT + A - P; 256 break; 257 #endif 258 default: 259 TRACE(("unhandled relocation type %d\n", ELF32_R_TYPE(rel[i].r_info))); 260 return B_NOT_ALLOWED; 261 } 262 263 *P = final_val; 264 } 265 266 # undef P 267 # undef A 268 # undef B 269 270 return B_NO_ERROR; 271 } 272 273 274 status_t 275 arch_relocate_image(image_t *rootImage, image_t *image) 276 { 277 status_t status; 278 279 // deal with the rels first 280 if (image->rel) { 281 TRACE(("RELA relocations not supported\n")); 282 return EOPNOTSUPP; 283 } 284 285 if (image->pltrel) { 286 TRACE(("RELA relocations not supported\n")); 287 return EOPNOTSUPP; 288 #if 0 289 status = relocate_rel(rootImage, image, image->pltrel, 290 image->pltrel_len); 291 if (status < B_OK) 292 return status; 293 #endif 294 } 295 296 if (image->rela) { 297 status = relocate_rela(rootImage, image, image->rela, image->rela_len); 298 //int i; 299 if (status < B_OK) 300 return status; 301 //TRACE(("RELA relocations not supported\n")); 302 //return EOPNOTSUPP; 303 304 //for (i = 1; i * (int)sizeof(struct Elf32_Rela) < image->rela_len; i++) { 305 // printf("rela: type %d\n", ELF32_R_TYPE(image->rela[i].r_info)); 306 //} 307 } 308 309 #if 0 310 if (image->pltrela) { 311 status = relocate_rela(rootImage, image, image->pltrela, 312 image->pltrela_len); 313 if (status < B_OK) 314 return status; 315 } 316 #endif 317 318 return B_OK; 319 } 320