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