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