xref: /haiku/src/system/runtime_loader/elf.cpp (revision 62f5ba006a08b0df30631375878effaf67ae5dbc)
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 		KTRACE("rld: preload_image(\"%s\") failed to load container: %s", path,
311 			strerror(status));
312 		return status;
313 	}
314 
315 	if (image->find_undefined_symbol == NULL)
316 		image->find_undefined_symbol = find_undefined_symbol_global;
317 
318 	status = load_dependencies(image);
319 	if (status < B_OK)
320 		goto err;
321 
322 	set_image_flags_recursively(image, RTLD_GLOBAL);
323 
324 	status = relocate_dependencies(image);
325 	if (status < B_OK)
326 		goto err;
327 
328 	status = add_preloaded_image(image);
329 	if (status < B_OK)
330 		goto err;
331 
332 	inject_runtime_loader_api(image);
333 
334 	remap_images();
335 	init_dependencies(image, true);
336 
337 	// if the image contains an add-on, register it
338 	runtime_loader_add_on* addOnStruct;
339 	if (find_symbol(image,
340 			SymbolLookupInfo("__gRuntimeLoaderAddOn", B_SYMBOL_TYPE_DATA),
341 			(void**)&addOnStruct) == B_OK) {
342 		add_add_on(image, addOnStruct);
343 	}
344 
345 	KTRACE("rld: preload_image(\"%s\") done: id: %ld", path, image->id);
346 
347 	return image->id;
348 
349 err:
350 	KTRACE("rld: preload_image(\"%s\") failed: %s", path, strerror(status));
351 
352 	dequeue_loaded_image(image);
353 	delete_image(image);
354 	return status;
355 }
356 
357 
358 static void
359 preload_images()
360 {
361 	const char* imagePaths = getenv("LD_PRELOAD");
362 	if (imagePaths == NULL)
363 		return;
364 
365 	while (*imagePaths != '\0') {
366 		// find begin of image path
367 		while (*imagePaths != '\0' && isspace(*imagePaths))
368 			imagePaths++;
369 
370 		if (*imagePaths == '\0')
371 			break;
372 
373 		// find end of image path
374 		const char* imagePath = imagePaths;
375 		while (*imagePaths != '\0' && !isspace(*imagePaths))
376 			imagePaths++;
377 
378 		// extract the path
379 		char path[B_PATH_NAME_LENGTH];
380 		size_t pathLen = imagePaths - imagePath;
381 		if (pathLen > sizeof(path) - 1)
382 			continue;
383 		memcpy(path, imagePath, pathLen);
384 		path[pathLen] = '\0';
385 
386 		// load the image
387 		preload_image(path);
388 	}
389 }
390 
391 
392 //	#pragma mark - libroot.so exported functions
393 
394 
395 image_id
396 load_program(char const *path, void **_entry)
397 {
398 	status_t status;
399 	image_t *image;
400 
401 	KTRACE("rld: load_program(\"%s\")", path);
402 
403 	rld_lock();
404 		// for now, just do stupid simple global locking
405 
406 	preload_images();
407 
408 	TRACE(("rld: load %s\n", path));
409 
410 	status = load_image(path, B_APP_IMAGE, NULL, &gProgramImage);
411 	if (status < B_OK)
412 		goto err;
413 
414 	if (gProgramImage->find_undefined_symbol == NULL)
415 		gProgramImage->find_undefined_symbol = find_undefined_symbol_global;
416 
417 	status = load_dependencies(gProgramImage);
418 	if (status < B_OK)
419 		goto err;
420 
421 	// Set RTLD_GLOBAL on all libraries including the program.
422 	// This results in the desired symbol resolution for dlopen()ed libraries.
423 	set_image_flags_recursively(gProgramImage, RTLD_GLOBAL);
424 
425 	status = relocate_dependencies(gProgramImage);
426 	if (status < B_OK)
427 		goto err;
428 
429 	inject_runtime_loader_api(gProgramImage);
430 
431 	remap_images();
432 	init_dependencies(gProgramImage, true);
433 
434 	// Since the images are initialized now, we no longer should use our
435 	// getenv(), but use the one from libroot.so
436 	find_symbol_breadth_first(gProgramImage,
437 		SymbolLookupInfo("getenv", B_SYMBOL_TYPE_TEXT), &image,
438 		(void**)&gGetEnv);
439 
440 	if (gProgramImage->entry_point == 0) {
441 		status = B_NOT_AN_EXECUTABLE;
442 		goto err;
443 	}
444 
445 	*_entry = (void *)(gProgramImage->entry_point);
446 
447 	rld_unlock();
448 
449 	gProgramLoaded = true;
450 
451 	KTRACE("rld: load_program(\"%s\") done: entry: %p, id: %ld", path,
452 		*_entry, gProgramImage->id);
453 
454 	return gProgramImage->id;
455 
456 err:
457 	KTRACE("rld: load_program(\"%s\") failed: %s", path, strerror(status));
458 
459 	delete_image(gProgramImage);
460 
461 	if (report_errors()) {
462 		// send error message
463 		gErrorMessage.AddInt32("error", status);
464 		gErrorMessage.SetDeliveryInfo(gProgramArgs->error_token,
465 			-1, 0, find_thread(NULL));
466 
467 		_kern_write_port_etc(gProgramArgs->error_port, 'KMSG',
468 			gErrorMessage.Buffer(), gErrorMessage.ContentSize(), 0, 0);
469 	}
470 	_kern_loading_app_failed(status);
471 	rld_unlock();
472 
473 	return status;
474 }
475 
476 
477 image_id
478 load_library(char const *path, uint32 flags, bool addOn, void** _handle)
479 {
480 	image_t *image = NULL;
481 	image_type type = (addOn ? B_ADD_ON_IMAGE : B_LIBRARY_IMAGE);
482 	status_t status;
483 
484 	if (path == NULL && addOn)
485 		return B_BAD_VALUE;
486 
487 	KTRACE("rld: load_library(\"%s\", 0x%lx, %d)", path, flags, addOn);
488 
489 	rld_lock();
490 		// for now, just do stupid simple global locking
491 
492 	// have we already loaded this library?
493 	// Checking it at this stage saves loading its dependencies again
494 	if (!addOn) {
495 		// a NULL path is fine -- it means the global scope shall be opened
496 		if (path == NULL) {
497 			*_handle = RLD_GLOBAL_SCOPE;
498 			rld_unlock();
499 			return 0;
500 		}
501 
502 		image = find_loaded_image_by_name(path, APP_OR_LIBRARY_TYPE);
503 		if (image != NULL && (flags & RTLD_GLOBAL) != 0)
504 			set_image_flags_recursively(image, RTLD_GLOBAL);
505 
506 		if (image) {
507 			atomic_add(&image->ref_count, 1);
508 			rld_unlock();
509 			KTRACE("rld: load_library(\"%s\"): already loaded: %ld", path,
510 				image->id);
511 			*_handle = image;
512 			return image->id;
513 		}
514 	}
515 
516 	status = load_image(path, type, NULL, &image);
517 	if (status < B_OK) {
518 		rld_unlock();
519 		KTRACE("rld: load_library(\"%s\") failed to load container: %s", path,
520 			strerror(status));
521 		return status;
522 	}
523 
524 	if (image->find_undefined_symbol == NULL) {
525 		if (addOn)
526 			image->find_undefined_symbol = find_undefined_symbol_add_on;
527 		else
528 			image->find_undefined_symbol = find_undefined_symbol_global;
529 	}
530 
531 	status = load_dependencies(image);
532 	if (status < B_OK)
533 		goto err;
534 
535 	// If specified, set the RTLD_GLOBAL flag recursively on this image and all
536 	// dependencies. If not specified, we temporarily set
537 	// RFLAG_USE_FOR_RESOLVING so that the dependencies will correctly be used
538 	// for undefined symbol resolution.
539 	if ((flags & RTLD_GLOBAL) != 0)
540 		set_image_flags_recursively(image, RTLD_GLOBAL);
541 	else
542 		set_image_flags_recursively(image, RFLAG_USE_FOR_RESOLVING);
543 
544 	status = relocate_dependencies(image);
545 	if (status < B_OK)
546 		goto err;
547 
548 	if ((flags & RTLD_GLOBAL) == 0)
549 		clear_image_flags_recursively(image, RFLAG_USE_FOR_RESOLVING);
550 
551 	remap_images();
552 	init_dependencies(image, true);
553 
554 	rld_unlock();
555 
556 	KTRACE("rld: load_library(\"%s\") done: id: %ld", path, image->id);
557 
558 	*_handle = image;
559 	return image->id;
560 
561 err:
562 	KTRACE("rld: load_library(\"%s\") failed: %s", path, strerror(status));
563 
564 	dequeue_loaded_image(image);
565 	delete_image(image);
566 	rld_unlock();
567 	return status;
568 }
569 
570 
571 status_t
572 unload_library(void* handle, image_id imageID, bool addOn)
573 {
574 	image_t *image;
575 	image_type type = addOn ? B_ADD_ON_IMAGE : B_LIBRARY_IMAGE;
576 
577 	if (handle == NULL && imageID < 0)
578 		return B_BAD_IMAGE_ID;
579 
580 	if (handle == RLD_GLOBAL_SCOPE)
581 		return B_OK;
582 
583 	rld_lock();
584 		// for now, just do stupid simple global locking
585 
586 	if (gInvalidImageIDs) {
587 		// After fork, we lazily rebuild the image IDs of all loaded images
588 		update_image_ids();
589 	}
590 
591 	// we only check images that have been already initialized
592 
593 	status_t status = B_BAD_IMAGE_ID;
594 
595 	if (handle != NULL) {
596 		image = (image_t*)handle;
597 		put_image(image);
598 		status = B_OK;
599 	} else {
600 		image = find_loaded_image_by_id(imageID, true);
601 		if (image != NULL) {
602 			// unload image
603 			if (type == image->type) {
604 				put_image(image);
605 				status = B_OK;
606 			} else
607 				status = B_BAD_VALUE;
608 		}
609 	}
610 
611 	if (status == B_OK) {
612 		while ((image = get_disposable_images().head) != NULL) {
613 			// call image fini here...
614 			if (gRuntimeLoader.call_atexit_hooks_for_range) {
615 				gRuntimeLoader.call_atexit_hooks_for_range(
616 					image->regions[0].vmstart, image->regions[0].vmsize);
617 			}
618 
619 			image_event(image, IMAGE_EVENT_UNINITIALIZING);
620 
621 			if (image->term_routine)
622 				((init_term_function)image->term_routine)(image->id);
623 
624 			dequeue_disposable_image(image);
625 			unmap_image(image);
626 
627 			image_event(image, IMAGE_EVENT_UNLOADING);
628 
629 			delete_image(image);
630 		}
631 	}
632 
633 	rld_unlock();
634 	return status;
635 }
636 
637 
638 status_t
639 get_nth_symbol(image_id imageID, int32 num, char *nameBuffer,
640 	int32 *_nameLength, int32 *_type, void **_location)
641 {
642 	int32 count = 0, j;
643 	uint32 i;
644 	image_t *image;
645 
646 	rld_lock();
647 
648 	// get the image from those who have been already initialized
649 	image = find_loaded_image_by_id(imageID, false);
650 	if (image == NULL) {
651 		rld_unlock();
652 		return B_BAD_IMAGE_ID;
653 	}
654 
655 	// iterate through all the hash buckets until we've found the one
656 	for (i = 0; i < HASHTABSIZE(image); i++) {
657 		for (j = HASHBUCKETS(image)[i]; j != STN_UNDEF; j = HASHCHAINS(image)[j]) {
658 			struct Elf32_Sym *symbol = &image->syms[j];
659 
660 			if (count == num) {
661 				const char* symbolName = SYMNAME(image, symbol);
662 				strlcpy(nameBuffer, symbolName, *_nameLength);
663 				*_nameLength = strlen(symbolName);
664 
665 				void* location = (void*)(symbol->st_value
666 					+ image->regions[0].delta);
667 				int32 type;
668 				if (ELF32_ST_TYPE(symbol->st_info) == STT_FUNC)
669 					type = B_SYMBOL_TYPE_TEXT;
670 				else if (ELF32_ST_TYPE(symbol->st_info) == STT_OBJECT)
671 					type = B_SYMBOL_TYPE_DATA;
672 				else
673 					type = B_SYMBOL_TYPE_ANY;
674 					// TODO: check with the return types of that BeOS function
675 
676 				patch_defined_symbol(image, symbolName, &location, &type);
677 
678 				if (_type != NULL)
679 					*_type = type;
680 				if (_location != NULL)
681 					*_location = location;
682 				goto out;
683 			}
684 			count++;
685 		}
686 	}
687 out:
688 	rld_unlock();
689 
690 	if (num != count)
691 		return B_BAD_INDEX;
692 
693 	return B_OK;
694 }
695 
696 
697 status_t
698 get_symbol(image_id imageID, char const *symbolName, int32 symbolType,
699 	bool recursive, image_id *_inImage, void **_location)
700 {
701 	status_t status = B_OK;
702 	image_t *image;
703 
704 	if (imageID < B_OK)
705 		return B_BAD_IMAGE_ID;
706 	if (symbolName == NULL)
707 		return B_BAD_VALUE;
708 
709 	rld_lock();
710 		// for now, just do stupid simple global locking
711 
712 	// get the image from those who have been already initialized
713 	image = find_loaded_image_by_id(imageID, false);
714 	if (image != NULL) {
715 		if (recursive) {
716 			// breadth-first search in the given image and its dependencies
717 			status = find_symbol_breadth_first(image,
718 				SymbolLookupInfo(symbolName, symbolType, NULL,
719 					LOOKUP_FLAG_DEFAULT_VERSION),
720 				&image, _location);
721 		} else {
722 			status = find_symbol(image,
723 				SymbolLookupInfo(symbolName, symbolType, NULL,
724 					LOOKUP_FLAG_DEFAULT_VERSION),
725 				_location);
726 		}
727 
728 		if (status == B_OK && _inImage != NULL)
729 			*_inImage = image->id;
730 	} else
731 		status = B_BAD_IMAGE_ID;
732 
733 	rld_unlock();
734 	return status;
735 }
736 
737 
738 status_t
739 get_library_symbol(void* handle, void* caller, const char* symbolName,
740 	void **_location)
741 {
742 	status_t status = B_ENTRY_NOT_FOUND;
743 
744 	if (symbolName == NULL)
745 		return B_BAD_VALUE;
746 
747 	rld_lock();
748 		// for now, just do stupid simple global locking
749 
750 	if (handle == RTLD_DEFAULT || handle == RLD_GLOBAL_SCOPE) {
751 		// look in the default scope
752 		image_t* image;
753 		Elf32_Sym* symbol = find_undefined_symbol_global(gProgramImage,
754 			gProgramImage,
755 			SymbolLookupInfo(symbolName, B_SYMBOL_TYPE_ANY, NULL,
756 				LOOKUP_FLAG_DEFAULT_VERSION),
757 			&image);
758 		if (symbol != NULL) {
759 			*_location = (void*)(symbol->st_value + image->regions[0].delta);
760 			int32 symbolType = ELF32_ST_TYPE(symbol->st_info) == STT_FUNC
761 				? B_SYMBOL_TYPE_TEXT : B_SYMBOL_TYPE_DATA;
762 			patch_defined_symbol(image, symbolName, _location, &symbolType);
763 			status = B_OK;
764 		}
765 	} else if (handle == RTLD_NEXT) {
766 		// Look in the default scope, but also in the dependencies of the
767 		// calling image. Return the next after the caller symbol.
768 
769 		// First of all, find the caller image.
770 		image_t* callerImage = get_loaded_images().head;
771 		for (; callerImage != NULL; callerImage = callerImage->next) {
772 			elf_region_t& text = callerImage->regions[0];
773 			if ((addr_t)caller >= text.vmstart
774 				&& (addr_t)caller < text.vmstart + text.vmsize) {
775 				// found the image
776 				break;
777 			}
778 		}
779 
780 		if (callerImage != NULL) {
781 			// found the caller -- now search the global scope until we find
782 			// the next symbol
783 			bool hitCallerImage = false;
784 			set_image_flags_recursively(callerImage, RFLAG_USE_FOR_RESOLVING);
785 
786 			image_t* image = get_loaded_images().head;
787 			for (; image != NULL; image = image->next) {
788 				// skip the caller image
789 				if (image == callerImage) {
790 					hitCallerImage = true;
791 					continue;
792 				}
793 
794 				// skip all images up to the caller image; also skip add-on
795 				// images and those not marked above for resolution
796 				if (!hitCallerImage || image->type == B_ADD_ON_IMAGE
797 					|| (image->flags
798 						& (RTLD_GLOBAL | RFLAG_USE_FOR_RESOLVING)) == 0) {
799 					continue;
800 				}
801 
802 				struct Elf32_Sym *symbol = find_symbol(image,
803 					SymbolLookupInfo(symbolName, B_SYMBOL_TYPE_TEXT, NULL,
804 						LOOKUP_FLAG_DEFAULT_VERSION));
805 				if (symbol == NULL)
806 					continue;
807 
808 				// found the symbol
809 				*_location = (void*)(symbol->st_value
810 					+ image->regions[0].delta);
811 				int32 symbolType = B_SYMBOL_TYPE_TEXT;
812 				patch_defined_symbol(image, symbolName, _location,
813 					&symbolType);
814 				status = B_OK;
815 				break;
816 			}
817 
818 			clear_image_flags_recursively(callerImage, RFLAG_USE_FOR_RESOLVING);
819 		}
820 	} else {
821 		// breadth-first search in the given image and its dependencies
822 		image_t* inImage;
823 		status = find_symbol_breadth_first((image_t*)handle,
824 			SymbolLookupInfo(symbolName, B_SYMBOL_TYPE_ANY, NULL,
825 				LOOKUP_FLAG_DEFAULT_VERSION),
826 			&inImage, _location);
827 	}
828 
829 	rld_unlock();
830 	return status;
831 }
832 
833 
834 status_t
835 get_next_image_dependency(image_id id, uint32 *cookie, const char **_name)
836 {
837 	uint32 i, j, searchIndex = *cookie;
838 	struct Elf32_Dyn *dynamicSection;
839 	image_t *image;
840 
841 	if (_name == NULL)
842 		return B_BAD_VALUE;
843 
844 	rld_lock();
845 
846 	image = find_loaded_image_by_id(id, false);
847 	if (image == NULL) {
848 		rld_unlock();
849 		return B_BAD_IMAGE_ID;
850 	}
851 
852 	dynamicSection = (struct Elf32_Dyn *)image->dynamic_ptr;
853 	if (dynamicSection == NULL || image->num_needed <= searchIndex) {
854 		rld_unlock();
855 		return B_ENTRY_NOT_FOUND;
856 	}
857 
858 	for (i = 0, j = 0; dynamicSection[i].d_tag != DT_NULL; i++) {
859 		if (dynamicSection[i].d_tag != DT_NEEDED)
860 			continue;
861 
862 		if (j++ == searchIndex) {
863 			int32 neededOffset = dynamicSection[i].d_un.d_val;
864 
865 			*_name = STRING(image, neededOffset);
866 			*cookie = searchIndex + 1;
867 			rld_unlock();
868 			return B_OK;
869 		}
870 	}
871 
872 	rld_unlock();
873 	return B_ENTRY_NOT_FOUND;
874 }
875 
876 
877 //	#pragma mark - runtime_loader private exports
878 
879 
880 /*! Read and verify the ELF header */
881 status_t
882 elf_verify_header(void *header, int32 length)
883 {
884 	int32 programSize, sectionSize;
885 
886 	if (length < (int32)sizeof(struct Elf32_Ehdr))
887 		return B_NOT_AN_EXECUTABLE;
888 
889 	return parse_elf_header((struct Elf32_Ehdr *)header, &programSize,
890 		&sectionSize);
891 }
892 
893 
894 void
895 terminate_program(void)
896 {
897 	image_t **termList;
898 	ssize_t count, i;
899 
900 	count = get_sorted_image_list(gProgramImage, &termList, RFLAG_TERMINATED);
901 	if (count < B_OK)
902 		return;
903 
904 	if (gInvalidImageIDs) {
905 		// After fork, we lazily rebuild the image IDs of all loaded images
906 		update_image_ids();
907 	}
908 
909 	TRACE(("%ld: terminate dependencies\n", find_thread(NULL)));
910 	for (i = count; i-- > 0;) {
911 		image_t *image = termList[i];
912 
913 		TRACE(("%ld:  term: %s\n", find_thread(NULL), image->name));
914 
915 		image_event(image, IMAGE_EVENT_UNINITIALIZING);
916 
917 		if (image->term_routine)
918 			((init_term_function)image->term_routine)(image->id);
919 
920 		image_event(image, IMAGE_EVENT_UNLOADING);
921 	}
922 	TRACE(("%ld:  term done.\n", find_thread(NULL)));
923 
924 	free(termList);
925 }
926 
927 
928 void
929 rldelf_init(void)
930 {
931 	recursive_lock_init(&sLock, "runtime loader");
932 
933 	init_add_ons();
934 
935 	// create the debug area
936 	{
937 		int32 size = TO_PAGE_SIZE(sizeof(runtime_loader_debug_area));
938 
939 		runtime_loader_debug_area *area;
940 		area_id areaID = _kern_create_area(RUNTIME_LOADER_DEBUG_AREA_NAME,
941 			(void **)&area, B_ANY_ADDRESS, size, B_NO_LOCK,
942 			B_READ_AREA | B_WRITE_AREA);
943 		if (areaID < B_OK) {
944 			FATAL("Failed to create debug area.\n");
945 			_kern_loading_app_failed(areaID);
946 		}
947 
948 		area->loaded_images = &get_loaded_images();
949 	}
950 
951 	// initialize error message if needed
952 	if (report_errors()) {
953 		void *buffer = malloc(1024);
954 		if (buffer == NULL)
955 			return;
956 
957 		gErrorMessage.SetTo(buffer, 1024, 'Rler');
958 	}
959 }
960 
961 
962 status_t
963 elf_reinit_after_fork(void)
964 {
965 	status_t error = recursive_lock_init(&sLock, "runtime loader");
966 	if (error != B_OK)
967 		return error;
968 
969 	// We also need to update the IDs of our images. We are the child and
970 	// and have cloned images with different IDs. Since in most cases (fork()
971 	// + exec*()) this would just increase the fork() overhead with no one
972 	// caring, we do that lazily, when first doing something different.
973 	gInvalidImageIDs = true;
974 
975 	return B_OK;
976 }
977