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