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