xref: /haiku/src/system/runtime_loader/elf.cpp (revision b31cb92f29fe89eaca84d173d0f70d38bf0c6a3d)
1 /*
2  * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Copyright 2003-2011, 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 <syscalls.h>
22 #include <util/kernel_cpp.h>
23 
24 #include <locks.h>
25 
26 #include "add_ons.h"
27 #include "elf_load_image.h"
28 #include "elf_symbol_lookup.h"
29 #include "elf_tls.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 	elf_dyn *d = (elf_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 	elf_dyn *d = (elf_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: %" B_PRId32 ")", 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: %" B_PRId32
108 			") failed: no memory", 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->path, &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: %" B_PRId32
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: %" B_PRId32 ") "
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: %" B_PRId32 ") "
163 			"failed: internal error", image->name, image->id);
164 		return B_ERROR;
165 	}
166 
167 	KTRACE("rld: load_dependencies(\"%s\", id: %" B_PRId32 ") done",
168 		image->name, 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 	SymbolLookupCache cache(image);
202 
203 	status_t status = arch_relocate_image(rootImage, image, &cache);
204 	if (status < B_OK) {
205 		FATAL("%s: Troubles relocating: %s\n", image->path, strerror(status));
206 		return status;
207 	}
208 
209 	_kern_image_relocated(image->id);
210 	image_event(image, IMAGE_EVENT_RELOCATED);
211 	return B_OK;
212 }
213 
214 
215 static status_t
216 relocate_dependencies(image_t *image)
217 {
218 	// get the images that still have to be relocated
219 	image_t **list;
220 	ssize_t count = get_sorted_image_list(image, &list, RFLAG_RELOCATED);
221 	if (count < B_OK)
222 		return count;
223 
224 	// relocate
225 	for (ssize_t i = 0; i < count; i++) {
226 		status_t status = relocate_image(image, list[i]);
227 		if (status < B_OK) {
228 			free(list);
229 			return status;
230 		}
231 	}
232 
233 	free(list);
234 	return B_OK;
235 }
236 
237 
238 static void
239 init_dependencies(image_t *image, bool initHead)
240 {
241 	image_t **initList;
242 	ssize_t count, i;
243 
244 	count = get_sorted_image_list(image, &initList, RFLAG_INITIALIZED);
245 	if (count <= 0)
246 		return;
247 
248 	if (!initHead) {
249 		// this removes the "calling" image
250 		image->flags &= ~RFLAG_INITIALIZED;
251 		initList[--count] = NULL;
252 	}
253 
254 	TRACE(("%ld: init dependencies\n", find_thread(NULL)));
255 	for (i = 0; i < count; i++) {
256 		image = initList[i];
257 
258 		TRACE(("%ld:  init: %s\n", find_thread(NULL), image->name));
259 
260 		if (image->preinit_array) {
261 			uint count_preinit = image->preinit_array_len / sizeof(addr_t);
262 			for (uint j = 0; j < count_preinit; j++)
263 				((init_term_function)image->preinit_array[j])(image->id);
264 		}
265 
266 		if (image->init_routine != 0)
267 			((init_term_function)image->init_routine)(image->id);
268 
269 		if (image->init_array) {
270 			uint count_init = image->init_array_len / sizeof(addr_t);
271 			for (uint j = 0; j < count_init; j++)
272 				((init_term_function)image->init_array[j])(image->id);
273 		}
274 
275 		image_event(image, IMAGE_EVENT_INITIALIZED);
276 	}
277 	TRACE(("%ld:  init done.\n", find_thread(NULL)));
278 
279 	free(initList);
280 }
281 
282 
283 static void
284 inject_runtime_loader_api(image_t* rootImage)
285 {
286 	// We patch any exported __gRuntimeLoader symbols to point to our private
287 	// API.
288 	image_t* image;
289 	void* _export;
290 	if (find_symbol_breadth_first(rootImage,
291 			SymbolLookupInfo("__gRuntimeLoader", B_SYMBOL_TYPE_DATA), &image,
292 			&_export) == B_OK) {
293 		*(void**)_export = &gRuntimeLoader;
294 	}
295 }
296 
297 
298 static status_t
299 add_preloaded_image(image_t* image)
300 {
301 	// We realloc() everytime -- not particularly efficient, but good enough for
302 	// small number of preloaded images.
303 	image_t** newArray = (image_t**)realloc(sPreloadedImages,
304 		sizeof(image_t*) * (sPreloadedImageCount + 1));
305 	if (newArray == NULL)
306 		return B_NO_MEMORY;
307 
308 	sPreloadedImages = newArray;
309 	newArray[sPreloadedImageCount++] = image;
310 
311 	return B_OK;
312 }
313 
314 
315 image_id
316 preload_image(char const* path)
317 {
318 	if (path == NULL)
319 		return B_BAD_VALUE;
320 
321 	KTRACE("rld: preload_image(\"%s\")", path);
322 
323 	image_t *image = NULL;
324 	status_t status = load_image(path, B_LIBRARY_IMAGE, NULL, NULL, &image);
325 	if (status < B_OK) {
326 		KTRACE("rld: preload_image(\"%s\") failed to load container: %s", path,
327 			strerror(status));
328 		return status;
329 	}
330 
331 	if (image->find_undefined_symbol == NULL)
332 		image->find_undefined_symbol = find_undefined_symbol_global;
333 
334 	status = load_dependencies(image);
335 	if (status < B_OK)
336 		goto err;
337 
338 	set_image_flags_recursively(image, RTLD_GLOBAL);
339 
340 	status = relocate_dependencies(image);
341 	if (status < B_OK)
342 		goto err;
343 
344 	status = add_preloaded_image(image);
345 	if (status < B_OK)
346 		goto err;
347 
348 	inject_runtime_loader_api(image);
349 
350 	remap_images();
351 	init_dependencies(image, true);
352 
353 	// if the image contains an add-on, register it
354 	runtime_loader_add_on* addOnStruct;
355 	if (find_symbol(image,
356 			SymbolLookupInfo("__gRuntimeLoaderAddOn", B_SYMBOL_TYPE_DATA),
357 			(void**)&addOnStruct) == B_OK) {
358 		add_add_on(image, addOnStruct);
359 	}
360 
361 	KTRACE("rld: preload_image(\"%s\") done: id: %" B_PRId32, path, image->id);
362 
363 	return image->id;
364 
365 err:
366 	KTRACE("rld: preload_image(\"%s\") failed: %s", path, strerror(status));
367 
368 	dequeue_loaded_image(image);
369 	delete_image(image);
370 	return status;
371 }
372 
373 
374 static void
375 preload_images()
376 {
377 	const char* imagePaths = getenv("LD_PRELOAD");
378 	if (imagePaths == NULL)
379 		return;
380 
381 	while (*imagePaths != '\0') {
382 		// find begin of image path
383 		while (*imagePaths != '\0' && isspace(*imagePaths))
384 			imagePaths++;
385 
386 		if (*imagePaths == '\0')
387 			break;
388 
389 		// find end of image path
390 		const char* imagePath = imagePaths;
391 		while (*imagePaths != '\0' && !isspace(*imagePaths))
392 			imagePaths++;
393 
394 		// extract the path
395 		char path[B_PATH_NAME_LENGTH];
396 		size_t pathLen = imagePaths - imagePath;
397 		if (pathLen > sizeof(path) - 1)
398 			continue;
399 		memcpy(path, imagePath, pathLen);
400 		path[pathLen] = '\0';
401 
402 		// load the image
403 		preload_image(path);
404 	}
405 }
406 
407 
408 //	#pragma mark - libroot.so exported functions
409 
410 
411 image_id
412 load_program(char const *path, void **_entry)
413 {
414 	status_t status;
415 	image_t *image;
416 
417 	KTRACE("rld: load_program(\"%s\")", path);
418 
419 	rld_lock();
420 		// for now, just do stupid simple global locking
421 
422 	preload_images();
423 
424 	TRACE(("rld: load %s\n", path));
425 
426 	status = load_image(path, B_APP_IMAGE, NULL, NULL, &gProgramImage);
427 	if (status < B_OK)
428 		goto err;
429 
430 	if (gProgramImage->find_undefined_symbol == NULL)
431 		gProgramImage->find_undefined_symbol = find_undefined_symbol_global;
432 
433 	status = load_dependencies(gProgramImage);
434 	if (status < B_OK)
435 		goto err;
436 
437 	// Set RTLD_GLOBAL on all libraries including the program.
438 	// This results in the desired symbol resolution for dlopen()ed libraries.
439 	set_image_flags_recursively(gProgramImage, RTLD_GLOBAL);
440 
441 	status = relocate_dependencies(gProgramImage);
442 	if (status < B_OK)
443 		goto err;
444 
445 	inject_runtime_loader_api(gProgramImage);
446 
447 	remap_images();
448 	init_dependencies(gProgramImage, true);
449 
450 	// Since the images are initialized now, we no longer should use our
451 	// getenv(), but use the one from libroot.so
452 	find_symbol_breadth_first(gProgramImage,
453 		SymbolLookupInfo("getenv", B_SYMBOL_TYPE_TEXT), &image,
454 		(void**)&gGetEnv);
455 
456 	if (gProgramImage->entry_point == 0) {
457 		status = B_NOT_AN_EXECUTABLE;
458 		goto err;
459 	}
460 
461 	*_entry = (void *)(gProgramImage->entry_point);
462 
463 	rld_unlock();
464 
465 	gProgramLoaded = true;
466 
467 	KTRACE("rld: load_program(\"%s\") done: entry: %p, id: %" B_PRId32 , path,
468 		*_entry, gProgramImage->id);
469 
470 	return gProgramImage->id;
471 
472 err:
473 	KTRACE("rld: load_program(\"%s\") failed: %s", path, strerror(status));
474 
475 	delete_image(gProgramImage);
476 
477 	if (report_errors()) {
478 		// send error message
479 		gErrorMessage.AddInt32("error", status);
480 		gErrorMessage.SetDeliveryInfo(gProgramArgs->error_token,
481 			-1, 0, find_thread(NULL));
482 
483 		_kern_write_port_etc(gProgramArgs->error_port, 'KMSG',
484 			gErrorMessage.Buffer(), gErrorMessage.ContentSize(), 0, 0);
485 	}
486 	_kern_loading_app_failed(status);
487 	rld_unlock();
488 
489 	return status;
490 }
491 
492 
493 image_id
494 load_library(char const *path, uint32 flags, bool addOn, void** _handle)
495 {
496 	image_t *image = NULL;
497 	image_type type = (addOn ? B_ADD_ON_IMAGE : B_LIBRARY_IMAGE);
498 	status_t status;
499 
500 	if (path == NULL && addOn)
501 		return B_BAD_VALUE;
502 
503 	KTRACE("rld: load_library(\"%s\", %#" B_PRIx32 ", %d)", path, flags, addOn);
504 
505 	rld_lock();
506 		// for now, just do stupid simple global locking
507 
508 	// have we already loaded this library?
509 	// Checking it at this stage saves loading its dependencies again
510 	if (!addOn) {
511 		// a NULL path is fine -- it means the global scope shall be opened
512 		if (path == NULL) {
513 			*_handle = RLD_GLOBAL_SCOPE;
514 			rld_unlock();
515 			return 0;
516 		}
517 
518 		image = find_loaded_image_by_name(path, APP_OR_LIBRARY_TYPE);
519 		if (image != NULL && (flags & RTLD_GLOBAL) != 0)
520 			set_image_flags_recursively(image, RTLD_GLOBAL);
521 
522 		if (image) {
523 			atomic_add(&image->ref_count, 1);
524 			rld_unlock();
525 			KTRACE("rld: load_library(\"%s\"): already loaded: %" B_PRId32,
526 				path, image->id);
527 			*_handle = image;
528 			return image->id;
529 		}
530 	}
531 
532 	status = load_image(path, type, NULL, NULL, &image);
533 	if (status < B_OK) {
534 		rld_unlock();
535 		KTRACE("rld: load_library(\"%s\") failed to load container: %s", path,
536 			strerror(status));
537 		return status;
538 	}
539 
540 	if (image->find_undefined_symbol == NULL) {
541 		if (addOn)
542 			image->find_undefined_symbol = find_undefined_symbol_add_on;
543 		else
544 			image->find_undefined_symbol = find_undefined_symbol_global;
545 	}
546 
547 	status = load_dependencies(image);
548 	if (status < B_OK)
549 		goto err;
550 
551 	// If specified, set the RTLD_GLOBAL flag recursively on this image and all
552 	// dependencies. If not specified, we temporarily set
553 	// RFLAG_USE_FOR_RESOLVING so that the dependencies will correctly be used
554 	// for undefined symbol resolution.
555 	if ((flags & RTLD_GLOBAL) != 0)
556 		set_image_flags_recursively(image, RTLD_GLOBAL);
557 	else
558 		set_image_flags_recursively(image, RFLAG_USE_FOR_RESOLVING);
559 
560 	status = relocate_dependencies(image);
561 	if (status < B_OK)
562 		goto err;
563 
564 	if ((flags & RTLD_GLOBAL) == 0)
565 		clear_image_flags_recursively(image, RFLAG_USE_FOR_RESOLVING);
566 
567 	remap_images();
568 	init_dependencies(image, true);
569 
570 	rld_unlock();
571 
572 	KTRACE("rld: load_library(\"%s\") done: id: %" B_PRId32, path, image->id);
573 
574 	*_handle = image;
575 	return image->id;
576 
577 err:
578 	KTRACE("rld: load_library(\"%s\") failed: %s", path, strerror(status));
579 
580 	dequeue_loaded_image(image);
581 	delete_image(image);
582 	rld_unlock();
583 	return status;
584 }
585 
586 
587 status_t
588 unload_library(void* handle, image_id imageID, bool addOn)
589 {
590 	image_t *image;
591 	image_type type = addOn ? B_ADD_ON_IMAGE : B_LIBRARY_IMAGE;
592 
593 	if (handle == NULL && imageID < 0)
594 		return B_BAD_IMAGE_ID;
595 
596 	if (handle == RLD_GLOBAL_SCOPE)
597 		return B_OK;
598 
599 	rld_lock();
600 		// for now, just do stupid simple global locking
601 
602 	if (gInvalidImageIDs) {
603 		// After fork, we lazily rebuild the image IDs of all loaded images
604 		update_image_ids();
605 	}
606 
607 	// we only check images that have been already initialized
608 
609 	status_t status = B_BAD_IMAGE_ID;
610 
611 	if (handle != NULL) {
612 		image = (image_t*)handle;
613 		put_image(image);
614 		status = B_OK;
615 	} else {
616 		image = find_loaded_image_by_id(imageID, true);
617 		if (image != NULL) {
618 			// unload image
619 			if (type == image->type) {
620 				put_image(image);
621 				status = B_OK;
622 			} else
623 				status = B_BAD_VALUE;
624 		}
625 	}
626 
627 	if (status == B_OK) {
628 		while ((image = get_disposable_images().head) != NULL) {
629 			// Call the exit hooks that live in this image.
630 			// Note: With the Itanium ABI this shouldn't really be done this
631 			// way anymore, since global destructors are registered via
632 			// __cxa_atexit() (the ones that are registered dynamically) and the
633 			// termination routine should call __cxa_finalize() for the image.
634 			// The reason why we still do it is that hooks registered with
635 			// atexit() aren't associated with the image. We could find out
636 			// there which image the hooks lives in and register it
637 			// respectively, but since that would be done always, that's
638 			// probably more expensive than calling
639 			// call_atexit_hooks_for_range() only here, which happens only when
640 			// libraries are unloaded dynamically.
641 			if (gRuntimeLoader.call_atexit_hooks_for_range) {
642 				gRuntimeLoader.call_atexit_hooks_for_range(
643 					image->regions[0].vmstart, image->regions[0].vmsize);
644 			}
645 
646 			image_event(image, IMAGE_EVENT_UNINITIALIZING);
647 
648 			if (image->term_array) {
649 				uint count_term = image->term_array_len / sizeof(addr_t);
650 				for (uint i = count_term; i-- > 0;)
651 					((init_term_function)image->term_array[i])(image->id);
652 			}
653 
654 			if (image->term_routine)
655 				((init_term_function)image->term_routine)(image->id);
656 
657 			TLSBlockTemplates::Get().Unregister(image->dso_tls_id);
658 
659 			dequeue_disposable_image(image);
660 			unmap_image(image);
661 
662 			image_event(image, IMAGE_EVENT_UNLOADING);
663 
664 			delete_image(image);
665 		}
666 	}
667 
668 	rld_unlock();
669 	return status;
670 }
671 
672 
673 status_t
674 get_nth_symbol(image_id imageID, int32 num, char *nameBuffer,
675 	int32 *_nameLength, int32 *_type, void **_location)
676 {
677 	int32 count = 0, j;
678 	uint32 i;
679 	image_t *image;
680 
681 	rld_lock();
682 
683 	// get the image from those who have been already initialized
684 	image = find_loaded_image_by_id(imageID, false);
685 	if (image == NULL) {
686 		rld_unlock();
687 		return B_BAD_IMAGE_ID;
688 	}
689 
690 	// iterate through all the hash buckets until we've found the one
691 	for (i = 0; i < HASHTABSIZE(image); i++) {
692 		for (j = HASHBUCKETS(image)[i]; j != STN_UNDEF; j = HASHCHAINS(image)[j]) {
693 			elf_sym *symbol = &image->syms[j];
694 
695 			if (count == num) {
696 				const char* symbolName = SYMNAME(image, symbol);
697 				strlcpy(nameBuffer, symbolName, *_nameLength);
698 				*_nameLength = strlen(symbolName);
699 
700 				void* location = (void*)(symbol->st_value
701 					+ image->regions[0].delta);
702 				int32 type;
703 				if (symbol->Type() == STT_FUNC)
704 					type = B_SYMBOL_TYPE_TEXT;
705 				else if (symbol->Type() == STT_OBJECT)
706 					type = B_SYMBOL_TYPE_DATA;
707 				else
708 					type = B_SYMBOL_TYPE_ANY;
709 					// TODO: check with the return types of that BeOS function
710 
711 				patch_defined_symbol(image, symbolName, &location, &type);
712 
713 				if (_type != NULL)
714 					*_type = type;
715 				if (_location != NULL)
716 					*_location = location;
717 				goto out;
718 			}
719 			count++;
720 		}
721 	}
722 out:
723 	rld_unlock();
724 
725 	if (num != count)
726 		return B_BAD_INDEX;
727 
728 	return B_OK;
729 }
730 
731 
732 status_t
733 get_nearest_symbol_at_address(void* address, image_id* _imageID,
734 	char** _imagePath, char** _imageName, char** _symbolName, int32* _type,
735 	void** _location, bool* _exactMatch)
736 {
737 	rld_lock();
738 
739 	image_t* image = find_loaded_image_by_address((addr_t)address);
740 	if (image == NULL) {
741 		rld_unlock();
742 		return B_BAD_VALUE;
743 	}
744 
745 	bool exactMatch = false;
746 	elf_sym* foundSymbol = NULL;
747 	addr_t foundLocation = (addr_t)NULL;
748 
749 	for (uint32 i = 0; i < HASHTABSIZE(image) && !exactMatch; i++) {
750 		for (int32 j = HASHBUCKETS(image)[i]; j != STN_UNDEF;
751 				j = HASHCHAINS(image)[j]) {
752 			elf_sym *symbol = &image->syms[j];
753 			addr_t location = symbol->st_value + image->regions[0].delta;
754 
755 			if (location <= (addr_t)address	&& location >= foundLocation) {
756 				foundSymbol = symbol;
757 				foundLocation = location;
758 
759 				// jump out if we have an exact match
760 				if (location + symbol->st_size > (addr_t)address) {
761 					exactMatch = true;
762 					break;
763 				}
764 			}
765 		}
766 	}
767 
768 	if (_imageID != NULL)
769 		*_imageID = image->id;
770 	if (_imagePath != NULL)
771 		*_imagePath = image->path;
772 	if (_imageName != NULL)
773 		*_imageName = image->name;
774 	if (_exactMatch != NULL)
775 		*_exactMatch = exactMatch;
776 
777 	if (foundSymbol != NULL) {
778 		*_symbolName = SYMNAME(image, foundSymbol);
779 
780 		if (_type != NULL) {
781 			if (foundSymbol->Type() == STT_FUNC)
782 				*_type = B_SYMBOL_TYPE_TEXT;
783 			else if (foundSymbol->Type() == STT_OBJECT)
784 				*_type = B_SYMBOL_TYPE_DATA;
785 			else
786 				*_type = B_SYMBOL_TYPE_ANY;
787 			// TODO: check with the return types of that BeOS function
788 		}
789 
790 		if (_location != NULL)
791 			*_location = (void*)foundLocation;
792 	} else {
793 		*_symbolName = NULL;
794 		if (_location != NULL)
795 			*_location = NULL;
796 	}
797 
798 	rld_unlock();
799 	return B_OK;
800 }
801 
802 
803 status_t
804 get_symbol(image_id imageID, char const *symbolName, int32 symbolType,
805 	bool recursive, image_id *_inImage, void **_location)
806 {
807 	status_t status = B_OK;
808 	image_t *image;
809 
810 	if (imageID < B_OK)
811 		return B_BAD_IMAGE_ID;
812 	if (symbolName == NULL)
813 		return B_BAD_VALUE;
814 
815 	rld_lock();
816 		// for now, just do stupid simple global locking
817 
818 	// get the image from those who have been already initialized
819 	image = find_loaded_image_by_id(imageID, false);
820 	if (image != NULL) {
821 		if (recursive) {
822 			// breadth-first search in the given image and its dependencies
823 			status = find_symbol_breadth_first(image,
824 				SymbolLookupInfo(symbolName, symbolType, NULL,
825 					LOOKUP_FLAG_DEFAULT_VERSION),
826 				&image, _location);
827 		} else {
828 			status = find_symbol(image,
829 				SymbolLookupInfo(symbolName, symbolType, NULL,
830 					LOOKUP_FLAG_DEFAULT_VERSION),
831 				_location);
832 		}
833 
834 		if (status == B_OK && _inImage != NULL)
835 			*_inImage = image->id;
836 	} else
837 		status = B_BAD_IMAGE_ID;
838 
839 	rld_unlock();
840 	return status;
841 }
842 
843 
844 status_t
845 get_library_symbol(void* handle, void* caller, const char* symbolName,
846 	void **_location)
847 {
848 	status_t status = B_ENTRY_NOT_FOUND;
849 
850 	if (symbolName == NULL)
851 		return B_BAD_VALUE;
852 
853 	rld_lock();
854 		// for now, just do stupid simple global locking
855 
856 	if (handle == RTLD_DEFAULT || handle == RLD_GLOBAL_SCOPE) {
857 		// look in the default scope
858 		image_t* image;
859 		elf_sym* symbol = find_undefined_symbol_global(gProgramImage,
860 			gProgramImage,
861 			SymbolLookupInfo(symbolName, B_SYMBOL_TYPE_ANY, NULL,
862 				LOOKUP_FLAG_DEFAULT_VERSION),
863 			&image);
864 		if (symbol != NULL) {
865 			*_location = (void*)(symbol->st_value + image->regions[0].delta);
866 			int32 symbolType = symbol->Type() == STT_FUNC
867 				? B_SYMBOL_TYPE_TEXT : B_SYMBOL_TYPE_DATA;
868 			patch_defined_symbol(image, symbolName, _location, &symbolType);
869 			status = B_OK;
870 		}
871 	} else if (handle == RTLD_NEXT) {
872 		// Look in the default scope, but also in the dependencies of the
873 		// calling image. Return the next after the caller symbol.
874 
875 		// First of all, find the caller image.
876 		image_t* callerImage = get_loaded_images().head;
877 		for (; callerImage != NULL; callerImage = callerImage->next) {
878 			elf_region_t& text = callerImage->regions[0];
879 			if ((addr_t)caller >= text.vmstart
880 				&& (addr_t)caller < text.vmstart + text.vmsize) {
881 				// found the image
882 				break;
883 			}
884 		}
885 
886 		if (callerImage != NULL) {
887 			// found the caller -- now search the global scope until we find
888 			// the next symbol
889 			bool hitCallerImage = false;
890 			set_image_flags_recursively(callerImage, RFLAG_USE_FOR_RESOLVING);
891 
892 			elf_sym* candidateSymbol = NULL;
893 			image_t* candidateImage = NULL;
894 
895 			image_t* image = get_loaded_images().head;
896 			for (; image != NULL; image = image->next) {
897 				// skip the caller image
898 				if (image == callerImage) {
899 					hitCallerImage = true;
900 					continue;
901 				}
902 
903 				// skip all images up to the caller image; also skip add-on
904 				// images and those not marked above for resolution
905 				if (!hitCallerImage || image->type == B_ADD_ON_IMAGE
906 					|| (image->flags
907 						& (RTLD_GLOBAL | RFLAG_USE_FOR_RESOLVING)) == 0) {
908 					continue;
909 				}
910 
911 				elf_sym *symbol = find_symbol(image,
912 					SymbolLookupInfo(symbolName, B_SYMBOL_TYPE_TEXT, NULL,
913 						LOOKUP_FLAG_DEFAULT_VERSION));
914 				if (symbol == NULL)
915 					continue;
916 
917 				// found a symbol
918 				bool isWeak = symbol->Bind() == STB_WEAK;
919 				if (candidateImage == NULL || !isWeak) {
920 					candidateSymbol = symbol;
921 					candidateImage = image;
922 
923 					if (!isWeak)
924 						break;
925 				}
926 
927 				// symbol is weak, so we need to continue
928 			}
929 
930 			if (candidateSymbol != NULL) {
931 				// found the symbol
932 				*_location = (void*)(candidateSymbol->st_value
933 					+ candidateImage->regions[0].delta);
934 				int32 symbolType = B_SYMBOL_TYPE_TEXT;
935 				patch_defined_symbol(candidateImage, symbolName, _location,
936 					&symbolType);
937 				status = B_OK;
938 			}
939 
940 			clear_image_flags_recursively(callerImage, RFLAG_USE_FOR_RESOLVING);
941 		}
942 	} else {
943 		// breadth-first search in the given image and its dependencies
944 		image_t* inImage;
945 		status = find_symbol_breadth_first((image_t*)handle,
946 			SymbolLookupInfo(symbolName, B_SYMBOL_TYPE_ANY, NULL,
947 				LOOKUP_FLAG_DEFAULT_VERSION),
948 			&inImage, _location);
949 	}
950 
951 	rld_unlock();
952 	return status;
953 }
954 
955 
956 status_t
957 get_next_image_dependency(image_id id, uint32 *cookie, const char **_name)
958 {
959 	uint32 i, j, searchIndex = *cookie;
960 	elf_dyn *dynamicSection;
961 	image_t *image;
962 
963 	if (_name == NULL)
964 		return B_BAD_VALUE;
965 
966 	rld_lock();
967 
968 	image = find_loaded_image_by_id(id, false);
969 	if (image == NULL) {
970 		rld_unlock();
971 		return B_BAD_IMAGE_ID;
972 	}
973 
974 	dynamicSection = (elf_dyn *)image->dynamic_ptr;
975 	if (dynamicSection == NULL || image->num_needed <= searchIndex) {
976 		rld_unlock();
977 		return B_ENTRY_NOT_FOUND;
978 	}
979 
980 	for (i = 0, j = 0; dynamicSection[i].d_tag != DT_NULL; i++) {
981 		if (dynamicSection[i].d_tag != DT_NEEDED)
982 			continue;
983 
984 		if (j++ == searchIndex) {
985 			int32 neededOffset = dynamicSection[i].d_un.d_val;
986 
987 			*_name = STRING(image, neededOffset);
988 			*cookie = searchIndex + 1;
989 			rld_unlock();
990 			return B_OK;
991 		}
992 	}
993 
994 	rld_unlock();
995 	return B_ENTRY_NOT_FOUND;
996 }
997 
998 
999 //	#pragma mark - runtime_loader private exports
1000 
1001 
1002 /*! Read and verify the ELF header */
1003 status_t
1004 elf_verify_header(void *header, size_t length)
1005 {
1006 	int32 programSize, sectionSize;
1007 
1008 	if (length < sizeof(elf_ehdr))
1009 		return B_NOT_AN_EXECUTABLE;
1010 
1011 	return parse_elf_header((elf_ehdr *)header, &programSize, &sectionSize);
1012 }
1013 
1014 
1015 #ifdef _COMPAT_MODE
1016 #ifdef __x86_64__
1017 status_t
1018 elf32_verify_header(void *header, size_t length)
1019 {
1020 	int32 programSize, sectionSize;
1021 
1022 	if (length < sizeof(Elf32_Ehdr))
1023 		return B_NOT_AN_EXECUTABLE;
1024 
1025 	return parse_elf32_header((Elf32_Ehdr *)header, &programSize, &sectionSize);
1026 }
1027 #else
1028 status_t
1029 elf64_verify_header(void *header, size_t length)
1030 {
1031 	int32 programSize, sectionSize;
1032 
1033 	if (length < sizeof(Elf64_Ehdr))
1034 		return B_NOT_AN_EXECUTABLE;
1035 
1036 	return parse_elf64_header((Elf64_Ehdr *)header, &programSize, &sectionSize);
1037 }
1038 #endif	// __x86_64__
1039 #endif	// _COMPAT_MODE
1040 
1041 
1042 void
1043 terminate_program(void)
1044 {
1045 	image_t **termList;
1046 	ssize_t count, i;
1047 
1048 	count = get_sorted_image_list(NULL, &termList, RFLAG_TERMINATED);
1049 	if (count < B_OK)
1050 		return;
1051 
1052 	if (gInvalidImageIDs) {
1053 		// After fork, we lazily rebuild the image IDs of all loaded images
1054 		update_image_ids();
1055 	}
1056 
1057 	TRACE(("%ld: terminate dependencies\n", find_thread(NULL)));
1058 	for (i = count; i-- > 0;) {
1059 		image_t *image = termList[i];
1060 
1061 		TRACE(("%ld:  term: %s\n", find_thread(NULL), image->name));
1062 
1063 		image_event(image, IMAGE_EVENT_UNINITIALIZING);
1064 
1065 		if (image->term_array) {
1066 			uint count_term = image->term_array_len / sizeof(addr_t);
1067 			for (uint j = count_term; j-- > 0;)
1068 				((init_term_function)image->term_array[j])(image->id);
1069 		}
1070 
1071 		if (image->term_routine)
1072 			((init_term_function)image->term_routine)(image->id);
1073 
1074 		image_event(image, IMAGE_EVENT_UNLOADING);
1075 	}
1076 	TRACE(("%ld:  term done.\n", find_thread(NULL)));
1077 
1078 	free(termList);
1079 }
1080 
1081 
1082 void
1083 rldelf_init(void)
1084 {
1085 	init_add_ons();
1086 
1087 	// create the debug area
1088 	{
1089 		size_t size = TO_PAGE_SIZE(sizeof(runtime_loader_debug_area));
1090 
1091 		runtime_loader_debug_area *area;
1092 		area_id areaID = _kern_create_area(RUNTIME_LOADER_DEBUG_AREA_NAME,
1093 			(void **)&area, B_RANDOMIZED_ANY_ADDRESS, size, B_NO_LOCK,
1094 			B_READ_AREA | B_WRITE_AREA);
1095 		if (areaID < B_OK) {
1096 			FATAL("Failed to create debug area.\n");
1097 			_kern_loading_app_failed(areaID);
1098 		}
1099 
1100 		area->loaded_images = &get_loaded_images();
1101 	}
1102 
1103 	// initialize error message if needed
1104 	if (report_errors()) {
1105 		void *buffer = malloc(1024);
1106 		if (buffer == NULL)
1107 			return;
1108 
1109 		gErrorMessage.SetTo(buffer, 1024, 'Rler');
1110 	}
1111 }
1112 
1113 
1114 status_t
1115 elf_reinit_after_fork(void)
1116 {
1117 	recursive_lock_init(&sLock, kLockName);
1118 
1119 	// We also need to update the IDs of our images. We are the child and
1120 	// and have cloned images with different IDs. Since in most cases (fork()
1121 	// + exec*()) this would just increase the fork() overhead with no one
1122 	// caring, we do that lazily, when first doing something different.
1123 	gInvalidImageIDs = true;
1124 
1125 	return B_OK;
1126 }
1127