xref: /haiku/src/system/runtime_loader/elf.cpp (revision 56eb8e78cc702792e3b032e3f5f45da9e5dbea9e)
1 /*
2  * Copyright 2003-2007, 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  * Copyright 2001, Travis Geiselbrecht. All rights reserved.
7  * Distributed under the terms of the NewOS License.
8  */
9 
10 
11 #include "runtime_loader_private.h"
12 #include "vm.h"
13 
14 #include <OS.h>
15 
16 #include <elf32.h>
17 #include <user_runtime.h>
18 #include <syscalls.h>
19 #include <vm_types.h>
20 #include <arch/cpu.h>
21 #include <sem.h>
22 #include <runtime_loader.h>
23 
24 #include <string.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 
28 
29 //#define TRACE_RLD
30 #ifdef TRACE_RLD
31 #	define TRACE(x) dprintf x
32 #else
33 #	define TRACE(x) ;
34 #endif
35 
36 
37 // ToDo: implement better locking strategy
38 // ToDo: implement lazy binding
39 
40 #define	PAGE_MASK (B_PAGE_SIZE - 1)
41 
42 #define	PAGE_OFFSET(x) ((x) & (PAGE_MASK))
43 #define	PAGE_BASE(x) ((x) & ~(PAGE_MASK))
44 #define TO_PAGE_SIZE(x) ((x + (PAGE_MASK)) & ~(PAGE_MASK))
45 
46 #define RLD_PROGRAM_BASE 0x00200000
47 	/* keep in sync with app ldscript */
48 
49 enum {
50 	RFLAG_RW					= 0x0001,
51 	RFLAG_ANON					= 0x0002,
52 
53 	RFLAG_TERMINATED			= 0x0200,
54 	RFLAG_INITIALIZED			= 0x0400,
55 	RFLAG_SYMBOLIC				= 0x0800,
56 	RFLAG_RELOCATED				= 0x1000,
57 	RFLAG_PROTECTED				= 0x2000,
58 	RFLAG_DEPENDENCIES_LOADED	= 0x4000,
59 	RFLAG_REMAPPED				= 0x8000,
60 
61 	RFLAG_VISITED				= 0x10000
62 		// temporarily set in the symbol resolution code
63 };
64 
65 
66 #define IMAGE_TYPE_TO_MASK(type)	(1 << ((type) - 1))
67 #define ALL_IMAGE_TYPES				(IMAGE_TYPE_TO_MASK(B_APP_IMAGE) \
68 									| IMAGE_TYPE_TO_MASK(B_LIBRARY_IMAGE) \
69 									| IMAGE_TYPE_TO_MASK(B_ADD_ON_IMAGE) \
70 									| IMAGE_TYPE_TO_MASK(B_SYSTEM_IMAGE))
71 #define APP_OR_LIBRARY_TYPE			(IMAGE_TYPE_TO_MASK(B_APP_IMAGE) \
72 									| IMAGE_TYPE_TO_MASK(B_LIBRARY_IMAGE))
73 
74 typedef void (*init_term_function)(image_id);
75 
76 static image_queue_t sLoadedImages = {0, 0};
77 static image_queue_t sDisposableImages = {0, 0};
78 static uint32 sLoadedImageCount = 0;
79 static image_t *sProgramImage;
80 static KMessage sErrorMessage;
81 
82 #ifdef BEOS_STYLE_SYMBOLS_RESOLUTION
83 static bool sResolveSymbolsBeOSStyle = true;
84 #else
85 static bool sResolveSymbolsBeOSStyle = false;
86 #endif
87 
88 // a recursive lock
89 static sem_id rld_sem;
90 static thread_id rld_sem_owner;
91 static int32 rld_sem_count;
92 
93 
94 #ifdef TRACE_RLD
95 #	define FATAL(x...) dprintf("runtime_loader: " x);
96 
97 void
98 dprintf(const char *format, ...)
99 {
100 	char buffer[1024];
101 
102 	va_list list;
103 	va_start(list, format);
104 
105 	vsnprintf(buffer, sizeof(buffer), format, list);
106 	_kern_debug_output(buffer);
107 
108 	va_end(list);
109 }
110 #else
111 #	define FATAL(x...) printf("runtime_loader: " x);
112 #endif
113 
114 
115 static void
116 rld_unlock()
117 {
118 	if (rld_sem_count-- == 1) {
119 		rld_sem_owner = -1;
120 		release_sem(rld_sem);
121 	}
122 }
123 
124 
125 static void
126 rld_lock()
127 {
128 	thread_id self = find_thread(NULL);
129 	if (self != rld_sem_owner) {
130 		acquire_sem(rld_sem);
131 		rld_sem_owner = self;
132 	}
133 	rld_sem_count++;
134 }
135 
136 
137 static void
138 enqueue_image(image_queue_t *queue, image_t *image)
139 {
140 	image->next = 0;
141 
142 	image->prev = queue->tail;
143 	if (queue->tail)
144 		queue->tail->next = image;
145 
146 	queue->tail = image;
147 	if (!queue->head)
148 		queue->head = image;
149 }
150 
151 
152 static void
153 dequeue_image(image_queue_t *queue, image_t *image)
154 {
155 	if (image->next)
156 		image->next->prev = image->prev;
157 	else
158 		queue->tail = image->prev;
159 
160 	if (image->prev)
161 		image->prev->next = image->next;
162 	else
163 		queue->head = image->next;
164 
165 	image->prev = 0;
166 	image->next = 0;
167 }
168 
169 
170 static uint32
171 elf_hash(const uint8 *name)
172 {
173 	uint32 hash = 0;
174 	uint32 temp;
175 
176 	while (*name) {
177 		hash = (hash << 4) + *name++;
178 		if ((temp = hash & 0xf0000000)) {
179 			hash ^= temp >> 24;
180 		}
181 		hash &= ~temp;
182 	}
183 	return hash;
184 }
185 
186 
187 static inline bool
188 report_errors()
189 {
190 	return gProgramArgs->error_port >= 0;
191 }
192 
193 
194 static image_t *
195 find_image_in_queue(image_queue_t *queue, const char *name, bool isPath,
196 	uint32 typeMask)
197 {
198 	image_t *image;
199 
200 	for (image = queue->head; image; image = image->next) {
201 		const char *imageName = isPath ? image->path : image->name;
202 		int length = isPath ? sizeof(image->path) : sizeof(image->name);
203 
204 		if (!strncmp(imageName, name, length)
205 			&& (typeMask & IMAGE_TYPE_TO_MASK(image->type)) != 0) {
206 			return image;
207 		}
208 	}
209 
210 	return NULL;
211 }
212 
213 
214 static image_t *
215 find_image(char const *name, uint32 typeMask)
216 {
217 	bool isPath = (strchr(name, '/') != NULL);
218 	return find_image_in_queue(&sLoadedImages, name, isPath, typeMask);
219 }
220 
221 
222 static image_t *
223 find_loaded_image_by_id(image_id id)
224 {
225 	image_t *image;
226 
227 	for (image = sLoadedImages.head; image; image = image->next) {
228 		if (image->id == id)
229 			return image;
230 	}
231 
232 	// For the termination routine, we need to look into the list of
233 	// disposable images as well
234 	for (image = sDisposableImages.head; image; image = image->next) {
235 		if (image->id == id)
236 			return image;
237 	}
238 
239 	return NULL;
240 }
241 
242 
243 static status_t
244 parse_elf_header(struct Elf32_Ehdr *eheader, int32 *_pheaderSize, int32 *_sheaderSize)
245 {
246 	if (memcmp(eheader->e_ident, ELF_MAGIC, 4) != 0)
247 		return B_NOT_AN_EXECUTABLE;
248 
249 	if (eheader->e_ident[4] != ELFCLASS32)
250 		return B_NOT_AN_EXECUTABLE;
251 
252 	if (eheader->e_phoff == 0)
253 		return B_NOT_AN_EXECUTABLE;
254 
255 	if (eheader->e_phentsize < sizeof(struct Elf32_Phdr))
256 		return B_NOT_AN_EXECUTABLE;
257 
258 	*_pheaderSize = eheader->e_phentsize * eheader->e_phnum;
259 	*_sheaderSize = eheader->e_shentsize * eheader->e_shnum;
260 
261 	if (*_pheaderSize <= 0 || *_sheaderSize <= 0)
262 		return B_NOT_AN_EXECUTABLE;
263 
264 	return B_OK;
265 }
266 
267 
268 static int32
269 count_regions(char const *buff, int phnum, int phentsize)
270 {
271 	struct Elf32_Phdr *pheaders;
272 	int32 count = 0;
273 	int i;
274 
275 	for (i = 0; i < phnum; i++) {
276 		pheaders = (struct Elf32_Phdr *)(buff + i * phentsize);
277 
278 		switch (pheaders->p_type) {
279 			case PT_NULL:
280 				/* NOP header */
281 				break;
282 			case PT_LOAD:
283 				count += 1;
284 				if (pheaders->p_memsz != pheaders->p_filesz) {
285 					addr_t A = TO_PAGE_SIZE(pheaders->p_vaddr + pheaders->p_memsz);
286 					addr_t B = TO_PAGE_SIZE(pheaders->p_vaddr + pheaders->p_filesz);
287 
288 					if (A != B)
289 						count += 1;
290 				}
291 				break;
292 			case PT_DYNAMIC:
293 				/* will be handled at some other place */
294 				break;
295 			case PT_INTERP:
296 				/* should check here for appropiate interpreter */
297 				break;
298 			case PT_NOTE:
299 				/* unsupported */
300 				break;
301 			case PT_SHLIB:
302 				/* undefined semantics */
303 				break;
304 			case PT_PHDR:
305 				/* we don't use it */
306 				break;
307 			default:
308 				FATAL("unhandled pheader type 0x%lx\n", pheaders[i].p_type);
309 				return B_BAD_DATA;
310 		}
311 	}
312 
313 	return count;
314 }
315 
316 
317 /*
318  * create_image() & destroy_image()
319  *
320  * 	Create and destroy image_t structures. The destroyer makes sure that the
321  * 	memory buffers are full of garbage before freeing.
322  */
323 
324 static image_t *
325 create_image(const char *name, const char *path, int num_regions)
326 {
327 	size_t allocSize = sizeof(image_t) + (num_regions - 1) * sizeof(elf_region_t);
328 	const char *lastSlash;
329 
330 	image_t *image = (image_t*)malloc(allocSize);
331 	if (image == NULL) {
332 		FATAL("no memory for image %s\n", path);
333 		return NULL;
334 	}
335 
336 	memset(image, 0, allocSize);
337 
338 	strlcpy(image->path, path, sizeof(image->path));
339 
340 	// Make the last component of the supplied name the image name.
341 	// If present, DT_SONAME will replace this name.
342 	if ((lastSlash = strrchr(name, '/')))
343 		strlcpy(image->name, lastSlash + 1, sizeof(image->name));
344 	else
345 		strlcpy(image->name, name, sizeof(image->name));
346 
347 	image->ref_count = 1;
348 	image->num_regions = num_regions;
349 
350 	return image;
351 }
352 
353 
354 static void
355 delete_image_struct(image_t *image)
356 {
357 #ifdef DEBUG
358 	size_t size = sizeof(image_t) + (image->num_regions - 1) * sizeof(elf_region_t);
359 	memset(image->needed, 0xa5, sizeof(image->needed[0]) * image->num_needed);
360 #endif
361 	free(image->needed);
362 
363 #ifdef DEBUG
364 	memset(image, 0xa5, size);
365 #endif
366 	free(image);
367 }
368 
369 
370 static void
371 delete_image(image_t *image)
372 {
373 	if (image == NULL)
374 		return;
375 
376 	_kern_unregister_image(image->id);
377 		// registered in load_container()
378 
379 	delete_image_struct(image);
380 }
381 
382 
383 static status_t
384 parse_program_headers(image_t *image, char *buff, int phnum, int phentsize)
385 {
386 	struct Elf32_Phdr *pheader;
387 	int regcount;
388 	int i;
389 
390 	regcount = 0;
391 	for (i = 0; i < phnum; i++) {
392 		pheader = (struct Elf32_Phdr *)(buff + i * phentsize);
393 
394 		switch (pheader->p_type) {
395 			case PT_NULL:
396 				/* NOP header */
397 				break;
398 			case PT_LOAD:
399 				if (pheader->p_memsz == pheader->p_filesz) {
400 					/*
401 					 * everything in one area
402 					 */
403 					image->regions[regcount].start = pheader->p_vaddr;
404 					image->regions[regcount].size = pheader->p_memsz;
405 					image->regions[regcount].vmstart = PAGE_BASE(pheader->p_vaddr);
406 					image->regions[regcount].vmsize = TO_PAGE_SIZE(pheader->p_memsz
407 						+ PAGE_OFFSET(pheader->p_vaddr));
408 					image->regions[regcount].fdstart = pheader->p_offset;
409 					image->regions[regcount].fdsize = pheader->p_filesz;
410 					image->regions[regcount].delta = 0;
411 					image->regions[regcount].flags = 0;
412 					if (pheader->p_flags & PF_WRITE) {
413 						// this is a writable segment
414 						image->regions[regcount].flags |= RFLAG_RW;
415 					}
416 				} else {
417 					/*
418 					 * may require splitting
419 					 */
420 					addr_t A = TO_PAGE_SIZE(pheader->p_vaddr + pheader->p_memsz);
421 					addr_t B = TO_PAGE_SIZE(pheader->p_vaddr + pheader->p_filesz);
422 
423 					image->regions[regcount].start = pheader->p_vaddr;
424 					image->regions[regcount].size = pheader->p_filesz;
425 					image->regions[regcount].vmstart = PAGE_BASE(pheader->p_vaddr);
426 					image->regions[regcount].vmsize = TO_PAGE_SIZE(pheader->p_filesz
427 						+ PAGE_OFFSET(pheader->p_vaddr));
428 					image->regions[regcount].fdstart = pheader->p_offset;
429 					image->regions[regcount].fdsize = pheader->p_filesz;
430 					image->regions[regcount].delta = 0;
431 					image->regions[regcount].flags = 0;
432 					if (pheader->p_flags & PF_WRITE) {
433 						// this is a writable segment
434 						image->regions[regcount].flags |= RFLAG_RW;
435 					}
436 
437 					if (A != B) {
438 						/*
439 						 * yeah, it requires splitting
440 						 */
441 						regcount += 1;
442 						image->regions[regcount].start = pheader->p_vaddr;
443 						image->regions[regcount].size = pheader->p_memsz - pheader->p_filesz;
444 						image->regions[regcount].vmstart = image->regions[regcount-1].vmstart + image->regions[regcount-1].vmsize;
445 						image->regions[regcount].vmsize = TO_PAGE_SIZE(pheader->p_memsz + PAGE_OFFSET(pheader->p_vaddr))
446 							- image->regions[regcount-1].vmsize;
447 						image->regions[regcount].fdstart = 0;
448 						image->regions[regcount].fdsize = 0;
449 						image->regions[regcount].delta = 0;
450 						image->regions[regcount].flags = RFLAG_ANON;
451 						if (pheader->p_flags & PF_WRITE) {
452 							// this is a writable segment
453 							image->regions[regcount].flags |= RFLAG_RW;
454 						}
455 					}
456 				}
457 				regcount += 1;
458 				break;
459 			case PT_DYNAMIC:
460 				image->dynamic_ptr = pheader->p_vaddr;
461 				break;
462 			case PT_INTERP:
463 				/* should check here for appropiate interpreter */
464 				break;
465 			case PT_NOTE:
466 				/* unsupported */
467 				break;
468 			case PT_SHLIB:
469 				/* undefined semantics */
470 				break;
471 			case PT_PHDR:
472 				/* we don't use it */
473 				break;
474 			default:
475 				FATAL("unhandled pheader type 0x%lx\n", pheader[i].p_type);
476 				return B_BAD_DATA;
477 		}
478 	}
479 
480 	return B_OK;
481 }
482 
483 
484 static bool
485 assert_dynamic_loadable(image_t *image)
486 {
487 	uint32 i;
488 
489 	if (!image->dynamic_ptr)
490 		return true;
491 
492 	for (i = 0; i < image->num_regions; i++) {
493 		if (image->dynamic_ptr >= image->regions[i].start
494 			&& image->dynamic_ptr < image->regions[i].start + image->regions[i].size)
495 			return true;
496 	}
497 
498 	return false;
499 }
500 
501 
502 /**	This function will change the protection of all read-only segments
503  *	to really be read-only.
504  *	The areas have to be read/write first, so that they can be relocated.
505  */
506 
507 static void
508 remap_images(void)
509 {
510 	image_t *image;
511 	uint32 i;
512 
513 	for (image = sLoadedImages.head; image != NULL; image = image->next) {
514 		for (i = 0; i < image->num_regions; i++) {
515 			if ((image->regions[i].flags & RFLAG_RW) == 0
516 				&& (image->regions[i].flags & RFLAG_REMAPPED) == 0) {
517 				// we only need to do this once, so we remember those we've already mapped
518 				if (_kern_set_area_protection(image->regions[i].id,
519 						B_READ_AREA | B_EXECUTE_AREA) == B_OK)
520 					image->regions[i].flags |= RFLAG_REMAPPED;
521 			}
522 		}
523 	}
524 }
525 
526 
527 static status_t
528 map_image(int fd, char const *path, image_t *image, bool fixed)
529 {
530 	status_t status = B_OK;
531 	const char *baseName;
532 	uint32 i;
533 
534 	(void)(fd);
535 
536 	// cut the file name from the path as base name for the created areas
537 	baseName = strrchr(path, '/');
538 	if (baseName != NULL)
539 		baseName++;
540 	else
541 		baseName = path;
542 
543 	for (i = 0; i < image->num_regions; i++) {
544 		char regionName[B_OS_NAME_LENGTH];
545 		addr_t loadAddress;
546 		uint32 addressSpecifier;
547 
548 		// for BeOS compatibility: if we load an old BeOS executable, we
549 		// have to relocate it, if possible - we recognize it because the
550 		// vmstart is set to 0 (hopefully always)
551 		if (fixed && image->regions[i].vmstart == 0)
552 			fixed = false;
553 
554 		snprintf(regionName, sizeof(regionName), "%s_seg%lu%s",
555 			baseName, i, (image->regions[i].flags & RFLAG_RW) ? "rw" : "ro");
556 
557 		if (image->dynamic_ptr && !fixed) {
558 			// relocatable image... we can afford to place wherever
559 			if (i == 0) {
560 				// but only the first segment gets a free ride
561 				loadAddress = RLD_PROGRAM_BASE;
562 				addressSpecifier = B_BASE_ADDRESS;
563 			} else {
564 				loadAddress = image->regions[i].vmstart + image->regions[i-1].delta;
565 				addressSpecifier = B_EXACT_ADDRESS;
566 			}
567 		} else {
568 			// not relocatable, put it where it asks or die trying
569 			loadAddress = image->regions[i].vmstart;
570 			addressSpecifier = B_EXACT_ADDRESS;
571 		}
572 
573 		if (image->regions[i].flags & RFLAG_ANON) {
574 			image->regions[i].id = _kern_create_area(regionName, (void **)&loadAddress,
575 				addressSpecifier, image->regions[i].vmsize, B_NO_LOCK,
576 				B_READ_AREA | B_WRITE_AREA);
577 
578 			if (image->regions[i].id < 0) {
579 				status = image->regions[i].id;
580 				goto error;
581 			}
582 
583 			image->regions[i].delta = loadAddress - image->regions[i].vmstart;
584 			image->regions[i].vmstart = loadAddress;
585 		} else {
586 			image->regions[i].id = sys_vm_map_file(regionName, (void **)&loadAddress,
587 				addressSpecifier, image->regions[i].vmsize, B_READ_AREA | B_WRITE_AREA,
588 				REGION_PRIVATE_MAP, path, PAGE_BASE(image->regions[i].fdstart));
589 
590 			if (image->regions[i].id < 0) {
591 				status = image->regions[i].id;
592 				goto error;
593 			}
594 
595 			TRACE(("\"%s\" at %p, 0x%lx bytes (%s)\n", path,
596 				(void *)loadAddress, image->regions[i].vmsize,
597 				image->regions[i].flags & RFLAG_RW ? "rw" : "read-only"));
598 
599 			image->regions[i].delta = loadAddress - image->regions[i].vmstart;
600 			image->regions[i].vmstart = loadAddress;
601 
602 			// handle trailer bits in data segment
603 			if (image->regions[i].flags & RFLAG_RW) {
604 				addr_t startClearing;
605 				addr_t toClear;
606 
607 				startClearing = image->regions[i].vmstart
608 					+ PAGE_OFFSET(image->regions[i].start)
609 					+ image->regions[i].size;
610 				toClear = image->regions[i].vmsize
611 					- PAGE_OFFSET(image->regions[i].start)
612 					- image->regions[i].size;
613 
614 				TRACE(("cleared 0x%lx and the following 0x%lx bytes\n", startClearing, toClear));
615 				memset((void *)startClearing, 0, toClear);
616 			}
617 		}
618 	}
619 
620 	if (image->dynamic_ptr)
621 		image->dynamic_ptr += image->regions[0].delta;
622 
623 	return B_OK;
624 
625 error:
626 	return status;
627 }
628 
629 
630 static void
631 unmap_image(image_t *image)
632 {
633 	uint32 i;
634 
635 	for (i = 0; i < image->num_regions; i++) {
636 		_kern_delete_area(image->regions[i].id);
637 
638 		image->regions[i].id = -1;
639 	}
640 }
641 
642 
643 static bool
644 parse_dynamic_segment(image_t *image)
645 {
646 	struct Elf32_Dyn *d;
647 	int i;
648 	int sonameOffset = -1;
649 
650 	image->symhash = 0;
651 	image->syms = 0;
652 	image->strtab = 0;
653 
654 	d = (struct Elf32_Dyn *)image->dynamic_ptr;
655 	if (!d)
656 		return true;
657 
658 	for (i = 0; d[i].d_tag != DT_NULL; i++) {
659 		switch (d[i].d_tag) {
660 			case DT_NEEDED:
661 				image->num_needed += 1;
662 				break;
663 			case DT_HASH:
664 				image->symhash = (uint32 *)(d[i].d_un.d_ptr + image->regions[0].delta);
665 				break;
666 			case DT_STRTAB:
667 				image->strtab = (char *)(d[i].d_un.d_ptr + image->regions[0].delta);
668 				break;
669 			case DT_SYMTAB:
670 				image->syms = (struct Elf32_Sym *)(d[i].d_un.d_ptr + image->regions[0].delta);
671 				break;
672 			case DT_REL:
673 				image->rel = (struct Elf32_Rel *)(d[i].d_un.d_ptr + image->regions[0].delta);
674 				break;
675 			case DT_RELSZ:
676 				image->rel_len = d[i].d_un.d_val;
677 				break;
678 			case DT_RELA:
679 				image->rela = (struct Elf32_Rela *)(d[i].d_un.d_ptr + image->regions[0].delta);
680 				break;
681 			case DT_RELASZ:
682 				image->rela_len = d[i].d_un.d_val;
683 				break;
684 			// TK: procedure linkage table
685 			case DT_JMPREL:
686 				image->pltrel = (struct Elf32_Rel *)(d[i].d_un.d_ptr + image->regions[0].delta);
687 				break;
688 			case DT_PLTRELSZ:
689 				image->pltrel_len = d[i].d_un.d_val;
690 				break;
691 			case DT_INIT:
692 				image->init_routine = (d[i].d_un.d_ptr + image->regions[0].delta);
693 				break;
694 			case DT_FINI:
695 				image->term_routine = (d[i].d_un.d_ptr + image->regions[0].delta);
696 				break;
697 			case DT_SONAME:
698 				sonameOffset = d[i].d_un.d_val;
699 				break;
700 			default:
701 				continue;
702 		}
703 	}
704 
705 	// lets make sure we found all the required sections
706 	if (!image->symhash || !image->syms || !image->strtab)
707 		return false;
708 
709 	if (sonameOffset >= 0)
710 		strlcpy(image->name, STRING(image, sonameOffset), sizeof(image->name));
711 
712 	return true;
713 }
714 
715 
716 static struct Elf32_Sym *
717 find_symbol(image_t *image, const char *name, int32 type)
718 {
719 	uint32 hash, i;
720 
721 	// ToDo: "type" is currently ignored!
722 	(void)type;
723 
724 	if (image->dynamic_ptr == NULL)
725 		return NULL;
726 
727 	hash = elf_hash((uint8 *)name) % HASHTABSIZE(image);
728 
729 	for (i = HASHBUCKETS(image)[hash]; i != STN_UNDEF; i = HASHCHAINS(image)[i]) {
730 		struct Elf32_Sym *symbol = &image->syms[i];
731 
732 		if (symbol->st_shndx != SHN_UNDEF
733 			&& ((ELF32_ST_BIND(symbol->st_info)== STB_GLOBAL)
734 				|| (ELF32_ST_BIND(symbol->st_info) == STB_WEAK))
735 			&& !strcmp(SYMNAME(image, symbol), name)) {
736 			// check if the type matches
737 			if ((type == B_SYMBOL_TYPE_TEXT && ELF32_ST_TYPE(symbol->st_info) != STT_FUNC)
738 				|| (type == B_SYMBOL_TYPE_DATA && ELF32_ST_TYPE(symbol->st_info) != STT_OBJECT))
739 				continue;
740 
741 			return symbol;
742 		}
743 	}
744 
745 	return NULL;
746 }
747 
748 
749 static struct Elf32_Sym*
750 find_symbol_recursively_impl(image_t* image, const char* name,
751 	image_t** foundInImage)
752 {
753 	image->flags |= RFLAG_VISITED;
754 
755 	struct Elf32_Sym *symbol;
756 
757 	// look up the symbol in this image
758 	if (image->dynamic_ptr) {
759 		symbol = find_symbol(image, name, B_SYMBOL_TYPE_ANY);
760 		if (symbol) {
761 			*foundInImage = image;
762 			return symbol;
763 		}
764 	}
765 
766 	// recursively search dependencies
767 	for (uint32 i = 0; i < image->num_needed; i++) {
768 		if (!(image->needed[i]->flags & RFLAG_VISITED)) {
769 			symbol = find_symbol_recursively_impl(image->needed[i], name,
770 				foundInImage);
771 			if (symbol)
772 				return symbol;
773 		}
774 	}
775 
776 	return NULL;
777 }
778 
779 
780 static void
781 clear_image_flag_recursively(image_t* image, uint32 flag)
782 {
783 	image->flags &= ~flag;
784 
785 	for (uint32 i = 0; i < image->num_needed; i++) {
786 		if (image->needed[i]->flags & flag)
787 			clear_image_flag_recursively(image->needed[i], flag);
788 	}
789 }
790 
791 
792 static struct Elf32_Sym*
793 find_symbol_recursively(image_t* image, const char* name,
794 	image_t** foundInImage)
795 {
796 	struct Elf32_Sym* symbol = find_symbol_recursively_impl(image, name,
797 		foundInImage);
798 	clear_image_flag_recursively(image, RFLAG_VISITED);
799 	return symbol;
800 }
801 
802 
803 static struct Elf32_Sym*
804 find_symbol_in_loaded_images(const char* name, image_t** foundInImage)
805 {
806 	return find_symbol_recursively(sLoadedImages.head, name, foundInImage);
807 }
808 
809 
810 static struct Elf32_Sym*
811 find_undefined_symbol(image_t* rootImage, image_t* image, const char* name,
812 	image_t** foundInImage)
813 {
814 	// If not simulating BeOS style symbol resolution, undefined symbols are
815 	// search recursively starting from the root image. (Note, breadth first
816 	// might be better than the depth first use here.)
817 	if (!sResolveSymbolsBeOSStyle)
818 		return find_symbol_recursively(rootImage, name, foundInImage);
819 
820 	// BeOS style symbol resolution: It is sufficient to check the direct
821 	// dependencies. The linker would have complained, if the symbol wasn't
822 	// there.
823 	for (uint32 i = 0; i < image->num_needed; i++) {
824 		if (image->needed[i]->dynamic_ptr) {
825 			struct Elf32_Sym *symbol = find_symbol(image->needed[i], name,
826 				B_SYMBOL_TYPE_ANY);
827 			if (symbol) {
828 				*foundInImage = image->needed[i];
829 				return symbol;
830 			}
831 		}
832 	}
833 
834 	return NULL;
835 }
836 
837 
838 int
839 resolve_symbol(image_t *rootImage, image_t *image, struct Elf32_Sym *sym,
840 	addr_t *sym_addr)
841 {
842 	struct Elf32_Sym *sym2;
843 	char *symname;
844 	image_t *shimg;
845 
846 	switch (sym->st_shndx) {
847 		case SHN_UNDEF:
848 			// patch the symbol name
849 			symname = SYMNAME(image, sym);
850 
851 			// it's undefined, must be outside this image, try the other images
852 			sym2 = find_undefined_symbol(rootImage, image, symname, &shimg);
853 			if (!sym2) {
854 				printf("elf_resolve_symbol: could not resolve symbol '%s'\n", symname);
855 				return B_MISSING_SYMBOL;
856 			}
857 
858 			// make sure they're the same type
859 			if (ELF32_ST_TYPE(sym->st_info) != STT_NOTYPE
860 				&& ELF32_ST_TYPE(sym->st_info) != ELF32_ST_TYPE(sym2->st_info)) {
861 				printf("elf_resolve_symbol: found symbol '%s' in shared image but wrong type\n", symname);
862 				return B_MISSING_SYMBOL;
863 			}
864 
865 			if (ELF32_ST_BIND(sym2->st_info) != STB_GLOBAL
866 				&& ELF32_ST_BIND(sym2->st_info) != STB_WEAK) {
867 				printf("elf_resolve_symbol: found symbol '%s' but not exported\n", symname);
868 				return B_MISSING_SYMBOL;
869 			}
870 
871 			*sym_addr = sym2->st_value + shimg->regions[0].delta;
872 			return B_NO_ERROR;
873 
874 		case SHN_ABS:
875 			*sym_addr = sym->st_value + image->regions[0].delta;
876 			return B_NO_ERROR;
877 
878 		case SHN_COMMON:
879 			// ToDo: finish this
880 			printf("elf_resolve_symbol: COMMON symbol, finish me!\n");
881 			return B_ERROR; //ERR_NOT_IMPLEMENTED_YET;
882 
883 		default:
884 			// standard symbol
885 			*sym_addr = sym->st_value + image->regions[0].delta;
886 			return B_NO_ERROR;
887 	}
888 }
889 
890 
891 static void
892 register_image(image_t *image, int fd, const char *path)
893 {
894 	struct stat stat;
895 	image_info info;
896 
897 	// ToDo: set these correctly
898 	info.id = 0;
899 	info.type = image->type;
900 	info.sequence = 0;
901 	info.init_order = 0;
902 	info.init_routine = (void (*)())image->init_routine;
903 	info.term_routine = (void (*)())image->term_routine;
904 
905 	if (_kern_read_stat(fd, NULL, false, &stat, sizeof(struct stat)) == B_OK) {
906 		info.device = stat.st_dev;
907 		info.node = stat.st_ino;
908 	} else {
909 		info.device = -1;
910 		info.node = -1;
911 	}
912 
913 	strlcpy(info.name, path, sizeof(info.name));
914 	info.text = (void *)image->regions[0].vmstart;
915 	info.text_size = image->regions[0].vmsize;
916 	info.data = (void *)image->regions[1].vmstart;
917 	info.data_size = image->regions[1].vmsize;
918 	image->id = _kern_register_image(&info, sizeof(image_info));
919 }
920 
921 
922 static status_t
923 relocate_image(image_t *rootImage, image_t *image)
924 {
925 	status_t status = arch_relocate_image(rootImage, image);
926 	if (status < B_OK) {
927 		FATAL("troubles relocating: 0x%lx (image: %s)\n", status, image->name);
928 		return status;
929 	}
930 
931 	_kern_image_relocated(image->id);
932 	return B_OK;
933 }
934 
935 
936 static status_t
937 load_container(char const *name, image_type type, const char *rpath, image_t **_image)
938 {
939 	int32 pheaderSize, sheaderSize;
940 	char path[PATH_MAX];
941 	ssize_t length;
942 	char ph_buff[4096];
943 	int32 numRegions;
944 	image_t *found;
945 	image_t *image;
946 	status_t status;
947 	int fd;
948 
949 	struct Elf32_Ehdr eheader;
950 
951 	// Have we already loaded that image? Don't check for add-ons -- we always
952 	// reload them.
953 	if (type != B_ADD_ON_IMAGE) {
954 		found = find_image(name, APP_OR_LIBRARY_TYPE);
955 		if (found) {
956 			atomic_add(&found->ref_count, 1);
957 			*_image = found;
958 			return B_OK;
959 		}
960 	}
961 
962 	strlcpy(path, name, sizeof(path));
963 
964 	// Try to load explicit image path first
965 	fd = open_executable(path, type, rpath);
966 	if (fd < 0) {
967 		FATAL("cannot open file %s\n", path);
968 		return fd;
969 	}
970 
971 	// If the path is not absolute, we prepend the CWD to make it one.
972 	if (path[0] != '/') {
973 		char relativePath[PATH_MAX];
974 		if (!strncmp(path, "./", 2))
975 			strcpy(relativePath, path + 2);
976 		else
977 			strcpy(relativePath, path);
978 
979 		// get the CWD
980 		status = _kern_getcwd(path, sizeof(path));
981 		if (status < B_OK) {
982 			FATAL("_kern_getcwd() failed\n");
983 			goto err1;
984 		}
985 
986 		if (strlcat(path, "/", sizeof(path)) >= sizeof(path)
987 			|| strlcat(path, relativePath, sizeof(path)) >= sizeof(path)) {
988 			status = B_NAME_TOO_LONG;
989 			FATAL("Absolute path of image %s is too "
990 				"long!\n", relativePath);
991 			goto err1;
992 		}
993 	}
994 
995 	// Test again if this image has been registered already - this time,
996 	// we can check the full path, not just its name as noted.
997 	// You could end up loading an image twice with symbolic links, else.
998 	if (type != B_ADD_ON_IMAGE) {
999 		found = find_image(path, APP_OR_LIBRARY_TYPE);
1000 		if (found) {
1001 			atomic_add(&found->ref_count, 1);
1002 			*_image = found;
1003 			return B_OK;
1004 		}
1005 	}
1006 
1007 	length = _kern_read(fd, 0, &eheader, sizeof(eheader));
1008 	if (length != sizeof(eheader)) {
1009 		status = B_NOT_AN_EXECUTABLE;
1010 		FATAL("troubles reading ELF header\n");
1011 		goto err1;
1012 	}
1013 
1014 	status = parse_elf_header(&eheader, &pheaderSize, &sheaderSize);
1015 	if (status < B_OK) {
1016 		FATAL("incorrect ELF header\n");
1017 		goto err1;
1018 	}
1019 
1020 	// ToDo: what to do about this restriction??
1021 	if (pheaderSize > (int)sizeof(ph_buff)) {
1022 		FATAL("Cannot handle program headers bigger than %lu\n", sizeof(ph_buff));
1023 		status = B_UNSUPPORTED;
1024 		goto err1;
1025 	}
1026 
1027 	length = _kern_read(fd, eheader.e_phoff, ph_buff, pheaderSize);
1028 	if (length != pheaderSize) {
1029 		FATAL("Could not read program headers: %s\n", strerror(length));
1030 		status = B_BAD_DATA;
1031 		goto err1;
1032 	}
1033 
1034 	numRegions = count_regions(ph_buff, eheader.e_phnum, eheader.e_phentsize);
1035 	if (numRegions <= 0) {
1036 		FATAL("Troubles parsing Program headers, numRegions = %ld\n", numRegions);
1037 		status = B_BAD_DATA;
1038 		goto err1;
1039 	}
1040 
1041 	image = create_image(name, path, numRegions);
1042 	if (image == NULL) {
1043 		FATAL("Failed to allocate image_t object\n");
1044 		status = B_NO_MEMORY;
1045 		goto err1;
1046 	}
1047 
1048 	status = parse_program_headers(image, ph_buff, eheader.e_phnum, eheader.e_phentsize);
1049 	if (status < B_OK)
1050 		goto err2;
1051 
1052 	if (!assert_dynamic_loadable(image)) {
1053 		FATAL("Dynamic segment must be loadable (implementation restriction)\n");
1054 		status = B_UNSUPPORTED;
1055 		goto err2;
1056 	}
1057 
1058 	status = map_image(fd, path, image, type == B_APP_IMAGE);
1059 	if (status < B_OK) {
1060 		FATAL("Could not map image: %s\n", strerror(status));
1061 		status = B_ERROR;
1062 		goto err2;
1063 	}
1064 
1065 	if (!parse_dynamic_segment(image)) {
1066 		FATAL("Troubles handling dynamic section\n");
1067 		status = B_BAD_DATA;
1068 		goto err3;
1069 	}
1070 
1071 	if (eheader.e_entry != NULL)
1072 		image->entry_point = eheader.e_entry + image->regions[0].delta;
1073 
1074 	image->type = type;
1075 	register_image(image, fd, path);
1076 
1077 	_kern_close(fd);
1078 
1079 	enqueue_image(&sLoadedImages, image);
1080 	sLoadedImageCount++;
1081 
1082 	*_image = image;
1083 	return B_OK;
1084 
1085 err3:
1086 	unmap_image(image);
1087 err2:
1088 	delete_image_struct(image);
1089 err1:
1090 	_kern_close(fd);
1091 	return status;
1092 }
1093 
1094 
1095 static const char *
1096 find_dt_rpath(image_t *image)
1097 {
1098 	int i;
1099 	struct Elf32_Dyn *d = (struct Elf32_Dyn *)image->dynamic_ptr;
1100 
1101 	for (i = 0; d[i].d_tag != DT_NULL; i++) {
1102 		if (d[i].d_tag == DT_RPATH)
1103 			return STRING(image, d[i].d_un.d_val);
1104 	}
1105 
1106 	return NULL;
1107 }
1108 
1109 
1110 static status_t
1111 load_dependencies(image_t *image)
1112 {
1113 	struct Elf32_Dyn *d = (struct Elf32_Dyn *)image->dynamic_ptr;
1114 	bool reportErrors = report_errors();
1115 	status_t status = B_OK;
1116 	uint32 i, j;
1117 	const char *rpath;
1118 
1119 	if (!d || (image->flags & RFLAG_DEPENDENCIES_LOADED))
1120 		return B_OK;
1121 
1122 	image->flags |= RFLAG_DEPENDENCIES_LOADED;
1123 
1124 	if (image->num_needed == 0)
1125 		return B_OK;
1126 
1127 	image->needed = (image_t**)malloc(image->num_needed * sizeof(image_t *));
1128 	if (image->needed == NULL) {
1129 		FATAL("failed to allocate needed struct\n");
1130 		return B_NO_MEMORY;
1131 	}
1132 
1133 	memset(image->needed, 0, image->num_needed * sizeof(image_t *));
1134 	rpath = find_dt_rpath(image);
1135 
1136 	for (i = 0, j = 0; d[i].d_tag != DT_NULL; i++) {
1137 		switch (d[i].d_tag) {
1138 			case DT_NEEDED:
1139 			{
1140 				int32 neededOffset = d[i].d_un.d_val;
1141 				const char *name = STRING(image, neededOffset);
1142 
1143 				status_t loadStatus = load_container(name, B_LIBRARY_IMAGE,
1144 					rpath, &image->needed[j]);
1145 				if (loadStatus < B_OK) {
1146 					status = loadStatus;
1147 					// correct error code in case the file could not been found
1148 					if (status == B_ENTRY_NOT_FOUND) {
1149 						status = B_MISSING_LIBRARY;
1150 
1151 						if (reportErrors)
1152 							sErrorMessage.AddString("missing library", name);
1153 					}
1154 
1155 					// Collect all missing libraries in case we report back
1156 					if (!reportErrors)
1157 						return status;
1158 				}
1159 
1160 				j += 1;
1161 				break;
1162 			}
1163 
1164 			default:
1165 				// ignore any other tag
1166 				continue;
1167 		}
1168 	}
1169 
1170 	if (status < B_OK)
1171 		return status;
1172 
1173 	if (j != image->num_needed) {
1174 		FATAL("Internal error at load_dependencies()");
1175 		return B_ERROR;
1176 	}
1177 
1178 	return B_OK;
1179 }
1180 
1181 
1182 static uint32
1183 topological_sort(image_t *image, uint32 slot, image_t **initList,
1184 	uint32 sortFlag)
1185 {
1186 	uint32 i;
1187 
1188 	if (image->flags & sortFlag)
1189 		return slot;
1190 
1191 	image->flags |= sortFlag; /* make sure we don't visit this one */
1192 	for (i = 0; i < image->num_needed; i++)
1193 		slot = topological_sort(image->needed[i], slot, initList, sortFlag);
1194 
1195 	initList[slot] = image;
1196 	return slot + 1;
1197 }
1198 
1199 
1200 static ssize_t
1201 get_sorted_image_list(image_t *image, image_t ***_list, uint32 sortFlag)
1202 {
1203 	image_t **list;
1204 
1205 	list = (image_t**)malloc(sLoadedImageCount * sizeof(image_t *));
1206 	if (list == NULL) {
1207 		FATAL("memory shortage in get_sorted_image_list()");
1208 		*_list = NULL;
1209 		return B_NO_MEMORY;
1210 	}
1211 
1212 	memset(list, 0, sLoadedImageCount * sizeof(image_t *));
1213 
1214 	*_list = list;
1215 	return topological_sort(image, 0, list, sortFlag);
1216 }
1217 
1218 
1219 static status_t
1220 relocate_dependencies(image_t *image)
1221 {
1222 	ssize_t count, i;
1223 	image_t **list;
1224 
1225 	count = get_sorted_image_list(image, &list, RFLAG_RELOCATED);
1226 	if (count < B_OK)
1227 		return count;
1228 
1229 	for (i = 0; i < count; i++) {
1230 		status_t status = relocate_image(image, list[i]);
1231 		if (status < B_OK)
1232 			return status;
1233 	}
1234 
1235 	free(list);
1236 	return B_OK;
1237 }
1238 
1239 
1240 static void
1241 init_dependencies(image_t *image, bool initHead)
1242 {
1243 	image_t **initList;
1244 	ssize_t count, i;
1245 
1246 	count = get_sorted_image_list(image, &initList, RFLAG_INITIALIZED);
1247 	if (count <= 0)
1248 		return;
1249 
1250 	if (!initHead) {
1251 		// this removes the "calling" image
1252 		image->flags &= ~RFLAG_INITIALIZED;
1253 		initList[--count] = NULL;
1254 	}
1255 
1256 	TRACE(("%ld: init dependencies\n", find_thread(NULL)));
1257 	for (i = 0; i < count; i++) {
1258 		image = initList[i];
1259 
1260 		TRACE(("%ld:  init: %s\n", find_thread(NULL), image->name));
1261 
1262 		if (image->init_routine != NULL)
1263 			((init_term_function)image->init_routine)(image->id);
1264 	}
1265 	TRACE(("%ld:  init done.\n", find_thread(NULL)));
1266 
1267 	free(initList);
1268 }
1269 
1270 
1271 static void
1272 put_image(image_t *image)
1273 {
1274 	// If all references to the image are gone, add it to the disposable list
1275 	// and remove all dependencies
1276 
1277 	if (atomic_add(&image->ref_count, -1) == 1) {
1278 		size_t i;
1279 
1280 		dequeue_image(&sLoadedImages, image);
1281 		enqueue_image(&sDisposableImages, image);
1282 		sLoadedImageCount--;
1283 
1284 		for (i = 0; i < image->num_needed; i++) {
1285 			put_image(image->needed[i]);
1286 		}
1287 	}
1288 }
1289 
1290 
1291 //	#pragma mark - libroot.so exported functions
1292 
1293 
1294 image_id
1295 load_program(char const *path, void **_entry)
1296 {
1297 	status_t status;
1298 	image_t *image;
1299 
1300 	rld_lock();
1301 		// for now, just do stupid simple global locking
1302 
1303 	TRACE(("rld: load %s\n", path));
1304 
1305 	status = load_container(path, B_APP_IMAGE, NULL, &sProgramImage);
1306 	if (status < B_OK)
1307 		goto err;
1308 
1309 	for (image = sLoadedImages.head; image != NULL; image = image->next) {
1310 		status = load_dependencies(image);
1311 		if (status < B_OK)
1312 			goto err;
1313 	}
1314 
1315 	status = relocate_dependencies(sProgramImage);
1316 	if (status < B_OK)
1317 		goto err;
1318 
1319 	// We patch any exported __gRuntimeLoader symbols to point to our private API
1320 	{
1321 		struct Elf32_Sym *symbol = find_symbol_in_loaded_images(
1322 			"__gRuntimeLoader", &image);
1323 		if (symbol != NULL) {
1324 			void **_export = (void **)(symbol->st_value + image->regions[0].delta);
1325 			*_export = &gRuntimeLoader;
1326 		}
1327 	}
1328 
1329 	init_dependencies(sLoadedImages.head, true);
1330 	remap_images();
1331 		// ToDo: once setup_system_time() is fixed, move this one line higher!
1332 
1333 	// Since the images are initialized now, we no longer should use our
1334 	// getenv(), but use the one from libroot.so
1335 	{
1336 		struct Elf32_Sym *symbol = find_symbol_in_loaded_images("getenv",
1337 			&image);
1338 		if (symbol != NULL)
1339 			gGetEnv = (char* (*)(const char*))
1340 				(symbol->st_value + image->regions[0].delta);
1341 	}
1342 
1343 	if (sProgramImage->entry_point == NULL) {
1344 		status = B_NOT_AN_EXECUTABLE;
1345 		goto err;
1346 	}
1347 
1348 	*_entry = (void *)(sProgramImage->entry_point);
1349 
1350 	rld_unlock();
1351 	return sProgramImage->id;
1352 
1353 err:
1354 	delete_image(sProgramImage);
1355 
1356 	if (report_errors()) {
1357 		// send error message
1358 		sErrorMessage.AddInt32("error", status);
1359 		sErrorMessage.SetDeliveryInfo(gProgramArgs->error_token,
1360 			-1, 0, find_thread(NULL));
1361 
1362 		_kern_write_port_etc(gProgramArgs->error_port, 'KMSG',
1363 			sErrorMessage.Buffer(), sErrorMessage.ContentSize(), 0, 0);
1364 	}
1365 	_kern_loading_app_failed(status);
1366 	rld_unlock();
1367 
1368 	return status;
1369 }
1370 
1371 
1372 image_id
1373 load_library(char const *path, uint32 flags, bool addOn)
1374 {
1375 	image_t *image = NULL;
1376 	image_t *iter;
1377 	image_type type = (addOn ? B_ADD_ON_IMAGE : B_LIBRARY_IMAGE);
1378 	status_t status;
1379 
1380 	if (path == NULL)
1381 		return B_BAD_VALUE;
1382 
1383 	// ToDo: implement flags
1384 	(void)flags;
1385 
1386 	rld_lock();
1387 		// for now, just do stupid simple global locking
1388 
1389 	// have we already loaded this library?
1390 	// Checking it at this stage saves loading its dependencies again
1391 	if (!addOn) {
1392 		image = find_image(path, APP_OR_LIBRARY_TYPE);
1393 		if (image) {
1394 			atomic_add(&image->ref_count, 1);
1395 			rld_unlock();
1396 			return image->id;
1397 		}
1398 	}
1399 
1400 	status = load_container(path, type, NULL, &image);
1401 	if (status < B_OK) {
1402 		rld_unlock();
1403 		return status;
1404 	}
1405 
1406 	for (iter = sLoadedImages.head; iter; iter = iter->next) {
1407 		status = load_dependencies(iter);
1408 		if (status < B_OK)
1409 			goto err;
1410 	}
1411 
1412 	status = relocate_dependencies(image);
1413 	if (status < B_OK)
1414 		goto err;
1415 
1416 	remap_images();
1417 	init_dependencies(image, true);
1418 
1419 	rld_unlock();
1420 	return image->id;
1421 
1422 err:
1423 	dequeue_image(&sLoadedImages, image);
1424 	sLoadedImageCount--;
1425 	delete_image(image);
1426 	rld_unlock();
1427 	return status;
1428 }
1429 
1430 
1431 status_t
1432 unload_library(image_id imageID, bool addOn)
1433 {
1434 	status_t status = B_BAD_IMAGE_ID;
1435 	image_t *image;
1436 	image_type type = addOn ? B_ADD_ON_IMAGE : B_LIBRARY_IMAGE;
1437 
1438 	if (imageID < B_OK)
1439 		return B_BAD_IMAGE_ID;
1440 
1441 	rld_lock();
1442 		// for now, just do stupid simple global locking
1443 
1444 	// we only check images that have been already initialized
1445 
1446 	for (image = sLoadedImages.head; image; image = image->next) {
1447 		if (image->id == imageID) {
1448 			// unload image
1449 			if (type == image->type) {
1450 				put_image(image);
1451 				status = B_OK;
1452 			} else
1453 				status = B_BAD_VALUE;
1454 			break;
1455 		}
1456 	}
1457 
1458 	if (status == B_OK) {
1459 		while ((image = sDisposableImages.head) != NULL) {
1460 			// call image fini here...
1461 			if (image->term_routine)
1462 				((init_term_function)image->term_routine)(image->id);
1463 
1464 			dequeue_image(&sDisposableImages, image);
1465 			unmap_image(image);
1466 
1467 			delete_image(image);
1468 		}
1469 	}
1470 
1471 	rld_unlock();
1472 	return status;
1473 }
1474 
1475 
1476 status_t
1477 get_nth_symbol(image_id imageID, int32 num, char *nameBuffer, int32 *_nameLength,
1478 	int32 *_type, void **_location)
1479 {
1480 	int32 count = 0, j;
1481 	uint32 i;
1482 	image_t *image;
1483 
1484 	rld_lock();
1485 
1486 	// get the image from those who have been already initialized
1487 	image = find_loaded_image_by_id(imageID);
1488 	if (image == NULL) {
1489 		rld_unlock();
1490 		return B_BAD_IMAGE_ID;
1491 	}
1492 
1493 	// iterate through all the hash buckets until we've found the one
1494 	for (i = 0; i < HASHTABSIZE(image); i++) {
1495 		for (j = HASHBUCKETS(image)[i]; j != STN_UNDEF; j = HASHCHAINS(image)[j]) {
1496 			struct Elf32_Sym *symbol = &image->syms[i];
1497 
1498 			if (count == num) {
1499 				strlcpy(nameBuffer, SYMNAME(image, symbol), *_nameLength);
1500 				*_nameLength = strlen(SYMNAME(image, symbol));
1501 
1502 				if (_type != NULL) {
1503 					// ToDo: check with the return types of that BeOS function
1504 					if (ELF32_ST_TYPE(symbol->st_info) == STT_FUNC)
1505 						*_type = B_SYMBOL_TYPE_TEXT;
1506 					else if (ELF32_ST_TYPE(symbol->st_info) == STT_OBJECT)
1507 						*_type = B_SYMBOL_TYPE_DATA;
1508 					else
1509 						*_type = B_SYMBOL_TYPE_ANY;
1510 				}
1511 
1512 				if (_location != NULL)
1513 					*_location = (void *)(symbol->st_value + image->regions[0].delta);
1514 				goto out;
1515 			}
1516 			count++;
1517 		}
1518 	}
1519 out:
1520 	rld_unlock();
1521 
1522 	if (num != count)
1523 		return B_BAD_INDEX;
1524 
1525 	return B_OK;
1526 }
1527 
1528 
1529 status_t
1530 get_symbol(image_id imageID, char const *symbolName, int32 symbolType, void **_location)
1531 {
1532 	status_t status = B_OK;
1533 	image_t *image;
1534 
1535 	if (imageID < B_OK)
1536 		return B_BAD_IMAGE_ID;
1537 	if (symbolName == NULL)
1538 		return B_BAD_VALUE;
1539 
1540 	rld_lock();
1541 		// for now, just do stupid simple global locking
1542 
1543 	// get the image from those who have been already initialized
1544 	image = find_loaded_image_by_id(imageID);
1545 	if (image != NULL) {
1546 		struct Elf32_Sym *symbol;
1547 
1548 		// get the symbol in the image
1549 		symbol = find_symbol(image, symbolName, symbolType);
1550 		if (symbol) {
1551 			if (_location != NULL)
1552 				*_location = (void *)(symbol->st_value + image->regions[0].delta);
1553 		} else
1554 			status = B_ENTRY_NOT_FOUND;
1555 	} else
1556 		status = B_BAD_IMAGE_ID;
1557 
1558 	rld_unlock();
1559 	return status;
1560 }
1561 
1562 
1563 status_t
1564 get_next_image_dependency(image_id id, uint32 *cookie, const char **_name)
1565 {
1566 	uint32 i, j, searchIndex = *cookie;
1567 	struct Elf32_Dyn *dynamicSection;
1568 	image_t *image;
1569 
1570 	if (_name == NULL)
1571 		return B_BAD_VALUE;
1572 
1573 	rld_lock();
1574 
1575 	image = find_loaded_image_by_id(id);
1576 	if (image == NULL) {
1577 		rld_unlock();
1578 		return B_BAD_IMAGE_ID;
1579 	}
1580 
1581 	dynamicSection = (struct Elf32_Dyn *)image->dynamic_ptr;
1582 	if (dynamicSection == NULL || image->num_needed <= searchIndex) {
1583 		rld_unlock();
1584 		return B_ENTRY_NOT_FOUND;
1585 	}
1586 
1587 	for (i = 0, j = 0; dynamicSection[i].d_tag != DT_NULL; i++) {
1588 		if (dynamicSection[i].d_tag != DT_NEEDED)
1589 			continue;
1590 
1591 		if (j++ == searchIndex) {
1592 			int32 neededOffset = dynamicSection[i].d_un.d_val;
1593 
1594 			*_name = STRING(image, neededOffset);
1595 			*cookie = searchIndex + 1;
1596 			rld_unlock();
1597 			return B_OK;
1598 		}
1599 	}
1600 
1601 	rld_unlock();
1602 	return B_ENTRY_NOT_FOUND;
1603 }
1604 
1605 
1606 //	#pragma mark - runtime_loader private exports
1607 
1608 
1609 /** Read and verify the ELF header */
1610 
1611 status_t
1612 elf_verify_header(void *header, int32 length)
1613 {
1614 	int32 programSize, sectionSize;
1615 
1616 	if (length < (int32)sizeof(struct Elf32_Ehdr))
1617 		return B_NOT_AN_EXECUTABLE;
1618 
1619 	return parse_elf_header((struct Elf32_Ehdr *)header, &programSize, &sectionSize);
1620 }
1621 
1622 
1623 void
1624 terminate_program(void)
1625 {
1626 	image_t **termList;
1627 	ssize_t count, i;
1628 
1629 	count = get_sorted_image_list(sProgramImage, &termList, RFLAG_TERMINATED);
1630 	if (count < B_OK)
1631 		return;
1632 
1633 	TRACE(("%ld: terminate dependencies\n", find_thread(NULL)));
1634 	for (i = count; i-- > 0;) {
1635 		image_t *image = termList[i];
1636 
1637 		TRACE(("%ld:  term: %s\n", find_thread(NULL), image->name));
1638 
1639 		if (image->term_routine)
1640 			((init_term_function)image->term_routine)(image->id);
1641 	}
1642 	TRACE(("%ld:  term done.\n", find_thread(NULL)));
1643 
1644 	free(termList);
1645 }
1646 
1647 
1648 void
1649 rldelf_init(void)
1650 {
1651 	rld_sem = create_sem(1, "rld_lock");
1652 	rld_sem_owner = -1;
1653 	rld_sem_count = 0;
1654 
1655 	// create the debug area
1656 	{
1657 		int32 size = TO_PAGE_SIZE(sizeof(runtime_loader_debug_area));
1658 
1659 		runtime_loader_debug_area *area;
1660 		area_id areaID = _kern_create_area(RUNTIME_LOADER_DEBUG_AREA_NAME,
1661 			(void **)&area, B_ANY_ADDRESS, size, B_NO_LOCK,
1662 			B_READ_AREA | B_WRITE_AREA);
1663 		if (areaID < B_OK) {
1664 			FATAL("Failed to create debug area.\n");
1665 			_kern_loading_app_failed(areaID);
1666 		}
1667 
1668 		area->loaded_images = &sLoadedImages;
1669 	}
1670 
1671 	// initialize error message if needed
1672 	if (report_errors()) {
1673 		void *buffer = malloc(1024);
1674 		if (buffer == NULL)
1675 			return;
1676 
1677 		sErrorMessage.SetTo(buffer, 1024, 'Rler');
1678 	}
1679 }
1680 
1681 
1682 status_t
1683 elf_reinit_after_fork()
1684 {
1685 	rld_sem = create_sem(1, "rld_lock");
1686 	if (rld_sem < 0)
1687 		return rld_sem;
1688 
1689 	return B_OK;
1690 }
1691