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