1 /* 2 * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Copyright 2003-2011, Axel Dörfler, axeld@pinc-software.de. 4 * Distributed under the terms of the MIT License. 5 * 6 * Copyright 2002, Manuel J. Petit. All rights reserved. 7 * Copyright 2001, Travis Geiselbrecht. All rights reserved. 8 * Distributed under the terms of the NewOS License. 9 */ 10 11 #include "runtime_loader_private.h" 12 13 #include <ctype.h> 14 #include <dlfcn.h> 15 #include <stdio.h> 16 #include <stdlib.h> 17 #include <string.h> 18 19 #include <OS.h> 20 21 #include <syscalls.h> 22 #include <util/kernel_cpp.h> 23 24 #include <locks.h> 25 26 #include "add_ons.h" 27 #include "elf_load_image.h" 28 #include "elf_symbol_lookup.h" 29 #include "elf_tls.h" 30 #include "elf_versioning.h" 31 #include "errors.h" 32 #include "images.h" 33 34 35 // TODO: implement better locking strategy 36 // TODO: implement lazy binding 37 38 // a handle returned by load_library() (dlopen()) 39 #define RLD_GLOBAL_SCOPE ((void*)-2l) 40 41 static const char* const kLockName = "runtime loader"; 42 43 44 typedef void (*init_term_function)(image_id); 45 46 bool gProgramLoaded = false; 47 image_t* gProgramImage; 48 49 static image_t** sPreloadedImages = NULL; 50 static uint32 sPreloadedImageCount = 0; 51 52 static recursive_lock sLock = RECURSIVE_LOCK_INITIALIZER(kLockName); 53 54 55 static inline void 56 rld_lock() 57 { 58 recursive_lock_lock(&sLock); 59 } 60 61 62 static inline void 63 rld_unlock() 64 { 65 recursive_lock_unlock(&sLock); 66 } 67 68 69 static const char * 70 find_dt_rpath(image_t *image) 71 { 72 int i; 73 elf_dyn *d = (elf_dyn *)image->dynamic_ptr; 74 75 for (i = 0; d[i].d_tag != DT_NULL; i++) { 76 if (d[i].d_tag == DT_RPATH) 77 return STRING(image, d[i].d_un.d_val); 78 } 79 80 return NULL; 81 } 82 83 84 static status_t 85 load_immediate_dependencies(image_t *image) 86 { 87 elf_dyn *d = (elf_dyn *)image->dynamic_ptr; 88 bool reportErrors = report_errors(); 89 status_t status = B_OK; 90 uint32 i, j; 91 const char *rpath; 92 93 if (!d || (image->flags & RFLAG_DEPENDENCIES_LOADED)) 94 return B_OK; 95 96 image->flags |= RFLAG_DEPENDENCIES_LOADED; 97 98 if (image->num_needed == 0) 99 return B_OK; 100 101 KTRACE("rld: load_dependencies(\"%s\", id: %" B_PRId32 ")", image->name, 102 image->id); 103 104 image->needed = (image_t**)malloc(image->num_needed * sizeof(image_t *)); 105 if (image->needed == NULL) { 106 FATAL("%s: Failed to allocate needed struct\n", image->path); 107 KTRACE("rld: load_dependencies(\"%s\", id: %" B_PRId32 108 ") failed: no memory", image->name, image->id); 109 return B_NO_MEMORY; 110 } 111 112 memset(image->needed, 0, image->num_needed * sizeof(image_t *)); 113 rpath = find_dt_rpath(image); 114 115 for (i = 0, j = 0; d[i].d_tag != DT_NULL; i++) { 116 switch (d[i].d_tag) { 117 case DT_NEEDED: 118 { 119 int32 neededOffset = d[i].d_un.d_val; 120 const char *name = STRING(image, neededOffset); 121 122 status_t loadStatus = load_image(name, B_LIBRARY_IMAGE, 123 rpath, image->path, &image->needed[j]); 124 if (loadStatus < B_OK) { 125 status = loadStatus; 126 // correct error code in case the file could not been found 127 if (status == B_ENTRY_NOT_FOUND) { 128 status = B_MISSING_LIBRARY; 129 130 if (reportErrors) 131 gErrorMessage.AddString("missing library", name); 132 } 133 134 // Collect all missing libraries in case we report back 135 if (!reportErrors) { 136 KTRACE("rld: load_dependencies(\"%s\", id: %" B_PRId32 137 ") failed: %s", image->name, image->id, 138 strerror(status)); 139 return status; 140 } 141 } 142 143 j += 1; 144 break; 145 } 146 147 default: 148 // ignore any other tag 149 continue; 150 } 151 } 152 153 if (status < B_OK) { 154 KTRACE("rld: load_dependencies(\"%s\", id: %" B_PRId32 ") " 155 "failed: %s", image->name, image->id, 156 strerror(status)); 157 return status; 158 } 159 160 if (j != image->num_needed) { 161 FATAL("Internal error at load_dependencies()"); 162 KTRACE("rld: load_dependencies(\"%s\", id: %" B_PRId32 ") " 163 "failed: internal error", image->name, image->id); 164 return B_ERROR; 165 } 166 167 KTRACE("rld: load_dependencies(\"%s\", id: %" B_PRId32 ") done", 168 image->name, image->id); 169 170 return B_OK; 171 } 172 173 174 static status_t 175 load_dependencies(image_t* image) 176 { 177 // load dependencies (breadth-first) 178 for (image_t* otherImage = image; otherImage != NULL; 179 otherImage = otherImage->next) { 180 status_t status = load_immediate_dependencies(otherImage); 181 if (status != B_OK) 182 return status; 183 } 184 185 // Check the needed versions for the given image and all newly loaded 186 // dependencies. 187 for (image_t* otherImage = image; otherImage != NULL; 188 otherImage = otherImage->next) { 189 status_t status = check_needed_image_versions(otherImage); 190 if (status != B_OK) 191 return status; 192 } 193 194 return B_OK; 195 } 196 197 198 static status_t 199 relocate_image(image_t *rootImage, image_t *image) 200 { 201 SymbolLookupCache cache(image); 202 203 status_t status = arch_relocate_image(rootImage, image, &cache); 204 if (status < B_OK) { 205 FATAL("%s: Troubles relocating: %s\n", image->path, strerror(status)); 206 return status; 207 } 208 209 _kern_image_relocated(image->id); 210 image_event(image, IMAGE_EVENT_RELOCATED); 211 return B_OK; 212 } 213 214 215 static status_t 216 relocate_dependencies(image_t *image) 217 { 218 // get the images that still have to be relocated 219 image_t **list; 220 ssize_t count = get_sorted_image_list(image, &list, RFLAG_RELOCATED); 221 if (count < B_OK) 222 return count; 223 224 // relocate 225 for (ssize_t i = 0; i < count; i++) { 226 status_t status = relocate_image(image, list[i]); 227 if (status < B_OK) { 228 free(list); 229 return status; 230 } 231 } 232 233 free(list); 234 return B_OK; 235 } 236 237 238 static void 239 init_dependencies(image_t *image, bool initHead) 240 { 241 image_t **initList; 242 ssize_t count, i; 243 244 count = get_sorted_image_list(image, &initList, RFLAG_INITIALIZED); 245 if (count <= 0) 246 return; 247 248 if (!initHead) { 249 // this removes the "calling" image 250 image->flags &= ~RFLAG_INITIALIZED; 251 initList[--count] = NULL; 252 } 253 254 TRACE(("%ld: init dependencies\n", find_thread(NULL))); 255 for (i = 0; i < count; i++) { 256 image = initList[i]; 257 258 TRACE(("%ld: init: %s\n", find_thread(NULL), image->name)); 259 260 if (image->preinit_array) { 261 uint count_preinit = image->preinit_array_len / sizeof(addr_t); 262 for (uint j = 0; j < count_preinit; j++) 263 ((init_term_function)image->preinit_array[j])(image->id); 264 } 265 266 if (image->init_routine != 0) 267 ((init_term_function)image->init_routine)(image->id); 268 269 if (image->init_array) { 270 uint count_init = image->init_array_len / sizeof(addr_t); 271 for (uint j = 0; j < count_init; j++) 272 ((init_term_function)image->init_array[j])(image->id); 273 } 274 275 image_event(image, IMAGE_EVENT_INITIALIZED); 276 } 277 TRACE(("%ld: init done.\n", find_thread(NULL))); 278 279 free(initList); 280 } 281 282 283 static void 284 inject_runtime_loader_api(image_t* rootImage) 285 { 286 // We patch any exported __gRuntimeLoader symbols to point to our private 287 // API. 288 image_t* image; 289 void* _export; 290 if (find_symbol_breadth_first(rootImage, 291 SymbolLookupInfo("__gRuntimeLoader", B_SYMBOL_TYPE_DATA), &image, 292 &_export) == B_OK) { 293 *(void**)_export = &gRuntimeLoader; 294 } 295 } 296 297 298 static status_t 299 add_preloaded_image(image_t* image) 300 { 301 // We realloc() everytime -- not particularly efficient, but good enough for 302 // small number of preloaded images. 303 image_t** newArray = (image_t**)realloc(sPreloadedImages, 304 sizeof(image_t*) * (sPreloadedImageCount + 1)); 305 if (newArray == NULL) 306 return B_NO_MEMORY; 307 308 sPreloadedImages = newArray; 309 newArray[sPreloadedImageCount++] = image; 310 311 return B_OK; 312 } 313 314 315 image_id 316 preload_image(char const* path) 317 { 318 if (path == NULL) 319 return B_BAD_VALUE; 320 321 KTRACE("rld: preload_image(\"%s\")", path); 322 323 image_t *image = NULL; 324 status_t status = load_image(path, B_LIBRARY_IMAGE, NULL, NULL, &image); 325 if (status < B_OK) { 326 KTRACE("rld: preload_image(\"%s\") failed to load container: %s", path, 327 strerror(status)); 328 return status; 329 } 330 331 if (image->find_undefined_symbol == NULL) 332 image->find_undefined_symbol = find_undefined_symbol_global; 333 334 status = load_dependencies(image); 335 if (status < B_OK) 336 goto err; 337 338 set_image_flags_recursively(image, RTLD_GLOBAL); 339 340 status = relocate_dependencies(image); 341 if (status < B_OK) 342 goto err; 343 344 status = add_preloaded_image(image); 345 if (status < B_OK) 346 goto err; 347 348 inject_runtime_loader_api(image); 349 350 remap_images(); 351 init_dependencies(image, true); 352 353 // if the image contains an add-on, register it 354 runtime_loader_add_on* addOnStruct; 355 if (find_symbol(image, 356 SymbolLookupInfo("__gRuntimeLoaderAddOn", B_SYMBOL_TYPE_DATA), 357 (void**)&addOnStruct) == B_OK) { 358 add_add_on(image, addOnStruct); 359 } 360 361 KTRACE("rld: preload_image(\"%s\") done: id: %" B_PRId32, path, image->id); 362 363 return image->id; 364 365 err: 366 KTRACE("rld: preload_image(\"%s\") failed: %s", path, strerror(status)); 367 368 dequeue_loaded_image(image); 369 delete_image(image); 370 return status; 371 } 372 373 374 static void 375 preload_images() 376 { 377 const char* imagePaths = getenv("LD_PRELOAD"); 378 if (imagePaths == NULL) 379 return; 380 381 while (*imagePaths != '\0') { 382 // find begin of image path 383 while (*imagePaths != '\0' && isspace(*imagePaths)) 384 imagePaths++; 385 386 if (*imagePaths == '\0') 387 break; 388 389 // find end of image path 390 const char* imagePath = imagePaths; 391 while (*imagePaths != '\0' && !isspace(*imagePaths)) 392 imagePaths++; 393 394 // extract the path 395 char path[B_PATH_NAME_LENGTH]; 396 size_t pathLen = imagePaths - imagePath; 397 if (pathLen > sizeof(path) - 1) 398 continue; 399 memcpy(path, imagePath, pathLen); 400 path[pathLen] = '\0'; 401 402 // load the image 403 preload_image(path); 404 } 405 } 406 407 408 // #pragma mark - libroot.so exported functions 409 410 411 image_id 412 load_program(char const *path, void **_entry) 413 { 414 status_t status; 415 image_t *image; 416 417 KTRACE("rld: load_program(\"%s\")", path); 418 419 rld_lock(); 420 // for now, just do stupid simple global locking 421 422 preload_images(); 423 424 TRACE(("rld: load %s\n", path)); 425 426 status = load_image(path, B_APP_IMAGE, NULL, NULL, &gProgramImage); 427 if (status < B_OK) 428 goto err; 429 430 if (gProgramImage->find_undefined_symbol == NULL) 431 gProgramImage->find_undefined_symbol = find_undefined_symbol_global; 432 433 status = load_dependencies(gProgramImage); 434 if (status < B_OK) 435 goto err; 436 437 // Set RTLD_GLOBAL on all libraries including the program. 438 // This results in the desired symbol resolution for dlopen()ed libraries. 439 set_image_flags_recursively(gProgramImage, RTLD_GLOBAL); 440 441 status = relocate_dependencies(gProgramImage); 442 if (status < B_OK) 443 goto err; 444 445 inject_runtime_loader_api(gProgramImage); 446 447 remap_images(); 448 init_dependencies(gProgramImage, true); 449 450 // Since the images are initialized now, we no longer should use our 451 // getenv(), but use the one from libroot.so 452 find_symbol_breadth_first(gProgramImage, 453 SymbolLookupInfo("getenv", B_SYMBOL_TYPE_TEXT), &image, 454 (void**)&gGetEnv); 455 456 if (gProgramImage->entry_point == 0) { 457 status = B_NOT_AN_EXECUTABLE; 458 goto err; 459 } 460 461 *_entry = (void *)(gProgramImage->entry_point); 462 463 rld_unlock(); 464 465 gProgramLoaded = true; 466 467 KTRACE("rld: load_program(\"%s\") done: entry: %p, id: %" B_PRId32 , path, 468 *_entry, gProgramImage->id); 469 470 return gProgramImage->id; 471 472 err: 473 KTRACE("rld: load_program(\"%s\") failed: %s", path, strerror(status)); 474 475 delete_image(gProgramImage); 476 477 if (report_errors()) { 478 // send error message 479 gErrorMessage.AddInt32("error", status); 480 gErrorMessage.SetDeliveryInfo(gProgramArgs->error_token, 481 -1, 0, find_thread(NULL)); 482 483 _kern_write_port_etc(gProgramArgs->error_port, 'KMSG', 484 gErrorMessage.Buffer(), gErrorMessage.ContentSize(), 0, 0); 485 } 486 _kern_loading_app_failed(status); 487 rld_unlock(); 488 489 return status; 490 } 491 492 493 image_id 494 load_library(char const *path, uint32 flags, bool addOn, void** _handle) 495 { 496 image_t *image = NULL; 497 image_type type = (addOn ? B_ADD_ON_IMAGE : B_LIBRARY_IMAGE); 498 status_t status; 499 500 if (path == NULL && addOn) 501 return B_BAD_VALUE; 502 503 KTRACE("rld: load_library(\"%s\", %#" B_PRIx32 ", %d)", path, flags, addOn); 504 505 rld_lock(); 506 // for now, just do stupid simple global locking 507 508 // have we already loaded this library? 509 // Checking it at this stage saves loading its dependencies again 510 if (!addOn) { 511 // a NULL path is fine -- it means the global scope shall be opened 512 if (path == NULL) { 513 *_handle = RLD_GLOBAL_SCOPE; 514 rld_unlock(); 515 return 0; 516 } 517 518 image = find_loaded_image_by_name(path, APP_OR_LIBRARY_TYPE); 519 if (image != NULL && (flags & RTLD_GLOBAL) != 0) 520 set_image_flags_recursively(image, RTLD_GLOBAL); 521 522 if (image) { 523 atomic_add(&image->ref_count, 1); 524 rld_unlock(); 525 KTRACE("rld: load_library(\"%s\"): already loaded: %" B_PRId32, 526 path, image->id); 527 *_handle = image; 528 return image->id; 529 } 530 } 531 532 status = load_image(path, type, NULL, NULL, &image); 533 if (status < B_OK) { 534 rld_unlock(); 535 KTRACE("rld: load_library(\"%s\") failed to load container: %s", path, 536 strerror(status)); 537 return status; 538 } 539 540 if (image->find_undefined_symbol == NULL) { 541 if (addOn) 542 image->find_undefined_symbol = find_undefined_symbol_add_on; 543 else 544 image->find_undefined_symbol = find_undefined_symbol_global; 545 } 546 547 status = load_dependencies(image); 548 if (status < B_OK) 549 goto err; 550 551 // If specified, set the RTLD_GLOBAL flag recursively on this image and all 552 // dependencies. If not specified, we temporarily set 553 // RFLAG_USE_FOR_RESOLVING so that the dependencies will correctly be used 554 // for undefined symbol resolution. 555 if ((flags & RTLD_GLOBAL) != 0) 556 set_image_flags_recursively(image, RTLD_GLOBAL); 557 else 558 set_image_flags_recursively(image, RFLAG_USE_FOR_RESOLVING); 559 560 status = relocate_dependencies(image); 561 if (status < B_OK) 562 goto err; 563 564 if ((flags & RTLD_GLOBAL) == 0) 565 clear_image_flags_recursively(image, RFLAG_USE_FOR_RESOLVING); 566 567 remap_images(); 568 init_dependencies(image, true); 569 570 rld_unlock(); 571 572 KTRACE("rld: load_library(\"%s\") done: id: %" B_PRId32, path, image->id); 573 574 *_handle = image; 575 return image->id; 576 577 err: 578 KTRACE("rld: load_library(\"%s\") failed: %s", path, strerror(status)); 579 580 dequeue_loaded_image(image); 581 delete_image(image); 582 rld_unlock(); 583 return status; 584 } 585 586 587 status_t 588 unload_library(void* handle, image_id imageID, bool addOn) 589 { 590 image_t *image; 591 image_type type = addOn ? B_ADD_ON_IMAGE : B_LIBRARY_IMAGE; 592 593 if (handle == NULL && imageID < 0) 594 return B_BAD_IMAGE_ID; 595 596 if (handle == RLD_GLOBAL_SCOPE) 597 return B_OK; 598 599 rld_lock(); 600 // for now, just do stupid simple global locking 601 602 if (gInvalidImageIDs) { 603 // After fork, we lazily rebuild the image IDs of all loaded images 604 update_image_ids(); 605 } 606 607 // we only check images that have been already initialized 608 609 status_t status = B_BAD_IMAGE_ID; 610 611 if (handle != NULL) { 612 image = (image_t*)handle; 613 put_image(image); 614 status = B_OK; 615 } else { 616 image = find_loaded_image_by_id(imageID, true); 617 if (image != NULL) { 618 // unload image 619 if (type == image->type) { 620 put_image(image); 621 status = B_OK; 622 } else 623 status = B_BAD_VALUE; 624 } 625 } 626 627 if (status == B_OK) { 628 while ((image = get_disposable_images().head) != NULL) { 629 // Call the exit hooks that live in this image. 630 // Note: With the Itanium ABI this shouldn't really be done this 631 // way anymore, since global destructors are registered via 632 // __cxa_atexit() (the ones that are registered dynamically) and the 633 // termination routine should call __cxa_finalize() for the image. 634 // The reason why we still do it is that hooks registered with 635 // atexit() aren't associated with the image. We could find out 636 // there which image the hooks lives in and register it 637 // respectively, but since that would be done always, that's 638 // probably more expensive than calling 639 // call_atexit_hooks_for_range() only here, which happens only when 640 // libraries are unloaded dynamically. 641 if (gRuntimeLoader.call_atexit_hooks_for_range) { 642 gRuntimeLoader.call_atexit_hooks_for_range( 643 image->regions[0].vmstart, image->regions[0].vmsize); 644 } 645 646 image_event(image, IMAGE_EVENT_UNINITIALIZING); 647 648 if (image->term_array) { 649 uint count_term = image->term_array_len / sizeof(addr_t); 650 for (uint i = count_term; i-- > 0;) 651 ((init_term_function)image->term_array[i])(image->id); 652 } 653 654 if (image->term_routine) 655 ((init_term_function)image->term_routine)(image->id); 656 657 TLSBlockTemplates::Get().Unregister(image->dso_tls_id); 658 659 dequeue_disposable_image(image); 660 unmap_image(image); 661 662 image_event(image, IMAGE_EVENT_UNLOADING); 663 664 delete_image(image); 665 } 666 } 667 668 rld_unlock(); 669 return status; 670 } 671 672 673 status_t 674 get_nth_symbol(image_id imageID, int32 num, char *nameBuffer, 675 int32 *_nameLength, int32 *_type, void **_location) 676 { 677 int32 count = 0, j; 678 uint32 i; 679 image_t *image; 680 681 rld_lock(); 682 683 // get the image from those who have been already initialized 684 image = find_loaded_image_by_id(imageID, false); 685 if (image == NULL) { 686 rld_unlock(); 687 return B_BAD_IMAGE_ID; 688 } 689 690 // iterate through all the hash buckets until we've found the one 691 for (i = 0; i < HASHTABSIZE(image); i++) { 692 for (j = HASHBUCKETS(image)[i]; j != STN_UNDEF; j = HASHCHAINS(image)[j]) { 693 elf_sym *symbol = &image->syms[j]; 694 695 if (count == num) { 696 const char* symbolName = SYMNAME(image, symbol); 697 strlcpy(nameBuffer, symbolName, *_nameLength); 698 *_nameLength = strlen(symbolName); 699 700 void* location = (void*)(symbol->st_value 701 + image->regions[0].delta); 702 int32 type; 703 if (symbol->Type() == STT_FUNC) 704 type = B_SYMBOL_TYPE_TEXT; 705 else if (symbol->Type() == STT_OBJECT) 706 type = B_SYMBOL_TYPE_DATA; 707 else 708 type = B_SYMBOL_TYPE_ANY; 709 // TODO: check with the return types of that BeOS function 710 711 patch_defined_symbol(image, symbolName, &location, &type); 712 713 if (_type != NULL) 714 *_type = type; 715 if (_location != NULL) 716 *_location = location; 717 goto out; 718 } 719 count++; 720 } 721 } 722 out: 723 rld_unlock(); 724 725 if (num != count) 726 return B_BAD_INDEX; 727 728 return B_OK; 729 } 730 731 732 status_t 733 get_nearest_symbol_at_address(void* address, image_id* _imageID, 734 char** _imagePath, char** _imageName, char** _symbolName, int32* _type, 735 void** _location, bool* _exactMatch) 736 { 737 rld_lock(); 738 739 image_t* image = find_loaded_image_by_address((addr_t)address); 740 if (image == NULL) { 741 rld_unlock(); 742 return B_BAD_VALUE; 743 } 744 745 bool exactMatch = false; 746 elf_sym* foundSymbol = NULL; 747 addr_t foundLocation = (addr_t)NULL; 748 749 for (uint32 i = 0; i < HASHTABSIZE(image) && !exactMatch; i++) { 750 for (int32 j = HASHBUCKETS(image)[i]; j != STN_UNDEF; 751 j = HASHCHAINS(image)[j]) { 752 elf_sym *symbol = &image->syms[j]; 753 addr_t location = symbol->st_value + image->regions[0].delta; 754 755 if (location <= (addr_t)address && location >= foundLocation) { 756 foundSymbol = symbol; 757 foundLocation = location; 758 759 // jump out if we have an exact match 760 if (location + symbol->st_size > (addr_t)address) { 761 exactMatch = true; 762 break; 763 } 764 } 765 } 766 } 767 768 if (_imageID != NULL) 769 *_imageID = image->id; 770 if (_imagePath != NULL) 771 *_imagePath = image->path; 772 if (_imageName != NULL) 773 *_imageName = image->name; 774 if (_exactMatch != NULL) 775 *_exactMatch = exactMatch; 776 777 if (foundSymbol != NULL) { 778 *_symbolName = SYMNAME(image, foundSymbol); 779 780 if (_type != NULL) { 781 if (foundSymbol->Type() == STT_FUNC) 782 *_type = B_SYMBOL_TYPE_TEXT; 783 else if (foundSymbol->Type() == STT_OBJECT) 784 *_type = B_SYMBOL_TYPE_DATA; 785 else 786 *_type = B_SYMBOL_TYPE_ANY; 787 // TODO: check with the return types of that BeOS function 788 } 789 790 if (_location != NULL) 791 *_location = (void*)foundLocation; 792 } else { 793 *_symbolName = NULL; 794 if (_location != NULL) 795 *_location = NULL; 796 } 797 798 rld_unlock(); 799 return B_OK; 800 } 801 802 803 status_t 804 get_symbol(image_id imageID, char const *symbolName, int32 symbolType, 805 bool recursive, image_id *_inImage, void **_location) 806 { 807 status_t status = B_OK; 808 image_t *image; 809 810 if (imageID < B_OK) 811 return B_BAD_IMAGE_ID; 812 if (symbolName == NULL) 813 return B_BAD_VALUE; 814 815 rld_lock(); 816 // for now, just do stupid simple global locking 817 818 // get the image from those who have been already initialized 819 image = find_loaded_image_by_id(imageID, false); 820 if (image != NULL) { 821 if (recursive) { 822 // breadth-first search in the given image and its dependencies 823 status = find_symbol_breadth_first(image, 824 SymbolLookupInfo(symbolName, symbolType, NULL, 825 LOOKUP_FLAG_DEFAULT_VERSION), 826 &image, _location); 827 } else { 828 status = find_symbol(image, 829 SymbolLookupInfo(symbolName, symbolType, NULL, 830 LOOKUP_FLAG_DEFAULT_VERSION), 831 _location); 832 } 833 834 if (status == B_OK && _inImage != NULL) 835 *_inImage = image->id; 836 } else 837 status = B_BAD_IMAGE_ID; 838 839 rld_unlock(); 840 return status; 841 } 842 843 844 status_t 845 get_library_symbol(void* handle, void* caller, const char* symbolName, 846 void **_location) 847 { 848 status_t status = B_ENTRY_NOT_FOUND; 849 850 if (symbolName == NULL) 851 return B_BAD_VALUE; 852 853 rld_lock(); 854 // for now, just do stupid simple global locking 855 856 if (handle == RTLD_DEFAULT || handle == RLD_GLOBAL_SCOPE) { 857 // look in the default scope 858 image_t* image; 859 elf_sym* symbol = find_undefined_symbol_global(gProgramImage, 860 gProgramImage, 861 SymbolLookupInfo(symbolName, B_SYMBOL_TYPE_ANY, NULL, 862 LOOKUP_FLAG_DEFAULT_VERSION), 863 &image); 864 if (symbol != NULL) { 865 *_location = (void*)(symbol->st_value + image->regions[0].delta); 866 int32 symbolType = symbol->Type() == STT_FUNC 867 ? B_SYMBOL_TYPE_TEXT : B_SYMBOL_TYPE_DATA; 868 patch_defined_symbol(image, symbolName, _location, &symbolType); 869 status = B_OK; 870 } 871 } else if (handle == RTLD_NEXT) { 872 // Look in the default scope, but also in the dependencies of the 873 // calling image. Return the next after the caller symbol. 874 875 // First of all, find the caller image. 876 image_t* callerImage = get_loaded_images().head; 877 for (; callerImage != NULL; callerImage = callerImage->next) { 878 elf_region_t& text = callerImage->regions[0]; 879 if ((addr_t)caller >= text.vmstart 880 && (addr_t)caller < text.vmstart + text.vmsize) { 881 // found the image 882 break; 883 } 884 } 885 886 if (callerImage != NULL) { 887 // found the caller -- now search the global scope until we find 888 // the next symbol 889 bool hitCallerImage = false; 890 set_image_flags_recursively(callerImage, RFLAG_USE_FOR_RESOLVING); 891 892 elf_sym* candidateSymbol = NULL; 893 image_t* candidateImage = NULL; 894 895 image_t* image = get_loaded_images().head; 896 for (; image != NULL; image = image->next) { 897 // skip the caller image 898 if (image == callerImage) { 899 hitCallerImage = true; 900 continue; 901 } 902 903 // skip all images up to the caller image; also skip add-on 904 // images and those not marked above for resolution 905 if (!hitCallerImage || image->type == B_ADD_ON_IMAGE 906 || (image->flags 907 & (RTLD_GLOBAL | RFLAG_USE_FOR_RESOLVING)) == 0) { 908 continue; 909 } 910 911 elf_sym *symbol = find_symbol(image, 912 SymbolLookupInfo(symbolName, B_SYMBOL_TYPE_TEXT, NULL, 913 LOOKUP_FLAG_DEFAULT_VERSION)); 914 if (symbol == NULL) 915 continue; 916 917 // found a symbol 918 bool isWeak = symbol->Bind() == STB_WEAK; 919 if (candidateImage == NULL || !isWeak) { 920 candidateSymbol = symbol; 921 candidateImage = image; 922 923 if (!isWeak) 924 break; 925 } 926 927 // symbol is weak, so we need to continue 928 } 929 930 if (candidateSymbol != NULL) { 931 // found the symbol 932 *_location = (void*)(candidateSymbol->st_value 933 + candidateImage->regions[0].delta); 934 int32 symbolType = B_SYMBOL_TYPE_TEXT; 935 patch_defined_symbol(candidateImage, symbolName, _location, 936 &symbolType); 937 status = B_OK; 938 } 939 940 clear_image_flags_recursively(callerImage, RFLAG_USE_FOR_RESOLVING); 941 } 942 } else { 943 // breadth-first search in the given image and its dependencies 944 image_t* inImage; 945 status = find_symbol_breadth_first((image_t*)handle, 946 SymbolLookupInfo(symbolName, B_SYMBOL_TYPE_ANY, NULL, 947 LOOKUP_FLAG_DEFAULT_VERSION), 948 &inImage, _location); 949 } 950 951 rld_unlock(); 952 return status; 953 } 954 955 956 status_t 957 get_next_image_dependency(image_id id, uint32 *cookie, const char **_name) 958 { 959 uint32 i, j, searchIndex = *cookie; 960 elf_dyn *dynamicSection; 961 image_t *image; 962 963 if (_name == NULL) 964 return B_BAD_VALUE; 965 966 rld_lock(); 967 968 image = find_loaded_image_by_id(id, false); 969 if (image == NULL) { 970 rld_unlock(); 971 return B_BAD_IMAGE_ID; 972 } 973 974 dynamicSection = (elf_dyn *)image->dynamic_ptr; 975 if (dynamicSection == NULL || image->num_needed <= searchIndex) { 976 rld_unlock(); 977 return B_ENTRY_NOT_FOUND; 978 } 979 980 for (i = 0, j = 0; dynamicSection[i].d_tag != DT_NULL; i++) { 981 if (dynamicSection[i].d_tag != DT_NEEDED) 982 continue; 983 984 if (j++ == searchIndex) { 985 int32 neededOffset = dynamicSection[i].d_un.d_val; 986 987 *_name = STRING(image, neededOffset); 988 *cookie = searchIndex + 1; 989 rld_unlock(); 990 return B_OK; 991 } 992 } 993 994 rld_unlock(); 995 return B_ENTRY_NOT_FOUND; 996 } 997 998 999 // #pragma mark - runtime_loader private exports 1000 1001 1002 /*! Read and verify the ELF header */ 1003 status_t 1004 elf_verify_header(void *header, size_t length) 1005 { 1006 int32 programSize, sectionSize; 1007 1008 if (length < sizeof(elf_ehdr)) 1009 return B_NOT_AN_EXECUTABLE; 1010 1011 return parse_elf_header((elf_ehdr *)header, &programSize, §ionSize); 1012 } 1013 1014 1015 #ifdef _COMPAT_MODE 1016 #ifdef __x86_64__ 1017 status_t 1018 elf32_verify_header(void *header, size_t length) 1019 { 1020 int32 programSize, sectionSize; 1021 1022 if (length < sizeof(Elf32_Ehdr)) 1023 return B_NOT_AN_EXECUTABLE; 1024 1025 return parse_elf32_header((Elf32_Ehdr *)header, &programSize, §ionSize); 1026 } 1027 #else 1028 status_t 1029 elf64_verify_header(void *header, size_t length) 1030 { 1031 int32 programSize, sectionSize; 1032 1033 if (length < sizeof(Elf64_Ehdr)) 1034 return B_NOT_AN_EXECUTABLE; 1035 1036 return parse_elf64_header((Elf64_Ehdr *)header, &programSize, §ionSize); 1037 } 1038 #endif // __x86_64__ 1039 #endif // _COMPAT_MODE 1040 1041 1042 void 1043 terminate_program(void) 1044 { 1045 image_t **termList; 1046 ssize_t count, i; 1047 1048 count = get_sorted_image_list(NULL, &termList, RFLAG_TERMINATED); 1049 if (count < B_OK) 1050 return; 1051 1052 if (gInvalidImageIDs) { 1053 // After fork, we lazily rebuild the image IDs of all loaded images 1054 update_image_ids(); 1055 } 1056 1057 TRACE(("%ld: terminate dependencies\n", find_thread(NULL))); 1058 for (i = count; i-- > 0;) { 1059 image_t *image = termList[i]; 1060 1061 TRACE(("%ld: term: %s\n", find_thread(NULL), image->name)); 1062 1063 image_event(image, IMAGE_EVENT_UNINITIALIZING); 1064 1065 if (image->term_array) { 1066 uint count_term = image->term_array_len / sizeof(addr_t); 1067 for (uint j = count_term; j-- > 0;) 1068 ((init_term_function)image->term_array[j])(image->id); 1069 } 1070 1071 if (image->term_routine) 1072 ((init_term_function)image->term_routine)(image->id); 1073 1074 image_event(image, IMAGE_EVENT_UNLOADING); 1075 } 1076 TRACE(("%ld: term done.\n", find_thread(NULL))); 1077 1078 free(termList); 1079 } 1080 1081 1082 void 1083 rldelf_init(void) 1084 { 1085 init_add_ons(); 1086 1087 // create the debug area 1088 { 1089 size_t size = TO_PAGE_SIZE(sizeof(runtime_loader_debug_area)); 1090 1091 runtime_loader_debug_area *area; 1092 area_id areaID = _kern_create_area(RUNTIME_LOADER_DEBUG_AREA_NAME, 1093 (void **)&area, B_RANDOMIZED_ANY_ADDRESS, size, B_NO_LOCK, 1094 B_READ_AREA | B_WRITE_AREA); 1095 if (areaID < B_OK) { 1096 FATAL("Failed to create debug area.\n"); 1097 _kern_loading_app_failed(areaID); 1098 } 1099 1100 area->loaded_images = &get_loaded_images(); 1101 } 1102 1103 // initialize error message if needed 1104 if (report_errors()) { 1105 void *buffer = malloc(1024); 1106 if (buffer == NULL) 1107 return; 1108 1109 gErrorMessage.SetTo(buffer, 1024, 'Rler'); 1110 } 1111 } 1112 1113 1114 status_t 1115 elf_reinit_after_fork(void) 1116 { 1117 recursive_lock_init(&sLock, kLockName); 1118 1119 // We also need to update the IDs of our images. We are the child and 1120 // and have cloned images with different IDs. Since in most cases (fork() 1121 // + exec*()) this would just increase the fork() overhead with no one 1122 // caring, we do that lazily, when first doing something different. 1123 gInvalidImageIDs = true; 1124 1125 return B_OK; 1126 } 1127