1 /* 2 * common.c 3 * 4 * Created on: Aug 11, 2008 5 * Author: Stefan Bucur <stefanb (at) zytor.com> 6 */ 7 8 #include <stdio.h> 9 #include <elf.h> 10 #include <string.h> 11 #include <fs.h> 12 13 #include <linux/list.h> 14 #include <sys/module.h> 15 16 #include "elfutils.h" 17 #include "common.h" 18 19 /** 20 * The one and only list of loaded modules 21 */ 22 LIST_HEAD(modules_head); 23 24 // User-space debugging routines 25 #ifdef ELF_DEBUG 26 void print_elf_ehdr(Elf_Ehdr *ehdr) { 27 int i; 28 29 fprintf(stderr, "Identification:\t"); 30 for (i=0; i < EI_NIDENT; i++) { 31 printf("%d ", ehdr->e_ident[i]); 32 } 33 fprintf(stderr, "\n"); 34 fprintf(stderr, "Type:\t\t%u\n", ehdr->e_type); 35 fprintf(stderr, "Machine:\t%u\n", ehdr->e_machine); 36 fprintf(stderr, "Version:\t%u\n", ehdr->e_version); 37 fprintf(stderr, "Entry:\t\t0x%08x\n", ehdr->e_entry); 38 fprintf(stderr, "PHT Offset:\t0x%08x\n", ehdr->e_phoff); 39 fprintf(stderr, "SHT Offset:\t0x%08x\n", ehdr->e_shoff); 40 //fprintf(stderr, "Flags:\t\t%u\n", ehdr->e_flags); 41 //fprintf(stderr, "Header size:\t%u (Structure size: %u)\n", ehdr->e_ehsize,sizeof(Elf_Ehdr)); 42 fprintf(stderr, "phnum: %d shnum: %d\n", ehdr->e_phnum, 43 ehdr->e_shnum); 44 } 45 46 void print_elf_symbols(struct elf_module *module) { 47 unsigned int i; 48 Elf_Sym *crt_sym; 49 50 for (i = 1; i < module->symtable_size/module->syment_size; i++) 51 { 52 crt_sym = (Elf_Sym*)(module->sym_table + i*module->syment_size); 53 54 fprintf(stderr,"%s %d\n", module->str_table + crt_sym->st_name, crt_sym->st_value); 55 56 } 57 } 58 #endif //ELF_DEBUG 59 60 FILE *findpath(char *name) 61 { 62 struct path_entry *entry; 63 char path[FILENAME_MAX]; 64 FILE *f; 65 66 f = fopen(name, "rb"); /* for full path */ 67 if (f) 68 return f; 69 70 list_for_each_entry(entry, &PATH, list) { 71 bool slash = false; 72 73 /* Ensure we have a '/' separator */ 74 if (entry->str[strlen(entry->str) - 1] != '/') 75 slash = true; 76 77 snprintf(path, sizeof(path), "%s%s%s", 78 entry->str, slash ? "/" : "", name); 79 80 dprintf("findpath: trying \"%s\"\n", path); 81 f = fopen(path, "rb"); 82 if (f) 83 return f; 84 } 85 86 return NULL; 87 } 88 89 /* 90 * Image files manipulation routines 91 */ 92 93 int image_load(struct elf_module *module) 94 { 95 module->u.l._file = findpath(module->name); 96 97 if (module->u.l._file == NULL) { 98 dprintf("Could not open object file '%s'\n", module->name); 99 goto error; 100 } 101 102 module->u.l._cr_offset = 0; 103 104 return 0; 105 106 error: 107 if (module->u.l._file != NULL) { 108 fclose(module->u.l._file); 109 module->u.l._file = NULL; 110 } 111 112 return -1; 113 } 114 115 116 int image_unload(struct elf_module *module) { 117 if (module->u.l._file != NULL) { 118 fclose(module->u.l._file); 119 module->u.l._file = NULL; 120 121 } 122 module->u.l._cr_offset = 0; 123 124 return 0; 125 } 126 127 int image_read(void *buff, size_t size, struct elf_module *module) { 128 size_t result = fread(buff, size, 1, module->u.l._file); 129 130 if (result < 1) 131 return -1; 132 133 module->u.l._cr_offset += size; 134 return 0; 135 } 136 137 int image_skip(size_t size, struct elf_module *module) { 138 void *skip_buff = NULL; 139 size_t result; 140 141 if (size == 0) 142 return 0; 143 144 skip_buff = malloc(size); 145 result = fread(skip_buff, size, 1, module->u.l._file); 146 free(skip_buff); 147 148 if (result < 1) 149 return -1; 150 151 module->u.l._cr_offset += size; 152 return 0; 153 } 154 155 int image_seek(Elf_Off offset, struct elf_module *module) { 156 if (offset < module->u.l._cr_offset) // Cannot seek backwards 157 return -1; 158 159 return image_skip(offset - module->u.l._cr_offset, module); 160 } 161 162 163 // Initialization of the module subsystem 164 int modules_init(void) { 165 return 0; 166 } 167 168 // Termination of the module subsystem 169 void modules_term(void) { 170 171 } 172 173 // Allocates the structure for a new module 174 struct elf_module *module_alloc(const char *name) { 175 struct elf_module *result = malloc(sizeof(struct elf_module)); 176 177 if (!result) { 178 dprintf("module: Failed to alloc elf_module\n"); 179 return NULL; 180 } 181 182 memset(result, 0, sizeof(struct elf_module)); 183 184 INIT_LIST_HEAD(&result->list); 185 INIT_LIST_HEAD(&result->required); 186 INIT_LIST_HEAD(&result->dependants); 187 188 strncpy(result->name, name, MODULE_NAME_SIZE); 189 190 return result; 191 } 192 193 struct module_dep *module_dep_alloc(struct elf_module *module) { 194 struct module_dep *result = malloc(sizeof(struct module_dep)); 195 196 INIT_LIST_HEAD (&result->list); 197 198 result->module = module; 199 200 return result; 201 } 202 203 struct elf_module *module_find(const char *name) { 204 struct elf_module *cr_module; 205 206 for_each_module(cr_module) { 207 if (strcmp(cr_module->name, name) == 0) 208 return cr_module; 209 } 210 211 return NULL; 212 } 213 214 215 // Mouli: This is checking the header for 32bit machine 216 // Support 64bit architecture as well. 217 // Parts of the ELF header checked are common to both ELF32 and ELF64 218 // Adding simple checks for both 32bit and 64bit should work (hopefully) 219 // 220 // Performs verifications on ELF header to assure that the open file is a 221 // valid SYSLINUX ELF module. 222 int check_header_common(Elf_Ehdr *elf_hdr) { 223 // Check the header magic 224 if (elf_hdr->e_ident[EI_MAG0] != ELFMAG0 || 225 elf_hdr->e_ident[EI_MAG1] != ELFMAG1 || 226 elf_hdr->e_ident[EI_MAG2] != ELFMAG2 || 227 elf_hdr->e_ident[EI_MAG3] != ELFMAG3) { 228 229 dprintf("The file is not an ELF object\n"); 230 return -1; 231 } 232 233 if (elf_hdr->e_ident[EI_CLASS] != ELFCLASS32 && 234 elf_hdr->e_ident[EI_CLASS] != ELFCLASS64) { 235 dprintf("Invalid ELF class code\n"); 236 return -1; 237 } 238 239 if (elf_hdr->e_ident[EI_DATA] != MODULE_ELF_DATA) { 240 dprintf("Invalid ELF data encoding\n"); 241 return -1; 242 } 243 244 if (elf_hdr->e_ident[EI_VERSION] != MODULE_ELF_VERSION || 245 elf_hdr->e_version != MODULE_ELF_VERSION) { 246 dprintf("Invalid ELF file version\n"); 247 return -1; 248 } 249 250 if (elf_hdr->e_machine != EM_386 && 251 elf_hdr->e_machine != EM_X86_64) { 252 dprintf("Invalid ELF architecture\n"); 253 return -1; 254 } 255 256 return 0; 257 } 258 259 260 261 int enforce_dependency(struct elf_module *req, struct elf_module *dep) { 262 struct module_dep *crt_dep; 263 struct module_dep *new_dep; 264 265 list_for_each_entry(crt_dep, &req->dependants, list) { 266 if (crt_dep->module == dep) { 267 // The dependency is already enforced 268 return 0; 269 } 270 } 271 272 new_dep = module_dep_alloc(req); 273 list_add(&new_dep->list, &dep->required); 274 275 new_dep = module_dep_alloc(dep); 276 list_add(&new_dep->list, &req->dependants); 277 278 return 0; 279 } 280 281 int clear_dependency(struct elf_module *req, struct elf_module *dep) { 282 struct module_dep *crt_dep = NULL; 283 int found = 0; 284 285 list_for_each_entry(crt_dep, &req->dependants, list) { 286 if (crt_dep->module == dep) { 287 found = 1; 288 break; 289 } 290 } 291 292 if (found) { 293 list_del(&crt_dep->list); 294 free(crt_dep); 295 } 296 297 found = 0; 298 299 list_for_each_entry(crt_dep, &dep->required, list) { 300 if (crt_dep->module == req) { 301 found = 1; 302 break; 303 } 304 } 305 306 if (found) { 307 list_del(&crt_dep->list); 308 free(crt_dep); 309 } 310 311 return 0; 312 } 313 314 int check_symbols(struct elf_module *module) 315 { 316 unsigned int i; 317 Elf_Sym *crt_sym = NULL, *ref_sym = NULL; 318 char *crt_name; 319 struct elf_module *crt_module; 320 321 int strong_count; 322 int weak_count; 323 324 for (i = 1; i < module->symtable_size/module->syment_size; i++) 325 { 326 crt_sym = symbol_get_entry(module, i); 327 crt_name = module->str_table + crt_sym->st_name; 328 329 strong_count = 0; 330 weak_count = (ELF32_ST_BIND(crt_sym->st_info) == STB_WEAK); 331 332 for_each_module(crt_module) 333 { 334 ref_sym = module_find_symbol(crt_name, crt_module); 335 336 // If we found a definition for our symbol... 337 if (ref_sym != NULL && ref_sym->st_shndx != SHN_UNDEF) 338 { 339 switch (ELF32_ST_BIND(ref_sym->st_info)) 340 { 341 case STB_GLOBAL: 342 strong_count++; 343 break; 344 case STB_WEAK: 345 weak_count++; 346 break; 347 } 348 } 349 } 350 351 if (crt_sym->st_shndx == SHN_UNDEF) 352 { 353 // We have an undefined symbol 354 // 355 // We use the weak_count to differentiate 356 // between Syslinux-derivative-specific 357 // functions. For example, unload_pxe() is 358 // only provided by PXELINUX, so we mark it as 359 // __weak and replace it with a reference to 360 // undefined_symbol() on SYSLINUX, EXTLINUX, 361 // and ISOLINUX. See perform_relocations(). 362 if (strong_count == 0 && weak_count == 0) 363 { 364 dprintf("Symbol %s is undefined\n", crt_name); 365 printf("Undef symbol FAIL: %s\n",crt_name); 366 return -1; 367 } 368 } 369 else 370 { 371 if (strong_count > 0 && ELF32_ST_BIND(ref_sym->st_info) == STB_GLOBAL) 372 { 373 // It's not an error - at relocation, the most recent symbol 374 // will be considered 375 dprintf("Info: Symbol %s is defined more than once\n", crt_name); 376 } 377 } 378 //printf("symbol %s laoded from %d\n",crt_name,crt_sym->st_value); 379 } 380 381 return 0; 382 } 383 384 int module_unloadable(struct elf_module *module) { 385 if (!list_empty(&module->dependants)) 386 return 0; 387 388 return 1; 389 } 390 391 392 // Unloads the module from the system and releases all the associated memory 393 int _module_unload(struct elf_module *module) { 394 struct module_dep *crt_dep, *tmp; 395 // Make sure nobody needs us 396 if (!module_unloadable(module)) { 397 dprintf("Module is required by other modules.\n"); 398 return -1; 399 } 400 401 // Remove any dependency information 402 list_for_each_entry_safe(crt_dep, tmp, &module->required, list) { 403 clear_dependency(crt_dep->module, module); 404 } 405 406 // Remove the module from the module list 407 list_del_init(&module->list); 408 409 // Release the loaded segments or sections 410 if (module->module_addr != NULL) { 411 elf_free(module->module_addr); 412 413 dprintf("%s MODULE %s UNLOADED\n", module->shallow ? "SHALLOW" : "", 414 module->name); 415 } 416 417 dprintf("Unloading module %s\n", module->name); 418 // Release the module structure 419 free(module); 420 421 return 0; 422 } 423 424 int module_unload(struct elf_module *module) { 425 module_ctor_t *dtor; 426 427 for (dtor = module->dtors; dtor && *dtor; dtor++) 428 (*dtor) (); 429 430 return _module_unload(module); 431 } 432 433 struct elf_module *unload_modules_since(const char *name) { 434 struct elf_module *m, *mod, *begin = NULL; 435 436 for_each_module(mod) { 437 if (!strcmp(mod->name, name)) { 438 begin = mod; 439 break; 440 } 441 } 442 443 if (!begin) 444 return begin; 445 446 for_each_module_safe(mod, m) { 447 if (mod == begin) 448 break; 449 450 if (mod != begin) 451 module_unload(mod); 452 } 453 454 return begin; 455 } 456 457 static Elf_Sym *module_find_symbol_sysv(const char *name, struct elf_module *module) { 458 unsigned long h = elf_hash((const unsigned char*)name); 459 Elf_Word *cr_word = module->hash_table; 460 461 Elf_Word nbucket = *cr_word++; 462 cr_word++; // Skip nchain 463 464 Elf_Word *bkt = cr_word; 465 Elf_Word *chn = cr_word + nbucket; 466 467 Elf_Word crt_index = bkt[h % module->hash_table[0]]; 468 Elf_Sym *crt_sym; 469 470 471 while (crt_index != STN_UNDEF) { 472 crt_sym = symbol_get_entry(module, crt_index); 473 474 if (strcmp(name, module->str_table + crt_sym->st_name) == 0) 475 return crt_sym; 476 477 crt_index = chn[crt_index]; 478 } 479 480 return NULL; 481 } 482 483 static Elf_Sym *module_find_symbol_gnu(const char *name, struct elf_module *module) { 484 unsigned long h = elf_gnu_hash((const unsigned char*)name); 485 486 // Setup code (TODO: Optimize this by computing only once) 487 Elf_Word *cr_word = module->ghash_table; 488 Elf_Word nbucket = *cr_word++; 489 Elf_Word symbias = *cr_word++; 490 Elf_Word bitmask_nwords = *cr_word++; 491 492 if ((bitmask_nwords & (bitmask_nwords - 1)) != 0) { 493 dprintf("Invalid GNU Hash structure\n"); 494 return NULL; 495 } 496 497 Elf_Word gnu_shift = *cr_word++; 498 499 Elf_Addr *gnu_bitmask = (Elf_Addr*)cr_word; 500 cr_word += MODULE_ELF_CLASS_SIZE / 32 * bitmask_nwords; 501 502 Elf_Word *gnu_buckets = cr_word; 503 cr_word += nbucket; 504 505 Elf_Word *gnu_chain_zero = cr_word - symbias; 506 507 // Computations 508 Elf_Bword bitmask_word = gnu_bitmask[(h / MODULE_ELF_CLASS_SIZE) & 509 (bitmask_nwords - 1)]; 510 511 unsigned int hashbit1 = h & (MODULE_ELF_CLASS_SIZE - 1); 512 unsigned int hashbit2 = (h >> gnu_shift) & (MODULE_ELF_CLASS_SIZE - 1); 513 514 if ((bitmask_word >> hashbit1) & (bitmask_word >> hashbit2) & 1) { 515 unsigned long rem; 516 Elf_Word bucket; 517 518 rem = h % nbucket; 519 520 bucket = gnu_buckets[rem]; 521 522 if (bucket != 0) { 523 const Elf_Word* hasharr = &gnu_chain_zero[bucket]; 524 525 do { 526 if (((*hasharr ^ h ) >> 1) == 0) { 527 Elf_Sym *crt_sym = symbol_get_entry(module, (hasharr - gnu_chain_zero)); 528 529 if (strcmp(name, module->str_table + crt_sym->st_name) == 0) { 530 return crt_sym; 531 } 532 } 533 } while ((*hasharr++ & 1u) == 0); 534 } 535 } 536 537 return NULL; 538 } 539 540 static Elf_Sym *module_find_symbol_iterate(const char *name,struct elf_module *module) 541 { 542 543 unsigned int i; 544 Elf_Sym *crt_sym; 545 546 for (i = 1; i < module->symtable_size/module->syment_size; i++) 547 { 548 crt_sym = symbol_get_entry(module, i); 549 if (strcmp(name, module->str_table + crt_sym->st_name) == 0) 550 { 551 return crt_sym; 552 } 553 } 554 555 return NULL; 556 } 557 558 Elf_Sym *module_find_symbol(const char *name, struct elf_module *module) { 559 Elf_Sym *result = NULL; 560 561 if (module->ghash_table != NULL) 562 result = module_find_symbol_gnu(name, module); 563 564 if (result == NULL) 565 { 566 if (module->hash_table != NULL) 567 { 568 //printf("Attempting SYSV Symbol search\n"); 569 result = module_find_symbol_sysv(name, module); 570 } 571 else 572 { 573 //printf("Attempting Iterative Symbol search\n"); 574 result = module_find_symbol_iterate(name, module); 575 } 576 } 577 578 return result; 579 } 580 581 Elf_Sym *global_find_symbol(const char *name, struct elf_module **module) { 582 struct elf_module *crt_module; 583 Elf_Sym *crt_sym = NULL; 584 Elf_Sym *result = NULL; 585 586 for_each_module(crt_module) { 587 crt_sym = module_find_symbol(name, crt_module); 588 589 if (crt_sym != NULL && crt_sym->st_shndx != SHN_UNDEF) { 590 switch (ELF32_ST_BIND(crt_sym->st_info)) { 591 case STB_GLOBAL: 592 if (module != NULL) { 593 *module = crt_module; 594 } 595 return crt_sym; 596 case STB_WEAK: 597 // Consider only the first weak symbol 598 if (result == NULL) { 599 if (module != NULL) { 600 *module = crt_module; 601 } 602 result = crt_sym; 603 } 604 break; 605 } 606 } 607 } 608 609 return result; 610 } 611