1 /* 2 * Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de. 4 * Distributed under the terms of the MIT License. 5 * 6 * Copyright 2001, Travis Geiselbrecht. All rights reserved. 7 * Distributed under the terms of the NewOS License. 8 */ 9 10 /*! Contains the ELF loader */ 11 12 13 #include <elf.h> 14 15 #include <OS.h> 16 17 #include <unistd.h> 18 #include <stdlib.h> 19 #include <string.h> 20 #include <stdio.h> 21 #include <ctype.h> 22 23 #include <algorithm> 24 25 #include <AutoDeleter.h> 26 #include <commpage.h> 27 #include <boot/kernel_args.h> 28 #include <debug.h> 29 #include <image_defs.h> 30 #include <kernel.h> 31 #include <kimage.h> 32 #include <syscalls.h> 33 #include <team.h> 34 #include <thread.h> 35 #include <runtime_loader.h> 36 #include <util/AutoLock.h> 37 #include <vfs.h> 38 #include <vm/vm.h> 39 #include <vm/vm_types.h> 40 #include <vm/VMAddressSpace.h> 41 #include <vm/VMArea.h> 42 43 #include <arch/cpu.h> 44 #include <arch/elf.h> 45 #include <elf_priv.h> 46 #include <boot/elf.h> 47 48 //#define TRACE_ELF 49 #ifdef TRACE_ELF 50 # define TRACE(x) dprintf x 51 #else 52 # define TRACE(x) ; 53 #endif 54 55 56 namespace { 57 58 #define IMAGE_HASH_SIZE 16 59 60 struct ImageHashDefinition { 61 typedef struct elf_image_info ValueType; 62 typedef image_id KeyType; 63 64 size_t Hash(ValueType* entry) const 65 { return HashKey(entry->id); } 66 ValueType*& GetLink(ValueType* entry) const 67 { return entry->next; } 68 69 size_t HashKey(KeyType key) const 70 { 71 return (size_t)key; 72 } 73 74 bool Compare(KeyType key, ValueType* entry) const 75 { 76 return key == entry->id; 77 } 78 }; 79 80 typedef BOpenHashTable<ImageHashDefinition> ImageHash; 81 82 } // namespace 83 84 85 static ImageHash *sImagesHash; 86 87 static struct elf_image_info *sKernelImage = NULL; 88 static mutex sImageMutex = MUTEX_INITIALIZER("kimages_lock"); 89 // guards sImagesHash 90 static mutex sImageLoadMutex = MUTEX_INITIALIZER("kimages_load_lock"); 91 // serializes loading/unloading add-ons locking order 92 // sImageLoadMutex -> sImageMutex 93 static bool sInitialized = false; 94 95 96 static elf_sym *elf_find_symbol(struct elf_image_info *image, const char *name, 97 const elf_version_info *version, bool lookupDefault); 98 99 100 static void 101 unregister_elf_image(struct elf_image_info *image) 102 { 103 unregister_image(team_get_kernel_team(), image->id); 104 sImagesHash->Remove(image); 105 } 106 107 108 static void 109 register_elf_image(struct elf_image_info *image) 110 { 111 image_info imageInfo; 112 113 memset(&imageInfo, 0, sizeof(image_info)); 114 imageInfo.id = image->id; 115 imageInfo.type = B_SYSTEM_IMAGE; 116 strlcpy(imageInfo.name, image->name, sizeof(imageInfo.name)); 117 118 imageInfo.text = (void *)image->text_region.start; 119 imageInfo.text_size = image->text_region.size; 120 imageInfo.data = (void *)image->data_region.start; 121 imageInfo.data_size = image->data_region.size; 122 123 if (image->text_region.id >= 0) { 124 // evaluate the API/ABI version symbols 125 126 // Haiku API version 127 imageInfo.api_version = 0; 128 elf_sym* symbol = elf_find_symbol(image, 129 B_SHARED_OBJECT_HAIKU_VERSION_VARIABLE_NAME, NULL, true); 130 if (symbol != NULL && symbol->st_shndx != SHN_UNDEF 131 && symbol->st_value > 0 132 && symbol->Type() == STT_OBJECT 133 && symbol->st_size >= sizeof(uint32)) { 134 addr_t symbolAddress = symbol->st_value + image->text_region.delta; 135 if (symbolAddress >= image->text_region.start 136 && symbolAddress - image->text_region.start + sizeof(uint32) 137 <= image->text_region.size) { 138 imageInfo.api_version = *(uint32*)symbolAddress; 139 } 140 } 141 142 // Haiku ABI 143 imageInfo.abi = 0; 144 symbol = elf_find_symbol(image, 145 B_SHARED_OBJECT_HAIKU_ABI_VARIABLE_NAME, NULL, true); 146 if (symbol != NULL && symbol->st_shndx != SHN_UNDEF 147 && symbol->st_value > 0 148 && symbol->Type() == STT_OBJECT 149 && symbol->st_size >= sizeof(uint32)) { 150 addr_t symbolAddress = symbol->st_value + image->text_region.delta; 151 if (symbolAddress >= image->text_region.start 152 && symbolAddress - image->text_region.start + sizeof(uint32) 153 <= image->text_region.size) { 154 imageInfo.api_version = *(uint32*)symbolAddress; 155 } 156 } 157 } else { 158 // in-memory image -- use the current values 159 imageInfo.api_version = B_HAIKU_VERSION; 160 imageInfo.abi = B_HAIKU_ABI; 161 } 162 163 image->id = register_image(team_get_kernel_team(), &imageInfo, 164 sizeof(image_info)); 165 sImagesHash->Insert(image); 166 } 167 168 169 /*! Note, you must lock the image mutex when you call this function. */ 170 static struct elf_image_info * 171 find_image_at_address(addr_t address) 172 { 173 #if KDEBUG 174 if (!debug_debugger_running()) 175 ASSERT_LOCKED_MUTEX(&sImageMutex); 176 #endif 177 178 ImageHash::Iterator iterator(sImagesHash); 179 180 // get image that may contain the address 181 182 while (iterator.HasNext()) { 183 struct elf_image_info* image = iterator.Next(); 184 if ((address >= image->text_region.start && address 185 <= (image->text_region.start + image->text_region.size)) 186 || (address >= image->data_region.start 187 && address 188 <= (image->data_region.start + image->data_region.size))) 189 return image; 190 } 191 192 return NULL; 193 } 194 195 196 static int 197 dump_address_info(int argc, char **argv) 198 { 199 const char *symbol, *imageName; 200 bool exactMatch; 201 addr_t address, baseAddress; 202 203 if (argc < 2) { 204 kprintf("usage: ls <address>\n"); 205 return 0; 206 } 207 208 address = strtoul(argv[1], NULL, 16); 209 210 status_t error; 211 212 if (IS_KERNEL_ADDRESS(address)) { 213 error = elf_debug_lookup_symbol_address(address, &baseAddress, &symbol, 214 &imageName, &exactMatch); 215 } else { 216 error = elf_debug_lookup_user_symbol_address( 217 debug_get_debugged_thread()->team, address, &baseAddress, &symbol, 218 &imageName, &exactMatch); 219 } 220 221 if (error == B_OK) { 222 kprintf("%p = %s + 0x%lx (%s)%s\n", (void*)address, symbol, 223 address - baseAddress, imageName, exactMatch ? "" : " (nearest)"); 224 } else 225 kprintf("There is no image loaded at this address!\n"); 226 227 return 0; 228 } 229 230 231 static struct elf_image_info * 232 find_image(image_id id) 233 { 234 return sImagesHash->Lookup(id); 235 } 236 237 238 static struct elf_image_info * 239 find_image_by_vnode(void *vnode) 240 { 241 MutexLocker locker(sImageMutex); 242 243 ImageHash::Iterator iterator(sImagesHash); 244 while (iterator.HasNext()) { 245 struct elf_image_info* image = iterator.Next(); 246 if (image->vnode == vnode) 247 return image; 248 } 249 250 return NULL; 251 } 252 253 254 static struct elf_image_info * 255 create_image_struct() 256 { 257 struct elf_image_info *image 258 = (struct elf_image_info *)malloc(sizeof(struct elf_image_info)); 259 if (image == NULL) 260 return NULL; 261 262 memset(image, 0, sizeof(struct elf_image_info)); 263 264 image->text_region.id = -1; 265 image->data_region.id = -1; 266 image->ref_count = 1; 267 268 return image; 269 } 270 271 272 static void 273 delete_elf_image(struct elf_image_info *image) 274 { 275 if (image->text_region.id >= 0) 276 delete_area(image->text_region.id); 277 278 if (image->data_region.id >= 0) 279 delete_area(image->data_region.id); 280 281 if (image->vnode) 282 vfs_put_vnode(image->vnode); 283 284 free(image->versions); 285 free(image->debug_symbols); 286 free((void*)image->debug_string_table); 287 free(image->elf_header); 288 free(image->name); 289 free(image); 290 } 291 292 293 static uint32 294 elf_hash(const char *name) 295 { 296 uint32 hash = 0; 297 uint32 temp; 298 299 while (*name) { 300 hash = (hash << 4) + (uint8)*name++; 301 if ((temp = hash & 0xf0000000) != 0) 302 hash ^= temp >> 24; 303 hash &= ~temp; 304 } 305 return hash; 306 } 307 308 309 static const char * 310 get_symbol_type_string(elf_sym *symbol) 311 { 312 switch (symbol->Type()) { 313 case STT_FUNC: 314 return "func"; 315 case STT_OBJECT: 316 return " obj"; 317 case STT_FILE: 318 return "file"; 319 default: 320 return "----"; 321 } 322 } 323 324 325 static const char * 326 get_symbol_bind_string(elf_sym *symbol) 327 { 328 switch (symbol->Bind()) { 329 case STB_LOCAL: 330 return "loc "; 331 case STB_GLOBAL: 332 return "glob"; 333 case STB_WEAK: 334 return "weak"; 335 default: 336 return "----"; 337 } 338 } 339 340 341 /*! Searches a symbol (pattern) in all kernel images */ 342 static int 343 dump_symbol(int argc, char **argv) 344 { 345 if (argc != 2 || !strcmp(argv[1], "--help")) { 346 kprintf("usage: %s <symbol-name>\n", argv[0]); 347 return 0; 348 } 349 350 struct elf_image_info *image = NULL; 351 const char *pattern = argv[1]; 352 353 void* symbolAddress = NULL; 354 355 ImageHash::Iterator iterator(sImagesHash); 356 while (iterator.HasNext()) { 357 image = iterator.Next(); 358 if (image->num_debug_symbols > 0) { 359 // search extended debug symbol table (contains static symbols) 360 for (uint32 i = 0; i < image->num_debug_symbols; i++) { 361 elf_sym *symbol = &image->debug_symbols[i]; 362 const char *name = image->debug_string_table + symbol->st_name; 363 364 if (symbol->st_value > 0 && strstr(name, pattern) != 0) { 365 symbolAddress 366 = (void*)(symbol->st_value + image->text_region.delta); 367 kprintf("%p %5lu %s:%s\n", symbolAddress, symbol->st_size, 368 image->name, name); 369 } 370 } 371 } else { 372 // search standard symbol lookup table 373 for (uint32 i = 0; i < HASHTABSIZE(image); i++) { 374 for (uint32 j = HASHBUCKETS(image)[i]; j != STN_UNDEF; 375 j = HASHCHAINS(image)[j]) { 376 elf_sym *symbol = &image->syms[j]; 377 const char *name = SYMNAME(image, symbol); 378 379 if (symbol->st_value > 0 && strstr(name, pattern) != 0) { 380 symbolAddress = (void*)(symbol->st_value 381 + image->text_region.delta); 382 kprintf("%p %5lu %s:%s\n", symbolAddress, 383 symbol->st_size, image->name, name); 384 } 385 } 386 } 387 } 388 } 389 390 if (symbolAddress != NULL) 391 set_debug_variable("_", (addr_t)symbolAddress); 392 393 return 0; 394 } 395 396 397 static int 398 dump_symbols(int argc, char **argv) 399 { 400 struct elf_image_info *image = NULL; 401 uint32 i; 402 403 // if the argument looks like a hex number, treat it as such 404 if (argc > 1) { 405 if (isdigit(argv[1][0])) { 406 addr_t num = strtoul(argv[1], NULL, 0); 407 408 if (IS_KERNEL_ADDRESS(num)) { 409 // find image at address 410 411 ImageHash::Iterator iterator(sImagesHash); 412 while (iterator.HasNext()) { 413 elf_image_info* current = iterator.Next(); 414 if (current->text_region.start <= num 415 && current->text_region.start 416 + current->text_region.size >= num) { 417 image = current; 418 break; 419 } 420 } 421 422 if (image == NULL) { 423 kprintf("No image covers %#" B_PRIxADDR " in the kernel!\n", 424 num); 425 } 426 } else { 427 image = sImagesHash->Lookup(num); 428 if (image == NULL) { 429 kprintf("image %#" B_PRIxADDR " doesn't exist in the " 430 "kernel!\n", num); 431 } 432 } 433 } else { 434 // look for image by name 435 ImageHash::Iterator iterator(sImagesHash); 436 while (iterator.HasNext()) { 437 elf_image_info* current = iterator.Next(); 438 if (!strcmp(current->name, argv[1])) { 439 image = current; 440 break; 441 } 442 } 443 444 if (image == NULL) 445 kprintf("No image \"%s\" found in kernel!\n", argv[1]); 446 } 447 } else { 448 kprintf("usage: %s image_name/image_id/address_in_image\n", argv[0]); 449 return 0; 450 } 451 452 if (image == NULL) 453 return -1; 454 455 // dump symbols 456 457 kprintf("Symbols of image %" B_PRId32 " \"%s\":\n", image->id, image->name); 458 kprintf("%-*s Type Size Name\n", B_PRINTF_POINTER_WIDTH, "Address"); 459 460 if (image->num_debug_symbols > 0) { 461 // search extended debug symbol table (contains static symbols) 462 for (i = 0; i < image->num_debug_symbols; i++) { 463 elf_sym *symbol = &image->debug_symbols[i]; 464 465 if (symbol->st_value == 0 || symbol->st_size 466 >= image->text_region.size + image->data_region.size) 467 continue; 468 469 kprintf("%0*lx %s/%s %5ld %s\n", B_PRINTF_POINTER_WIDTH, 470 symbol->st_value + image->text_region.delta, 471 get_symbol_type_string(symbol), get_symbol_bind_string(symbol), 472 symbol->st_size, image->debug_string_table + symbol->st_name); 473 } 474 } else { 475 int32 j; 476 477 // search standard symbol lookup table 478 for (i = 0; i < HASHTABSIZE(image); i++) { 479 for (j = HASHBUCKETS(image)[i]; j != STN_UNDEF; 480 j = HASHCHAINS(image)[j]) { 481 elf_sym *symbol = &image->syms[j]; 482 483 if (symbol->st_value == 0 || symbol->st_size 484 >= image->text_region.size + image->data_region.size) 485 continue; 486 487 kprintf("%08lx %s/%s %5ld %s\n", 488 symbol->st_value + image->text_region.delta, 489 get_symbol_type_string(symbol), 490 get_symbol_bind_string(symbol), 491 symbol->st_size, SYMNAME(image, symbol)); 492 } 493 } 494 } 495 496 return 0; 497 } 498 499 500 static void 501 dump_elf_region(struct elf_region *region, const char *name) 502 { 503 kprintf(" %s.id %" B_PRId32 "\n", name, region->id); 504 kprintf(" %s.start %#" B_PRIxADDR "\n", name, region->start); 505 kprintf(" %s.size %#" B_PRIxSIZE "\n", name, region->size); 506 kprintf(" %s.delta %ld\n", name, region->delta); 507 } 508 509 510 static void 511 dump_image_info(struct elf_image_info *image) 512 { 513 kprintf("elf_image_info at %p:\n", image); 514 kprintf(" next %p\n", image->next); 515 kprintf(" id %" B_PRId32 "\n", image->id); 516 dump_elf_region(&image->text_region, "text"); 517 dump_elf_region(&image->data_region, "data"); 518 kprintf(" dynamic_section %#" B_PRIxADDR "\n", image->dynamic_section); 519 kprintf(" needed %p\n", image->needed); 520 kprintf(" symhash %p\n", image->symhash); 521 kprintf(" syms %p\n", image->syms); 522 kprintf(" strtab %p\n", image->strtab); 523 kprintf(" rel %p\n", image->rel); 524 kprintf(" rel_len %#x\n", image->rel_len); 525 kprintf(" rela %p\n", image->rela); 526 kprintf(" rela_len %#x\n", image->rela_len); 527 kprintf(" pltrel %p\n", image->pltrel); 528 kprintf(" pltrel_len %#x\n", image->pltrel_len); 529 530 kprintf(" debug_symbols %p (%" B_PRIu32 ")\n", 531 image->debug_symbols, image->num_debug_symbols); 532 } 533 534 535 static int 536 dump_image(int argc, char **argv) 537 { 538 struct elf_image_info *image; 539 540 // if the argument looks like a hex number, treat it as such 541 if (argc > 1) { 542 addr_t num = strtoul(argv[1], NULL, 0); 543 544 if (IS_KERNEL_ADDRESS(num)) { 545 // semi-hack 546 dump_image_info((struct elf_image_info *)num); 547 } else { 548 image = sImagesHash->Lookup(num); 549 if (image == NULL) { 550 kprintf("image %#" B_PRIxADDR " doesn't exist in the kernel!\n", 551 num); 552 } else 553 dump_image_info(image); 554 } 555 return 0; 556 } 557 558 kprintf("loaded kernel images:\n"); 559 560 ImageHash::Iterator iterator(sImagesHash); 561 562 while (iterator.HasNext()) { 563 image = iterator.Next(); 564 kprintf("%p (%" B_PRId32 ") %s\n", image, image->id, image->name); 565 } 566 567 return 0; 568 } 569 570 571 // Currently unused 572 #if 0 573 static 574 void dump_symbol(struct elf_image_info *image, elf_sym *sym) 575 { 576 577 kprintf("symbol at %p, in image %p\n", sym, image); 578 579 kprintf(" name index %d, '%s'\n", sym->st_name, SYMNAME(image, sym)); 580 kprintf(" st_value 0x%x\n", sym->st_value); 581 kprintf(" st_size %d\n", sym->st_size); 582 kprintf(" st_info 0x%x\n", sym->st_info); 583 kprintf(" st_other 0x%x\n", sym->st_other); 584 kprintf(" st_shndx %d\n", sym->st_shndx); 585 } 586 #endif 587 588 589 static elf_sym * 590 elf_find_symbol(struct elf_image_info *image, const char *name, 591 const elf_version_info *lookupVersion, bool lookupDefault) 592 { 593 if (image->dynamic_section == 0 || HASHTABSIZE(image) == 0) 594 return NULL; 595 596 elf_sym* versionedSymbol = NULL; 597 uint32 versionedSymbolCount = 0; 598 599 uint32 hash = elf_hash(name) % HASHTABSIZE(image); 600 for (uint32 i = HASHBUCKETS(image)[hash]; i != STN_UNDEF; 601 i = HASHCHAINS(image)[i]) { 602 elf_sym* symbol = &image->syms[i]; 603 604 // consider only symbols with the right name and binding 605 if (symbol->st_shndx == SHN_UNDEF 606 || ((symbol->Bind() != STB_GLOBAL) && (symbol->Bind() != STB_WEAK)) 607 || strcmp(SYMNAME(image, symbol), name) != 0) { 608 continue; 609 } 610 611 // check the version 612 613 // Handle the simple cases -- the image doesn't have version 614 // information -- first. 615 if (image->symbol_versions == NULL) { 616 if (lookupVersion == NULL) { 617 // No specific symbol version was requested either, so the 618 // symbol is just fine. 619 return symbol; 620 } 621 622 // A specific version is requested. Since the only possible 623 // dependency is the kernel itself, the add-on was obviously linked 624 // against a newer kernel. 625 dprintf("Kernel add-on requires version support, but the kernel " 626 "is too old.\n"); 627 return NULL; 628 } 629 630 // The image has version information. Let's see what we've got. 631 uint32 versionID = image->symbol_versions[i]; 632 uint32 versionIndex = VER_NDX(versionID); 633 elf_version_info& version = image->versions[versionIndex]; 634 635 // skip local versions 636 if (versionIndex == VER_NDX_LOCAL) 637 continue; 638 639 if (lookupVersion != NULL) { 640 // a specific version is requested 641 642 // compare the versions 643 if (version.hash == lookupVersion->hash 644 && strcmp(version.name, lookupVersion->name) == 0) { 645 // versions match 646 return symbol; 647 } 648 649 // The versions don't match. We're still fine with the 650 // base version, if it is public and we're not looking for 651 // the default version. 652 if ((versionID & VER_NDX_FLAG_HIDDEN) == 0 653 && versionIndex == VER_NDX_GLOBAL 654 && !lookupDefault) { 655 // TODO: Revise the default version case! That's how 656 // FreeBSD implements it, but glibc doesn't handle it 657 // specially. 658 return symbol; 659 } 660 } else { 661 // No specific version requested, but the image has version 662 // information. This can happen in either of these cases: 663 // 664 // * The dependent object was linked against an older version 665 // of the now versioned dependency. 666 // * The symbol is looked up via find_image_symbol() or dlsym(). 667 // 668 // In the first case we return the base version of the symbol 669 // (VER_NDX_GLOBAL or VER_NDX_INITIAL), or, if that doesn't 670 // exist, the unique, non-hidden versioned symbol. 671 // 672 // In the second case we want to return the public default 673 // version of the symbol. The handling is pretty similar to the 674 // first case, with the exception that we treat VER_NDX_INITIAL 675 // as regular version. 676 677 // VER_NDX_GLOBAL is always good, VER_NDX_INITIAL is fine, if 678 // we don't look for the default version. 679 if (versionIndex == VER_NDX_GLOBAL 680 || (!lookupDefault && versionIndex == VER_NDX_INITIAL)) { 681 return symbol; 682 } 683 684 // If not hidden, remember the version -- we'll return it, if 685 // it is the only one. 686 if ((versionID & VER_NDX_FLAG_HIDDEN) == 0) { 687 versionedSymbolCount++; 688 versionedSymbol = symbol; 689 } 690 } 691 } 692 693 return versionedSymbolCount == 1 ? versionedSymbol : NULL; 694 } 695 696 697 static status_t 698 elf_parse_dynamic_section(struct elf_image_info *image) 699 { 700 elf_dyn *d; 701 ssize_t neededOffset = -1; 702 703 TRACE(("top of elf_parse_dynamic_section\n")); 704 705 image->symhash = 0; 706 image->syms = 0; 707 image->strtab = 0; 708 709 d = (elf_dyn *)image->dynamic_section; 710 if (!d) 711 return B_ERROR; 712 713 for (int32 i = 0; d[i].d_tag != DT_NULL; i++) { 714 switch (d[i].d_tag) { 715 case DT_NEEDED: 716 neededOffset = d[i].d_un.d_ptr + image->text_region.delta; 717 break; 718 case DT_HASH: 719 image->symhash = (uint32 *)(d[i].d_un.d_ptr 720 + image->text_region.delta); 721 break; 722 case DT_STRTAB: 723 image->strtab = (char *)(d[i].d_un.d_ptr 724 + image->text_region.delta); 725 break; 726 case DT_SYMTAB: 727 image->syms = (elf_sym *)(d[i].d_un.d_ptr 728 + image->text_region.delta); 729 break; 730 case DT_REL: 731 image->rel = (elf_rel *)(d[i].d_un.d_ptr 732 + image->text_region.delta); 733 break; 734 case DT_RELSZ: 735 image->rel_len = d[i].d_un.d_val; 736 break; 737 case DT_RELA: 738 image->rela = (elf_rela *)(d[i].d_un.d_ptr 739 + image->text_region.delta); 740 break; 741 case DT_RELASZ: 742 image->rela_len = d[i].d_un.d_val; 743 break; 744 case DT_JMPREL: 745 image->pltrel = (elf_rel *)(d[i].d_un.d_ptr 746 + image->text_region.delta); 747 break; 748 case DT_PLTRELSZ: 749 image->pltrel_len = d[i].d_un.d_val; 750 break; 751 case DT_PLTREL: 752 image->pltrel_type = d[i].d_un.d_val; 753 break; 754 case DT_VERSYM: 755 image->symbol_versions = (elf_versym*) 756 (d[i].d_un.d_ptr + image->text_region.delta); 757 break; 758 case DT_VERDEF: 759 image->version_definitions = (elf_verdef*) 760 (d[i].d_un.d_ptr + image->text_region.delta); 761 break; 762 case DT_VERDEFNUM: 763 image->num_version_definitions = d[i].d_un.d_val; 764 break; 765 case DT_VERNEED: 766 image->needed_versions = (elf_verneed*) 767 (d[i].d_un.d_ptr + image->text_region.delta); 768 break; 769 case DT_VERNEEDNUM: 770 image->num_needed_versions = d[i].d_un.d_val; 771 break; 772 case DT_SYMBOLIC: 773 image->symbolic = true; 774 break; 775 case DT_FLAGS: 776 { 777 uint32 flags = d[i].d_un.d_val; 778 if ((flags & DF_SYMBOLIC) != 0) 779 image->symbolic = true; 780 break; 781 } 782 783 default: 784 continue; 785 } 786 } 787 788 // lets make sure we found all the required sections 789 if (!image->symhash || !image->syms || !image->strtab) 790 return B_ERROR; 791 792 TRACE(("needed_offset = %ld\n", neededOffset)); 793 794 if (neededOffset >= 0) 795 image->needed = STRING(image, neededOffset); 796 797 return B_OK; 798 } 799 800 801 static status_t 802 assert_defined_image_version(elf_image_info* dependentImage, 803 elf_image_info* image, const elf_version_info& neededVersion, bool weak) 804 { 805 // If the image doesn't have version definitions, we print a warning and 806 // succeed. Weird, but that's how glibc does it. Not unlikely we'll fail 807 // later when resolving versioned symbols. 808 if (image->version_definitions == NULL) { 809 dprintf("%s: No version information available (required by %s)\n", 810 image->name, dependentImage->name); 811 return B_OK; 812 } 813 814 // iterate through the defined versions to find the given one 815 elf_verdef* definition = image->version_definitions; 816 for (uint32 i = 0; i < image->num_version_definitions; i++) { 817 uint32 versionIndex = VER_NDX(definition->vd_ndx); 818 elf_version_info& info = image->versions[versionIndex]; 819 820 if (neededVersion.hash == info.hash 821 && strcmp(neededVersion.name, info.name) == 0) { 822 return B_OK; 823 } 824 825 definition = (elf_verdef*) 826 ((uint8*)definition + definition->vd_next); 827 } 828 829 // version not found -- fail, if not weak 830 if (!weak) { 831 dprintf("%s: version \"%s\" not found (required by %s)\n", image->name, 832 neededVersion.name, dependentImage->name); 833 return B_MISSING_SYMBOL; 834 } 835 836 return B_OK; 837 } 838 839 840 static status_t 841 init_image_version_infos(elf_image_info* image) 842 { 843 // First find out how many version infos we need -- i.e. get the greatest 844 // version index from the defined and needed versions (they use the same 845 // index namespace). 846 uint32 maxIndex = 0; 847 848 if (image->version_definitions != NULL) { 849 elf_verdef* definition = image->version_definitions; 850 for (uint32 i = 0; i < image->num_version_definitions; i++) { 851 if (definition->vd_version != 1) { 852 dprintf("Unsupported version definition revision: %u\n", 853 definition->vd_version); 854 return B_BAD_VALUE; 855 } 856 857 uint32 versionIndex = VER_NDX(definition->vd_ndx); 858 if (versionIndex > maxIndex) 859 maxIndex = versionIndex; 860 861 definition = (elf_verdef*) 862 ((uint8*)definition + definition->vd_next); 863 } 864 } 865 866 if (image->needed_versions != NULL) { 867 elf_verneed* needed = image->needed_versions; 868 for (uint32 i = 0; i < image->num_needed_versions; i++) { 869 if (needed->vn_version != 1) { 870 dprintf("Unsupported version needed revision: %u\n", 871 needed->vn_version); 872 return B_BAD_VALUE; 873 } 874 875 elf_vernaux* vernaux 876 = (elf_vernaux*)((uint8*)needed + needed->vn_aux); 877 for (uint32 k = 0; k < needed->vn_cnt; k++) { 878 uint32 versionIndex = VER_NDX(vernaux->vna_other); 879 if (versionIndex > maxIndex) 880 maxIndex = versionIndex; 881 882 vernaux = (elf_vernaux*)((uint8*)vernaux + vernaux->vna_next); 883 } 884 885 needed = (elf_verneed*)((uint8*)needed + needed->vn_next); 886 } 887 } 888 889 if (maxIndex == 0) 890 return B_OK; 891 892 // allocate the version infos 893 image->versions 894 = (elf_version_info*)malloc(sizeof(elf_version_info) * (maxIndex + 1)); 895 if (image->versions == NULL) { 896 dprintf("Memory shortage in init_image_version_infos()\n"); 897 return B_NO_MEMORY; 898 } 899 image->num_versions = maxIndex + 1; 900 901 // init the version infos 902 903 // version definitions 904 if (image->version_definitions != NULL) { 905 elf_verdef* definition = image->version_definitions; 906 for (uint32 i = 0; i < image->num_version_definitions; i++) { 907 if (definition->vd_cnt > 0 908 && (definition->vd_flags & VER_FLG_BASE) == 0) { 909 elf_verdaux* verdaux 910 = (elf_verdaux*)((uint8*)definition + definition->vd_aux); 911 912 uint32 versionIndex = VER_NDX(definition->vd_ndx); 913 elf_version_info& info = image->versions[versionIndex]; 914 info.hash = definition->vd_hash; 915 info.name = STRING(image, verdaux->vda_name); 916 info.file_name = NULL; 917 } 918 919 definition = (elf_verdef*) 920 ((uint8*)definition + definition->vd_next); 921 } 922 } 923 924 // needed versions 925 if (image->needed_versions != NULL) { 926 elf_verneed* needed = image->needed_versions; 927 for (uint32 i = 0; i < image->num_needed_versions; i++) { 928 const char* fileName = STRING(image, needed->vn_file); 929 930 elf_vernaux* vernaux 931 = (elf_vernaux*)((uint8*)needed + needed->vn_aux); 932 for (uint32 k = 0; k < needed->vn_cnt; k++) { 933 uint32 versionIndex = VER_NDX(vernaux->vna_other); 934 elf_version_info& info = image->versions[versionIndex]; 935 info.hash = vernaux->vna_hash; 936 info.name = STRING(image, vernaux->vna_name); 937 info.file_name = fileName; 938 939 vernaux = (elf_vernaux*)((uint8*)vernaux + vernaux->vna_next); 940 } 941 942 needed = (elf_verneed*)((uint8*)needed + needed->vn_next); 943 } 944 } 945 946 return B_OK; 947 } 948 949 950 static status_t 951 check_needed_image_versions(elf_image_info* image) 952 { 953 if (image->needed_versions == NULL) 954 return B_OK; 955 956 elf_verneed* needed = image->needed_versions; 957 for (uint32 i = 0; i < image->num_needed_versions; i++) { 958 elf_image_info* dependency = sKernelImage; 959 960 elf_vernaux* vernaux 961 = (elf_vernaux*)((uint8*)needed + needed->vn_aux); 962 for (uint32 k = 0; k < needed->vn_cnt; k++) { 963 uint32 versionIndex = VER_NDX(vernaux->vna_other); 964 elf_version_info& info = image->versions[versionIndex]; 965 966 status_t error = assert_defined_image_version(image, dependency, 967 info, (vernaux->vna_flags & VER_FLG_WEAK) != 0); 968 if (error != B_OK) 969 return error; 970 971 vernaux = (elf_vernaux*)((uint8*)vernaux + vernaux->vna_next); 972 } 973 974 needed = (elf_verneed*)((uint8*)needed + needed->vn_next); 975 } 976 977 return B_OK; 978 } 979 980 981 /*! Resolves the \a symbol by linking against \a sharedImage if necessary. 982 Returns the resolved symbol's address in \a _symbolAddress. 983 */ 984 status_t 985 elf_resolve_symbol(struct elf_image_info *image, elf_sym *symbol, 986 struct elf_image_info *sharedImage, addr_t *_symbolAddress) 987 { 988 // Local symbols references are always resolved to the given symbol. 989 if (symbol->Bind() == STB_LOCAL) { 990 *_symbolAddress = symbol->st_value + image->text_region.delta; 991 return B_OK; 992 } 993 994 // Non-local symbols we try to resolve to the kernel image first. Unless 995 // the image is linked symbolically, then vice versa. 996 elf_image_info* firstImage = sharedImage; 997 elf_image_info* secondImage = image; 998 if (image->symbolic) 999 std::swap(firstImage, secondImage); 1000 1001 const char *symbolName = SYMNAME(image, symbol); 1002 1003 // get the version info 1004 const elf_version_info* versionInfo = NULL; 1005 if (image->symbol_versions != NULL) { 1006 uint32 index = symbol - image->syms; 1007 uint32 versionIndex = VER_NDX(image->symbol_versions[index]); 1008 if (versionIndex >= VER_NDX_INITIAL) 1009 versionInfo = image->versions + versionIndex; 1010 } 1011 1012 // find the symbol 1013 elf_image_info* foundImage = firstImage; 1014 elf_sym* foundSymbol = elf_find_symbol(firstImage, symbolName, versionInfo, 1015 false); 1016 if (foundSymbol == NULL 1017 || foundSymbol->Bind() == STB_WEAK) { 1018 // Not found or found a weak definition -- try to resolve in the other 1019 // image. 1020 elf_sym* secondSymbol = elf_find_symbol(secondImage, symbolName, 1021 versionInfo, false); 1022 // If we found a symbol -- take it in case we didn't have a symbol 1023 // before or the new symbol is not weak. 1024 if (secondSymbol != NULL 1025 && (foundSymbol == NULL 1026 || secondSymbol->Bind() != STB_WEAK)) { 1027 foundImage = secondImage; 1028 foundSymbol = secondSymbol; 1029 } 1030 } 1031 1032 if (foundSymbol == NULL) { 1033 // Weak undefined symbols get a value of 0, if unresolved. 1034 if (symbol->Bind() == STB_WEAK) { 1035 *_symbolAddress = 0; 1036 return B_OK; 1037 } 1038 1039 dprintf("\"%s\": could not resolve symbol '%s'\n", image->name, 1040 symbolName); 1041 return B_MISSING_SYMBOL; 1042 } 1043 1044 // make sure they're the same type 1045 if (symbol->Type() != foundSymbol->Type()) { 1046 dprintf("elf_resolve_symbol: found symbol '%s' in image '%s' " 1047 "(requested by image '%s') but wrong type (%d vs. %d)\n", 1048 symbolName, foundImage->name, image->name, 1049 foundSymbol->Type(), symbol->Type()); 1050 return B_MISSING_SYMBOL; 1051 } 1052 1053 *_symbolAddress = foundSymbol->st_value + foundImage->text_region.delta; 1054 return B_OK; 1055 } 1056 1057 1058 /*! Until we have shared library support, just this links against the kernel */ 1059 static int 1060 elf_relocate(struct elf_image_info* image, struct elf_image_info* resolveImage) 1061 { 1062 int status = B_NO_ERROR; 1063 1064 TRACE(("elf_relocate(%p (\"%s\"))\n", image, image->name)); 1065 1066 // deal with the rels first 1067 if (image->rel) { 1068 TRACE(("total %i rel relocs\n", image->rel_len / (int)sizeof(elf_rel))); 1069 1070 status = arch_elf_relocate_rel(image, resolveImage, image->rel, 1071 image->rel_len); 1072 if (status < B_OK) 1073 return status; 1074 } 1075 1076 if (image->pltrel) { 1077 if (image->pltrel_type == DT_REL) { 1078 TRACE(("total %i plt-relocs\n", 1079 image->pltrel_len / (int)sizeof(elf_rel))); 1080 status = arch_elf_relocate_rel(image, resolveImage, image->pltrel, 1081 image->pltrel_len); 1082 } else { 1083 TRACE(("total %i plt-relocs\n", 1084 image->pltrel_len / (int)sizeof(elf_rela))); 1085 status = arch_elf_relocate_rela(image, resolveImage, 1086 (elf_rela *)image->pltrel, image->pltrel_len); 1087 } 1088 if (status < B_OK) 1089 return status; 1090 } 1091 1092 if (image->rela) { 1093 TRACE(("total %i rel relocs\n", 1094 image->rela_len / (int)sizeof(elf_rela))); 1095 1096 status = arch_elf_relocate_rela(image, resolveImage, image->rela, 1097 image->rela_len); 1098 if (status < B_OK) 1099 return status; 1100 } 1101 1102 return status; 1103 } 1104 1105 1106 static int 1107 verify_eheader(elf_ehdr *elfHeader) 1108 { 1109 if (memcmp(elfHeader->e_ident, ELF_MAGIC, 4) != 0) 1110 return B_NOT_AN_EXECUTABLE; 1111 1112 if (elfHeader->e_ident[4] != ELF_CLASS) 1113 return B_NOT_AN_EXECUTABLE; 1114 1115 if (elfHeader->e_phoff == 0) 1116 return B_NOT_AN_EXECUTABLE; 1117 1118 if (elfHeader->e_phentsize < sizeof(elf_phdr)) 1119 return B_NOT_AN_EXECUTABLE; 1120 1121 return 0; 1122 } 1123 1124 1125 static void 1126 unload_elf_image(struct elf_image_info *image) 1127 { 1128 if (atomic_add(&image->ref_count, -1) > 1) 1129 return; 1130 1131 TRACE(("unload image %" B_PRId32 ", %s\n", image->id, image->name)); 1132 1133 unregister_elf_image(image); 1134 delete_elf_image(image); 1135 } 1136 1137 1138 static status_t 1139 load_elf_symbol_table(int fd, struct elf_image_info *image) 1140 { 1141 elf_ehdr *elfHeader = image->elf_header; 1142 elf_sym *symbolTable = NULL; 1143 elf_shdr *stringHeader = NULL; 1144 uint32 numSymbols = 0; 1145 char *stringTable; 1146 status_t status; 1147 ssize_t length; 1148 int32 i; 1149 1150 // get section headers 1151 1152 ssize_t size = elfHeader->e_shnum * elfHeader->e_shentsize; 1153 elf_shdr *sectionHeaders = (elf_shdr *)malloc(size); 1154 if (sectionHeaders == NULL) { 1155 dprintf("error allocating space for section headers\n"); 1156 return B_NO_MEMORY; 1157 } 1158 1159 length = read_pos(fd, elfHeader->e_shoff, sectionHeaders, size); 1160 if (length < size) { 1161 TRACE(("error reading in program headers\n")); 1162 status = B_ERROR; 1163 goto error1; 1164 } 1165 1166 // find symbol table in section headers 1167 1168 for (i = 0; i < elfHeader->e_shnum; i++) { 1169 if (sectionHeaders[i].sh_type == SHT_SYMTAB) { 1170 stringHeader = §ionHeaders[sectionHeaders[i].sh_link]; 1171 1172 if (stringHeader->sh_type != SHT_STRTAB) { 1173 TRACE(("doesn't link to string table\n")); 1174 status = B_BAD_DATA; 1175 goto error1; 1176 } 1177 1178 // read in symbol table 1179 size = sectionHeaders[i].sh_size; 1180 symbolTable = (elf_sym *)malloc(size); 1181 if (symbolTable == NULL) { 1182 status = B_NO_MEMORY; 1183 goto error1; 1184 } 1185 1186 length 1187 = read_pos(fd, sectionHeaders[i].sh_offset, symbolTable, size); 1188 if (length < size) { 1189 TRACE(("error reading in symbol table\n")); 1190 status = B_ERROR; 1191 goto error2; 1192 } 1193 1194 numSymbols = size / sizeof(elf_sym); 1195 break; 1196 } 1197 } 1198 1199 if (symbolTable == NULL) { 1200 TRACE(("no symbol table\n")); 1201 status = B_BAD_VALUE; 1202 goto error1; 1203 } 1204 1205 // read in string table 1206 1207 stringTable = (char *)malloc(size = stringHeader->sh_size); 1208 if (stringTable == NULL) { 1209 status = B_NO_MEMORY; 1210 goto error2; 1211 } 1212 1213 length = read_pos(fd, stringHeader->sh_offset, stringTable, size); 1214 if (length < size) { 1215 TRACE(("error reading in string table\n")); 1216 status = B_ERROR; 1217 goto error3; 1218 } 1219 1220 TRACE(("loaded %" B_PRId32 " debug symbols\n", numSymbols)); 1221 1222 // insert tables into image 1223 image->debug_symbols = symbolTable; 1224 image->num_debug_symbols = numSymbols; 1225 image->debug_string_table = stringTable; 1226 1227 free(sectionHeaders); 1228 return B_OK; 1229 1230 error3: 1231 free(stringTable); 1232 error2: 1233 free(symbolTable); 1234 error1: 1235 free(sectionHeaders); 1236 1237 return status; 1238 } 1239 1240 1241 static status_t 1242 insert_preloaded_image(preloaded_elf_image *preloadedImage, bool kernel) 1243 { 1244 status_t status; 1245 1246 status = verify_eheader(&preloadedImage->elf_header); 1247 if (status != B_OK) 1248 return status; 1249 1250 elf_image_info *image = create_image_struct(); 1251 if (image == NULL) 1252 return B_NO_MEMORY; 1253 1254 image->name = strdup(preloadedImage->name); 1255 image->dynamic_section = preloadedImage->dynamic_section.start; 1256 1257 image->text_region.id = preloadedImage->text_region.id; 1258 image->text_region.start = preloadedImage->text_region.start; 1259 image->text_region.size = preloadedImage->text_region.size; 1260 image->text_region.delta = preloadedImage->text_region.delta; 1261 image->data_region.id = preloadedImage->data_region.id; 1262 image->data_region.start = preloadedImage->data_region.start; 1263 image->data_region.size = preloadedImage->data_region.size; 1264 image->data_region.delta = preloadedImage->data_region.delta; 1265 1266 status = elf_parse_dynamic_section(image); 1267 if (status != B_OK) 1268 goto error1; 1269 1270 status = init_image_version_infos(image); 1271 if (status != B_OK) 1272 goto error1; 1273 1274 if (!kernel) { 1275 status = check_needed_image_versions(image); 1276 if (status != B_OK) 1277 goto error1; 1278 1279 status = elf_relocate(image, sKernelImage); 1280 if (status != B_OK) 1281 goto error1; 1282 } else 1283 sKernelImage = image; 1284 1285 // copy debug symbols to the kernel heap 1286 if (preloadedImage->debug_symbols != NULL) { 1287 int32 debugSymbolsSize = sizeof(elf_sym) 1288 * preloadedImage->num_debug_symbols; 1289 image->debug_symbols = (elf_sym*)malloc(debugSymbolsSize); 1290 if (image->debug_symbols != NULL) { 1291 memcpy(image->debug_symbols, preloadedImage->debug_symbols, 1292 debugSymbolsSize); 1293 } 1294 } 1295 image->num_debug_symbols = preloadedImage->num_debug_symbols; 1296 1297 // copy debug string table to the kernel heap 1298 if (preloadedImage->debug_string_table != NULL) { 1299 image->debug_string_table = (char*)malloc( 1300 preloadedImage->debug_string_table_size); 1301 if (image->debug_string_table != NULL) { 1302 memcpy((void*)image->debug_string_table, 1303 preloadedImage->debug_string_table, 1304 preloadedImage->debug_string_table_size); 1305 } 1306 } 1307 1308 register_elf_image(image); 1309 preloadedImage->id = image->id; 1310 // modules_init() uses this information to get the preloaded images 1311 1312 // we now no longer need to write to the text area anymore 1313 set_area_protection(image->text_region.id, 1314 B_KERNEL_READ_AREA | B_KERNEL_EXECUTE_AREA); 1315 1316 return B_OK; 1317 1318 error1: 1319 delete_elf_image(image); 1320 1321 preloadedImage->id = -1; 1322 1323 return status; 1324 } 1325 1326 1327 // #pragma mark - userland symbol lookup 1328 1329 1330 class UserSymbolLookup { 1331 public: 1332 static UserSymbolLookup& Default() 1333 { 1334 return sLookup; 1335 } 1336 1337 status_t Init(Team* team) 1338 { 1339 // find the runtime loader debug area 1340 VMArea* area; 1341 for (VMAddressSpace::AreaIterator it 1342 = team->address_space->GetAreaIterator(); 1343 (area = it.Next()) != NULL;) { 1344 if (strcmp(area->name, RUNTIME_LOADER_DEBUG_AREA_NAME) == 0) 1345 break; 1346 } 1347 1348 if (area == NULL) 1349 return B_ERROR; 1350 1351 // copy the runtime loader data structure 1352 if (!_Read((runtime_loader_debug_area*)area->Base(), fDebugArea)) 1353 return B_BAD_ADDRESS; 1354 1355 fTeam = team; 1356 return B_OK; 1357 } 1358 1359 status_t LookupSymbolAddress(addr_t address, addr_t *_baseAddress, 1360 const char **_symbolName, const char **_imageName, bool *_exactMatch) 1361 { 1362 // Note, that this function doesn't find all symbols that we would like 1363 // to find. E.g. static functions do not appear in the symbol table 1364 // as function symbols, but as sections without name and size. The 1365 // .symtab section together with the .strtab section, which apparently 1366 // differ from the tables referred to by the .dynamic section, also 1367 // contain proper names and sizes for those symbols. Therefore, to get 1368 // completely satisfying results, we would need to read those tables 1369 // from the shared object. 1370 1371 // get the image for the address 1372 image_t image; 1373 status_t error = _FindImageAtAddress(address, image); 1374 if (error != B_OK) { 1375 // commpage requires special treatment since kernel stores symbol 1376 // information 1377 addr_t commPageAddress = (addr_t)fTeam->commpage_address; 1378 if (address >= commPageAddress 1379 && address < commPageAddress + COMMPAGE_SIZE) { 1380 if (*_imageName) 1381 *_imageName = "commpage"; 1382 address -= (addr_t)commPageAddress; 1383 error = elf_debug_lookup_symbol_address(address, _baseAddress, 1384 _symbolName, NULL, _exactMatch); 1385 if (_baseAddress) 1386 *_baseAddress += (addr_t)fTeam->commpage_address; 1387 } 1388 return error; 1389 } 1390 1391 strlcpy(fImageName, image.name, sizeof(fImageName)); 1392 1393 // symbol hash table size 1394 uint32 hashTabSize; 1395 if (!_Read(image.symhash, hashTabSize)) 1396 return B_BAD_ADDRESS; 1397 1398 // remote pointers to hash buckets and chains 1399 const uint32* hashBuckets = image.symhash + 2; 1400 const uint32* hashChains = image.symhash + 2 + hashTabSize; 1401 1402 const elf_region_t& textRegion = image.regions[0]; 1403 1404 // search the image for the symbol 1405 elf_sym symbolFound; 1406 addr_t deltaFound = INT_MAX; 1407 bool exactMatch = false; 1408 1409 // to get rid of the erroneous "uninitialized" warnings 1410 symbolFound.st_name = 0; 1411 symbolFound.st_value = 0; 1412 1413 for (uint32 i = 0; i < hashTabSize; i++) { 1414 uint32 bucket; 1415 if (!_Read(&hashBuckets[i], bucket)) 1416 return B_BAD_ADDRESS; 1417 1418 for (uint32 j = bucket; j != STN_UNDEF; 1419 _Read(&hashChains[j], j) ? 0 : j = STN_UNDEF) { 1420 1421 elf_sym symbol; 1422 if (!_Read(image.syms + j, symbol)) 1423 continue; 1424 1425 // The symbol table contains not only symbols referring to 1426 // functions and data symbols within the shared object, but also 1427 // referenced symbols of other shared objects, as well as 1428 // section and file references. We ignore everything but 1429 // function and data symbols that have an st_value != 0 (0 1430 // seems to be an indication for a symbol defined elsewhere 1431 // -- couldn't verify that in the specs though). 1432 if ((symbol.Type() != STT_FUNC && symbol.Type() != STT_OBJECT) 1433 || symbol.st_value == 0 1434 || symbol.st_value + symbol.st_size + textRegion.delta 1435 > textRegion.vmstart + textRegion.size) { 1436 continue; 1437 } 1438 1439 // skip symbols starting after the given address 1440 addr_t symbolAddress = symbol.st_value + textRegion.delta; 1441 if (symbolAddress > address) 1442 continue; 1443 addr_t symbolDelta = address - symbolAddress; 1444 1445 if (symbolDelta < deltaFound) { 1446 deltaFound = symbolDelta; 1447 symbolFound = symbol; 1448 1449 if (symbolDelta >= 0 && symbolDelta < symbol.st_size) { 1450 // exact match 1451 exactMatch = true; 1452 break; 1453 } 1454 } 1455 } 1456 } 1457 1458 if (_imageName) 1459 *_imageName = fImageName; 1460 1461 if (_symbolName) { 1462 *_symbolName = NULL; 1463 1464 if (deltaFound < INT_MAX) { 1465 if (_ReadString(image, symbolFound.st_name, fSymbolName, 1466 sizeof(fSymbolName))) { 1467 *_symbolName = fSymbolName; 1468 } else { 1469 // we can't get its name, so forget the symbol 1470 deltaFound = INT_MAX; 1471 } 1472 } 1473 } 1474 1475 if (_baseAddress) { 1476 if (deltaFound < INT_MAX) 1477 *_baseAddress = symbolFound.st_value + textRegion.delta; 1478 else 1479 *_baseAddress = textRegion.vmstart; 1480 } 1481 1482 if (_exactMatch) 1483 *_exactMatch = exactMatch; 1484 1485 return B_OK; 1486 } 1487 1488 status_t _FindImageAtAddress(addr_t address, image_t& image) 1489 { 1490 image_queue_t imageQueue; 1491 if (!_Read(fDebugArea.loaded_images, imageQueue)) 1492 return B_BAD_ADDRESS; 1493 1494 image_t* imageAddress = imageQueue.head; 1495 while (imageAddress != NULL) { 1496 if (!_Read(imageAddress, image)) 1497 return B_BAD_ADDRESS; 1498 1499 if (image.regions[0].vmstart <= address 1500 && address < image.regions[0].vmstart + image.regions[0].size) { 1501 return B_OK; 1502 } 1503 1504 imageAddress = image.next; 1505 } 1506 1507 return B_ENTRY_NOT_FOUND; 1508 } 1509 1510 bool _ReadString(const image_t& image, uint32 offset, char* buffer, 1511 size_t bufferSize) 1512 { 1513 const char* address = image.strtab + offset; 1514 1515 if (!IS_USER_ADDRESS(address)) 1516 return false; 1517 1518 if (debug_debugger_running()) { 1519 return debug_strlcpy(B_CURRENT_TEAM, buffer, address, bufferSize) 1520 >= 0; 1521 } 1522 return user_strlcpy(buffer, address, bufferSize) >= 0; 1523 } 1524 1525 template<typename T> bool _Read(const T* address, T& data); 1526 // gcc 2.95.3 doesn't like it defined in-place 1527 1528 private: 1529 Team* fTeam; 1530 runtime_loader_debug_area fDebugArea; 1531 char fImageName[B_OS_NAME_LENGTH]; 1532 char fSymbolName[256]; 1533 static UserSymbolLookup sLookup; 1534 }; 1535 1536 1537 template<typename T> 1538 bool 1539 UserSymbolLookup::_Read(const T* address, T& data) 1540 { 1541 if (!IS_USER_ADDRESS(address)) 1542 return false; 1543 1544 if (debug_debugger_running()) 1545 return debug_memcpy(B_CURRENT_TEAM, &data, address, sizeof(T)) == B_OK; 1546 return user_memcpy(&data, address, sizeof(T)) == B_OK; 1547 } 1548 1549 1550 UserSymbolLookup UserSymbolLookup::sLookup; 1551 // doesn't need construction, but has an Init() method 1552 1553 1554 // #pragma mark - public kernel API 1555 1556 1557 status_t 1558 get_image_symbol(image_id id, const char *name, int32 symbolClass, 1559 void **_symbol) 1560 { 1561 struct elf_image_info *image; 1562 elf_sym *symbol; 1563 status_t status = B_OK; 1564 1565 TRACE(("get_image_symbol(%s)\n", name)); 1566 1567 mutex_lock(&sImageMutex); 1568 1569 image = find_image(id); 1570 if (image == NULL) { 1571 status = B_BAD_IMAGE_ID; 1572 goto done; 1573 } 1574 1575 symbol = elf_find_symbol(image, name, NULL, true); 1576 if (symbol == NULL || symbol->st_shndx == SHN_UNDEF) { 1577 status = B_ENTRY_NOT_FOUND; 1578 goto done; 1579 } 1580 1581 // TODO: support the "symbolClass" parameter! 1582 1583 TRACE(("found: %lx (%lx + %lx)\n", 1584 symbol->st_value + image->text_region.delta, 1585 symbol->st_value, image->text_region.delta)); 1586 1587 *_symbol = (void *)(symbol->st_value + image->text_region.delta); 1588 1589 done: 1590 mutex_unlock(&sImageMutex); 1591 return status; 1592 } 1593 1594 1595 // #pragma mark - kernel private API 1596 1597 1598 /*! Looks up a symbol by address in all images loaded in kernel space. 1599 Note, if you need to call this function outside a debugger, make 1600 sure you fix locking and the way it returns its information, first! 1601 */ 1602 status_t 1603 elf_debug_lookup_symbol_address(addr_t address, addr_t *_baseAddress, 1604 const char **_symbolName, const char **_imageName, bool *_exactMatch) 1605 { 1606 struct elf_image_info *image; 1607 elf_sym *symbolFound = NULL; 1608 const char *symbolName = NULL; 1609 addr_t deltaFound = INT_MAX; 1610 bool exactMatch = false; 1611 status_t status; 1612 1613 TRACE(("looking up %p\n", (void *)address)); 1614 1615 if (!sInitialized) 1616 return B_ERROR; 1617 1618 //mutex_lock(&sImageMutex); 1619 1620 image = find_image_at_address(address); 1621 // get image that may contain the address 1622 1623 if (image != NULL) { 1624 addr_t symbolDelta; 1625 uint32 i; 1626 int32 j; 1627 1628 TRACE((" image %p, base = %p, size = %p\n", image, 1629 (void *)image->text_region.start, (void *)image->text_region.size)); 1630 1631 if (image->debug_symbols != NULL) { 1632 // search extended debug symbol table (contains static symbols) 1633 1634 TRACE((" searching debug symbols...\n")); 1635 1636 for (i = 0; i < image->num_debug_symbols; i++) { 1637 elf_sym *symbol = &image->debug_symbols[i]; 1638 1639 if (symbol->st_value == 0 || symbol->st_size 1640 >= image->text_region.size + image->data_region.size) 1641 continue; 1642 1643 symbolDelta 1644 = address - (symbol->st_value + image->text_region.delta); 1645 if (symbolDelta >= 0 && symbolDelta < symbol->st_size) 1646 exactMatch = true; 1647 1648 if (exactMatch || symbolDelta < deltaFound) { 1649 deltaFound = symbolDelta; 1650 symbolFound = symbol; 1651 symbolName = image->debug_string_table + symbol->st_name; 1652 1653 if (exactMatch) 1654 break; 1655 } 1656 } 1657 } else { 1658 // search standard symbol lookup table 1659 1660 TRACE((" searching standard symbols...\n")); 1661 1662 for (i = 0; i < HASHTABSIZE(image); i++) { 1663 for (j = HASHBUCKETS(image)[i]; j != STN_UNDEF; 1664 j = HASHCHAINS(image)[j]) { 1665 elf_sym *symbol = &image->syms[j]; 1666 1667 if (symbol->st_value == 0 1668 || symbol->st_size >= image->text_region.size 1669 + image->data_region.size) 1670 continue; 1671 1672 symbolDelta = address - (long)(symbol->st_value 1673 + image->text_region.delta); 1674 if (symbolDelta >= 0 && symbolDelta < symbol->st_size) 1675 exactMatch = true; 1676 1677 if (exactMatch || symbolDelta < deltaFound) { 1678 deltaFound = symbolDelta; 1679 symbolFound = symbol; 1680 symbolName = SYMNAME(image, symbol); 1681 1682 if (exactMatch) 1683 goto symbol_found; 1684 } 1685 } 1686 } 1687 } 1688 } 1689 symbol_found: 1690 1691 if (symbolFound != NULL) { 1692 if (_symbolName) 1693 *_symbolName = symbolName; 1694 if (_imageName) 1695 *_imageName = image->name; 1696 if (_baseAddress) 1697 *_baseAddress = symbolFound->st_value + image->text_region.delta; 1698 if (_exactMatch) 1699 *_exactMatch = exactMatch; 1700 1701 status = B_OK; 1702 } else if (image != NULL) { 1703 TRACE(("symbol not found!\n")); 1704 1705 if (_symbolName) 1706 *_symbolName = NULL; 1707 if (_imageName) 1708 *_imageName = image->name; 1709 if (_baseAddress) 1710 *_baseAddress = image->text_region.start; 1711 if (_exactMatch) 1712 *_exactMatch = false; 1713 1714 status = B_OK; 1715 } else { 1716 TRACE(("image not found!\n")); 1717 status = B_ENTRY_NOT_FOUND; 1718 } 1719 1720 // Note, theoretically, all information we return back to our caller 1721 // would have to be locked - but since this function is only called 1722 // from the debugger, it's safe to do it this way 1723 1724 //mutex_unlock(&sImageMutex); 1725 1726 return status; 1727 } 1728 1729 1730 /*! Tries to find a matching user symbol for the given address. 1731 Note that the given team's address space must already be in effect. 1732 */ 1733 status_t 1734 elf_debug_lookup_user_symbol_address(Team* team, addr_t address, 1735 addr_t *_baseAddress, const char **_symbolName, const char **_imageName, 1736 bool *_exactMatch) 1737 { 1738 if (team == NULL || team == team_get_kernel_team()) 1739 return B_BAD_VALUE; 1740 1741 UserSymbolLookup& lookup = UserSymbolLookup::Default(); 1742 status_t error = lookup.Init(team); 1743 if (error != B_OK) 1744 return error; 1745 1746 return lookup.LookupSymbolAddress(address, _baseAddress, _symbolName, 1747 _imageName, _exactMatch); 1748 } 1749 1750 1751 /*! Looks up a symbol in all kernel images. Note, this function is thought to 1752 be used in the kernel debugger, and therefore doesn't perform any locking. 1753 */ 1754 addr_t 1755 elf_debug_lookup_symbol(const char* searchName) 1756 { 1757 struct elf_image_info *image = NULL; 1758 1759 ImageHash::Iterator iterator(sImagesHash); 1760 while (iterator.HasNext()) { 1761 image = iterator.Next(); 1762 if (image->num_debug_symbols > 0) { 1763 // search extended debug symbol table (contains static symbols) 1764 for (uint32 i = 0; i < image->num_debug_symbols; i++) { 1765 elf_sym *symbol = &image->debug_symbols[i]; 1766 const char *name = image->debug_string_table + symbol->st_name; 1767 1768 if (symbol->st_value > 0 && !strcmp(name, searchName)) 1769 return symbol->st_value + image->text_region.delta; 1770 } 1771 } else { 1772 // search standard symbol lookup table 1773 for (uint32 i = 0; i < HASHTABSIZE(image); i++) { 1774 for (uint32 j = HASHBUCKETS(image)[i]; j != STN_UNDEF; 1775 j = HASHCHAINS(image)[j]) { 1776 elf_sym *symbol = &image->syms[j]; 1777 const char *name = SYMNAME(image, symbol); 1778 1779 if (symbol->st_value > 0 && !strcmp(name, searchName)) 1780 return symbol->st_value + image->text_region.delta; 1781 } 1782 } 1783 } 1784 } 1785 1786 return 0; 1787 } 1788 1789 1790 status_t 1791 elf_lookup_kernel_symbol(const char* name, elf_symbol_info* info) 1792 { 1793 // find the symbol 1794 elf_sym* foundSymbol = elf_find_symbol(sKernelImage, name, NULL, false); 1795 if (foundSymbol == NULL) 1796 return B_MISSING_SYMBOL; 1797 1798 info->address = foundSymbol->st_value + sKernelImage->text_region.delta; 1799 info->size = foundSymbol->st_size; 1800 return B_OK; 1801 } 1802 1803 1804 status_t 1805 elf_load_user_image(const char *path, Team *team, int flags, addr_t *entry) 1806 { 1807 elf_ehdr elfHeader; 1808 elf_phdr *programHeaders = NULL; 1809 char baseName[B_OS_NAME_LENGTH]; 1810 status_t status; 1811 ssize_t length; 1812 int fd; 1813 int i; 1814 addr_t delta = 0; 1815 uint32 addressSpec = B_RANDOMIZED_BASE_ADDRESS; 1816 area_id* mappedAreas = NULL; 1817 1818 TRACE(("elf_load: entry path '%s', team %p\n", path, team)); 1819 1820 fd = _kern_open(-1, path, O_RDONLY, 0); 1821 if (fd < 0) 1822 return fd; 1823 1824 struct stat st; 1825 status = _kern_read_stat(fd, NULL, false, &st, sizeof(st)); 1826 if (status != B_OK) 1827 return status; 1828 1829 // read and verify the ELF header 1830 1831 length = _kern_read(fd, 0, &elfHeader, sizeof(elfHeader)); 1832 if (length < B_OK) { 1833 status = length; 1834 goto error; 1835 } 1836 1837 if (length != sizeof(elfHeader)) { 1838 // short read 1839 status = B_NOT_AN_EXECUTABLE; 1840 goto error; 1841 } 1842 status = verify_eheader(&elfHeader); 1843 if (status < B_OK) 1844 goto error; 1845 1846 struct elf_image_info* image; 1847 image = create_image_struct(); 1848 if (image == NULL) { 1849 status = B_NO_MEMORY; 1850 goto error; 1851 } 1852 image->elf_header = &elfHeader; 1853 1854 // read program header 1855 1856 programHeaders = (elf_phdr *)malloc( 1857 elfHeader.e_phnum * elfHeader.e_phentsize); 1858 if (programHeaders == NULL) { 1859 dprintf("error allocating space for program headers\n"); 1860 status = B_NO_MEMORY; 1861 goto error2; 1862 } 1863 1864 TRACE(("reading in program headers at 0x%lx, length 0x%x\n", 1865 elfHeader.e_phoff, elfHeader.e_phnum * elfHeader.e_phentsize)); 1866 length = _kern_read(fd, elfHeader.e_phoff, programHeaders, 1867 elfHeader.e_phnum * elfHeader.e_phentsize); 1868 if (length < B_OK) { 1869 status = length; 1870 dprintf("error reading in program headers\n"); 1871 goto error2; 1872 } 1873 if (length != elfHeader.e_phnum * elfHeader.e_phentsize) { 1874 dprintf("short read while reading in program headers\n"); 1875 status = -1; 1876 goto error2; 1877 } 1878 1879 // construct a nice name for the region we have to create below 1880 { 1881 int32 length; 1882 1883 const char *leaf = strrchr(path, '/'); 1884 if (leaf == NULL) 1885 leaf = path; 1886 else 1887 leaf++; 1888 1889 length = strlen(leaf); 1890 if (length > B_OS_NAME_LENGTH - 8) 1891 sprintf(baseName, "...%s", leaf + length + 8 - B_OS_NAME_LENGTH); 1892 else 1893 strcpy(baseName, leaf); 1894 } 1895 1896 // map the program's segments into memory, initially with rw access 1897 // correct area protection will be set after relocation 1898 1899 mappedAreas = (area_id*)malloc(sizeof(area_id) * elfHeader.e_phnum); 1900 if (mappedAreas == NULL) { 1901 status = B_NO_MEMORY; 1902 goto error2; 1903 } 1904 1905 image_info imageInfo; 1906 memset(&imageInfo, 0, sizeof(image_info)); 1907 1908 for (i = 0; i < elfHeader.e_phnum; i++) { 1909 char regionName[B_OS_NAME_LENGTH]; 1910 char *regionAddress; 1911 char *originalRegionAddress; 1912 area_id id; 1913 1914 mappedAreas[i] = -1; 1915 1916 if (programHeaders[i].p_type == PT_DYNAMIC) { 1917 image->dynamic_section = programHeaders[i].p_vaddr; 1918 continue; 1919 } 1920 1921 if (programHeaders[i].p_type != PT_LOAD) 1922 continue; 1923 1924 regionAddress = (char *)(ROUNDDOWN(programHeaders[i].p_vaddr, 1925 B_PAGE_SIZE) + delta); 1926 originalRegionAddress = regionAddress; 1927 1928 if (programHeaders[i].p_flags & PF_WRITE) { 1929 // rw/data segment 1930 size_t memUpperBound = (programHeaders[i].p_vaddr % B_PAGE_SIZE) 1931 + programHeaders[i].p_memsz; 1932 size_t fileUpperBound = (programHeaders[i].p_vaddr % B_PAGE_SIZE) 1933 + programHeaders[i].p_filesz; 1934 1935 memUpperBound = ROUNDUP(memUpperBound, B_PAGE_SIZE); 1936 fileUpperBound = ROUNDUP(fileUpperBound, B_PAGE_SIZE); 1937 1938 sprintf(regionName, "%s_seg%drw", baseName, i); 1939 1940 id = vm_map_file(team->id, regionName, (void **)®ionAddress, 1941 addressSpec, fileUpperBound, 1942 B_READ_AREA | B_WRITE_AREA, REGION_PRIVATE_MAP, false, 1943 fd, ROUNDDOWN(programHeaders[i].p_offset, B_PAGE_SIZE)); 1944 if (id < B_OK) { 1945 dprintf("error mapping file data: %s!\n", strerror(id)); 1946 status = B_NOT_AN_EXECUTABLE; 1947 goto error2; 1948 } 1949 mappedAreas[i] = id; 1950 1951 imageInfo.data = regionAddress; 1952 imageInfo.data_size = memUpperBound; 1953 1954 image->data_region.start = (addr_t)regionAddress; 1955 image->data_region.size = memUpperBound; 1956 1957 // clean garbage brought by mmap (the region behind the file, 1958 // at least parts of it are the bss and have to be zeroed) 1959 addr_t start = (addr_t)regionAddress 1960 + (programHeaders[i].p_vaddr % B_PAGE_SIZE) 1961 + programHeaders[i].p_filesz; 1962 size_t amount = fileUpperBound 1963 - (programHeaders[i].p_vaddr % B_PAGE_SIZE) 1964 - (programHeaders[i].p_filesz); 1965 memset((void *)start, 0, amount); 1966 1967 // Check if we need extra storage for the bss - we have to do this if 1968 // the above region doesn't already comprise the memory size, too. 1969 1970 if (memUpperBound != fileUpperBound) { 1971 size_t bssSize = memUpperBound - fileUpperBound; 1972 1973 snprintf(regionName, B_OS_NAME_LENGTH, "%s_bss%d", baseName, i); 1974 1975 regionAddress += fileUpperBound; 1976 virtual_address_restrictions virtualRestrictions = {}; 1977 virtualRestrictions.address = regionAddress; 1978 virtualRestrictions.address_specification = B_EXACT_ADDRESS; 1979 physical_address_restrictions physicalRestrictions = {}; 1980 id = create_area_etc(team->id, regionName, bssSize, B_NO_LOCK, 1981 B_READ_AREA | B_WRITE_AREA, 0, 0, &virtualRestrictions, 1982 &physicalRestrictions, (void**)®ionAddress); 1983 if (id < B_OK) { 1984 dprintf("error allocating bss area: %s!\n", strerror(id)); 1985 status = B_NOT_AN_EXECUTABLE; 1986 goto error2; 1987 } 1988 } 1989 } else { 1990 // assume ro/text segment 1991 snprintf(regionName, B_OS_NAME_LENGTH, "%s_seg%dro", baseName, i); 1992 1993 size_t segmentSize = ROUNDUP(programHeaders[i].p_memsz 1994 + (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE); 1995 1996 id = vm_map_file(team->id, regionName, (void **)®ionAddress, 1997 addressSpec, segmentSize, 1998 B_READ_AREA | B_WRITE_AREA, REGION_PRIVATE_MAP, false, fd, 1999 ROUNDDOWN(programHeaders[i].p_offset, B_PAGE_SIZE)); 2000 if (id < B_OK) { 2001 dprintf("error mapping file text: %s!\n", strerror(id)); 2002 status = B_NOT_AN_EXECUTABLE; 2003 goto error2; 2004 } 2005 2006 mappedAreas[i] = id; 2007 2008 imageInfo.text = regionAddress; 2009 imageInfo.text_size = segmentSize; 2010 2011 image->text_region.start = (addr_t)regionAddress; 2012 image->text_region.size = segmentSize; 2013 } 2014 2015 if (addressSpec != B_EXACT_ADDRESS) { 2016 addressSpec = B_EXACT_ADDRESS; 2017 delta = regionAddress - originalRegionAddress; 2018 } 2019 } 2020 2021 image->data_region.delta = delta; 2022 image->text_region.delta = delta; 2023 2024 // modify the dynamic ptr by the delta of the regions 2025 image->dynamic_section += image->text_region.delta; 2026 2027 status = elf_parse_dynamic_section(image); 2028 if (status != B_OK) 2029 goto error2; 2030 2031 status = elf_relocate(image, image); 2032 if (status != B_OK) 2033 goto error2; 2034 2035 // set correct area protection 2036 for (i = 0; i < elfHeader.e_phnum; i++) { 2037 if (mappedAreas[i] == -1) 2038 continue; 2039 2040 uint32 protection = 0; 2041 2042 if (programHeaders[i].p_flags & PF_EXECUTE) 2043 protection |= B_EXECUTE_AREA; 2044 if (programHeaders[i].p_flags & PF_WRITE) 2045 protection |= B_WRITE_AREA; 2046 if (programHeaders[i].p_flags & PF_READ) 2047 protection |= B_READ_AREA; 2048 2049 status = vm_set_area_protection(team->id, mappedAreas[i], protection, 2050 true); 2051 if (status != B_OK) 2052 goto error2; 2053 } 2054 2055 // register the loaded image 2056 imageInfo.type = B_LIBRARY_IMAGE; 2057 imageInfo.device = st.st_dev; 2058 imageInfo.node = st.st_ino; 2059 strlcpy(imageInfo.name, path, sizeof(imageInfo.name)); 2060 2061 imageInfo.api_version = B_HAIKU_VERSION; 2062 imageInfo.abi = B_HAIKU_ABI; 2063 // TODO: Get the actual values for the shared object. Currently only 2064 // the runtime loader is loaded, so this is good enough for the time 2065 // being. 2066 2067 imageInfo.id = register_image(team, &imageInfo, sizeof(image_info)); 2068 if (imageInfo.id >= 0 && team_get_current_team_id() == team->id) 2069 user_debug_image_created(&imageInfo); 2070 // Don't care, if registering fails. It's not crucial. 2071 2072 TRACE(("elf_load: done!\n")); 2073 2074 *entry = elfHeader.e_entry + delta; 2075 status = B_OK; 2076 2077 error2: 2078 free(mappedAreas); 2079 2080 image->elf_header = NULL; 2081 delete_elf_image(image); 2082 2083 error: 2084 free(programHeaders); 2085 _kern_close(fd); 2086 2087 return status; 2088 } 2089 2090 2091 image_id 2092 load_kernel_add_on(const char *path) 2093 { 2094 elf_phdr *programHeaders; 2095 elf_ehdr *elfHeader; 2096 struct elf_image_info *image; 2097 const char *fileName; 2098 void *reservedAddress; 2099 size_t reservedSize; 2100 status_t status; 2101 ssize_t length; 2102 bool textSectionWritable = false; 2103 int executableHeaderCount = 0; 2104 2105 TRACE(("elf_load_kspace: entry path '%s'\n", path)); 2106 2107 int fd = _kern_open(-1, path, O_RDONLY, 0); 2108 if (fd < 0) 2109 return fd; 2110 2111 struct vnode *vnode; 2112 status = vfs_get_vnode_from_fd(fd, true, &vnode); 2113 if (status < B_OK) 2114 goto error0; 2115 2116 // get the file name 2117 fileName = strrchr(path, '/'); 2118 if (fileName == NULL) 2119 fileName = path; 2120 else 2121 fileName++; 2122 2123 // Prevent someone else from trying to load this image 2124 mutex_lock(&sImageLoadMutex); 2125 2126 // make sure it's not loaded already. Search by vnode 2127 image = find_image_by_vnode(vnode); 2128 if (image) { 2129 atomic_add(&image->ref_count, 1); 2130 goto done; 2131 } 2132 2133 elfHeader = (elf_ehdr *)malloc(sizeof(*elfHeader)); 2134 if (!elfHeader) { 2135 status = B_NO_MEMORY; 2136 goto error; 2137 } 2138 2139 length = _kern_read(fd, 0, elfHeader, sizeof(*elfHeader)); 2140 if (length < B_OK) { 2141 status = length; 2142 goto error1; 2143 } 2144 if (length != sizeof(*elfHeader)) { 2145 // short read 2146 status = B_NOT_AN_EXECUTABLE; 2147 goto error1; 2148 } 2149 status = verify_eheader(elfHeader); 2150 if (status < B_OK) 2151 goto error1; 2152 2153 image = create_image_struct(); 2154 if (!image) { 2155 status = B_NO_MEMORY; 2156 goto error1; 2157 } 2158 image->vnode = vnode; 2159 image->elf_header = elfHeader; 2160 image->name = strdup(path); 2161 vnode = NULL; 2162 2163 programHeaders = (elf_phdr *)malloc(elfHeader->e_phnum 2164 * elfHeader->e_phentsize); 2165 if (programHeaders == NULL) { 2166 dprintf("%s: error allocating space for program headers\n", fileName); 2167 status = B_NO_MEMORY; 2168 goto error2; 2169 } 2170 2171 TRACE(("reading in program headers at 0x%lx, length 0x%x\n", 2172 elfHeader->e_phoff, elfHeader->e_phnum * elfHeader->e_phentsize)); 2173 2174 length = _kern_read(fd, elfHeader->e_phoff, programHeaders, 2175 elfHeader->e_phnum * elfHeader->e_phentsize); 2176 if (length < B_OK) { 2177 status = length; 2178 TRACE(("%s: error reading in program headers\n", fileName)); 2179 goto error3; 2180 } 2181 if (length != elfHeader->e_phnum * elfHeader->e_phentsize) { 2182 TRACE(("%s: short read while reading in program headers\n", fileName)); 2183 status = B_ERROR; 2184 goto error3; 2185 } 2186 2187 // determine how much space we need for all loaded segments 2188 2189 reservedSize = 0; 2190 length = 0; 2191 2192 for (int32 i = 0; i < elfHeader->e_phnum; i++) { 2193 size_t end; 2194 2195 if (programHeaders[i].p_type != PT_LOAD) 2196 continue; 2197 2198 length += ROUNDUP(programHeaders[i].p_memsz 2199 + (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE); 2200 2201 end = ROUNDUP(programHeaders[i].p_memsz + programHeaders[i].p_vaddr, 2202 B_PAGE_SIZE); 2203 if (end > reservedSize) 2204 reservedSize = end; 2205 2206 if (programHeaders[i].IsExecutable()) 2207 executableHeaderCount++; 2208 } 2209 2210 // Check whether the segments have an unreasonable amount of unused space 2211 // inbetween. 2212 if ((ssize_t)reservedSize > length + 8 * 1024) { 2213 status = B_BAD_DATA; 2214 goto error1; 2215 } 2216 2217 // reserve that space and allocate the areas from that one 2218 if (vm_reserve_address_range(VMAddressSpace::KernelID(), &reservedAddress, 2219 B_ANY_KERNEL_ADDRESS, reservedSize, 0) < B_OK) { 2220 status = B_NO_MEMORY; 2221 goto error3; 2222 } 2223 2224 image->data_region.size = 0; 2225 image->text_region.size = 0; 2226 2227 for (int32 i = 0; i < elfHeader->e_phnum; i++) { 2228 char regionName[B_OS_NAME_LENGTH]; 2229 elf_region *region; 2230 2231 TRACE(("looking at program header %" B_PRId32 "\n", i)); 2232 2233 switch (programHeaders[i].p_type) { 2234 case PT_LOAD: 2235 break; 2236 case PT_DYNAMIC: 2237 image->dynamic_section = programHeaders[i].p_vaddr; 2238 continue; 2239 case PT_INTERP: 2240 // should check here for appropriate interpreter 2241 continue; 2242 case PT_PHDR: 2243 // we don't use it 2244 continue; 2245 default: 2246 dprintf("%s: unhandled pheader type %#" B_PRIx32 "\n", fileName, 2247 programHeaders[i].p_type); 2248 continue; 2249 } 2250 2251 // we're here, so it must be a PT_LOAD segment 2252 2253 // Usually add-ons have two PT_LOAD headers: one for .data one or .text. 2254 // x86 and PPC may differ in permission bits for .data's PT_LOAD header 2255 // x86 is usually RW, PPC is RWE 2256 2257 // Some add-ons may have .text and .data concatenated in a single 2258 // PT_LOAD RWE header and we must map that to .text. 2259 if (programHeaders[i].IsReadWrite() 2260 && (!programHeaders[i].IsExecutable() 2261 || executableHeaderCount > 1)) { 2262 // this is the writable segment 2263 if (image->data_region.size != 0) { 2264 // we've already created this segment 2265 continue; 2266 } 2267 region = &image->data_region; 2268 2269 snprintf(regionName, B_OS_NAME_LENGTH, "%s_data", fileName); 2270 } else if (programHeaders[i].IsExecutable()) { 2271 // this is the non-writable segment 2272 if (image->text_region.size != 0) { 2273 // we've already created this segment 2274 continue; 2275 } 2276 region = &image->text_region; 2277 2278 // some programs may have .text and .data concatenated in a 2279 // single PT_LOAD section which is readable/writable/executable 2280 textSectionWritable = programHeaders[i].IsReadWrite(); 2281 snprintf(regionName, B_OS_NAME_LENGTH, "%s_text", fileName); 2282 } else { 2283 dprintf("%s: weird program header flags %#" B_PRIx32 "\n", fileName, 2284 programHeaders[i].p_flags); 2285 continue; 2286 } 2287 2288 region->start = (addr_t)reservedAddress + ROUNDDOWN( 2289 programHeaders[i].p_vaddr, B_PAGE_SIZE); 2290 region->size = ROUNDUP(programHeaders[i].p_memsz 2291 + (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE); 2292 region->id = create_area(regionName, (void **)®ion->start, 2293 B_EXACT_ADDRESS, region->size, B_FULL_LOCK, 2294 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); 2295 if (region->id < B_OK) { 2296 dprintf("%s: error allocating area: %s\n", fileName, 2297 strerror(region->id)); 2298 status = B_NOT_AN_EXECUTABLE; 2299 goto error4; 2300 } 2301 region->delta = -ROUNDDOWN(programHeaders[i].p_vaddr, B_PAGE_SIZE); 2302 2303 TRACE(("elf_load_kspace: created area \"%s\" at %p\n", 2304 regionName, (void *)region->start)); 2305 2306 length = _kern_read(fd, programHeaders[i].p_offset, 2307 (void *)(region->start + (programHeaders[i].p_vaddr % B_PAGE_SIZE)), 2308 programHeaders[i].p_filesz); 2309 if (length < B_OK) { 2310 status = length; 2311 dprintf("%s: error reading in segment %" B_PRId32 "\n", fileName, 2312 i); 2313 goto error5; 2314 } 2315 } 2316 2317 image->data_region.delta += image->data_region.start; 2318 image->text_region.delta += image->text_region.start; 2319 2320 // modify the dynamic ptr by the delta of the regions 2321 image->dynamic_section += image->text_region.delta; 2322 2323 status = elf_parse_dynamic_section(image); 2324 if (status < B_OK) 2325 goto error5; 2326 2327 status = init_image_version_infos(image); 2328 if (status != B_OK) 2329 goto error5; 2330 2331 status = check_needed_image_versions(image); 2332 if (status != B_OK) 2333 goto error5; 2334 2335 status = elf_relocate(image, sKernelImage); 2336 if (status < B_OK) 2337 goto error5; 2338 2339 // We needed to read in the contents of the "text" area, but 2340 // now we can protect it read-only/execute, unless this is a 2341 // special image with concatenated .text and .data, when it 2342 // will also need write access. 2343 set_area_protection(image->text_region.id, 2344 B_KERNEL_READ_AREA | B_KERNEL_EXECUTE_AREA 2345 | (textSectionWritable ? B_KERNEL_WRITE_AREA : 0)); 2346 2347 // There might be a hole between the two segments, and we don't need to 2348 // reserve this any longer 2349 vm_unreserve_address_range(VMAddressSpace::KernelID(), reservedAddress, 2350 reservedSize); 2351 2352 // ToDo: this should be enabled by kernel settings! 2353 if (1) 2354 load_elf_symbol_table(fd, image); 2355 2356 free(programHeaders); 2357 mutex_lock(&sImageMutex); 2358 register_elf_image(image); 2359 mutex_unlock(&sImageMutex); 2360 2361 done: 2362 _kern_close(fd); 2363 mutex_unlock(&sImageLoadMutex); 2364 2365 return image->id; 2366 2367 error5: 2368 error4: 2369 vm_unreserve_address_range(VMAddressSpace::KernelID(), reservedAddress, 2370 reservedSize); 2371 error3: 2372 free(programHeaders); 2373 error2: 2374 delete_elf_image(image); 2375 elfHeader = NULL; 2376 error1: 2377 free(elfHeader); 2378 error: 2379 mutex_unlock(&sImageLoadMutex); 2380 error0: 2381 dprintf("Could not load kernel add-on \"%s\": %s\n", path, 2382 strerror(status)); 2383 2384 if (vnode) 2385 vfs_put_vnode(vnode); 2386 _kern_close(fd); 2387 2388 return status; 2389 } 2390 2391 2392 status_t 2393 unload_kernel_add_on(image_id id) 2394 { 2395 MutexLocker _(sImageLoadMutex); 2396 MutexLocker _2(sImageMutex); 2397 2398 elf_image_info *image = find_image(id); 2399 if (image == NULL) 2400 return B_BAD_IMAGE_ID; 2401 2402 unload_elf_image(image); 2403 return B_OK; 2404 } 2405 2406 2407 struct elf_image_info* 2408 elf_get_kernel_image() 2409 { 2410 return sKernelImage; 2411 } 2412 2413 2414 status_t 2415 elf_get_image_info_for_address(addr_t address, image_info* info) 2416 { 2417 MutexLocker _(sImageMutex); 2418 struct elf_image_info* elfInfo = find_image_at_address(address); 2419 if (elfInfo == NULL) 2420 return B_ENTRY_NOT_FOUND; 2421 2422 info->id = elfInfo->id; 2423 info->type = B_SYSTEM_IMAGE; 2424 info->sequence = 0; 2425 info->init_order = 0; 2426 info->init_routine = NULL; 2427 info->term_routine = NULL; 2428 info->device = -1; 2429 info->node = -1; 2430 // TODO: We could actually fill device/node in. 2431 strlcpy(info->name, elfInfo->name, sizeof(info->name)); 2432 info->text = (void*)elfInfo->text_region.start; 2433 info->data = (void*)elfInfo->data_region.start; 2434 info->text_size = elfInfo->text_region.size; 2435 info->data_size = elfInfo->data_region.size; 2436 2437 return B_OK; 2438 } 2439 2440 2441 image_id 2442 elf_create_memory_image(const char* imageName, addr_t text, size_t textSize, 2443 addr_t data, size_t dataSize) 2444 { 2445 // allocate the image 2446 elf_image_info* image = create_image_struct(); 2447 if (image == NULL) 2448 return B_NO_MEMORY; 2449 MemoryDeleter imageDeleter(image); 2450 2451 // allocate symbol and string tables -- we allocate an empty symbol table, 2452 // so that elf_debug_lookup_symbol_address() won't try the dynamic symbol 2453 // table, which we don't have. 2454 elf_sym* symbolTable = (elf_sym*)malloc(0); 2455 char* stringTable = (char*)malloc(1); 2456 MemoryDeleter symbolTableDeleter(symbolTable); 2457 MemoryDeleter stringTableDeleter(stringTable); 2458 if (symbolTable == NULL || stringTable == NULL) 2459 return B_NO_MEMORY; 2460 2461 // the string table always contains the empty string 2462 stringTable[0] = '\0'; 2463 2464 image->debug_symbols = symbolTable; 2465 image->num_debug_symbols = 0; 2466 image->debug_string_table = stringTable; 2467 2468 // dup image name 2469 image->name = strdup(imageName); 2470 if (image->name == NULL) 2471 return B_NO_MEMORY; 2472 2473 // data and text region 2474 image->text_region.id = -1; 2475 image->text_region.start = text; 2476 image->text_region.size = textSize; 2477 image->text_region.delta = 0; 2478 2479 image->data_region.id = -1; 2480 image->data_region.start = data; 2481 image->data_region.size = dataSize; 2482 image->data_region.delta = 0; 2483 2484 mutex_lock(&sImageMutex); 2485 register_elf_image(image); 2486 image_id imageID = image->id; 2487 mutex_unlock(&sImageMutex); 2488 2489 // keep the allocated memory 2490 imageDeleter.Detach(); 2491 symbolTableDeleter.Detach(); 2492 stringTableDeleter.Detach(); 2493 2494 return imageID; 2495 } 2496 2497 2498 status_t 2499 elf_add_memory_image_symbol(image_id id, const char* name, addr_t address, 2500 size_t size, int32 type) 2501 { 2502 MutexLocker _(sImageMutex); 2503 2504 // get the image 2505 struct elf_image_info* image = find_image(id); 2506 if (image == NULL) 2507 return B_ENTRY_NOT_FOUND; 2508 2509 // get the current string table size 2510 size_t stringTableSize = 1; 2511 if (image->num_debug_symbols > 0) { 2512 for (int32 i = image->num_debug_symbols - 1; i >= 0; i--) { 2513 int32 nameIndex = image->debug_symbols[i].st_name; 2514 if (nameIndex != 0) { 2515 stringTableSize = nameIndex 2516 + strlen(image->debug_string_table + nameIndex) + 1; 2517 break; 2518 } 2519 } 2520 } 2521 2522 // enter the name in the string table 2523 char* stringTable = (char*)image->debug_string_table; 2524 size_t stringIndex = 0; 2525 if (name != NULL) { 2526 size_t nameSize = strlen(name) + 1; 2527 stringIndex = stringTableSize; 2528 stringTableSize += nameSize; 2529 stringTable = (char*)realloc((char*)image->debug_string_table, 2530 stringTableSize); 2531 if (stringTable == NULL) 2532 return B_NO_MEMORY; 2533 image->debug_string_table = stringTable; 2534 memcpy(stringTable + stringIndex, name, nameSize); 2535 } 2536 2537 // resize the symbol table 2538 int32 symbolCount = image->num_debug_symbols + 1; 2539 elf_sym* symbolTable = (elf_sym*)realloc( 2540 (elf_sym*)image->debug_symbols, sizeof(elf_sym) * symbolCount); 2541 if (symbolTable == NULL) 2542 return B_NO_MEMORY; 2543 image->debug_symbols = symbolTable; 2544 2545 // enter the symbol 2546 elf_sym& symbol = symbolTable[symbolCount - 1]; 2547 symbol.SetInfo(STB_GLOBAL, 2548 type == B_SYMBOL_TYPE_DATA ? STT_OBJECT : STT_FUNC); 2549 symbol.st_name = stringIndex; 2550 symbol.st_value = address; 2551 symbol.st_size = size; 2552 symbol.st_other = 0; 2553 symbol.st_shndx = 0; 2554 image->num_debug_symbols++; 2555 2556 return B_OK; 2557 } 2558 2559 2560 status_t 2561 elf_init(kernel_args *args) 2562 { 2563 struct preloaded_image *image; 2564 2565 image_init(); 2566 2567 sImagesHash = new(std::nothrow) ImageHash(); 2568 if (sImagesHash == NULL) 2569 return B_NO_MEMORY; 2570 status_t init = sImagesHash->Init(IMAGE_HASH_SIZE); 2571 if (init != B_OK) 2572 return init; 2573 2574 // Build a image structure for the kernel, which has already been loaded. 2575 // The preloaded_images were already prepared by the VM. 2576 image = args->kernel_image; 2577 if (insert_preloaded_image(static_cast<preloaded_elf_image *>(image), 2578 true) < B_OK) 2579 panic("could not create kernel image.\n"); 2580 2581 // Build image structures for all preloaded images. 2582 for (image = args->preloaded_images; image != NULL; image = image->next) 2583 insert_preloaded_image(static_cast<preloaded_elf_image *>(image), 2584 false); 2585 2586 add_debugger_command("ls", &dump_address_info, 2587 "lookup symbol for a particular address"); 2588 add_debugger_command("symbols", &dump_symbols, "dump symbols for image"); 2589 add_debugger_command("symbol", &dump_symbol, "search symbol in images"); 2590 add_debugger_command_etc("image", &dump_image, "dump image info", 2591 "Prints info about the specified image.\n" 2592 " <image> - pointer to the semaphore structure, or ID\n" 2593 " of the image to print info for.\n", 0); 2594 2595 sInitialized = true; 2596 return B_OK; 2597 } 2598 2599 2600 // #pragma mark - 2601 2602 2603 /*! Reads the symbol and string table for the kernel image with the given ID. 2604 \a _symbolCount and \a _stringTableSize are both in- and output parameters. 2605 When called they call the size of the buffers given by \a symbolTable and 2606 \a stringTable respectively. When the function returns successfully, they 2607 will contain the actual sizes (which can be greater than the original ones). 2608 The function will copy as much as possible into the buffers. For only 2609 getting the required buffer sizes, it can be invoked with \c NULL buffers. 2610 On success \a _imageDelta will contain the offset to be added to the symbol 2611 values in the table to get the actual symbol addresses. 2612 */ 2613 status_t 2614 _user_read_kernel_image_symbols(image_id id, elf_sym* symbolTable, 2615 int32* _symbolCount, char* stringTable, size_t* _stringTableSize, 2616 addr_t* _imageDelta) 2617 { 2618 // check params 2619 if (_symbolCount == NULL || _stringTableSize == NULL) 2620 return B_BAD_VALUE; 2621 if (!IS_USER_ADDRESS(_symbolCount) || !IS_USER_ADDRESS(_stringTableSize) 2622 || (_imageDelta != NULL && !IS_USER_ADDRESS(_imageDelta)) 2623 || (symbolTable != NULL && !IS_USER_ADDRESS(symbolTable)) 2624 || (stringTable != NULL && !IS_USER_ADDRESS(stringTable))) { 2625 return B_BAD_ADDRESS; 2626 } 2627 2628 // get buffer sizes 2629 int32 maxSymbolCount; 2630 size_t maxStringTableSize; 2631 if (user_memcpy(&maxSymbolCount, _symbolCount, sizeof(maxSymbolCount)) 2632 != B_OK 2633 || user_memcpy(&maxStringTableSize, _stringTableSize, 2634 sizeof(maxStringTableSize)) != B_OK) { 2635 return B_BAD_ADDRESS; 2636 } 2637 2638 // find the image 2639 MutexLocker _(sImageMutex); 2640 struct elf_image_info* image = find_image(id); 2641 if (image == NULL) 2642 return B_ENTRY_NOT_FOUND; 2643 2644 // get the tables and infos 2645 addr_t imageDelta = image->text_region.delta; 2646 const elf_sym* symbols; 2647 int32 symbolCount; 2648 const char* strings; 2649 2650 if (image->debug_symbols != NULL) { 2651 symbols = image->debug_symbols; 2652 symbolCount = image->num_debug_symbols; 2653 strings = image->debug_string_table; 2654 } else { 2655 symbols = image->syms; 2656 symbolCount = image->symhash[1]; 2657 strings = image->strtab; 2658 } 2659 2660 // The string table size isn't stored in the elf_image_info structure. Find 2661 // out by iterating through all symbols. 2662 size_t stringTableSize = 0; 2663 for (int32 i = 0; i < symbolCount; i++) { 2664 size_t index = symbols[i].st_name; 2665 if (index > stringTableSize) 2666 stringTableSize = index; 2667 } 2668 stringTableSize += strlen(strings + stringTableSize) + 1; 2669 // add size of the last string 2670 2671 // copy symbol table 2672 int32 symbolsToCopy = min_c(symbolCount, maxSymbolCount); 2673 if (symbolTable != NULL && symbolsToCopy > 0) { 2674 if (user_memcpy(symbolTable, symbols, sizeof(elf_sym) * symbolsToCopy) 2675 != B_OK) { 2676 return B_BAD_ADDRESS; 2677 } 2678 } 2679 2680 // copy string table 2681 size_t stringsToCopy = min_c(stringTableSize, maxStringTableSize); 2682 if (stringTable != NULL && stringsToCopy > 0) { 2683 if (user_memcpy(stringTable, strings, stringsToCopy) 2684 != B_OK) { 2685 return B_BAD_ADDRESS; 2686 } 2687 } 2688 2689 // copy sizes 2690 if (user_memcpy(_symbolCount, &symbolCount, sizeof(symbolCount)) != B_OK 2691 || user_memcpy(_stringTableSize, &stringTableSize, 2692 sizeof(stringTableSize)) != B_OK 2693 || (_imageDelta != NULL && user_memcpy(_imageDelta, &imageDelta, 2694 sizeof(imageDelta)) != B_OK)) { 2695 return B_BAD_ADDRESS; 2696 } 2697 2698 return B_OK; 2699 } 2700