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