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