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