xref: /haiku/src/system/runtime_loader/elf.cpp (revision 2222d0559df303a9846a2fad53741f8b20b14d7c)
1 /*
2  * Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Copyright 2003-2008, Axel Dörfler, axeld@pinc-software.de.
4  * Distributed under the terms of the MIT License.
5  *
6  * Copyright 2002, Manuel J. Petit. All rights reserved.
7  * Copyright 2001, Travis Geiselbrecht. All rights reserved.
8  * Distributed under the terms of the NewOS License.
9  */
10 
11 #include "runtime_loader_private.h"
12 
13 #include <ctype.h>
14 #include <dlfcn.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 
19 #include <OS.h>
20 
21 #include <elf32.h>
22 #include <syscalls.h>
23 #include <util/kernel_cpp.h>
24 
25 #include "add_ons.h"
26 #include "elf_load_image.h"
27 #include "elf_symbol_lookup.h"
28 #include "elf_versioning.h"
29 #include "errors.h"
30 #include "images.h"
31 
32 
33 // TODO: implement better locking strategy
34 // TODO: implement lazy binding
35 
36 // a handle returned by load_library() (dlopen())
37 #define RLD_GLOBAL_SCOPE	((void*)-2l)
38 
39 
40 typedef void (*init_term_function)(image_id);
41 
42 bool gProgramLoaded = false;
43 image_t* gProgramImage;
44 
45 static image_t** sPreloadedImages = NULL;
46 static uint32 sPreloadedImageCount = 0;
47 
48 // a recursive lock
49 static sem_id sSem;
50 static thread_id sSemOwner;
51 static int32 sSemCount;
52 
53 
54 static void
55 rld_unlock()
56 {
57 	if (sSemCount-- == 1) {
58 		sSemOwner = -1;
59 		release_sem(sSem);
60 	}
61 }
62 
63 
64 static void
65 rld_lock()
66 {
67 	thread_id self = find_thread(NULL);
68 	if (self != sSemOwner) {
69 		acquire_sem(sSem);
70 		sSemOwner = self;
71 	}
72 	sSemCount++;
73 }
74 
75 
76 static const char *
77 find_dt_rpath(image_t *image)
78 {
79 	int i;
80 	struct Elf32_Dyn *d = (struct Elf32_Dyn *)image->dynamic_ptr;
81 
82 	for (i = 0; d[i].d_tag != DT_NULL; i++) {
83 		if (d[i].d_tag == DT_RPATH)
84 			return STRING(image, d[i].d_un.d_val);
85 	}
86 
87 	return NULL;
88 }
89 
90 
91 static status_t
92 load_immediate_dependencies(image_t *image)
93 {
94 	struct Elf32_Dyn *d = (struct Elf32_Dyn *)image->dynamic_ptr;
95 	bool reportErrors = report_errors();
96 	status_t status = B_OK;
97 	uint32 i, j;
98 	const char *rpath;
99 
100 	if (!d || (image->flags & RFLAG_DEPENDENCIES_LOADED))
101 		return B_OK;
102 
103 	image->flags |= RFLAG_DEPENDENCIES_LOADED;
104 
105 	if (image->num_needed == 0)
106 		return B_OK;
107 
108 	KTRACE("rld: load_dependencies(\"%s\", id: %ld)", image->name,
109 		image->id);
110 
111 	image->needed = (image_t**)malloc(image->num_needed * sizeof(image_t *));
112 	if (image->needed == NULL) {
113 		FATAL("%s: Failed to allocate needed struct\n", image->path);
114 		KTRACE("rld: load_dependencies(\"%s\", id: %ld) failed: no memory",
115 			image->name, image->id);
116 		return B_NO_MEMORY;
117 	}
118 
119 	memset(image->needed, 0, image->num_needed * sizeof(image_t *));
120 	rpath = find_dt_rpath(image);
121 
122 	for (i = 0, j = 0; d[i].d_tag != DT_NULL; i++) {
123 		switch (d[i].d_tag) {
124 			case DT_NEEDED:
125 			{
126 				int32 neededOffset = d[i].d_un.d_val;
127 				const char *name = STRING(image, neededOffset);
128 
129 				status_t loadStatus = load_image(name, B_LIBRARY_IMAGE,
130 					rpath, &image->needed[j]);
131 				if (loadStatus < B_OK) {
132 					status = loadStatus;
133 					// correct error code in case the file could not been found
134 					if (status == B_ENTRY_NOT_FOUND) {
135 						status = B_MISSING_LIBRARY;
136 
137 						if (reportErrors)
138 							gErrorMessage.AddString("missing library", name);
139 					}
140 
141 					// Collect all missing libraries in case we report back
142 					if (!reportErrors) {
143 						KTRACE("rld: load_dependencies(\"%s\", id: %ld) "
144 							"failed: %s", image->name, image->id,
145 							strerror(status));
146 						return status;
147 					}
148 				}
149 
150 				j += 1;
151 				break;
152 			}
153 
154 			default:
155 				// ignore any other tag
156 				continue;
157 		}
158 	}
159 
160 	if (status < B_OK) {
161 		KTRACE("rld: load_dependencies(\"%s\", id: %ld) "
162 			"failed: %s", image->name, image->id,
163 			strerror(status));
164 		return status;
165 	}
166 
167 	if (j != image->num_needed) {
168 		FATAL("Internal error at load_dependencies()");
169 		KTRACE("rld: load_dependencies(\"%s\", id: %ld) "
170 			"failed: internal error", image->name, image->id);
171 		return B_ERROR;
172 	}
173 
174 	KTRACE("rld: load_dependencies(\"%s\", id: %ld) done", image->name,
175 		image->id);
176 
177 	return B_OK;
178 }
179 
180 
181 static status_t
182 load_dependencies(image_t* image)
183 {
184 	// load dependencies (breadth-first)
185 	for (image_t* otherImage = image; otherImage != NULL;
186 			otherImage = otherImage->next) {
187 		status_t status = load_immediate_dependencies(otherImage);
188 		if (status != B_OK)
189 			return status;
190 	}
191 
192 	// Check the needed versions for the given image and all newly loaded
193 	// dependencies.
194 	for (image_t* otherImage = image; otherImage != NULL;
195 			otherImage = otherImage->next) {
196 		status_t status = check_needed_image_versions(otherImage);
197 		if (status != B_OK)
198 			return status;
199 	}
200 
201 	return B_OK;
202 }
203 
204 
205 static status_t
206 relocate_image(image_t *rootImage, image_t *image)
207 {
208 	status_t status = arch_relocate_image(rootImage, image);
209 	if (status < B_OK) {
210 		FATAL("%s: Troubles relocating: %s\n", image->path, strerror(status));
211 		return status;
212 	}
213 
214 	_kern_image_relocated(image->id);
215 	image_event(image, IMAGE_EVENT_RELOCATED);
216 	return B_OK;
217 }
218 
219 
220 static status_t
221 relocate_dependencies(image_t *image)
222 {
223 	// get the images that still have to be relocated
224 	image_t **list;
225 	ssize_t count = get_sorted_image_list(image, &list, RFLAG_RELOCATED);
226 	if (count < B_OK)
227 		return count;
228 
229 	// relocate
230 	for (ssize_t i = 0; i < count; i++) {
231 		status_t status = relocate_image(image, list[i]);
232 		if (status < B_OK) {
233 			free(list);
234 			return status;
235 		}
236 	}
237 
238 	free(list);
239 	return B_OK;
240 }
241 
242 
243 static void
244 init_dependencies(image_t *image, bool initHead)
245 {
246 	image_t **initList;
247 	ssize_t count, i;
248 
249 	count = get_sorted_image_list(image, &initList, RFLAG_INITIALIZED);
250 	if (count <= 0)
251 		return;
252 
253 	if (!initHead) {
254 		// this removes the "calling" image
255 		image->flags &= ~RFLAG_INITIALIZED;
256 		initList[--count] = NULL;
257 	}
258 
259 	TRACE(("%ld: init dependencies\n", find_thread(NULL)));
260 	for (i = 0; i < count; i++) {
261 		image = initList[i];
262 
263 		TRACE(("%ld:  init: %s\n", find_thread(NULL), image->name));
264 
265 		if (image->init_routine != 0)
266 			((init_term_function)image->init_routine)(image->id);
267 
268 		image_event(image, IMAGE_EVENT_INITIALIZED);
269 	}
270 	TRACE(("%ld:  init done.\n", find_thread(NULL)));
271 
272 	free(initList);
273 }
274 
275 
276 static void
277 inject_runtime_loader_api(image_t* rootImage)
278 {
279 	// We patch any exported __gRuntimeLoader symbols to point to our private
280 	// API.
281 	image_t* image;
282 	void* _export;
283 	if (find_symbol_breadth_first(rootImage,
284 			SymbolLookupInfo("__gRuntimeLoader", B_SYMBOL_TYPE_DATA), &image,
285 			&_export) == B_OK) {
286 		*(void**)_export = &gRuntimeLoader;
287 	}
288 }
289 
290 
291 static status_t
292 add_preloaded_image(image_t* image)
293 {
294 	// We realloc() everytime -- not particularly efficient, but good enough for
295 	// small number of preloaded images.
296 	image_t** newArray = (image_t**)realloc(sPreloadedImages,
297 		sizeof(image_t*) * (sPreloadedImageCount + 1));
298 	if (newArray == NULL)
299 		return B_NO_MEMORY;
300 
301 	sPreloadedImages = newArray;
302 	newArray[sPreloadedImageCount++] = image;
303 
304 	return B_OK;
305 }
306 
307 
308 image_id
309 preload_image(char const* path)
310 {
311 	if (path == NULL)
312 		return B_BAD_VALUE;
313 
314 	KTRACE("rld: preload_image(\"%s\")", path);
315 
316 	image_t *image = NULL;
317 	status_t status = load_image(path, B_ADD_ON_IMAGE, NULL, &image);
318 	if (status < B_OK) {
319 		rld_unlock();
320 		KTRACE("rld: preload_image(\"%s\") failed to load container: %s", path,
321 			strerror(status));
322 		return status;
323 	}
324 
325 	if (image->find_undefined_symbol == NULL)
326 		image->find_undefined_symbol = find_undefined_symbol_global;
327 
328 	status = load_dependencies(image);
329 	if (status < B_OK)
330 		goto err;
331 
332 	set_image_flags_recursively(image, RTLD_GLOBAL);
333 
334 	status = relocate_dependencies(image);
335 	if (status < B_OK)
336 		goto err;
337 
338 	status = add_preloaded_image(image);
339 	if (status < B_OK)
340 		goto err;
341 
342 	inject_runtime_loader_api(image);
343 
344 	remap_images();
345 	init_dependencies(image, true);
346 
347 	// if the image contains an add-on, register it
348 	runtime_loader_add_on* addOnStruct;
349 	if (find_symbol(image,
350 			SymbolLookupInfo("__gRuntimeLoaderAddOn", B_SYMBOL_TYPE_DATA),
351 			(void**)&addOnStruct) == B_OK) {
352 		add_add_on(image, addOnStruct);
353 	}
354 
355 	KTRACE("rld: preload_image(\"%s\") done: id: %ld", path, image->id);
356 
357 	return image->id;
358 
359 err:
360 	KTRACE("rld: preload_image(\"%s\") failed: %s", path, strerror(status));
361 
362 	dequeue_loaded_image(image);
363 	delete_image(image);
364 	return status;
365 }
366 
367 
368 static void
369 preload_images()
370 {
371 	const char* imagePaths = getenv("LD_PRELOAD");
372 	if (imagePaths == NULL)
373 		return;
374 
375 	while (*imagePaths != '\0') {
376 		// find begin of image path
377 		while (*imagePaths != '\0' && isspace(*imagePaths))
378 			imagePaths++;
379 
380 		if (*imagePaths == '\0')
381 			break;
382 
383 		// find end of image path
384 		const char* imagePath = imagePaths;
385 		while (*imagePaths != '\0' && !isspace(*imagePaths))
386 			imagePaths++;
387 
388 		// extract the path
389 		char path[B_PATH_NAME_LENGTH];
390 		size_t pathLen = imagePaths - imagePath;
391 		if (pathLen > sizeof(path) - 1)
392 			continue;
393 		memcpy(path, imagePath, pathLen);
394 		path[pathLen] = '\0';
395 
396 		// load the image
397 		preload_image(path);
398 	}
399 }
400 
401 
402 //	#pragma mark - libroot.so exported functions
403 
404 
405 image_id
406 load_program(char const *path, void **_entry)
407 {
408 	status_t status;
409 	image_t *image;
410 
411 	KTRACE("rld: load_program(\"%s\")", path);
412 
413 	rld_lock();
414 		// for now, just do stupid simple global locking
415 
416 	preload_images();
417 
418 	TRACE(("rld: load %s\n", path));
419 
420 	status = load_image(path, B_APP_IMAGE, NULL, &gProgramImage);
421 	if (status < B_OK)
422 		goto err;
423 
424 	if (gProgramImage->find_undefined_symbol == NULL)
425 		gProgramImage->find_undefined_symbol = find_undefined_symbol_global;
426 
427 	status = load_dependencies(gProgramImage);
428 	if (status < B_OK)
429 		goto err;
430 
431 	// Set RTLD_GLOBAL on all libraries including the program.
432 	// This results in the desired symbol resolution for dlopen()ed libraries.
433 	set_image_flags_recursively(gProgramImage, RTLD_GLOBAL);
434 
435 	status = relocate_dependencies(gProgramImage);
436 	if (status < B_OK)
437 		goto err;
438 
439 	inject_runtime_loader_api(gProgramImage);
440 
441 	remap_images();
442 	init_dependencies(gProgramImage, true);
443 
444 	// Since the images are initialized now, we no longer should use our
445 	// getenv(), but use the one from libroot.so
446 	find_symbol_breadth_first(gProgramImage,
447 		SymbolLookupInfo("getenv", B_SYMBOL_TYPE_TEXT), &image,
448 		(void**)&gGetEnv);
449 
450 	if (gProgramImage->entry_point == 0) {
451 		status = B_NOT_AN_EXECUTABLE;
452 		goto err;
453 	}
454 
455 	*_entry = (void *)(gProgramImage->entry_point);
456 
457 	rld_unlock();
458 
459 	gProgramLoaded = true;
460 
461 	KTRACE("rld: load_program(\"%s\") done: entry: %p, id: %ld", path,
462 		*_entry, gProgramImage->id);
463 
464 	return gProgramImage->id;
465 
466 err:
467 	KTRACE("rld: load_program(\"%s\") failed: %s", path, strerror(status));
468 
469 	delete_image(gProgramImage);
470 
471 	if (report_errors()) {
472 		// send error message
473 		gErrorMessage.AddInt32("error", status);
474 		gErrorMessage.SetDeliveryInfo(gProgramArgs->error_token,
475 			-1, 0, find_thread(NULL));
476 
477 		_kern_write_port_etc(gProgramArgs->error_port, 'KMSG',
478 			gErrorMessage.Buffer(), gErrorMessage.ContentSize(), 0, 0);
479 	}
480 	_kern_loading_app_failed(status);
481 	rld_unlock();
482 
483 	return status;
484 }
485 
486 
487 image_id
488 load_library(char const *path, uint32 flags, bool addOn, void** _handle)
489 {
490 	image_t *image = NULL;
491 	image_type type = (addOn ? B_ADD_ON_IMAGE : B_LIBRARY_IMAGE);
492 	status_t status;
493 
494 	if (path == NULL && addOn)
495 		return B_BAD_VALUE;
496 
497 	KTRACE("rld: load_library(\"%s\", 0x%lx, %d)", path, flags, addOn);
498 
499 	rld_lock();
500 		// for now, just do stupid simple global locking
501 
502 	// have we already loaded this library?
503 	// Checking it at this stage saves loading its dependencies again
504 	if (!addOn) {
505 		// a NULL path is fine -- it means the global scope shall be opened
506 		if (path == NULL) {
507 			*_handle = RLD_GLOBAL_SCOPE;
508 			rld_unlock();
509 			return 0;
510 		}
511 
512 		image = find_loaded_image_by_name(path, APP_OR_LIBRARY_TYPE);
513 		if (image != NULL && (flags & RTLD_GLOBAL) != 0)
514 			set_image_flags_recursively(image, RTLD_GLOBAL);
515 
516 		if (image) {
517 			atomic_add(&image->ref_count, 1);
518 			rld_unlock();
519 			KTRACE("rld: load_library(\"%s\"): already loaded: %ld", path,
520 				image->id);
521 			*_handle = image;
522 			return image->id;
523 		}
524 	}
525 
526 	status = load_image(path, type, NULL, &image);
527 	if (status < B_OK) {
528 		rld_unlock();
529 		KTRACE("rld: load_library(\"%s\") failed to load container: %s", path,
530 			strerror(status));
531 		return status;
532 	}
533 
534 	if (image->find_undefined_symbol == NULL) {
535 		if (addOn)
536 			image->find_undefined_symbol = find_undefined_symbol_add_on;
537 		else
538 			image->find_undefined_symbol = find_undefined_symbol_global;
539 	}
540 
541 	status = load_dependencies(image);
542 	if (status < B_OK)
543 		goto err;
544 
545 	// If specified, set the RTLD_GLOBAL flag recursively on this image and all
546 	// dependencies. If not specified, we temporarily set
547 	// RFLAG_USE_FOR_RESOLVING so that the dependencies will correctly be used
548 	// for undefined symbol resolution.
549 	if ((flags & RTLD_GLOBAL) != 0)
550 		set_image_flags_recursively(image, RTLD_GLOBAL);
551 	else
552 		set_image_flags_recursively(image, RFLAG_USE_FOR_RESOLVING);
553 
554 	status = relocate_dependencies(image);
555 	if (status < B_OK)
556 		goto err;
557 
558 	if ((flags & RTLD_GLOBAL) == 0)
559 		clear_image_flags_recursively(image, RFLAG_USE_FOR_RESOLVING);
560 
561 	remap_images();
562 	init_dependencies(image, true);
563 
564 	rld_unlock();
565 
566 	KTRACE("rld: load_library(\"%s\") done: id: %ld", path, image->id);
567 
568 	*_handle = image;
569 	return image->id;
570 
571 err:
572 	KTRACE("rld: load_library(\"%s\") failed: %s", path, strerror(status));
573 
574 	dequeue_loaded_image(image);
575 	delete_image(image);
576 	rld_unlock();
577 	return status;
578 }
579 
580 
581 status_t
582 unload_library(void* handle, image_id imageID, bool addOn)
583 {
584 	image_t *image;
585 	image_type type = addOn ? B_ADD_ON_IMAGE : B_LIBRARY_IMAGE;
586 
587 	if (handle == NULL && imageID < 0)
588 		return B_BAD_IMAGE_ID;
589 
590 	if (handle == RLD_GLOBAL_SCOPE)
591 		return B_OK;
592 
593 	rld_lock();
594 		// for now, just do stupid simple global locking
595 
596 	if (gInvalidImageIDs) {
597 		// After fork, we lazily rebuild the image IDs of all loaded images
598 		update_image_ids();
599 	}
600 
601 	// we only check images that have been already initialized
602 
603 	status_t status = B_BAD_IMAGE_ID;
604 
605 	if (handle != NULL) {
606 		image = (image_t*)handle;
607 		put_image(image);
608 		status = B_OK;
609 	} else {
610 		image = find_loaded_image_by_id(imageID, true);
611 		if (image != NULL) {
612 			// unload image
613 			if (type == image->type) {
614 				put_image(image);
615 				status = B_OK;
616 			} else
617 				status = B_BAD_VALUE;
618 		}
619 	}
620 
621 	if (status == B_OK) {
622 		while ((image = get_disposable_images().head) != NULL) {
623 			// call image fini here...
624 			if (gRuntimeLoader.call_atexit_hooks_for_range) {
625 				gRuntimeLoader.call_atexit_hooks_for_range(
626 					image->regions[0].vmstart, image->regions[0].vmsize);
627 			}
628 
629 			image_event(image, IMAGE_EVENT_UNINITIALIZING);
630 
631 			if (image->term_routine)
632 				((init_term_function)image->term_routine)(image->id);
633 
634 			dequeue_disposable_image(image);
635 			unmap_image(image);
636 
637 			image_event(image, IMAGE_EVENT_UNLOADING);
638 
639 			delete_image(image);
640 		}
641 	}
642 
643 	rld_unlock();
644 	return status;
645 }
646 
647 
648 status_t
649 get_nth_symbol(image_id imageID, int32 num, char *nameBuffer,
650 	int32 *_nameLength, int32 *_type, void **_location)
651 {
652 	int32 count = 0, j;
653 	uint32 i;
654 	image_t *image;
655 
656 	rld_lock();
657 
658 	// get the image from those who have been already initialized
659 	image = find_loaded_image_by_id(imageID, false);
660 	if (image == NULL) {
661 		rld_unlock();
662 		return B_BAD_IMAGE_ID;
663 	}
664 
665 	// iterate through all the hash buckets until we've found the one
666 	for (i = 0; i < HASHTABSIZE(image); i++) {
667 		for (j = HASHBUCKETS(image)[i]; j != STN_UNDEF; j = HASHCHAINS(image)[j]) {
668 			struct Elf32_Sym *symbol = &image->syms[j];
669 
670 			if (count == num) {
671 				const char* symbolName = SYMNAME(image, symbol);
672 				strlcpy(nameBuffer, symbolName, *_nameLength);
673 				*_nameLength = strlen(symbolName);
674 
675 				void* location = (void*)(symbol->st_value
676 					+ image->regions[0].delta);
677 				int32 type;
678 				if (ELF32_ST_TYPE(symbol->st_info) == STT_FUNC)
679 					type = B_SYMBOL_TYPE_TEXT;
680 				else if (ELF32_ST_TYPE(symbol->st_info) == STT_OBJECT)
681 					type = B_SYMBOL_TYPE_DATA;
682 				else
683 					type = B_SYMBOL_TYPE_ANY;
684 					// TODO: check with the return types of that BeOS function
685 
686 				patch_defined_symbol(image, symbolName, &location, &type);
687 
688 				if (_type != NULL)
689 					*_type = type;
690 				if (_location != NULL)
691 					*_location = location;
692 				goto out;
693 			}
694 			count++;
695 		}
696 	}
697 out:
698 	rld_unlock();
699 
700 	if (num != count)
701 		return B_BAD_INDEX;
702 
703 	return B_OK;
704 }
705 
706 
707 status_t
708 get_symbol(image_id imageID, char const *symbolName, int32 symbolType,
709 	bool recursive, image_id *_inImage, void **_location)
710 {
711 	status_t status = B_OK;
712 	image_t *image;
713 
714 	if (imageID < B_OK)
715 		return B_BAD_IMAGE_ID;
716 	if (symbolName == NULL)
717 		return B_BAD_VALUE;
718 
719 	rld_lock();
720 		// for now, just do stupid simple global locking
721 
722 	// get the image from those who have been already initialized
723 	image = find_loaded_image_by_id(imageID, false);
724 	if (image != NULL) {
725 		if (recursive) {
726 			// breadth-first search in the given image and its dependencies
727 			status = find_symbol_breadth_first(image,
728 				SymbolLookupInfo(symbolName, symbolType, NULL,
729 					LOOKUP_FLAG_DEFAULT_VERSION),
730 				&image, _location);
731 		} else {
732 			status = find_symbol(image,
733 				SymbolLookupInfo(symbolName, symbolType, NULL,
734 					LOOKUP_FLAG_DEFAULT_VERSION),
735 				_location);
736 		}
737 
738 		if (status == B_OK && _inImage != NULL)
739 			*_inImage = image->id;
740 	} else
741 		status = B_BAD_IMAGE_ID;
742 
743 	rld_unlock();
744 	return status;
745 }
746 
747 
748 status_t
749 get_library_symbol(void* handle, void* caller, const char* symbolName,
750 	void **_location)
751 {
752 	status_t status = B_ENTRY_NOT_FOUND;
753 
754 	if (symbolName == NULL)
755 		return B_BAD_VALUE;
756 
757 	rld_lock();
758 		// for now, just do stupid simple global locking
759 
760 	if (handle == RTLD_DEFAULT || handle == RLD_GLOBAL_SCOPE) {
761 		// look in the default scope
762 		image_t* image;
763 		Elf32_Sym* symbol = find_undefined_symbol_global(gProgramImage,
764 			gProgramImage,
765 			SymbolLookupInfo(symbolName, B_SYMBOL_TYPE_ANY, NULL,
766 				LOOKUP_FLAG_DEFAULT_VERSION),
767 			&image);
768 		if (symbol != NULL) {
769 			*_location = (void*)(symbol->st_value + image->regions[0].delta);
770 			int32 symbolType = ELF32_ST_TYPE(symbol->st_info) == STT_FUNC
771 				? B_SYMBOL_TYPE_TEXT : B_SYMBOL_TYPE_DATA;
772 			patch_defined_symbol(image, symbolName, _location, &symbolType);
773 			status = B_OK;
774 		}
775 	} else if (handle == RTLD_NEXT) {
776 		// Look in the default scope, but also in the dependencies of the
777 		// calling image. Return the next after the caller symbol.
778 
779 		// First of all, find the caller image.
780 		image_t* callerImage = get_loaded_images().head;
781 		for (; callerImage != NULL; callerImage = callerImage->next) {
782 			elf_region_t& text = callerImage->regions[0];
783 			if ((addr_t)caller >= text.vmstart
784 				&& (addr_t)caller < text.vmstart + text.vmsize) {
785 				// found the image
786 				break;
787 			}
788 		}
789 
790 		if (callerImage != NULL) {
791 			// found the caller -- now search the global scope until we find
792 			// the next symbol
793 			bool hitCallerImage = false;
794 			set_image_flags_recursively(callerImage, RFLAG_USE_FOR_RESOLVING);
795 
796 			image_t* image = get_loaded_images().head;
797 			for (; image != NULL; image = image->next) {
798 				// skip the caller image
799 				if (image == callerImage) {
800 					hitCallerImage = true;
801 					continue;
802 				}
803 
804 				// skip all images up to the caller image; also skip add-on
805 				// images and those not marked above for resolution
806 				if (!hitCallerImage || image->type == B_ADD_ON_IMAGE
807 					|| (image->flags
808 						& (RTLD_GLOBAL | RFLAG_USE_FOR_RESOLVING)) == 0) {
809 					continue;
810 				}
811 
812 				struct Elf32_Sym *symbol = find_symbol(image,
813 					SymbolLookupInfo(symbolName, B_SYMBOL_TYPE_TEXT, NULL,
814 						LOOKUP_FLAG_DEFAULT_VERSION));
815 				if (symbol == NULL)
816 					continue;
817 
818 				// found the symbol
819 				*_location = (void*)(symbol->st_value
820 					+ image->regions[0].delta);
821 				int32 symbolType = B_SYMBOL_TYPE_TEXT;
822 				patch_defined_symbol(image, symbolName, _location,
823 					&symbolType);
824 				status = B_OK;
825 				break;
826 			}
827 
828 			clear_image_flags_recursively(callerImage, RFLAG_USE_FOR_RESOLVING);
829 		}
830 	} else {
831 		// breadth-first search in the given image and its dependencies
832 		image_t* inImage;
833 		status = find_symbol_breadth_first((image_t*)handle,
834 			SymbolLookupInfo(symbolName, B_SYMBOL_TYPE_ANY, NULL,
835 				LOOKUP_FLAG_DEFAULT_VERSION),
836 			&inImage, _location);
837 	}
838 
839 	rld_unlock();
840 	return status;
841 }
842 
843 
844 status_t
845 get_next_image_dependency(image_id id, uint32 *cookie, const char **_name)
846 {
847 	uint32 i, j, searchIndex = *cookie;
848 	struct Elf32_Dyn *dynamicSection;
849 	image_t *image;
850 
851 	if (_name == NULL)
852 		return B_BAD_VALUE;
853 
854 	rld_lock();
855 
856 	image = find_loaded_image_by_id(id, false);
857 	if (image == NULL) {
858 		rld_unlock();
859 		return B_BAD_IMAGE_ID;
860 	}
861 
862 	dynamicSection = (struct Elf32_Dyn *)image->dynamic_ptr;
863 	if (dynamicSection == NULL || image->num_needed <= searchIndex) {
864 		rld_unlock();
865 		return B_ENTRY_NOT_FOUND;
866 	}
867 
868 	for (i = 0, j = 0; dynamicSection[i].d_tag != DT_NULL; i++) {
869 		if (dynamicSection[i].d_tag != DT_NEEDED)
870 			continue;
871 
872 		if (j++ == searchIndex) {
873 			int32 neededOffset = dynamicSection[i].d_un.d_val;
874 
875 			*_name = STRING(image, neededOffset);
876 			*cookie = searchIndex + 1;
877 			rld_unlock();
878 			return B_OK;
879 		}
880 	}
881 
882 	rld_unlock();
883 	return B_ENTRY_NOT_FOUND;
884 }
885 
886 
887 //	#pragma mark - runtime_loader private exports
888 
889 
890 /*! Read and verify the ELF header */
891 status_t
892 elf_verify_header(void *header, int32 length)
893 {
894 	int32 programSize, sectionSize;
895 
896 	if (length < (int32)sizeof(struct Elf32_Ehdr))
897 		return B_NOT_AN_EXECUTABLE;
898 
899 	return parse_elf_header((struct Elf32_Ehdr *)header, &programSize,
900 		&sectionSize);
901 }
902 
903 
904 void
905 terminate_program(void)
906 {
907 	image_t **termList;
908 	ssize_t count, i;
909 
910 	count = get_sorted_image_list(gProgramImage, &termList, RFLAG_TERMINATED);
911 	if (count < B_OK)
912 		return;
913 
914 	if (gInvalidImageIDs) {
915 		// After fork, we lazily rebuild the image IDs of all loaded images
916 		update_image_ids();
917 	}
918 
919 	TRACE(("%ld: terminate dependencies\n", find_thread(NULL)));
920 	for (i = count; i-- > 0;) {
921 		image_t *image = termList[i];
922 
923 		TRACE(("%ld:  term: %s\n", find_thread(NULL), image->name));
924 
925 		image_event(image, IMAGE_EVENT_UNINITIALIZING);
926 
927 		if (image->term_routine)
928 			((init_term_function)image->term_routine)(image->id);
929 
930 		image_event(image, IMAGE_EVENT_UNLOADING);
931 	}
932 	TRACE(("%ld:  term done.\n", find_thread(NULL)));
933 
934 	free(termList);
935 }
936 
937 
938 void
939 rldelf_init(void)
940 {
941 	sSem = create_sem(1, "runtime loader");
942 	sSemOwner = -1;
943 	sSemCount = 0;
944 
945 	init_add_ons();
946 
947 	// create the debug area
948 	{
949 		int32 size = TO_PAGE_SIZE(sizeof(runtime_loader_debug_area));
950 
951 		runtime_loader_debug_area *area;
952 		area_id areaID = _kern_create_area(RUNTIME_LOADER_DEBUG_AREA_NAME,
953 			(void **)&area, B_ANY_ADDRESS, size, B_NO_LOCK,
954 			B_READ_AREA | B_WRITE_AREA);
955 		if (areaID < B_OK) {
956 			FATAL("Failed to create debug area.\n");
957 			_kern_loading_app_failed(areaID);
958 		}
959 
960 		area->loaded_images = &get_loaded_images();
961 	}
962 
963 	// initialize error message if needed
964 	if (report_errors()) {
965 		void *buffer = malloc(1024);
966 		if (buffer == NULL)
967 			return;
968 
969 		gErrorMessage.SetTo(buffer, 1024, 'Rler');
970 	}
971 }
972 
973 
974 status_t
975 elf_reinit_after_fork(void)
976 {
977 	sSem = create_sem(1, "runtime loader");
978 	if (sSem < 0)
979 		return sSem;
980 
981 	// We also need to update the IDs of our images. We are the child and
982 	// and have cloned images with different IDs. Since in most cases (fork()
983 	// + exec*()) this would just increase the fork() overhead with no one
984 	// caring, we do that lazily, when first doing something different.
985 	gInvalidImageIDs = true;
986 
987 	return B_OK;
988 }
989