1 /* 2 * Copyright 2002-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Copyright 2001, Travis Geiselbrecht. All rights reserved. 6 * Distributed under the terms of the NewOS License. 7 */ 8 9 /* Contains the ELF loader */ 10 11 #include <elf.h> 12 13 #include <OS.h> 14 15 #include <unistd.h> 16 #include <stdlib.h> 17 #include <string.h> 18 #include <stdio.h> 19 #include <ctype.h> 20 21 #include <debug.h> 22 #include <kernel.h> 23 #include <kimage.h> 24 #include <syscalls.h> 25 #include <team.h> 26 #include <thread.h> 27 #include <runtime_loader.h> 28 #include <util/khash.h> 29 #include <vfs.h> 30 #include <vm.h> 31 #include <vm_address_space.h> 32 #include <vm_types.h> 33 34 #include <arch/cpu.h> 35 #include <arch/elf.h> 36 #include <elf_priv.h> 37 #include <boot/elf.h> 38 39 //#define TRACE_ELF 40 #ifdef TRACE_ELF 41 # define TRACE(x) dprintf x 42 #else 43 # define TRACE(x) ; 44 #endif 45 46 47 // ToDo: this shall contain a list of linked images (one day) 48 // this is a preparation for shared libraries in the kernel 49 // and not yet used. 50 #if 0 51 typedef struct elf_linked_image { 52 struct elf_linked_image *next; 53 struct elf_image_info *image; 54 } elf_linked_image; 55 #endif 56 57 #define IMAGE_HASH_SIZE 16 58 59 static hash_table *sImagesHash; 60 61 static struct elf_image_info *sKernelImage = NULL; 62 static mutex sImageMutex; // guards sImagesHash 63 static mutex sImageLoadMutex; // serializes loading/unloading add-ons 64 // locking order sImageLoadMutex -> sImageMutex 65 static bool sInitialized = false; 66 67 68 /*! Calculates hash for an image using its ID */ 69 static uint32 70 image_hash(void *_image, const void *_key, uint32 range) 71 { 72 struct elf_image_info *image = (struct elf_image_info *)_image; 73 image_id id = (image_id)_key; 74 75 if (image != NULL) 76 return image->id % range; 77 78 return (uint32)id % range; 79 } 80 81 82 /*! Compares an image to a given ID */ 83 static int 84 image_compare(void *_image, const void *_key) 85 { 86 struct elf_image_info *image = (struct elf_image_info *)_image; 87 image_id id = (image_id)_key; 88 89 return id - image->id; 90 } 91 92 93 static void 94 unregister_elf_image(struct elf_image_info *image) 95 { 96 unregister_image(team_get_kernel_team(), image->id); 97 hash_remove(sImagesHash, image); 98 } 99 100 101 static void 102 register_elf_image(struct elf_image_info *image) 103 { 104 image_info imageInfo; 105 106 memset(&imageInfo, 0, sizeof(image_info)); 107 imageInfo.id = image->id; 108 imageInfo.type = B_SYSTEM_IMAGE; 109 strlcpy(imageInfo.name, image->name, sizeof(imageInfo.name)); 110 111 imageInfo.text = (void *)image->text_region.start; 112 imageInfo.text_size = image->text_region.size; 113 imageInfo.data = (void *)image->data_region.start; 114 imageInfo.data_size = image->data_region.size; 115 116 image->id = register_image(team_get_kernel_team(), &imageInfo, sizeof(image_info)); 117 hash_insert(sImagesHash, image); 118 } 119 120 121 /*! Note, you must lock the image mutex when you call this function. */ 122 static struct elf_image_info * 123 find_image_at_address(addr_t address) 124 { 125 struct hash_iterator iterator; 126 struct elf_image_info *image; 127 128 ASSERT_LOCKED_MUTEX(&sImageMutex); 129 130 hash_open(sImagesHash, &iterator); 131 132 // get image that may contain the address 133 134 while ((image = (elf_image_info *)hash_next(sImagesHash, &iterator)) != NULL) { 135 if ((address >= image->text_region.start 136 && address <= (image->text_region.start + image->text_region.size)) 137 || (address >= image->data_region.start 138 && address <= (image->data_region.start + image->data_region.size))) 139 break; 140 } 141 142 hash_close(sImagesHash, &iterator, false); 143 return image; 144 } 145 146 147 static int 148 dump_address_info(int argc, char **argv) 149 { 150 const char *symbol, *imageName; 151 bool exactMatch; 152 addr_t address, baseAddress; 153 154 if (argc < 2) { 155 kprintf("usage: ls <address>\n"); 156 return 0; 157 } 158 159 address = strtoul(argv[1], NULL, 16); 160 161 if (elf_debug_lookup_symbol_address(address, &baseAddress, &symbol, 162 &imageName, &exactMatch) == B_OK) { 163 kprintf("%p = %s + 0x%lx (%s)%s\n", (void *)address, symbol, 164 address - baseAddress, imageName, exactMatch ? "" : " (nearest)"); 165 } else 166 kprintf("There is no image loaded at this address!\n"); 167 168 return 0; 169 } 170 171 172 static struct elf_image_info * 173 find_image(image_id id) 174 { 175 return (elf_image_info *)hash_lookup(sImagesHash, (void *)id); 176 } 177 178 179 static struct elf_image_info * 180 find_image_by_vnode(void *vnode) 181 { 182 struct hash_iterator iterator; 183 struct elf_image_info *image; 184 185 mutex_lock(&sImageMutex); 186 hash_open(sImagesHash, &iterator); 187 188 while ((image = (elf_image_info *)hash_next(sImagesHash, &iterator)) != NULL) { 189 if (image->vnode == vnode) 190 break; 191 } 192 193 hash_close(sImagesHash, &iterator, false); 194 mutex_unlock(&sImageMutex); 195 196 return image; 197 } 198 199 200 static struct elf_image_info * 201 create_image_struct() 202 { 203 struct elf_image_info *image = (struct elf_image_info *)malloc(sizeof(struct elf_image_info)); 204 if (image == NULL) 205 return NULL; 206 207 memset(image, 0, sizeof(struct elf_image_info)); 208 209 image->text_region.id = -1; 210 image->data_region.id = -1; 211 image->ref_count = 1; 212 213 return image; 214 } 215 216 217 static uint32 218 elf_hash(const char *name) 219 { 220 uint32 hash = 0; 221 uint32 temp; 222 223 while (*name) { 224 hash = (hash << 4) + (uint8)*name++; 225 if ((temp = hash & 0xf0000000) != 0) 226 hash ^= temp >> 24; 227 hash &= ~temp; 228 } 229 return hash; 230 } 231 232 233 static const char * 234 get_symbol_type_string(struct Elf32_Sym *symbol) 235 { 236 switch (ELF32_ST_TYPE(symbol->st_info)) { 237 case STT_FUNC: 238 return "func"; 239 case STT_OBJECT: 240 return " obj"; 241 case STT_FILE: 242 return "file"; 243 default: 244 return "----"; 245 } 246 } 247 248 249 static const char * 250 get_symbol_bind_string(struct Elf32_Sym *symbol) 251 { 252 switch (ELF32_ST_BIND(symbol->st_info)) { 253 case STB_LOCAL: 254 return "loc "; 255 case STB_GLOBAL: 256 return "glob"; 257 case STB_WEAK: 258 return "weak"; 259 default: 260 return "----"; 261 } 262 } 263 264 265 /*! Searches a symbol (pattern) in all kernel images */ 266 static int 267 dump_symbol(int argc, char **argv) 268 { 269 if (argc != 2 || !strcmp(argv[1], "--help")) { 270 kprintf("usage: %s <symbol-name>\n", argv[0]); 271 return 0; 272 } 273 274 struct elf_image_info *image = NULL; 275 struct hash_iterator iterator; 276 const char *pattern = argv[1]; 277 278 hash_open(sImagesHash, &iterator); 279 while ((image = (elf_image_info *)hash_next(sImagesHash, &iterator)) 280 != NULL) { 281 if (image->num_debug_symbols > 0) { 282 // search extended debug symbol table (contains static symbols) 283 for (uint32 i = 0; i < image->num_debug_symbols; i++) { 284 struct Elf32_Sym *symbol = &image->debug_symbols[i]; 285 const char *name = image->debug_string_table + symbol->st_name; 286 287 if (symbol->st_value > 0 && strstr(name, pattern) != 0) { 288 kprintf("%p %5lu %s:%s\n", 289 (void *)(symbol->st_value + image->text_region.delta), 290 symbol->st_size, image->name, name); 291 } 292 } 293 } else { 294 // search standard symbol lookup table 295 for (uint32 i = 0; i < HASHTABSIZE(image); i++) { 296 for (uint32 j = HASHBUCKETS(image)[i]; j != STN_UNDEF; 297 j = HASHCHAINS(image)[j]) { 298 struct Elf32_Sym *symbol = &image->syms[j]; 299 const char *name = SYMNAME(image, symbol); 300 301 if (symbol->st_value > 0 && strstr(name, pattern) != 0) { 302 kprintf("%p %5lu %s:%s\n", (void *)(symbol->st_value 303 + image->text_region.delta), 304 symbol->st_size, image->name, name); 305 } 306 } 307 } 308 } 309 } 310 hash_close(sImagesHash, &iterator, false); 311 return 0; 312 } 313 314 315 static int 316 dump_symbols(int argc, char **argv) 317 { 318 struct elf_image_info *image = NULL; 319 struct hash_iterator iterator; 320 uint32 i; 321 322 // if the argument looks like a hex number, treat it as such 323 if (argc > 1) { 324 if (isdigit(argv[1][0])) { 325 uint32 num = strtoul(argv[1], NULL, 0); 326 327 if (IS_KERNEL_ADDRESS(num)) { 328 // find image at address 329 330 hash_open(sImagesHash, &iterator); 331 while ((image = (elf_image_info *)hash_next(sImagesHash, &iterator)) != NULL) { 332 if (image->text_region.start <= num 333 && image->text_region.start + image->text_region.size >= num) 334 break; 335 } 336 hash_close(sImagesHash, &iterator, false); 337 338 if (image == NULL) 339 kprintf("No image covers 0x%lx in the kernel!\n", num); 340 } else { 341 image = (elf_image_info *)hash_lookup(sImagesHash, (void *)num); 342 if (image == NULL) 343 kprintf("image 0x%lx doesn't exist in the kernel!\n", num); 344 } 345 } else { 346 // look for image by name 347 hash_open(sImagesHash, &iterator); 348 while ((image = (elf_image_info *)hash_next(sImagesHash, &iterator)) != NULL) { 349 if (!strcmp(image->name, argv[1])) 350 break; 351 } 352 hash_close(sImagesHash, &iterator, false); 353 354 if (image == NULL) 355 kprintf("No image \"%s\" found in kernel!\n", argv[1]); 356 } 357 } else { 358 kprintf("usage: %s image_name/image_id/address_in_image\n", argv[0]); 359 return 0; 360 } 361 362 if (image == NULL) 363 return -1; 364 365 // dump symbols 366 367 kprintf("Symbols of image %ld \"%s\":\nAddress Type Size Name\n", image->id, image->name); 368 369 if (image->num_debug_symbols > 0) { 370 // search extended debug symbol table (contains static symbols) 371 for (i = 0; i < image->num_debug_symbols; i++) { 372 struct Elf32_Sym *symbol = &image->debug_symbols[i]; 373 374 if (symbol->st_value == 0 375 || symbol->st_size >= image->text_region.size + image->data_region.size) 376 continue; 377 378 kprintf("%08lx %s/%s %5ld %s\n", symbol->st_value + image->text_region.delta, 379 get_symbol_type_string(symbol), get_symbol_bind_string(symbol), symbol->st_size, 380 image->debug_string_table + symbol->st_name); 381 } 382 } else { 383 int32 j; 384 385 // search standard symbol lookup table 386 for (i = 0; i < HASHTABSIZE(image); i++) { 387 for (j = HASHBUCKETS(image)[i]; j != STN_UNDEF; j = HASHCHAINS(image)[j]) { 388 struct Elf32_Sym *symbol = &image->syms[j]; 389 390 if (symbol->st_value == 0 391 || symbol->st_size >= image->text_region.size + image->data_region.size) 392 continue; 393 394 kprintf("%08lx %s/%s %5ld %s\n", symbol->st_value + image->text_region.delta, 395 get_symbol_type_string(symbol), get_symbol_bind_string(symbol), 396 symbol->st_size, SYMNAME(image, symbol)); 397 } 398 } 399 } 400 401 return 0; 402 } 403 404 405 static void 406 dump_elf_region(struct elf_region *region, const char *name) 407 { 408 kprintf(" %s.id 0x%lx\n", name, region->id); 409 kprintf(" %s.start 0x%lx\n", name, region->start); 410 kprintf(" %s.size 0x%lx\n", name, region->size); 411 kprintf(" %s.delta %ld\n", name, region->delta); 412 } 413 414 415 static void 416 dump_image_info(struct elf_image_info *image) 417 { 418 kprintf("elf_image_info at %p:\n", image); 419 kprintf(" next %p\n", image->next); 420 kprintf(" id 0x%lx\n", image->id); 421 dump_elf_region(&image->text_region, "text"); 422 dump_elf_region(&image->data_region, "data"); 423 kprintf(" dynamic_section 0x%lx\n", image->dynamic_section); 424 kprintf(" needed %p\n", image->needed); 425 kprintf(" symhash %p\n", image->symhash); 426 kprintf(" syms %p\n", image->syms); 427 kprintf(" strtab %p\n", image->strtab); 428 kprintf(" rel %p\n", image->rel); 429 kprintf(" rel_len 0x%x\n", image->rel_len); 430 kprintf(" rela %p\n", image->rela); 431 kprintf(" rela_len 0x%x\n", image->rela_len); 432 kprintf(" pltrel %p\n", image->pltrel); 433 kprintf(" pltrel_len 0x%x\n", image->pltrel_len); 434 435 kprintf(" debug_symbols %p (%ld)\n", image->debug_symbols, image->num_debug_symbols); 436 } 437 438 439 static int 440 dump_image(int argc, char **argv) 441 { 442 struct hash_iterator iterator; 443 struct elf_image_info *image; 444 445 // if the argument looks like a hex number, treat it as such 446 if (argc > 1) { 447 uint32 num = strtoul(argv[1], NULL, 0); 448 449 if (IS_KERNEL_ADDRESS(num)) { 450 // semi-hack 451 dump_image_info((struct elf_image_info *)num); 452 } else { 453 image = (elf_image_info *)hash_lookup(sImagesHash, (void *)num); 454 if (image == NULL) 455 kprintf("image 0x%lx doesn't exist in the kernel!\n", num); 456 else 457 dump_image_info(image); 458 } 459 return 0; 460 } 461 462 kprintf("loaded kernel images:\n"); 463 464 hash_open(sImagesHash, &iterator); 465 466 while ((image = (elf_image_info *)hash_next(sImagesHash, &iterator)) != NULL) { 467 kprintf("%p (%ld) %s\n", image, image->id, image->name); 468 } 469 470 hash_close(sImagesHash, &iterator, false); 471 return 0; 472 } 473 474 475 // Currently unused 476 #if 0 477 static 478 void dump_symbol(struct elf_image_info *image, struct Elf32_Sym *sym) 479 { 480 481 kprintf("symbol at %p, in image %p\n", sym, image); 482 483 kprintf(" name index %d, '%s'\n", sym->st_name, SYMNAME(image, sym)); 484 kprintf(" st_value 0x%x\n", sym->st_value); 485 kprintf(" st_size %d\n", sym->st_size); 486 kprintf(" st_info 0x%x\n", sym->st_info); 487 kprintf(" st_other 0x%x\n", sym->st_other); 488 kprintf(" st_shndx %d\n", sym->st_shndx); 489 } 490 #endif 491 492 493 static struct Elf32_Sym * 494 elf_find_symbol(struct elf_image_info *image, const char *name) 495 { 496 uint32 hash; 497 uint32 i; 498 499 if (!image->dynamic_section) 500 return NULL; 501 502 hash = elf_hash(name) % HASHTABSIZE(image); 503 for (i = HASHBUCKETS(image)[hash]; i != STN_UNDEF; i = HASHCHAINS(image)[i]) { 504 if (!strcmp(SYMNAME(image, &image->syms[i]), name)) 505 return &image->syms[i]; 506 } 507 508 return NULL; 509 } 510 511 512 static status_t 513 elf_parse_dynamic_section(struct elf_image_info *image) 514 { 515 struct Elf32_Dyn *d; 516 int32 neededOffset = -1; 517 518 TRACE(("top of elf_parse_dynamic_section\n")); 519 520 image->symhash = 0; 521 image->syms = 0; 522 image->strtab = 0; 523 524 d = (struct Elf32_Dyn *)image->dynamic_section; 525 if (!d) 526 return B_ERROR; 527 528 for (int32 i = 0; d[i].d_tag != DT_NULL; i++) { 529 switch (d[i].d_tag) { 530 case DT_NEEDED: 531 neededOffset = d[i].d_un.d_ptr + image->text_region.delta; 532 break; 533 case DT_HASH: 534 image->symhash = (uint32 *)(d[i].d_un.d_ptr 535 + image->text_region.delta); 536 break; 537 case DT_STRTAB: 538 image->strtab = (char *)(d[i].d_un.d_ptr 539 + image->text_region.delta); 540 break; 541 case DT_SYMTAB: 542 image->syms = (struct Elf32_Sym *)(d[i].d_un.d_ptr 543 + image->text_region.delta); 544 break; 545 case DT_REL: 546 image->rel = (struct Elf32_Rel *)(d[i].d_un.d_ptr 547 + image->text_region.delta); 548 break; 549 case DT_RELSZ: 550 image->rel_len = d[i].d_un.d_val; 551 break; 552 case DT_RELA: 553 image->rela = (struct Elf32_Rela *)(d[i].d_un.d_ptr 554 + image->text_region.delta); 555 break; 556 case DT_RELASZ: 557 image->rela_len = d[i].d_un.d_val; 558 break; 559 case DT_JMPREL: 560 image->pltrel = (struct Elf32_Rel *)(d[i].d_un.d_ptr 561 + image->text_region.delta); 562 break; 563 case DT_PLTRELSZ: 564 image->pltrel_len = d[i].d_un.d_val; 565 break; 566 case DT_PLTREL: 567 image->pltrel_type = d[i].d_un.d_val; 568 break; 569 570 default: 571 continue; 572 } 573 } 574 575 // lets make sure we found all the required sections 576 if (!image->symhash || !image->syms || !image->strtab) 577 return B_ERROR; 578 579 TRACE(("needed_offset = %ld\n", neededOffset)); 580 581 if (neededOffset >= 0) 582 image->needed = STRING(image, neededOffset); 583 584 return B_OK; 585 } 586 587 588 /*! Resolves the \a symbol by linking against \a sharedImage if necessary. 589 Returns the resolved symbol's address in \a _symbolAddress. 590 TODO: eventually get rid of "symbolPrepend" 591 */ 592 status_t 593 elf_resolve_symbol(struct elf_image_info *image, struct Elf32_Sym *symbol, 594 struct elf_image_info *sharedImage, const char *symbolPrepend, 595 addr_t *_symbolAddress) 596 { 597 switch (symbol->st_shndx) { 598 case SHN_UNDEF: 599 { 600 struct Elf32_Sym *newSymbol; 601 char newNameBuffer[368]; 602 char *newName; 603 604 // patch the symbol name 605 if (symbolPrepend) { 606 newName = newNameBuffer; 607 strlcpy(newName, symbolPrepend, sizeof(newName)); 608 strlcat(newName, SYMNAME(image, symbol), sizeof(newName)); 609 } else 610 newName = SYMNAME(image, symbol); 611 612 // it's undefined, must be outside this image, try the other image 613 newSymbol = elf_find_symbol(sharedImage, newName); 614 if (newSymbol == NULL) { 615 dprintf("\"%s\": could not resolve symbol '%s'\n", 616 image->name, newName); 617 return B_MISSING_SYMBOL; 618 } 619 620 // make sure they're the same type 621 if (ELF32_ST_TYPE(symbol->st_info) 622 != ELF32_ST_TYPE(newSymbol->st_info)) { 623 dprintf("elf_resolve_symbol: found symbol '%s' in shared image but wrong type\n", newName); 624 return B_MISSING_SYMBOL; 625 } 626 627 if (ELF32_ST_BIND(newSymbol->st_info) != STB_GLOBAL 628 && ELF32_ST_BIND(newSymbol->st_info) != STB_WEAK) { 629 TRACE(("elf_resolve_symbol: found symbol '%s' but not exported\n", newName)); 630 return B_MISSING_SYMBOL; 631 } 632 633 *_symbolAddress = newSymbol->st_value 634 + sharedImage->text_region.delta; 635 return B_OK; 636 } 637 case SHN_ABS: 638 *_symbolAddress = symbol->st_value; 639 return B_OK; 640 case SHN_COMMON: 641 // ToDo: finish this 642 TRACE(("elf_resolve_symbol: COMMON symbol, finish me!\n")); 643 return B_ERROR; 644 645 default: 646 // standard symbol 647 *_symbolAddress = symbol->st_value + image->text_region.delta; 648 return B_OK; 649 } 650 } 651 652 653 /*! Until we have shared library support, just links against the kernel */ 654 static int 655 elf_relocate(struct elf_image_info *image, const char *symbolPrepend) 656 { 657 int status = B_NO_ERROR; 658 659 TRACE(("top of elf_relocate\n")); 660 661 // deal with the rels first 662 if (image->rel) { 663 TRACE(("total %i relocs\n", 664 image->rel_len / (int)sizeof(struct Elf32_Rel))); 665 666 status = arch_elf_relocate_rel(image, symbolPrepend, sKernelImage, 667 image->rel, image->rel_len); 668 if (status < B_OK) 669 return status; 670 } 671 672 if (image->pltrel) { 673 TRACE(("total %i plt-relocs\n", 674 image->pltrel_len / (int)sizeof(struct Elf32_Rel))); 675 676 if (image->pltrel_type == DT_REL) { 677 status = arch_elf_relocate_rel(image, symbolPrepend, sKernelImage, 678 image->pltrel, image->pltrel_len); 679 } else { 680 status = arch_elf_relocate_rela(image, symbolPrepend, sKernelImage, 681 (struct Elf32_Rela *)image->pltrel, image->pltrel_len); 682 } 683 if (status < B_OK) 684 return status; 685 } 686 687 if (image->rela) { 688 status = arch_elf_relocate_rela(image, symbolPrepend, sKernelImage, 689 image->rela, image->rela_len); 690 if (status < B_OK) 691 return status; 692 } 693 694 return status; 695 } 696 697 698 static int 699 verify_eheader(struct Elf32_Ehdr *elfHeader) 700 { 701 if (memcmp(elfHeader->e_ident, ELF_MAGIC, 4) != 0) 702 return B_NOT_AN_EXECUTABLE; 703 704 if (elfHeader->e_ident[4] != ELFCLASS32) 705 return B_NOT_AN_EXECUTABLE; 706 707 if (elfHeader->e_phoff == 0) 708 return B_NOT_AN_EXECUTABLE; 709 710 if (elfHeader->e_phentsize < sizeof(struct Elf32_Phdr)) 711 return B_NOT_AN_EXECUTABLE; 712 713 return 0; 714 } 715 716 717 #if 0 718 static int 719 elf_unlink_relocs(struct elf_image_info *image) 720 { 721 elf_linked_image *link, *next_link; 722 723 for (link = image->linked_images; link; link = next_link) { 724 next_link = link->next; 725 elf_unload_image(link->image); 726 free(link); 727 } 728 729 return B_NO_ERROR; 730 } 731 #endif 732 733 734 static status_t 735 unload_elf_image(struct elf_image_info *image) 736 { 737 if (atomic_add(&image->ref_count, -1) > 1) 738 return B_OK; 739 740 TRACE(("unload image %ld, %s\n", image->id, image->name)); 741 742 //elf_unlink_relocs(image); 743 // not yet used 744 745 delete_area(image->text_region.id); 746 delete_area(image->data_region.id); 747 748 if (image->vnode) 749 vfs_put_vnode(image->vnode); 750 751 unregister_elf_image(image); 752 753 free(image->elf_header); 754 free(image->name); 755 free(image); 756 757 return B_NO_ERROR; 758 } 759 760 761 static status_t 762 load_elf_symbol_table(int fd, struct elf_image_info *image) 763 { 764 struct Elf32_Ehdr *elfHeader = image->elf_header; 765 struct Elf32_Sym *symbolTable = NULL; 766 struct Elf32_Shdr *stringHeader = NULL; 767 uint32 numSymbols = 0; 768 char *stringTable; 769 status_t status; 770 ssize_t length; 771 int32 i; 772 773 // get section headers 774 775 ssize_t size = elfHeader->e_shnum * elfHeader->e_shentsize; 776 struct Elf32_Shdr *sectionHeaders = (struct Elf32_Shdr *)malloc(size); 777 if (sectionHeaders == NULL) { 778 dprintf("error allocating space for section headers\n"); 779 return B_NO_MEMORY; 780 } 781 782 length = read_pos(fd, elfHeader->e_shoff, sectionHeaders, size); 783 if (length < size) { 784 TRACE(("error reading in program headers\n")); 785 status = B_ERROR; 786 goto error1; 787 } 788 789 // find symbol table in section headers 790 791 for (i = 0; i < elfHeader->e_shnum; i++) { 792 if (sectionHeaders[i].sh_type == SHT_SYMTAB) { 793 stringHeader = §ionHeaders[sectionHeaders[i].sh_link]; 794 795 if (stringHeader->sh_type != SHT_STRTAB) { 796 TRACE(("doesn't link to string table\n")); 797 status = B_BAD_DATA; 798 goto error1; 799 } 800 801 // read in symbol table 802 symbolTable = (struct Elf32_Sym *)malloc(size = sectionHeaders[i].sh_size); 803 if (symbolTable == NULL) { 804 status = B_NO_MEMORY; 805 goto error1; 806 } 807 808 length = read_pos(fd, sectionHeaders[i].sh_offset, symbolTable, size); 809 if (length < size) { 810 TRACE(("error reading in symbol table\n")); 811 status = B_ERROR; 812 goto error1; 813 } 814 815 numSymbols = size / sizeof(struct Elf32_Sym); 816 break; 817 } 818 } 819 820 if (symbolTable == NULL) { 821 TRACE(("no symbol table\n")); 822 status = B_BAD_VALUE; 823 goto error1; 824 } 825 826 // read in string table 827 828 stringTable = (char *)malloc(size = stringHeader->sh_size); 829 if (stringTable == NULL) { 830 status = B_NO_MEMORY; 831 goto error2; 832 } 833 834 length = read_pos(fd, stringHeader->sh_offset, stringTable, size); 835 if (length < size) { 836 TRACE(("error reading in string table\n")); 837 status = B_ERROR; 838 goto error3; 839 } 840 841 TRACE(("loaded debug %ld symbols\n", numSymbols)); 842 843 // insert tables into image 844 image->debug_symbols = symbolTable; 845 image->num_debug_symbols = numSymbols; 846 image->debug_string_table = stringTable; 847 848 free(sectionHeaders); 849 return B_OK; 850 851 error3: 852 free(stringTable); 853 error2: 854 free(symbolTable); 855 error1: 856 free(sectionHeaders); 857 858 return status; 859 } 860 861 862 static status_t 863 insert_preloaded_image(struct preloaded_image *preloadedImage, bool kernel) 864 { 865 struct elf_image_info *image; 866 status_t status; 867 868 status = verify_eheader(&preloadedImage->elf_header); 869 if (status < B_OK) 870 return status; 871 872 image = create_image_struct(); 873 if (image == NULL) 874 return B_NO_MEMORY; 875 876 image->name = strdup(preloadedImage->name); 877 image->dynamic_section = preloadedImage->dynamic_section.start; 878 879 image->text_region = preloadedImage->text_region; 880 image->data_region = preloadedImage->data_region; 881 882 status = elf_parse_dynamic_section(image); 883 if (status < B_OK) 884 goto error1; 885 886 if (!kernel) { 887 status = elf_relocate(image, NULL); 888 if (status < B_OK) 889 goto error1; 890 } else 891 sKernelImage = image; 892 893 image->debug_symbols = preloadedImage->debug_symbols; 894 image->num_debug_symbols = preloadedImage->num_debug_symbols; 895 image->debug_string_table = preloadedImage->debug_string_table; 896 897 register_elf_image(image); 898 preloadedImage->id = image->id; 899 // modules_init() uses this information to get the preloaded images 900 901 // we now no longer need to write to the text area anymore 902 set_area_protection(image->text_region.id, 903 B_KERNEL_READ_AREA | B_KERNEL_EXECUTE_AREA); 904 905 return B_OK; 906 907 error1: 908 free(image); 909 910 // clean up preloaded image resources (this image won't be used anymore) 911 delete_area(preloadedImage->text_region.id); 912 delete_area(preloadedImage->data_region.id); 913 preloadedImage->id = -1; 914 915 return status; 916 } 917 918 919 // #pragma mark - userland symbol lookup 920 921 922 class UserSymbolLookup { 923 public: 924 static UserSymbolLookup& Default() 925 { 926 return sLookup; 927 } 928 929 status_t Init(struct team* team) 930 { 931 // find the runtime loader debug area 932 vm_area* area = team->address_space->areas; 933 while (area != NULL) { 934 if (strcmp(area->name, RUNTIME_LOADER_DEBUG_AREA_NAME) == 0) 935 break; 936 area = area->address_space_next; 937 } 938 939 if (area == NULL) 940 return B_ERROR; 941 942 // copy the runtime loader data structure 943 if (!_Read((runtime_loader_debug_area*)area->base, fDebugArea)) 944 return B_BAD_ADDRESS; 945 946 return B_OK; 947 } 948 949 status_t LookupSymbolAddress(addr_t address, addr_t *_baseAddress, 950 const char **_symbolName, const char **_imageName, bool *_exactMatch) 951 { 952 // Note, that this function doesn't find all symbols that we would like 953 // to find. E.g. static functions do not appear in the symbol table 954 // as function symbols, but as sections without name and size. The .symtab 955 // section together with the .strtab section, which apparently differ from 956 // the tables referred to by the .dynamic section, also contain proper names 957 // and sizes for those symbols. Therefore, to get completely satisfying 958 // results, we would need to read those tables from the shared object. 959 960 // get the image for the address 961 image_t image; 962 status_t error = _FindImageAtAddress(address, image); 963 if (error != B_OK) 964 return error; 965 966 strlcpy(fImageName, image.name, sizeof(fImageName)); 967 968 // symbol hash table size 969 uint32 hashTabSize; 970 if (!_Read(image.symhash, hashTabSize)) 971 return B_BAD_ADDRESS; 972 973 // remote pointers to hash buckets and chains 974 const uint32* hashBuckets = image.symhash + 2; 975 const uint32* hashChains = image.symhash + 2 + hashTabSize; 976 977 const elf_region_t& textRegion = image.regions[0]; 978 979 // search the image for the symbol 980 Elf32_Sym symbolFound; 981 addr_t deltaFound = INT_MAX; 982 bool exactMatch = false; 983 984 for (uint32 i = 0; i < hashTabSize; i++) { 985 uint32 bucket; 986 if (!_Read(&hashBuckets[i], bucket)) 987 return B_BAD_ADDRESS; 988 989 for (uint32 j = bucket; j != STN_UNDEF; 990 _Read(&hashChains[j], j) ? 0 : j = STN_UNDEF) { 991 992 Elf32_Sym symbol; 993 if (!_Read(image.syms + j, symbol)) 994 continue; 995 996 // The symbol table contains not only symbols referring to functions 997 // and data symbols within the shared object, but also referenced 998 // symbols of other shared objects, as well as section and file 999 // references. We ignore everything but function and data symbols 1000 // that have an st_value != 0 (0 seems to be an indication for a 1001 // symbol defined elsewhere -- couldn't verify that in the specs 1002 // though). 1003 if ((ELF32_ST_TYPE(symbol.st_info) != STT_FUNC 1004 && ELF32_ST_TYPE(symbol.st_info) != STT_OBJECT) 1005 || symbol.st_value == 0 1006 || symbol.st_value + symbol.st_size + textRegion.delta 1007 > textRegion.vmstart + textRegion.size) { 1008 continue; 1009 } 1010 1011 // skip symbols starting after the given address 1012 addr_t symbolAddress = symbol.st_value + textRegion.delta; 1013 if (symbolAddress > address) 1014 continue; 1015 addr_t symbolDelta = address - symbolAddress; 1016 1017 if (symbolDelta < deltaFound) { 1018 deltaFound = symbolDelta; 1019 symbolFound = symbol; 1020 1021 if (symbolDelta >= 0 && symbolDelta < symbol.st_size) { 1022 // exact match 1023 exactMatch = true; 1024 break; 1025 } 1026 } 1027 } 1028 } 1029 1030 if (_imageName) 1031 *_imageName = fImageName; 1032 1033 if (_symbolName) { 1034 *_symbolName = NULL; 1035 1036 if (deltaFound < INT_MAX) { 1037 if (_ReadString(image, symbolFound.st_name, fSymbolName, 1038 sizeof(fSymbolName))) { 1039 *_symbolName = fSymbolName; 1040 } else { 1041 // we can't get its name, so forget the symbol 1042 deltaFound = INT_MAX; 1043 } 1044 } 1045 } 1046 1047 if (_baseAddress) { 1048 if (deltaFound < INT_MAX) 1049 *_baseAddress = symbolFound.st_value + textRegion.delta; 1050 else 1051 *_baseAddress = textRegion.vmstart; 1052 } 1053 1054 if (_exactMatch) 1055 *_exactMatch = exactMatch; 1056 1057 return B_OK; 1058 } 1059 1060 1061 status_t _FindImageAtAddress(addr_t address, image_t& image) 1062 { 1063 image_queue_t imageQueue; 1064 if (!_Read(fDebugArea.loaded_images, imageQueue)) 1065 return B_BAD_ADDRESS; 1066 1067 image_t* imageAddress = imageQueue.head; 1068 while (imageAddress != NULL) { 1069 if (!_Read(imageAddress, image)) 1070 return B_BAD_ADDRESS; 1071 1072 if (image.regions[0].vmstart <= address 1073 && address < image.regions[0].vmstart + image.regions[0].size) { 1074 return B_OK; 1075 } 1076 1077 imageAddress = image.next; 1078 } 1079 1080 return B_ENTRY_NOT_FOUND; 1081 } 1082 1083 bool _ReadString(const image_t& image, uint32 offset, char* buffer, 1084 size_t bufferSize) 1085 { 1086 const char* address = image.strtab + offset; 1087 1088 if (!IS_USER_ADDRESS(address)) 1089 return false; 1090 1091 return user_strlcpy(buffer, address, bufferSize) >= 0; 1092 } 1093 1094 template<typename T> bool _Read(const T* address, T& data); 1095 // gcc 2.95.3 doesn't like it defined in-place 1096 1097 private: 1098 runtime_loader_debug_area fDebugArea; 1099 char fImageName[B_OS_NAME_LENGTH]; 1100 char fSymbolName[256]; 1101 static UserSymbolLookup sLookup; 1102 }; 1103 1104 1105 template<typename T> 1106 bool 1107 UserSymbolLookup::_Read(const T* address, T& data) 1108 { 1109 if (!IS_USER_ADDRESS(address)) 1110 return false; 1111 1112 return user_memcpy(&data, address, sizeof(T)) == B_OK; 1113 } 1114 1115 1116 UserSymbolLookup UserSymbolLookup::sLookup; 1117 // doesn't need construction, but has an Init() method 1118 1119 1120 // #pragma mark - public kernel API 1121 1122 1123 status_t 1124 get_image_symbol(image_id id, const char *name, int32 sclass, void **_symbol) 1125 { 1126 struct elf_image_info *image; 1127 struct Elf32_Sym *symbol; 1128 status_t status = B_OK; 1129 1130 TRACE(("get_image_symbol(%s)\n", name)); 1131 1132 mutex_lock(&sImageMutex); 1133 1134 image = find_image(id); 1135 if (image == NULL) { 1136 status = B_BAD_IMAGE_ID; 1137 goto done; 1138 } 1139 1140 symbol = elf_find_symbol(image, name); 1141 if (symbol == NULL || symbol->st_shndx == SHN_UNDEF) { 1142 status = B_ENTRY_NOT_FOUND; 1143 goto done; 1144 } 1145 1146 // ToDo: support the "sclass" parameter! 1147 1148 TRACE(("found: %lx (%lx + %lx)\n", symbol->st_value + image->text_region.delta, 1149 symbol->st_value, image->text_region.delta)); 1150 1151 *_symbol = (void *)(symbol->st_value + image->text_region.delta); 1152 1153 done: 1154 mutex_unlock(&sImageMutex); 1155 return status; 1156 } 1157 1158 1159 // #pragma mark - kernel private API 1160 1161 1162 /*! Looks up a symbol by address in all images loaded in kernel space. 1163 Note, if you need to call this function outside a debugger, make 1164 sure you fix locking and the way it returns its information, first! 1165 */ 1166 status_t 1167 elf_debug_lookup_symbol_address(addr_t address, addr_t *_baseAddress, 1168 const char **_symbolName, const char **_imageName, bool *_exactMatch) 1169 { 1170 struct elf_image_info *image; 1171 struct Elf32_Sym *symbolFound = NULL; 1172 const char *symbolName = NULL; 1173 addr_t deltaFound = INT_MAX; 1174 bool exactMatch = false; 1175 status_t status; 1176 1177 TRACE(("looking up %p\n", (void *)address)); 1178 1179 if (!sInitialized) 1180 return B_ERROR; 1181 1182 //mutex_lock(&sImageMutex); 1183 1184 image = find_image_at_address(address); 1185 // get image that may contain the address 1186 1187 if (image != NULL) { 1188 addr_t symbolDelta; 1189 uint32 i; 1190 int32 j; 1191 1192 TRACE((" image %p, base = %p, size = %p\n", image, 1193 (void *)image->text_region.start, (void *)image->text_region.size)); 1194 1195 if (image->debug_symbols != NULL) { 1196 // search extended debug symbol table (contains static symbols) 1197 1198 TRACE((" searching debug symbols...\n")); 1199 1200 for (i = 0; i < image->num_debug_symbols; i++) { 1201 struct Elf32_Sym *symbol = &image->debug_symbols[i]; 1202 1203 if (symbol->st_value == 0 1204 || symbol->st_size >= image->text_region.size + image->data_region.size) 1205 continue; 1206 1207 symbolDelta = address - (symbol->st_value + image->text_region.delta); 1208 if (symbolDelta >= 0 && symbolDelta < symbol->st_size) 1209 exactMatch = true; 1210 1211 if (exactMatch || symbolDelta < deltaFound) { 1212 deltaFound = symbolDelta; 1213 symbolFound = symbol; 1214 symbolName = image->debug_string_table + symbol->st_name; 1215 1216 if (exactMatch) 1217 break; 1218 } 1219 } 1220 } else { 1221 // search standard symbol lookup table 1222 1223 TRACE((" searching standard symbols...\n")); 1224 1225 for (i = 0; i < HASHTABSIZE(image); i++) { 1226 for (j = HASHBUCKETS(image)[i]; j != STN_UNDEF; j = HASHCHAINS(image)[j]) { 1227 struct Elf32_Sym *symbol = &image->syms[j]; 1228 1229 if (symbol->st_value == 0 1230 || symbol->st_size >= image->text_region.size + image->data_region.size) 1231 continue; 1232 1233 symbolDelta = address - (long)(symbol->st_value + image->text_region.delta); 1234 if (symbolDelta >= 0 && symbolDelta < symbol->st_size) 1235 exactMatch = true; 1236 1237 if (exactMatch || symbolDelta < deltaFound) { 1238 deltaFound = symbolDelta; 1239 symbolFound = symbol; 1240 symbolName = SYMNAME(image, symbol); 1241 1242 if (exactMatch) 1243 goto symbol_found; 1244 } 1245 } 1246 } 1247 } 1248 } 1249 symbol_found: 1250 1251 if (symbolFound != NULL) { 1252 if (_symbolName) 1253 *_symbolName = symbolName; 1254 if (_imageName) 1255 *_imageName = image->name; 1256 if (_baseAddress) 1257 *_baseAddress = symbolFound->st_value + image->text_region.delta; 1258 if (_exactMatch) 1259 *_exactMatch = exactMatch; 1260 1261 status = B_OK; 1262 } else if (image != NULL) { 1263 TRACE(("symbol not found!\n")); 1264 1265 if (_symbolName) 1266 *_symbolName = NULL; 1267 if (_imageName) 1268 *_imageName = image->name; 1269 if (_baseAddress) 1270 *_baseAddress = image->text_region.start; 1271 if (_exactMatch) 1272 *_exactMatch = false; 1273 1274 status = B_OK; 1275 } else { 1276 TRACE(("image not found!\n")); 1277 status = B_ENTRY_NOT_FOUND; 1278 } 1279 1280 // Note, theoretically, all information we return back to our caller 1281 // would have to be locked - but since this function is only called 1282 // from the debugger, it's safe to do it this way 1283 1284 //mutex_unlock(&sImageMutex); 1285 1286 return status; 1287 } 1288 1289 1290 /*! Tries to find a matching user symbol for the given address. 1291 Note that the given team's address must already be in effect. 1292 */ 1293 status_t 1294 elf_debug_lookup_user_symbol_address(struct team* team, addr_t address, 1295 addr_t *_baseAddress, const char **_symbolName, const char **_imageName, 1296 bool *_exactMatch) 1297 { 1298 UserSymbolLookup& lookup = UserSymbolLookup::Default(); 1299 status_t error = lookup.Init(team); 1300 if (error != B_OK) 1301 return error; 1302 1303 return lookup.LookupSymbolAddress(address, _baseAddress, _symbolName, 1304 _imageName, _exactMatch); 1305 } 1306 1307 1308 status_t 1309 elf_load_user_image(const char *path, struct team *team, int flags, addr_t *entry) 1310 { 1311 struct Elf32_Ehdr elfHeader; 1312 struct Elf32_Phdr *programHeaders = NULL; 1313 char baseName[B_OS_NAME_LENGTH]; 1314 status_t status; 1315 ssize_t length; 1316 int fd; 1317 int i; 1318 1319 TRACE(("elf_load: entry path '%s', team %p\n", path, team)); 1320 1321 fd = _kern_open(-1, path, O_RDONLY, 0); 1322 if (fd < 0) 1323 return fd; 1324 1325 // read and verify the ELF header 1326 1327 length = _kern_read(fd, 0, &elfHeader, sizeof(elfHeader)); 1328 if (length < B_OK) { 1329 status = length; 1330 goto error; 1331 } 1332 1333 if (length != sizeof(elfHeader)) { 1334 // short read 1335 status = B_NOT_AN_EXECUTABLE; 1336 goto error; 1337 } 1338 status = verify_eheader(&elfHeader); 1339 if (status < B_OK) 1340 goto error; 1341 1342 // read program header 1343 1344 programHeaders = (struct Elf32_Phdr *)malloc(elfHeader.e_phnum * elfHeader.e_phentsize); 1345 if (programHeaders == NULL) { 1346 dprintf("error allocating space for program headers\n"); 1347 status = B_NO_MEMORY; 1348 goto error; 1349 } 1350 1351 TRACE(("reading in program headers at 0x%lx, length 0x%x\n", elfHeader.e_phoff, elfHeader.e_phnum * elfHeader.e_phentsize)); 1352 length = _kern_read(fd, elfHeader.e_phoff, programHeaders, elfHeader.e_phnum * elfHeader.e_phentsize); 1353 if (length < B_OK) { 1354 status = length; 1355 dprintf("error reading in program headers\n"); 1356 goto error; 1357 } 1358 if (length != elfHeader.e_phnum * elfHeader.e_phentsize) { 1359 dprintf("short read while reading in program headers\n"); 1360 status = -1; 1361 goto error; 1362 } 1363 1364 // construct a nice name for the region we have to create below 1365 { 1366 int32 length; 1367 1368 const char *leaf = strrchr(path, '/'); 1369 if (leaf == NULL) 1370 leaf = path; 1371 else 1372 leaf++; 1373 1374 length = strlen(leaf); 1375 if (length > B_OS_NAME_LENGTH - 8) 1376 sprintf(baseName, "...%s", leaf + length + 8 - B_OS_NAME_LENGTH); 1377 else 1378 strcpy(baseName, leaf); 1379 } 1380 1381 // map the program's segments into memory 1382 1383 for (i = 0; i < elfHeader.e_phnum; i++) { 1384 char regionName[B_OS_NAME_LENGTH]; 1385 char *regionAddress; 1386 area_id id; 1387 1388 if (programHeaders[i].p_type != PT_LOAD) 1389 continue; 1390 1391 regionAddress = (char *)ROUNDOWN(programHeaders[i].p_vaddr, B_PAGE_SIZE); 1392 if (programHeaders[i].p_flags & PF_WRITE) { 1393 /* 1394 * rw/data segment 1395 */ 1396 uint32 memUpperBound = (programHeaders[i].p_vaddr % B_PAGE_SIZE) + programHeaders[i].p_memsz; 1397 uint32 fileUpperBound = (programHeaders[i].p_vaddr % B_PAGE_SIZE) + programHeaders[i].p_filesz; 1398 1399 memUpperBound = ROUNDUP(memUpperBound, B_PAGE_SIZE); 1400 fileUpperBound = ROUNDUP(fileUpperBound, B_PAGE_SIZE); 1401 1402 sprintf(regionName, "%s_seg%drw", baseName, i); 1403 1404 id = vm_map_file(team->id, regionName, 1405 (void **)®ionAddress, 1406 B_EXACT_ADDRESS, 1407 fileUpperBound, 1408 B_READ_AREA | B_WRITE_AREA, REGION_PRIVATE_MAP, 1409 path, ROUNDOWN(programHeaders[i].p_offset, B_PAGE_SIZE)); 1410 if (id < B_OK) { 1411 dprintf("error mapping file data: %s!\n", strerror(id)); 1412 status = B_NOT_AN_EXECUTABLE; 1413 goto error; 1414 } 1415 1416 // clean garbage brought by mmap (the region behind the file, 1417 // at least parts of it are the bss and have to be zeroed) 1418 { 1419 uint32 start = (uint32)regionAddress 1420 + (programHeaders[i].p_vaddr % B_PAGE_SIZE) 1421 + programHeaders[i].p_filesz; 1422 uint32 amount = fileUpperBound 1423 - (programHeaders[i].p_vaddr % B_PAGE_SIZE) 1424 - (programHeaders[i].p_filesz); 1425 memset((void *)start, 0, amount); 1426 } 1427 1428 // Check if we need extra storage for the bss - we have to do this if 1429 // the above region doesn't already comprise the memory size, too. 1430 1431 if (memUpperBound != fileUpperBound) { 1432 size_t bss_size = memUpperBound - fileUpperBound; 1433 1434 snprintf(regionName, B_OS_NAME_LENGTH, "%s_bss%d", baseName, i); 1435 1436 regionAddress += fileUpperBound; 1437 id = create_area_etc(team, regionName, (void **)®ionAddress, 1438 B_EXACT_ADDRESS, bss_size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA); 1439 if (id < B_OK) { 1440 dprintf("error allocating bss area: %s!\n", strerror(id)); 1441 status = B_NOT_AN_EXECUTABLE; 1442 goto error; 1443 } 1444 } 1445 } else { 1446 /* 1447 * assume ro/text segment 1448 */ 1449 snprintf(regionName, B_OS_NAME_LENGTH, "%s_seg%dro", baseName, i); 1450 1451 id = vm_map_file(team->id, regionName, 1452 (void **)®ionAddress, 1453 B_EXACT_ADDRESS, 1454 ROUNDUP(programHeaders[i].p_memsz + (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE), 1455 B_READ_AREA | B_EXECUTE_AREA, REGION_PRIVATE_MAP, 1456 path, ROUNDOWN(programHeaders[i].p_offset, B_PAGE_SIZE)); 1457 if (id < B_OK) { 1458 dprintf("error mapping file text: %s!\n", strerror(id)); 1459 status = B_NOT_AN_EXECUTABLE; 1460 goto error; 1461 } 1462 } 1463 } 1464 1465 TRACE(("elf_load: done!\n")); 1466 1467 *entry = elfHeader.e_entry; 1468 1469 status = B_OK; 1470 1471 error: 1472 if (programHeaders) 1473 free(programHeaders); 1474 _kern_close(fd); 1475 1476 return status; 1477 } 1478 1479 1480 image_id 1481 load_kernel_add_on(const char *path) 1482 { 1483 struct Elf32_Phdr *programHeaders; 1484 struct Elf32_Ehdr *elfHeader; 1485 struct elf_image_info *image; 1486 const char *fileName; 1487 void *reservedAddress; 1488 addr_t start; 1489 size_t reservedSize; 1490 status_t status; 1491 ssize_t length; 1492 1493 TRACE(("elf_load_kspace: entry path '%s'\n", path)); 1494 1495 int fd = _kern_open(-1, path, O_RDONLY, 0); 1496 if (fd < 0) 1497 return fd; 1498 1499 struct vnode *vnode; 1500 status = vfs_get_vnode_from_fd(fd, true, &vnode); 1501 if (status < B_OK) 1502 goto error0; 1503 1504 // get the file name 1505 fileName = strrchr(path, '/'); 1506 if (fileName == NULL) 1507 fileName = path; 1508 else 1509 fileName++; 1510 1511 // Prevent someone else from trying to load this image 1512 mutex_lock(&sImageLoadMutex); 1513 1514 // make sure it's not loaded already. Search by vnode 1515 image = find_image_by_vnode(vnode); 1516 if (image) { 1517 atomic_add(&image->ref_count, 1); 1518 goto done; 1519 } 1520 1521 elfHeader = (struct Elf32_Ehdr *)malloc(sizeof(*elfHeader)); 1522 if (!elfHeader) { 1523 status = B_NO_MEMORY; 1524 goto error; 1525 } 1526 1527 length = _kern_read(fd, 0, elfHeader, sizeof(*elfHeader)); 1528 if (length < B_OK) { 1529 status = length; 1530 goto error1; 1531 } 1532 if (length != sizeof(*elfHeader)) { 1533 // short read 1534 status = B_NOT_AN_EXECUTABLE; 1535 goto error1; 1536 } 1537 status = verify_eheader(elfHeader); 1538 if (status < B_OK) 1539 goto error1; 1540 1541 image = create_image_struct(); 1542 if (!image) { 1543 status = B_NO_MEMORY; 1544 goto error1; 1545 } 1546 image->vnode = vnode; 1547 image->elf_header = elfHeader; 1548 image->name = strdup(path); 1549 1550 programHeaders = (struct Elf32_Phdr *)malloc(elfHeader->e_phnum 1551 * elfHeader->e_phentsize); 1552 if (programHeaders == NULL) { 1553 dprintf("%s: error allocating space for program headers\n", fileName); 1554 status = B_NO_MEMORY; 1555 goto error2; 1556 } 1557 1558 TRACE(("reading in program headers at 0x%lx, length 0x%x\n", 1559 elfHeader->e_phoff, elfHeader->e_phnum * elfHeader->e_phentsize)); 1560 1561 length = _kern_read(fd, elfHeader->e_phoff, programHeaders, 1562 elfHeader->e_phnum * elfHeader->e_phentsize); 1563 if (length < B_OK) { 1564 status = length; 1565 TRACE(("%s: error reading in program headers\n", fileName)); 1566 goto error3; 1567 } 1568 if (length != elfHeader->e_phnum * elfHeader->e_phentsize) { 1569 TRACE(("%s: short read while reading in program headers\n", fileName)); 1570 status = B_ERROR; 1571 goto error3; 1572 } 1573 1574 // determine how much space we need for all loaded segments 1575 1576 reservedSize = 0; 1577 length = 0; 1578 1579 for (int32 i = 0; i < elfHeader->e_phnum; i++) { 1580 size_t end; 1581 1582 if (programHeaders[i].p_type != PT_LOAD) 1583 continue; 1584 1585 length += ROUNDUP(programHeaders[i].p_memsz 1586 + (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE); 1587 1588 end = ROUNDUP(programHeaders[i].p_memsz + programHeaders[i].p_vaddr, 1589 B_PAGE_SIZE); 1590 if (end > reservedSize) 1591 reservedSize = end; 1592 } 1593 1594 // Check whether the segments have an unreasonable amount of unused space 1595 // inbetween. 1596 if ((ssize_t)reservedSize > length + 8 * 1024) { 1597 status = B_BAD_DATA; 1598 goto error1; 1599 } 1600 1601 // reserve that space and allocate the areas from that one 1602 if (vm_reserve_address_range(vm_kernel_address_space_id(), &reservedAddress, 1603 B_ANY_KERNEL_ADDRESS, reservedSize, 0) < B_OK) { 1604 status = B_NO_MEMORY; 1605 goto error3; 1606 } 1607 1608 start = (addr_t)reservedAddress; 1609 image->data_region.size = 0; 1610 image->text_region.size = 0; 1611 1612 for (int32 i = 0; i < elfHeader->e_phnum; i++) { 1613 char regionName[B_OS_NAME_LENGTH]; 1614 elf_region *region; 1615 1616 TRACE(("looking at program header %ld\n", i)); 1617 1618 switch (programHeaders[i].p_type) { 1619 case PT_LOAD: 1620 break; 1621 case PT_DYNAMIC: 1622 image->dynamic_section = programHeaders[i].p_vaddr; 1623 continue; 1624 default: 1625 dprintf("%s: unhandled pheader type 0x%lx\n", fileName, 1626 programHeaders[i].p_type); 1627 continue; 1628 } 1629 1630 // we're here, so it must be a PT_LOAD segment 1631 if (programHeaders[i].IsReadWrite()) { 1632 // this is the writable segment 1633 if (image->data_region.size != 0) { 1634 // we've already created this segment 1635 continue; 1636 } 1637 region = &image->data_region; 1638 1639 snprintf(regionName, B_OS_NAME_LENGTH, "%s_data", fileName); 1640 } else if (programHeaders[i].IsExecutable()) { 1641 // this is the non-writable segment 1642 if (image->text_region.size != 0) { 1643 // we've already created this segment 1644 continue; 1645 } 1646 region = &image->text_region; 1647 1648 snprintf(regionName, B_OS_NAME_LENGTH, "%s_text", fileName); 1649 } else { 1650 dprintf("%s: weird program header flags 0x%lx\n", fileName, 1651 programHeaders[i].p_flags); 1652 continue; 1653 } 1654 1655 region->start = (addr_t)reservedAddress + ROUNDOWN( 1656 programHeaders[i].p_vaddr, B_PAGE_SIZE); 1657 region->size = ROUNDUP(programHeaders[i].p_memsz 1658 + (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE); 1659 region->id = create_area(regionName, (void **)®ion->start, 1660 B_EXACT_ADDRESS, region->size, B_FULL_LOCK, 1661 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); 1662 if (region->id < B_OK) { 1663 dprintf("%s: error allocating area: %s\n", fileName, 1664 strerror(region->id)); 1665 status = B_NOT_AN_EXECUTABLE; 1666 goto error4; 1667 } 1668 region->delta = -ROUNDOWN(programHeaders[i].p_vaddr, B_PAGE_SIZE); 1669 1670 TRACE(("elf_load_kspace: created area \"%s\" at %p\n", 1671 regionName, (void *)region->start)); 1672 1673 length = _kern_read(fd, programHeaders[i].p_offset, 1674 (void *)(region->start + (programHeaders[i].p_vaddr % B_PAGE_SIZE)), 1675 programHeaders[i].p_filesz); 1676 if (length < B_OK) { 1677 status = length; 1678 dprintf("%s: error reading in segment %ld\n", fileName, i); 1679 goto error5; 1680 } 1681 } 1682 1683 // get the segment order 1684 elf_region *firstRegion; 1685 elf_region *secondRegion; 1686 if (image->text_region.start < image->data_region.start) { 1687 firstRegion = &image->text_region; 1688 secondRegion = &image->data_region; 1689 } else { 1690 firstRegion = &image->data_region; 1691 secondRegion = &image->text_region; 1692 } 1693 1694 image->data_region.delta += image->data_region.start; 1695 image->text_region.delta += image->text_region.start; 1696 1697 // modify the dynamic ptr by the delta of the regions 1698 image->dynamic_section += image->text_region.delta; 1699 1700 status = elf_parse_dynamic_section(image); 1701 if (status < B_OK) 1702 goto error5; 1703 1704 status = elf_relocate(image, NULL); 1705 if (status < B_OK) 1706 goto error5; 1707 1708 // We needed to read in the contents of the "text" area, but 1709 // now we can protect it read-only/execute 1710 set_area_protection(image->text_region.id, 1711 B_KERNEL_READ_AREA | B_KERNEL_EXECUTE_AREA); 1712 1713 // There might be a hole between the two segments, and we don't need to 1714 // reserve this any longer 1715 vm_unreserve_address_range(vm_kernel_address_space_id(), reservedAddress, 1716 reservedSize); 1717 1718 // ToDo: this should be enabled by kernel settings! 1719 if (1) 1720 load_elf_symbol_table(fd, image); 1721 1722 free(programHeaders); 1723 mutex_lock(&sImageMutex); 1724 register_elf_image(image); 1725 mutex_unlock(&sImageMutex); 1726 1727 done: 1728 _kern_close(fd); 1729 mutex_unlock(&sImageLoadMutex); 1730 1731 return image->id; 1732 1733 error5: 1734 delete_area(image->data_region.id); 1735 delete_area(image->text_region.id); 1736 error4: 1737 vm_unreserve_address_range(vm_kernel_address_space_id(), reservedAddress, 1738 reservedSize); 1739 error3: 1740 free(programHeaders); 1741 error2: 1742 free(image); 1743 error1: 1744 free(elfHeader); 1745 error: 1746 mutex_unlock(&sImageLoadMutex); 1747 error0: 1748 dprintf("Could not load kernel add-on \"%s\": %s\n", path, 1749 strerror(status)); 1750 1751 if (vnode) 1752 vfs_put_vnode(vnode); 1753 _kern_close(fd); 1754 1755 return status; 1756 } 1757 1758 1759 status_t 1760 unload_kernel_add_on(image_id id) 1761 { 1762 struct elf_image_info *image; 1763 status_t status; 1764 1765 mutex_lock(&sImageLoadMutex); 1766 mutex_lock(&sImageMutex); 1767 1768 image = find_image(id); 1769 if (image != NULL) 1770 status = unload_elf_image(image); 1771 else 1772 status = B_BAD_IMAGE_ID; 1773 1774 mutex_unlock(&sImageMutex); 1775 mutex_unlock(&sImageLoadMutex); 1776 1777 return status; 1778 } 1779 1780 1781 status_t 1782 elf_init(kernel_args *args) 1783 { 1784 struct preloaded_image *image; 1785 1786 image_init(); 1787 1788 mutex_init(&sImageMutex, "kimages_lock"); 1789 mutex_init(&sImageLoadMutex, "kimages_load_lock"); 1790 1791 sImagesHash = hash_init(IMAGE_HASH_SIZE, 0, image_compare, image_hash); 1792 if (sImagesHash == NULL) 1793 return B_NO_MEMORY; 1794 1795 // Build a image structure for the kernel, which has already been loaded. 1796 // The preloaded_images were already prepared by the VM. 1797 if (insert_preloaded_image(&args->kernel_image, true) < B_OK) 1798 panic("could not create kernel image.\n"); 1799 1800 // Build image structures for all preloaded images. 1801 for (image = args->preloaded_images; image != NULL; image = image->next) { 1802 insert_preloaded_image(image, false); 1803 } 1804 1805 add_debugger_command("ls", &dump_address_info, "lookup symbol for a particular address"); 1806 add_debugger_command("symbols", &dump_symbols, "dump symbols for image"); 1807 add_debugger_command("symbol", &dump_symbol, "search symbol in images"); 1808 add_debugger_command("image", &dump_image, "dump image info"); 1809 1810 sInitialized = true; 1811 return B_OK; 1812 } 1813 1814