1 /* 2 * Copyright 2003-2007, Axel Dörfler, axeld@pinc-software.de. 3 * Distributed under the terms of the MIT License. 4 * 5 * Copyright 2002, Manuel J. Petit. All rights reserved. 6 * Copyright 2001, Travis Geiselbrecht. All rights reserved. 7 * Distributed under the terms of the NewOS License. 8 */ 9 10 11 #include "runtime_loader_private.h" 12 #include "vm.h" 13 14 #include <OS.h> 15 16 #include <elf32.h> 17 #include <user_runtime.h> 18 #include <syscalls.h> 19 #include <vm_types.h> 20 #include <arch/cpu.h> 21 #include <sem.h> 22 #include <runtime_loader.h> 23 24 #include <string.h> 25 #include <stdio.h> 26 #include <stdlib.h> 27 28 29 //#define TRACE_RLD 30 #ifdef TRACE_RLD 31 # define TRACE(x) dprintf x 32 #else 33 # define TRACE(x) ; 34 #endif 35 36 37 // ToDo: implement better locking strategy 38 // ToDo: implement lazy binding 39 40 #define PAGE_MASK (B_PAGE_SIZE - 1) 41 42 #define PAGE_OFFSET(x) ((x) & (PAGE_MASK)) 43 #define PAGE_BASE(x) ((x) & ~(PAGE_MASK)) 44 #define TO_PAGE_SIZE(x) ((x + (PAGE_MASK)) & ~(PAGE_MASK)) 45 46 #define RLD_PROGRAM_BASE 0x00200000 47 /* keep in sync with app ldscript */ 48 49 enum { 50 RFLAG_RW = 0x0001, 51 RFLAG_ANON = 0x0002, 52 53 RFLAG_TERMINATED = 0x0200, 54 RFLAG_INITIALIZED = 0x0400, 55 RFLAG_SYMBOLIC = 0x0800, 56 RFLAG_RELOCATED = 0x1000, 57 RFLAG_PROTECTED = 0x2000, 58 RFLAG_DEPENDENCIES_LOADED = 0x4000, 59 RFLAG_REMAPPED = 0x8000, 60 61 RFLAG_VISITED = 0x10000 62 // temporarily set in the symbol resolution code 63 }; 64 65 66 #define IMAGE_TYPE_TO_MASK(type) (1 << ((type) - 1)) 67 #define ALL_IMAGE_TYPES (IMAGE_TYPE_TO_MASK(B_APP_IMAGE) \ 68 | IMAGE_TYPE_TO_MASK(B_LIBRARY_IMAGE) \ 69 | IMAGE_TYPE_TO_MASK(B_ADD_ON_IMAGE) \ 70 | IMAGE_TYPE_TO_MASK(B_SYSTEM_IMAGE)) 71 #define APP_OR_LIBRARY_TYPE (IMAGE_TYPE_TO_MASK(B_APP_IMAGE) \ 72 | IMAGE_TYPE_TO_MASK(B_LIBRARY_IMAGE)) 73 74 typedef void (*init_term_function)(image_id); 75 76 static image_queue_t sLoadedImages = {0, 0}; 77 static image_queue_t sDisposableImages = {0, 0}; 78 static uint32 sLoadedImageCount = 0; 79 static image_t *sProgramImage; 80 static KMessage sErrorMessage; 81 82 #ifdef BEOS_STYLE_SYMBOLS_RESOLUTION 83 static bool sResolveSymbolsBeOSStyle = true; 84 #else 85 static bool sResolveSymbolsBeOSStyle = false; 86 #endif 87 88 // a recursive lock 89 static sem_id rld_sem; 90 static thread_id rld_sem_owner; 91 static int32 rld_sem_count; 92 93 94 #ifdef TRACE_RLD 95 # define FATAL(x...) dprintf("runtime_loader: " x); 96 97 void 98 dprintf(const char *format, ...) 99 { 100 char buffer[1024]; 101 102 va_list list; 103 va_start(list, format); 104 105 vsnprintf(buffer, sizeof(buffer), format, list); 106 _kern_debug_output(buffer); 107 108 va_end(list); 109 } 110 #else 111 # define FATAL(x...) printf("runtime_loader: " x); 112 #endif 113 114 115 static void 116 rld_unlock() 117 { 118 if (rld_sem_count-- == 1) { 119 rld_sem_owner = -1; 120 release_sem(rld_sem); 121 } 122 } 123 124 125 static void 126 rld_lock() 127 { 128 thread_id self = find_thread(NULL); 129 if (self != rld_sem_owner) { 130 acquire_sem(rld_sem); 131 rld_sem_owner = self; 132 } 133 rld_sem_count++; 134 } 135 136 137 static void 138 enqueue_image(image_queue_t *queue, image_t *image) 139 { 140 image->next = 0; 141 142 image->prev = queue->tail; 143 if (queue->tail) 144 queue->tail->next = image; 145 146 queue->tail = image; 147 if (!queue->head) 148 queue->head = image; 149 } 150 151 152 static void 153 dequeue_image(image_queue_t *queue, image_t *image) 154 { 155 if (image->next) 156 image->next->prev = image->prev; 157 else 158 queue->tail = image->prev; 159 160 if (image->prev) 161 image->prev->next = image->next; 162 else 163 queue->head = image->next; 164 165 image->prev = 0; 166 image->next = 0; 167 } 168 169 170 static uint32 171 elf_hash(const uint8 *name) 172 { 173 uint32 hash = 0; 174 uint32 temp; 175 176 while (*name) { 177 hash = (hash << 4) + *name++; 178 if ((temp = hash & 0xf0000000)) { 179 hash ^= temp >> 24; 180 } 181 hash &= ~temp; 182 } 183 return hash; 184 } 185 186 187 static inline bool 188 report_errors() 189 { 190 return gProgramArgs->error_port >= 0; 191 } 192 193 194 static image_t * 195 find_image_in_queue(image_queue_t *queue, const char *name, bool isPath, 196 uint32 typeMask) 197 { 198 image_t *image; 199 200 for (image = queue->head; image; image = image->next) { 201 const char *imageName = isPath ? image->path : image->name; 202 int length = isPath ? sizeof(image->path) : sizeof(image->name); 203 204 if (!strncmp(imageName, name, length) 205 && (typeMask & IMAGE_TYPE_TO_MASK(image->type)) != 0) { 206 return image; 207 } 208 } 209 210 return NULL; 211 } 212 213 214 static image_t * 215 find_image(char const *name, uint32 typeMask) 216 { 217 bool isPath = (strchr(name, '/') != NULL); 218 return find_image_in_queue(&sLoadedImages, name, isPath, typeMask); 219 } 220 221 222 static image_t * 223 find_loaded_image_by_id(image_id id) 224 { 225 image_t *image; 226 227 for (image = sLoadedImages.head; image; image = image->next) { 228 if (image->id == id) 229 return image; 230 } 231 232 // For the termination routine, we need to look into the list of 233 // disposable images as well 234 for (image = sDisposableImages.head; image; image = image->next) { 235 if (image->id == id) 236 return image; 237 } 238 239 return NULL; 240 } 241 242 243 static status_t 244 parse_elf_header(struct Elf32_Ehdr *eheader, int32 *_pheaderSize, int32 *_sheaderSize) 245 { 246 if (memcmp(eheader->e_ident, ELF_MAGIC, 4) != 0) 247 return B_NOT_AN_EXECUTABLE; 248 249 if (eheader->e_ident[4] != ELFCLASS32) 250 return B_NOT_AN_EXECUTABLE; 251 252 if (eheader->e_phoff == 0) 253 return B_NOT_AN_EXECUTABLE; 254 255 if (eheader->e_phentsize < sizeof(struct Elf32_Phdr)) 256 return B_NOT_AN_EXECUTABLE; 257 258 *_pheaderSize = eheader->e_phentsize * eheader->e_phnum; 259 *_sheaderSize = eheader->e_shentsize * eheader->e_shnum; 260 261 if (*_pheaderSize <= 0 || *_sheaderSize <= 0) 262 return B_NOT_AN_EXECUTABLE; 263 264 return B_OK; 265 } 266 267 268 static int32 269 count_regions(char const *buff, int phnum, int phentsize) 270 { 271 struct Elf32_Phdr *pheaders; 272 int32 count = 0; 273 int i; 274 275 for (i = 0; i < phnum; i++) { 276 pheaders = (struct Elf32_Phdr *)(buff + i * phentsize); 277 278 switch (pheaders->p_type) { 279 case PT_NULL: 280 /* NOP header */ 281 break; 282 case PT_LOAD: 283 count += 1; 284 if (pheaders->p_memsz != pheaders->p_filesz) { 285 addr_t A = TO_PAGE_SIZE(pheaders->p_vaddr + pheaders->p_memsz); 286 addr_t B = TO_PAGE_SIZE(pheaders->p_vaddr + pheaders->p_filesz); 287 288 if (A != B) 289 count += 1; 290 } 291 break; 292 case PT_DYNAMIC: 293 /* will be handled at some other place */ 294 break; 295 case PT_INTERP: 296 /* should check here for appropiate interpreter */ 297 break; 298 case PT_NOTE: 299 /* unsupported */ 300 break; 301 case PT_SHLIB: 302 /* undefined semantics */ 303 break; 304 case PT_PHDR: 305 /* we don't use it */ 306 break; 307 default: 308 FATAL("unhandled pheader type 0x%lx\n", pheaders[i].p_type); 309 return B_BAD_DATA; 310 } 311 } 312 313 return count; 314 } 315 316 317 /* 318 * create_image() & destroy_image() 319 * 320 * Create and destroy image_t structures. The destroyer makes sure that the 321 * memory buffers are full of garbage before freeing. 322 */ 323 324 static image_t * 325 create_image(const char *name, const char *path, int num_regions) 326 { 327 size_t allocSize = sizeof(image_t) + (num_regions - 1) * sizeof(elf_region_t); 328 const char *lastSlash; 329 330 image_t *image = (image_t*)malloc(allocSize); 331 if (image == NULL) { 332 FATAL("no memory for image %s\n", path); 333 return NULL; 334 } 335 336 memset(image, 0, allocSize); 337 338 strlcpy(image->path, path, sizeof(image->path)); 339 340 // Make the last component of the supplied name the image name. 341 // If present, DT_SONAME will replace this name. 342 if ((lastSlash = strrchr(name, '/'))) 343 strlcpy(image->name, lastSlash + 1, sizeof(image->name)); 344 else 345 strlcpy(image->name, name, sizeof(image->name)); 346 347 image->ref_count = 1; 348 image->num_regions = num_regions; 349 350 return image; 351 } 352 353 354 static void 355 delete_image_struct(image_t *image) 356 { 357 #ifdef DEBUG 358 size_t size = sizeof(image_t) + (image->num_regions - 1) * sizeof(elf_region_t); 359 memset(image->needed, 0xa5, sizeof(image->needed[0]) * image->num_needed); 360 #endif 361 free(image->needed); 362 363 #ifdef DEBUG 364 memset(image, 0xa5, size); 365 #endif 366 free(image); 367 } 368 369 370 static void 371 delete_image(image_t *image) 372 { 373 if (image == NULL) 374 return; 375 376 _kern_unregister_image(image->id); 377 // registered in load_container() 378 379 delete_image_struct(image); 380 } 381 382 383 static status_t 384 parse_program_headers(image_t *image, char *buff, int phnum, int phentsize) 385 { 386 struct Elf32_Phdr *pheader; 387 int regcount; 388 int i; 389 390 regcount = 0; 391 for (i = 0; i < phnum; i++) { 392 pheader = (struct Elf32_Phdr *)(buff + i * phentsize); 393 394 switch (pheader->p_type) { 395 case PT_NULL: 396 /* NOP header */ 397 break; 398 case PT_LOAD: 399 if (pheader->p_memsz == pheader->p_filesz) { 400 /* 401 * everything in one area 402 */ 403 image->regions[regcount].start = pheader->p_vaddr; 404 image->regions[regcount].size = pheader->p_memsz; 405 image->regions[regcount].vmstart = PAGE_BASE(pheader->p_vaddr); 406 image->regions[regcount].vmsize = TO_PAGE_SIZE(pheader->p_memsz 407 + PAGE_OFFSET(pheader->p_vaddr)); 408 image->regions[regcount].fdstart = pheader->p_offset; 409 image->regions[regcount].fdsize = pheader->p_filesz; 410 image->regions[regcount].delta = 0; 411 image->regions[regcount].flags = 0; 412 if (pheader->p_flags & PF_WRITE) { 413 // this is a writable segment 414 image->regions[regcount].flags |= RFLAG_RW; 415 } 416 } else { 417 /* 418 * may require splitting 419 */ 420 addr_t A = TO_PAGE_SIZE(pheader->p_vaddr + pheader->p_memsz); 421 addr_t B = TO_PAGE_SIZE(pheader->p_vaddr + pheader->p_filesz); 422 423 image->regions[regcount].start = pheader->p_vaddr; 424 image->regions[regcount].size = pheader->p_filesz; 425 image->regions[regcount].vmstart = PAGE_BASE(pheader->p_vaddr); 426 image->regions[regcount].vmsize = TO_PAGE_SIZE(pheader->p_filesz 427 + PAGE_OFFSET(pheader->p_vaddr)); 428 image->regions[regcount].fdstart = pheader->p_offset; 429 image->regions[regcount].fdsize = pheader->p_filesz; 430 image->regions[regcount].delta = 0; 431 image->regions[regcount].flags = 0; 432 if (pheader->p_flags & PF_WRITE) { 433 // this is a writable segment 434 image->regions[regcount].flags |= RFLAG_RW; 435 } 436 437 if (A != B) { 438 /* 439 * yeah, it requires splitting 440 */ 441 regcount += 1; 442 image->regions[regcount].start = pheader->p_vaddr; 443 image->regions[regcount].size = pheader->p_memsz - pheader->p_filesz; 444 image->regions[regcount].vmstart = image->regions[regcount-1].vmstart + image->regions[regcount-1].vmsize; 445 image->regions[regcount].vmsize = TO_PAGE_SIZE(pheader->p_memsz + PAGE_OFFSET(pheader->p_vaddr)) 446 - image->regions[regcount-1].vmsize; 447 image->regions[regcount].fdstart = 0; 448 image->regions[regcount].fdsize = 0; 449 image->regions[regcount].delta = 0; 450 image->regions[regcount].flags = RFLAG_ANON; 451 if (pheader->p_flags & PF_WRITE) { 452 // this is a writable segment 453 image->regions[regcount].flags |= RFLAG_RW; 454 } 455 } 456 } 457 regcount += 1; 458 break; 459 case PT_DYNAMIC: 460 image->dynamic_ptr = pheader->p_vaddr; 461 break; 462 case PT_INTERP: 463 /* should check here for appropiate interpreter */ 464 break; 465 case PT_NOTE: 466 /* unsupported */ 467 break; 468 case PT_SHLIB: 469 /* undefined semantics */ 470 break; 471 case PT_PHDR: 472 /* we don't use it */ 473 break; 474 default: 475 FATAL("unhandled pheader type 0x%lx\n", pheader[i].p_type); 476 return B_BAD_DATA; 477 } 478 } 479 480 return B_OK; 481 } 482 483 484 static bool 485 assert_dynamic_loadable(image_t *image) 486 { 487 uint32 i; 488 489 if (!image->dynamic_ptr) 490 return true; 491 492 for (i = 0; i < image->num_regions; i++) { 493 if (image->dynamic_ptr >= image->regions[i].start 494 && image->dynamic_ptr < image->regions[i].start + image->regions[i].size) 495 return true; 496 } 497 498 return false; 499 } 500 501 502 /** This function will change the protection of all read-only segments 503 * to really be read-only. 504 * The areas have to be read/write first, so that they can be relocated. 505 */ 506 507 static void 508 remap_images(void) 509 { 510 image_t *image; 511 uint32 i; 512 513 for (image = sLoadedImages.head; image != NULL; image = image->next) { 514 for (i = 0; i < image->num_regions; i++) { 515 if ((image->regions[i].flags & RFLAG_RW) == 0 516 && (image->regions[i].flags & RFLAG_REMAPPED) == 0) { 517 // we only need to do this once, so we remember those we've already mapped 518 if (_kern_set_area_protection(image->regions[i].id, 519 B_READ_AREA | B_EXECUTE_AREA) == B_OK) 520 image->regions[i].flags |= RFLAG_REMAPPED; 521 } 522 } 523 } 524 } 525 526 527 static status_t 528 map_image(int fd, char const *path, image_t *image, bool fixed) 529 { 530 status_t status = B_OK; 531 const char *baseName; 532 uint32 i; 533 534 (void)(fd); 535 536 // cut the file name from the path as base name for the created areas 537 baseName = strrchr(path, '/'); 538 if (baseName != NULL) 539 baseName++; 540 else 541 baseName = path; 542 543 for (i = 0; i < image->num_regions; i++) { 544 char regionName[B_OS_NAME_LENGTH]; 545 addr_t loadAddress; 546 uint32 addressSpecifier; 547 548 // for BeOS compatibility: if we load an old BeOS executable, we 549 // have to relocate it, if possible - we recognize it because the 550 // vmstart is set to 0 (hopefully always) 551 if (fixed && image->regions[i].vmstart == 0) 552 fixed = false; 553 554 snprintf(regionName, sizeof(regionName), "%s_seg%lu%s", 555 baseName, i, (image->regions[i].flags & RFLAG_RW) ? "rw" : "ro"); 556 557 if (image->dynamic_ptr && !fixed) { 558 // relocatable image... we can afford to place wherever 559 if (i == 0) { 560 // but only the first segment gets a free ride 561 loadAddress = RLD_PROGRAM_BASE; 562 addressSpecifier = B_BASE_ADDRESS; 563 } else { 564 loadAddress = image->regions[i].vmstart + image->regions[i-1].delta; 565 addressSpecifier = B_EXACT_ADDRESS; 566 } 567 } else { 568 // not relocatable, put it where it asks or die trying 569 loadAddress = image->regions[i].vmstart; 570 addressSpecifier = B_EXACT_ADDRESS; 571 } 572 573 if (image->regions[i].flags & RFLAG_ANON) { 574 image->regions[i].id = _kern_create_area(regionName, (void **)&loadAddress, 575 addressSpecifier, image->regions[i].vmsize, B_NO_LOCK, 576 B_READ_AREA | B_WRITE_AREA); 577 578 if (image->regions[i].id < 0) { 579 status = image->regions[i].id; 580 goto error; 581 } 582 583 image->regions[i].delta = loadAddress - image->regions[i].vmstart; 584 image->regions[i].vmstart = loadAddress; 585 } else { 586 image->regions[i].id = sys_vm_map_file(regionName, (void **)&loadAddress, 587 addressSpecifier, image->regions[i].vmsize, B_READ_AREA | B_WRITE_AREA, 588 REGION_PRIVATE_MAP, path, PAGE_BASE(image->regions[i].fdstart)); 589 590 if (image->regions[i].id < 0) { 591 status = image->regions[i].id; 592 goto error; 593 } 594 595 TRACE(("\"%s\" at %p, 0x%lx bytes (%s)\n", path, 596 (void *)loadAddress, image->regions[i].vmsize, 597 image->regions[i].flags & RFLAG_RW ? "rw" : "read-only")); 598 599 image->regions[i].delta = loadAddress - image->regions[i].vmstart; 600 image->regions[i].vmstart = loadAddress; 601 602 // handle trailer bits in data segment 603 if (image->regions[i].flags & RFLAG_RW) { 604 addr_t startClearing; 605 addr_t toClear; 606 607 startClearing = image->regions[i].vmstart 608 + PAGE_OFFSET(image->regions[i].start) 609 + image->regions[i].size; 610 toClear = image->regions[i].vmsize 611 - PAGE_OFFSET(image->regions[i].start) 612 - image->regions[i].size; 613 614 TRACE(("cleared 0x%lx and the following 0x%lx bytes\n", startClearing, toClear)); 615 memset((void *)startClearing, 0, toClear); 616 } 617 } 618 } 619 620 if (image->dynamic_ptr) 621 image->dynamic_ptr += image->regions[0].delta; 622 623 return B_OK; 624 625 error: 626 return status; 627 } 628 629 630 static void 631 unmap_image(image_t *image) 632 { 633 uint32 i; 634 635 for (i = 0; i < image->num_regions; i++) { 636 _kern_delete_area(image->regions[i].id); 637 638 image->regions[i].id = -1; 639 } 640 } 641 642 643 static bool 644 parse_dynamic_segment(image_t *image) 645 { 646 struct Elf32_Dyn *d; 647 int i; 648 int sonameOffset = -1; 649 650 image->symhash = 0; 651 image->syms = 0; 652 image->strtab = 0; 653 654 d = (struct Elf32_Dyn *)image->dynamic_ptr; 655 if (!d) 656 return true; 657 658 for (i = 0; d[i].d_tag != DT_NULL; i++) { 659 switch (d[i].d_tag) { 660 case DT_NEEDED: 661 image->num_needed += 1; 662 break; 663 case DT_HASH: 664 image->symhash = (uint32 *)(d[i].d_un.d_ptr + image->regions[0].delta); 665 break; 666 case DT_STRTAB: 667 image->strtab = (char *)(d[i].d_un.d_ptr + image->regions[0].delta); 668 break; 669 case DT_SYMTAB: 670 image->syms = (struct Elf32_Sym *)(d[i].d_un.d_ptr + image->regions[0].delta); 671 break; 672 case DT_REL: 673 image->rel = (struct Elf32_Rel *)(d[i].d_un.d_ptr + image->regions[0].delta); 674 break; 675 case DT_RELSZ: 676 image->rel_len = d[i].d_un.d_val; 677 break; 678 case DT_RELA: 679 image->rela = (struct Elf32_Rela *)(d[i].d_un.d_ptr + image->regions[0].delta); 680 break; 681 case DT_RELASZ: 682 image->rela_len = d[i].d_un.d_val; 683 break; 684 // TK: procedure linkage table 685 case DT_JMPREL: 686 image->pltrel = (struct Elf32_Rel *)(d[i].d_un.d_ptr + image->regions[0].delta); 687 break; 688 case DT_PLTRELSZ: 689 image->pltrel_len = d[i].d_un.d_val; 690 break; 691 case DT_INIT: 692 image->init_routine = (d[i].d_un.d_ptr + image->regions[0].delta); 693 break; 694 case DT_FINI: 695 image->term_routine = (d[i].d_un.d_ptr + image->regions[0].delta); 696 break; 697 case DT_SONAME: 698 sonameOffset = d[i].d_un.d_val; 699 break; 700 default: 701 continue; 702 } 703 } 704 705 // lets make sure we found all the required sections 706 if (!image->symhash || !image->syms || !image->strtab) 707 return false; 708 709 if (sonameOffset >= 0) 710 strlcpy(image->name, STRING(image, sonameOffset), sizeof(image->name)); 711 712 return true; 713 } 714 715 716 static struct Elf32_Sym * 717 find_symbol(image_t *image, const char *name, int32 type) 718 { 719 uint32 hash, i; 720 721 // ToDo: "type" is currently ignored! 722 (void)type; 723 724 if (image->dynamic_ptr == NULL) 725 return NULL; 726 727 hash = elf_hash((uint8 *)name) % HASHTABSIZE(image); 728 729 for (i = HASHBUCKETS(image)[hash]; i != STN_UNDEF; i = HASHCHAINS(image)[i]) { 730 struct Elf32_Sym *symbol = &image->syms[i]; 731 732 if (symbol->st_shndx != SHN_UNDEF 733 && ((ELF32_ST_BIND(symbol->st_info)== STB_GLOBAL) 734 || (ELF32_ST_BIND(symbol->st_info) == STB_WEAK)) 735 && !strcmp(SYMNAME(image, symbol), name)) { 736 // check if the type matches 737 if ((type == B_SYMBOL_TYPE_TEXT && ELF32_ST_TYPE(symbol->st_info) != STT_FUNC) 738 || (type == B_SYMBOL_TYPE_DATA && ELF32_ST_TYPE(symbol->st_info) != STT_OBJECT)) 739 continue; 740 741 return symbol; 742 } 743 } 744 745 return NULL; 746 } 747 748 749 static struct Elf32_Sym* 750 find_symbol_recursively_impl(image_t* image, const char* name, 751 image_t** foundInImage) 752 { 753 image->flags |= RFLAG_VISITED; 754 755 struct Elf32_Sym *symbol; 756 757 // look up the symbol in this image 758 if (image->dynamic_ptr) { 759 symbol = find_symbol(image, name, B_SYMBOL_TYPE_ANY); 760 if (symbol) { 761 *foundInImage = image; 762 return symbol; 763 } 764 } 765 766 // recursively search dependencies 767 for (uint32 i = 0; i < image->num_needed; i++) { 768 if (!(image->needed[i]->flags & RFLAG_VISITED)) { 769 symbol = find_symbol_recursively_impl(image->needed[i], name, 770 foundInImage); 771 if (symbol) 772 return symbol; 773 } 774 } 775 776 return NULL; 777 } 778 779 780 static void 781 clear_image_flag_recursively(image_t* image, uint32 flag) 782 { 783 image->flags &= ~flag; 784 785 for (uint32 i = 0; i < image->num_needed; i++) { 786 if (image->needed[i]->flags & flag) 787 clear_image_flag_recursively(image->needed[i], flag); 788 } 789 } 790 791 792 static struct Elf32_Sym* 793 find_symbol_recursively(image_t* image, const char* name, 794 image_t** foundInImage) 795 { 796 struct Elf32_Sym* symbol = find_symbol_recursively_impl(image, name, 797 foundInImage); 798 clear_image_flag_recursively(image, RFLAG_VISITED); 799 return symbol; 800 } 801 802 803 static struct Elf32_Sym* 804 find_symbol_in_loaded_images(const char* name, image_t** foundInImage) 805 { 806 return find_symbol_recursively(sLoadedImages.head, name, foundInImage); 807 } 808 809 810 static struct Elf32_Sym* 811 find_undefined_symbol(image_t* rootImage, image_t* image, const char* name, 812 image_t** foundInImage) 813 { 814 // If not simulating BeOS style symbol resolution, undefined symbols are 815 // search recursively starting from the root image. (Note, breadth first 816 // might be better than the depth first use here.) 817 if (!sResolveSymbolsBeOSStyle) 818 return find_symbol_recursively(rootImage, name, foundInImage); 819 820 // BeOS style symbol resolution: It is sufficient to check the direct 821 // dependencies. The linker would have complained, if the symbol wasn't 822 // there. 823 for (uint32 i = 0; i < image->num_needed; i++) { 824 if (image->needed[i]->dynamic_ptr) { 825 struct Elf32_Sym *symbol = find_symbol(image->needed[i], name, 826 B_SYMBOL_TYPE_ANY); 827 if (symbol) { 828 *foundInImage = image->needed[i]; 829 return symbol; 830 } 831 } 832 } 833 834 return NULL; 835 } 836 837 838 int 839 resolve_symbol(image_t *rootImage, image_t *image, struct Elf32_Sym *sym, 840 addr_t *sym_addr) 841 { 842 struct Elf32_Sym *sym2; 843 char *symname; 844 image_t *shimg; 845 846 switch (sym->st_shndx) { 847 case SHN_UNDEF: 848 // patch the symbol name 849 symname = SYMNAME(image, sym); 850 851 // it's undefined, must be outside this image, try the other images 852 sym2 = find_undefined_symbol(rootImage, image, symname, &shimg); 853 if (!sym2) { 854 printf("elf_resolve_symbol: could not resolve symbol '%s'\n", symname); 855 return B_MISSING_SYMBOL; 856 } 857 858 // make sure they're the same type 859 if (ELF32_ST_TYPE(sym->st_info) != STT_NOTYPE 860 && ELF32_ST_TYPE(sym->st_info) != ELF32_ST_TYPE(sym2->st_info)) { 861 printf("elf_resolve_symbol: found symbol '%s' in shared image but wrong type\n", symname); 862 return B_MISSING_SYMBOL; 863 } 864 865 if (ELF32_ST_BIND(sym2->st_info) != STB_GLOBAL 866 && ELF32_ST_BIND(sym2->st_info) != STB_WEAK) { 867 printf("elf_resolve_symbol: found symbol '%s' but not exported\n", symname); 868 return B_MISSING_SYMBOL; 869 } 870 871 *sym_addr = sym2->st_value + shimg->regions[0].delta; 872 return B_NO_ERROR; 873 874 case SHN_ABS: 875 *sym_addr = sym->st_value + image->regions[0].delta; 876 return B_NO_ERROR; 877 878 case SHN_COMMON: 879 // ToDo: finish this 880 printf("elf_resolve_symbol: COMMON symbol, finish me!\n"); 881 return B_ERROR; //ERR_NOT_IMPLEMENTED_YET; 882 883 default: 884 // standard symbol 885 *sym_addr = sym->st_value + image->regions[0].delta; 886 return B_NO_ERROR; 887 } 888 } 889 890 891 static void 892 register_image(image_t *image, int fd, const char *path) 893 { 894 struct stat stat; 895 image_info info; 896 897 // ToDo: set these correctly 898 info.id = 0; 899 info.type = image->type; 900 info.sequence = 0; 901 info.init_order = 0; 902 info.init_routine = (void (*)())image->init_routine; 903 info.term_routine = (void (*)())image->term_routine; 904 905 if (_kern_read_stat(fd, NULL, false, &stat, sizeof(struct stat)) == B_OK) { 906 info.device = stat.st_dev; 907 info.node = stat.st_ino; 908 } else { 909 info.device = -1; 910 info.node = -1; 911 } 912 913 strlcpy(info.name, path, sizeof(info.name)); 914 info.text = (void *)image->regions[0].vmstart; 915 info.text_size = image->regions[0].vmsize; 916 info.data = (void *)image->regions[1].vmstart; 917 info.data_size = image->regions[1].vmsize; 918 image->id = _kern_register_image(&info, sizeof(image_info)); 919 } 920 921 922 static status_t 923 relocate_image(image_t *rootImage, image_t *image) 924 { 925 status_t status = arch_relocate_image(rootImage, image); 926 if (status < B_OK) { 927 FATAL("troubles relocating: 0x%lx (image: %s)\n", status, image->name); 928 return status; 929 } 930 931 _kern_image_relocated(image->id); 932 return B_OK; 933 } 934 935 936 static status_t 937 load_container(char const *name, image_type type, const char *rpath, image_t **_image) 938 { 939 int32 pheaderSize, sheaderSize; 940 char path[PATH_MAX]; 941 ssize_t length; 942 char ph_buff[4096]; 943 int32 numRegions; 944 image_t *found; 945 image_t *image; 946 status_t status; 947 int fd; 948 949 struct Elf32_Ehdr eheader; 950 951 // Have we already loaded that image? Don't check for add-ons -- we always 952 // reload them. 953 if (type != B_ADD_ON_IMAGE) { 954 found = find_image(name, APP_OR_LIBRARY_TYPE); 955 if (found) { 956 atomic_add(&found->ref_count, 1); 957 *_image = found; 958 return B_OK; 959 } 960 } 961 962 strlcpy(path, name, sizeof(path)); 963 964 // Try to load explicit image path first 965 fd = open_executable(path, type, rpath); 966 if (fd < 0) { 967 FATAL("cannot open file %s\n", path); 968 return fd; 969 } 970 971 // If the path is not absolute, we prepend the CWD to make it one. 972 if (path[0] != '/') { 973 char relativePath[PATH_MAX]; 974 if (!strncmp(path, "./", 2)) 975 strcpy(relativePath, path + 2); 976 else 977 strcpy(relativePath, path); 978 979 // get the CWD 980 status = _kern_getcwd(path, sizeof(path)); 981 if (status < B_OK) { 982 FATAL("_kern_getcwd() failed\n"); 983 goto err1; 984 } 985 986 if (strlcat(path, "/", sizeof(path)) >= sizeof(path) 987 || strlcat(path, relativePath, sizeof(path)) >= sizeof(path)) { 988 status = B_NAME_TOO_LONG; 989 FATAL("Absolute path of image %s is too " 990 "long!\n", relativePath); 991 goto err1; 992 } 993 } 994 995 // Test again if this image has been registered already - this time, 996 // we can check the full path, not just its name as noted. 997 // You could end up loading an image twice with symbolic links, else. 998 if (type != B_ADD_ON_IMAGE) { 999 found = find_image(path, APP_OR_LIBRARY_TYPE); 1000 if (found) { 1001 atomic_add(&found->ref_count, 1); 1002 *_image = found; 1003 return B_OK; 1004 } 1005 } 1006 1007 length = _kern_read(fd, 0, &eheader, sizeof(eheader)); 1008 if (length != sizeof(eheader)) { 1009 status = B_NOT_AN_EXECUTABLE; 1010 FATAL("troubles reading ELF header\n"); 1011 goto err1; 1012 } 1013 1014 status = parse_elf_header(&eheader, &pheaderSize, &sheaderSize); 1015 if (status < B_OK) { 1016 FATAL("incorrect ELF header\n"); 1017 goto err1; 1018 } 1019 1020 // ToDo: what to do about this restriction?? 1021 if (pheaderSize > (int)sizeof(ph_buff)) { 1022 FATAL("Cannot handle program headers bigger than %lu\n", sizeof(ph_buff)); 1023 status = B_UNSUPPORTED; 1024 goto err1; 1025 } 1026 1027 length = _kern_read(fd, eheader.e_phoff, ph_buff, pheaderSize); 1028 if (length != pheaderSize) { 1029 FATAL("Could not read program headers: %s\n", strerror(length)); 1030 status = B_BAD_DATA; 1031 goto err1; 1032 } 1033 1034 numRegions = count_regions(ph_buff, eheader.e_phnum, eheader.e_phentsize); 1035 if (numRegions <= 0) { 1036 FATAL("Troubles parsing Program headers, numRegions = %ld\n", numRegions); 1037 status = B_BAD_DATA; 1038 goto err1; 1039 } 1040 1041 image = create_image(name, path, numRegions); 1042 if (image == NULL) { 1043 FATAL("Failed to allocate image_t object\n"); 1044 status = B_NO_MEMORY; 1045 goto err1; 1046 } 1047 1048 status = parse_program_headers(image, ph_buff, eheader.e_phnum, eheader.e_phentsize); 1049 if (status < B_OK) 1050 goto err2; 1051 1052 if (!assert_dynamic_loadable(image)) { 1053 FATAL("Dynamic segment must be loadable (implementation restriction)\n"); 1054 status = B_UNSUPPORTED; 1055 goto err2; 1056 } 1057 1058 status = map_image(fd, path, image, type == B_APP_IMAGE); 1059 if (status < B_OK) { 1060 FATAL("Could not map image: %s\n", strerror(status)); 1061 status = B_ERROR; 1062 goto err2; 1063 } 1064 1065 if (!parse_dynamic_segment(image)) { 1066 FATAL("Troubles handling dynamic section\n"); 1067 status = B_BAD_DATA; 1068 goto err3; 1069 } 1070 1071 if (eheader.e_entry != NULL) 1072 image->entry_point = eheader.e_entry + image->regions[0].delta; 1073 1074 image->type = type; 1075 register_image(image, fd, path); 1076 1077 _kern_close(fd); 1078 1079 enqueue_image(&sLoadedImages, image); 1080 sLoadedImageCount++; 1081 1082 *_image = image; 1083 return B_OK; 1084 1085 err3: 1086 unmap_image(image); 1087 err2: 1088 delete_image_struct(image); 1089 err1: 1090 _kern_close(fd); 1091 return status; 1092 } 1093 1094 1095 static const char * 1096 find_dt_rpath(image_t *image) 1097 { 1098 int i; 1099 struct Elf32_Dyn *d = (struct Elf32_Dyn *)image->dynamic_ptr; 1100 1101 for (i = 0; d[i].d_tag != DT_NULL; i++) { 1102 if (d[i].d_tag == DT_RPATH) 1103 return STRING(image, d[i].d_un.d_val); 1104 } 1105 1106 return NULL; 1107 } 1108 1109 1110 static status_t 1111 load_dependencies(image_t *image) 1112 { 1113 struct Elf32_Dyn *d = (struct Elf32_Dyn *)image->dynamic_ptr; 1114 bool reportErrors = report_errors(); 1115 status_t status = B_OK; 1116 uint32 i, j; 1117 const char *rpath; 1118 1119 if (!d || (image->flags & RFLAG_DEPENDENCIES_LOADED)) 1120 return B_OK; 1121 1122 image->flags |= RFLAG_DEPENDENCIES_LOADED; 1123 1124 if (image->num_needed == 0) 1125 return B_OK; 1126 1127 image->needed = (image_t**)malloc(image->num_needed * sizeof(image_t *)); 1128 if (image->needed == NULL) { 1129 FATAL("failed to allocate needed struct\n"); 1130 return B_NO_MEMORY; 1131 } 1132 1133 memset(image->needed, 0, image->num_needed * sizeof(image_t *)); 1134 rpath = find_dt_rpath(image); 1135 1136 for (i = 0, j = 0; d[i].d_tag != DT_NULL; i++) { 1137 switch (d[i].d_tag) { 1138 case DT_NEEDED: 1139 { 1140 int32 neededOffset = d[i].d_un.d_val; 1141 const char *name = STRING(image, neededOffset); 1142 1143 status_t loadStatus = load_container(name, B_LIBRARY_IMAGE, 1144 rpath, &image->needed[j]); 1145 if (loadStatus < B_OK) { 1146 status = loadStatus; 1147 // correct error code in case the file could not been found 1148 if (status == B_ENTRY_NOT_FOUND) { 1149 status = B_MISSING_LIBRARY; 1150 1151 if (reportErrors) 1152 sErrorMessage.AddString("missing library", name); 1153 } 1154 1155 // Collect all missing libraries in case we report back 1156 if (!reportErrors) 1157 return status; 1158 } 1159 1160 j += 1; 1161 break; 1162 } 1163 1164 default: 1165 // ignore any other tag 1166 continue; 1167 } 1168 } 1169 1170 if (status < B_OK) 1171 return status; 1172 1173 if (j != image->num_needed) { 1174 FATAL("Internal error at load_dependencies()"); 1175 return B_ERROR; 1176 } 1177 1178 return B_OK; 1179 } 1180 1181 1182 static uint32 1183 topological_sort(image_t *image, uint32 slot, image_t **initList, 1184 uint32 sortFlag) 1185 { 1186 uint32 i; 1187 1188 if (image->flags & sortFlag) 1189 return slot; 1190 1191 image->flags |= sortFlag; /* make sure we don't visit this one */ 1192 for (i = 0; i < image->num_needed; i++) 1193 slot = topological_sort(image->needed[i], slot, initList, sortFlag); 1194 1195 initList[slot] = image; 1196 return slot + 1; 1197 } 1198 1199 1200 static ssize_t 1201 get_sorted_image_list(image_t *image, image_t ***_list, uint32 sortFlag) 1202 { 1203 image_t **list; 1204 1205 list = (image_t**)malloc(sLoadedImageCount * sizeof(image_t *)); 1206 if (list == NULL) { 1207 FATAL("memory shortage in get_sorted_image_list()"); 1208 *_list = NULL; 1209 return B_NO_MEMORY; 1210 } 1211 1212 memset(list, 0, sLoadedImageCount * sizeof(image_t *)); 1213 1214 *_list = list; 1215 return topological_sort(image, 0, list, sortFlag); 1216 } 1217 1218 1219 static status_t 1220 relocate_dependencies(image_t *image) 1221 { 1222 ssize_t count, i; 1223 image_t **list; 1224 1225 count = get_sorted_image_list(image, &list, RFLAG_RELOCATED); 1226 if (count < B_OK) 1227 return count; 1228 1229 for (i = 0; i < count; i++) { 1230 status_t status = relocate_image(image, list[i]); 1231 if (status < B_OK) 1232 return status; 1233 } 1234 1235 free(list); 1236 return B_OK; 1237 } 1238 1239 1240 static void 1241 init_dependencies(image_t *image, bool initHead) 1242 { 1243 image_t **initList; 1244 ssize_t count, i; 1245 1246 count = get_sorted_image_list(image, &initList, RFLAG_INITIALIZED); 1247 if (count <= 0) 1248 return; 1249 1250 if (!initHead) { 1251 // this removes the "calling" image 1252 image->flags &= ~RFLAG_INITIALIZED; 1253 initList[--count] = NULL; 1254 } 1255 1256 TRACE(("%ld: init dependencies\n", find_thread(NULL))); 1257 for (i = 0; i < count; i++) { 1258 image = initList[i]; 1259 1260 TRACE(("%ld: init: %s\n", find_thread(NULL), image->name)); 1261 1262 if (image->init_routine != NULL) 1263 ((init_term_function)image->init_routine)(image->id); 1264 } 1265 TRACE(("%ld: init done.\n", find_thread(NULL))); 1266 1267 free(initList); 1268 } 1269 1270 1271 static void 1272 put_image(image_t *image) 1273 { 1274 // If all references to the image are gone, add it to the disposable list 1275 // and remove all dependencies 1276 1277 if (atomic_add(&image->ref_count, -1) == 1) { 1278 size_t i; 1279 1280 dequeue_image(&sLoadedImages, image); 1281 enqueue_image(&sDisposableImages, image); 1282 sLoadedImageCount--; 1283 1284 for (i = 0; i < image->num_needed; i++) { 1285 put_image(image->needed[i]); 1286 } 1287 } 1288 } 1289 1290 1291 // #pragma mark - libroot.so exported functions 1292 1293 1294 image_id 1295 load_program(char const *path, void **_entry) 1296 { 1297 status_t status; 1298 image_t *image; 1299 1300 rld_lock(); 1301 // for now, just do stupid simple global locking 1302 1303 TRACE(("rld: load %s\n", path)); 1304 1305 status = load_container(path, B_APP_IMAGE, NULL, &sProgramImage); 1306 if (status < B_OK) 1307 goto err; 1308 1309 for (image = sLoadedImages.head; image != NULL; image = image->next) { 1310 status = load_dependencies(image); 1311 if (status < B_OK) 1312 goto err; 1313 } 1314 1315 status = relocate_dependencies(sProgramImage); 1316 if (status < B_OK) 1317 goto err; 1318 1319 // We patch any exported __gRuntimeLoader symbols to point to our private API 1320 { 1321 struct Elf32_Sym *symbol = find_symbol_in_loaded_images( 1322 "__gRuntimeLoader", &image); 1323 if (symbol != NULL) { 1324 void **_export = (void **)(symbol->st_value + image->regions[0].delta); 1325 *_export = &gRuntimeLoader; 1326 } 1327 } 1328 1329 init_dependencies(sLoadedImages.head, true); 1330 remap_images(); 1331 // ToDo: once setup_system_time() is fixed, move this one line higher! 1332 1333 // Since the images are initialized now, we no longer should use our 1334 // getenv(), but use the one from libroot.so 1335 { 1336 struct Elf32_Sym *symbol = find_symbol_in_loaded_images("getenv", 1337 &image); 1338 if (symbol != NULL) 1339 gGetEnv = (char* (*)(const char*)) 1340 (symbol->st_value + image->regions[0].delta); 1341 } 1342 1343 if (sProgramImage->entry_point == NULL) { 1344 status = B_NOT_AN_EXECUTABLE; 1345 goto err; 1346 } 1347 1348 *_entry = (void *)(sProgramImage->entry_point); 1349 1350 rld_unlock(); 1351 return sProgramImage->id; 1352 1353 err: 1354 delete_image(sProgramImage); 1355 1356 if (report_errors()) { 1357 // send error message 1358 sErrorMessage.AddInt32("error", status); 1359 sErrorMessage.SetDeliveryInfo(gProgramArgs->error_token, 1360 -1, 0, find_thread(NULL)); 1361 1362 _kern_write_port_etc(gProgramArgs->error_port, 'KMSG', 1363 sErrorMessage.Buffer(), sErrorMessage.ContentSize(), 0, 0); 1364 } 1365 _kern_loading_app_failed(status); 1366 rld_unlock(); 1367 1368 return status; 1369 } 1370 1371 1372 image_id 1373 load_library(char const *path, uint32 flags, bool addOn) 1374 { 1375 image_t *image = NULL; 1376 image_t *iter; 1377 image_type type = (addOn ? B_ADD_ON_IMAGE : B_LIBRARY_IMAGE); 1378 status_t status; 1379 1380 if (path == NULL) 1381 return B_BAD_VALUE; 1382 1383 // ToDo: implement flags 1384 (void)flags; 1385 1386 rld_lock(); 1387 // for now, just do stupid simple global locking 1388 1389 // have we already loaded this library? 1390 // Checking it at this stage saves loading its dependencies again 1391 if (!addOn) { 1392 image = find_image(path, APP_OR_LIBRARY_TYPE); 1393 if (image) { 1394 atomic_add(&image->ref_count, 1); 1395 rld_unlock(); 1396 return image->id; 1397 } 1398 } 1399 1400 status = load_container(path, type, NULL, &image); 1401 if (status < B_OK) { 1402 rld_unlock(); 1403 return status; 1404 } 1405 1406 for (iter = sLoadedImages.head; iter; iter = iter->next) { 1407 status = load_dependencies(iter); 1408 if (status < B_OK) 1409 goto err; 1410 } 1411 1412 status = relocate_dependencies(image); 1413 if (status < B_OK) 1414 goto err; 1415 1416 remap_images(); 1417 init_dependencies(image, true); 1418 1419 rld_unlock(); 1420 return image->id; 1421 1422 err: 1423 dequeue_image(&sLoadedImages, image); 1424 sLoadedImageCount--; 1425 delete_image(image); 1426 rld_unlock(); 1427 return status; 1428 } 1429 1430 1431 status_t 1432 unload_library(image_id imageID, bool addOn) 1433 { 1434 status_t status = B_BAD_IMAGE_ID; 1435 image_t *image; 1436 image_type type = addOn ? B_ADD_ON_IMAGE : B_LIBRARY_IMAGE; 1437 1438 if (imageID < B_OK) 1439 return B_BAD_IMAGE_ID; 1440 1441 rld_lock(); 1442 // for now, just do stupid simple global locking 1443 1444 // we only check images that have been already initialized 1445 1446 for (image = sLoadedImages.head; image; image = image->next) { 1447 if (image->id == imageID) { 1448 // unload image 1449 if (type == image->type) { 1450 put_image(image); 1451 status = B_OK; 1452 } else 1453 status = B_BAD_VALUE; 1454 break; 1455 } 1456 } 1457 1458 if (status == B_OK) { 1459 while ((image = sDisposableImages.head) != NULL) { 1460 // call image fini here... 1461 if (image->term_routine) 1462 ((init_term_function)image->term_routine)(image->id); 1463 1464 dequeue_image(&sDisposableImages, image); 1465 unmap_image(image); 1466 1467 delete_image(image); 1468 } 1469 } 1470 1471 rld_unlock(); 1472 return status; 1473 } 1474 1475 1476 status_t 1477 get_nth_symbol(image_id imageID, int32 num, char *nameBuffer, int32 *_nameLength, 1478 int32 *_type, void **_location) 1479 { 1480 int32 count = 0, j; 1481 uint32 i; 1482 image_t *image; 1483 1484 rld_lock(); 1485 1486 // get the image from those who have been already initialized 1487 image = find_loaded_image_by_id(imageID); 1488 if (image == NULL) { 1489 rld_unlock(); 1490 return B_BAD_IMAGE_ID; 1491 } 1492 1493 // iterate through all the hash buckets until we've found the one 1494 for (i = 0; i < HASHTABSIZE(image); i++) { 1495 for (j = HASHBUCKETS(image)[i]; j != STN_UNDEF; j = HASHCHAINS(image)[j]) { 1496 struct Elf32_Sym *symbol = &image->syms[i]; 1497 1498 if (count == num) { 1499 strlcpy(nameBuffer, SYMNAME(image, symbol), *_nameLength); 1500 *_nameLength = strlen(SYMNAME(image, symbol)); 1501 1502 if (_type != NULL) { 1503 // ToDo: check with the return types of that BeOS function 1504 if (ELF32_ST_TYPE(symbol->st_info) == STT_FUNC) 1505 *_type = B_SYMBOL_TYPE_TEXT; 1506 else if (ELF32_ST_TYPE(symbol->st_info) == STT_OBJECT) 1507 *_type = B_SYMBOL_TYPE_DATA; 1508 else 1509 *_type = B_SYMBOL_TYPE_ANY; 1510 } 1511 1512 if (_location != NULL) 1513 *_location = (void *)(symbol->st_value + image->regions[0].delta); 1514 goto out; 1515 } 1516 count++; 1517 } 1518 } 1519 out: 1520 rld_unlock(); 1521 1522 if (num != count) 1523 return B_BAD_INDEX; 1524 1525 return B_OK; 1526 } 1527 1528 1529 status_t 1530 get_symbol(image_id imageID, char const *symbolName, int32 symbolType, void **_location) 1531 { 1532 status_t status = B_OK; 1533 image_t *image; 1534 1535 if (imageID < B_OK) 1536 return B_BAD_IMAGE_ID; 1537 if (symbolName == NULL) 1538 return B_BAD_VALUE; 1539 1540 rld_lock(); 1541 // for now, just do stupid simple global locking 1542 1543 // get the image from those who have been already initialized 1544 image = find_loaded_image_by_id(imageID); 1545 if (image != NULL) { 1546 struct Elf32_Sym *symbol; 1547 1548 // get the symbol in the image 1549 symbol = find_symbol(image, symbolName, symbolType); 1550 if (symbol) { 1551 if (_location != NULL) 1552 *_location = (void *)(symbol->st_value + image->regions[0].delta); 1553 } else 1554 status = B_ENTRY_NOT_FOUND; 1555 } else 1556 status = B_BAD_IMAGE_ID; 1557 1558 rld_unlock(); 1559 return status; 1560 } 1561 1562 1563 status_t 1564 get_next_image_dependency(image_id id, uint32 *cookie, const char **_name) 1565 { 1566 uint32 i, j, searchIndex = *cookie; 1567 struct Elf32_Dyn *dynamicSection; 1568 image_t *image; 1569 1570 if (_name == NULL) 1571 return B_BAD_VALUE; 1572 1573 rld_lock(); 1574 1575 image = find_loaded_image_by_id(id); 1576 if (image == NULL) { 1577 rld_unlock(); 1578 return B_BAD_IMAGE_ID; 1579 } 1580 1581 dynamicSection = (struct Elf32_Dyn *)image->dynamic_ptr; 1582 if (dynamicSection == NULL || image->num_needed <= searchIndex) { 1583 rld_unlock(); 1584 return B_ENTRY_NOT_FOUND; 1585 } 1586 1587 for (i = 0, j = 0; dynamicSection[i].d_tag != DT_NULL; i++) { 1588 if (dynamicSection[i].d_tag != DT_NEEDED) 1589 continue; 1590 1591 if (j++ == searchIndex) { 1592 int32 neededOffset = dynamicSection[i].d_un.d_val; 1593 1594 *_name = STRING(image, neededOffset); 1595 *cookie = searchIndex + 1; 1596 rld_unlock(); 1597 return B_OK; 1598 } 1599 } 1600 1601 rld_unlock(); 1602 return B_ENTRY_NOT_FOUND; 1603 } 1604 1605 1606 // #pragma mark - runtime_loader private exports 1607 1608 1609 /** Read and verify the ELF header */ 1610 1611 status_t 1612 elf_verify_header(void *header, int32 length) 1613 { 1614 int32 programSize, sectionSize; 1615 1616 if (length < (int32)sizeof(struct Elf32_Ehdr)) 1617 return B_NOT_AN_EXECUTABLE; 1618 1619 return parse_elf_header((struct Elf32_Ehdr *)header, &programSize, §ionSize); 1620 } 1621 1622 1623 void 1624 terminate_program(void) 1625 { 1626 image_t **termList; 1627 ssize_t count, i; 1628 1629 count = get_sorted_image_list(sProgramImage, &termList, RFLAG_TERMINATED); 1630 if (count < B_OK) 1631 return; 1632 1633 TRACE(("%ld: terminate dependencies\n", find_thread(NULL))); 1634 for (i = count; i-- > 0;) { 1635 image_t *image = termList[i]; 1636 1637 TRACE(("%ld: term: %s\n", find_thread(NULL), image->name)); 1638 1639 if (image->term_routine) 1640 ((init_term_function)image->term_routine)(image->id); 1641 } 1642 TRACE(("%ld: term done.\n", find_thread(NULL))); 1643 1644 free(termList); 1645 } 1646 1647 1648 void 1649 rldelf_init(void) 1650 { 1651 rld_sem = create_sem(1, "rld_lock"); 1652 rld_sem_owner = -1; 1653 rld_sem_count = 0; 1654 1655 // create the debug area 1656 { 1657 int32 size = TO_PAGE_SIZE(sizeof(runtime_loader_debug_area)); 1658 1659 runtime_loader_debug_area *area; 1660 area_id areaID = _kern_create_area(RUNTIME_LOADER_DEBUG_AREA_NAME, 1661 (void **)&area, B_ANY_ADDRESS, size, B_NO_LOCK, 1662 B_READ_AREA | B_WRITE_AREA); 1663 if (areaID < B_OK) { 1664 FATAL("Failed to create debug area.\n"); 1665 _kern_loading_app_failed(areaID); 1666 } 1667 1668 area->loaded_images = &sLoadedImages; 1669 } 1670 1671 // initialize error message if needed 1672 if (report_errors()) { 1673 void *buffer = malloc(1024); 1674 if (buffer == NULL) 1675 return; 1676 1677 sErrorMessage.SetTo(buffer, 1024, 'Rler'); 1678 } 1679 } 1680 1681 1682 status_t 1683 elf_reinit_after_fork() 1684 { 1685 rld_sem = create_sem(1, "rld_lock"); 1686 if (rld_sem < 0) 1687 return rld_sem; 1688 1689 return B_OK; 1690 } 1691