1 /* 2 * Copyright 2005-2009, 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 * Distributed under the terms of the NewOS License. 7 */ 8 9 10 #include "runtime_loader_private.h" 11 12 #include <string.h> 13 #include <stdlib.h> 14 #include <sys/stat.h> 15 16 #include <algorithm> 17 18 #include <ByteOrder.h> 19 20 #include <directories.h> 21 #include <find_directory_private.h> 22 #include <image_defs.h> 23 #include <syscalls.h> 24 #include <user_runtime.h> 25 #include <vm_defs.h> 26 27 #include "elf_symbol_lookup.h" 28 #include "pe.h" 29 30 31 struct user_space_program_args *gProgramArgs; 32 void *__gCommPageAddress; 33 void *__dso_handle; 34 35 int32 __gCPUCount = 1; 36 37 const directory_which kLibraryDirectories[] = { 38 B_SYSTEM_LIB_DIRECTORY, 39 B_SYSTEM_NONPACKAGED_LIB_DIRECTORY, 40 B_USER_LIB_DIRECTORY, 41 B_USER_NONPACKAGED_LIB_DIRECTORY 42 }; 43 44 45 static const char * 46 search_path_for_type(image_type type) 47 { 48 const char *path = NULL; 49 50 // If "user add-ons" are disabled via safemode settings, we bypass the 51 // environment and defaults and return a different set of paths without 52 // the user or non-packaged ones. 53 if (gProgramArgs->disable_user_addons) { 54 switch (type) { 55 case B_APP_IMAGE: 56 return kGlobalBinDirectory 57 ":" kSystemAppsDirectory 58 ":" kSystemPreferencesDirectory; 59 60 case B_LIBRARY_IMAGE: 61 return kAppLocalLibDirectory 62 ":" kSystemLibDirectory; 63 64 case B_ADD_ON_IMAGE: 65 return kAppLocalAddonsDirectory 66 ":" kSystemAddonsDirectory; 67 68 default: 69 return NULL; 70 } 71 } 72 73 // TODO: The *PATH variables should not include the standard system paths. 74 // Instead those paths should always be used after the directories specified 75 // via the variables. 76 switch (type) { 77 case B_APP_IMAGE: 78 path = getenv("PATH"); 79 break; 80 case B_LIBRARY_IMAGE: 81 path = getenv("LIBRARY_PATH"); 82 break; 83 case B_ADD_ON_IMAGE: 84 path = getenv("ADDON_PATH"); 85 break; 86 87 default: 88 return NULL; 89 } 90 91 if (path != NULL) 92 return path; 93 94 // The environment variables may not have been set yet - in that case, 95 // we're returning some useful defaults. 96 // Since the kernel does not set any variables, this is also needed 97 // to start the root shell. 98 99 switch (type) { 100 case B_APP_IMAGE: 101 return kSystemNonpackagedBinDirectory 102 ":" kGlobalBinDirectory 103 ":" kSystemAppsDirectory 104 ":" kSystemPreferencesDirectory; 105 106 case B_LIBRARY_IMAGE: 107 return kAppLocalLibDirectory 108 ":" kSystemNonpackagedLibDirectory 109 ":" kSystemLibDirectory; 110 111 case B_ADD_ON_IMAGE: 112 return kAppLocalAddonsDirectory 113 ":" kSystemNonpackagedAddonsDirectory 114 ":" kSystemAddonsDirectory; 115 116 default: 117 return NULL; 118 } 119 } 120 121 122 static bool 123 replace_executable_path_placeholder(const char*& dir, int& dirLength, 124 const char* placeholder, size_t placeholderLength, 125 const char* replacementSubPath, char*& buffer, size_t& bufferSize, 126 status_t& _error) 127 { 128 if (dirLength < (int)placeholderLength 129 || strncmp(dir, placeholder, placeholderLength) != 0) { 130 return false; 131 } 132 133 if (replacementSubPath == NULL) { 134 _error = B_ENTRY_NOT_FOUND; 135 return true; 136 } 137 138 char* lastSlash = strrchr(replacementSubPath, '/'); 139 140 // Copy replacementSubPath without the last component (the application file 141 // name, respectively the requesting executable file name). 142 size_t toCopy; 143 if (lastSlash != NULL) { 144 toCopy = lastSlash - replacementSubPath; 145 strlcpy(buffer, replacementSubPath, 146 std::min((ssize_t)bufferSize, lastSlash + 1 - replacementSubPath)); 147 } else { 148 replacementSubPath = "."; 149 toCopy = 1; 150 strlcpy(buffer, ".", bufferSize); 151 } 152 153 if (toCopy >= bufferSize) { 154 _error = B_NAME_TOO_LONG; 155 return true; 156 } 157 158 memcpy(buffer, replacementSubPath, toCopy); 159 buffer[toCopy] = '\0'; 160 161 buffer += toCopy; 162 bufferSize -= toCopy; 163 dir += placeholderLength; 164 dirLength -= placeholderLength; 165 166 _error = B_OK; 167 return true; 168 } 169 170 171 static int 172 try_open_executable(const char *dir, int dirLength, const char *name, 173 const char *programPath, const char *requestingObjectPath, 174 const char *abiSpecificSubDir, char *path, size_t pathLength) 175 { 176 size_t nameLength = strlen(name); 177 struct stat stat; 178 status_t status; 179 180 // construct the path 181 if (dirLength > 0) { 182 char *buffer = path; 183 size_t subDirLen = 0; 184 185 if (programPath == NULL) 186 programPath = gProgramArgs->program_path; 187 188 if (replace_executable_path_placeholder(dir, dirLength, "%A", 2, 189 programPath, buffer, pathLength, status) 190 || replace_executable_path_placeholder(dir, dirLength, "$ORIGIN", 7, 191 requestingObjectPath, buffer, pathLength, status)) { 192 if (status != B_OK) 193 return status; 194 } else if (abiSpecificSubDir != NULL) { 195 // We're looking for a library or an add-on and the executable has 196 // not been compiled with a compiler using the same ABI as the one 197 // the OS has been built with. Thus we only look in subdirs 198 // specific to that ABI. 199 // However, only if it's a known library location 200 for (int i = 0; i < 4; ++i) { 201 char buffer[PATH_MAX]; 202 status_t result = __find_directory(kLibraryDirectories[i], -1, 203 false, buffer, PATH_MAX); 204 if (result == B_OK && strncmp(dir, buffer, dirLength) == 0) { 205 subDirLen = strlen(abiSpecificSubDir) + 1; 206 break; 207 } 208 } 209 } 210 211 if (dirLength + 1 + subDirLen + nameLength >= pathLength) 212 return B_NAME_TOO_LONG; 213 214 memcpy(buffer, dir, dirLength); 215 buffer[dirLength] = '/'; 216 if (subDirLen > 0) { 217 memcpy(buffer + dirLength + 1, abiSpecificSubDir, subDirLen - 1); 218 buffer[dirLength + subDirLen] = '/'; 219 } 220 strcpy(buffer + dirLength + 1 + subDirLen, name); 221 } else { 222 if (nameLength >= pathLength) 223 return B_NAME_TOO_LONG; 224 225 strcpy(path + dirLength + 1, name); 226 } 227 228 TRACE(("runtime_loader: try_open_container(): %s\n", path)); 229 230 // Test if the target is a symbolic link, and correct the path in this case 231 232 status = _kern_read_stat(-1, path, false, &stat, sizeof(struct stat)); 233 if (status < B_OK) 234 return status; 235 236 if (S_ISLNK(stat.st_mode)) { 237 char buffer[PATH_MAX]; 238 size_t length = PATH_MAX - 1; 239 char *lastSlash; 240 241 // it's a link, indeed 242 status = _kern_read_link(-1, path, buffer, &length); 243 if (status < B_OK) 244 return status; 245 buffer[length] = '\0'; 246 247 lastSlash = strrchr(path, '/'); 248 if (buffer[0] != '/' && lastSlash != NULL) { 249 // relative path 250 strlcpy(lastSlash + 1, buffer, lastSlash + 1 - path + pathLength); 251 } else 252 strlcpy(path, buffer, pathLength); 253 } 254 255 return _kern_open(-1, path, O_RDONLY, 0); 256 } 257 258 259 static int 260 search_executable_in_path_list(const char *name, const char *pathList, 261 int pathListLen, const char *programPath, const char *requestingObjectPath, 262 const char *abiSpecificSubDir, char *pathBuffer, size_t pathBufferLength) 263 { 264 const char *pathListEnd = pathList + pathListLen; 265 status_t status = B_ENTRY_NOT_FOUND; 266 267 TRACE(("runtime_loader: search_container_in_path_list() %s in %.*s\n", name, 268 pathListLen, pathList)); 269 270 while (pathListLen > 0) { 271 const char *pathEnd = pathList; 272 int fd; 273 274 // find the next ':' or run till the end of the string 275 while (pathEnd < pathListEnd && *pathEnd != ':') 276 pathEnd++; 277 278 fd = try_open_executable(pathList, pathEnd - pathList, name, 279 programPath, requestingObjectPath, abiSpecificSubDir, pathBuffer, 280 pathBufferLength); 281 if (fd >= 0) { 282 // see if it's a dir 283 struct stat stat; 284 status = _kern_read_stat(fd, NULL, true, &stat, sizeof(struct stat)); 285 if (status == B_OK) { 286 if (!S_ISDIR(stat.st_mode)) 287 return fd; 288 status = B_IS_A_DIRECTORY; 289 } 290 _kern_close(fd); 291 } 292 293 pathListLen = pathListEnd - pathEnd - 1; 294 pathList = pathEnd + 1; 295 } 296 297 return status; 298 } 299 300 301 int 302 open_executable(char *name, image_type type, const char *rpath, 303 const char *programPath, const char *requestingObjectPath, 304 const char *abiSpecificSubDir) 305 { 306 char buffer[PATH_MAX]; 307 int fd = B_ENTRY_NOT_FOUND; 308 309 if (strchr(name, '/')) { 310 // the name already contains a path, we don't have to search for it 311 fd = _kern_open(-1, name, O_RDONLY, 0); 312 if (fd >= 0 || type == B_APP_IMAGE) 313 return fd; 314 315 // can't search harder an absolute path add-on name! 316 if (type == B_ADD_ON_IMAGE && name[0] == '/') 317 return fd; 318 319 // Even though ELF specs don't say this, we give shared libraries 320 // and relative path based add-ons another chance and look 321 // them up in the usual search paths - at 322 // least that seems to be what BeOS does, and since it doesn't hurt... 323 if (type == B_LIBRARY_IMAGE) { 324 // For library (but not add-on), strip any path from name. 325 // Relative path of add-on is kept. 326 const char* paths = strrchr(name, '/') + 1; 327 memmove(name, paths, strlen(paths) + 1); 328 } 329 } 330 331 // try rpath (DT_RPATH) 332 if (rpath != NULL) { 333 // It consists of a colon-separated search path list. Optionally a 334 // second search path list follows, separated from the first by a 335 // semicolon. 336 const char *semicolon = strchr(rpath, ';'); 337 const char *firstList = (semicolon ? rpath : NULL); 338 const char *secondList = (semicolon ? semicolon + 1 : rpath); 339 // If there is no ';', we set only secondList to simplify things. 340 if (firstList) { 341 fd = search_executable_in_path_list(name, firstList, 342 semicolon - firstList, programPath, requestingObjectPath, NULL, 343 buffer, sizeof(buffer)); 344 } 345 if (fd < 0) { 346 fd = search_executable_in_path_list(name, secondList, 347 strlen(secondList), programPath, requestingObjectPath, NULL, 348 buffer, sizeof(buffer)); 349 } 350 } 351 352 // If not found yet, let's evaluate the system path variables to find the 353 // shared object. 354 if (fd < 0) { 355 if (const char *paths = search_path_for_type(type)) { 356 fd = search_executable_in_path_list(name, paths, strlen(paths), 357 programPath, NULL, abiSpecificSubDir, buffer, sizeof(buffer)); 358 } 359 } 360 361 if (fd >= 0) { 362 // we found it, copy path! 363 TRACE(("runtime_loader: open_executable(%s): found at %s\n", name, buffer)); 364 strlcpy(name, buffer, PATH_MAX); 365 } 366 367 return fd; 368 } 369 370 371 /*! 372 Applies haiku-specific fixes to a shebang line. 373 */ 374 static void 375 fixup_shebang(char *invoker) 376 { 377 char *current = invoker; 378 while (*current == ' ' || *current == '\t') { 379 ++current; 380 } 381 382 char *commandStart = current; 383 while (*current != ' ' && *current != '\t' && *current != '\0') { 384 ++current; 385 } 386 387 // replace /usr/bin/ with /bin/ 388 if (memcmp(commandStart, "/usr/bin/", strlen("/usr/bin/")) == 0) 389 memmove(commandStart, commandStart + 4, strlen(commandStart + 4) + 1); 390 } 391 392 393 /*! 394 Tests if there is an executable file at the provided path. It will 395 also test if the file has a valid ELF header or is a shell script. 396 Even if the runtime loader does not need to be able to deal with 397 both types, the caller will give scripts a proper treatment. 398 */ 399 status_t 400 test_executable(const char *name, char *invoker) 401 { 402 char path[B_PATH_NAME_LENGTH]; 403 char buffer[B_FILE_NAME_LENGTH]; 404 // must be large enough to hold the ELF header 405 status_t status; 406 ssize_t length; 407 int fd; 408 409 if (name == NULL) 410 return B_BAD_VALUE; 411 412 strlcpy(path, name, sizeof(path)); 413 414 fd = open_executable(path, B_APP_IMAGE, NULL, NULL, NULL, NULL); 415 if (fd < B_OK) 416 return fd; 417 418 // see if it's executable at all 419 status = _kern_access(-1, path, X_OK, false); 420 if (status != B_OK) 421 goto out; 422 423 // read and verify the ELF header 424 425 length = _kern_read(fd, 0, buffer, sizeof(buffer)); 426 if (length < 0) { 427 status = length; 428 goto out; 429 } 430 431 status = elf_verify_header(buffer, length); 432 #ifdef _COMPAT_MODE 433 #ifdef __x86_64__ 434 if (status == B_NOT_AN_EXECUTABLE) 435 status = elf32_verify_header(buffer, length); 436 #else 437 if (status == B_NOT_AN_EXECUTABLE) 438 status = elf64_verify_header(buffer, length); 439 #endif // __x86_64__ 440 #endif // _COMPAT_MODE 441 if (status == B_NOT_AN_EXECUTABLE) { 442 if (!strncmp(buffer, "#!", 2)) { 443 // test for shell scripts 444 char *end; 445 buffer[min_c((size_t)length, sizeof(buffer) - 1)] = '\0'; 446 447 end = strchr(buffer, '\n'); 448 if (end == NULL) { 449 status = E2BIG; 450 goto out; 451 } else 452 end[0] = '\0'; 453 454 if (invoker) { 455 strcpy(invoker, buffer + 2); 456 fixup_shebang(invoker); 457 } 458 459 status = B_OK; 460 } else { 461 // Something odd like a PE? 462 status = pe_verify_header(buffer, length); 463 464 // It is a PE, throw B_UNKNOWN_EXECUTABLE 465 // likely win32 at this point 466 if (status == B_OK) 467 status = B_UNKNOWN_EXECUTABLE; 468 } 469 } else if (status == B_OK) { 470 elf_ehdr *elfHeader = (elf_ehdr *)buffer; 471 if (elfHeader->e_entry == 0) { 472 // we don't like to open shared libraries 473 status = B_NOT_AN_EXECUTABLE; 474 } else if (invoker) 475 invoker[0] = '\0'; 476 } 477 478 out: 479 _kern_close(fd); 480 return status; 481 } 482 483 484 static bool 485 determine_x86_abi(int fd, const Elf32_Ehdr& elfHeader, bool& _isGcc2) 486 { 487 // Unless we're a little-endian CPU, don't bother. We're not x86, so it 488 // doesn't matter all that much whether we can determine the correct gcc 489 // ABI. This saves the code below from having to deal with endianess 490 // conversion. 491 #if B_HOST_IS_LENDIAN 492 493 // Since we don't want to load the complete image, we can't use the 494 // functions that normally determine the Haiku version and ABI. Instead 495 // we'll load the symbol and string tables and resolve the ABI symbol 496 // manually. 497 498 // map the file into memory 499 struct stat st; 500 if (_kern_read_stat(fd, NULL, true, &st, sizeof(st)) != B_OK) 501 return false; 502 503 void* fileBaseAddress; 504 area_id area = _kern_map_file("mapped file", &fileBaseAddress, 505 B_ANY_ADDRESS, st.st_size, B_READ_AREA, REGION_NO_PRIVATE_MAP, false, 506 fd, 0); 507 if (area < 0) 508 return false; 509 510 struct AreaDeleter { 511 AreaDeleter(area_id area) 512 : 513 fArea(area) 514 { 515 } 516 517 ~AreaDeleter() 518 { 519 _kern_delete_area(fArea); 520 } 521 522 private: 523 area_id fArea; 524 } areaDeleter(area); 525 526 // get the section headers 527 if (elfHeader.e_shoff == 0 || elfHeader.e_shentsize < sizeof(Elf32_Shdr)) 528 return false; 529 530 size_t sectionHeadersSize = elfHeader.e_shentsize * elfHeader.e_shnum; 531 if (elfHeader.e_shoff + (off_t)sectionHeadersSize > st.st_size) 532 return false; 533 534 void* sectionHeaders = (uint8*)fileBaseAddress + elfHeader.e_shoff; 535 536 // find the sections we need 537 uint32* symbolHash = NULL; 538 uint32 symbolHashSize = 0; 539 uint32 symbolHashChainSize = 0; 540 Elf32_Sym* symbolTable = NULL; 541 uint32 symbolTableSize = 0; 542 const char* stringTable = NULL; 543 off_t stringTableSize = 0; 544 545 for (int32 i = 0; i < elfHeader.e_shnum; i++) { 546 Elf32_Shdr* sectionHeader 547 = (Elf32_Shdr*)((uint8*)sectionHeaders + i * elfHeader.e_shentsize); 548 if ((off_t)sectionHeader->sh_offset + (off_t)sectionHeader->sh_size 549 > st.st_size) { 550 continue; 551 } 552 553 void* sectionAddress = (uint8*)fileBaseAddress 554 + sectionHeader->sh_offset; 555 556 switch (sectionHeader->sh_type) { 557 case SHT_HASH: 558 symbolHash = (uint32*)sectionAddress; 559 if (sectionHeader->sh_size < (off_t)sizeof(symbolHash[0])) 560 return false; 561 symbolHashSize = symbolHash[0]; 562 symbolHashChainSize 563 = sectionHeader->sh_size / sizeof(symbolHash[0]); 564 if (symbolHashChainSize < symbolHashSize + 2) 565 return false; 566 symbolHashChainSize -= symbolHashSize + 2; 567 break; 568 case SHT_DYNSYM: 569 symbolTable = (Elf32_Sym*)sectionAddress; 570 symbolTableSize = sectionHeader->sh_size; 571 break; 572 case SHT_STRTAB: 573 // .shstrtab has the same type as .dynstr, but it isn't loaded 574 // into memory. 575 if (sectionHeader->sh_addr == 0) 576 continue; 577 stringTable = (const char*)sectionAddress; 578 stringTableSize = (off_t)sectionHeader->sh_size; 579 break; 580 default: 581 continue; 582 } 583 } 584 585 if (symbolHash == NULL || symbolTable == NULL || stringTable == NULL) 586 return false; 587 uint32 symbolCount 588 = std::min(symbolTableSize / (uint32)sizeof(Elf32_Sym), 589 symbolHashChainSize); 590 if (symbolCount < symbolHashSize) 591 return false; 592 593 // look up the ABI symbol 594 const char* name = B_SHARED_OBJECT_HAIKU_ABI_VARIABLE_NAME; 595 size_t nameLength = strlen(name); 596 uint32 bucket = elf_hash(name) % symbolHashSize; 597 598 for (uint32 i = symbolHash[bucket + 2]; i < symbolCount && i != STN_UNDEF; 599 i = symbolHash[2 + symbolHashSize + i]) { 600 Elf32_Sym* symbol = symbolTable + i; 601 if (symbol->st_shndx != SHN_UNDEF 602 && ((symbol->Bind() == STB_GLOBAL) || (symbol->Bind() == STB_WEAK)) 603 && symbol->Type() == STT_OBJECT 604 && (off_t)symbol->st_name + (off_t)nameLength < stringTableSize 605 && strcmp(stringTable + symbol->st_name, name) == 0) { 606 if (symbol->st_value > 0 && symbol->st_size >= sizeof(uint32) 607 && symbol->st_shndx < elfHeader.e_shnum) { 608 Elf32_Shdr* sectionHeader = (Elf32_Shdr*)((uint8*)sectionHeaders 609 + symbol->st_shndx * elfHeader.e_shentsize); 610 if (symbol->st_value >= sectionHeader->sh_addr 611 && symbol->st_value 612 <= sectionHeader->sh_addr + sectionHeader->sh_size) { 613 off_t fileOffset = symbol->st_value - sectionHeader->sh_addr 614 + sectionHeader->sh_offset; 615 if (fileOffset + (off_t)sizeof(uint32) <= st.st_size) { 616 uint32 abi 617 = *(uint32*)((uint8*)fileBaseAddress + fileOffset); 618 _isGcc2 = (abi & B_HAIKU_ABI_MAJOR) 619 == B_HAIKU_ABI_GCC_2; 620 return true; 621 } 622 } 623 } 624 625 return false; 626 } 627 } 628 629 // ABI symbol not found. That means the object pre-dates its introduction 630 // in Haiku. So this is most likely gcc 2. We don't fall back to reading 631 // the comment sections to verify. 632 _isGcc2 = true; 633 return true; 634 #else // not little endian 635 return false; 636 #endif 637 } 638 639 640 static status_t 641 get_executable_architecture(int fd, const char** _architecture) 642 { 643 // Read the ELF header. We read the 32 bit header. Generally the e_machine 644 // field is the last one that interests us and the 64 bit header is still 645 // identical at that point. 646 Elf32_Ehdr elfHeader; 647 ssize_t bytesRead = _kern_read(fd, 0, &elfHeader, sizeof(elfHeader)); 648 if (bytesRead < 0) 649 return bytesRead; 650 if ((size_t)bytesRead != sizeof(elfHeader)) 651 return B_NOT_AN_EXECUTABLE; 652 653 // check whether this is indeed an ELF file 654 if (memcmp(elfHeader.e_ident, ELFMAG, 4) != 0) 655 return B_NOT_AN_EXECUTABLE; 656 657 // check the architecture 658 uint16 machine = elfHeader.e_machine; 659 if ((elfHeader.e_ident[EI_DATA] == ELFDATA2LSB) != (B_HOST_IS_LENDIAN != 0)) 660 machine = (machine >> 8) | (machine << 8); 661 662 const char* architecture = NULL; 663 switch (machine) { 664 case EM_386: 665 case EM_486: 666 { 667 bool isGcc2; 668 if (determine_x86_abi(fd, elfHeader, isGcc2) && isGcc2) 669 architecture = "x86_gcc2"; 670 else 671 architecture = "x86"; 672 break; 673 } 674 case EM_68K: 675 architecture = "m68k"; 676 break; 677 case EM_PPC: 678 architecture = "ppc"; 679 break; 680 case EM_ARM: 681 architecture = "arm"; 682 break; 683 case EM_ARM64: 684 architecture = "arm64"; 685 break; 686 case EM_X86_64: 687 architecture = "x86_64"; 688 break; 689 case EM_RISCV: 690 architecture = "riscv"; 691 break; 692 } 693 694 if (architecture == NULL) 695 return B_NOT_SUPPORTED; 696 697 *_architecture = architecture; 698 return B_OK; 699 } 700 701 702 status_t 703 get_executable_architecture(const char* path, const char** _architecture) 704 { 705 int fd = _kern_open(-1, path, O_RDONLY, 0); 706 if (fd < 0) 707 return fd; 708 709 status_t error = get_executable_architecture(fd, _architecture); 710 711 _kern_close(fd); 712 return error; 713 } 714 715 716 /*! 717 This is the main entry point of the runtime loader as 718 specified by its ld-script. 719 */ 720 int 721 runtime_loader(void* _args, void* commpage) 722 { 723 void *entry = NULL; 724 int returnCode; 725 726 gProgramArgs = (struct user_space_program_args *)_args; 727 __gCommPageAddress = commpage; 728 729 // Relocate the args and env arrays -- they are organized in a contiguous 730 // buffer which the kernel just copied into user space without adjusting the 731 // pointers. 732 { 733 int32 i; 734 addr_t relocationOffset = 0; 735 736 if (gProgramArgs->arg_count > 0) 737 relocationOffset = (addr_t)gProgramArgs->args[0]; 738 else if (gProgramArgs->env_count > 0) 739 relocationOffset = (addr_t)gProgramArgs->env[0]; 740 741 // That's basically: <new buffer address> - <old buffer address>. 742 // It looks a little complicated, since we don't have the latter one at 743 // hand and thus need to reconstruct it (<first string pointer> - 744 // <arguments + environment array sizes>). 745 relocationOffset = (addr_t)gProgramArgs->args - relocationOffset 746 + (gProgramArgs->arg_count + gProgramArgs->env_count + 2) 747 * sizeof(char*); 748 749 for (i = 0; i < gProgramArgs->arg_count; i++) 750 gProgramArgs->args[i] += relocationOffset; 751 752 for (i = 0; i < gProgramArgs->env_count; i++) 753 gProgramArgs->env[i] += relocationOffset; 754 } 755 756 #if DEBUG_RLD 757 close(0); open("/dev/console", 0); /* stdin */ 758 close(1); open("/dev/console", 0); /* stdout */ 759 close(2); open("/dev/console", 0); /* stderr */ 760 #endif 761 762 if (heap_init() < B_OK) 763 return 1; 764 765 rldexport_init(); 766 rldelf_init(); 767 768 load_program(gProgramArgs->program_path, &entry); 769 770 if (entry == NULL) 771 return -1; 772 773 // call the program entry point (usually _start()) 774 returnCode = ((int (*)(int, void *, void *))entry)(gProgramArgs->arg_count, 775 gProgramArgs->args, gProgramArgs->env); 776 777 terminate_program(); 778 779 return returnCode; 780 } 781