1 /* 2 * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Copyright 2003-2011, 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 "images.h" 12 13 #include <stdio.h> 14 #include <stdlib.h> 15 #include <string.h> 16 17 #include <algorithm> 18 19 #include <syscalls.h> 20 #include <vm_defs.h> 21 22 #include "add_ons.h" 23 #include "runtime_loader_private.h" 24 25 26 // keep in sync with app ldscript 27 #ifdef __x86_64__ 28 // runtime_loader potentially occupies 0x200000 - 0x600000 due to large 29 // page segment alignment. 30 # define RLD_PROGRAM_BASE 0x600000 31 # define MAX_PAGE_SIZE 0x200000 32 #else 33 # define RLD_PROGRAM_BASE 0x200000 34 # define MAX_PAGE_SIZE B_PAGE_SIZE 35 #endif 36 37 38 bool gInvalidImageIDs; 39 40 static image_queue_t sLoadedImages = {0, 0}; 41 static image_queue_t sDisposableImages = {0, 0}; 42 static uint32 sLoadedImageCount = 0; 43 44 45 //! Remaps the image ID of \a image after fork. 46 static status_t 47 update_image_id(image_t* image) 48 { 49 int32 cookie = 0; 50 image_info info; 51 while (_kern_get_next_image_info(B_CURRENT_TEAM, &cookie, &info, 52 sizeof(image_info)) == B_OK) { 53 for (uint32 i = 0; i < image->num_regions; i++) { 54 if (image->regions[i].vmstart == (addr_t)info.text) { 55 image->id = info.id; 56 return B_OK; 57 } 58 } 59 } 60 61 FATAL("Could not update image ID %" B_PRId32 " after fork()!\n", image->id); 62 return B_ENTRY_NOT_FOUND; 63 } 64 65 66 static void 67 enqueue_image(image_queue_t* queue, image_t* image) 68 { 69 image->next = NULL; 70 71 image->prev = queue->tail; 72 if (queue->tail) 73 queue->tail->next = image; 74 75 queue->tail = image; 76 if (!queue->head) 77 queue->head = image; 78 } 79 80 81 static void 82 dequeue_image(image_queue_t* queue, image_t* image) 83 { 84 if (image->next) 85 image->next->prev = image->prev; 86 else 87 queue->tail = image->prev; 88 89 if (image->prev) 90 image->prev->next = image->next; 91 else 92 queue->head = image->next; 93 94 image->prev = NULL; 95 image->next = NULL; 96 } 97 98 99 static image_t* 100 find_image_in_queue(image_queue_t* queue, const char* name, bool isPath, 101 uint32 typeMask) 102 { 103 for (image_t* image = queue->head; image; image = image->next) { 104 const char* imageName = isPath ? image->path : image->name; 105 int length = isPath ? sizeof(image->path) : sizeof(image->name); 106 107 if (!strncmp(imageName, name, length) 108 && (typeMask & IMAGE_TYPE_TO_MASK(image->type)) != 0) { 109 return image; 110 } 111 } 112 113 return NULL; 114 } 115 116 117 static void 118 update_image_flags_recursively(image_t* image, uint32 flagsToSet, 119 uint32 flagsToClear) 120 { 121 image_t* queue[sLoadedImageCount]; 122 uint32 count = 0; 123 uint32 index = 0; 124 queue[count++] = image; 125 image->flags |= RFLAG_VISITED; 126 127 while (index < count) { 128 // pop next image 129 image = queue[index++]; 130 131 // push dependencies 132 for (uint32 i = 0; i < image->num_needed; i++) { 133 image_t* needed = image->needed[i]; 134 if ((needed->flags & RFLAG_VISITED) == 0) { 135 queue[count++] = needed; 136 needed->flags |= RFLAG_VISITED; 137 } 138 } 139 } 140 141 // update flags 142 for (uint32 i = 0; i < count; i++) { 143 queue[i]->flags = (queue[i]->flags | flagsToSet) 144 & ~(flagsToClear | RFLAG_VISITED); 145 } 146 } 147 148 149 static uint32 150 topological_sort(image_t* image, uint32 slot, image_t** initList, 151 uint32 sortFlag) 152 { 153 if (image->flags & sortFlag) 154 return slot; 155 156 image->flags |= sortFlag; /* make sure we don't visit this one */ 157 for (uint32 i = 0; i < image->num_needed; i++) 158 slot = topological_sort(image->needed[i], slot, initList, sortFlag); 159 160 initList[slot] = image; 161 return slot + 1; 162 } 163 164 165 /*! Finds the load address and address specifier of the given image region. 166 */ 167 static void 168 get_image_region_load_address(image_t* image, uint32 index, int32 lastDelta, 169 bool fixed, addr_t& loadAddress, uint32& addressSpecifier) 170 { 171 if (image->dynamic_ptr != 0 && !fixed) { 172 // relocatable image... we can afford to place wherever 173 if (index == 0) { 174 // but only the first segment gets a free ride 175 loadAddress = RLD_PROGRAM_BASE; 176 addressSpecifier = B_BASE_ADDRESS; 177 } else { 178 loadAddress = image->regions[index].vmstart + lastDelta; 179 addressSpecifier = B_EXACT_ADDRESS; 180 } 181 } else { 182 // not relocatable, put it where it asks or die trying 183 loadAddress = image->regions[index].vmstart; 184 addressSpecifier = B_EXACT_ADDRESS; 185 } 186 } 187 188 189 // #pragma mark - 190 191 192 image_t* 193 create_image(const char* name, const char* path, int regionCount) 194 { 195 size_t allocSize = sizeof(image_t) 196 + (regionCount - 1) * sizeof(elf_region_t); 197 198 image_t* image = (image_t*)malloc(allocSize); 199 if (image == NULL) { 200 FATAL("no memory for image %s\n", path); 201 return NULL; 202 } 203 204 memset(image, 0, allocSize); 205 206 strlcpy(image->path, path, sizeof(image->path)); 207 208 // Make the last component of the supplied name the image name. 209 // If present, DT_SONAME will replace this name. 210 const char* lastSlash = strrchr(name, '/'); 211 if (lastSlash != NULL) 212 strlcpy(image->name, lastSlash + 1, sizeof(image->name)); 213 else 214 strlcpy(image->name, name, sizeof(image->name)); 215 216 image->ref_count = 1; 217 image->num_regions = regionCount; 218 219 return image; 220 } 221 222 223 void 224 delete_image_struct(image_t* image) 225 { 226 #ifdef DEBUG 227 size_t size = sizeof(image_t) 228 + (image->num_regions - 1) * sizeof(elf_region_t); 229 memset(image->needed, 0xa5, sizeof(image->needed[0]) * image->num_needed); 230 #endif 231 free(image->needed); 232 free(image->versions); 233 234 while (RuntimeLoaderSymbolPatcher* patcher 235 = image->defined_symbol_patchers) { 236 image->defined_symbol_patchers = patcher->next; 237 delete patcher; 238 } 239 while (RuntimeLoaderSymbolPatcher* patcher 240 = image->undefined_symbol_patchers) { 241 image->undefined_symbol_patchers = patcher->next; 242 delete patcher; 243 } 244 245 #ifdef DEBUG 246 // overwrite images to make sure they aren't accidently reused anywhere 247 memset(image, 0xa5, size); 248 #endif 249 free(image); 250 } 251 252 253 void 254 delete_image(image_t* image) 255 { 256 if (image == NULL) 257 return; 258 259 _kern_unregister_image(image->id); 260 // registered in load_container() 261 262 delete_image_struct(image); 263 } 264 265 266 void 267 put_image(image_t* image) 268 { 269 // If all references to the image are gone, add it to the disposable list 270 // and remove all dependencies 271 272 if (atomic_add(&image->ref_count, -1) == 1) { 273 size_t i; 274 275 dequeue_image(&sLoadedImages, image); 276 enqueue_image(&sDisposableImages, image); 277 sLoadedImageCount--; 278 279 for (i = 0; i < image->num_needed; i++) 280 put_image(image->needed[i]); 281 } 282 } 283 284 285 status_t 286 map_image(int fd, char const* path, image_t* image, bool fixed) 287 { 288 // cut the file name from the path as base name for the created areas 289 const char* baseName = strrchr(path, '/'); 290 if (baseName != NULL) 291 baseName++; 292 else 293 baseName = path; 294 295 // determine how much space we need for all loaded segments 296 297 addr_t reservedAddress = 0; 298 addr_t loadAddress; 299 size_t reservedSize = 0; 300 size_t length = 0; 301 uint32 addressSpecifier = B_ANY_ADDRESS; 302 303 for (uint32 i = 0; i < image->num_regions; i++) { 304 // for BeOS compatibility: if we load an old BeOS executable, we 305 // have to relocate it, if possible - we recognize it because the 306 // vmstart is set to 0 (hopefully always) 307 if (fixed && image->regions[i].vmstart == 0) 308 fixed = false; 309 310 uint32 regionAddressSpecifier; 311 get_image_region_load_address(image, i, 312 i > 0 ? loadAddress - image->regions[i - 1].vmstart : 0, 313 fixed, loadAddress, regionAddressSpecifier); 314 if (i == 0) { 315 reservedAddress = loadAddress; 316 addressSpecifier = regionAddressSpecifier; 317 } 318 319 length += TO_PAGE_SIZE(image->regions[i].vmsize 320 + (loadAddress % B_PAGE_SIZE)); 321 322 size_t size = TO_PAGE_SIZE(loadAddress + image->regions[i].vmsize) 323 - reservedAddress; 324 if (size > reservedSize) 325 reservedSize = size; 326 } 327 328 // Check whether the segments have an unreasonable amount of unused space 329 // inbetween. 330 if (reservedSize > length + MAX_PAGE_SIZE * 2) 331 return B_BAD_DATA; 332 333 // reserve that space and allocate the areas from that one 334 if (_kern_reserve_address_range(&reservedAddress, addressSpecifier, 335 reservedSize) != B_OK) 336 return B_NO_MEMORY; 337 338 for (uint32 i = 0; i < image->num_regions; i++) { 339 char regionName[B_OS_NAME_LENGTH]; 340 341 snprintf(regionName, sizeof(regionName), "%s_seg%" B_PRIu32 "%s", 342 baseName, i, (image->regions[i].flags & RFLAG_RW) ? "rw" : "ro"); 343 344 get_image_region_load_address(image, i, 345 i > 0 ? image->regions[i - 1].delta : 0, fixed, loadAddress, 346 addressSpecifier); 347 348 // If the image position is arbitrary, we must let it point to the start 349 // of the reserved address range. 350 if (addressSpecifier != B_EXACT_ADDRESS) 351 loadAddress = reservedAddress; 352 353 if ((image->regions[i].flags & RFLAG_ANON) != 0) { 354 image->regions[i].id = _kern_create_area(regionName, 355 (void**)&loadAddress, B_EXACT_ADDRESS, 356 image->regions[i].vmsize, B_NO_LOCK, 357 B_READ_AREA | B_WRITE_AREA); 358 359 if (image->regions[i].id < 0) { 360 _kern_unreserve_address_range(reservedAddress, reservedSize); 361 return image->regions[i].id; 362 } 363 } else { 364 // Map all segments r/w first -- write access might be needed for 365 // relocations. When we've done with those we change the protection 366 // of read-only segments back to read-only. We map those segments 367 // over-committing, since quite likely only a relatively small 368 // number of pages needs to be touched and we want to avoid a lot 369 // of memory to be committed for them temporarily, just because we 370 // have to write map them. 371 uint32 protection = B_READ_AREA | B_WRITE_AREA 372 | ((image->regions[i].flags & RFLAG_RW) != 0 373 ? 0 : B_OVERCOMMITTING_AREA); 374 image->regions[i].id = _kern_map_file(regionName, 375 (void**)&loadAddress, B_EXACT_ADDRESS, 376 image->regions[i].vmsize, protection, REGION_PRIVATE_MAP, false, 377 fd, PAGE_BASE(image->regions[i].fdstart)); 378 379 if (image->regions[i].id < 0) { 380 _kern_unreserve_address_range(reservedAddress, reservedSize); 381 return image->regions[i].id; 382 } 383 384 TRACE(("\"%s\" at %p, 0x%lx bytes (%s)\n", path, 385 (void *)loadAddress, image->regions[i].vmsize, 386 image->regions[i].flags & RFLAG_RW ? "rw" : "read-only")); 387 388 // handle trailer bits in data segment 389 if (image->regions[i].flags & RFLAG_RW) { 390 addr_t startClearing = loadAddress 391 + PAGE_OFFSET(image->regions[i].start) 392 + image->regions[i].size; 393 addr_t toClear = image->regions[i].vmsize 394 - PAGE_OFFSET(image->regions[i].start) 395 - image->regions[i].size; 396 397 TRACE(("cleared 0x%lx and the following 0x%lx bytes\n", 398 startClearing, toClear)); 399 memset((void *)startClearing, 0, toClear); 400 } 401 } 402 403 image->regions[i].delta = loadAddress - image->regions[i].vmstart; 404 image->regions[i].vmstart = loadAddress; 405 } 406 407 if (image->dynamic_ptr != 0) 408 image->dynamic_ptr += image->regions[0].delta; 409 410 return B_OK; 411 } 412 413 414 void 415 unmap_image(image_t* image) 416 { 417 for (uint32 i = 0; i < image->num_regions; i++) { 418 _kern_delete_area(image->regions[i].id); 419 420 image->regions[i].id = -1; 421 } 422 } 423 424 425 /*! This function will change the protection of all read-only segments to really 426 be read-only. 427 The areas have to be read/write first, so that they can be relocated. 428 */ 429 void 430 remap_images() 431 { 432 for (image_t* image = sLoadedImages.head; image != NULL; 433 image = image->next) { 434 for (uint32 i = 0; i < image->num_regions; i++) { 435 if ((image->regions[i].flags & RFLAG_RW) == 0 436 && (image->regions[i].flags & RFLAG_REMAPPED) == 0) { 437 // we only need to do this once, so we remember those we've already mapped 438 if (_kern_set_area_protection(image->regions[i].id, 439 B_READ_AREA | B_EXECUTE_AREA) == B_OK) { 440 image->regions[i].flags |= RFLAG_REMAPPED; 441 } 442 } 443 } 444 } 445 } 446 447 448 void 449 register_image(image_t* image, int fd, const char* path) 450 { 451 struct stat stat; 452 image_info info; 453 454 // TODO: set these correctly 455 info.id = 0; 456 info.type = image->type; 457 info.sequence = 0; 458 info.init_order = 0; 459 info.init_routine = (void (*)())image->init_routine; 460 info.term_routine = (void (*)())image->term_routine; 461 462 if (_kern_read_stat(fd, NULL, false, &stat, sizeof(struct stat)) == B_OK) { 463 info.device = stat.st_dev; 464 info.node = stat.st_ino; 465 } else { 466 info.device = -1; 467 info.node = -1; 468 } 469 470 // We may have split segments into separate regions. Compute the correct 471 // segments for the image info. 472 addr_t textBase = 0; 473 addr_t textEnd = 0; 474 addr_t dataBase = 0; 475 addr_t dataEnd = 0; 476 for (uint32 i= 0; i < image->num_regions; i++) { 477 addr_t base = image->regions[i].vmstart; 478 addr_t end = base + image->regions[i].vmsize; 479 if (image->regions[i].flags & RFLAG_RW) { 480 // data 481 if (dataBase == 0) { 482 dataBase = base; 483 dataEnd = end; 484 } else { 485 dataBase = std::min(dataBase, base); 486 dataEnd = std::max(dataEnd, end); 487 } 488 } else { 489 // text 490 if (textBase == 0) { 491 textBase = base; 492 textEnd = end; 493 } else { 494 textBase = std::min(textBase, base); 495 textEnd = std::max(textEnd, end); 496 } 497 } 498 } 499 500 strlcpy(info.name, path, sizeof(info.name)); 501 info.text = (void*)textBase; 502 info.text_size = textEnd - textBase; 503 info.data = (void*)dataBase; 504 info.data_size = dataEnd - dataBase; 505 info.api_version = image->api_version; 506 info.abi = image->abi; 507 image->id = _kern_register_image(&info, sizeof(image_info)); 508 } 509 510 511 //! After fork, we lazily rebuild the image IDs of all loaded images. 512 status_t 513 update_image_ids() 514 { 515 for (image_t* image = sLoadedImages.head; image; image = image->next) { 516 status_t status = update_image_id(image); 517 if (status != B_OK) 518 return status; 519 } 520 for (image_t* image = sDisposableImages.head; image; image = image->next) { 521 status_t status = update_image_id(image); 522 if (status != B_OK) 523 return status; 524 } 525 526 gInvalidImageIDs = false; 527 return B_OK; 528 } 529 530 531 image_queue_t& 532 get_loaded_images() 533 { 534 return sLoadedImages; 535 } 536 537 538 image_queue_t& 539 get_disposable_images() 540 { 541 return sDisposableImages; 542 } 543 544 545 uint32 546 count_loaded_images() 547 { 548 return sLoadedImageCount; 549 } 550 551 552 void 553 enqueue_loaded_image(image_t* image) 554 { 555 enqueue_image(&sLoadedImages, image); 556 sLoadedImageCount++; 557 } 558 559 560 void 561 dequeue_loaded_image(image_t* image) 562 { 563 dequeue_image(&sLoadedImages, image); 564 sLoadedImageCount--; 565 } 566 567 568 void 569 dequeue_disposable_image(image_t* image) 570 { 571 dequeue_image(&sDisposableImages, image); 572 } 573 574 575 image_t* 576 find_loaded_image_by_name(char const* name, uint32 typeMask) 577 { 578 bool isPath = strchr(name, '/') != NULL; 579 return find_image_in_queue(&sLoadedImages, name, isPath, typeMask); 580 } 581 582 583 image_t* 584 find_loaded_image_by_id(image_id id, bool ignoreDisposable) 585 { 586 if (gInvalidImageIDs) { 587 // After fork, we lazily rebuild the image IDs of all loaded images 588 update_image_ids(); 589 } 590 591 for (image_t* image = sLoadedImages.head; image; image = image->next) { 592 if (image->id == id) 593 return image; 594 } 595 596 if (ignoreDisposable) 597 return NULL; 598 599 for (image_t* image = sDisposableImages.head; image; image = image->next) { 600 if (image->id == id) 601 return image; 602 } 603 604 return NULL; 605 } 606 607 608 image_t* 609 find_loaded_image_by_address(addr_t address) 610 { 611 for (image_t* image = sLoadedImages.head; image; image = image->next) { 612 for (uint32 i = 0; i < image->num_regions; i++) { 613 elf_region_t& region = image->regions[i]; 614 if (region.vmstart <= address 615 && region.vmstart - 1 + region.vmsize >= address) 616 return image; 617 } 618 } 619 620 return NULL; 621 } 622 623 624 void 625 set_image_flags_recursively(image_t* image, uint32 flags) 626 { 627 update_image_flags_recursively(image, flags, 0); 628 } 629 630 631 void 632 clear_image_flags_recursively(image_t* image, uint32 flags) 633 { 634 update_image_flags_recursively(image, 0, flags); 635 } 636 637 638 /*! Returns a topologically sorted image list. 639 640 If \a image is non-NULL, an array containing the image and all its 641 transitive dependencies is returned. If \a image is NULL, all loaded images 642 are returned. In either case dependencies are listed before images 643 depending on them. 644 645 \param image The image specifying the tree of images that shall be sorted. 646 If NULL, all loaded images are sorted. 647 \param _list On success it will be set to an array of the sorted images. 648 The caller is responsible for free()ing it. 649 \param sortFlags The image flag that shall be used for sorting. Images that 650 already have this flag set are ignored (and their dependencies, unless 651 they are also reachable via another path). The flag will be set on all 652 returned images. 653 \return The number of images in the returned array or an error code on 654 failure. 655 */ 656 ssize_t 657 get_sorted_image_list(image_t* image, image_t*** _list, uint32 sortFlag) 658 { 659 image_t** list; 660 661 list = (image_t**)malloc(sLoadedImageCount * sizeof(image_t*)); 662 if (list == NULL) { 663 FATAL("memory shortage in get_sorted_image_list()"); 664 *_list = NULL; 665 return B_NO_MEMORY; 666 } 667 668 memset(list, 0, sLoadedImageCount * sizeof(image_t*)); 669 670 *_list = list; 671 672 if (image != NULL) 673 return topological_sort(image, 0, list, sortFlag); 674 675 // no image given -- sort all loaded images 676 uint32 count = 0; 677 image = sLoadedImages.head; 678 while (image != NULL) { 679 count = topological_sort(image, count, list, sortFlag); 680 image = image->next; 681 } 682 683 return count; 684 } 685