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