1 /* 2 * Copyright 2008, 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 <runtime_loader.h> 23 #include <syscalls.h> 24 #include <user_runtime.h> 25 #include <util/DoublyLinkedList.h> 26 #include <util/kernel_cpp.h> 27 #include <util/KMessage.h> 28 #include <vm_defs.h> 29 30 #include "tracing_config.h" 31 32 33 //#define TRACE_RLD 34 #ifdef TRACE_RLD 35 # define TRACE(x) dprintf x 36 #else 37 # define TRACE(x) ; 38 #endif 39 40 41 // TODO: implement better locking strategy 42 // TODO: implement lazy binding 43 44 #define PAGE_MASK (B_PAGE_SIZE - 1) 45 46 #define PAGE_OFFSET(x) ((x) & (PAGE_MASK)) 47 #define PAGE_BASE(x) ((x) & ~(PAGE_MASK)) 48 #define TO_PAGE_SIZE(x) ((x + (PAGE_MASK)) & ~(PAGE_MASK)) 49 50 #define RLD_PROGRAM_BASE 0x00200000 51 /* keep in sync with app ldscript */ 52 53 // a handle returned by load_library() (dlopen()) 54 #define RLD_GLOBAL_SCOPE ((void*)-2l) 55 56 enum { 57 // the lower two bits are reserved for RTLD_NOW and RTLD_GLOBAL 58 59 RFLAG_RW = 0x0010, 60 RFLAG_ANON = 0x0020, 61 62 RFLAG_TERMINATED = 0x0200, 63 RFLAG_INITIALIZED = 0x0400, 64 RFLAG_SYMBOLIC = 0x0800, 65 RFLAG_RELOCATED = 0x1000, 66 RFLAG_PROTECTED = 0x2000, 67 RFLAG_DEPENDENCIES_LOADED = 0x4000, 68 RFLAG_REMAPPED = 0x8000, 69 70 RFLAG_VISITED = 0x10000, 71 RFLAG_USE_FOR_RESOLVING = 0x20000 72 // temporarily set in the symbol resolution code 73 }; 74 75 76 #define IMAGE_TYPE_TO_MASK(type) (1 << ((type) - 1)) 77 #define ALL_IMAGE_TYPES (IMAGE_TYPE_TO_MASK(B_APP_IMAGE) \ 78 | IMAGE_TYPE_TO_MASK(B_LIBRARY_IMAGE) \ 79 | IMAGE_TYPE_TO_MASK(B_ADD_ON_IMAGE) \ 80 | IMAGE_TYPE_TO_MASK(B_SYSTEM_IMAGE)) 81 #define APP_OR_LIBRARY_TYPE (IMAGE_TYPE_TO_MASK(B_APP_IMAGE) \ 82 | IMAGE_TYPE_TO_MASK(B_LIBRARY_IMAGE)) 83 84 typedef void (*init_term_function)(image_id); 85 86 87 // image events 88 enum { 89 IMAGE_EVENT_LOADED, 90 IMAGE_EVENT_RELOCATED, 91 IMAGE_EVENT_INITIALIZED, 92 IMAGE_EVENT_UNINITIALIZING, 93 IMAGE_EVENT_UNLOADING 94 }; 95 96 97 struct RuntimeLoaderAddOn 98 : public DoublyLinkedListLinkImpl<RuntimeLoaderAddOn> { 99 image_t* image; 100 runtime_loader_add_on* addOn; 101 102 RuntimeLoaderAddOn(image_t* image, runtime_loader_add_on* addOn) 103 : 104 image(image), 105 addOn(addOn) 106 { 107 } 108 }; 109 110 typedef DoublyLinkedList<RuntimeLoaderAddOn> AddOnList; 111 112 struct RuntimeLoaderSymbolPatcher { 113 RuntimeLoaderSymbolPatcher* next; 114 runtime_loader_symbol_patcher* patcher; 115 void* cookie; 116 117 RuntimeLoaderSymbolPatcher(runtime_loader_symbol_patcher* patcher, 118 void* cookie) 119 : 120 patcher(patcher), 121 cookie(cookie) 122 { 123 } 124 }; 125 126 127 static image_queue_t sLoadedImages = {0, 0}; 128 static image_queue_t sDisposableImages = {0, 0}; 129 static uint32 sLoadedImageCount = 0; 130 static image_t *sProgramImage; 131 static KMessage sErrorMessage; 132 static bool sProgramLoaded = false; 133 static const char *sSearchPathSubDir = NULL; 134 static bool sInvalidImageIDs; 135 static image_t **sPreloadedImages = NULL; 136 static uint32 sPreloadedImageCount = 0; 137 static AddOnList sAddOns; 138 139 // a recursive lock 140 static sem_id sSem; 141 static thread_id sSemOwner; 142 static int32 sSemCount; 143 144 extern runtime_loader_add_on_export gRuntimeLoaderAddOnExport; 145 146 147 void 148 dprintf(const char *format, ...) 149 { 150 char buffer[1024]; 151 152 va_list list; 153 va_start(list, format); 154 155 vsnprintf(buffer, sizeof(buffer), format, list); 156 _kern_debug_output(buffer); 157 158 va_end(list); 159 } 160 161 #define FATAL(x...) \ 162 do { \ 163 dprintf("runtime_loader: " x); \ 164 if (!sProgramLoaded) \ 165 printf("runtime_loader: " x); \ 166 } while (false) 167 168 169 /*! Mini atoi(), so we don't have to include the libroot dependencies. 170 */ 171 int 172 atoi(const char* num) 173 { 174 int result = 0; 175 while (*num >= '0' && *num <= '9') { 176 result = (result * 10) + (*num - '0'); 177 num++; 178 } 179 180 return result; 181 } 182 183 184 #if RUNTIME_LOADER_TRACING 185 186 void 187 ktrace_printf(const char *format, ...) 188 { 189 va_list list; 190 va_start(list, format); 191 192 char buffer[1024]; 193 vsnprintf(buffer, sizeof(buffer), format, list); 194 _kern_ktrace_output(buffer); 195 196 va_end(list); 197 } 198 199 #define KTRACE(x...) ktrace_printf(x) 200 201 #else 202 # define KTRACE(x...) 203 #endif // RUNTIME_LOADER_TRACING 204 205 206 static void 207 rld_unlock() 208 { 209 if (sSemCount-- == 1) { 210 sSemOwner = -1; 211 release_sem(sSem); 212 } 213 } 214 215 216 static void 217 rld_lock() 218 { 219 thread_id self = find_thread(NULL); 220 if (self != sSemOwner) { 221 acquire_sem(sSem); 222 sSemOwner = self; 223 } 224 sSemCount++; 225 } 226 227 228 static void 229 enqueue_image(image_queue_t *queue, image_t *image) 230 { 231 image->next = 0; 232 233 image->prev = queue->tail; 234 if (queue->tail) 235 queue->tail->next = image; 236 237 queue->tail = image; 238 if (!queue->head) 239 queue->head = image; 240 } 241 242 243 static void 244 dequeue_image(image_queue_t *queue, image_t *image) 245 { 246 if (image->next) 247 image->next->prev = image->prev; 248 else 249 queue->tail = image->prev; 250 251 if (image->prev) 252 image->prev->next = image->next; 253 else 254 queue->head = image->next; 255 256 image->prev = 0; 257 image->next = 0; 258 } 259 260 261 static uint32 262 elf_hash(const uint8 *name) 263 { 264 uint32 hash = 0; 265 uint32 temp; 266 267 while (*name) { 268 hash = (hash << 4) + *name++; 269 if ((temp = hash & 0xf0000000)) { 270 hash ^= temp >> 24; 271 } 272 hash &= ~temp; 273 } 274 return hash; 275 } 276 277 278 static inline bool 279 report_errors() 280 { 281 return gProgramArgs->error_port >= 0; 282 } 283 284 285 //! Remaps the image ID of \a image after fork. 286 static status_t 287 update_image_id(image_t *image) 288 { 289 int32 cookie = 0; 290 image_info info; 291 while (_kern_get_next_image_info(B_CURRENT_TEAM, &cookie, &info, 292 sizeof(image_info)) == B_OK) { 293 for (uint32 i = 0; i < image->num_regions; i++) { 294 if (image->regions[i].vmstart == (addr_t)info.text) { 295 image->id = info.id; 296 return B_OK; 297 } 298 } 299 } 300 301 FATAL("Could not update image ID %ld after fork()!\n", image->id); 302 return B_ENTRY_NOT_FOUND; 303 } 304 305 306 //! After fork, we lazily rebuild the image IDs of all loaded images. 307 static status_t 308 update_image_ids(void) 309 { 310 for (image_t *image = sLoadedImages.head; image; image = image->next) { 311 status_t status = update_image_id(image); 312 if (status != B_OK) 313 return status; 314 } 315 for (image_t *image = sDisposableImages.head; image; image = image->next) { 316 status_t status = update_image_id(image); 317 if (status != B_OK) 318 return status; 319 } 320 321 sInvalidImageIDs = false; 322 return B_OK; 323 } 324 325 326 static image_t * 327 find_image_in_queue(image_queue_t *queue, const char *name, bool isPath, 328 uint32 typeMask) 329 { 330 for (image_t *image = queue->head; image; image = image->next) { 331 const char *imageName = isPath ? image->path : image->name; 332 int length = isPath ? sizeof(image->path) : sizeof(image->name); 333 334 if (!strncmp(imageName, name, length) 335 && (typeMask & IMAGE_TYPE_TO_MASK(image->type)) != 0) { 336 return image; 337 } 338 } 339 340 return NULL; 341 } 342 343 344 static image_t * 345 find_image(char const *name, uint32 typeMask) 346 { 347 bool isPath = strchr(name, '/') != NULL; 348 return find_image_in_queue(&sLoadedImages, name, isPath, typeMask); 349 } 350 351 352 static image_t * 353 find_loaded_image_by_id(image_id id) 354 { 355 if (sInvalidImageIDs) { 356 // After fork, we lazily rebuild the image IDs of all loaded images 357 update_image_ids(); 358 } 359 360 for (image_t *image = sLoadedImages.head; image; image = image->next) { 361 if (image->id == id) 362 return image; 363 } 364 365 // For the termination routine, we need to look into the list of 366 // disposable images as well 367 for (image_t *image = sDisposableImages.head; image; image = image->next) { 368 if (image->id == id) 369 return image; 370 } 371 372 return NULL; 373 } 374 375 376 static image_t* 377 get_program_image() 378 { 379 for (image_t *image = sLoadedImages.head; image; image = image->next) { 380 if (image->type == B_APP_IMAGE) 381 return image; 382 } 383 384 return NULL; 385 } 386 387 388 static const char * 389 get_program_path() 390 { 391 if (image_t* image = get_program_image()) 392 return image->path; 393 394 return NULL; 395 } 396 397 398 static status_t 399 parse_elf_header(struct Elf32_Ehdr *eheader, int32 *_pheaderSize, 400 int32 *_sheaderSize) 401 { 402 if (memcmp(eheader->e_ident, ELF_MAGIC, 4) != 0) 403 return B_NOT_AN_EXECUTABLE; 404 405 if (eheader->e_ident[4] != ELFCLASS32) 406 return B_NOT_AN_EXECUTABLE; 407 408 if (eheader->e_phoff == 0) 409 return B_NOT_AN_EXECUTABLE; 410 411 if (eheader->e_phentsize < sizeof(struct Elf32_Phdr)) 412 return B_NOT_AN_EXECUTABLE; 413 414 *_pheaderSize = eheader->e_phentsize * eheader->e_phnum; 415 *_sheaderSize = eheader->e_shentsize * eheader->e_shnum; 416 417 if (*_pheaderSize <= 0 || *_sheaderSize <= 0) 418 return B_NOT_AN_EXECUTABLE; 419 420 return B_OK; 421 } 422 423 424 static int32 425 count_regions(char const *buff, int phnum, int phentsize) 426 { 427 struct Elf32_Phdr *pheaders; 428 int32 count = 0; 429 int i; 430 431 for (i = 0; i < phnum; i++) { 432 pheaders = (struct Elf32_Phdr *)(buff + i * phentsize); 433 434 switch (pheaders->p_type) { 435 case PT_NULL: 436 /* NOP header */ 437 break; 438 case PT_LOAD: 439 count += 1; 440 if (pheaders->p_memsz != pheaders->p_filesz) { 441 addr_t A = TO_PAGE_SIZE(pheaders->p_vaddr + pheaders->p_memsz); 442 addr_t B = TO_PAGE_SIZE(pheaders->p_vaddr + pheaders->p_filesz); 443 444 if (A != B) 445 count += 1; 446 } 447 break; 448 case PT_DYNAMIC: 449 /* will be handled at some other place */ 450 break; 451 case PT_INTERP: 452 /* should check here for appropiate interpreter */ 453 break; 454 case PT_NOTE: 455 /* unsupported */ 456 break; 457 case PT_SHLIB: 458 /* undefined semantics */ 459 break; 460 case PT_PHDR: 461 /* we don't use it */ 462 break; 463 default: 464 FATAL("unhandled pheader type 0x%lx\n", pheaders[i].p_type); 465 return B_BAD_DATA; 466 } 467 } 468 469 return count; 470 } 471 472 473 static image_t * 474 create_image(const char *name, const char *path, int num_regions) 475 { 476 size_t allocSize = sizeof(image_t) + (num_regions - 1) * sizeof(elf_region_t); 477 const char *lastSlash; 478 479 image_t *image = (image_t*)malloc(allocSize); 480 if (image == NULL) { 481 FATAL("no memory for image %s\n", path); 482 return NULL; 483 } 484 485 memset(image, 0, allocSize); 486 487 strlcpy(image->path, path, sizeof(image->path)); 488 489 // Make the last component of the supplied name the image name. 490 // If present, DT_SONAME will replace this name. 491 if ((lastSlash = strrchr(name, '/'))) 492 strlcpy(image->name, lastSlash + 1, sizeof(image->name)); 493 else 494 strlcpy(image->name, name, sizeof(image->name)); 495 496 image->ref_count = 1; 497 image->num_regions = num_regions; 498 499 return image; 500 } 501 502 503 static void 504 delete_image_struct(image_t *image) 505 { 506 #ifdef DEBUG 507 size_t size = sizeof(image_t) + (image->num_regions - 1) * sizeof(elf_region_t); 508 memset(image->needed, 0xa5, sizeof(image->needed[0]) * image->num_needed); 509 #endif 510 free(image->needed); 511 512 while (RuntimeLoaderSymbolPatcher* patcher 513 = image->defined_symbol_patchers) { 514 image->defined_symbol_patchers = patcher->next; 515 delete patcher; 516 } 517 while (RuntimeLoaderSymbolPatcher* patcher 518 = image->undefined_symbol_patchers) { 519 image->undefined_symbol_patchers = patcher->next; 520 delete patcher; 521 } 522 523 #ifdef DEBUG 524 // overwrite images to make sure they aren't accidently reused anywhere 525 memset(image, 0xa5, size); 526 #endif 527 free(image); 528 } 529 530 531 static void 532 delete_image(image_t *image) 533 { 534 if (image == NULL) 535 return; 536 537 _kern_unregister_image(image->id); 538 // registered in load_container() 539 540 delete_image_struct(image); 541 } 542 543 544 static void 545 update_image_flags_recursively(image_t* image, uint32 flagsToSet, 546 uint32 flagsToClear) 547 { 548 image_t* queue[sLoadedImageCount]; 549 uint32 count = 0; 550 uint32 index = 0; 551 queue[count++] = image; 552 image->flags |= RFLAG_VISITED; 553 554 while (index < count) { 555 // pop next image 556 image = queue[index++]; 557 558 // push dependencies 559 for (uint32 i = 0; i < image->num_needed; i++) { 560 image_t* needed = image->needed[i]; 561 if ((needed->flags & RFLAG_VISITED) == 0) { 562 queue[count++] = needed; 563 needed->flags |= RFLAG_VISITED; 564 } 565 } 566 } 567 568 // update flags 569 for (uint32 i = 0; i < count; i++) { 570 queue[i]->flags = (queue[i]->flags | flagsToSet) 571 & ~(flagsToClear | RFLAG_VISITED); 572 } 573 } 574 575 576 static void 577 set_image_flags_recursively(image_t* image, uint32 flags) 578 { 579 update_image_flags_recursively(image, flags, 0); 580 } 581 582 583 static void 584 clear_image_flags_recursively(image_t* image, uint32 flags) 585 { 586 update_image_flags_recursively(image, 0, flags); 587 } 588 589 590 static status_t 591 parse_program_headers(image_t *image, char *buff, int phnum, int phentsize) 592 { 593 struct Elf32_Phdr *pheader; 594 int regcount; 595 int i; 596 597 regcount = 0; 598 for (i = 0; i < phnum; i++) { 599 pheader = (struct Elf32_Phdr *)(buff + i * phentsize); 600 601 switch (pheader->p_type) { 602 case PT_NULL: 603 /* NOP header */ 604 break; 605 case PT_LOAD: 606 if (pheader->p_memsz == pheader->p_filesz) { 607 /* 608 * everything in one area 609 */ 610 image->regions[regcount].start = pheader->p_vaddr; 611 image->regions[regcount].size = pheader->p_memsz; 612 image->regions[regcount].vmstart = PAGE_BASE(pheader->p_vaddr); 613 image->regions[regcount].vmsize = TO_PAGE_SIZE(pheader->p_memsz 614 + PAGE_OFFSET(pheader->p_vaddr)); 615 image->regions[regcount].fdstart = pheader->p_offset; 616 image->regions[regcount].fdsize = pheader->p_filesz; 617 image->regions[regcount].delta = 0; 618 image->regions[regcount].flags = 0; 619 if (pheader->p_flags & PF_WRITE) { 620 // this is a writable segment 621 image->regions[regcount].flags |= RFLAG_RW; 622 } 623 } else { 624 /* 625 * may require splitting 626 */ 627 addr_t A = TO_PAGE_SIZE(pheader->p_vaddr + pheader->p_memsz); 628 addr_t B = TO_PAGE_SIZE(pheader->p_vaddr + pheader->p_filesz); 629 630 image->regions[regcount].start = pheader->p_vaddr; 631 image->regions[regcount].size = pheader->p_filesz; 632 image->regions[regcount].vmstart = PAGE_BASE(pheader->p_vaddr); 633 image->regions[regcount].vmsize = TO_PAGE_SIZE(pheader->p_filesz 634 + PAGE_OFFSET(pheader->p_vaddr)); 635 image->regions[regcount].fdstart = pheader->p_offset; 636 image->regions[regcount].fdsize = pheader->p_filesz; 637 image->regions[regcount].delta = 0; 638 image->regions[regcount].flags = 0; 639 if (pheader->p_flags & PF_WRITE) { 640 // this is a writable segment 641 image->regions[regcount].flags |= RFLAG_RW; 642 } 643 644 if (A != B) { 645 /* 646 * yeah, it requires splitting 647 */ 648 regcount += 1; 649 image->regions[regcount].start = pheader->p_vaddr; 650 image->regions[regcount].size = pheader->p_memsz - pheader->p_filesz; 651 image->regions[regcount].vmstart = image->regions[regcount-1].vmstart + image->regions[regcount-1].vmsize; 652 image->regions[regcount].vmsize = TO_PAGE_SIZE(pheader->p_memsz + PAGE_OFFSET(pheader->p_vaddr)) 653 - image->regions[regcount-1].vmsize; 654 image->regions[regcount].fdstart = 0; 655 image->regions[regcount].fdsize = 0; 656 image->regions[regcount].delta = 0; 657 image->regions[regcount].flags = RFLAG_ANON; 658 if (pheader->p_flags & PF_WRITE) { 659 // this is a writable segment 660 image->regions[regcount].flags |= RFLAG_RW; 661 } 662 } 663 } 664 regcount += 1; 665 break; 666 case PT_DYNAMIC: 667 image->dynamic_ptr = pheader->p_vaddr; 668 break; 669 case PT_INTERP: 670 /* should check here for appropiate interpreter */ 671 break; 672 case PT_NOTE: 673 /* unsupported */ 674 break; 675 case PT_SHLIB: 676 /* undefined semantics */ 677 break; 678 case PT_PHDR: 679 /* we don't use it */ 680 break; 681 default: 682 FATAL("unhandled pheader type 0x%lx\n", pheader[i].p_type); 683 return B_BAD_DATA; 684 } 685 } 686 687 return B_OK; 688 } 689 690 691 static bool 692 analyze_object_gcc_version(int fd, image_t* image, Elf32_Ehdr& eheader, 693 int32 sheaderSize, char* buffer, size_t bufferSize) 694 { 695 image->gcc_version.major = 0; 696 image->gcc_version.middle = 0; 697 image->gcc_version.minor = 0; 698 699 if (sheaderSize > (int)bufferSize) { 700 FATAL("Cannot handle section headers bigger than %lu\n", bufferSize); 701 return false; 702 } 703 704 // read section headers 705 ssize_t length = _kern_read(fd, eheader.e_shoff, buffer, sheaderSize); 706 if (length != sheaderSize) { 707 FATAL("Could not read section headers: %s\n", strerror(length)); 708 return false; 709 } 710 711 // load the string section 712 Elf32_Shdr* sectionHeader 713 = (Elf32_Shdr*)(buffer + eheader.e_shstrndx * eheader.e_shentsize); 714 715 if (sheaderSize + sectionHeader->sh_size > bufferSize) { 716 FATAL("Buffer not big enough for section string section\n"); 717 return false; 718 } 719 720 char* sectionStrings = buffer + bufferSize - sectionHeader->sh_size; 721 length = _kern_read(fd, sectionHeader->sh_offset, sectionStrings, 722 sectionHeader->sh_size); 723 if (length != (int)sectionHeader->sh_size) { 724 FATAL("Could not read section string section: %s\n", strerror(length)); 725 return false; 726 } 727 728 // find the .comment section 729 off_t commentOffset = 0; 730 size_t commentSize = 0; 731 for (uint32 i = 0; i < eheader.e_shnum; i++) { 732 sectionHeader = (Elf32_Shdr*)(buffer + i * eheader.e_shentsize); 733 const char* sectionName = sectionStrings + sectionHeader->sh_name; 734 if (sectionHeader->sh_name != 0 735 && strcmp(sectionName, ".comment") == 0) { 736 commentOffset = sectionHeader->sh_offset; 737 commentSize = sectionHeader->sh_size; 738 break; 739 } 740 } 741 742 if (commentSize == 0) { 743 FATAL("Could not find .comment section\n"); 744 return false; 745 } 746 747 // read a part of the comment section 748 if (commentSize > 512) 749 commentSize = 512; 750 751 length = _kern_read(fd, commentOffset, buffer, commentSize); 752 if (length != (int)commentSize) { 753 FATAL("Could not read .comment section: %s\n", strerror(length)); 754 return false; 755 } 756 757 // the common prefix of the strings in the .comment section 758 static const char* kGCCVersionPrefix = "GCC: (GNU) "; 759 size_t gccVersionPrefixLen = strlen(kGCCVersionPrefix); 760 761 size_t index = 0; 762 int gccMajor = 0; 763 int gccMiddle = 0; 764 int gccMinor = 0; 765 bool isHaiku = true; 766 767 // Read up to 10 comments. The first three or four are usually from the 768 // glue code. 769 for (int i = 0; i < 10; i++) { 770 // skip '\0' 771 while (index < commentSize && buffer[index] == '\0') 772 index++; 773 char* stringStart = buffer + index; 774 775 // find string end 776 while (index < commentSize && buffer[index] != '\0') 777 index++; 778 779 // ignore the entry at the end of the buffer 780 if (index == commentSize) 781 break; 782 783 // We have to analyze string like these: 784 // GCC: (GNU) 2.9-beos-991026 785 // GCC: (GNU) 2.95.3-haiku-080322 786 // GCC: (GNU) 4.1.2 787 788 // skip the common prefix 789 if (strncmp(stringStart, kGCCVersionPrefix, gccVersionPrefixLen) != 0) 790 continue; 791 792 // the rest is the GCC version 793 char* gccVersion = stringStart + gccVersionPrefixLen; 794 char* gccPlatform = strchr(gccVersion, '-'); 795 char* patchLevel = NULL; 796 if (gccPlatform != NULL) { 797 *gccPlatform = '\0'; 798 gccPlatform++; 799 patchLevel = strchr(gccPlatform, '-'); 800 if (patchLevel != NULL) { 801 *patchLevel = '\0'; 802 patchLevel++; 803 } 804 } 805 806 // split the gcc version into major, middle, and minor 807 int version[3] = { 0, 0, 0 }; 808 809 for (int k = 0; gccVersion != NULL && k < 3; k++) { 810 char* dot = strchr(gccVersion, '.'); 811 if (dot) { 812 *dot = '\0'; 813 dot++; 814 } 815 version[k] = atoi(gccVersion); 816 gccVersion = dot; 817 } 818 819 // got any version? 820 if (version[0] == 0) 821 continue; 822 823 // Select the gcc version with the smallest major, but the greatest 824 // middle/minor. This should usually ignore the glue code version as 825 // well as cases where e.g. in a gcc 2 program a single C file has 826 // been compiled with gcc 4. 827 if (gccMajor == 0 || gccMajor > version[0] 828 || gccMajor == version[0] 829 && (gccMiddle < version[1] 830 || gccMiddle == version[1] && gccMinor < version[2])) { 831 gccMajor = version[0]; 832 gccMiddle = version[1]; 833 gccMinor = version[2]; 834 } 835 836 if (gccMajor == 2 && gccPlatform != NULL && strcmp(gccPlatform, "haiku")) 837 isHaiku = false; 838 } 839 840 image->gcc_version.major = gccMajor; 841 image->gcc_version.middle = gccMiddle; 842 image->gcc_version.minor = gccMinor; 843 image->gcc_version.haiku = isHaiku; 844 845 return gccMajor != 0; 846 } 847 848 849 static bool 850 assert_dynamic_loadable(image_t *image) 851 { 852 uint32 i; 853 854 if (!image->dynamic_ptr) 855 return true; 856 857 for (i = 0; i < image->num_regions; i++) { 858 if (image->dynamic_ptr >= image->regions[i].start 859 && image->dynamic_ptr < image->regions[i].start + image->regions[i].size) 860 return true; 861 } 862 863 return false; 864 } 865 866 867 /** This function will change the protection of all read-only segments 868 * to really be read-only. 869 * The areas have to be read/write first, so that they can be relocated. 870 */ 871 872 static void 873 remap_images(void) 874 { 875 image_t *image; 876 uint32 i; 877 878 for (image = sLoadedImages.head; image != NULL; image = image->next) { 879 for (i = 0; i < image->num_regions; i++) { 880 if ((image->regions[i].flags & RFLAG_RW) == 0 881 && (image->regions[i].flags & RFLAG_REMAPPED) == 0) { 882 // we only need to do this once, so we remember those we've already mapped 883 if (_kern_set_area_protection(image->regions[i].id, 884 B_READ_AREA | B_EXECUTE_AREA) == B_OK) 885 image->regions[i].flags |= RFLAG_REMAPPED; 886 } 887 } 888 } 889 } 890 891 892 static status_t 893 map_image(int fd, char const *path, image_t *image, bool fixed) 894 { 895 status_t status = B_OK; 896 const char *baseName; 897 uint32 i; 898 899 (void)(fd); 900 901 // cut the file name from the path as base name for the created areas 902 baseName = strrchr(path, '/'); 903 if (baseName != NULL) 904 baseName++; 905 else 906 baseName = path; 907 908 for (i = 0; i < image->num_regions; i++) { 909 char regionName[B_OS_NAME_LENGTH]; 910 addr_t loadAddress; 911 uint32 addressSpecifier; 912 913 // for BeOS compatibility: if we load an old BeOS executable, we 914 // have to relocate it, if possible - we recognize it because the 915 // vmstart is set to 0 (hopefully always) 916 if (fixed && image->regions[i].vmstart == 0) 917 fixed = false; 918 919 snprintf(regionName, sizeof(regionName), "%s_seg%lu%s", 920 baseName, i, (image->regions[i].flags & RFLAG_RW) ? "rw" : "ro"); 921 922 if (image->dynamic_ptr && !fixed) { 923 // relocatable image... we can afford to place wherever 924 if (i == 0) { 925 // but only the first segment gets a free ride 926 loadAddress = RLD_PROGRAM_BASE; 927 addressSpecifier = B_BASE_ADDRESS; 928 } else { 929 loadAddress = image->regions[i].vmstart + image->regions[i-1].delta; 930 addressSpecifier = B_EXACT_ADDRESS; 931 } 932 } else { 933 // not relocatable, put it where it asks or die trying 934 loadAddress = image->regions[i].vmstart; 935 addressSpecifier = B_EXACT_ADDRESS; 936 } 937 938 if (image->regions[i].flags & RFLAG_ANON) { 939 image->regions[i].id = _kern_create_area(regionName, (void **)&loadAddress, 940 addressSpecifier, image->regions[i].vmsize, B_NO_LOCK, 941 B_READ_AREA | B_WRITE_AREA); 942 943 if (image->regions[i].id < 0) { 944 status = image->regions[i].id; 945 goto error; 946 } 947 948 image->regions[i].delta = loadAddress - image->regions[i].vmstart; 949 image->regions[i].vmstart = loadAddress; 950 } else { 951 image->regions[i].id = _kern_map_file(regionName, 952 (void **)&loadAddress, addressSpecifier, 953 image->regions[i].vmsize, B_READ_AREA | B_WRITE_AREA, 954 REGION_PRIVATE_MAP, fd, PAGE_BASE(image->regions[i].fdstart)); 955 956 if (image->regions[i].id < 0) { 957 status = image->regions[i].id; 958 goto error; 959 } 960 961 TRACE(("\"%s\" at %p, 0x%lx bytes (%s)\n", path, 962 (void *)loadAddress, image->regions[i].vmsize, 963 image->regions[i].flags & RFLAG_RW ? "rw" : "read-only")); 964 965 image->regions[i].delta = loadAddress - image->regions[i].vmstart; 966 image->regions[i].vmstart = loadAddress; 967 968 // handle trailer bits in data segment 969 if (image->regions[i].flags & RFLAG_RW) { 970 addr_t startClearing; 971 addr_t toClear; 972 973 startClearing = image->regions[i].vmstart 974 + PAGE_OFFSET(image->regions[i].start) 975 + image->regions[i].size; 976 toClear = image->regions[i].vmsize 977 - PAGE_OFFSET(image->regions[i].start) 978 - image->regions[i].size; 979 980 TRACE(("cleared 0x%lx and the following 0x%lx bytes\n", startClearing, toClear)); 981 memset((void *)startClearing, 0, toClear); 982 } 983 } 984 } 985 986 if (image->dynamic_ptr) 987 image->dynamic_ptr += image->regions[0].delta; 988 989 return B_OK; 990 991 error: 992 return status; 993 } 994 995 996 static void 997 unmap_image(image_t *image) 998 { 999 uint32 i; 1000 1001 for (i = 0; i < image->num_regions; i++) { 1002 _kern_delete_area(image->regions[i].id); 1003 1004 image->regions[i].id = -1; 1005 } 1006 } 1007 1008 1009 static bool 1010 parse_dynamic_segment(image_t *image) 1011 { 1012 struct Elf32_Dyn *d; 1013 int i; 1014 int sonameOffset = -1; 1015 1016 image->symhash = 0; 1017 image->syms = 0; 1018 image->strtab = 0; 1019 1020 d = (struct Elf32_Dyn *)image->dynamic_ptr; 1021 if (!d) 1022 return true; 1023 1024 for (i = 0; d[i].d_tag != DT_NULL; i++) { 1025 switch (d[i].d_tag) { 1026 case DT_NEEDED: 1027 image->num_needed += 1; 1028 break; 1029 case DT_HASH: 1030 image->symhash = (uint32 *)(d[i].d_un.d_ptr + image->regions[0].delta); 1031 break; 1032 case DT_STRTAB: 1033 image->strtab = (char *)(d[i].d_un.d_ptr + image->regions[0].delta); 1034 break; 1035 case DT_SYMTAB: 1036 image->syms = (struct Elf32_Sym *)(d[i].d_un.d_ptr + image->regions[0].delta); 1037 break; 1038 case DT_REL: 1039 image->rel = (struct Elf32_Rel *)(d[i].d_un.d_ptr + image->regions[0].delta); 1040 break; 1041 case DT_RELSZ: 1042 image->rel_len = d[i].d_un.d_val; 1043 break; 1044 case DT_RELA: 1045 image->rela = (struct Elf32_Rela *)(d[i].d_un.d_ptr + image->regions[0].delta); 1046 break; 1047 case DT_RELASZ: 1048 image->rela_len = d[i].d_un.d_val; 1049 break; 1050 // TK: procedure linkage table 1051 case DT_JMPREL: 1052 image->pltrel = (struct Elf32_Rel *)(d[i].d_un.d_ptr + image->regions[0].delta); 1053 break; 1054 case DT_PLTRELSZ: 1055 image->pltrel_len = d[i].d_un.d_val; 1056 break; 1057 case DT_INIT: 1058 image->init_routine = (d[i].d_un.d_ptr + image->regions[0].delta); 1059 break; 1060 case DT_FINI: 1061 image->term_routine = (d[i].d_un.d_ptr + image->regions[0].delta); 1062 break; 1063 case DT_SONAME: 1064 sonameOffset = d[i].d_un.d_val; 1065 break; 1066 default: 1067 continue; 1068 } 1069 } 1070 1071 // lets make sure we found all the required sections 1072 if (!image->symhash || !image->syms || !image->strtab) 1073 return false; 1074 1075 if (sonameOffset >= 0) 1076 strlcpy(image->name, STRING(image, sonameOffset), sizeof(image->name)); 1077 1078 return true; 1079 } 1080 1081 1082 static void 1083 patch_defined_symbol(image_t* image, const char* name, void** symbol, 1084 int32* type) 1085 { 1086 RuntimeLoaderSymbolPatcher* patcher = image->defined_symbol_patchers; 1087 while (patcher != NULL && *symbol != 0) { 1088 image_t* inImage = image; 1089 patcher->patcher(patcher->cookie, NULL, image, name, &inImage, 1090 symbol, type); 1091 patcher = patcher->next; 1092 } 1093 } 1094 1095 1096 static void 1097 patch_undefined_symbol(image_t* rootImage, image_t* image, const char* name, 1098 image_t** foundInImage, void** symbol, int32* type) 1099 { 1100 if (*foundInImage != NULL) 1101 patch_defined_symbol(*foundInImage, name, symbol, type); 1102 1103 RuntimeLoaderSymbolPatcher* patcher = image->undefined_symbol_patchers; 1104 while (patcher != NULL) { 1105 patcher->patcher(patcher->cookie, rootImage, image, name, foundInImage, 1106 symbol, type); 1107 patcher = patcher->next; 1108 } 1109 } 1110 1111 1112 status_t 1113 register_defined_symbol_patcher(struct image_t* image, 1114 runtime_loader_symbol_patcher* _patcher, void* cookie) 1115 { 1116 RuntimeLoaderSymbolPatcher* patcher 1117 = new(mynothrow) RuntimeLoaderSymbolPatcher(_patcher, cookie); 1118 if (patcher == NULL) 1119 return B_NO_MEMORY; 1120 1121 patcher->next = image->defined_symbol_patchers; 1122 image->defined_symbol_patchers = patcher; 1123 1124 return B_OK; 1125 } 1126 1127 1128 void 1129 unregister_defined_symbol_patcher(struct image_t* image, 1130 runtime_loader_symbol_patcher* _patcher, void* cookie) 1131 { 1132 RuntimeLoaderSymbolPatcher** patcher = &image->defined_symbol_patchers; 1133 while (*patcher != NULL) { 1134 if ((*patcher)->patcher == _patcher && (*patcher)->cookie == cookie) { 1135 RuntimeLoaderSymbolPatcher* toDelete = *patcher; 1136 *patcher = (*patcher)->next; 1137 delete toDelete; 1138 return; 1139 } 1140 patcher = &(*patcher)->next; 1141 } 1142 } 1143 1144 1145 status_t 1146 register_undefined_symbol_patcher(struct image_t* image, 1147 runtime_loader_symbol_patcher* _patcher, void* cookie) 1148 { 1149 RuntimeLoaderSymbolPatcher* patcher 1150 = new(mynothrow) RuntimeLoaderSymbolPatcher(_patcher, cookie); 1151 if (patcher == NULL) 1152 return B_NO_MEMORY; 1153 1154 patcher->next = image->undefined_symbol_patchers; 1155 image->undefined_symbol_patchers = patcher; 1156 1157 return B_OK; 1158 } 1159 1160 1161 void 1162 unregister_undefined_symbol_patcher(struct image_t* image, 1163 runtime_loader_symbol_patcher* _patcher, void* cookie) 1164 { 1165 RuntimeLoaderSymbolPatcher** patcher = &image->undefined_symbol_patchers; 1166 while (*patcher != NULL) { 1167 if ((*patcher)->patcher == _patcher && (*patcher)->cookie == cookie) { 1168 RuntimeLoaderSymbolPatcher* toDelete = *patcher; 1169 *patcher = (*patcher)->next; 1170 delete toDelete; 1171 return; 1172 } 1173 patcher = &(*patcher)->next; 1174 } 1175 } 1176 1177 1178 runtime_loader_add_on_export gRuntimeLoaderAddOnExport = { 1179 register_defined_symbol_patcher, 1180 unregister_defined_symbol_patcher, 1181 register_undefined_symbol_patcher, 1182 unregister_undefined_symbol_patcher 1183 }; 1184 1185 1186 static struct Elf32_Sym * 1187 find_symbol(image_t *image, const char *name, int32 type) 1188 { 1189 uint32 hash, i; 1190 1191 // ToDo: "type" is currently ignored! 1192 (void)type; 1193 1194 if (image->dynamic_ptr == 0) 1195 return NULL; 1196 1197 hash = elf_hash((uint8 *)name) % HASHTABSIZE(image); 1198 1199 for (i = HASHBUCKETS(image)[hash]; i != STN_UNDEF; i = HASHCHAINS(image)[i]) { 1200 struct Elf32_Sym *symbol = &image->syms[i]; 1201 1202 if (symbol->st_shndx != SHN_UNDEF 1203 && ((ELF32_ST_BIND(symbol->st_info)== STB_GLOBAL) 1204 || (ELF32_ST_BIND(symbol->st_info) == STB_WEAK)) 1205 && !strcmp(SYMNAME(image, symbol), name)) { 1206 // check if the type matches 1207 if ((type == B_SYMBOL_TYPE_TEXT && ELF32_ST_TYPE(symbol->st_info) != STT_FUNC) 1208 || (type == B_SYMBOL_TYPE_DATA && ELF32_ST_TYPE(symbol->st_info) != STT_OBJECT)) 1209 continue; 1210 1211 return symbol; 1212 } 1213 } 1214 1215 return NULL; 1216 } 1217 1218 1219 static status_t 1220 find_symbol(image_t* image, char const* symbolName, int32 symbolType, 1221 void **_location) 1222 { 1223 // get the symbol in the image 1224 struct Elf32_Sym* symbol = find_symbol(image, symbolName, symbolType); 1225 if (symbol == NULL) 1226 return B_ENTRY_NOT_FOUND; 1227 1228 void* location = (void*)(symbol->st_value + image->regions[0].delta); 1229 patch_defined_symbol(image, symbolName, &location, &symbolType); 1230 1231 if (_location != NULL) 1232 *_location = location; 1233 1234 return B_OK; 1235 } 1236 1237 1238 static status_t 1239 find_symbol_breadth_first(image_t* image, const char* name, int32 type, 1240 image_t** _foundInImage, void** _location) 1241 { 1242 image_t* queue[sLoadedImageCount]; 1243 uint32 count = 0; 1244 uint32 index = 0; 1245 queue[count++] = image; 1246 image->flags |= RFLAG_VISITED; 1247 1248 bool found = false; 1249 while (index < count) { 1250 // pop next image 1251 image = queue[index++]; 1252 1253 if (find_symbol(image, name, type, _location) == B_OK) { 1254 found = true; 1255 break; 1256 } 1257 1258 // push needed images 1259 for (uint32 i = 0; i < image->num_needed; i++) { 1260 image_t* needed = image->needed[i]; 1261 if ((needed->flags & RFLAG_VISITED) == 0) { 1262 queue[count++] = needed; 1263 needed->flags |= RFLAG_VISITED; 1264 } 1265 } 1266 } 1267 1268 // clear visited flags 1269 for (uint32 i = 0; i < count; i++) 1270 queue[i]->flags &= ~RFLAG_VISITED; 1271 1272 return found ? B_OK : B_ENTRY_NOT_FOUND; 1273 } 1274 1275 1276 static struct Elf32_Sym* 1277 find_undefined_symbol_beos(image_t* rootImage, image_t* image, const char* name, 1278 image_t** foundInImage) 1279 { 1280 // BeOS style symbol resolution: It is sufficient to check the direct 1281 // dependencies. The linker would have complained, if the symbol wasn't 1282 // there. 1283 for (uint32 i = 0; i < image->num_needed; i++) { 1284 if (image->needed[i]->dynamic_ptr) { 1285 struct Elf32_Sym *symbol = find_symbol(image->needed[i], name, 1286 B_SYMBOL_TYPE_ANY); 1287 if (symbol) { 1288 *foundInImage = image->needed[i]; 1289 return symbol; 1290 } 1291 } 1292 } 1293 1294 return NULL; 1295 } 1296 1297 1298 static struct Elf32_Sym* 1299 find_undefined_symbol_global(image_t* rootImage, image_t* image, 1300 const char* name, image_t** foundInImage) 1301 { 1302 // Global load order symbol resolution: All loaded images are searched for 1303 // the symbol in the order they have been loaded. We skip add-on images and 1304 // RTLD_LOCAL images though. 1305 image_t* otherImage = sLoadedImages.head; 1306 while (otherImage != NULL) { 1307 if (otherImage == rootImage 1308 || otherImage->type != B_ADD_ON_IMAGE 1309 && (otherImage->flags 1310 & (RTLD_GLOBAL | RFLAG_USE_FOR_RESOLVING)) != 0) { 1311 struct Elf32_Sym *symbol = find_symbol(otherImage, name, 1312 B_SYMBOL_TYPE_ANY); 1313 if (symbol) { 1314 *foundInImage = otherImage; 1315 return symbol; 1316 } 1317 } 1318 otherImage = otherImage->next; 1319 } 1320 1321 return NULL; 1322 } 1323 1324 1325 static struct Elf32_Sym* 1326 find_undefined_symbol_add_on(image_t* rootImage, image_t* image, 1327 const char* name, image_t** foundInImage) 1328 { 1329 // TODO: How do we want to implement this one? Using global scope resolution 1330 // might be undesired as it is now, since libraries could refer to symbols in 1331 // the add-on, which would result in add-on symbols implicitely becoming used 1332 // outside of the add-on. So the options would be to use the global scope but 1333 // skip the add-on, or to do breadth-first resolution in the add-on dependency 1334 // scope, also skipping the add-on itself. BeOS style resolution is safe, too, 1335 // but we miss out features like undefined symbols and preloading. 1336 return find_undefined_symbol_beos(rootImage, image, name, foundInImage); 1337 } 1338 1339 1340 /*! This function is called when we run BeOS images on Haiku. 1341 It allows us to redirect functions to ensure compatibility. 1342 */ 1343 static const char* 1344 beos_compatibility_map_symbol(const char* symbolName) 1345 { 1346 struct symbol_mapping { 1347 const char* from; 1348 const char* to; 1349 }; 1350 static const struct symbol_mapping kMappings[] = { 1351 // TODO: Improve this, and also use it for libnet.so compatibility! 1352 // Allow an image to provide a function that will be invoked for every 1353 // (transitively) depending image. The function can return a table to 1354 // remap symbols (probably better address to address). All the tables 1355 // for a single image would be combined into a hash table and an 1356 // undefined symbol patcher using this hash table would be added. 1357 {"fstat", "__be_fstat"}, 1358 {"lstat", "__be_lstat"}, 1359 {"stat", "__be_stat"}, 1360 }; 1361 const uint32 kMappingCount = sizeof(kMappings) / sizeof(kMappings[0]); 1362 1363 for (uint32 i = 0; i < kMappingCount; i++) { 1364 if (!strcmp(symbolName, kMappings[i].from)) 1365 return kMappings[i].to; 1366 } 1367 1368 return symbolName; 1369 } 1370 1371 1372 int 1373 resolve_symbol(image_t *rootImage, image_t *image, struct Elf32_Sym *sym, 1374 addr_t *symAddress) 1375 { 1376 switch (sym->st_shndx) { 1377 case SHN_UNDEF: 1378 { 1379 struct Elf32_Sym *sharedSym; 1380 image_t *sharedImage; 1381 const char *symName; 1382 1383 // patch the symbol name 1384 symName = SYMNAME(image, sym); 1385 if (!image->gcc_version.haiku) { 1386 // The image has been compiled with a BeOS compiler. This means 1387 // we'll have to redirect some functions for compatibility. 1388 symName = beos_compatibility_map_symbol(symName); 1389 } 1390 1391 int32 type = B_SYMBOL_TYPE_ANY; 1392 if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC) 1393 type = B_SYMBOL_TYPE_TEXT; 1394 else if (ELF32_ST_TYPE(sym->st_info) == STT_OBJECT) 1395 type = B_SYMBOL_TYPE_DATA; 1396 1397 // it's undefined, must be outside this image, try the other images 1398 sharedSym = rootImage->find_undefined_symbol(rootImage, image, 1399 symName, &sharedImage); 1400 void* location = NULL; 1401 1402 enum { 1403 ERROR_NO_SYMBOL, 1404 ERROR_WRONG_TYPE, 1405 ERROR_NOT_EXPORTED, 1406 ERROR_UNPATCHED 1407 }; 1408 uint32 lookupError = ERROR_UNPATCHED; 1409 1410 if (sharedSym == NULL) { 1411 // symbol not found at all 1412 lookupError = ERROR_NO_SYMBOL; 1413 sharedImage = NULL; 1414 } else if (ELF32_ST_TYPE(sym->st_info) != STT_NOTYPE 1415 && ELF32_ST_TYPE(sym->st_info) 1416 != ELF32_ST_TYPE(sharedSym->st_info)) { 1417 // symbol not of the requested type 1418 lookupError = ERROR_WRONG_TYPE; 1419 sharedImage = NULL; 1420 } else if (ELF32_ST_BIND(sharedSym->st_info) != STB_GLOBAL 1421 && ELF32_ST_BIND(sharedSym->st_info) != STB_WEAK) { 1422 // symbol not exported 1423 lookupError = ERROR_NOT_EXPORTED; 1424 sharedImage = NULL; 1425 } else { 1426 // symbol is fine, get its location 1427 location = (void*)(sharedSym->st_value 1428 + sharedImage->regions[0].delta); 1429 } 1430 1431 patch_undefined_symbol(rootImage, image, symName, &sharedImage, 1432 &location, &type); 1433 1434 if (location == NULL) { 1435 switch (lookupError) { 1436 case ERROR_NO_SYMBOL: 1437 FATAL("elf_resolve_symbol: could not resolve symbol " 1438 "'%s'\n", symName); 1439 break; 1440 case ERROR_WRONG_TYPE: 1441 FATAL("elf_resolve_symbol: found symbol '%s' in shared " 1442 "image but wrong type\n", symName); 1443 break; 1444 case ERROR_NOT_EXPORTED: 1445 FATAL("elf_resolve_symbol: found symbol '%s', but not " 1446 "exported\n", symName); 1447 break; 1448 case ERROR_UNPATCHED: 1449 FATAL("elf_resolve_symbol: found symbol '%s', but was " 1450 "hidden by symbol patchers\n", symName); 1451 break; 1452 } 1453 return B_MISSING_SYMBOL; 1454 } 1455 1456 *symAddress = (addr_t)location; 1457 return B_OK; 1458 } 1459 1460 case SHN_ABS: 1461 *symAddress = sym->st_value + image->regions[0].delta; 1462 return B_NO_ERROR; 1463 1464 case SHN_COMMON: 1465 // ToDo: finish this 1466 FATAL("elf_resolve_symbol: COMMON symbol, finish me!\n"); 1467 return B_ERROR; //ERR_NOT_IMPLEMENTED_YET; 1468 1469 default: 1470 // standard symbol 1471 *symAddress = sym->st_value + image->regions[0].delta; 1472 return B_NO_ERROR; 1473 } 1474 } 1475 1476 1477 static void 1478 image_event(image_t* image, uint32 event) 1479 { 1480 AddOnList::Iterator it = sAddOns.GetIterator(); 1481 while (RuntimeLoaderAddOn* addOn = it.Next()) { 1482 void (*function)(image_t* image) = NULL; 1483 1484 switch (event) { 1485 case IMAGE_EVENT_LOADED: 1486 function = addOn->addOn->image_loaded; 1487 break; 1488 case IMAGE_EVENT_RELOCATED: 1489 function = addOn->addOn->image_relocated; 1490 break; 1491 case IMAGE_EVENT_INITIALIZED: 1492 function = addOn->addOn->image_initialized; 1493 break; 1494 case IMAGE_EVENT_UNINITIALIZING: 1495 function = addOn->addOn->image_uninitializing; 1496 break; 1497 case IMAGE_EVENT_UNLOADING: 1498 function = addOn->addOn->image_unloading; 1499 break; 1500 } 1501 1502 if (function != NULL) 1503 function(image); 1504 } 1505 } 1506 1507 1508 static void 1509 register_image(image_t *image, int fd, const char *path) 1510 { 1511 struct stat stat; 1512 image_info info; 1513 1514 // ToDo: set these correctly 1515 info.id = 0; 1516 info.type = image->type; 1517 info.sequence = 0; 1518 info.init_order = 0; 1519 info.init_routine = (void (*)())image->init_routine; 1520 info.term_routine = (void (*)())image->term_routine; 1521 1522 if (_kern_read_stat(fd, NULL, false, &stat, sizeof(struct stat)) == B_OK) { 1523 info.device = stat.st_dev; 1524 info.node = stat.st_ino; 1525 } else { 1526 info.device = -1; 1527 info.node = -1; 1528 } 1529 1530 strlcpy(info.name, path, sizeof(info.name)); 1531 info.text = (void *)image->regions[0].vmstart; 1532 info.text_size = image->regions[0].vmsize; 1533 info.data = (void *)image->regions[1].vmstart; 1534 info.data_size = image->regions[1].vmsize; 1535 image->id = _kern_register_image(&info, sizeof(image_info)); 1536 } 1537 1538 1539 static status_t 1540 relocate_image(image_t *rootImage, image_t *image) 1541 { 1542 status_t status = arch_relocate_image(rootImage, image); 1543 if (status < B_OK) { 1544 FATAL("troubles relocating: 0x%lx (image: %s, %s)\n", status, 1545 image->path, image->name); 1546 return status; 1547 } 1548 1549 _kern_image_relocated(image->id); 1550 image_event(image, IMAGE_EVENT_RELOCATED); 1551 return B_OK; 1552 } 1553 1554 1555 static status_t 1556 load_container(char const *name, image_type type, const char *rpath, 1557 image_t **_image) 1558 { 1559 int32 pheaderSize, sheaderSize; 1560 char path[PATH_MAX]; 1561 ssize_t length; 1562 char ph_buff[4096]; 1563 int32 numRegions; 1564 image_t *found; 1565 image_t *image; 1566 status_t status; 1567 int fd; 1568 1569 struct Elf32_Ehdr eheader; 1570 1571 // Have we already loaded that image? Don't check for add-ons -- we always 1572 // reload them. 1573 if (type != B_ADD_ON_IMAGE) { 1574 found = find_image(name, APP_OR_LIBRARY_TYPE); 1575 1576 if (found == NULL && type != B_APP_IMAGE) { 1577 // Special case for add-ons that link against the application 1578 // executable, with the executable not having a soname set. 1579 if (const char* lastSlash = strrchr(name, '/')) { 1580 image_t* programImage = get_program_image(); 1581 if (strcmp(programImage->name, lastSlash + 1) == 0) 1582 found = programImage; 1583 } 1584 } 1585 1586 if (found) { 1587 atomic_add(&found->ref_count, 1); 1588 *_image = found; 1589 KTRACE("rld: load_container(\"%s\", type: %d, rpath: \"%s\") " 1590 "already loaded", name, type, rpath); 1591 return B_OK; 1592 } 1593 } 1594 1595 KTRACE("rld: load_container(\"%s\", type: %d, rpath: \"%s\")", name, type, 1596 rpath); 1597 1598 strlcpy(path, name, sizeof(path)); 1599 1600 // find and open the file 1601 fd = open_executable(path, type, rpath, get_program_path(), 1602 sSearchPathSubDir); 1603 if (fd < 0) { 1604 FATAL("cannot open file %s\n", name); 1605 KTRACE("rld: load_container(\"%s\"): failed to open file", name); 1606 return fd; 1607 } 1608 1609 // normalize the image path 1610 status = _kern_normalize_path(path, true, path); 1611 if (status != B_OK) 1612 goto err1; 1613 1614 // Test again if this image has been registered already - this time, 1615 // we can check the full path, not just its name as noted. 1616 // You could end up loading an image twice with symbolic links, else. 1617 if (type != B_ADD_ON_IMAGE) { 1618 found = find_image(path, APP_OR_LIBRARY_TYPE); 1619 if (found) { 1620 atomic_add(&found->ref_count, 1); 1621 *_image = found; 1622 _kern_close(fd); 1623 KTRACE("rld: load_container(\"%s\"): already loaded after all", 1624 name); 1625 return B_OK; 1626 } 1627 } 1628 1629 length = _kern_read(fd, 0, &eheader, sizeof(eheader)); 1630 if (length != sizeof(eheader)) { 1631 status = B_NOT_AN_EXECUTABLE; 1632 FATAL("troubles reading ELF header\n"); 1633 goto err1; 1634 } 1635 1636 status = parse_elf_header(&eheader, &pheaderSize, &sheaderSize); 1637 if (status < B_OK) { 1638 FATAL("incorrect ELF header\n"); 1639 goto err1; 1640 } 1641 1642 // ToDo: what to do about this restriction?? 1643 if (pheaderSize > (int)sizeof(ph_buff)) { 1644 FATAL("Cannot handle program headers bigger than %lu\n", sizeof(ph_buff)); 1645 status = B_UNSUPPORTED; 1646 goto err1; 1647 } 1648 1649 length = _kern_read(fd, eheader.e_phoff, ph_buff, pheaderSize); 1650 if (length != pheaderSize) { 1651 FATAL("Could not read program headers: %s\n", strerror(length)); 1652 status = B_BAD_DATA; 1653 goto err1; 1654 } 1655 1656 numRegions = count_regions(ph_buff, eheader.e_phnum, eheader.e_phentsize); 1657 if (numRegions <= 0) { 1658 FATAL("Troubles parsing Program headers, numRegions = %ld\n", numRegions); 1659 status = B_BAD_DATA; 1660 goto err1; 1661 } 1662 1663 image = create_image(name, path, numRegions); 1664 if (image == NULL) { 1665 FATAL("Failed to allocate image_t object\n"); 1666 status = B_NO_MEMORY; 1667 goto err1; 1668 } 1669 1670 status = parse_program_headers(image, ph_buff, eheader.e_phnum, eheader.e_phentsize); 1671 if (status < B_OK) 1672 goto err2; 1673 1674 if (!assert_dynamic_loadable(image)) { 1675 FATAL("Dynamic segment must be loadable (implementation restriction)\n"); 1676 status = B_UNSUPPORTED; 1677 goto err2; 1678 } 1679 1680 if (analyze_object_gcc_version(fd, image, eheader, sheaderSize, ph_buff, 1681 sizeof(ph_buff))) { 1682 // If this is the executable image, we init the search path 1683 // subdir, if the compiler version doesn't match ours. 1684 if (type == B_APP_IMAGE) { 1685 #if __GNUC__ == 2 1686 if (image->gcc_version.major > 2) 1687 sSearchPathSubDir = "gcc4"; 1688 #elif __GNUC__ == 4 1689 if (image->gcc_version.major == 2) 1690 sSearchPathSubDir = "gcc2"; 1691 #endif 1692 } 1693 } else { 1694 FATAL("Failed to get gcc version for %s\n", path); 1695 // not really fatal, actually 1696 } 1697 1698 // init gcc version dependent image flags 1699 // symbol resolution strategy (fallback is R5-style, if version is 1700 // unavailable) 1701 if (image->gcc_version.major == 0 1702 || image->gcc_version.major == 2 && image->gcc_version.middle < 95) { 1703 image->find_undefined_symbol = find_undefined_symbol_beos; 1704 } 1705 1706 status = map_image(fd, path, image, type == B_APP_IMAGE); 1707 if (status < B_OK) { 1708 FATAL("Could not map image: %s\n", strerror(status)); 1709 status = B_ERROR; 1710 goto err2; 1711 } 1712 1713 if (!parse_dynamic_segment(image)) { 1714 FATAL("Troubles handling dynamic section\n"); 1715 status = B_BAD_DATA; 1716 goto err3; 1717 } 1718 1719 if (eheader.e_entry != 0) 1720 image->entry_point = eheader.e_entry + image->regions[0].delta; 1721 1722 image->type = type; 1723 register_image(image, fd, path); 1724 image_event(image, IMAGE_EVENT_LOADED); 1725 1726 _kern_close(fd); 1727 1728 enqueue_image(&sLoadedImages, image); 1729 sLoadedImageCount++; 1730 1731 *_image = image; 1732 1733 KTRACE("rld: load_container(\"%s\"): done: id: %ld (gcc: %d.%d.%d)", name, 1734 image->id, image->gcc_version.major, image->gcc_version.middle, 1735 image->gcc_version.minor); 1736 1737 return B_OK; 1738 1739 err3: 1740 unmap_image(image); 1741 err2: 1742 delete_image_struct(image); 1743 err1: 1744 _kern_close(fd); 1745 1746 KTRACE("rld: load_container(\"%s\"): failed: %s", name, 1747 strerror(status)); 1748 1749 return status; 1750 } 1751 1752 1753 static const char * 1754 find_dt_rpath(image_t *image) 1755 { 1756 int i; 1757 struct Elf32_Dyn *d = (struct Elf32_Dyn *)image->dynamic_ptr; 1758 1759 for (i = 0; d[i].d_tag != DT_NULL; i++) { 1760 if (d[i].d_tag == DT_RPATH) 1761 return STRING(image, d[i].d_un.d_val); 1762 } 1763 1764 return NULL; 1765 } 1766 1767 1768 static status_t 1769 load_immediate_dependencies(image_t *image) 1770 { 1771 struct Elf32_Dyn *d = (struct Elf32_Dyn *)image->dynamic_ptr; 1772 bool reportErrors = report_errors(); 1773 status_t status = B_OK; 1774 uint32 i, j; 1775 const char *rpath; 1776 1777 if (!d || (image->flags & RFLAG_DEPENDENCIES_LOADED)) 1778 return B_OK; 1779 1780 image->flags |= RFLAG_DEPENDENCIES_LOADED; 1781 1782 if (image->num_needed == 0) 1783 return B_OK; 1784 1785 KTRACE("rld: load_dependencies(\"%s\", id: %ld)", image->name, 1786 image->id); 1787 1788 image->needed = (image_t**)malloc(image->num_needed * sizeof(image_t *)); 1789 if (image->needed == NULL) { 1790 FATAL("failed to allocate needed struct\n"); 1791 KTRACE("rld: load_dependencies(\"%s\", id: %ld) failed: no memory", 1792 image->name, image->id); 1793 return B_NO_MEMORY; 1794 } 1795 1796 memset(image->needed, 0, image->num_needed * sizeof(image_t *)); 1797 rpath = find_dt_rpath(image); 1798 1799 for (i = 0, j = 0; d[i].d_tag != DT_NULL; i++) { 1800 switch (d[i].d_tag) { 1801 case DT_NEEDED: 1802 { 1803 int32 neededOffset = d[i].d_un.d_val; 1804 const char *name = STRING(image, neededOffset); 1805 1806 status_t loadStatus = load_container(name, B_LIBRARY_IMAGE, 1807 rpath, &image->needed[j]); 1808 if (loadStatus < B_OK) { 1809 status = loadStatus; 1810 // correct error code in case the file could not been found 1811 if (status == B_ENTRY_NOT_FOUND) { 1812 status = B_MISSING_LIBRARY; 1813 1814 if (reportErrors) 1815 sErrorMessage.AddString("missing library", name); 1816 } 1817 1818 // Collect all missing libraries in case we report back 1819 if (!reportErrors) { 1820 KTRACE("rld: load_dependencies(\"%s\", id: %ld) " 1821 "failed: %s", image->name, image->id, 1822 strerror(status)); 1823 return status; 1824 } 1825 } 1826 1827 j += 1; 1828 break; 1829 } 1830 1831 default: 1832 // ignore any other tag 1833 continue; 1834 } 1835 } 1836 1837 if (status < B_OK) { 1838 KTRACE("rld: load_dependencies(\"%s\", id: %ld) " 1839 "failed: %s", image->name, image->id, 1840 strerror(status)); 1841 return status; 1842 } 1843 1844 if (j != image->num_needed) { 1845 FATAL("Internal error at load_dependencies()"); 1846 KTRACE("rld: load_dependencies(\"%s\", id: %ld) " 1847 "failed: internal error", image->name, image->id); 1848 return B_ERROR; 1849 } 1850 1851 KTRACE("rld: load_dependencies(\"%s\", id: %ld) done", image->name, 1852 image->id); 1853 1854 return B_OK; 1855 } 1856 1857 1858 static status_t 1859 load_dependencies(image_t* image) 1860 { 1861 for (image_t* otherImage = image; otherImage != NULL; 1862 otherImage = otherImage->next) { 1863 status_t status = load_immediate_dependencies(otherImage); 1864 if (status != B_OK) 1865 return status; 1866 } 1867 1868 return B_OK; 1869 } 1870 1871 1872 static uint32 1873 topological_sort(image_t *image, uint32 slot, image_t **initList, 1874 uint32 sortFlag) 1875 { 1876 uint32 i; 1877 1878 if (image->flags & sortFlag) 1879 return slot; 1880 1881 image->flags |= sortFlag; /* make sure we don't visit this one */ 1882 for (i = 0; i < image->num_needed; i++) 1883 slot = topological_sort(image->needed[i], slot, initList, sortFlag); 1884 1885 initList[slot] = image; 1886 return slot + 1; 1887 } 1888 1889 1890 static ssize_t 1891 get_sorted_image_list(image_t *image, image_t ***_list, uint32 sortFlag) 1892 { 1893 image_t **list; 1894 1895 list = (image_t**)malloc(sLoadedImageCount * sizeof(image_t *)); 1896 if (list == NULL) { 1897 FATAL("memory shortage in get_sorted_image_list()"); 1898 *_list = NULL; 1899 return B_NO_MEMORY; 1900 } 1901 1902 memset(list, 0, sLoadedImageCount * sizeof(image_t *)); 1903 1904 *_list = list; 1905 return topological_sort(image, 0, list, sortFlag); 1906 } 1907 1908 1909 static status_t 1910 relocate_dependencies(image_t *image) 1911 { 1912 // get the images that still have to be relocated 1913 image_t **list; 1914 ssize_t count = get_sorted_image_list(image, &list, RFLAG_RELOCATED); 1915 if (count < B_OK) 1916 return count; 1917 1918 // relocate 1919 for (ssize_t i = 0; i < count; i++) { 1920 status_t status = relocate_image(image, list[i]); 1921 if (status < B_OK) { 1922 free(list); 1923 return status; 1924 } 1925 } 1926 1927 free(list); 1928 return B_OK; 1929 } 1930 1931 1932 static void 1933 init_dependencies(image_t *image, bool initHead) 1934 { 1935 image_t **initList; 1936 ssize_t count, i; 1937 1938 count = get_sorted_image_list(image, &initList, RFLAG_INITIALIZED); 1939 if (count <= 0) 1940 return; 1941 1942 if (!initHead) { 1943 // this removes the "calling" image 1944 image->flags &= ~RFLAG_INITIALIZED; 1945 initList[--count] = NULL; 1946 } 1947 1948 TRACE(("%ld: init dependencies\n", find_thread(NULL))); 1949 for (i = 0; i < count; i++) { 1950 image = initList[i]; 1951 1952 TRACE(("%ld: init: %s\n", find_thread(NULL), image->name)); 1953 1954 if (image->init_routine != 0) 1955 ((init_term_function)image->init_routine)(image->id); 1956 1957 image_event(image, IMAGE_EVENT_INITIALIZED); 1958 } 1959 TRACE(("%ld: init done.\n", find_thread(NULL))); 1960 1961 free(initList); 1962 } 1963 1964 1965 static void 1966 put_image(image_t *image) 1967 { 1968 // If all references to the image are gone, add it to the disposable list 1969 // and remove all dependencies 1970 1971 if (atomic_add(&image->ref_count, -1) == 1) { 1972 size_t i; 1973 1974 dequeue_image(&sLoadedImages, image); 1975 enqueue_image(&sDisposableImages, image); 1976 sLoadedImageCount--; 1977 1978 for (i = 0; i < image->num_needed; i++) { 1979 put_image(image->needed[i]); 1980 } 1981 } 1982 } 1983 1984 1985 void 1986 inject_runtime_loader_api(image_t* rootImage) 1987 { 1988 // We patch any exported __gRuntimeLoader symbols to point to our private 1989 // API. 1990 image_t* image; 1991 void* _export; 1992 if (find_symbol_breadth_first(rootImage, "__gRuntimeLoader", 1993 B_SYMBOL_TYPE_DATA, &image, &_export) == B_OK) { 1994 *(void**)_export = &gRuntimeLoader; 1995 } 1996 } 1997 1998 1999 static status_t 2000 add_preloaded_image(image_t* image) 2001 { 2002 // We realloc() everytime -- not particularly efficient, but good enough for 2003 // small number of preloaded images. 2004 image_t** newArray = (image_t**)realloc(sPreloadedImages, 2005 sizeof(image_t*) * (sPreloadedImageCount + 1)); 2006 if (newArray == NULL) 2007 return B_NO_MEMORY; 2008 2009 sPreloadedImages = newArray; 2010 newArray[sPreloadedImageCount++] = image; 2011 2012 return B_OK; 2013 } 2014 2015 2016 image_id 2017 preload_image(char const* path) 2018 { 2019 if (path == NULL) 2020 return B_BAD_VALUE; 2021 2022 KTRACE("rld: preload_image(\"%s\")", path); 2023 2024 image_t *image = NULL; 2025 status_t status = load_container(path, B_ADD_ON_IMAGE, NULL, &image); 2026 if (status < B_OK) { 2027 rld_unlock(); 2028 KTRACE("rld: preload_image(\"%s\") failed to load container: %s", path, 2029 strerror(status)); 2030 return status; 2031 } 2032 2033 if (image->find_undefined_symbol == NULL) 2034 image->find_undefined_symbol = find_undefined_symbol_global; 2035 2036 status = load_dependencies(image); 2037 if (status < B_OK) 2038 goto err; 2039 2040 set_image_flags_recursively(image, RTLD_GLOBAL); 2041 2042 status = relocate_dependencies(image); 2043 if (status < B_OK) 2044 goto err; 2045 2046 status = add_preloaded_image(image); 2047 if (status < B_OK) 2048 goto err; 2049 2050 inject_runtime_loader_api(image); 2051 2052 remap_images(); 2053 init_dependencies(image, true); 2054 2055 // if the image contains an add-on, register it 2056 runtime_loader_add_on* addOnStruct; 2057 if (find_symbol(image, "__gRuntimeLoaderAddOn", B_SYMBOL_TYPE_DATA, 2058 (void**)&addOnStruct) == B_OK) { 2059 RuntimeLoaderAddOn* addOn = new(mynothrow) RuntimeLoaderAddOn(image, 2060 addOnStruct); 2061 if (addOn != NULL) { 2062 sAddOns.Add(addOn); 2063 addOnStruct->init(&gRuntimeLoader, &gRuntimeLoaderAddOnExport); 2064 } 2065 } 2066 2067 KTRACE("rld: preload_image(\"%s\") done: id: %ld", path, image->id); 2068 2069 return image->id; 2070 2071 err: 2072 KTRACE("rld: preload_image(\"%s\") failed: %s", path, strerror(status)); 2073 2074 dequeue_image(&sLoadedImages, image); 2075 sLoadedImageCount--; 2076 delete_image(image); 2077 return status; 2078 } 2079 2080 2081 static void 2082 preload_images() 2083 { 2084 const char* imagePaths = getenv("LD_PRELOAD"); 2085 if (imagePaths == NULL) 2086 return; 2087 2088 while (*imagePaths != '\0') { 2089 // find begin of image path 2090 while (*imagePaths != '\0' && isspace(*imagePaths)) 2091 imagePaths++; 2092 2093 if (*imagePaths == '\0') 2094 break; 2095 2096 // find end of image path 2097 const char* imagePath = imagePaths; 2098 while (*imagePaths != '\0' && !isspace(*imagePaths)) 2099 imagePaths++; 2100 2101 // extract the path 2102 char path[B_PATH_NAME_LENGTH]; 2103 size_t pathLen = imagePaths - imagePath; 2104 if (pathLen > sizeof(path) - 1) 2105 continue; 2106 memcpy(path, imagePath, pathLen); 2107 path[pathLen] = '\0'; 2108 2109 // load the image 2110 preload_image(path); 2111 } 2112 } 2113 2114 2115 // #pragma mark - libroot.so exported functions 2116 2117 2118 image_id 2119 load_program(char const *path, void **_entry) 2120 { 2121 status_t status; 2122 image_t *image; 2123 2124 KTRACE("rld: load_program(\"%s\")", path); 2125 2126 rld_lock(); 2127 // for now, just do stupid simple global locking 2128 2129 preload_images(); 2130 2131 TRACE(("rld: load %s\n", path)); 2132 2133 status = load_container(path, B_APP_IMAGE, NULL, &sProgramImage); 2134 if (status < B_OK) 2135 goto err; 2136 2137 if (sProgramImage->find_undefined_symbol == NULL) 2138 sProgramImage->find_undefined_symbol = find_undefined_symbol_global; 2139 2140 status = load_dependencies(sProgramImage); 2141 if (status < B_OK) 2142 goto err; 2143 2144 // Set RTLD_GLOBAL on all libraries, but clear it on the program image. 2145 // This results in the desired symbol resolution for dlopen()ed libraries. 2146 set_image_flags_recursively(sProgramImage, RTLD_GLOBAL); 2147 sProgramImage->flags &= ~RTLD_GLOBAL; 2148 2149 status = relocate_dependencies(sProgramImage); 2150 if (status < B_OK) 2151 goto err; 2152 2153 inject_runtime_loader_api(sProgramImage); 2154 2155 remap_images(); 2156 init_dependencies(sProgramImage, true); 2157 2158 // Since the images are initialized now, we no longer should use our 2159 // getenv(), but use the one from libroot.so 2160 find_symbol_breadth_first(sProgramImage, "getenv", B_SYMBOL_TYPE_TEXT, 2161 &image, (void**)&gGetEnv); 2162 2163 if (sProgramImage->entry_point == 0) { 2164 status = B_NOT_AN_EXECUTABLE; 2165 goto err; 2166 } 2167 2168 *_entry = (void *)(sProgramImage->entry_point); 2169 2170 rld_unlock(); 2171 2172 sProgramLoaded = true; 2173 2174 KTRACE("rld: load_program(\"%s\") done: entry: %p, id: %ld", path, 2175 *_entry, sProgramImage->id); 2176 2177 return sProgramImage->id; 2178 2179 err: 2180 KTRACE("rld: load_program(\"%s\") failed: %s", path, strerror(status)); 2181 2182 delete_image(sProgramImage); 2183 2184 if (report_errors()) { 2185 // send error message 2186 sErrorMessage.AddInt32("error", status); 2187 sErrorMessage.SetDeliveryInfo(gProgramArgs->error_token, 2188 -1, 0, find_thread(NULL)); 2189 2190 _kern_write_port_etc(gProgramArgs->error_port, 'KMSG', 2191 sErrorMessage.Buffer(), sErrorMessage.ContentSize(), 0, 0); 2192 } 2193 _kern_loading_app_failed(status); 2194 rld_unlock(); 2195 2196 return status; 2197 } 2198 2199 2200 image_id 2201 load_library(char const *path, uint32 flags, bool addOn, void** _handle) 2202 { 2203 image_t *image = NULL; 2204 image_type type = (addOn ? B_ADD_ON_IMAGE : B_LIBRARY_IMAGE); 2205 status_t status; 2206 2207 if (path == NULL && addOn) 2208 return B_BAD_VALUE; 2209 2210 KTRACE("rld: load_library(\"%s\", 0x%lx, %d)", path, flags, addOn); 2211 2212 rld_lock(); 2213 // for now, just do stupid simple global locking 2214 2215 // have we already loaded this library? 2216 // Checking it at this stage saves loading its dependencies again 2217 if (!addOn) { 2218 // a NULL path is fine -- it means the global scope shall be opened 2219 if (path == NULL) { 2220 *_handle = RLD_GLOBAL_SCOPE; 2221 rld_unlock(); 2222 return 0; 2223 } 2224 2225 image = find_image(path, APP_OR_LIBRARY_TYPE); 2226 if (image != NULL && (flags & RTLD_GLOBAL) != 0) 2227 set_image_flags_recursively(image, RTLD_GLOBAL); 2228 2229 if (image) { 2230 atomic_add(&image->ref_count, 1); 2231 rld_unlock(); 2232 KTRACE("rld: load_library(\"%s\"): already loaded: %ld", path, 2233 image->id); 2234 *_handle = image; 2235 return image->id; 2236 } 2237 } 2238 2239 status = load_container(path, type, NULL, &image); 2240 if (status < B_OK) { 2241 rld_unlock(); 2242 KTRACE("rld: load_library(\"%s\") failed to load container: %s", path, 2243 strerror(status)); 2244 return status; 2245 } 2246 2247 if (image->find_undefined_symbol == NULL) { 2248 if (addOn) 2249 image->find_undefined_symbol = find_undefined_symbol_add_on; 2250 else 2251 image->find_undefined_symbol = find_undefined_symbol_global; 2252 } 2253 2254 status = load_dependencies(image); 2255 if (status < B_OK) 2256 goto err; 2257 2258 // If specified, set the RTLD_GLOBAL flag recursively on this image and all 2259 // dependencies. If not specified, we temporarily set 2260 // RFLAG_USE_FOR_RESOLVING so that the dependencies will correctly be used 2261 // for undefined symbol resolution. 2262 if ((flags & RTLD_GLOBAL) != 0) 2263 set_image_flags_recursively(image, RTLD_GLOBAL); 2264 else 2265 set_image_flags_recursively(image, RFLAG_USE_FOR_RESOLVING); 2266 2267 status = relocate_dependencies(image); 2268 if (status < B_OK) 2269 goto err; 2270 2271 if ((flags & RTLD_GLOBAL) == 0) 2272 clear_image_flags_recursively(image, RFLAG_USE_FOR_RESOLVING); 2273 2274 remap_images(); 2275 init_dependencies(image, true); 2276 2277 rld_unlock(); 2278 2279 KTRACE("rld: load_library(\"%s\") done: id: %ld", path, image->id); 2280 2281 *_handle = image; 2282 return image->id; 2283 2284 err: 2285 KTRACE("rld: load_library(\"%s\") failed: %s", path, strerror(status)); 2286 2287 dequeue_image(&sLoadedImages, image); 2288 sLoadedImageCount--; 2289 delete_image(image); 2290 rld_unlock(); 2291 return status; 2292 } 2293 2294 2295 status_t 2296 unload_library(void* handle, image_id imageID, bool addOn) 2297 { 2298 image_t *image; 2299 image_type type = addOn ? B_ADD_ON_IMAGE : B_LIBRARY_IMAGE; 2300 2301 if (handle == NULL && imageID < 0) 2302 return B_BAD_IMAGE_ID; 2303 2304 if (handle == RLD_GLOBAL_SCOPE) 2305 return B_OK; 2306 2307 rld_lock(); 2308 // for now, just do stupid simple global locking 2309 2310 if (sInvalidImageIDs) { 2311 // After fork, we lazily rebuild the image IDs of all loaded images 2312 update_image_ids(); 2313 } 2314 2315 // we only check images that have been already initialized 2316 2317 status_t status = B_BAD_IMAGE_ID; 2318 2319 if (handle != NULL) { 2320 image = (image_t*)handle; 2321 put_image(image); 2322 status = B_OK; 2323 } else { 2324 for (image = sLoadedImages.head; image; image = image->next) { 2325 if (image->id == imageID) { 2326 // unload image 2327 if (type == image->type) { 2328 put_image(image); 2329 status = B_OK; 2330 } else 2331 status = B_BAD_VALUE; 2332 break; 2333 } 2334 } 2335 } 2336 2337 if (status == B_OK) { 2338 while ((image = sDisposableImages.head) != NULL) { 2339 // call image fini here... 2340 if (gRuntimeLoader.call_atexit_hooks_for_range) { 2341 gRuntimeLoader.call_atexit_hooks_for_range( 2342 image->regions[0].vmstart, image->regions[0].vmsize); 2343 } 2344 2345 image_event(image, IMAGE_EVENT_UNINITIALIZING); 2346 2347 if (image->term_routine) 2348 ((init_term_function)image->term_routine)(image->id); 2349 2350 dequeue_image(&sDisposableImages, image); 2351 unmap_image(image); 2352 2353 image_event(image, IMAGE_EVENT_UNLOADING); 2354 2355 delete_image(image); 2356 } 2357 } 2358 2359 rld_unlock(); 2360 return status; 2361 } 2362 2363 2364 status_t 2365 get_nth_symbol(image_id imageID, int32 num, char *nameBuffer, 2366 int32 *_nameLength, int32 *_type, void **_location) 2367 { 2368 int32 count = 0, j; 2369 uint32 i; 2370 image_t *image; 2371 2372 rld_lock(); 2373 2374 // get the image from those who have been already initialized 2375 image = find_loaded_image_by_id(imageID); 2376 if (image == NULL) { 2377 rld_unlock(); 2378 return B_BAD_IMAGE_ID; 2379 } 2380 2381 // iterate through all the hash buckets until we've found the one 2382 for (i = 0; i < HASHTABSIZE(image); i++) { 2383 for (j = HASHBUCKETS(image)[i]; j != STN_UNDEF; j = HASHCHAINS(image)[j]) { 2384 struct Elf32_Sym *symbol = &image->syms[j]; 2385 2386 if (count == num) { 2387 const char* symbolName = SYMNAME(image, symbol); 2388 strlcpy(nameBuffer, symbolName, *_nameLength); 2389 *_nameLength = strlen(symbolName); 2390 2391 void* location = (void*)(symbol->st_value 2392 + image->regions[0].delta); 2393 int32 type; 2394 if (ELF32_ST_TYPE(symbol->st_info) == STT_FUNC) 2395 type = B_SYMBOL_TYPE_TEXT; 2396 else if (ELF32_ST_TYPE(symbol->st_info) == STT_OBJECT) 2397 type = B_SYMBOL_TYPE_DATA; 2398 else 2399 type = B_SYMBOL_TYPE_ANY; 2400 // TODO: check with the return types of that BeOS function 2401 2402 patch_defined_symbol(image, symbolName, &location, &type); 2403 2404 if (_type != NULL) 2405 *_type = type; 2406 if (_location != NULL) 2407 *_location = location; 2408 goto out; 2409 } 2410 count++; 2411 } 2412 } 2413 out: 2414 rld_unlock(); 2415 2416 if (num != count) 2417 return B_BAD_INDEX; 2418 2419 return B_OK; 2420 } 2421 2422 2423 status_t 2424 get_symbol(image_id imageID, char const *symbolName, int32 symbolType, 2425 void **_location) 2426 { 2427 status_t status = B_OK; 2428 image_t *image; 2429 2430 if (imageID < B_OK) 2431 return B_BAD_IMAGE_ID; 2432 if (symbolName == NULL) 2433 return B_BAD_VALUE; 2434 2435 rld_lock(); 2436 // for now, just do stupid simple global locking 2437 2438 // get the image from those who have been already initialized 2439 image = find_loaded_image_by_id(imageID); 2440 if (image != NULL) 2441 status = find_symbol(image, symbolName, symbolType, _location); 2442 else 2443 status = B_BAD_IMAGE_ID; 2444 2445 rld_unlock(); 2446 return status; 2447 } 2448 2449 2450 status_t 2451 get_library_symbol(void* handle, void* caller, const char* symbolName, 2452 void **_location) 2453 { 2454 status_t status = B_ENTRY_NOT_FOUND; 2455 2456 if (symbolName == NULL) 2457 return B_BAD_VALUE; 2458 2459 rld_lock(); 2460 // for now, just do stupid simple global locking 2461 2462 if (handle == RTLD_DEFAULT || handle == RLD_GLOBAL_SCOPE) { 2463 // look in the default scope 2464 image_t* image; 2465 Elf32_Sym* symbol = find_undefined_symbol_global(sProgramImage, 2466 sProgramImage, symbolName, &image); 2467 if (symbol != NULL) { 2468 *_location = (void*)(symbol->st_value + image->regions[0].delta); 2469 int32 symbolType = ELF32_ST_TYPE(symbol->st_info) == STT_FUNC 2470 ? B_SYMBOL_TYPE_TEXT : B_SYMBOL_TYPE_DATA; 2471 patch_defined_symbol(image, symbolName, _location, &symbolType); 2472 status = B_OK; 2473 } 2474 } else if (handle == RTLD_NEXT) { 2475 // Look in the default scope, but also in the dependencies of the 2476 // calling image. Return the next after the caller symbol. 2477 2478 // First of all, find the caller symbol and its image. 2479 Elf32_Sym* callerSymbol = NULL; 2480 image_t* callerImage = sLoadedImages.head; 2481 for (; callerImage != NULL; callerImage = callerImage->next) { 2482 elf_region_t& text = callerImage->regions[0]; 2483 if ((addr_t)caller < text.vmstart 2484 || (addr_t)caller >= text.vmstart + text.vmsize) { 2485 continue; 2486 } 2487 2488 // found the image -- now find the symbol 2489 for (uint32 i = 0; i < callerImage->symhash[1]; i++) { 2490 Elf32_Sym& symbol = callerImage->syms[i]; 2491 if ((ELF32_ST_TYPE(symbol.st_info) != STT_FUNC) 2492 || symbol.st_value == 0) { 2493 continue; 2494 } 2495 2496 addr_t address = symbol.st_value 2497 + callerImage->regions[0].delta; 2498 if ((addr_t)caller >= address 2499 && (addr_t)caller < address + symbol.st_size) { 2500 callerSymbol = &symbol; 2501 break; 2502 } 2503 } 2504 2505 break; 2506 } 2507 2508 if (callerSymbol != NULL) { 2509 // found the caller -- now search the global scope until we find 2510 // the next symbol 2511 set_image_flags_recursively(callerImage, RFLAG_USE_FOR_RESOLVING); 2512 2513 image_t* image = sLoadedImages.head; 2514 for (; image != NULL; image = image->next) { 2515 if (image != callerImage 2516 && (image->type == B_ADD_ON_IMAGE 2517 || (image->flags 2518 & (RTLD_GLOBAL | RFLAG_USE_FOR_RESOLVING)) == 0)) { 2519 continue; 2520 } 2521 2522 struct Elf32_Sym *symbol = find_symbol(image, symbolName, 2523 B_SYMBOL_TYPE_TEXT); 2524 if (symbol == NULL) 2525 continue; 2526 2527 if (callerSymbol == NULL) { 2528 // already skipped the caller symbol -- so this is 2529 // the one we're looking for 2530 *_location = (void*)(symbol->st_value 2531 + image->regions[0].delta); 2532 int32 symbolType = B_SYMBOL_TYPE_TEXT; 2533 patch_defined_symbol(image, symbolName, _location, 2534 &symbolType); 2535 status = B_OK; 2536 break; 2537 } 2538 if (symbol == callerSymbol) { 2539 // found the caller symbol 2540 callerSymbol = NULL; 2541 } 2542 } 2543 2544 clear_image_flags_recursively(callerImage, RFLAG_USE_FOR_RESOLVING); 2545 } 2546 2547 } else { 2548 // breadth-first search in the given image and its dependencies 2549 image_t* inImage; 2550 status = find_symbol_breadth_first((image_t*)handle, symbolName, 2551 B_SYMBOL_TYPE_ANY, &inImage, _location); 2552 } 2553 2554 rld_unlock(); 2555 return status; 2556 } 2557 2558 2559 status_t 2560 get_next_image_dependency(image_id id, uint32 *cookie, const char **_name) 2561 { 2562 uint32 i, j, searchIndex = *cookie; 2563 struct Elf32_Dyn *dynamicSection; 2564 image_t *image; 2565 2566 if (_name == NULL) 2567 return B_BAD_VALUE; 2568 2569 rld_lock(); 2570 2571 image = find_loaded_image_by_id(id); 2572 if (image == NULL) { 2573 rld_unlock(); 2574 return B_BAD_IMAGE_ID; 2575 } 2576 2577 dynamicSection = (struct Elf32_Dyn *)image->dynamic_ptr; 2578 if (dynamicSection == NULL || image->num_needed <= searchIndex) { 2579 rld_unlock(); 2580 return B_ENTRY_NOT_FOUND; 2581 } 2582 2583 for (i = 0, j = 0; dynamicSection[i].d_tag != DT_NULL; i++) { 2584 if (dynamicSection[i].d_tag != DT_NEEDED) 2585 continue; 2586 2587 if (j++ == searchIndex) { 2588 int32 neededOffset = dynamicSection[i].d_un.d_val; 2589 2590 *_name = STRING(image, neededOffset); 2591 *cookie = searchIndex + 1; 2592 rld_unlock(); 2593 return B_OK; 2594 } 2595 } 2596 2597 rld_unlock(); 2598 return B_ENTRY_NOT_FOUND; 2599 } 2600 2601 2602 // #pragma mark - runtime_loader private exports 2603 2604 2605 /*! Read and verify the ELF header */ 2606 status_t 2607 elf_verify_header(void *header, int32 length) 2608 { 2609 int32 programSize, sectionSize; 2610 2611 if (length < (int32)sizeof(struct Elf32_Ehdr)) 2612 return B_NOT_AN_EXECUTABLE; 2613 2614 return parse_elf_header((struct Elf32_Ehdr *)header, &programSize, 2615 §ionSize); 2616 } 2617 2618 2619 void 2620 terminate_program(void) 2621 { 2622 image_t **termList; 2623 ssize_t count, i; 2624 2625 count = get_sorted_image_list(sProgramImage, &termList, RFLAG_TERMINATED); 2626 if (count < B_OK) 2627 return; 2628 2629 if (sInvalidImageIDs) { 2630 // After fork, we lazily rebuild the image IDs of all loaded images 2631 update_image_ids(); 2632 } 2633 2634 TRACE(("%ld: terminate dependencies\n", find_thread(NULL))); 2635 for (i = count; i-- > 0;) { 2636 image_t *image = termList[i]; 2637 2638 TRACE(("%ld: term: %s\n", find_thread(NULL), image->name)); 2639 2640 image_event(image, IMAGE_EVENT_UNINITIALIZING); 2641 2642 if (image->term_routine) 2643 ((init_term_function)image->term_routine)(image->id); 2644 2645 image_event(image, IMAGE_EVENT_UNLOADING); 2646 } 2647 TRACE(("%ld: term done.\n", find_thread(NULL))); 2648 2649 free(termList); 2650 } 2651 2652 2653 void 2654 rldelf_init(void) 2655 { 2656 // invoke static constructors 2657 new(&sAddOns) AddOnList; 2658 2659 sSem = create_sem(1, "runtime loader"); 2660 sSemOwner = -1; 2661 sSemCount = 0; 2662 2663 // create the debug area 2664 { 2665 int32 size = TO_PAGE_SIZE(sizeof(runtime_loader_debug_area)); 2666 2667 runtime_loader_debug_area *area; 2668 area_id areaID = _kern_create_area(RUNTIME_LOADER_DEBUG_AREA_NAME, 2669 (void **)&area, B_ANY_ADDRESS, size, B_NO_LOCK, 2670 B_READ_AREA | B_WRITE_AREA); 2671 if (areaID < B_OK) { 2672 FATAL("Failed to create debug area.\n"); 2673 _kern_loading_app_failed(areaID); 2674 } 2675 2676 area->loaded_images = &sLoadedImages; 2677 } 2678 2679 // initialize error message if needed 2680 if (report_errors()) { 2681 void *buffer = malloc(1024); 2682 if (buffer == NULL) 2683 return; 2684 2685 sErrorMessage.SetTo(buffer, 1024, 'Rler'); 2686 } 2687 } 2688 2689 2690 status_t 2691 elf_reinit_after_fork(void) 2692 { 2693 sSem = create_sem(1, "runtime loader"); 2694 if (sSem < 0) 2695 return sSem; 2696 2697 // We also need to update the IDs of our images. We are the child and 2698 // and have cloned images with different IDs. Since in most cases (fork() 2699 // + exec*()) this would just increase the fork() overhead with no one 2700 // caring, we do that lazily, when first doing something different. 2701 sInvalidImageIDs = true; 2702 2703 return B_OK; 2704 } 2705