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