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