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