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