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->init_routine != 0) 261 ((init_term_function)image->init_routine)(image->id); 262 263 image_event(image, IMAGE_EVENT_INITIALIZED); 264 } 265 TRACE(("%ld: init done.\n", find_thread(NULL))); 266 267 free(initList); 268 } 269 270 271 static void 272 inject_runtime_loader_api(image_t* rootImage) 273 { 274 // We patch any exported __gRuntimeLoader symbols to point to our private 275 // API. 276 image_t* image; 277 void* _export; 278 if (find_symbol_breadth_first(rootImage, 279 SymbolLookupInfo("__gRuntimeLoader", B_SYMBOL_TYPE_DATA), &image, 280 &_export) == B_OK) { 281 *(void**)_export = &gRuntimeLoader; 282 } 283 } 284 285 286 static status_t 287 add_preloaded_image(image_t* image) 288 { 289 // We realloc() everytime -- not particularly efficient, but good enough for 290 // small number of preloaded images. 291 image_t** newArray = (image_t**)realloc(sPreloadedImages, 292 sizeof(image_t*) * (sPreloadedImageCount + 1)); 293 if (newArray == NULL) 294 return B_NO_MEMORY; 295 296 sPreloadedImages = newArray; 297 newArray[sPreloadedImageCount++] = image; 298 299 return B_OK; 300 } 301 302 303 image_id 304 preload_image(char const* path) 305 { 306 if (path == NULL) 307 return B_BAD_VALUE; 308 309 KTRACE("rld: preload_image(\"%s\")", path); 310 311 image_t *image = NULL; 312 status_t status = load_image(path, B_LIBRARY_IMAGE, NULL, NULL, &image); 313 if (status < B_OK) { 314 KTRACE("rld: preload_image(\"%s\") failed to load container: %s", path, 315 strerror(status)); 316 return status; 317 } 318 319 if (image->find_undefined_symbol == NULL) 320 image->find_undefined_symbol = find_undefined_symbol_global; 321 322 status = load_dependencies(image); 323 if (status < B_OK) 324 goto err; 325 326 set_image_flags_recursively(image, RTLD_GLOBAL); 327 328 status = relocate_dependencies(image); 329 if (status < B_OK) 330 goto err; 331 332 status = add_preloaded_image(image); 333 if (status < B_OK) 334 goto err; 335 336 inject_runtime_loader_api(image); 337 338 remap_images(); 339 init_dependencies(image, true); 340 341 // if the image contains an add-on, register it 342 runtime_loader_add_on* addOnStruct; 343 if (find_symbol(image, 344 SymbolLookupInfo("__gRuntimeLoaderAddOn", B_SYMBOL_TYPE_DATA), 345 (void**)&addOnStruct) == B_OK) { 346 add_add_on(image, addOnStruct); 347 } 348 349 KTRACE("rld: preload_image(\"%s\") done: id: %" B_PRId32, path, image->id); 350 351 return image->id; 352 353 err: 354 KTRACE("rld: preload_image(\"%s\") failed: %s", path, strerror(status)); 355 356 dequeue_loaded_image(image); 357 delete_image(image); 358 return status; 359 } 360 361 362 static void 363 preload_images() 364 { 365 const char* imagePaths = getenv("LD_PRELOAD"); 366 if (imagePaths == NULL) 367 return; 368 369 while (*imagePaths != '\0') { 370 // find begin of image path 371 while (*imagePaths != '\0' && isspace(*imagePaths)) 372 imagePaths++; 373 374 if (*imagePaths == '\0') 375 break; 376 377 // find end of image path 378 const char* imagePath = imagePaths; 379 while (*imagePaths != '\0' && !isspace(*imagePaths)) 380 imagePaths++; 381 382 // extract the path 383 char path[B_PATH_NAME_LENGTH]; 384 size_t pathLen = imagePaths - imagePath; 385 if (pathLen > sizeof(path) - 1) 386 continue; 387 memcpy(path, imagePath, pathLen); 388 path[pathLen] = '\0'; 389 390 // load the image 391 preload_image(path); 392 } 393 } 394 395 396 // #pragma mark - libroot.so exported functions 397 398 399 image_id 400 load_program(char const *path, void **_entry) 401 { 402 status_t status; 403 image_t *image; 404 405 KTRACE("rld: load_program(\"%s\")", path); 406 407 rld_lock(); 408 // for now, just do stupid simple global locking 409 410 preload_images(); 411 412 TRACE(("rld: load %s\n", path)); 413 414 status = load_image(path, B_APP_IMAGE, NULL, NULL, &gProgramImage); 415 if (status < B_OK) 416 goto err; 417 418 if (gProgramImage->find_undefined_symbol == NULL) 419 gProgramImage->find_undefined_symbol = find_undefined_symbol_global; 420 421 status = load_dependencies(gProgramImage); 422 if (status < B_OK) 423 goto err; 424 425 // Set RTLD_GLOBAL on all libraries including the program. 426 // This results in the desired symbol resolution for dlopen()ed libraries. 427 set_image_flags_recursively(gProgramImage, RTLD_GLOBAL); 428 429 status = relocate_dependencies(gProgramImage); 430 if (status < B_OK) 431 goto err; 432 433 inject_runtime_loader_api(gProgramImage); 434 435 remap_images(); 436 init_dependencies(gProgramImage, true); 437 438 // Since the images are initialized now, we no longer should use our 439 // getenv(), but use the one from libroot.so 440 find_symbol_breadth_first(gProgramImage, 441 SymbolLookupInfo("getenv", B_SYMBOL_TYPE_TEXT), &image, 442 (void**)&gGetEnv); 443 444 if (gProgramImage->entry_point == 0) { 445 status = B_NOT_AN_EXECUTABLE; 446 goto err; 447 } 448 449 *_entry = (void *)(gProgramImage->entry_point); 450 451 rld_unlock(); 452 453 gProgramLoaded = true; 454 455 KTRACE("rld: load_program(\"%s\") done: entry: %p, id: %" B_PRId32 , path, 456 *_entry, gProgramImage->id); 457 458 return gProgramImage->id; 459 460 err: 461 KTRACE("rld: load_program(\"%s\") failed: %s", path, strerror(status)); 462 463 delete_image(gProgramImage); 464 465 if (report_errors()) { 466 // send error message 467 gErrorMessage.AddInt32("error", status); 468 gErrorMessage.SetDeliveryInfo(gProgramArgs->error_token, 469 -1, 0, find_thread(NULL)); 470 471 _kern_write_port_etc(gProgramArgs->error_port, 'KMSG', 472 gErrorMessage.Buffer(), gErrorMessage.ContentSize(), 0, 0); 473 } 474 _kern_loading_app_failed(status); 475 rld_unlock(); 476 477 return status; 478 } 479 480 481 image_id 482 load_library(char const *path, uint32 flags, bool addOn, void** _handle) 483 { 484 image_t *image = NULL; 485 image_type type = (addOn ? B_ADD_ON_IMAGE : B_LIBRARY_IMAGE); 486 status_t status; 487 488 if (path == NULL && addOn) 489 return B_BAD_VALUE; 490 491 KTRACE("rld: load_library(\"%s\", %#" B_PRIx32 ", %d)", path, flags, addOn); 492 493 rld_lock(); 494 // for now, just do stupid simple global locking 495 496 // have we already loaded this library? 497 // Checking it at this stage saves loading its dependencies again 498 if (!addOn) { 499 // a NULL path is fine -- it means the global scope shall be opened 500 if (path == NULL) { 501 *_handle = RLD_GLOBAL_SCOPE; 502 rld_unlock(); 503 return 0; 504 } 505 506 image = find_loaded_image_by_name(path, APP_OR_LIBRARY_TYPE); 507 if (image != NULL && (flags & RTLD_GLOBAL) != 0) 508 set_image_flags_recursively(image, RTLD_GLOBAL); 509 510 if (image) { 511 atomic_add(&image->ref_count, 1); 512 rld_unlock(); 513 KTRACE("rld: load_library(\"%s\"): already loaded: %" B_PRId32, 514 path, image->id); 515 *_handle = image; 516 return image->id; 517 } 518 } 519 520 status = load_image(path, type, NULL, NULL, &image); 521 if (status < B_OK) { 522 rld_unlock(); 523 KTRACE("rld: load_library(\"%s\") failed to load container: %s", path, 524 strerror(status)); 525 return status; 526 } 527 528 if (image->find_undefined_symbol == NULL) { 529 if (addOn) 530 image->find_undefined_symbol = find_undefined_symbol_add_on; 531 else 532 image->find_undefined_symbol = find_undefined_symbol_global; 533 } 534 535 status = load_dependencies(image); 536 if (status < B_OK) 537 goto err; 538 539 // If specified, set the RTLD_GLOBAL flag recursively on this image and all 540 // dependencies. If not specified, we temporarily set 541 // RFLAG_USE_FOR_RESOLVING so that the dependencies will correctly be used 542 // for undefined symbol resolution. 543 if ((flags & RTLD_GLOBAL) != 0) 544 set_image_flags_recursively(image, RTLD_GLOBAL); 545 else 546 set_image_flags_recursively(image, RFLAG_USE_FOR_RESOLVING); 547 548 status = relocate_dependencies(image); 549 if (status < B_OK) 550 goto err; 551 552 if ((flags & RTLD_GLOBAL) == 0) 553 clear_image_flags_recursively(image, RFLAG_USE_FOR_RESOLVING); 554 555 remap_images(); 556 init_dependencies(image, true); 557 558 rld_unlock(); 559 560 KTRACE("rld: load_library(\"%s\") done: id: %" B_PRId32, path, image->id); 561 562 *_handle = image; 563 return image->id; 564 565 err: 566 KTRACE("rld: load_library(\"%s\") failed: %s", path, strerror(status)); 567 568 dequeue_loaded_image(image); 569 delete_image(image); 570 rld_unlock(); 571 return status; 572 } 573 574 575 status_t 576 unload_library(void* handle, image_id imageID, bool addOn) 577 { 578 image_t *image; 579 image_type type = addOn ? B_ADD_ON_IMAGE : B_LIBRARY_IMAGE; 580 581 if (handle == NULL && imageID < 0) 582 return B_BAD_IMAGE_ID; 583 584 if (handle == RLD_GLOBAL_SCOPE) 585 return B_OK; 586 587 rld_lock(); 588 // for now, just do stupid simple global locking 589 590 if (gInvalidImageIDs) { 591 // After fork, we lazily rebuild the image IDs of all loaded images 592 update_image_ids(); 593 } 594 595 // we only check images that have been already initialized 596 597 status_t status = B_BAD_IMAGE_ID; 598 599 if (handle != NULL) { 600 image = (image_t*)handle; 601 put_image(image); 602 status = B_OK; 603 } else { 604 image = find_loaded_image_by_id(imageID, true); 605 if (image != NULL) { 606 // unload image 607 if (type == image->type) { 608 put_image(image); 609 status = B_OK; 610 } else 611 status = B_BAD_VALUE; 612 } 613 } 614 615 if (status == B_OK) { 616 while ((image = get_disposable_images().head) != NULL) { 617 // Call the exit hooks that live in this image. 618 // Note: With the Itanium ABI this shouldn't really be done this 619 // way anymore, since global destructors are registered via 620 // __cxa_atexit() (the ones that are registered dynamically) and the 621 // termination routine should call __cxa_finalize() for the image. 622 // The reason why we still do it is that hooks registered with 623 // atexit() aren't associated with the image. We could find out 624 // there which image the hooks lives in and register it 625 // respectively, but since that would be done always, that's 626 // probably more expensive than calling 627 // call_atexit_hooks_for_range() only here, which happens only when 628 // libraries are unloaded dynamically. 629 if (gRuntimeLoader.call_atexit_hooks_for_range) { 630 gRuntimeLoader.call_atexit_hooks_for_range( 631 image->regions[0].vmstart, image->regions[0].vmsize); 632 } 633 634 image_event(image, IMAGE_EVENT_UNINITIALIZING); 635 636 if (image->term_routine) 637 ((init_term_function)image->term_routine)(image->id); 638 639 TLSBlockTemplates::Get().Unregister(image->dso_tls_id); 640 641 dequeue_disposable_image(image); 642 unmap_image(image); 643 644 image_event(image, IMAGE_EVENT_UNLOADING); 645 646 delete_image(image); 647 } 648 } 649 650 rld_unlock(); 651 return status; 652 } 653 654 655 status_t 656 get_nth_symbol(image_id imageID, int32 num, char *nameBuffer, 657 int32 *_nameLength, int32 *_type, void **_location) 658 { 659 int32 count = 0, j; 660 uint32 i; 661 image_t *image; 662 663 rld_lock(); 664 665 // get the image from those who have been already initialized 666 image = find_loaded_image_by_id(imageID, false); 667 if (image == NULL) { 668 rld_unlock(); 669 return B_BAD_IMAGE_ID; 670 } 671 672 // iterate through all the hash buckets until we've found the one 673 for (i = 0; i < HASHTABSIZE(image); i++) { 674 for (j = HASHBUCKETS(image)[i]; j != STN_UNDEF; j = HASHCHAINS(image)[j]) { 675 elf_sym *symbol = &image->syms[j]; 676 677 if (count == num) { 678 const char* symbolName = SYMNAME(image, symbol); 679 strlcpy(nameBuffer, symbolName, *_nameLength); 680 *_nameLength = strlen(symbolName); 681 682 void* location = (void*)(symbol->st_value 683 + image->regions[0].delta); 684 int32 type; 685 if (symbol->Type() == STT_FUNC) 686 type = B_SYMBOL_TYPE_TEXT; 687 else if (symbol->Type() == STT_OBJECT) 688 type = B_SYMBOL_TYPE_DATA; 689 else 690 type = B_SYMBOL_TYPE_ANY; 691 // TODO: check with the return types of that BeOS function 692 693 patch_defined_symbol(image, symbolName, &location, &type); 694 695 if (_type != NULL) 696 *_type = type; 697 if (_location != NULL) 698 *_location = location; 699 goto out; 700 } 701 count++; 702 } 703 } 704 out: 705 rld_unlock(); 706 707 if (num != count) 708 return B_BAD_INDEX; 709 710 return B_OK; 711 } 712 713 714 status_t 715 get_nearest_symbol_at_address(void* address, image_id* _imageID, 716 char** _imagePath, char** _imageName, char** _symbolName, int32* _type, 717 void** _location, bool* _exactMatch) 718 { 719 rld_lock(); 720 721 image_t* image = find_loaded_image_by_address((addr_t)address); 722 if (image == NULL) { 723 rld_unlock(); 724 return B_BAD_VALUE; 725 } 726 727 bool exactMatch = false; 728 elf_sym* foundSymbol = NULL; 729 addr_t foundLocation = (addr_t)NULL; 730 731 for (uint32 i = 0; i < HASHTABSIZE(image) && !exactMatch; i++) { 732 for (int32 j = HASHBUCKETS(image)[i]; j != STN_UNDEF; 733 j = HASHCHAINS(image)[j]) { 734 elf_sym *symbol = &image->syms[j]; 735 addr_t location = symbol->st_value + image->regions[0].delta; 736 737 if (location <= (addr_t)address && location >= foundLocation) { 738 foundSymbol = symbol; 739 foundLocation = location; 740 741 // jump out if we have an exact match 742 if (location + symbol->st_size > (addr_t)address) { 743 exactMatch = true; 744 break; 745 } 746 } 747 } 748 } 749 750 if (_imageID != NULL) 751 *_imageID = image->id; 752 if (_imagePath != NULL) 753 *_imagePath = image->path; 754 if (_imageName != NULL) 755 *_imageName = image->name; 756 if (_exactMatch != NULL) 757 *_exactMatch = exactMatch; 758 759 if (foundSymbol != NULL) { 760 *_symbolName = SYMNAME(image, foundSymbol); 761 762 if (_type != NULL) { 763 if (foundSymbol->Type() == STT_FUNC) 764 *_type = B_SYMBOL_TYPE_TEXT; 765 else if (foundSymbol->Type() == STT_OBJECT) 766 *_type = B_SYMBOL_TYPE_DATA; 767 else 768 *_type = B_SYMBOL_TYPE_ANY; 769 // TODO: check with the return types of that BeOS function 770 } 771 772 if (_location != NULL) 773 *_location = (void*)foundLocation; 774 } else { 775 *_symbolName = NULL; 776 if (_location != NULL) 777 *_location = NULL; 778 } 779 780 rld_unlock(); 781 return B_OK; 782 } 783 784 785 status_t 786 get_symbol(image_id imageID, char const *symbolName, int32 symbolType, 787 bool recursive, image_id *_inImage, void **_location) 788 { 789 status_t status = B_OK; 790 image_t *image; 791 792 if (imageID < B_OK) 793 return B_BAD_IMAGE_ID; 794 if (symbolName == NULL) 795 return B_BAD_VALUE; 796 797 rld_lock(); 798 // for now, just do stupid simple global locking 799 800 // get the image from those who have been already initialized 801 image = find_loaded_image_by_id(imageID, false); 802 if (image != NULL) { 803 if (recursive) { 804 // breadth-first search in the given image and its dependencies 805 status = find_symbol_breadth_first(image, 806 SymbolLookupInfo(symbolName, symbolType, NULL, 807 LOOKUP_FLAG_DEFAULT_VERSION), 808 &image, _location); 809 } else { 810 status = find_symbol(image, 811 SymbolLookupInfo(symbolName, symbolType, NULL, 812 LOOKUP_FLAG_DEFAULT_VERSION), 813 _location); 814 } 815 816 if (status == B_OK && _inImage != NULL) 817 *_inImage = image->id; 818 } else 819 status = B_BAD_IMAGE_ID; 820 821 rld_unlock(); 822 return status; 823 } 824 825 826 status_t 827 get_library_symbol(void* handle, void* caller, const char* symbolName, 828 void **_location) 829 { 830 status_t status = B_ENTRY_NOT_FOUND; 831 832 if (symbolName == NULL) 833 return B_BAD_VALUE; 834 835 rld_lock(); 836 // for now, just do stupid simple global locking 837 838 if (handle == RTLD_DEFAULT || handle == RLD_GLOBAL_SCOPE) { 839 // look in the default scope 840 image_t* image; 841 elf_sym* symbol = find_undefined_symbol_global(gProgramImage, 842 gProgramImage, 843 SymbolLookupInfo(symbolName, B_SYMBOL_TYPE_ANY, NULL, 844 LOOKUP_FLAG_DEFAULT_VERSION), 845 &image); 846 if (symbol != NULL) { 847 *_location = (void*)(symbol->st_value + image->regions[0].delta); 848 int32 symbolType = symbol->Type() == STT_FUNC 849 ? B_SYMBOL_TYPE_TEXT : B_SYMBOL_TYPE_DATA; 850 patch_defined_symbol(image, symbolName, _location, &symbolType); 851 status = B_OK; 852 } 853 } else if (handle == RTLD_NEXT) { 854 // Look in the default scope, but also in the dependencies of the 855 // calling image. Return the next after the caller symbol. 856 857 // First of all, find the caller image. 858 image_t* callerImage = get_loaded_images().head; 859 for (; callerImage != NULL; callerImage = callerImage->next) { 860 elf_region_t& text = callerImage->regions[0]; 861 if ((addr_t)caller >= text.vmstart 862 && (addr_t)caller < text.vmstart + text.vmsize) { 863 // found the image 864 break; 865 } 866 } 867 868 if (callerImage != NULL) { 869 // found the caller -- now search the global scope until we find 870 // the next symbol 871 bool hitCallerImage = false; 872 set_image_flags_recursively(callerImage, RFLAG_USE_FOR_RESOLVING); 873 874 elf_sym* candidateSymbol = NULL; 875 image_t* candidateImage = NULL; 876 877 image_t* image = get_loaded_images().head; 878 for (; image != NULL; image = image->next) { 879 // skip the caller image 880 if (image == callerImage) { 881 hitCallerImage = true; 882 continue; 883 } 884 885 // skip all images up to the caller image; also skip add-on 886 // images and those not marked above for resolution 887 if (!hitCallerImage || image->type == B_ADD_ON_IMAGE 888 || (image->flags 889 & (RTLD_GLOBAL | RFLAG_USE_FOR_RESOLVING)) == 0) { 890 continue; 891 } 892 893 elf_sym *symbol = find_symbol(image, 894 SymbolLookupInfo(symbolName, B_SYMBOL_TYPE_TEXT, NULL, 895 LOOKUP_FLAG_DEFAULT_VERSION)); 896 if (symbol == NULL) 897 continue; 898 899 // found a symbol 900 bool isWeak = symbol->Bind() == STB_WEAK; 901 if (candidateImage == NULL || !isWeak) { 902 candidateSymbol = symbol; 903 candidateImage = image; 904 905 if (!isWeak) 906 break; 907 } 908 909 // symbol is weak, so we need to continue 910 } 911 912 if (candidateSymbol != NULL) { 913 // found the symbol 914 *_location = (void*)(candidateSymbol->st_value 915 + candidateImage->regions[0].delta); 916 int32 symbolType = B_SYMBOL_TYPE_TEXT; 917 patch_defined_symbol(candidateImage, symbolName, _location, 918 &symbolType); 919 status = B_OK; 920 } 921 922 clear_image_flags_recursively(callerImage, RFLAG_USE_FOR_RESOLVING); 923 } 924 } else { 925 // breadth-first search in the given image and its dependencies 926 image_t* inImage; 927 status = find_symbol_breadth_first((image_t*)handle, 928 SymbolLookupInfo(symbolName, B_SYMBOL_TYPE_ANY, NULL, 929 LOOKUP_FLAG_DEFAULT_VERSION), 930 &inImage, _location); 931 } 932 933 rld_unlock(); 934 return status; 935 } 936 937 938 status_t 939 get_next_image_dependency(image_id id, uint32 *cookie, const char **_name) 940 { 941 uint32 i, j, searchIndex = *cookie; 942 elf_dyn *dynamicSection; 943 image_t *image; 944 945 if (_name == NULL) 946 return B_BAD_VALUE; 947 948 rld_lock(); 949 950 image = find_loaded_image_by_id(id, false); 951 if (image == NULL) { 952 rld_unlock(); 953 return B_BAD_IMAGE_ID; 954 } 955 956 dynamicSection = (elf_dyn *)image->dynamic_ptr; 957 if (dynamicSection == NULL || image->num_needed <= searchIndex) { 958 rld_unlock(); 959 return B_ENTRY_NOT_FOUND; 960 } 961 962 for (i = 0, j = 0; dynamicSection[i].d_tag != DT_NULL; i++) { 963 if (dynamicSection[i].d_tag != DT_NEEDED) 964 continue; 965 966 if (j++ == searchIndex) { 967 int32 neededOffset = dynamicSection[i].d_un.d_val; 968 969 *_name = STRING(image, neededOffset); 970 *cookie = searchIndex + 1; 971 rld_unlock(); 972 return B_OK; 973 } 974 } 975 976 rld_unlock(); 977 return B_ENTRY_NOT_FOUND; 978 } 979 980 981 // #pragma mark - runtime_loader private exports 982 983 984 /*! Read and verify the ELF header */ 985 status_t 986 elf_verify_header(void *header, size_t length) 987 { 988 int32 programSize, sectionSize; 989 990 if (length < sizeof(elf_ehdr)) 991 return B_NOT_AN_EXECUTABLE; 992 993 return parse_elf_header((elf_ehdr *)header, &programSize, §ionSize); 994 } 995 996 997 void 998 terminate_program(void) 999 { 1000 image_t **termList; 1001 ssize_t count, i; 1002 1003 count = get_sorted_image_list(NULL, &termList, RFLAG_TERMINATED); 1004 if (count < B_OK) 1005 return; 1006 1007 if (gInvalidImageIDs) { 1008 // After fork, we lazily rebuild the image IDs of all loaded images 1009 update_image_ids(); 1010 } 1011 1012 TRACE(("%ld: terminate dependencies\n", find_thread(NULL))); 1013 for (i = count; i-- > 0;) { 1014 image_t *image = termList[i]; 1015 1016 TRACE(("%ld: term: %s\n", find_thread(NULL), image->name)); 1017 1018 image_event(image, IMAGE_EVENT_UNINITIALIZING); 1019 1020 if (image->term_routine) 1021 ((init_term_function)image->term_routine)(image->id); 1022 1023 image_event(image, IMAGE_EVENT_UNLOADING); 1024 } 1025 TRACE(("%ld: term done.\n", find_thread(NULL))); 1026 1027 free(termList); 1028 } 1029 1030 1031 void 1032 rldelf_init(void) 1033 { 1034 init_add_ons(); 1035 1036 // create the debug area 1037 { 1038 size_t size = TO_PAGE_SIZE(sizeof(runtime_loader_debug_area)); 1039 1040 runtime_loader_debug_area *area; 1041 area_id areaID = _kern_create_area(RUNTIME_LOADER_DEBUG_AREA_NAME, 1042 (void **)&area, B_RANDOMIZED_ANY_ADDRESS, size, B_NO_LOCK, 1043 B_READ_AREA | B_WRITE_AREA); 1044 if (areaID < B_OK) { 1045 FATAL("Failed to create debug area.\n"); 1046 _kern_loading_app_failed(areaID); 1047 } 1048 1049 area->loaded_images = &get_loaded_images(); 1050 } 1051 1052 // initialize error message if needed 1053 if (report_errors()) { 1054 void *buffer = malloc(1024); 1055 if (buffer == NULL) 1056 return; 1057 1058 gErrorMessage.SetTo(buffer, 1024, 'Rler'); 1059 } 1060 } 1061 1062 1063 status_t 1064 elf_reinit_after_fork(void) 1065 { 1066 recursive_lock_init(&sLock, kLockName); 1067 1068 // We also need to update the IDs of our images. We are the child and 1069 // and have cloned images with different IDs. Since in most cases (fork() 1070 // + exec*()) this would just increase the fork() overhead with no one 1071 // caring, we do that lazily, when first doing something different. 1072 gInvalidImageIDs = true; 1073 1074 return B_OK; 1075 } 1076