xref: /haiku/src/system/runtime_loader/elf.cpp (revision 7486b72dd1ef270f3f16dff4d19064c2d6efb51f)
10c0fea5dSIngo Weinhold /*
20c0fea5dSIngo Weinhold  * Copyright 2003-2007, Axel Dörfler, axeld@pinc-software.de.
30c0fea5dSIngo Weinhold  * Distributed under the terms of the MIT License.
40c0fea5dSIngo Weinhold  *
50c0fea5dSIngo Weinhold  * Copyright 2002, Manuel J. Petit. All rights reserved.
60c0fea5dSIngo Weinhold  * Copyright 2001, Travis Geiselbrecht. All rights reserved.
70c0fea5dSIngo Weinhold  * Distributed under the terms of the NewOS License.
80c0fea5dSIngo Weinhold  */
90c0fea5dSIngo Weinhold 
100c0fea5dSIngo Weinhold 
110c0fea5dSIngo Weinhold #include "runtime_loader_private.h"
125aa7b7b6SMarcus Overhagen #include "vm.h"
130c0fea5dSIngo Weinhold 
140c0fea5dSIngo Weinhold #include <OS.h>
150c0fea5dSIngo Weinhold 
160c0fea5dSIngo Weinhold #include <string.h>
170c0fea5dSIngo Weinhold #include <stdio.h>
180c0fea5dSIngo Weinhold #include <stdlib.h>
190c0fea5dSIngo Weinhold 
20*7486b72dSIngo Weinhold #include <arch/cpu.h>
21*7486b72dSIngo Weinhold #include <elf32.h>
22*7486b72dSIngo Weinhold #include <runtime_loader.h>
23*7486b72dSIngo Weinhold #include <sem.h>
24*7486b72dSIngo Weinhold #include <syscalls.h>
25*7486b72dSIngo Weinhold #include <tracing_config.h>
26*7486b72dSIngo Weinhold #include <user_runtime.h>
27*7486b72dSIngo Weinhold #include <vm_types.h>
28*7486b72dSIngo Weinhold 
290c0fea5dSIngo Weinhold 
300c0fea5dSIngo Weinhold //#define TRACE_RLD
310c0fea5dSIngo Weinhold #ifdef TRACE_RLD
320c0fea5dSIngo Weinhold #	define TRACE(x) dprintf x
330c0fea5dSIngo Weinhold #else
340c0fea5dSIngo Weinhold #	define TRACE(x) ;
350c0fea5dSIngo Weinhold #endif
360c0fea5dSIngo Weinhold 
370c0fea5dSIngo Weinhold 
380c0fea5dSIngo Weinhold // ToDo: implement better locking strategy
390c0fea5dSIngo Weinhold // ToDo: implement lazy binding
400c0fea5dSIngo Weinhold 
410c0fea5dSIngo Weinhold #define	PAGE_MASK (B_PAGE_SIZE - 1)
420c0fea5dSIngo Weinhold 
430c0fea5dSIngo Weinhold #define	PAGE_OFFSET(x) ((x) & (PAGE_MASK))
440c0fea5dSIngo Weinhold #define	PAGE_BASE(x) ((x) & ~(PAGE_MASK))
450c0fea5dSIngo Weinhold #define TO_PAGE_SIZE(x) ((x + (PAGE_MASK)) & ~(PAGE_MASK))
460c0fea5dSIngo Weinhold 
470c0fea5dSIngo Weinhold #define RLD_PROGRAM_BASE 0x00200000
480c0fea5dSIngo Weinhold 	/* keep in sync with app ldscript */
490c0fea5dSIngo Weinhold 
500c0fea5dSIngo Weinhold enum {
510c0fea5dSIngo Weinhold 	RFLAG_RW					= 0x0001,
520c0fea5dSIngo Weinhold 	RFLAG_ANON					= 0x0002,
530c0fea5dSIngo Weinhold 
540c0fea5dSIngo Weinhold 	RFLAG_TERMINATED			= 0x0200,
550c0fea5dSIngo Weinhold 	RFLAG_INITIALIZED			= 0x0400,
560c0fea5dSIngo Weinhold 	RFLAG_SYMBOLIC				= 0x0800,
570c0fea5dSIngo Weinhold 	RFLAG_RELOCATED				= 0x1000,
580c0fea5dSIngo Weinhold 	RFLAG_PROTECTED				= 0x2000,
590c0fea5dSIngo Weinhold 	RFLAG_DEPENDENCIES_LOADED	= 0x4000,
6046f4d849SIngo Weinhold 	RFLAG_REMAPPED				= 0x8000,
6146f4d849SIngo Weinhold 
6246f4d849SIngo Weinhold 	RFLAG_VISITED				= 0x10000
6346f4d849SIngo Weinhold 		// temporarily set in the symbol resolution code
640c0fea5dSIngo Weinhold };
650c0fea5dSIngo Weinhold 
660c0fea5dSIngo Weinhold 
670c0fea5dSIngo Weinhold #define IMAGE_TYPE_TO_MASK(type)	(1 << ((type) - 1))
680c0fea5dSIngo Weinhold #define ALL_IMAGE_TYPES				(IMAGE_TYPE_TO_MASK(B_APP_IMAGE) \
690c0fea5dSIngo Weinhold 									| IMAGE_TYPE_TO_MASK(B_LIBRARY_IMAGE) \
700c0fea5dSIngo Weinhold 									| IMAGE_TYPE_TO_MASK(B_ADD_ON_IMAGE) \
710c0fea5dSIngo Weinhold 									| IMAGE_TYPE_TO_MASK(B_SYSTEM_IMAGE))
720c0fea5dSIngo Weinhold #define APP_OR_LIBRARY_TYPE			(IMAGE_TYPE_TO_MASK(B_APP_IMAGE) \
730c0fea5dSIngo Weinhold 									| IMAGE_TYPE_TO_MASK(B_LIBRARY_IMAGE))
740c0fea5dSIngo Weinhold 
750c0fea5dSIngo Weinhold typedef void (*init_term_function)(image_id);
760c0fea5dSIngo Weinhold 
770c0fea5dSIngo Weinhold static image_queue_t sLoadedImages = {0, 0};
780c0fea5dSIngo Weinhold static image_queue_t sDisposableImages = {0, 0};
790c0fea5dSIngo Weinhold static uint32 sLoadedImageCount = 0;
800c0fea5dSIngo Weinhold static image_t *sProgramImage;
8174c0424aSAxel Dörfler static KMessage sErrorMessage;
820c0fea5dSIngo Weinhold 
8346f4d849SIngo Weinhold #ifdef BEOS_STYLE_SYMBOLS_RESOLUTION
8446f4d849SIngo Weinhold static bool sResolveSymbolsBeOSStyle = true;
8546f4d849SIngo Weinhold #else
8646f4d849SIngo Weinhold static bool sResolveSymbolsBeOSStyle = false;
8746f4d849SIngo Weinhold #endif
8846f4d849SIngo Weinhold 
890c0fea5dSIngo Weinhold // a recursive lock
900c0fea5dSIngo Weinhold static sem_id rld_sem;
910c0fea5dSIngo Weinhold static thread_id rld_sem_owner;
920c0fea5dSIngo Weinhold static int32 rld_sem_count;
930c0fea5dSIngo Weinhold 
940c0fea5dSIngo Weinhold 
950c0fea5dSIngo Weinhold #ifdef TRACE_RLD
960c0fea5dSIngo Weinhold #	define FATAL(x...) dprintf("runtime_loader: " x);
970c0fea5dSIngo Weinhold 
980c0fea5dSIngo Weinhold void
990c0fea5dSIngo Weinhold dprintf(const char *format, ...)
1000c0fea5dSIngo Weinhold {
1010c0fea5dSIngo Weinhold 	char buffer[1024];
1020c0fea5dSIngo Weinhold 
1030c0fea5dSIngo Weinhold 	va_list list;
1040c0fea5dSIngo Weinhold 	va_start(list, format);
1050c0fea5dSIngo Weinhold 
1060c0fea5dSIngo Weinhold 	vsnprintf(buffer, sizeof(buffer), format, list);
1070c0fea5dSIngo Weinhold 	_kern_debug_output(buffer);
1080c0fea5dSIngo Weinhold 
1090c0fea5dSIngo Weinhold 	va_end(list);
1100c0fea5dSIngo Weinhold }
1110c0fea5dSIngo Weinhold #else
1120c0fea5dSIngo Weinhold #	define FATAL(x...) printf("runtime_loader: " x);
1130c0fea5dSIngo Weinhold #endif
1140c0fea5dSIngo Weinhold 
1150c0fea5dSIngo Weinhold 
116*7486b72dSIngo Weinhold #ifdef RUNTIME_LOADER_TRACING
117*7486b72dSIngo Weinhold 
118*7486b72dSIngo Weinhold void
119*7486b72dSIngo Weinhold ktrace_printf(const char *format, ...)
120*7486b72dSIngo Weinhold {
121*7486b72dSIngo Weinhold 	va_list list;
122*7486b72dSIngo Weinhold 	va_start(list, format);
123*7486b72dSIngo Weinhold 
124*7486b72dSIngo Weinhold 	char buffer[1024];
125*7486b72dSIngo Weinhold 	vsnprintf(buffer, sizeof(buffer), format, list);
126*7486b72dSIngo Weinhold 	_kern_ktrace_output(buffer);
127*7486b72dSIngo Weinhold 
128*7486b72dSIngo Weinhold 	va_end(list);
129*7486b72dSIngo Weinhold }
130*7486b72dSIngo Weinhold 
131*7486b72dSIngo Weinhold #define KTRACE(x...)	ktrace_printf(x)
132*7486b72dSIngo Weinhold 
133*7486b72dSIngo Weinhold #else
134*7486b72dSIngo Weinhold #	define KTRACE(x...)
135*7486b72dSIngo Weinhold #endif	// RUNTIME_LOADER_TRACING
136*7486b72dSIngo Weinhold 
137*7486b72dSIngo Weinhold 
1380c0fea5dSIngo Weinhold static void
1390c0fea5dSIngo Weinhold rld_unlock()
1400c0fea5dSIngo Weinhold {
1410c0fea5dSIngo Weinhold 	if (rld_sem_count-- == 1) {
1420c0fea5dSIngo Weinhold 		rld_sem_owner = -1;
1430c0fea5dSIngo Weinhold 		release_sem(rld_sem);
1440c0fea5dSIngo Weinhold 	}
1450c0fea5dSIngo Weinhold }
1460c0fea5dSIngo Weinhold 
1470c0fea5dSIngo Weinhold 
1480c0fea5dSIngo Weinhold static void
1490c0fea5dSIngo Weinhold rld_lock()
1500c0fea5dSIngo Weinhold {
1510c0fea5dSIngo Weinhold 	thread_id self = find_thread(NULL);
1520c0fea5dSIngo Weinhold 	if (self != rld_sem_owner) {
1530c0fea5dSIngo Weinhold 		acquire_sem(rld_sem);
1540c0fea5dSIngo Weinhold 		rld_sem_owner = self;
1550c0fea5dSIngo Weinhold 	}
1560c0fea5dSIngo Weinhold 	rld_sem_count++;
1570c0fea5dSIngo Weinhold }
1580c0fea5dSIngo Weinhold 
1590c0fea5dSIngo Weinhold 
1600c0fea5dSIngo Weinhold static void
1610c0fea5dSIngo Weinhold enqueue_image(image_queue_t *queue, image_t *image)
1620c0fea5dSIngo Weinhold {
1630c0fea5dSIngo Weinhold 	image->next = 0;
1640c0fea5dSIngo Weinhold 
1650c0fea5dSIngo Weinhold 	image->prev = queue->tail;
1660c0fea5dSIngo Weinhold 	if (queue->tail)
1670c0fea5dSIngo Weinhold 		queue->tail->next = image;
1680c0fea5dSIngo Weinhold 
1690c0fea5dSIngo Weinhold 	queue->tail = image;
1700c0fea5dSIngo Weinhold 	if (!queue->head)
1710c0fea5dSIngo Weinhold 		queue->head = image;
1720c0fea5dSIngo Weinhold }
1730c0fea5dSIngo Weinhold 
1740c0fea5dSIngo Weinhold 
1750c0fea5dSIngo Weinhold static void
1760c0fea5dSIngo Weinhold dequeue_image(image_queue_t *queue, image_t *image)
1770c0fea5dSIngo Weinhold {
1780c0fea5dSIngo Weinhold 	if (image->next)
1790c0fea5dSIngo Weinhold 		image->next->prev = image->prev;
1800c0fea5dSIngo Weinhold 	else
1810c0fea5dSIngo Weinhold 		queue->tail = image->prev;
1820c0fea5dSIngo Weinhold 
1830c0fea5dSIngo Weinhold 	if (image->prev)
1840c0fea5dSIngo Weinhold 		image->prev->next = image->next;
1850c0fea5dSIngo Weinhold 	else
1860c0fea5dSIngo Weinhold 		queue->head = image->next;
1870c0fea5dSIngo Weinhold 
1880c0fea5dSIngo Weinhold 	image->prev = 0;
1890c0fea5dSIngo Weinhold 	image->next = 0;
1900c0fea5dSIngo Weinhold }
1910c0fea5dSIngo Weinhold 
1920c0fea5dSIngo Weinhold 
1930c0fea5dSIngo Weinhold static uint32
1940c0fea5dSIngo Weinhold elf_hash(const uint8 *name)
1950c0fea5dSIngo Weinhold {
1960c0fea5dSIngo Weinhold 	uint32 hash = 0;
1970c0fea5dSIngo Weinhold 	uint32 temp;
1980c0fea5dSIngo Weinhold 
1990c0fea5dSIngo Weinhold 	while (*name) {
2000c0fea5dSIngo Weinhold 		hash = (hash << 4) + *name++;
2010c0fea5dSIngo Weinhold 		if ((temp = hash & 0xf0000000)) {
2020c0fea5dSIngo Weinhold 			hash ^= temp >> 24;
2030c0fea5dSIngo Weinhold 		}
2040c0fea5dSIngo Weinhold 		hash &= ~temp;
2050c0fea5dSIngo Weinhold 	}
2060c0fea5dSIngo Weinhold 	return hash;
2070c0fea5dSIngo Weinhold }
2080c0fea5dSIngo Weinhold 
2090c0fea5dSIngo Weinhold 
2104bef3723SAxel Dörfler static inline bool
2114bef3723SAxel Dörfler report_errors()
2124bef3723SAxel Dörfler {
2134bef3723SAxel Dörfler 	return gProgramArgs->error_port >= 0;
2144bef3723SAxel Dörfler }
2154bef3723SAxel Dörfler 
2164bef3723SAxel Dörfler 
2170c0fea5dSIngo Weinhold static image_t *
2180c0fea5dSIngo Weinhold find_image_in_queue(image_queue_t *queue, const char *name, bool isPath,
2190c0fea5dSIngo Weinhold 	uint32 typeMask)
2200c0fea5dSIngo Weinhold {
2210c0fea5dSIngo Weinhold 	image_t *image;
2220c0fea5dSIngo Weinhold 
2230c0fea5dSIngo Weinhold 	for (image = queue->head; image; image = image->next) {
2240c0fea5dSIngo Weinhold 		const char *imageName = isPath ? image->path : image->name;
2250c0fea5dSIngo Weinhold 		int length = isPath ? sizeof(image->path) : sizeof(image->name);
2260c0fea5dSIngo Weinhold 
2270c0fea5dSIngo Weinhold 		if (!strncmp(imageName, name, length)
2280c0fea5dSIngo Weinhold 			&& (typeMask & IMAGE_TYPE_TO_MASK(image->type)) != 0) {
2290c0fea5dSIngo Weinhold 			return image;
2300c0fea5dSIngo Weinhold 		}
2310c0fea5dSIngo Weinhold 	}
2320c0fea5dSIngo Weinhold 
2330c0fea5dSIngo Weinhold 	return NULL;
2340c0fea5dSIngo Weinhold }
2350c0fea5dSIngo Weinhold 
2360c0fea5dSIngo Weinhold 
2370c0fea5dSIngo Weinhold static image_t *
2380c0fea5dSIngo Weinhold find_image(char const *name, uint32 typeMask)
2390c0fea5dSIngo Weinhold {
2400c0fea5dSIngo Weinhold 	bool isPath = (strchr(name, '/') != NULL);
24146f4d849SIngo Weinhold 	return find_image_in_queue(&sLoadedImages, name, isPath, typeMask);
2420c0fea5dSIngo Weinhold }
2430c0fea5dSIngo Weinhold 
2440c0fea5dSIngo Weinhold 
2450c0fea5dSIngo Weinhold static image_t *
2460c0fea5dSIngo Weinhold find_loaded_image_by_id(image_id id)
2470c0fea5dSIngo Weinhold {
2480c0fea5dSIngo Weinhold 	image_t *image;
2490c0fea5dSIngo Weinhold 
2500c0fea5dSIngo Weinhold 	for (image = sLoadedImages.head; image; image = image->next) {
2510c0fea5dSIngo Weinhold 		if (image->id == id)
2520c0fea5dSIngo Weinhold 			return image;
2530c0fea5dSIngo Weinhold 	}
2540c0fea5dSIngo Weinhold 
2550c0fea5dSIngo Weinhold 	// For the termination routine, we need to look into the list of
2560c0fea5dSIngo Weinhold 	// disposable images as well
2570c0fea5dSIngo Weinhold 	for (image = sDisposableImages.head; image; image = image->next) {
2580c0fea5dSIngo Weinhold 		if (image->id == id)
2590c0fea5dSIngo Weinhold 			return image;
2600c0fea5dSIngo Weinhold 	}
2610c0fea5dSIngo Weinhold 
2620c0fea5dSIngo Weinhold 	return NULL;
2630c0fea5dSIngo Weinhold }
2640c0fea5dSIngo Weinhold 
2650c0fea5dSIngo Weinhold 
2660c0fea5dSIngo Weinhold static status_t
2670c0fea5dSIngo Weinhold parse_elf_header(struct Elf32_Ehdr *eheader, int32 *_pheaderSize, int32 *_sheaderSize)
2680c0fea5dSIngo Weinhold {
2690c0fea5dSIngo Weinhold 	if (memcmp(eheader->e_ident, ELF_MAGIC, 4) != 0)
2700c0fea5dSIngo Weinhold 		return B_NOT_AN_EXECUTABLE;
2710c0fea5dSIngo Weinhold 
2720c0fea5dSIngo Weinhold 	if (eheader->e_ident[4] != ELFCLASS32)
2730c0fea5dSIngo Weinhold 		return B_NOT_AN_EXECUTABLE;
2740c0fea5dSIngo Weinhold 
2750c0fea5dSIngo Weinhold 	if (eheader->e_phoff == 0)
2760c0fea5dSIngo Weinhold 		return B_NOT_AN_EXECUTABLE;
2770c0fea5dSIngo Weinhold 
2780c0fea5dSIngo Weinhold 	if (eheader->e_phentsize < sizeof(struct Elf32_Phdr))
2790c0fea5dSIngo Weinhold 		return B_NOT_AN_EXECUTABLE;
2800c0fea5dSIngo Weinhold 
2810c0fea5dSIngo Weinhold 	*_pheaderSize = eheader->e_phentsize * eheader->e_phnum;
2820c0fea5dSIngo Weinhold 	*_sheaderSize = eheader->e_shentsize * eheader->e_shnum;
2830c0fea5dSIngo Weinhold 
2845aa7b7b6SMarcus Overhagen 	if (*_pheaderSize <= 0 || *_sheaderSize <= 0)
2855aa7b7b6SMarcus Overhagen 		return B_NOT_AN_EXECUTABLE;
2865aa7b7b6SMarcus Overhagen 
2875aa7b7b6SMarcus Overhagen 	return B_OK;
2880c0fea5dSIngo Weinhold }
2890c0fea5dSIngo Weinhold 
2900c0fea5dSIngo Weinhold 
2910c0fea5dSIngo Weinhold static int32
2920c0fea5dSIngo Weinhold count_regions(char const *buff, int phnum, int phentsize)
2930c0fea5dSIngo Weinhold {
2940c0fea5dSIngo Weinhold 	struct Elf32_Phdr *pheaders;
2950c0fea5dSIngo Weinhold 	int32 count = 0;
2960c0fea5dSIngo Weinhold 	int i;
2970c0fea5dSIngo Weinhold 
2980c0fea5dSIngo Weinhold 	for (i = 0; i < phnum; i++) {
2990c0fea5dSIngo Weinhold 		pheaders = (struct Elf32_Phdr *)(buff + i * phentsize);
3000c0fea5dSIngo Weinhold 
3010c0fea5dSIngo Weinhold 		switch (pheaders->p_type) {
3020c0fea5dSIngo Weinhold 			case PT_NULL:
3030c0fea5dSIngo Weinhold 				/* NOP header */
3040c0fea5dSIngo Weinhold 				break;
3050c0fea5dSIngo Weinhold 			case PT_LOAD:
3060c0fea5dSIngo Weinhold 				count += 1;
3070c0fea5dSIngo Weinhold 				if (pheaders->p_memsz != pheaders->p_filesz) {
3080c0fea5dSIngo Weinhold 					addr_t A = TO_PAGE_SIZE(pheaders->p_vaddr + pheaders->p_memsz);
3090c0fea5dSIngo Weinhold 					addr_t B = TO_PAGE_SIZE(pheaders->p_vaddr + pheaders->p_filesz);
3100c0fea5dSIngo Weinhold 
3110c0fea5dSIngo Weinhold 					if (A != B)
3120c0fea5dSIngo Weinhold 						count += 1;
3130c0fea5dSIngo Weinhold 				}
3140c0fea5dSIngo Weinhold 				break;
3150c0fea5dSIngo Weinhold 			case PT_DYNAMIC:
3160c0fea5dSIngo Weinhold 				/* will be handled at some other place */
3170c0fea5dSIngo Weinhold 				break;
3180c0fea5dSIngo Weinhold 			case PT_INTERP:
3190c0fea5dSIngo Weinhold 				/* should check here for appropiate interpreter */
3200c0fea5dSIngo Weinhold 				break;
3210c0fea5dSIngo Weinhold 			case PT_NOTE:
3220c0fea5dSIngo Weinhold 				/* unsupported */
3230c0fea5dSIngo Weinhold 				break;
3240c0fea5dSIngo Weinhold 			case PT_SHLIB:
3250c0fea5dSIngo Weinhold 				/* undefined semantics */
3260c0fea5dSIngo Weinhold 				break;
3270c0fea5dSIngo Weinhold 			case PT_PHDR:
3280c0fea5dSIngo Weinhold 				/* we don't use it */
3290c0fea5dSIngo Weinhold 				break;
3300c0fea5dSIngo Weinhold 			default:
3310c0fea5dSIngo Weinhold 				FATAL("unhandled pheader type 0x%lx\n", pheaders[i].p_type);
3320c0fea5dSIngo Weinhold 				return B_BAD_DATA;
3330c0fea5dSIngo Weinhold 		}
3340c0fea5dSIngo Weinhold 	}
3350c0fea5dSIngo Weinhold 
3360c0fea5dSIngo Weinhold 	return count;
3370c0fea5dSIngo Weinhold }
3380c0fea5dSIngo Weinhold 
3390c0fea5dSIngo Weinhold 
3400c0fea5dSIngo Weinhold /*
3410c0fea5dSIngo Weinhold  * create_image() & destroy_image()
3420c0fea5dSIngo Weinhold  *
3430c0fea5dSIngo Weinhold  * 	Create and destroy image_t structures. The destroyer makes sure that the
3440c0fea5dSIngo Weinhold  * 	memory buffers are full of garbage before freeing.
3450c0fea5dSIngo Weinhold  */
3460c0fea5dSIngo Weinhold 
3470c0fea5dSIngo Weinhold static image_t *
3480c0fea5dSIngo Weinhold create_image(const char *name, const char *path, int num_regions)
3490c0fea5dSIngo Weinhold {
3500c0fea5dSIngo Weinhold 	size_t allocSize = sizeof(image_t) + (num_regions - 1) * sizeof(elf_region_t);
3510c0fea5dSIngo Weinhold 	const char *lastSlash;
3520c0fea5dSIngo Weinhold 
3530c0fea5dSIngo Weinhold 	image_t *image = (image_t*)malloc(allocSize);
3540c0fea5dSIngo Weinhold 	if (image == NULL) {
3550c0fea5dSIngo Weinhold 		FATAL("no memory for image %s\n", path);
3560c0fea5dSIngo Weinhold 		return NULL;
3570c0fea5dSIngo Weinhold 	}
3580c0fea5dSIngo Weinhold 
3590c0fea5dSIngo Weinhold 	memset(image, 0, allocSize);
3600c0fea5dSIngo Weinhold 
3610c0fea5dSIngo Weinhold 	strlcpy(image->path, path, sizeof(image->path));
3620c0fea5dSIngo Weinhold 
3630c0fea5dSIngo Weinhold 	// Make the last component of the supplied name the image name.
3640c0fea5dSIngo Weinhold 	// If present, DT_SONAME will replace this name.
3650c0fea5dSIngo Weinhold 	if ((lastSlash = strrchr(name, '/')))
3660c0fea5dSIngo Weinhold 		strlcpy(image->name, lastSlash + 1, sizeof(image->name));
3670c0fea5dSIngo Weinhold 	else
3680c0fea5dSIngo Weinhold 		strlcpy(image->name, name, sizeof(image->name));
3690c0fea5dSIngo Weinhold 
3700c0fea5dSIngo Weinhold 	image->ref_count = 1;
3710c0fea5dSIngo Weinhold 	image->num_regions = num_regions;
3720c0fea5dSIngo Weinhold 
3730c0fea5dSIngo Weinhold 	return image;
3740c0fea5dSIngo Weinhold }
3750c0fea5dSIngo Weinhold 
3760c0fea5dSIngo Weinhold 
3770c0fea5dSIngo Weinhold static void
3780c0fea5dSIngo Weinhold delete_image_struct(image_t *image)
3790c0fea5dSIngo Weinhold {
3800c0fea5dSIngo Weinhold #ifdef DEBUG
3810c0fea5dSIngo Weinhold 	size_t size = sizeof(image_t) + (image->num_regions - 1) * sizeof(elf_region_t);
3820c0fea5dSIngo Weinhold 	memset(image->needed, 0xa5, sizeof(image->needed[0]) * image->num_needed);
3830c0fea5dSIngo Weinhold #endif
3840c0fea5dSIngo Weinhold 	free(image->needed);
3850c0fea5dSIngo Weinhold 
3860c0fea5dSIngo Weinhold #ifdef DEBUG
3870c0fea5dSIngo Weinhold 	memset(image, 0xa5, size);
3880c0fea5dSIngo Weinhold #endif
3890c0fea5dSIngo Weinhold 	free(image);
3900c0fea5dSIngo Weinhold }
3910c0fea5dSIngo Weinhold 
3920c0fea5dSIngo Weinhold 
3930c0fea5dSIngo Weinhold static void
3940c0fea5dSIngo Weinhold delete_image(image_t *image)
3950c0fea5dSIngo Weinhold {
3962760c4cdSAxel Dörfler 	if (image == NULL)
3972760c4cdSAxel Dörfler 		return;
3982760c4cdSAxel Dörfler 
3990c0fea5dSIngo Weinhold 	_kern_unregister_image(image->id);
4000c0fea5dSIngo Weinhold 		// registered in load_container()
4010c0fea5dSIngo Weinhold 
4020c0fea5dSIngo Weinhold 	delete_image_struct(image);
4030c0fea5dSIngo Weinhold }
4040c0fea5dSIngo Weinhold 
4050c0fea5dSIngo Weinhold 
4060c0fea5dSIngo Weinhold static status_t
4070c0fea5dSIngo Weinhold parse_program_headers(image_t *image, char *buff, int phnum, int phentsize)
4080c0fea5dSIngo Weinhold {
4090c0fea5dSIngo Weinhold 	struct Elf32_Phdr *pheader;
4100c0fea5dSIngo Weinhold 	int regcount;
4110c0fea5dSIngo Weinhold 	int i;
4120c0fea5dSIngo Weinhold 
4130c0fea5dSIngo Weinhold 	regcount = 0;
4140c0fea5dSIngo Weinhold 	for (i = 0; i < phnum; i++) {
4150c0fea5dSIngo Weinhold 		pheader = (struct Elf32_Phdr *)(buff + i * phentsize);
4160c0fea5dSIngo Weinhold 
4170c0fea5dSIngo Weinhold 		switch (pheader->p_type) {
4180c0fea5dSIngo Weinhold 			case PT_NULL:
4190c0fea5dSIngo Weinhold 				/* NOP header */
4200c0fea5dSIngo Weinhold 				break;
4210c0fea5dSIngo Weinhold 			case PT_LOAD:
4220c0fea5dSIngo Weinhold 				if (pheader->p_memsz == pheader->p_filesz) {
4230c0fea5dSIngo Weinhold 					/*
4240c0fea5dSIngo Weinhold 					 * everything in one area
4250c0fea5dSIngo Weinhold 					 */
4260c0fea5dSIngo Weinhold 					image->regions[regcount].start = pheader->p_vaddr;
4270c0fea5dSIngo Weinhold 					image->regions[regcount].size = pheader->p_memsz;
4280c0fea5dSIngo Weinhold 					image->regions[regcount].vmstart = PAGE_BASE(pheader->p_vaddr);
4290c0fea5dSIngo Weinhold 					image->regions[regcount].vmsize = TO_PAGE_SIZE(pheader->p_memsz
4300c0fea5dSIngo Weinhold 						+ PAGE_OFFSET(pheader->p_vaddr));
4310c0fea5dSIngo Weinhold 					image->regions[regcount].fdstart = pheader->p_offset;
4320c0fea5dSIngo Weinhold 					image->regions[regcount].fdsize = pheader->p_filesz;
4330c0fea5dSIngo Weinhold 					image->regions[regcount].delta = 0;
4340c0fea5dSIngo Weinhold 					image->regions[regcount].flags = 0;
4350c0fea5dSIngo Weinhold 					if (pheader->p_flags & PF_WRITE) {
4360c0fea5dSIngo Weinhold 						// this is a writable segment
4370c0fea5dSIngo Weinhold 						image->regions[regcount].flags |= RFLAG_RW;
4380c0fea5dSIngo Weinhold 					}
4390c0fea5dSIngo Weinhold 				} else {
4400c0fea5dSIngo Weinhold 					/*
4410c0fea5dSIngo Weinhold 					 * may require splitting
4420c0fea5dSIngo Weinhold 					 */
4430c0fea5dSIngo Weinhold 					addr_t A = TO_PAGE_SIZE(pheader->p_vaddr + pheader->p_memsz);
4440c0fea5dSIngo Weinhold 					addr_t B = TO_PAGE_SIZE(pheader->p_vaddr + pheader->p_filesz);
4450c0fea5dSIngo Weinhold 
4460c0fea5dSIngo Weinhold 					image->regions[regcount].start = pheader->p_vaddr;
4470c0fea5dSIngo Weinhold 					image->regions[regcount].size = pheader->p_filesz;
4480c0fea5dSIngo Weinhold 					image->regions[regcount].vmstart = PAGE_BASE(pheader->p_vaddr);
4490c0fea5dSIngo Weinhold 					image->regions[regcount].vmsize = TO_PAGE_SIZE(pheader->p_filesz
4500c0fea5dSIngo Weinhold 						+ PAGE_OFFSET(pheader->p_vaddr));
4510c0fea5dSIngo Weinhold 					image->regions[regcount].fdstart = pheader->p_offset;
4520c0fea5dSIngo Weinhold 					image->regions[regcount].fdsize = pheader->p_filesz;
4530c0fea5dSIngo Weinhold 					image->regions[regcount].delta = 0;
4540c0fea5dSIngo Weinhold 					image->regions[regcount].flags = 0;
4550c0fea5dSIngo Weinhold 					if (pheader->p_flags & PF_WRITE) {
4560c0fea5dSIngo Weinhold 						// this is a writable segment
4570c0fea5dSIngo Weinhold 						image->regions[regcount].flags |= RFLAG_RW;
4580c0fea5dSIngo Weinhold 					}
4590c0fea5dSIngo Weinhold 
4600c0fea5dSIngo Weinhold 					if (A != B) {
4610c0fea5dSIngo Weinhold 						/*
4620c0fea5dSIngo Weinhold 						 * yeah, it requires splitting
4630c0fea5dSIngo Weinhold 						 */
4640c0fea5dSIngo Weinhold 						regcount += 1;
4650c0fea5dSIngo Weinhold 						image->regions[regcount].start = pheader->p_vaddr;
4660c0fea5dSIngo Weinhold 						image->regions[regcount].size = pheader->p_memsz - pheader->p_filesz;
4670c0fea5dSIngo Weinhold 						image->regions[regcount].vmstart = image->regions[regcount-1].vmstart + image->regions[regcount-1].vmsize;
4680c0fea5dSIngo Weinhold 						image->regions[regcount].vmsize = TO_PAGE_SIZE(pheader->p_memsz + PAGE_OFFSET(pheader->p_vaddr))
4690c0fea5dSIngo Weinhold 							- image->regions[regcount-1].vmsize;
4700c0fea5dSIngo Weinhold 						image->regions[regcount].fdstart = 0;
4710c0fea5dSIngo Weinhold 						image->regions[regcount].fdsize = 0;
4720c0fea5dSIngo Weinhold 						image->regions[regcount].delta = 0;
4730c0fea5dSIngo Weinhold 						image->regions[regcount].flags = RFLAG_ANON;
4740c0fea5dSIngo Weinhold 						if (pheader->p_flags & PF_WRITE) {
4750c0fea5dSIngo Weinhold 							// this is a writable segment
4760c0fea5dSIngo Weinhold 							image->regions[regcount].flags |= RFLAG_RW;
4770c0fea5dSIngo Weinhold 						}
4780c0fea5dSIngo Weinhold 					}
4790c0fea5dSIngo Weinhold 				}
4800c0fea5dSIngo Weinhold 				regcount += 1;
4810c0fea5dSIngo Weinhold 				break;
4820c0fea5dSIngo Weinhold 			case PT_DYNAMIC:
4830c0fea5dSIngo Weinhold 				image->dynamic_ptr = pheader->p_vaddr;
4840c0fea5dSIngo Weinhold 				break;
4850c0fea5dSIngo Weinhold 			case PT_INTERP:
4860c0fea5dSIngo Weinhold 				/* should check here for appropiate interpreter */
4870c0fea5dSIngo Weinhold 				break;
4880c0fea5dSIngo Weinhold 			case PT_NOTE:
4890c0fea5dSIngo Weinhold 				/* unsupported */
4900c0fea5dSIngo Weinhold 				break;
4910c0fea5dSIngo Weinhold 			case PT_SHLIB:
4920c0fea5dSIngo Weinhold 				/* undefined semantics */
4930c0fea5dSIngo Weinhold 				break;
4940c0fea5dSIngo Weinhold 			case PT_PHDR:
4950c0fea5dSIngo Weinhold 				/* we don't use it */
4960c0fea5dSIngo Weinhold 				break;
4970c0fea5dSIngo Weinhold 			default:
4980c0fea5dSIngo Weinhold 				FATAL("unhandled pheader type 0x%lx\n", pheader[i].p_type);
4990c0fea5dSIngo Weinhold 				return B_BAD_DATA;
5000c0fea5dSIngo Weinhold 		}
5010c0fea5dSIngo Weinhold 	}
5020c0fea5dSIngo Weinhold 
5030c0fea5dSIngo Weinhold 	return B_OK;
5040c0fea5dSIngo Weinhold }
5050c0fea5dSIngo Weinhold 
5060c0fea5dSIngo Weinhold 
5070c0fea5dSIngo Weinhold static bool
5080c0fea5dSIngo Weinhold assert_dynamic_loadable(image_t *image)
5090c0fea5dSIngo Weinhold {
5100c0fea5dSIngo Weinhold 	uint32 i;
5110c0fea5dSIngo Weinhold 
5120c0fea5dSIngo Weinhold 	if (!image->dynamic_ptr)
5130c0fea5dSIngo Weinhold 		return true;
5140c0fea5dSIngo Weinhold 
5150c0fea5dSIngo Weinhold 	for (i = 0; i < image->num_regions; i++) {
5160c0fea5dSIngo Weinhold 		if (image->dynamic_ptr >= image->regions[i].start
5170c0fea5dSIngo Weinhold 			&& image->dynamic_ptr < image->regions[i].start + image->regions[i].size)
5180c0fea5dSIngo Weinhold 			return true;
5190c0fea5dSIngo Weinhold 	}
5200c0fea5dSIngo Weinhold 
5210c0fea5dSIngo Weinhold 	return false;
5220c0fea5dSIngo Weinhold }
5230c0fea5dSIngo Weinhold 
5240c0fea5dSIngo Weinhold 
5250c0fea5dSIngo Weinhold /**	This function will change the protection of all read-only segments
5260c0fea5dSIngo Weinhold  *	to really be read-only.
5270c0fea5dSIngo Weinhold  *	The areas have to be read/write first, so that they can be relocated.
5280c0fea5dSIngo Weinhold  */
5290c0fea5dSIngo Weinhold 
5300c0fea5dSIngo Weinhold static void
5310c0fea5dSIngo Weinhold remap_images(void)
5320c0fea5dSIngo Weinhold {
5330c0fea5dSIngo Weinhold 	image_t *image;
5340c0fea5dSIngo Weinhold 	uint32 i;
5350c0fea5dSIngo Weinhold 
5360c0fea5dSIngo Weinhold 	for (image = sLoadedImages.head; image != NULL; image = image->next) {
5370c0fea5dSIngo Weinhold 		for (i = 0; i < image->num_regions; i++) {
5380c0fea5dSIngo Weinhold 			if ((image->regions[i].flags & RFLAG_RW) == 0
5390c0fea5dSIngo Weinhold 				&& (image->regions[i].flags & RFLAG_REMAPPED) == 0) {
5400c0fea5dSIngo Weinhold 				// we only need to do this once, so we remember those we've already mapped
5410c0fea5dSIngo Weinhold 				if (_kern_set_area_protection(image->regions[i].id,
5420c0fea5dSIngo Weinhold 						B_READ_AREA | B_EXECUTE_AREA) == B_OK)
5430c0fea5dSIngo Weinhold 					image->regions[i].flags |= RFLAG_REMAPPED;
5440c0fea5dSIngo Weinhold 			}
5450c0fea5dSIngo Weinhold 		}
5460c0fea5dSIngo Weinhold 	}
5470c0fea5dSIngo Weinhold }
5480c0fea5dSIngo Weinhold 
5490c0fea5dSIngo Weinhold 
5500c0fea5dSIngo Weinhold static status_t
5510c0fea5dSIngo Weinhold map_image(int fd, char const *path, image_t *image, bool fixed)
5520c0fea5dSIngo Weinhold {
5530c0fea5dSIngo Weinhold 	status_t status = B_OK;
5540c0fea5dSIngo Weinhold 	const char *baseName;
5550c0fea5dSIngo Weinhold 	uint32 i;
5560c0fea5dSIngo Weinhold 
5570c0fea5dSIngo Weinhold 	(void)(fd);
5580c0fea5dSIngo Weinhold 
5590c0fea5dSIngo Weinhold 	// cut the file name from the path as base name for the created areas
5600c0fea5dSIngo Weinhold 	baseName = strrchr(path, '/');
5610c0fea5dSIngo Weinhold 	if (baseName != NULL)
5620c0fea5dSIngo Weinhold 		baseName++;
5630c0fea5dSIngo Weinhold 	else
5640c0fea5dSIngo Weinhold 		baseName = path;
5650c0fea5dSIngo Weinhold 
5660c0fea5dSIngo Weinhold 	for (i = 0; i < image->num_regions; i++) {
5670c0fea5dSIngo Weinhold 		char regionName[B_OS_NAME_LENGTH];
5680c0fea5dSIngo Weinhold 		addr_t loadAddress;
5690c0fea5dSIngo Weinhold 		uint32 addressSpecifier;
5700c0fea5dSIngo Weinhold 
5710c0fea5dSIngo Weinhold 		// for BeOS compatibility: if we load an old BeOS executable, we
5720c0fea5dSIngo Weinhold 		// have to relocate it, if possible - we recognize it because the
5730c0fea5dSIngo Weinhold 		// vmstart is set to 0 (hopefully always)
5740c0fea5dSIngo Weinhold 		if (fixed && image->regions[i].vmstart == 0)
5750c0fea5dSIngo Weinhold 			fixed = false;
5760c0fea5dSIngo Weinhold 
5770c0fea5dSIngo Weinhold 		snprintf(regionName, sizeof(regionName), "%s_seg%lu%s",
5780c0fea5dSIngo Weinhold 			baseName, i, (image->regions[i].flags & RFLAG_RW) ? "rw" : "ro");
5790c0fea5dSIngo Weinhold 
5800c0fea5dSIngo Weinhold 		if (image->dynamic_ptr && !fixed) {
5810c0fea5dSIngo Weinhold 			// relocatable image... we can afford to place wherever
5820c0fea5dSIngo Weinhold 			if (i == 0) {
5830c0fea5dSIngo Weinhold 				// but only the first segment gets a free ride
5840c0fea5dSIngo Weinhold 				loadAddress = RLD_PROGRAM_BASE;
5850c0fea5dSIngo Weinhold 				addressSpecifier = B_BASE_ADDRESS;
5860c0fea5dSIngo Weinhold 			} else {
5870c0fea5dSIngo Weinhold 				loadAddress = image->regions[i].vmstart + image->regions[i-1].delta;
5880c0fea5dSIngo Weinhold 				addressSpecifier = B_EXACT_ADDRESS;
5890c0fea5dSIngo Weinhold 			}
5900c0fea5dSIngo Weinhold 		} else {
5910c0fea5dSIngo Weinhold 			// not relocatable, put it where it asks or die trying
5920c0fea5dSIngo Weinhold 			loadAddress = image->regions[i].vmstart;
5930c0fea5dSIngo Weinhold 			addressSpecifier = B_EXACT_ADDRESS;
5940c0fea5dSIngo Weinhold 		}
5950c0fea5dSIngo Weinhold 
5960c0fea5dSIngo Weinhold 		if (image->regions[i].flags & RFLAG_ANON) {
5970c0fea5dSIngo Weinhold 			image->regions[i].id = _kern_create_area(regionName, (void **)&loadAddress,
5980c0fea5dSIngo Weinhold 				addressSpecifier, image->regions[i].vmsize, B_NO_LOCK,
5990c0fea5dSIngo Weinhold 				B_READ_AREA | B_WRITE_AREA);
6000c0fea5dSIngo Weinhold 
6010c0fea5dSIngo Weinhold 			if (image->regions[i].id < 0) {
6020c0fea5dSIngo Weinhold 				status = image->regions[i].id;
6030c0fea5dSIngo Weinhold 				goto error;
6040c0fea5dSIngo Weinhold 			}
6050c0fea5dSIngo Weinhold 
6060c0fea5dSIngo Weinhold 			image->regions[i].delta = loadAddress - image->regions[i].vmstart;
6070c0fea5dSIngo Weinhold 			image->regions[i].vmstart = loadAddress;
6080c0fea5dSIngo Weinhold 		} else {
6090c0fea5dSIngo Weinhold 			image->regions[i].id = sys_vm_map_file(regionName, (void **)&loadAddress,
6100c0fea5dSIngo Weinhold 				addressSpecifier, image->regions[i].vmsize, B_READ_AREA | B_WRITE_AREA,
6110c0fea5dSIngo Weinhold 				REGION_PRIVATE_MAP, path, PAGE_BASE(image->regions[i].fdstart));
6120c0fea5dSIngo Weinhold 
6130c0fea5dSIngo Weinhold 			if (image->regions[i].id < 0) {
6140c0fea5dSIngo Weinhold 				status = image->regions[i].id;
6150c0fea5dSIngo Weinhold 				goto error;
6160c0fea5dSIngo Weinhold 			}
6170c0fea5dSIngo Weinhold 
6180c0fea5dSIngo Weinhold 			TRACE(("\"%s\" at %p, 0x%lx bytes (%s)\n", path,
6190c0fea5dSIngo Weinhold 				(void *)loadAddress, image->regions[i].vmsize,
6200c0fea5dSIngo Weinhold 				image->regions[i].flags & RFLAG_RW ? "rw" : "read-only"));
6210c0fea5dSIngo Weinhold 
6220c0fea5dSIngo Weinhold 			image->regions[i].delta = loadAddress - image->regions[i].vmstart;
6230c0fea5dSIngo Weinhold 			image->regions[i].vmstart = loadAddress;
6240c0fea5dSIngo Weinhold 
6250c0fea5dSIngo Weinhold 			// handle trailer bits in data segment
6260c0fea5dSIngo Weinhold 			if (image->regions[i].flags & RFLAG_RW) {
6270c0fea5dSIngo Weinhold 				addr_t startClearing;
6280c0fea5dSIngo Weinhold 				addr_t toClear;
6290c0fea5dSIngo Weinhold 
6300c0fea5dSIngo Weinhold 				startClearing = image->regions[i].vmstart
6310c0fea5dSIngo Weinhold 					+ PAGE_OFFSET(image->regions[i].start)
6320c0fea5dSIngo Weinhold 					+ image->regions[i].size;
6330c0fea5dSIngo Weinhold 				toClear = image->regions[i].vmsize
6340c0fea5dSIngo Weinhold 					- PAGE_OFFSET(image->regions[i].start)
6350c0fea5dSIngo Weinhold 					- image->regions[i].size;
6360c0fea5dSIngo Weinhold 
6370c0fea5dSIngo Weinhold 				TRACE(("cleared 0x%lx and the following 0x%lx bytes\n", startClearing, toClear));
6380c0fea5dSIngo Weinhold 				memset((void *)startClearing, 0, toClear);
6390c0fea5dSIngo Weinhold 			}
6400c0fea5dSIngo Weinhold 		}
6410c0fea5dSIngo Weinhold 	}
6420c0fea5dSIngo Weinhold 
6430c0fea5dSIngo Weinhold 	if (image->dynamic_ptr)
6440c0fea5dSIngo Weinhold 		image->dynamic_ptr += image->regions[0].delta;
6450c0fea5dSIngo Weinhold 
6460c0fea5dSIngo Weinhold 	return B_OK;
6470c0fea5dSIngo Weinhold 
6480c0fea5dSIngo Weinhold error:
6490c0fea5dSIngo Weinhold 	return status;
6500c0fea5dSIngo Weinhold }
6510c0fea5dSIngo Weinhold 
6520c0fea5dSIngo Weinhold 
6530c0fea5dSIngo Weinhold static void
6540c0fea5dSIngo Weinhold unmap_image(image_t *image)
6550c0fea5dSIngo Weinhold {
6560c0fea5dSIngo Weinhold 	uint32 i;
6570c0fea5dSIngo Weinhold 
6580c0fea5dSIngo Weinhold 	for (i = 0; i < image->num_regions; i++) {
6590c0fea5dSIngo Weinhold 		_kern_delete_area(image->regions[i].id);
6600c0fea5dSIngo Weinhold 
6610c0fea5dSIngo Weinhold 		image->regions[i].id = -1;
6620c0fea5dSIngo Weinhold 	}
6630c0fea5dSIngo Weinhold }
6640c0fea5dSIngo Weinhold 
6650c0fea5dSIngo Weinhold 
6660c0fea5dSIngo Weinhold static bool
6670c0fea5dSIngo Weinhold parse_dynamic_segment(image_t *image)
6680c0fea5dSIngo Weinhold {
6690c0fea5dSIngo Weinhold 	struct Elf32_Dyn *d;
6700c0fea5dSIngo Weinhold 	int i;
6710c0fea5dSIngo Weinhold 	int sonameOffset = -1;
6720c0fea5dSIngo Weinhold 
6730c0fea5dSIngo Weinhold 	image->symhash = 0;
6740c0fea5dSIngo Weinhold 	image->syms = 0;
6750c0fea5dSIngo Weinhold 	image->strtab = 0;
6760c0fea5dSIngo Weinhold 
6770c0fea5dSIngo Weinhold 	d = (struct Elf32_Dyn *)image->dynamic_ptr;
6780c0fea5dSIngo Weinhold 	if (!d)
6790c0fea5dSIngo Weinhold 		return true;
6800c0fea5dSIngo Weinhold 
6810c0fea5dSIngo Weinhold 	for (i = 0; d[i].d_tag != DT_NULL; i++) {
6820c0fea5dSIngo Weinhold 		switch (d[i].d_tag) {
6830c0fea5dSIngo Weinhold 			case DT_NEEDED:
6840c0fea5dSIngo Weinhold 				image->num_needed += 1;
6850c0fea5dSIngo Weinhold 				break;
6860c0fea5dSIngo Weinhold 			case DT_HASH:
6870c0fea5dSIngo Weinhold 				image->symhash = (uint32 *)(d[i].d_un.d_ptr + image->regions[0].delta);
6880c0fea5dSIngo Weinhold 				break;
6890c0fea5dSIngo Weinhold 			case DT_STRTAB:
6900c0fea5dSIngo Weinhold 				image->strtab = (char *)(d[i].d_un.d_ptr + image->regions[0].delta);
6910c0fea5dSIngo Weinhold 				break;
6920c0fea5dSIngo Weinhold 			case DT_SYMTAB:
6930c0fea5dSIngo Weinhold 				image->syms = (struct Elf32_Sym *)(d[i].d_un.d_ptr + image->regions[0].delta);
6940c0fea5dSIngo Weinhold 				break;
6950c0fea5dSIngo Weinhold 			case DT_REL:
6960c0fea5dSIngo Weinhold 				image->rel = (struct Elf32_Rel *)(d[i].d_un.d_ptr + image->regions[0].delta);
6970c0fea5dSIngo Weinhold 				break;
6980c0fea5dSIngo Weinhold 			case DT_RELSZ:
6990c0fea5dSIngo Weinhold 				image->rel_len = d[i].d_un.d_val;
7000c0fea5dSIngo Weinhold 				break;
7010c0fea5dSIngo Weinhold 			case DT_RELA:
7020c0fea5dSIngo Weinhold 				image->rela = (struct Elf32_Rela *)(d[i].d_un.d_ptr + image->regions[0].delta);
7030c0fea5dSIngo Weinhold 				break;
7040c0fea5dSIngo Weinhold 			case DT_RELASZ:
7050c0fea5dSIngo Weinhold 				image->rela_len = d[i].d_un.d_val;
7060c0fea5dSIngo Weinhold 				break;
7070c0fea5dSIngo Weinhold 			// TK: procedure linkage table
7080c0fea5dSIngo Weinhold 			case DT_JMPREL:
7090c0fea5dSIngo Weinhold 				image->pltrel = (struct Elf32_Rel *)(d[i].d_un.d_ptr + image->regions[0].delta);
7100c0fea5dSIngo Weinhold 				break;
7110c0fea5dSIngo Weinhold 			case DT_PLTRELSZ:
7120c0fea5dSIngo Weinhold 				image->pltrel_len = d[i].d_un.d_val;
7130c0fea5dSIngo Weinhold 				break;
7140c0fea5dSIngo Weinhold 			case DT_INIT:
7150c0fea5dSIngo Weinhold 				image->init_routine = (d[i].d_un.d_ptr + image->regions[0].delta);
7160c0fea5dSIngo Weinhold 				break;
7170c0fea5dSIngo Weinhold 			case DT_FINI:
7180c0fea5dSIngo Weinhold 				image->term_routine = (d[i].d_un.d_ptr + image->regions[0].delta);
7190c0fea5dSIngo Weinhold 				break;
7200c0fea5dSIngo Weinhold 			case DT_SONAME:
7210c0fea5dSIngo Weinhold 				sonameOffset = d[i].d_un.d_val;
7220c0fea5dSIngo Weinhold 				break;
7230c0fea5dSIngo Weinhold 			default:
7240c0fea5dSIngo Weinhold 				continue;
7250c0fea5dSIngo Weinhold 		}
7260c0fea5dSIngo Weinhold 	}
7270c0fea5dSIngo Weinhold 
7280c0fea5dSIngo Weinhold 	// lets make sure we found all the required sections
7290c0fea5dSIngo Weinhold 	if (!image->symhash || !image->syms || !image->strtab)
7300c0fea5dSIngo Weinhold 		return false;
7310c0fea5dSIngo Weinhold 
7320c0fea5dSIngo Weinhold 	if (sonameOffset >= 0)
7330c0fea5dSIngo Weinhold 		strlcpy(image->name, STRING(image, sonameOffset), sizeof(image->name));
7340c0fea5dSIngo Weinhold 
7350c0fea5dSIngo Weinhold 	return true;
7360c0fea5dSIngo Weinhold }
7370c0fea5dSIngo Weinhold 
7380c0fea5dSIngo Weinhold 
7390c0fea5dSIngo Weinhold static struct Elf32_Sym *
7400c0fea5dSIngo Weinhold find_symbol(image_t *image, const char *name, int32 type)
7410c0fea5dSIngo Weinhold {
7420c0fea5dSIngo Weinhold 	uint32 hash, i;
7430c0fea5dSIngo Weinhold 
7440c0fea5dSIngo Weinhold 	// ToDo: "type" is currently ignored!
7450c0fea5dSIngo Weinhold 	(void)type;
7460c0fea5dSIngo Weinhold 
7470c0fea5dSIngo Weinhold 	if (image->dynamic_ptr == NULL)
7480c0fea5dSIngo Weinhold 		return NULL;
7490c0fea5dSIngo Weinhold 
7500c0fea5dSIngo Weinhold 	hash = elf_hash((uint8 *)name) % HASHTABSIZE(image);
7510c0fea5dSIngo Weinhold 
7520c0fea5dSIngo Weinhold 	for (i = HASHBUCKETS(image)[hash]; i != STN_UNDEF; i = HASHCHAINS(image)[i]) {
7530c0fea5dSIngo Weinhold 		struct Elf32_Sym *symbol = &image->syms[i];
7540c0fea5dSIngo Weinhold 
7550c0fea5dSIngo Weinhold 		if (symbol->st_shndx != SHN_UNDEF
7560c0fea5dSIngo Weinhold 			&& ((ELF32_ST_BIND(symbol->st_info)== STB_GLOBAL)
7570c0fea5dSIngo Weinhold 				|| (ELF32_ST_BIND(symbol->st_info) == STB_WEAK))
7580c0fea5dSIngo Weinhold 			&& !strcmp(SYMNAME(image, symbol), name)) {
7590c0fea5dSIngo Weinhold 			// check if the type matches
7600c0fea5dSIngo Weinhold 			if ((type == B_SYMBOL_TYPE_TEXT && ELF32_ST_TYPE(symbol->st_info) != STT_FUNC)
7610c0fea5dSIngo Weinhold 				|| (type == B_SYMBOL_TYPE_DATA && ELF32_ST_TYPE(symbol->st_info) != STT_OBJECT))
7620c0fea5dSIngo Weinhold 				continue;
7630c0fea5dSIngo Weinhold 
7640c0fea5dSIngo Weinhold 			return symbol;
7650c0fea5dSIngo Weinhold 		}
7660c0fea5dSIngo Weinhold 	}
7670c0fea5dSIngo Weinhold 
7680c0fea5dSIngo Weinhold 	return NULL;
7690c0fea5dSIngo Weinhold }
7700c0fea5dSIngo Weinhold 
7710c0fea5dSIngo Weinhold 
7720c0fea5dSIngo Weinhold static struct Elf32_Sym*
77346f4d849SIngo Weinhold find_symbol_recursively_impl(image_t* image, const char* name,
77446f4d849SIngo Weinhold 	image_t** foundInImage)
7750c0fea5dSIngo Weinhold {
77646f4d849SIngo Weinhold 	image->flags |= RFLAG_VISITED;
7770c0fea5dSIngo Weinhold 
7780c0fea5dSIngo Weinhold 	struct Elf32_Sym *symbol;
7790c0fea5dSIngo Weinhold 
78046f4d849SIngo Weinhold 	// look up the symbol in this image
78146f4d849SIngo Weinhold 	if (image->dynamic_ptr) {
7820c0fea5dSIngo Weinhold 		symbol = find_symbol(image, name, B_SYMBOL_TYPE_ANY);
7830c0fea5dSIngo Weinhold 		if (symbol) {
78446f4d849SIngo Weinhold 			*foundInImage = image;
78546f4d849SIngo Weinhold 			return symbol;
78646f4d849SIngo Weinhold 		}
78746f4d849SIngo Weinhold 	}
78846f4d849SIngo Weinhold 
78946f4d849SIngo Weinhold 	// recursively search dependencies
79046f4d849SIngo Weinhold 	for (uint32 i = 0; i < image->num_needed; i++) {
79146f4d849SIngo Weinhold 		if (!(image->needed[i]->flags & RFLAG_VISITED)) {
79246f4d849SIngo Weinhold 			symbol = find_symbol_recursively_impl(image->needed[i], name,
79346f4d849SIngo Weinhold 				foundInImage);
79446f4d849SIngo Weinhold 			if (symbol)
7950c0fea5dSIngo Weinhold 				return symbol;
7960c0fea5dSIngo Weinhold 		}
7970c0fea5dSIngo Weinhold 	}
7980c0fea5dSIngo Weinhold 
7990c0fea5dSIngo Weinhold 	return NULL;
8000c0fea5dSIngo Weinhold }
8010c0fea5dSIngo Weinhold 
8020c0fea5dSIngo Weinhold 
80346f4d849SIngo Weinhold static void
80446f4d849SIngo Weinhold clear_image_flag_recursively(image_t* image, uint32 flag)
80546f4d849SIngo Weinhold {
80646f4d849SIngo Weinhold 	image->flags &= ~flag;
80746f4d849SIngo Weinhold 
80846f4d849SIngo Weinhold 	for (uint32 i = 0; i < image->num_needed; i++) {
80946f4d849SIngo Weinhold 		if (image->needed[i]->flags & flag)
81046f4d849SIngo Weinhold 			clear_image_flag_recursively(image->needed[i], flag);
81146f4d849SIngo Weinhold 	}
81246f4d849SIngo Weinhold }
81346f4d849SIngo Weinhold 
81446f4d849SIngo Weinhold 
81546f4d849SIngo Weinhold static struct Elf32_Sym*
81646f4d849SIngo Weinhold find_symbol_recursively(image_t* image, const char* name,
81746f4d849SIngo Weinhold 	image_t** foundInImage)
81846f4d849SIngo Weinhold {
81946f4d849SIngo Weinhold 	struct Elf32_Sym* symbol = find_symbol_recursively_impl(image, name,
82046f4d849SIngo Weinhold 		foundInImage);
82146f4d849SIngo Weinhold 	clear_image_flag_recursively(image, RFLAG_VISITED);
82246f4d849SIngo Weinhold 	return symbol;
82346f4d849SIngo Weinhold }
82446f4d849SIngo Weinhold 
82546f4d849SIngo Weinhold 
82646f4d849SIngo Weinhold static struct Elf32_Sym*
82746f4d849SIngo Weinhold find_symbol_in_loaded_images(const char* name, image_t** foundInImage)
82846f4d849SIngo Weinhold {
82946f4d849SIngo Weinhold 	return find_symbol_recursively(sLoadedImages.head, name, foundInImage);
83046f4d849SIngo Weinhold }
83146f4d849SIngo Weinhold 
83246f4d849SIngo Weinhold 
83346f4d849SIngo Weinhold static struct Elf32_Sym*
83446f4d849SIngo Weinhold find_undefined_symbol(image_t* rootImage, image_t* image, const char* name,
83546f4d849SIngo Weinhold 	image_t** foundInImage)
83646f4d849SIngo Weinhold {
83746f4d849SIngo Weinhold 	// If not simulating BeOS style symbol resolution, undefined symbols are
83846f4d849SIngo Weinhold 	// search recursively starting from the root image. (Note, breadth first
83946f4d849SIngo Weinhold 	// might be better than the depth first use here.)
84046f4d849SIngo Weinhold 	if (!sResolveSymbolsBeOSStyle)
84146f4d849SIngo Weinhold 		return find_symbol_recursively(rootImage, name, foundInImage);
84246f4d849SIngo Weinhold 
84346f4d849SIngo Weinhold 	// BeOS style symbol resolution: It is sufficient to check the direct
84446f4d849SIngo Weinhold 	// dependencies. The linker would have complained, if the symbol wasn't
84546f4d849SIngo Weinhold 	// there.
84646f4d849SIngo Weinhold 	for (uint32 i = 0; i < image->num_needed; i++) {
84746f4d849SIngo Weinhold 		if (image->needed[i]->dynamic_ptr) {
84846f4d849SIngo Weinhold 			struct Elf32_Sym *symbol = find_symbol(image->needed[i], name,
84946f4d849SIngo Weinhold 				B_SYMBOL_TYPE_ANY);
85046f4d849SIngo Weinhold 			if (symbol) {
85146f4d849SIngo Weinhold 				*foundInImage = image->needed[i];
85246f4d849SIngo Weinhold 				return symbol;
85346f4d849SIngo Weinhold 			}
85446f4d849SIngo Weinhold 		}
85546f4d849SIngo Weinhold 	}
85646f4d849SIngo Weinhold 
85746f4d849SIngo Weinhold 	return NULL;
85846f4d849SIngo Weinhold }
85946f4d849SIngo Weinhold 
86046f4d849SIngo Weinhold 
8610c0fea5dSIngo Weinhold int
86246f4d849SIngo Weinhold resolve_symbol(image_t *rootImage, image_t *image, struct Elf32_Sym *sym,
86346f4d849SIngo Weinhold 	addr_t *sym_addr)
8640c0fea5dSIngo Weinhold {
8650c0fea5dSIngo Weinhold 	struct Elf32_Sym *sym2;
8660c0fea5dSIngo Weinhold 	char *symname;
8670c0fea5dSIngo Weinhold 	image_t *shimg;
8680c0fea5dSIngo Weinhold 
8690c0fea5dSIngo Weinhold 	switch (sym->st_shndx) {
8700c0fea5dSIngo Weinhold 		case SHN_UNDEF:
8710c0fea5dSIngo Weinhold 			// patch the symbol name
8720c0fea5dSIngo Weinhold 			symname = SYMNAME(image, sym);
8730c0fea5dSIngo Weinhold 
87446f4d849SIngo Weinhold 			// it's undefined, must be outside this image, try the other images
87546f4d849SIngo Weinhold 			sym2 = find_undefined_symbol(rootImage, image, symname, &shimg);
8760c0fea5dSIngo Weinhold 			if (!sym2) {
8770c0fea5dSIngo Weinhold 				printf("elf_resolve_symbol: could not resolve symbol '%s'\n", symname);
8780c0fea5dSIngo Weinhold 				return B_MISSING_SYMBOL;
8790c0fea5dSIngo Weinhold 			}
8800c0fea5dSIngo Weinhold 
8810c0fea5dSIngo Weinhold 			// make sure they're the same type
8820c0fea5dSIngo Weinhold 			if (ELF32_ST_TYPE(sym->st_info) != STT_NOTYPE
8830c0fea5dSIngo Weinhold 				&& ELF32_ST_TYPE(sym->st_info) != ELF32_ST_TYPE(sym2->st_info)) {
8840c0fea5dSIngo Weinhold 				printf("elf_resolve_symbol: found symbol '%s' in shared image but wrong type\n", symname);
8850c0fea5dSIngo Weinhold 				return B_MISSING_SYMBOL;
8860c0fea5dSIngo Weinhold 			}
8870c0fea5dSIngo Weinhold 
8880c0fea5dSIngo Weinhold 			if (ELF32_ST_BIND(sym2->st_info) != STB_GLOBAL
8890c0fea5dSIngo Weinhold 				&& ELF32_ST_BIND(sym2->st_info) != STB_WEAK) {
8900c0fea5dSIngo Weinhold 				printf("elf_resolve_symbol: found symbol '%s' but not exported\n", symname);
8910c0fea5dSIngo Weinhold 				return B_MISSING_SYMBOL;
8920c0fea5dSIngo Weinhold 			}
8930c0fea5dSIngo Weinhold 
8940c0fea5dSIngo Weinhold 			*sym_addr = sym2->st_value + shimg->regions[0].delta;
8950c0fea5dSIngo Weinhold 			return B_NO_ERROR;
8960c0fea5dSIngo Weinhold 
8970c0fea5dSIngo Weinhold 		case SHN_ABS:
8980c0fea5dSIngo Weinhold 			*sym_addr = sym->st_value + image->regions[0].delta;
8990c0fea5dSIngo Weinhold 			return B_NO_ERROR;
9000c0fea5dSIngo Weinhold 
9010c0fea5dSIngo Weinhold 		case SHN_COMMON:
9020c0fea5dSIngo Weinhold 			// ToDo: finish this
9030c0fea5dSIngo Weinhold 			printf("elf_resolve_symbol: COMMON symbol, finish me!\n");
9040c0fea5dSIngo Weinhold 			return B_ERROR; //ERR_NOT_IMPLEMENTED_YET;
9050c0fea5dSIngo Weinhold 
9060c0fea5dSIngo Weinhold 		default:
9070c0fea5dSIngo Weinhold 			// standard symbol
9080c0fea5dSIngo Weinhold 			*sym_addr = sym->st_value + image->regions[0].delta;
9090c0fea5dSIngo Weinhold 			return B_NO_ERROR;
9100c0fea5dSIngo Weinhold 	}
9110c0fea5dSIngo Weinhold }
9120c0fea5dSIngo Weinhold 
9130c0fea5dSIngo Weinhold 
9140c0fea5dSIngo Weinhold static void
9150c0fea5dSIngo Weinhold register_image(image_t *image, int fd, const char *path)
9160c0fea5dSIngo Weinhold {
9170c0fea5dSIngo Weinhold 	struct stat stat;
9180c0fea5dSIngo Weinhold 	image_info info;
9190c0fea5dSIngo Weinhold 
9200c0fea5dSIngo Weinhold 	// ToDo: set these correctly
9210c0fea5dSIngo Weinhold 	info.id = 0;
9220c0fea5dSIngo Weinhold 	info.type = image->type;
9230c0fea5dSIngo Weinhold 	info.sequence = 0;
9240c0fea5dSIngo Weinhold 	info.init_order = 0;
9250c0fea5dSIngo Weinhold 	info.init_routine = (void (*)())image->init_routine;
9260c0fea5dSIngo Weinhold 	info.term_routine = (void (*)())image->term_routine;
9270c0fea5dSIngo Weinhold 
9280c0fea5dSIngo Weinhold 	if (_kern_read_stat(fd, NULL, false, &stat, sizeof(struct stat)) == B_OK) {
9290c0fea5dSIngo Weinhold 		info.device = stat.st_dev;
9300c0fea5dSIngo Weinhold 		info.node = stat.st_ino;
9310c0fea5dSIngo Weinhold 	} else {
9320c0fea5dSIngo Weinhold 		info.device = -1;
9330c0fea5dSIngo Weinhold 		info.node = -1;
9340c0fea5dSIngo Weinhold 	}
9350c0fea5dSIngo Weinhold 
9360c0fea5dSIngo Weinhold 	strlcpy(info.name, path, sizeof(info.name));
9370c0fea5dSIngo Weinhold 	info.text = (void *)image->regions[0].vmstart;
9380c0fea5dSIngo Weinhold 	info.text_size = image->regions[0].vmsize;
9390c0fea5dSIngo Weinhold 	info.data = (void *)image->regions[1].vmstart;
9400c0fea5dSIngo Weinhold 	info.data_size = image->regions[1].vmsize;
9410c0fea5dSIngo Weinhold 	image->id = _kern_register_image(&info, sizeof(image_info));
9420c0fea5dSIngo Weinhold }
9430c0fea5dSIngo Weinhold 
9440c0fea5dSIngo Weinhold 
9450c0fea5dSIngo Weinhold static status_t
94646f4d849SIngo Weinhold relocate_image(image_t *rootImage, image_t *image)
9470c0fea5dSIngo Weinhold {
94846f4d849SIngo Weinhold 	status_t status = arch_relocate_image(rootImage, image);
9490c0fea5dSIngo Weinhold 	if (status < B_OK) {
95046f4d849SIngo Weinhold 		FATAL("troubles relocating: 0x%lx (image: %s)\n", status, image->name);
9510c0fea5dSIngo Weinhold 		return status;
9520c0fea5dSIngo Weinhold 	}
9530c0fea5dSIngo Weinhold 
9540c0fea5dSIngo Weinhold 	_kern_image_relocated(image->id);
9550c0fea5dSIngo Weinhold 	return B_OK;
9560c0fea5dSIngo Weinhold }
9570c0fea5dSIngo Weinhold 
9580c0fea5dSIngo Weinhold 
9590c0fea5dSIngo Weinhold static status_t
9600c0fea5dSIngo Weinhold load_container(char const *name, image_type type, const char *rpath, image_t **_image)
9610c0fea5dSIngo Weinhold {
9620c0fea5dSIngo Weinhold 	int32 pheaderSize, sheaderSize;
9630c0fea5dSIngo Weinhold 	char path[PATH_MAX];
9640c0fea5dSIngo Weinhold 	ssize_t length;
9650c0fea5dSIngo Weinhold 	char ph_buff[4096];
9660c0fea5dSIngo Weinhold 	int32 numRegions;
9670c0fea5dSIngo Weinhold 	image_t *found;
9680c0fea5dSIngo Weinhold 	image_t *image;
9690c0fea5dSIngo Weinhold 	status_t status;
9700c0fea5dSIngo Weinhold 	int fd;
9710c0fea5dSIngo Weinhold 
9720c0fea5dSIngo Weinhold 	struct Elf32_Ehdr eheader;
9730c0fea5dSIngo Weinhold 
9740c0fea5dSIngo Weinhold 	// Have we already loaded that image? Don't check for add-ons -- we always
9750c0fea5dSIngo Weinhold 	// reload them.
9760c0fea5dSIngo Weinhold 	if (type != B_ADD_ON_IMAGE) {
9770c0fea5dSIngo Weinhold 		found = find_image(name, APP_OR_LIBRARY_TYPE);
9780c0fea5dSIngo Weinhold 		if (found) {
9790c0fea5dSIngo Weinhold 			atomic_add(&found->ref_count, 1);
9800c0fea5dSIngo Weinhold 			*_image = found;
981*7486b72dSIngo Weinhold 			KTRACE("rld: load_container(\"%s\", type: %d, rpath: \"%s\") "
982*7486b72dSIngo Weinhold 				"already loaded", name, type, rpath);
9830c0fea5dSIngo Weinhold 			return B_OK;
9840c0fea5dSIngo Weinhold 		}
9850c0fea5dSIngo Weinhold 	}
9860c0fea5dSIngo Weinhold 
987*7486b72dSIngo Weinhold 	KTRACE("rld: load_container(\"%s\", type: %d, rpath: \"%s\")", name, type,
988*7486b72dSIngo Weinhold 		rpath);
989*7486b72dSIngo Weinhold 
9900c0fea5dSIngo Weinhold 	strlcpy(path, name, sizeof(path));
9910c0fea5dSIngo Weinhold 
9920c0fea5dSIngo Weinhold 	// Try to load explicit image path first
9930c0fea5dSIngo Weinhold 	fd = open_executable(path, type, rpath);
9940c0fea5dSIngo Weinhold 	if (fd < 0) {
9950c0fea5dSIngo Weinhold 		FATAL("cannot open file %s\n", path);
996*7486b72dSIngo Weinhold 		KTRACE("rld: load_container(\"%s\"): failed to open file", name);
9970c0fea5dSIngo Weinhold 		return fd;
9980c0fea5dSIngo Weinhold 	}
9990c0fea5dSIngo Weinhold 
10000c0fea5dSIngo Weinhold 	// If the path is not absolute, we prepend the CWD to make it one.
10010c0fea5dSIngo Weinhold 	if (path[0] != '/') {
10020c0fea5dSIngo Weinhold 		char relativePath[PATH_MAX];
10030c0fea5dSIngo Weinhold 		if (!strncmp(path, "./", 2))
10040c0fea5dSIngo Weinhold 			strcpy(relativePath, path + 2);
10050c0fea5dSIngo Weinhold 		else
10060c0fea5dSIngo Weinhold 			strcpy(relativePath, path);
10070c0fea5dSIngo Weinhold 
10080c0fea5dSIngo Weinhold 		// get the CWD
10090c0fea5dSIngo Weinhold 		status = _kern_getcwd(path, sizeof(path));
10100c0fea5dSIngo Weinhold 		if (status < B_OK) {
10110c0fea5dSIngo Weinhold 			FATAL("_kern_getcwd() failed\n");
10120c0fea5dSIngo Weinhold 			goto err1;
10130c0fea5dSIngo Weinhold 		}
10140c0fea5dSIngo Weinhold 
10150c0fea5dSIngo Weinhold 		if (strlcat(path, "/", sizeof(path)) >= sizeof(path)
10160c0fea5dSIngo Weinhold 			|| strlcat(path, relativePath, sizeof(path)) >= sizeof(path)) {
10170c0fea5dSIngo Weinhold 			status = B_NAME_TOO_LONG;
10180c0fea5dSIngo Weinhold 			FATAL("Absolute path of image %s is too "
10190c0fea5dSIngo Weinhold 				"long!\n", relativePath);
10200c0fea5dSIngo Weinhold 			goto err1;
10210c0fea5dSIngo Weinhold 		}
10220c0fea5dSIngo Weinhold 	}
10230c0fea5dSIngo Weinhold 
10240c0fea5dSIngo Weinhold 	// Test again if this image has been registered already - this time,
10250c0fea5dSIngo Weinhold 	// we can check the full path, not just its name as noted.
10260c0fea5dSIngo Weinhold 	// You could end up loading an image twice with symbolic links, else.
10270c0fea5dSIngo Weinhold 	if (type != B_ADD_ON_IMAGE) {
10280c0fea5dSIngo Weinhold 		found = find_image(path, APP_OR_LIBRARY_TYPE);
10290c0fea5dSIngo Weinhold 		if (found) {
10300c0fea5dSIngo Weinhold 			atomic_add(&found->ref_count, 1);
10310c0fea5dSIngo Weinhold 			*_image = found;
1032*7486b72dSIngo Weinhold 			KTRACE("rld: load_container(\"%s\"): already loaded after all",
1033*7486b72dSIngo Weinhold 				name);
10340c0fea5dSIngo Weinhold 			return B_OK;
10350c0fea5dSIngo Weinhold 		}
10360c0fea5dSIngo Weinhold 	}
10370c0fea5dSIngo Weinhold 
10380c0fea5dSIngo Weinhold 	length = _kern_read(fd, 0, &eheader, sizeof(eheader));
10390c0fea5dSIngo Weinhold 	if (length != sizeof(eheader)) {
10400c0fea5dSIngo Weinhold 		status = B_NOT_AN_EXECUTABLE;
10410c0fea5dSIngo Weinhold 		FATAL("troubles reading ELF header\n");
10420c0fea5dSIngo Weinhold 		goto err1;
10430c0fea5dSIngo Weinhold 	}
10440c0fea5dSIngo Weinhold 
10450c0fea5dSIngo Weinhold 	status = parse_elf_header(&eheader, &pheaderSize, &sheaderSize);
10460c0fea5dSIngo Weinhold 	if (status < B_OK) {
10470c0fea5dSIngo Weinhold 		FATAL("incorrect ELF header\n");
10480c0fea5dSIngo Weinhold 		goto err1;
10490c0fea5dSIngo Weinhold 	}
10500c0fea5dSIngo Weinhold 
10510c0fea5dSIngo Weinhold 	// ToDo: what to do about this restriction??
10520c0fea5dSIngo Weinhold 	if (pheaderSize > (int)sizeof(ph_buff)) {
10530c0fea5dSIngo Weinhold 		FATAL("Cannot handle program headers bigger than %lu\n", sizeof(ph_buff));
10540c0fea5dSIngo Weinhold 		status = B_UNSUPPORTED;
10550c0fea5dSIngo Weinhold 		goto err1;
10560c0fea5dSIngo Weinhold 	}
10570c0fea5dSIngo Weinhold 
10580c0fea5dSIngo Weinhold 	length = _kern_read(fd, eheader.e_phoff, ph_buff, pheaderSize);
10590c0fea5dSIngo Weinhold 	if (length != pheaderSize) {
10600c0fea5dSIngo Weinhold 		FATAL("Could not read program headers: %s\n", strerror(length));
10610c0fea5dSIngo Weinhold 		status = B_BAD_DATA;
10620c0fea5dSIngo Weinhold 		goto err1;
10630c0fea5dSIngo Weinhold 	}
10640c0fea5dSIngo Weinhold 
10650c0fea5dSIngo Weinhold 	numRegions = count_regions(ph_buff, eheader.e_phnum, eheader.e_phentsize);
10660c0fea5dSIngo Weinhold 	if (numRegions <= 0) {
10670c0fea5dSIngo Weinhold 		FATAL("Troubles parsing Program headers, numRegions = %ld\n", numRegions);
10680c0fea5dSIngo Weinhold 		status = B_BAD_DATA;
10690c0fea5dSIngo Weinhold 		goto err1;
10700c0fea5dSIngo Weinhold 	}
10710c0fea5dSIngo Weinhold 
10720c0fea5dSIngo Weinhold 	image = create_image(name, path, numRegions);
10730c0fea5dSIngo Weinhold 	if (image == NULL) {
10740c0fea5dSIngo Weinhold 		FATAL("Failed to allocate image_t object\n");
10750c0fea5dSIngo Weinhold 		status = B_NO_MEMORY;
10760c0fea5dSIngo Weinhold 		goto err1;
10770c0fea5dSIngo Weinhold 	}
10780c0fea5dSIngo Weinhold 
10790c0fea5dSIngo Weinhold 	status = parse_program_headers(image, ph_buff, eheader.e_phnum, eheader.e_phentsize);
10800c0fea5dSIngo Weinhold 	if (status < B_OK)
10810c0fea5dSIngo Weinhold 		goto err2;
10820c0fea5dSIngo Weinhold 
10830c0fea5dSIngo Weinhold 	if (!assert_dynamic_loadable(image)) {
10840c0fea5dSIngo Weinhold 		FATAL("Dynamic segment must be loadable (implementation restriction)\n");
10850c0fea5dSIngo Weinhold 		status = B_UNSUPPORTED;
10860c0fea5dSIngo Weinhold 		goto err2;
10870c0fea5dSIngo Weinhold 	}
10880c0fea5dSIngo Weinhold 
10890c0fea5dSIngo Weinhold 	status = map_image(fd, path, image, type == B_APP_IMAGE);
10900c0fea5dSIngo Weinhold 	if (status < B_OK) {
10910c0fea5dSIngo Weinhold 		FATAL("Could not map image: %s\n", strerror(status));
10920c0fea5dSIngo Weinhold 		status = B_ERROR;
10930c0fea5dSIngo Weinhold 		goto err2;
10940c0fea5dSIngo Weinhold 	}
10950c0fea5dSIngo Weinhold 
10960c0fea5dSIngo Weinhold 	if (!parse_dynamic_segment(image)) {
10970c0fea5dSIngo Weinhold 		FATAL("Troubles handling dynamic section\n");
10980c0fea5dSIngo Weinhold 		status = B_BAD_DATA;
10990c0fea5dSIngo Weinhold 		goto err3;
11000c0fea5dSIngo Weinhold 	}
11010c0fea5dSIngo Weinhold 
11020c0fea5dSIngo Weinhold 	if (eheader.e_entry != NULL)
11030c0fea5dSIngo Weinhold 		image->entry_point = eheader.e_entry + image->regions[0].delta;
11040c0fea5dSIngo Weinhold 
11050c0fea5dSIngo Weinhold 	image->type = type;
11060c0fea5dSIngo Weinhold 	register_image(image, fd, path);
11070c0fea5dSIngo Weinhold 
11080c0fea5dSIngo Weinhold 	_kern_close(fd);
11090c0fea5dSIngo Weinhold 
11100c0fea5dSIngo Weinhold 	enqueue_image(&sLoadedImages, image);
11110c0fea5dSIngo Weinhold 	sLoadedImageCount++;
11120c0fea5dSIngo Weinhold 
11130c0fea5dSIngo Weinhold 	*_image = image;
1114*7486b72dSIngo Weinhold 
1115*7486b72dSIngo Weinhold 	KTRACE("rld: load_container(\"%s\"): done: id: %ld", name, image->id);
1116*7486b72dSIngo Weinhold 
11170c0fea5dSIngo Weinhold 	return B_OK;
11180c0fea5dSIngo Weinhold 
11190c0fea5dSIngo Weinhold err3:
11200c0fea5dSIngo Weinhold 	unmap_image(image);
11210c0fea5dSIngo Weinhold err2:
11220c0fea5dSIngo Weinhold 	delete_image_struct(image);
11230c0fea5dSIngo Weinhold err1:
11240c0fea5dSIngo Weinhold 	_kern_close(fd);
1125*7486b72dSIngo Weinhold 
1126*7486b72dSIngo Weinhold 	KTRACE("rld: load_container(\"%s\"): failed: %s", name,
1127*7486b72dSIngo Weinhold 		strerror(status));
1128*7486b72dSIngo Weinhold 
11290c0fea5dSIngo Weinhold 	return status;
11300c0fea5dSIngo Weinhold }
11310c0fea5dSIngo Weinhold 
11320c0fea5dSIngo Weinhold 
11330c0fea5dSIngo Weinhold static const char *
11340c0fea5dSIngo Weinhold find_dt_rpath(image_t *image)
11350c0fea5dSIngo Weinhold {
11360c0fea5dSIngo Weinhold 	int i;
11370c0fea5dSIngo Weinhold 	struct Elf32_Dyn *d = (struct Elf32_Dyn *)image->dynamic_ptr;
11380c0fea5dSIngo Weinhold 
11390c0fea5dSIngo Weinhold 	for (i = 0; d[i].d_tag != DT_NULL; i++) {
11400c0fea5dSIngo Weinhold 		if (d[i].d_tag == DT_RPATH)
11410c0fea5dSIngo Weinhold 			return STRING(image, d[i].d_un.d_val);
11420c0fea5dSIngo Weinhold 	}
11430c0fea5dSIngo Weinhold 
11440c0fea5dSIngo Weinhold 	return NULL;
11450c0fea5dSIngo Weinhold }
11460c0fea5dSIngo Weinhold 
11470c0fea5dSIngo Weinhold 
11480c0fea5dSIngo Weinhold static status_t
11490c0fea5dSIngo Weinhold load_dependencies(image_t *image)
11500c0fea5dSIngo Weinhold {
11510c0fea5dSIngo Weinhold 	struct Elf32_Dyn *d = (struct Elf32_Dyn *)image->dynamic_ptr;
11524bef3723SAxel Dörfler 	bool reportErrors = report_errors();
115374c0424aSAxel Dörfler 	status_t status = B_OK;
11540c0fea5dSIngo Weinhold 	uint32 i, j;
11550c0fea5dSIngo Weinhold 	const char *rpath;
11560c0fea5dSIngo Weinhold 
11570c0fea5dSIngo Weinhold 	if (!d || (image->flags & RFLAG_DEPENDENCIES_LOADED))
11580c0fea5dSIngo Weinhold 		return B_OK;
11590c0fea5dSIngo Weinhold 
11600c0fea5dSIngo Weinhold 	image->flags |= RFLAG_DEPENDENCIES_LOADED;
11610c0fea5dSIngo Weinhold 
11620c0fea5dSIngo Weinhold 	if (image->num_needed == 0)
11630c0fea5dSIngo Weinhold 		return B_OK;
11640c0fea5dSIngo Weinhold 
1165*7486b72dSIngo Weinhold 	KTRACE("rld: load_dependencies(\"%s\", id: %ld)", image->name,
1166*7486b72dSIngo Weinhold 		image->id);
1167*7486b72dSIngo Weinhold 
11680c0fea5dSIngo Weinhold 	image->needed = (image_t**)malloc(image->num_needed * sizeof(image_t *));
11690c0fea5dSIngo Weinhold 	if (image->needed == NULL) {
11700c0fea5dSIngo Weinhold 		FATAL("failed to allocate needed struct\n");
1171*7486b72dSIngo Weinhold 		KTRACE("rld: load_dependencies(\"%s\", id: %ld) failed: no memory",
1172*7486b72dSIngo Weinhold 			image->name, image->id);
11730c0fea5dSIngo Weinhold 		return B_NO_MEMORY;
11740c0fea5dSIngo Weinhold 	}
11750c0fea5dSIngo Weinhold 
11760c0fea5dSIngo Weinhold 	memset(image->needed, 0, image->num_needed * sizeof(image_t *));
11770c0fea5dSIngo Weinhold 	rpath = find_dt_rpath(image);
11780c0fea5dSIngo Weinhold 
11790c0fea5dSIngo Weinhold 	for (i = 0, j = 0; d[i].d_tag != DT_NULL; i++) {
11800c0fea5dSIngo Weinhold 		switch (d[i].d_tag) {
11810c0fea5dSIngo Weinhold 			case DT_NEEDED:
118274c0424aSAxel Dörfler 			{
118374c0424aSAxel Dörfler 				int32 neededOffset = d[i].d_un.d_val;
118474c0424aSAxel Dörfler 				const char *name = STRING(image, neededOffset);
11850c0fea5dSIngo Weinhold 
118674c0424aSAxel Dörfler 				status_t loadStatus = load_container(name, B_LIBRARY_IMAGE,
118774c0424aSAxel Dörfler 					rpath, &image->needed[j]);
118874c0424aSAxel Dörfler 				if (loadStatus < B_OK) {
118974c0424aSAxel Dörfler 					status = loadStatus;
119074c0424aSAxel Dörfler 					// correct error code in case the file could not been found
119174c0424aSAxel Dörfler 					if (status == B_ENTRY_NOT_FOUND) {
119274c0424aSAxel Dörfler 						status = B_MISSING_LIBRARY;
119374c0424aSAxel Dörfler 
119474c0424aSAxel Dörfler 						if (reportErrors)
119574c0424aSAxel Dörfler 							sErrorMessage.AddString("missing library", name);
119674c0424aSAxel Dörfler 					}
119774c0424aSAxel Dörfler 
119874c0424aSAxel Dörfler 					// Collect all missing libraries in case we report back
1199*7486b72dSIngo Weinhold 					if (!reportErrors) {
1200*7486b72dSIngo Weinhold 						KTRACE("rld: load_dependencies(\"%s\", id: %ld) "
1201*7486b72dSIngo Weinhold 							"failed: %s", image->name, image->id,
1202*7486b72dSIngo Weinhold 							strerror(status));
12030c0fea5dSIngo Weinhold 						return status;
120474c0424aSAxel Dörfler 					}
1205*7486b72dSIngo Weinhold 				}
12060c0fea5dSIngo Weinhold 
12070c0fea5dSIngo Weinhold 				j += 1;
12080c0fea5dSIngo Weinhold 				break;
120974c0424aSAxel Dörfler 			}
12100c0fea5dSIngo Weinhold 
12110c0fea5dSIngo Weinhold 			default:
12120c0fea5dSIngo Weinhold 				// ignore any other tag
12130c0fea5dSIngo Weinhold 				continue;
12140c0fea5dSIngo Weinhold 		}
12150c0fea5dSIngo Weinhold 	}
12160c0fea5dSIngo Weinhold 
1217*7486b72dSIngo Weinhold 	if (status < B_OK) {
1218*7486b72dSIngo Weinhold 		KTRACE("rld: load_dependencies(\"%s\", id: %ld) "
1219*7486b72dSIngo Weinhold 			"failed: %s", image->name, image->id,
1220*7486b72dSIngo Weinhold 			strerror(status));
122174c0424aSAxel Dörfler 		return status;
1222*7486b72dSIngo Weinhold 	}
122374c0424aSAxel Dörfler 
12240c0fea5dSIngo Weinhold 	if (j != image->num_needed) {
12250c0fea5dSIngo Weinhold 		FATAL("Internal error at load_dependencies()");
1226*7486b72dSIngo Weinhold 		KTRACE("rld: load_dependencies(\"%s\", id: %ld) "
1227*7486b72dSIngo Weinhold 			"failed: internal error", image->name, image->id);
12280c0fea5dSIngo Weinhold 		return B_ERROR;
12290c0fea5dSIngo Weinhold 	}
12300c0fea5dSIngo Weinhold 
1231*7486b72dSIngo Weinhold 	KTRACE("rld: load_dependencies(\"%s\", id: %ld) done", image->name,
1232*7486b72dSIngo Weinhold 		image->id);
1233*7486b72dSIngo Weinhold 
12340c0fea5dSIngo Weinhold 	return B_OK;
12350c0fea5dSIngo Weinhold }
12360c0fea5dSIngo Weinhold 
12370c0fea5dSIngo Weinhold 
12380c0fea5dSIngo Weinhold static uint32
12390c0fea5dSIngo Weinhold topological_sort(image_t *image, uint32 slot, image_t **initList,
12400c0fea5dSIngo Weinhold 	uint32 sortFlag)
12410c0fea5dSIngo Weinhold {
12420c0fea5dSIngo Weinhold 	uint32 i;
12430c0fea5dSIngo Weinhold 
12440c0fea5dSIngo Weinhold 	if (image->flags & sortFlag)
12450c0fea5dSIngo Weinhold 		return slot;
12460c0fea5dSIngo Weinhold 
12470c0fea5dSIngo Weinhold 	image->flags |= sortFlag; /* make sure we don't visit this one */
12480c0fea5dSIngo Weinhold 	for (i = 0; i < image->num_needed; i++)
12490c0fea5dSIngo Weinhold 		slot = topological_sort(image->needed[i], slot, initList, sortFlag);
12500c0fea5dSIngo Weinhold 
12510c0fea5dSIngo Weinhold 	initList[slot] = image;
12520c0fea5dSIngo Weinhold 	return slot + 1;
12530c0fea5dSIngo Weinhold }
12540c0fea5dSIngo Weinhold 
12550c0fea5dSIngo Weinhold 
12560c0fea5dSIngo Weinhold static ssize_t
12570c0fea5dSIngo Weinhold get_sorted_image_list(image_t *image, image_t ***_list, uint32 sortFlag)
12580c0fea5dSIngo Weinhold {
12590c0fea5dSIngo Weinhold 	image_t **list;
12600c0fea5dSIngo Weinhold 
12610c0fea5dSIngo Weinhold 	list = (image_t**)malloc(sLoadedImageCount * sizeof(image_t *));
12620c0fea5dSIngo Weinhold 	if (list == NULL) {
12630c0fea5dSIngo Weinhold 		FATAL("memory shortage in get_sorted_image_list()");
12640c0fea5dSIngo Weinhold 		*_list = NULL;
12650c0fea5dSIngo Weinhold 		return B_NO_MEMORY;
12660c0fea5dSIngo Weinhold 	}
12670c0fea5dSIngo Weinhold 
12680c0fea5dSIngo Weinhold 	memset(list, 0, sLoadedImageCount * sizeof(image_t *));
12690c0fea5dSIngo Weinhold 
12700c0fea5dSIngo Weinhold 	*_list = list;
12710c0fea5dSIngo Weinhold 	return topological_sort(image, 0, list, sortFlag);
12720c0fea5dSIngo Weinhold }
12730c0fea5dSIngo Weinhold 
12740c0fea5dSIngo Weinhold 
12750c0fea5dSIngo Weinhold static status_t
12760c0fea5dSIngo Weinhold relocate_dependencies(image_t *image)
12770c0fea5dSIngo Weinhold {
12780c0fea5dSIngo Weinhold 	ssize_t count, i;
12790c0fea5dSIngo Weinhold 	image_t **list;
12800c0fea5dSIngo Weinhold 
12810c0fea5dSIngo Weinhold 	count = get_sorted_image_list(image, &list, RFLAG_RELOCATED);
12820c0fea5dSIngo Weinhold 	if (count < B_OK)
12830c0fea5dSIngo Weinhold 		return count;
12840c0fea5dSIngo Weinhold 
12850c0fea5dSIngo Weinhold 	for (i = 0; i < count; i++) {
128646f4d849SIngo Weinhold 		status_t status = relocate_image(image, list[i]);
12870c0fea5dSIngo Weinhold 		if (status < B_OK)
12880c0fea5dSIngo Weinhold 			return status;
12890c0fea5dSIngo Weinhold 	}
12900c0fea5dSIngo Weinhold 
12910c0fea5dSIngo Weinhold 	free(list);
12920c0fea5dSIngo Weinhold 	return B_OK;
12930c0fea5dSIngo Weinhold }
12940c0fea5dSIngo Weinhold 
12950c0fea5dSIngo Weinhold 
12960c0fea5dSIngo Weinhold static void
12970c0fea5dSIngo Weinhold init_dependencies(image_t *image, bool initHead)
12980c0fea5dSIngo Weinhold {
12990c0fea5dSIngo Weinhold 	image_t **initList;
13000c0fea5dSIngo Weinhold 	ssize_t count, i;
13010c0fea5dSIngo Weinhold 
13020c0fea5dSIngo Weinhold 	count = get_sorted_image_list(image, &initList, RFLAG_INITIALIZED);
13030c0fea5dSIngo Weinhold 	if (count <= 0)
13040c0fea5dSIngo Weinhold 		return;
13050c0fea5dSIngo Weinhold 
13060c0fea5dSIngo Weinhold 	if (!initHead) {
13070c0fea5dSIngo Weinhold 		// this removes the "calling" image
13080c0fea5dSIngo Weinhold 		image->flags &= ~RFLAG_INITIALIZED;
13090c0fea5dSIngo Weinhold 		initList[--count] = NULL;
13100c0fea5dSIngo Weinhold 	}
13110c0fea5dSIngo Weinhold 
13120c0fea5dSIngo Weinhold 	TRACE(("%ld: init dependencies\n", find_thread(NULL)));
13130c0fea5dSIngo Weinhold 	for (i = 0; i < count; i++) {
13140c0fea5dSIngo Weinhold 		image = initList[i];
13150c0fea5dSIngo Weinhold 
13160c0fea5dSIngo Weinhold 		TRACE(("%ld:  init: %s\n", find_thread(NULL), image->name));
13170c0fea5dSIngo Weinhold 
13180c0fea5dSIngo Weinhold 		if (image->init_routine != NULL)
13190c0fea5dSIngo Weinhold 			((init_term_function)image->init_routine)(image->id);
13200c0fea5dSIngo Weinhold 	}
13210c0fea5dSIngo Weinhold 	TRACE(("%ld:  init done.\n", find_thread(NULL)));
13220c0fea5dSIngo Weinhold 
13230c0fea5dSIngo Weinhold 	free(initList);
13240c0fea5dSIngo Weinhold }
13250c0fea5dSIngo Weinhold 
13260c0fea5dSIngo Weinhold 
13270c0fea5dSIngo Weinhold static void
13280c0fea5dSIngo Weinhold put_image(image_t *image)
13290c0fea5dSIngo Weinhold {
13300c0fea5dSIngo Weinhold 	// If all references to the image are gone, add it to the disposable list
13310c0fea5dSIngo Weinhold 	// and remove all dependencies
13320c0fea5dSIngo Weinhold 
13330c0fea5dSIngo Weinhold 	if (atomic_add(&image->ref_count, -1) == 1) {
13340c0fea5dSIngo Weinhold 		size_t i;
13350c0fea5dSIngo Weinhold 
13360c0fea5dSIngo Weinhold 		dequeue_image(&sLoadedImages, image);
13370c0fea5dSIngo Weinhold 		enqueue_image(&sDisposableImages, image);
13380c0fea5dSIngo Weinhold 		sLoadedImageCount--;
13390c0fea5dSIngo Weinhold 
13400c0fea5dSIngo Weinhold 		for (i = 0; i < image->num_needed; i++) {
13410c0fea5dSIngo Weinhold 			put_image(image->needed[i]);
13420c0fea5dSIngo Weinhold 		}
13430c0fea5dSIngo Weinhold 	}
13440c0fea5dSIngo Weinhold }
13450c0fea5dSIngo Weinhold 
13460c0fea5dSIngo Weinhold 
134774c0424aSAxel Dörfler //	#pragma mark - libroot.so exported functions
13480c0fea5dSIngo Weinhold 
13490c0fea5dSIngo Weinhold 
13500c0fea5dSIngo Weinhold image_id
13510c0fea5dSIngo Weinhold load_program(char const *path, void **_entry)
13520c0fea5dSIngo Weinhold {
13530c0fea5dSIngo Weinhold 	status_t status;
13540c0fea5dSIngo Weinhold 	image_t *image;
13550c0fea5dSIngo Weinhold 
1356*7486b72dSIngo Weinhold 	KTRACE("rld: load_program(\"%s\")", path);
1357*7486b72dSIngo Weinhold 
13580c0fea5dSIngo Weinhold 	rld_lock();
13590c0fea5dSIngo Weinhold 		// for now, just do stupid simple global locking
13600c0fea5dSIngo Weinhold 
13610c0fea5dSIngo Weinhold 	TRACE(("rld: load %s\n", path));
13620c0fea5dSIngo Weinhold 
13630c0fea5dSIngo Weinhold 	status = load_container(path, B_APP_IMAGE, NULL, &sProgramImage);
136474c0424aSAxel Dörfler 	if (status < B_OK)
136574c0424aSAxel Dörfler 		goto err;
13660c0fea5dSIngo Weinhold 
13670c0fea5dSIngo Weinhold 	for (image = sLoadedImages.head; image != NULL; image = image->next) {
13680c0fea5dSIngo Weinhold 		status = load_dependencies(image);
13690c0fea5dSIngo Weinhold 		if (status < B_OK)
13700c0fea5dSIngo Weinhold 			goto err;
13710c0fea5dSIngo Weinhold 	}
13720c0fea5dSIngo Weinhold 
13730c0fea5dSIngo Weinhold 	status = relocate_dependencies(sProgramImage);
13740c0fea5dSIngo Weinhold 	if (status < B_OK)
13750c0fea5dSIngo Weinhold 		goto err;
13760c0fea5dSIngo Weinhold 
13770c0fea5dSIngo Weinhold 	// We patch any exported __gRuntimeLoader symbols to point to our private API
13780c0fea5dSIngo Weinhold 	{
137946f4d849SIngo Weinhold 		struct Elf32_Sym *symbol = find_symbol_in_loaded_images(
138046f4d849SIngo Weinhold 			"__gRuntimeLoader", &image);
13810c0fea5dSIngo Weinhold 		if (symbol != NULL) {
13820c0fea5dSIngo Weinhold 			void **_export = (void **)(symbol->st_value + image->regions[0].delta);
13830c0fea5dSIngo Weinhold 			*_export = &gRuntimeLoader;
13840c0fea5dSIngo Weinhold 		}
13850c0fea5dSIngo Weinhold 	}
13860c0fea5dSIngo Weinhold 
13870c0fea5dSIngo Weinhold 	init_dependencies(sLoadedImages.head, true);
13880c0fea5dSIngo Weinhold 	remap_images();
13890c0fea5dSIngo Weinhold 		// ToDo: once setup_system_time() is fixed, move this one line higher!
13900c0fea5dSIngo Weinhold 
13910c0fea5dSIngo Weinhold 	// Since the images are initialized now, we no longer should use our
13920c0fea5dSIngo Weinhold 	// getenv(), but use the one from libroot.so
13930c0fea5dSIngo Weinhold 	{
139446f4d849SIngo Weinhold 		struct Elf32_Sym *symbol = find_symbol_in_loaded_images("getenv",
139546f4d849SIngo Weinhold 			&image);
13960c0fea5dSIngo Weinhold 		if (symbol != NULL)
13970c0fea5dSIngo Weinhold 			gGetEnv = (char* (*)(const char*))
13980c0fea5dSIngo Weinhold 				(symbol->st_value + image->regions[0].delta);
13990c0fea5dSIngo Weinhold 	}
14000c0fea5dSIngo Weinhold 
14010c0fea5dSIngo Weinhold 	if (sProgramImage->entry_point == NULL) {
14020c0fea5dSIngo Weinhold 		status = B_NOT_AN_EXECUTABLE;
14030c0fea5dSIngo Weinhold 		goto err;
14040c0fea5dSIngo Weinhold 	}
14050c0fea5dSIngo Weinhold 
14060c0fea5dSIngo Weinhold 	*_entry = (void *)(sProgramImage->entry_point);
14070c0fea5dSIngo Weinhold 
14080c0fea5dSIngo Weinhold 	rld_unlock();
1409*7486b72dSIngo Weinhold 
1410*7486b72dSIngo Weinhold 	KTRACE("rld: load_program(\"%s\") done: entry: %p, id: %ld", path,
1411*7486b72dSIngo Weinhold 		*_entry, sProgramImage->id);
1412*7486b72dSIngo Weinhold 
14130c0fea5dSIngo Weinhold 	return sProgramImage->id;
14140c0fea5dSIngo Weinhold 
14150c0fea5dSIngo Weinhold err:
1416*7486b72dSIngo Weinhold 	KTRACE("rld: load_program(\"%s\") failed: %s", path, strerror(status));
1417*7486b72dSIngo Weinhold 
14180c0fea5dSIngo Weinhold 	delete_image(sProgramImage);
141974c0424aSAxel Dörfler 
14204bef3723SAxel Dörfler 	if (report_errors()) {
14214bef3723SAxel Dörfler 		// send error message
142274c0424aSAxel Dörfler 		sErrorMessage.AddInt32("error", status);
14234bef3723SAxel Dörfler 		sErrorMessage.SetDeliveryInfo(gProgramArgs->error_token,
14244bef3723SAxel Dörfler 			-1, 0, find_thread(NULL));
14254bef3723SAxel Dörfler 
14264bef3723SAxel Dörfler 		_kern_write_port_etc(gProgramArgs->error_port, 'KMSG',
14274bef3723SAxel Dörfler 			sErrorMessage.Buffer(), sErrorMessage.ContentSize(), 0, 0);
142874c0424aSAxel Dörfler 	}
142974c0424aSAxel Dörfler 	_kern_loading_app_failed(status);
14300c0fea5dSIngo Weinhold 	rld_unlock();
143174c0424aSAxel Dörfler 
14320c0fea5dSIngo Weinhold 	return status;
14330c0fea5dSIngo Weinhold }
14340c0fea5dSIngo Weinhold 
14350c0fea5dSIngo Weinhold 
14360c0fea5dSIngo Weinhold image_id
14370c0fea5dSIngo Weinhold load_library(char const *path, uint32 flags, bool addOn)
14380c0fea5dSIngo Weinhold {
14390c0fea5dSIngo Weinhold 	image_t *image = NULL;
14400c0fea5dSIngo Weinhold 	image_t *iter;
14410c0fea5dSIngo Weinhold 	image_type type = (addOn ? B_ADD_ON_IMAGE : B_LIBRARY_IMAGE);
14420c0fea5dSIngo Weinhold 	status_t status;
14430c0fea5dSIngo Weinhold 
14440c0fea5dSIngo Weinhold 	if (path == NULL)
14450c0fea5dSIngo Weinhold 		return B_BAD_VALUE;
14460c0fea5dSIngo Weinhold 
14470c0fea5dSIngo Weinhold 	// ToDo: implement flags
14480c0fea5dSIngo Weinhold 	(void)flags;
14490c0fea5dSIngo Weinhold 
1450*7486b72dSIngo Weinhold 	KTRACE("rld: load_library(\"%s\", 0x%lx, %d)", path, flags, addOn);
1451*7486b72dSIngo Weinhold 
14520c0fea5dSIngo Weinhold 	rld_lock();
14530c0fea5dSIngo Weinhold 		// for now, just do stupid simple global locking
14540c0fea5dSIngo Weinhold 
14550c0fea5dSIngo Weinhold 	// have we already loaded this library?
14560c0fea5dSIngo Weinhold 	// Checking it at this stage saves loading its dependencies again
14570c0fea5dSIngo Weinhold 	if (!addOn) {
14580c0fea5dSIngo Weinhold 		image = find_image(path, APP_OR_LIBRARY_TYPE);
14590c0fea5dSIngo Weinhold 		if (image) {
14600c0fea5dSIngo Weinhold 			atomic_add(&image->ref_count, 1);
14610c0fea5dSIngo Weinhold 			rld_unlock();
1462*7486b72dSIngo Weinhold 			KTRACE("rld: load_library(\"%s\"): already loaded: %ld", path,
1463*7486b72dSIngo Weinhold 				image->id);
14640c0fea5dSIngo Weinhold 			return image->id;
14650c0fea5dSIngo Weinhold 		}
14660c0fea5dSIngo Weinhold 	}
14670c0fea5dSIngo Weinhold 
14680c0fea5dSIngo Weinhold 	status = load_container(path, type, NULL, &image);
14690c0fea5dSIngo Weinhold 	if (status < B_OK) {
14700c0fea5dSIngo Weinhold 		rld_unlock();
1471*7486b72dSIngo Weinhold 		KTRACE("rld: load_library(\"%s\") failed to load container: %s", path,
1472*7486b72dSIngo Weinhold 			strerror(status));
14730c0fea5dSIngo Weinhold 		return status;
14740c0fea5dSIngo Weinhold 	}
14750c0fea5dSIngo Weinhold 
14760c0fea5dSIngo Weinhold 	for (iter = sLoadedImages.head; iter; iter = iter->next) {
14770c0fea5dSIngo Weinhold 		status = load_dependencies(iter);
14780c0fea5dSIngo Weinhold 		if (status < B_OK)
14790c0fea5dSIngo Weinhold 			goto err;
14800c0fea5dSIngo Weinhold 	}
14810c0fea5dSIngo Weinhold 
14820c0fea5dSIngo Weinhold 	status = relocate_dependencies(image);
14830c0fea5dSIngo Weinhold 	if (status < B_OK)
14840c0fea5dSIngo Weinhold 		goto err;
14850c0fea5dSIngo Weinhold 
14860c0fea5dSIngo Weinhold 	remap_images();
14870c0fea5dSIngo Weinhold 	init_dependencies(image, true);
14880c0fea5dSIngo Weinhold 
14890c0fea5dSIngo Weinhold 	rld_unlock();
1490*7486b72dSIngo Weinhold 
1491*7486b72dSIngo Weinhold 	KTRACE("rld: load_library(\"%s\") done: id: %ld", path, image->id);
1492*7486b72dSIngo Weinhold 
14930c0fea5dSIngo Weinhold 	return image->id;
14940c0fea5dSIngo Weinhold 
14950c0fea5dSIngo Weinhold err:
1496*7486b72dSIngo Weinhold 	KTRACE("rld: load_library(\"%s\") failed: %s", path, strerror(status));
1497*7486b72dSIngo Weinhold 
14980c0fea5dSIngo Weinhold 	dequeue_image(&sLoadedImages, image);
14990c0fea5dSIngo Weinhold 	sLoadedImageCount--;
15000c0fea5dSIngo Weinhold 	delete_image(image);
15010c0fea5dSIngo Weinhold 	rld_unlock();
15020c0fea5dSIngo Weinhold 	return status;
15030c0fea5dSIngo Weinhold }
15040c0fea5dSIngo Weinhold 
15050c0fea5dSIngo Weinhold 
15060c0fea5dSIngo Weinhold status_t
15070c0fea5dSIngo Weinhold unload_library(image_id imageID, bool addOn)
15080c0fea5dSIngo Weinhold {
15090c0fea5dSIngo Weinhold 	status_t status = B_BAD_IMAGE_ID;
15100c0fea5dSIngo Weinhold 	image_t *image;
15110c0fea5dSIngo Weinhold 	image_type type = addOn ? B_ADD_ON_IMAGE : B_LIBRARY_IMAGE;
15120c0fea5dSIngo Weinhold 
15130c0fea5dSIngo Weinhold 	if (imageID < B_OK)
15140c0fea5dSIngo Weinhold 		return B_BAD_IMAGE_ID;
15150c0fea5dSIngo Weinhold 
15160c0fea5dSIngo Weinhold 	rld_lock();
15170c0fea5dSIngo Weinhold 		// for now, just do stupid simple global locking
15180c0fea5dSIngo Weinhold 
15190c0fea5dSIngo Weinhold 	// we only check images that have been already initialized
15200c0fea5dSIngo Weinhold 
15210c0fea5dSIngo Weinhold 	for (image = sLoadedImages.head; image; image = image->next) {
15220c0fea5dSIngo Weinhold 		if (image->id == imageID) {
15230c0fea5dSIngo Weinhold 			// unload image
15240c0fea5dSIngo Weinhold 			if (type == image->type) {
15250c0fea5dSIngo Weinhold 				put_image(image);
15260c0fea5dSIngo Weinhold 				status = B_OK;
15270c0fea5dSIngo Weinhold 			} else
15280c0fea5dSIngo Weinhold 				status = B_BAD_VALUE;
15290c0fea5dSIngo Weinhold 			break;
15300c0fea5dSIngo Weinhold 		}
15310c0fea5dSIngo Weinhold 	}
15320c0fea5dSIngo Weinhold 
15330c0fea5dSIngo Weinhold 	if (status == B_OK) {
15340c0fea5dSIngo Weinhold 		while ((image = sDisposableImages.head) != NULL) {
15350c0fea5dSIngo Weinhold 			// call image fini here...
15368c2a9d74SMichael Lotz 			if (gRuntimeLoader.call_atexit_hooks_for_range) {
15378c2a9d74SMichael Lotz 				gRuntimeLoader.call_atexit_hooks_for_range(
15383be509a2SMichael Lotz 					image->regions[0].vmstart, image->regions[0].vmsize);
15398c2a9d74SMichael Lotz 			}
15408c2a9d74SMichael Lotz 
15410c0fea5dSIngo Weinhold 			if (image->term_routine)
15420c0fea5dSIngo Weinhold 				((init_term_function)image->term_routine)(image->id);
15430c0fea5dSIngo Weinhold 
15440c0fea5dSIngo Weinhold 			dequeue_image(&sDisposableImages, image);
15450c0fea5dSIngo Weinhold 			unmap_image(image);
15460c0fea5dSIngo Weinhold 
15470c0fea5dSIngo Weinhold 			delete_image(image);
15480c0fea5dSIngo Weinhold 		}
15490c0fea5dSIngo Weinhold 	}
15500c0fea5dSIngo Weinhold 
15510c0fea5dSIngo Weinhold 	rld_unlock();
15520c0fea5dSIngo Weinhold 	return status;
15530c0fea5dSIngo Weinhold }
15540c0fea5dSIngo Weinhold 
15550c0fea5dSIngo Weinhold 
15560c0fea5dSIngo Weinhold status_t
15570c0fea5dSIngo Weinhold get_nth_symbol(image_id imageID, int32 num, char *nameBuffer, int32 *_nameLength,
15580c0fea5dSIngo Weinhold 	int32 *_type, void **_location)
15590c0fea5dSIngo Weinhold {
15600c0fea5dSIngo Weinhold 	int32 count = 0, j;
15610c0fea5dSIngo Weinhold 	uint32 i;
15620c0fea5dSIngo Weinhold 	image_t *image;
15630c0fea5dSIngo Weinhold 
15640c0fea5dSIngo Weinhold 	rld_lock();
15650c0fea5dSIngo Weinhold 
15660c0fea5dSIngo Weinhold 	// get the image from those who have been already initialized
15670c0fea5dSIngo Weinhold 	image = find_loaded_image_by_id(imageID);
15680c0fea5dSIngo Weinhold 	if (image == NULL) {
15690c0fea5dSIngo Weinhold 		rld_unlock();
15700c0fea5dSIngo Weinhold 		return B_BAD_IMAGE_ID;
15710c0fea5dSIngo Weinhold 	}
15720c0fea5dSIngo Weinhold 
15730c0fea5dSIngo Weinhold 	// iterate through all the hash buckets until we've found the one
15740c0fea5dSIngo Weinhold 	for (i = 0; i < HASHTABSIZE(image); i++) {
15750c0fea5dSIngo Weinhold 		for (j = HASHBUCKETS(image)[i]; j != STN_UNDEF; j = HASHCHAINS(image)[j]) {
15760c0fea5dSIngo Weinhold 			struct Elf32_Sym *symbol = &image->syms[i];
15770c0fea5dSIngo Weinhold 
15780c0fea5dSIngo Weinhold 			if (count == num) {
15790c0fea5dSIngo Weinhold 				strlcpy(nameBuffer, SYMNAME(image, symbol), *_nameLength);
15800c0fea5dSIngo Weinhold 				*_nameLength = strlen(SYMNAME(image, symbol));
15810c0fea5dSIngo Weinhold 
15820c0fea5dSIngo Weinhold 				if (_type != NULL) {
15830c0fea5dSIngo Weinhold 					// ToDo: check with the return types of that BeOS function
15840c0fea5dSIngo Weinhold 					if (ELF32_ST_TYPE(symbol->st_info) == STT_FUNC)
15850c0fea5dSIngo Weinhold 						*_type = B_SYMBOL_TYPE_TEXT;
15860c0fea5dSIngo Weinhold 					else if (ELF32_ST_TYPE(symbol->st_info) == STT_OBJECT)
15870c0fea5dSIngo Weinhold 						*_type = B_SYMBOL_TYPE_DATA;
15880c0fea5dSIngo Weinhold 					else
15890c0fea5dSIngo Weinhold 						*_type = B_SYMBOL_TYPE_ANY;
15900c0fea5dSIngo Weinhold 				}
15910c0fea5dSIngo Weinhold 
15920c0fea5dSIngo Weinhold 				if (_location != NULL)
15930c0fea5dSIngo Weinhold 					*_location = (void *)(symbol->st_value + image->regions[0].delta);
15940c0fea5dSIngo Weinhold 				goto out;
15950c0fea5dSIngo Weinhold 			}
15960c0fea5dSIngo Weinhold 			count++;
15970c0fea5dSIngo Weinhold 		}
15980c0fea5dSIngo Weinhold 	}
15990c0fea5dSIngo Weinhold out:
16000c0fea5dSIngo Weinhold 	rld_unlock();
16010c0fea5dSIngo Weinhold 
16020c0fea5dSIngo Weinhold 	if (num != count)
16030c0fea5dSIngo Weinhold 		return B_BAD_INDEX;
16040c0fea5dSIngo Weinhold 
16050c0fea5dSIngo Weinhold 	return B_OK;
16060c0fea5dSIngo Weinhold }
16070c0fea5dSIngo Weinhold 
16080c0fea5dSIngo Weinhold 
16090c0fea5dSIngo Weinhold status_t
16100c0fea5dSIngo Weinhold get_symbol(image_id imageID, char const *symbolName, int32 symbolType, void **_location)
16110c0fea5dSIngo Weinhold {
16120c0fea5dSIngo Weinhold 	status_t status = B_OK;
16130c0fea5dSIngo Weinhold 	image_t *image;
16140c0fea5dSIngo Weinhold 
16150c0fea5dSIngo Weinhold 	if (imageID < B_OK)
16160c0fea5dSIngo Weinhold 		return B_BAD_IMAGE_ID;
16170c0fea5dSIngo Weinhold 	if (symbolName == NULL)
16180c0fea5dSIngo Weinhold 		return B_BAD_VALUE;
16190c0fea5dSIngo Weinhold 
16200c0fea5dSIngo Weinhold 	rld_lock();
16210c0fea5dSIngo Weinhold 		// for now, just do stupid simple global locking
16220c0fea5dSIngo Weinhold 
16230c0fea5dSIngo Weinhold 	// get the image from those who have been already initialized
16240c0fea5dSIngo Weinhold 	image = find_loaded_image_by_id(imageID);
16250c0fea5dSIngo Weinhold 	if (image != NULL) {
16260c0fea5dSIngo Weinhold 		struct Elf32_Sym *symbol;
16270c0fea5dSIngo Weinhold 
16280c0fea5dSIngo Weinhold 		// get the symbol in the image
16290c0fea5dSIngo Weinhold 		symbol = find_symbol(image, symbolName, symbolType);
16300c0fea5dSIngo Weinhold 		if (symbol) {
16310c0fea5dSIngo Weinhold 			if (_location != NULL)
16320c0fea5dSIngo Weinhold 				*_location = (void *)(symbol->st_value + image->regions[0].delta);
16330c0fea5dSIngo Weinhold 		} else
16340c0fea5dSIngo Weinhold 			status = B_ENTRY_NOT_FOUND;
16350c0fea5dSIngo Weinhold 	} else
16360c0fea5dSIngo Weinhold 		status = B_BAD_IMAGE_ID;
16370c0fea5dSIngo Weinhold 
16380c0fea5dSIngo Weinhold 	rld_unlock();
16390c0fea5dSIngo Weinhold 	return status;
16400c0fea5dSIngo Weinhold }
16410c0fea5dSIngo Weinhold 
16420c0fea5dSIngo Weinhold 
16430c0fea5dSIngo Weinhold status_t
16440c0fea5dSIngo Weinhold get_next_image_dependency(image_id id, uint32 *cookie, const char **_name)
16450c0fea5dSIngo Weinhold {
16460c0fea5dSIngo Weinhold 	uint32 i, j, searchIndex = *cookie;
16470c0fea5dSIngo Weinhold 	struct Elf32_Dyn *dynamicSection;
16480c0fea5dSIngo Weinhold 	image_t *image;
16490c0fea5dSIngo Weinhold 
16500c0fea5dSIngo Weinhold 	if (_name == NULL)
16510c0fea5dSIngo Weinhold 		return B_BAD_VALUE;
16520c0fea5dSIngo Weinhold 
16530c0fea5dSIngo Weinhold 	rld_lock();
16540c0fea5dSIngo Weinhold 
16550c0fea5dSIngo Weinhold 	image = find_loaded_image_by_id(id);
16560c0fea5dSIngo Weinhold 	if (image == NULL) {
16570c0fea5dSIngo Weinhold 		rld_unlock();
16580c0fea5dSIngo Weinhold 		return B_BAD_IMAGE_ID;
16590c0fea5dSIngo Weinhold 	}
16600c0fea5dSIngo Weinhold 
16610c0fea5dSIngo Weinhold 	dynamicSection = (struct Elf32_Dyn *)image->dynamic_ptr;
16620c0fea5dSIngo Weinhold 	if (dynamicSection == NULL || image->num_needed <= searchIndex) {
16630c0fea5dSIngo Weinhold 		rld_unlock();
16640c0fea5dSIngo Weinhold 		return B_ENTRY_NOT_FOUND;
16650c0fea5dSIngo Weinhold 	}
16660c0fea5dSIngo Weinhold 
16670c0fea5dSIngo Weinhold 	for (i = 0, j = 0; dynamicSection[i].d_tag != DT_NULL; i++) {
16680c0fea5dSIngo Weinhold 		if (dynamicSection[i].d_tag != DT_NEEDED)
16690c0fea5dSIngo Weinhold 			continue;
16700c0fea5dSIngo Weinhold 
16710c0fea5dSIngo Weinhold 		if (j++ == searchIndex) {
16720c0fea5dSIngo Weinhold 			int32 neededOffset = dynamicSection[i].d_un.d_val;
16730c0fea5dSIngo Weinhold 
16740c0fea5dSIngo Weinhold 			*_name = STRING(image, neededOffset);
16750c0fea5dSIngo Weinhold 			*cookie = searchIndex + 1;
16760c0fea5dSIngo Weinhold 			rld_unlock();
16770c0fea5dSIngo Weinhold 			return B_OK;
16780c0fea5dSIngo Weinhold 		}
16790c0fea5dSIngo Weinhold 	}
16800c0fea5dSIngo Weinhold 
16810c0fea5dSIngo Weinhold 	rld_unlock();
16820c0fea5dSIngo Weinhold 	return B_ENTRY_NOT_FOUND;
16830c0fea5dSIngo Weinhold }
16840c0fea5dSIngo Weinhold 
16850c0fea5dSIngo Weinhold 
168674c0424aSAxel Dörfler //	#pragma mark - runtime_loader private exports
16870c0fea5dSIngo Weinhold 
16880c0fea5dSIngo Weinhold 
16890c0fea5dSIngo Weinhold /** Read and verify the ELF header */
16900c0fea5dSIngo Weinhold 
16910c0fea5dSIngo Weinhold status_t
16920c0fea5dSIngo Weinhold elf_verify_header(void *header, int32 length)
16930c0fea5dSIngo Weinhold {
16940c0fea5dSIngo Weinhold 	int32 programSize, sectionSize;
16950c0fea5dSIngo Weinhold 
16960c0fea5dSIngo Weinhold 	if (length < (int32)sizeof(struct Elf32_Ehdr))
16970c0fea5dSIngo Weinhold 		return B_NOT_AN_EXECUTABLE;
16980c0fea5dSIngo Weinhold 
16990c0fea5dSIngo Weinhold 	return parse_elf_header((struct Elf32_Ehdr *)header, &programSize, &sectionSize);
17000c0fea5dSIngo Weinhold }
17010c0fea5dSIngo Weinhold 
17020c0fea5dSIngo Weinhold 
17030c0fea5dSIngo Weinhold void
17040c0fea5dSIngo Weinhold terminate_program(void)
17050c0fea5dSIngo Weinhold {
17060c0fea5dSIngo Weinhold 	image_t **termList;
17070c0fea5dSIngo Weinhold 	ssize_t count, i;
17080c0fea5dSIngo Weinhold 
17090c0fea5dSIngo Weinhold 	count = get_sorted_image_list(sProgramImage, &termList, RFLAG_TERMINATED);
17100c0fea5dSIngo Weinhold 	if (count < B_OK)
17110c0fea5dSIngo Weinhold 		return;
17120c0fea5dSIngo Weinhold 
17130c0fea5dSIngo Weinhold 	TRACE(("%ld: terminate dependencies\n", find_thread(NULL)));
17140c0fea5dSIngo Weinhold 	for (i = count; i-- > 0;) {
17150c0fea5dSIngo Weinhold 		image_t *image = termList[i];
17160c0fea5dSIngo Weinhold 
17170c0fea5dSIngo Weinhold 		TRACE(("%ld:  term: %s\n", find_thread(NULL), image->name));
17180c0fea5dSIngo Weinhold 
17190c0fea5dSIngo Weinhold 		if (image->term_routine)
17200c0fea5dSIngo Weinhold 			((init_term_function)image->term_routine)(image->id);
17210c0fea5dSIngo Weinhold 	}
17220c0fea5dSIngo Weinhold 	TRACE(("%ld:  term done.\n", find_thread(NULL)));
17230c0fea5dSIngo Weinhold 
17240c0fea5dSIngo Weinhold 	free(termList);
17250c0fea5dSIngo Weinhold }
17260c0fea5dSIngo Weinhold 
17270c0fea5dSIngo Weinhold 
17280c0fea5dSIngo Weinhold void
17290c0fea5dSIngo Weinhold rldelf_init(void)
17300c0fea5dSIngo Weinhold {
17310c0fea5dSIngo Weinhold 	rld_sem = create_sem(1, "rld_lock");
17320c0fea5dSIngo Weinhold 	rld_sem_owner = -1;
17330c0fea5dSIngo Weinhold 	rld_sem_count = 0;
17340c0fea5dSIngo Weinhold 
17350c0fea5dSIngo Weinhold 	// create the debug area
17360c0fea5dSIngo Weinhold 	{
17370c0fea5dSIngo Weinhold 		int32 size = TO_PAGE_SIZE(sizeof(runtime_loader_debug_area));
17380c0fea5dSIngo Weinhold 
17390c0fea5dSIngo Weinhold 		runtime_loader_debug_area *area;
17400c0fea5dSIngo Weinhold 		area_id areaID = _kern_create_area(RUNTIME_LOADER_DEBUG_AREA_NAME,
17410c0fea5dSIngo Weinhold 			(void **)&area, B_ANY_ADDRESS, size, B_NO_LOCK,
17420c0fea5dSIngo Weinhold 			B_READ_AREA | B_WRITE_AREA);
17430c0fea5dSIngo Weinhold 		if (areaID < B_OK) {
17440c0fea5dSIngo Weinhold 			FATAL("Failed to create debug area.\n");
17450c0fea5dSIngo Weinhold 			_kern_loading_app_failed(areaID);
17460c0fea5dSIngo Weinhold 		}
17470c0fea5dSIngo Weinhold 
17480c0fea5dSIngo Weinhold 		area->loaded_images = &sLoadedImages;
17490c0fea5dSIngo Weinhold 	}
175074c0424aSAxel Dörfler 
175174c0424aSAxel Dörfler 	// initialize error message if needed
17524bef3723SAxel Dörfler 	if (report_errors()) {
175374c0424aSAxel Dörfler 		void *buffer = malloc(1024);
175474c0424aSAxel Dörfler 		if (buffer == NULL)
175574c0424aSAxel Dörfler 			return;
175674c0424aSAxel Dörfler 
175774c0424aSAxel Dörfler 		sErrorMessage.SetTo(buffer, 1024, 'Rler');
175874c0424aSAxel Dörfler 	}
17590c0fea5dSIngo Weinhold }
17601873b4b3SIngo Weinhold 
17611873b4b3SIngo Weinhold 
17621873b4b3SIngo Weinhold status_t
17631873b4b3SIngo Weinhold elf_reinit_after_fork()
17641873b4b3SIngo Weinhold {
17651873b4b3SIngo Weinhold 	rld_sem = create_sem(1, "rld_lock");
17661873b4b3SIngo Weinhold 	if (rld_sem < 0)
17671873b4b3SIngo Weinhold 		return rld_sem;
17681873b4b3SIngo Weinhold 
17691873b4b3SIngo Weinhold 	return B_OK;
17701873b4b3SIngo Weinhold }
1771