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