1/*
2 * Copyright 2018, J��r��me Duval, jerome.duval@gmail.com.
3 * Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
4 * Copyright 2002-2009, Axel D��rfler, axeld@pinc-software.de.
5 * Distributed under the terms of the MIT License.
6 *
7 * Copyright 2001, Travis Geiselbrecht. All rights reserved.
8 * Distributed under the terms of the NewOS License.
9 */
10
11/*!	Contains the ELF loader */
12
13
14#include <elf.h>
15
16#include <OS.h>
17
18#include <unistd.h>
19#include <stdlib.h>
20#include <string.h>
21#include <stdio.h>
22#include <ctype.h>
23
24#include <algorithm>
25
26#include <AutoDeleter.h>
27#include <BytePointer.h>
28#include <commpage.h>
29#include <driver_settings.h>
30#include <boot/kernel_args.h>
31#include <debug.h>
32#include <image_defs.h>
33#include <kernel.h>
34#include <kimage.h>
35#include <syscalls.h>
36#include <team.h>
37#include <thread.h>
38#include <runtime_loader.h>
39#include <util/AutoLock.h>
40#include <vfs.h>
41#include <vm/vm.h>
42#include <vm/vm_types.h>
43#include <vm/VMAddressSpace.h>
44#include <vm/VMArea.h>
45
46#include <arch/cpu.h>
47#include <arch/elf.h>
48#include <elf_priv.h>
49#include <boot/elf.h>
50
51//#define TRACE_ELF
52#ifdef TRACE_ELF
53#	define TRACE(x) dprintf x
54#else
55#	define TRACE(x) ;
56#endif
57
58
59namespace {
60
61#define IMAGE_HASH_SIZE 16
62
63struct ImageHashDefinition {
64	typedef struct elf_image_info ValueType;
65	typedef image_id KeyType;
66
67	size_t Hash(ValueType* entry) const
68		{ return HashKey(entry->id); }
69	ValueType*& GetLink(ValueType* entry) const
70		{ return entry->next; }
71
72	size_t HashKey(KeyType key) const
73	{
74		return (size_t)key;
75	}
76
77	bool Compare(KeyType key, ValueType* entry) const
78	{
79		return key == entry->id;
80	}
81};
82
83typedef BOpenHashTable<ImageHashDefinition> ImageHash;
84
85} // namespace
86
87
88#ifndef ELF32_COMPAT
89
90static ImageHash *sImagesHash;
91
92static struct elf_image_info *sKernelImage = NULL;
93static mutex sImageMutex = MUTEX_INITIALIZER("kimages_lock");
94	// guards sImagesHash
95static mutex sImageLoadMutex = MUTEX_INITIALIZER("kimages_load_lock");
96	// serializes loading/unloading add-ons locking order
97	// sImageLoadMutex -> sImageMutex
98static bool sLoadElfSymbols = false;
99static bool sInitialized = false;
100
101
102static elf_sym *elf_find_symbol(struct elf_image_info *image, const char *name,
103	const elf_version_info *version, bool lookupDefault);
104
105
106static void
107unregister_elf_image(struct elf_image_info *image)
108{
109	unregister_image(team_get_kernel_team(), image->id);
110	sImagesHash->Remove(image);
111}
112
113
114static void
115register_elf_image(struct elf_image_info *image)
116{
117	extended_image_info imageInfo;
118
119	memset(&imageInfo, 0, sizeof(imageInfo));
120	imageInfo.basic_info.id = image->id;
121	imageInfo.basic_info.type = B_SYSTEM_IMAGE;
122	strlcpy(imageInfo.basic_info.name, image->name,
123		sizeof(imageInfo.basic_info.name));
124
125	imageInfo.basic_info.text = (void *)image->text_region.start;
126	imageInfo.basic_info.text_size = image->text_region.size;
127	imageInfo.basic_info.data = (void *)image->data_region.start;
128	imageInfo.basic_info.data_size = image->data_region.size;
129
130	if (image->text_region.id >= 0) {
131		// evaluate the API/ABI version symbols
132
133		// Haiku API version
134		imageInfo.basic_info.api_version = 0;
135		elf_sym* symbol = elf_find_symbol(image,
136			B_SHARED_OBJECT_HAIKU_VERSION_VARIABLE_NAME, NULL, true);
137		if (symbol != NULL && symbol->st_shndx != SHN_UNDEF
138			&& symbol->st_value > 0
139			&& symbol->Type() == STT_OBJECT
140			&& symbol->st_size >= sizeof(uint32)) {
141			addr_t symbolAddress = symbol->st_value + image->text_region.delta;
142			if (symbolAddress >= image->text_region.start
143				&& symbolAddress - image->text_region.start + sizeof(uint32)
144					<= image->text_region.size) {
145				imageInfo.basic_info.api_version = *(uint32*)symbolAddress;
146			}
147		}
148
149		// Haiku ABI
150		imageInfo.basic_info.abi = 0;
151		symbol = elf_find_symbol(image,
152			B_SHARED_OBJECT_HAIKU_ABI_VARIABLE_NAME, NULL, true);
153		if (symbol != NULL && symbol->st_shndx != SHN_UNDEF
154			&& symbol->st_value > 0
155			&& symbol->Type() == STT_OBJECT
156			&& symbol->st_size >= sizeof(uint32)) {
157			addr_t symbolAddress = symbol->st_value + image->text_region.delta;
158			if (symbolAddress >= image->text_region.start
159				&& symbolAddress - image->text_region.start + sizeof(uint32)
160					<= image->text_region.size) {
161				imageInfo.basic_info.api_version = *(uint32*)symbolAddress;
162			}
163		}
164	} else {
165		// in-memory image -- use the current values
166		imageInfo.basic_info.api_version = B_HAIKU_VERSION;
167		imageInfo.basic_info.abi = B_HAIKU_ABI;
168	}
169
170	image->id = register_image(team_get_kernel_team(), &imageInfo,
171		sizeof(imageInfo));
172	sImagesHash->Insert(image);
173}
174
175
176/*!	Note, you must lock the image mutex when you call this function. */
177static struct elf_image_info *
178find_image_at_address(addr_t address)
179{
180#if KDEBUG
181	if (!debug_debugger_running())
182		ASSERT_LOCKED_MUTEX(&sImageMutex);
183#endif
184
185	ImageHash::Iterator iterator(sImagesHash);
186
187	// get image that may contain the address
188
189	while (iterator.HasNext()) {
190		struct elf_image_info* image = iterator.Next();
191		if ((address >= image->text_region.start && address
192				<= (image->text_region.start + image->text_region.size))
193			|| (address >= image->data_region.start
194				&& address
195					<= (image->data_region.start + image->data_region.size)))
196			return image;
197	}
198
199	return NULL;
200}
201
202
203static int
204dump_address_info(int argc, char **argv)
205{
206	const char *symbol, *imageName;
207	bool exactMatch;
208	addr_t address, baseAddress;
209
210	if (argc < 2) {
211		kprintf("usage: ls <address>\n");
212		return 0;
213	}
214
215	address = strtoul(argv[1], NULL, 16);
216
217	status_t error;
218
219	if (IS_KERNEL_ADDRESS(address)) {
220		error = elf_debug_lookup_symbol_address(address, &baseAddress, &symbol,
221			&imageName, &exactMatch);
222	} else {
223		error = elf_debug_lookup_user_symbol_address(
224			debug_get_debugged_thread()->team, address, &baseAddress, &symbol,
225			&imageName, &exactMatch);
226	}
227
228	if (error == B_OK) {
229		kprintf("%p = %s + 0x%lx (%s)%s\n", (void*)address, symbol,
230			address - baseAddress, imageName, exactMatch ? "" : " (nearest)");
231	} else
232		kprintf("There is no image loaded at this address!\n");
233
234	return 0;
235}
236
237
238static struct elf_image_info *
239find_image(image_id id)
240{
241	return sImagesHash->Lookup(id);
242}
243
244
245static struct elf_image_info *
246find_image_by_vnode(void *vnode)
247{
248	MutexLocker locker(sImageMutex);
249
250	ImageHash::Iterator iterator(sImagesHash);
251	while (iterator.HasNext()) {
252		struct elf_image_info* image = iterator.Next();
253		if (image->vnode == vnode)
254			return image;
255	}
256
257	return NULL;
258}
259
260
261#endif // ELF32_COMPAT
262
263
264static struct elf_image_info *
265create_image_struct()
266{
267	struct elf_image_info *image
268		= (struct elf_image_info *)malloc(sizeof(struct elf_image_info));
269	if (image == NULL)
270		return NULL;
271
272	memset(image, 0, sizeof(struct elf_image_info));
273
274	image->text_region.id = -1;
275	image->data_region.id = -1;
276	image->ref_count = 1;
277
278	return image;
279}
280
281
282static void
283delete_elf_image(struct elf_image_info *image)
284{
285	if (image->text_region.id >= 0)
286		delete_area(image->text_region.id);
287
288	if (image->data_region.id >= 0)
289		delete_area(image->data_region.id);
290
291	if (image->vnode)
292		vfs_put_vnode(image->vnode);
293
294	free(image->versions);
295	free(image->debug_symbols);
296	free((void*)image->debug_string_table);
297	free(image->elf_header);
298	free(image->name);
299	free(image);
300}
301
302
303static uint32
304elf_hash(const char *name)
305{
306	uint32 hash = 0;
307	uint32 temp;
308
309	while (*name) {
310		hash = (hash << 4) + (uint8)*name++;
311		if ((temp = hash & 0xf0000000) != 0)
312			hash ^= temp >> 24;
313		hash &= ~temp;
314	}
315	return hash;
316}
317
318
319static const char *
320get_symbol_type_string(elf_sym *symbol)
321{
322	switch (symbol->Type()) {
323		case STT_FUNC:
324			return "func";
325		case STT_OBJECT:
326			return " obj";
327		case STT_FILE:
328			return "file";
329		default:
330			return "----";
331	}
332}
333
334
335static const char *
336get_symbol_bind_string(elf_sym *symbol)
337{
338	switch (symbol->Bind()) {
339		case STB_LOCAL:
340			return "loc ";
341		case STB_GLOBAL:
342			return "glob";
343		case STB_WEAK:
344			return "weak";
345		default:
346			return "----";
347	}
348}
349
350
351#ifndef ELF32_COMPAT
352
353
354/*!	Searches a symbol (pattern) in all kernel images */
355static int
356dump_symbol(int argc, char **argv)
357{
358	if (argc != 2 || !strcmp(argv[1], "--help")) {
359		kprintf("usage: %s <symbol-name>\n", argv[0]);
360		return 0;
361	}
362
363	struct elf_image_info *image = NULL;
364	const char *pattern = argv[1];
365
366	void* symbolAddress = NULL;
367
368	ImageHash::Iterator iterator(sImagesHash);
369	while (iterator.HasNext()) {
370		image = iterator.Next();
371		if (image->num_debug_symbols > 0) {
372			// search extended debug symbol table (contains static symbols)
373			for (uint32 i = 0; i < image->num_debug_symbols; i++) {
374				elf_sym *symbol = &image->debug_symbols[i];
375				const char *name = image->debug_string_table + symbol->st_name;
376
377				if (symbol->st_value > 0 && strstr(name, pattern) != 0) {
378					symbolAddress
379						= (void*)(symbol->st_value + image->text_region.delta);
380					kprintf("%p %5lu %s:%s\n", symbolAddress, symbol->st_size,
381						image->name, name);
382				}
383			}
384		} else {
385			// search standard symbol lookup table
386			for (uint32 i = 0; i < HASHTABSIZE(image); i++) {
387				for (uint32 j = HASHBUCKETS(image)[i]; j != STN_UNDEF;
388						j = HASHCHAINS(image)[j]) {
389					elf_sym *symbol = &image->syms[j];
390					const char *name = SYMNAME(image, symbol);
391
392					if (symbol->st_value > 0 && strstr(name, pattern) != 0) {
393						symbolAddress = (void*)(symbol->st_value
394							+ image->text_region.delta);
395						kprintf("%p %5lu %s:%s\n", symbolAddress,
396							symbol->st_size, image->name, name);
397					}
398				}
399			}
400		}
401	}
402
403	if (symbolAddress != NULL)
404		set_debug_variable("_", (addr_t)symbolAddress);
405
406	return 0;
407}
408
409
410static int
411dump_symbols(int argc, char **argv)
412{
413	struct elf_image_info *image = NULL;
414	uint32 i;
415
416	// if the argument looks like a hex number, treat it as such
417	if (argc > 1) {
418		if (isdigit(argv[1][0])) {
419			addr_t num = strtoul(argv[1], NULL, 0);
420
421			if (IS_KERNEL_ADDRESS(num)) {
422				// find image at address
423
424				ImageHash::Iterator iterator(sImagesHash);
425				while (iterator.HasNext()) {
426					elf_image_info* current = iterator.Next();
427					if (current->text_region.start <= num
428						&& current->text_region.start
429							+ current->text_region.size	>= num) {
430						image = current;
431						break;
432					}
433				}
434
435				if (image == NULL) {
436					kprintf("No image covers %#" B_PRIxADDR " in the kernel!\n",
437						num);
438				}
439			} else {
440				image = sImagesHash->Lookup(num);
441				if (image == NULL) {
442					kprintf("image %#" B_PRIxADDR " doesn't exist in the "
443						"kernel!\n", num);
444				}
445			}
446		} else {
447			// look for image by name
448			ImageHash::Iterator iterator(sImagesHash);
449			while (iterator.HasNext()) {
450				elf_image_info* current = iterator.Next();
451				if (!strcmp(current->name, argv[1])) {
452					image = current;
453					break;
454				}
455			}
456
457			if (image == NULL)
458				kprintf("No image \"%s\" found in kernel!\n", argv[1]);
459		}
460	} else {
461		kprintf("usage: %s image_name/image_id/address_in_image\n", argv[0]);
462		return 0;
463	}
464
465	if (image == NULL)
466		return -1;
467
468	// dump symbols
469
470	kprintf("Symbols of image %" B_PRId32 " \"%s\":\n", image->id, image->name);
471	kprintf("%-*s Type       Size Name\n", B_PRINTF_POINTER_WIDTH, "Address");
472
473	if (image->num_debug_symbols > 0) {
474		// search extended debug symbol table (contains static symbols)
475		for (i = 0; i < image->num_debug_symbols; i++) {
476			elf_sym *symbol = &image->debug_symbols[i];
477
478			if (symbol->st_value == 0 || symbol->st_size
479					>= image->text_region.size + image->data_region.size)
480				continue;
481
482			kprintf("%0*lx %s/%s %5ld %s\n", B_PRINTF_POINTER_WIDTH,
483				symbol->st_value + image->text_region.delta,
484				get_symbol_type_string(symbol), get_symbol_bind_string(symbol),
485				symbol->st_size, image->debug_string_table + symbol->st_name);
486		}
487	} else {
488		int32 j;
489
490		// search standard symbol lookup table
491		for (i = 0; i < HASHTABSIZE(image); i++) {
492			for (j = HASHBUCKETS(image)[i]; j != STN_UNDEF;
493					j = HASHCHAINS(image)[j]) {
494				elf_sym *symbol = &image->syms[j];
495
496				if (symbol->st_value == 0 || symbol->st_size
497						>= image->text_region.size + image->data_region.size)
498					continue;
499
500				kprintf("%08lx %s/%s %5ld %s\n",
501					symbol->st_value + image->text_region.delta,
502					get_symbol_type_string(symbol),
503					get_symbol_bind_string(symbol),
504					symbol->st_size, SYMNAME(image, symbol));
505			}
506		}
507	}
508
509	return 0;
510}
511
512
513static void
514dump_elf_region(struct elf_region *region, const char *name)
515{
516	kprintf("   %s.id %" B_PRId32 "\n", name, region->id);
517	kprintf("   %s.start %#" B_PRIxADDR "\n", name, region->start);
518	kprintf("   %s.size %#" B_PRIxSIZE "\n", name, region->size);
519	kprintf("   %s.delta %ld\n", name, region->delta);
520}
521
522
523static void
524dump_image_info(struct elf_image_info *image)
525{
526	kprintf("elf_image_info at %p:\n", image);
527	kprintf(" next %p\n", image->next);
528	kprintf(" id %" B_PRId32 "\n", image->id);
529	dump_elf_region(&image->text_region, "text");
530	dump_elf_region(&image->data_region, "data");
531	kprintf(" dynamic_section %#" B_PRIxADDR "\n", image->dynamic_section);
532	kprintf(" needed %p\n", image->needed);
533	kprintf(" symhash %p\n", image->symhash);
534	kprintf(" syms %p\n", image->syms);
535	kprintf(" strtab %p\n", image->strtab);
536	kprintf(" rel %p\n", image->rel);
537	kprintf(" rel_len %#x\n", image->rel_len);
538	kprintf(" rela %p\n", image->rela);
539	kprintf(" rela_len %#x\n", image->rela_len);
540	kprintf(" pltrel %p\n", image->pltrel);
541	kprintf(" pltrel_len %#x\n", image->pltrel_len);
542
543	kprintf(" debug_symbols %p (%" B_PRIu32 ")\n",
544		image->debug_symbols, image->num_debug_symbols);
545}
546
547
548static int
549dump_image(int argc, char **argv)
550{
551	struct elf_image_info *image;
552
553	// if the argument looks like a hex number, treat it as such
554	if (argc > 1) {
555		addr_t num = strtoul(argv[1], NULL, 0);
556
557		if (IS_KERNEL_ADDRESS(num)) {
558			// semi-hack
559			dump_image_info((struct elf_image_info *)num);
560		} else {
561			image = sImagesHash->Lookup(num);
562			if (image == NULL) {
563				kprintf("image %#" B_PRIxADDR " doesn't exist in the kernel!\n",
564					num);
565			} else
566				dump_image_info(image);
567		}
568		return 0;
569	}
570
571	kprintf("loaded kernel images:\n");
572
573	ImageHash::Iterator iterator(sImagesHash);
574
575	while (iterator.HasNext()) {
576		image = iterator.Next();
577		kprintf("%p (%" B_PRId32 ") %s\n", image, image->id, image->name);
578	}
579
580	return 0;
581}
582
583
584// Currently unused
585/*static
586void dump_symbol(struct elf_image_info *image, elf_sym *sym)
587{
588
589	kprintf("symbol at %p, in image %p\n", sym, image);
590
591	kprintf(" name index %d, '%s'\n", sym->st_name, SYMNAME(image, sym));
592	kprintf(" st_value 0x%x\n", sym->st_value);
593	kprintf(" st_size %d\n", sym->st_size);
594	kprintf(" st_info 0x%x\n", sym->st_info);
595	kprintf(" st_other 0x%x\n", sym->st_other);
596	kprintf(" st_shndx %d\n", sym->st_shndx);
597}
598*/
599
600
601#endif // ELF32_COMPAT
602
603
604static elf_sym *
605elf_find_symbol(struct elf_image_info *image, const char *name,
606	const elf_version_info *lookupVersion, bool lookupDefault)
607{
608	if (image->dynamic_section == 0 || HASHTABSIZE(image) == 0)
609		return NULL;
610
611	elf_sym* versionedSymbol = NULL;
612	uint32 versionedSymbolCount = 0;
613
614	uint32 hash = elf_hash(name) % HASHTABSIZE(image);
615	for (uint32 i = HASHBUCKETS(image)[hash]; i != STN_UNDEF;
616			i = HASHCHAINS(image)[i]) {
617		elf_sym* symbol = &image->syms[i];
618
619		// consider only symbols with the right name and binding
620		if (symbol->st_shndx == SHN_UNDEF
621			|| ((symbol->Bind() != STB_GLOBAL) && (symbol->Bind() != STB_WEAK))
622			|| strcmp(SYMNAME(image, symbol), name) != 0) {
623			continue;
624		}
625
626		// check the version
627
628		// Handle the simple cases -- the image doesn't have version
629		// information -- first.
630		if (image->symbol_versions == NULL) {
631			if (lookupVersion == NULL) {
632				// No specific symbol version was requested either, so the
633				// symbol is just fine.
634				return symbol;
635			}
636
637			// A specific version is requested. Since the only possible
638			// dependency is the kernel itself, the add-on was obviously linked
639			// against a newer kernel.
640			dprintf("Kernel add-on requires version support, but the kernel "
641				"is too old.\n");
642			return NULL;
643		}
644
645		// The image has version information. Let's see what we've got.
646		uint32 versionID = image->symbol_versions[i];
647		uint32 versionIndex = VER_NDX(versionID);
648		elf_version_info& version = image->versions[versionIndex];
649
650		// skip local versions
651		if (versionIndex == VER_NDX_LOCAL)
652			continue;
653
654		if (lookupVersion != NULL) {
655			// a specific version is requested
656
657			// compare the versions
658			if (version.hash == lookupVersion->hash
659				&& strcmp(version.name, lookupVersion->name) == 0) {
660				// versions match
661				return symbol;
662			}
663
664			// The versions don't match. We're still fine with the
665			// base version, if it is public and we're not looking for
666			// the default version.
667			if ((versionID & VER_NDX_FLAG_HIDDEN) == 0
668				&& versionIndex == VER_NDX_GLOBAL
669				&& !lookupDefault) {
670				// TODO: Revise the default version case! That's how
671				// FreeBSD implements it, but glibc doesn't handle it
672				// specially.
673				return symbol;
674			}
675		} else {
676			// No specific version requested, but the image has version
677			// information. This can happen in either of these cases:
678			//
679			// * The dependent object was linked against an older version
680			//   of the now versioned dependency.
681			// * The symbol is looked up via find_image_symbol() or dlsym().
682			//
683			// In the first case we return the base version of the symbol
684			// (VER_NDX_GLOBAL or VER_NDX_INITIAL), or, if that doesn't
685			// exist, the unique, non-hidden versioned symbol.
686			//
687			// In the second case we want to return the public default
688			// version of the symbol. The handling is pretty similar to the
689			// first case, with the exception that we treat VER_NDX_INITIAL
690			// as regular version.
691
692			// VER_NDX_GLOBAL is always good, VER_NDX_INITIAL is fine, if
693			// we don't look for the default version.
694			if (versionIndex == VER_NDX_GLOBAL
695				|| (!lookupDefault && versionIndex == VER_NDX_INITIAL)) {
696				return symbol;
697			}
698
699			// If not hidden, remember the version -- we'll return it, if
700			// it is the only one.
701			if ((versionID & VER_NDX_FLAG_HIDDEN) == 0) {
702				versionedSymbolCount++;
703				versionedSymbol = symbol;
704			}
705		}
706	}
707
708	return versionedSymbolCount == 1 ? versionedSymbol : NULL;
709}
710
711
712static status_t
713elf_parse_dynamic_section(struct elf_image_info *image)
714{
715	elf_dyn *d;
716	ssize_t neededOffset = -1;
717
718	TRACE(("top of elf_parse_dynamic_section\n"));
719
720	image->symhash = 0;
721	image->syms = 0;
722	image->strtab = 0;
723
724	d = (elf_dyn *)image->dynamic_section;
725	if (!d)
726		return B_ERROR;
727
728	for (int32 i = 0; d[i].d_tag != DT_NULL; i++) {
729		switch (d[i].d_tag) {
730			case DT_NEEDED:
731				neededOffset = d[i].d_un.d_ptr + image->text_region.delta;
732				break;
733			case DT_HASH:
734				image->symhash = (uint32 *)(d[i].d_un.d_ptr
735					+ image->text_region.delta);
736				break;
737			case DT_STRTAB:
738				image->strtab = (char *)(d[i].d_un.d_ptr
739					+ image->text_region.delta);
740				break;
741			case DT_SYMTAB:
742				image->syms = (elf_sym *)(d[i].d_un.d_ptr
743					+ image->text_region.delta);
744				break;
745			case DT_REL:
746				image->rel = (elf_rel *)(d[i].d_un.d_ptr
747					+ image->text_region.delta);
748				break;
749			case DT_RELSZ:
750				image->rel_len = d[i].d_un.d_val;
751				break;
752			case DT_RELA:
753				image->rela = (elf_rela *)(d[i].d_un.d_ptr
754					+ image->text_region.delta);
755				break;
756			case DT_RELASZ:
757				image->rela_len = d[i].d_un.d_val;
758				break;
759			case DT_JMPREL:
760				image->pltrel = (elf_rel *)(d[i].d_un.d_ptr
761					+ image->text_region.delta);
762				break;
763			case DT_PLTRELSZ:
764				image->pltrel_len = d[i].d_un.d_val;
765				break;
766			case DT_PLTREL:
767				image->pltrel_type = d[i].d_un.d_val;
768				break;
769			case DT_VERSYM:
770				image->symbol_versions = (elf_versym*)
771					(d[i].d_un.d_ptr + image->text_region.delta);
772				break;
773			case DT_VERDEF:
774				image->version_definitions = (elf_verdef*)
775					(d[i].d_un.d_ptr + image->text_region.delta);
776				break;
777			case DT_VERDEFNUM:
778				image->num_version_definitions = d[i].d_un.d_val;
779				break;
780			case DT_VERNEED:
781				image->needed_versions = (elf_verneed*)
782					(d[i].d_un.d_ptr + image->text_region.delta);
783				break;
784			case DT_VERNEEDNUM:
785				image->num_needed_versions = d[i].d_un.d_val;
786				break;
787			case DT_SYMBOLIC:
788				image->symbolic = true;
789				break;
790			case DT_FLAGS:
791			{
792				uint32 flags = d[i].d_un.d_val;
793				if ((flags & DF_SYMBOLIC) != 0)
794					image->symbolic = true;
795				break;
796			}
797
798			default:
799				continue;
800		}
801	}
802
803	// lets make sure we found all the required sections
804	if (!image->symhash || !image->syms || !image->strtab)
805		return B_ERROR;
806
807	TRACE(("needed_offset = %ld\n", neededOffset));
808
809	if (neededOffset >= 0)
810		image->needed = STRING(image, neededOffset);
811
812	return B_OK;
813}
814
815
816#ifndef ELF32_COMPAT
817
818
819static status_t
820assert_defined_image_version(elf_image_info* dependentImage,
821	elf_image_info* image, const elf_version_info& neededVersion, bool weak)
822{
823	// If the image doesn't have version definitions, we print a warning and
824	// succeed. Weird, but that's how glibc does it. Not unlikely we'll fail
825	// later when resolving versioned symbols.
826	if (image->version_definitions == NULL) {
827		dprintf("%s: No version information available (required by %s)\n",
828			image->name, dependentImage->name);
829		return B_OK;
830	}
831
832	// iterate through the defined versions to find the given one
833	BytePointer<elf_verdef> definition(image->version_definitions);
834	for (uint32 i = 0; i < image->num_version_definitions; i++) {
835		uint32 versionIndex = VER_NDX(definition->vd_ndx);
836		elf_version_info& info = image->versions[versionIndex];
837
838		if (neededVersion.hash == info.hash
839			&& strcmp(neededVersion.name, info.name) == 0) {
840			return B_OK;
841		}
842
843		definition += definition->vd_next;
844	}
845
846	// version not found -- fail, if not weak
847	if (!weak) {
848		dprintf("%s: version \"%s\" not found (required by %s)\n", image->name,
849			neededVersion.name, dependentImage->name);
850		return B_MISSING_SYMBOL;
851	}
852
853	return B_OK;
854}
855
856
857static status_t
858init_image_version_infos(elf_image_info* image)
859{
860	// First find out how many version infos we need -- i.e. get the greatest
861	// version index from the defined and needed versions (they use the same
862	// index namespace).
863	uint32 maxIndex = 0;
864
865	if (image->version_definitions != NULL) {
866		BytePointer<elf_verdef> definition(image->version_definitions);
867		for (uint32 i = 0; i < image->num_version_definitions; i++) {
868			if (definition->vd_version != 1) {
869				dprintf("Unsupported version definition revision: %u\n",
870					definition->vd_version);
871				return B_BAD_VALUE;
872			}
873
874			uint32 versionIndex = VER_NDX(definition->vd_ndx);
875			if (versionIndex > maxIndex)
876				maxIndex = versionIndex;
877
878			definition += definition->vd_next;
879		}
880	}
881
882	if (image->needed_versions != NULL) {
883		BytePointer<elf_verneed> needed(image->needed_versions);
884		for (uint32 i = 0; i < image->num_needed_versions; i++) {
885			if (needed->vn_version != 1) {
886				dprintf("Unsupported version needed revision: %u\n",
887					needed->vn_version);
888				return B_BAD_VALUE;
889			}
890
891			BytePointer<elf_vernaux> vernaux(needed + needed->vn_aux);
892			for (uint32 k = 0; k < needed->vn_cnt; k++) {
893				uint32 versionIndex = VER_NDX(vernaux->vna_other);
894				if (versionIndex > maxIndex)
895					maxIndex = versionIndex;
896
897				vernaux += vernaux->vna_next;
898			}
899
900			needed += needed->vn_next;
901		}
902	}
903
904	if (maxIndex == 0)
905		return B_OK;
906
907	// allocate the version infos
908	image->versions
909		= (elf_version_info*)malloc(sizeof(elf_version_info) * (maxIndex + 1));
910	if (image->versions == NULL) {
911		dprintf("Memory shortage in init_image_version_infos()\n");
912		return B_NO_MEMORY;
913	}
914	image->num_versions = maxIndex + 1;
915
916	// init the version infos
917
918	// version definitions
919	if (image->version_definitions != NULL) {
920		BytePointer<elf_verdef> definition(image->version_definitions);
921		for (uint32 i = 0; i < image->num_version_definitions; i++) {
922			if (definition->vd_cnt > 0
923				&& (definition->vd_flags & VER_FLG_BASE) == 0) {
924				BytePointer<elf_verdaux> verdaux(definition
925					+ definition->vd_aux);
926
927				uint32 versionIndex = VER_NDX(definition->vd_ndx);
928				elf_version_info& info = image->versions[versionIndex];
929				info.hash = definition->vd_hash;
930				info.name = STRING(image, verdaux->vda_name);
931				info.file_name = NULL;
932			}
933
934			definition += definition->vd_next;
935		}
936	}
937
938	// needed versions
939	if (image->needed_versions != NULL) {
940		BytePointer<elf_verneed> needed(image->needed_versions);
941		for (uint32 i = 0; i < image->num_needed_versions; i++) {
942			const char* fileName = STRING(image, needed->vn_file);
943
944			BytePointer<elf_vernaux> vernaux(needed + needed->vn_aux);
945			for (uint32 k = 0; k < needed->vn_cnt; k++) {
946				uint32 versionIndex = VER_NDX(vernaux->vna_other);
947				elf_version_info& info = image->versions[versionIndex];
948				info.hash = vernaux->vna_hash;
949				info.name = STRING(image, vernaux->vna_name);
950				info.file_name = fileName;
951
952				vernaux += vernaux->vna_next;
953			}
954
955			needed += needed->vn_next;
956		}
957	}
958
959	return B_OK;
960}
961
962
963static status_t
964check_needed_image_versions(elf_image_info* image)
965{
966	if (image->needed_versions == NULL)
967		return B_OK;
968
969	BytePointer<elf_verneed> needed(image->needed_versions);
970	for (uint32 i = 0; i < image->num_needed_versions; i++) {
971		elf_image_info* dependency = sKernelImage;
972
973		BytePointer<elf_vernaux> vernaux(needed + needed->vn_aux);
974		for (uint32 k = 0; k < needed->vn_cnt; k++) {
975			uint32 versionIndex = VER_NDX(vernaux->vna_other);
976			elf_version_info& info = image->versions[versionIndex];
977
978			status_t error = assert_defined_image_version(image, dependency,
979				info, (vernaux->vna_flags & VER_FLG_WEAK) != 0);
980			if (error != B_OK)
981				return error;
982
983			vernaux += vernaux->vna_next;
984		}
985
986		needed += needed->vn_next;
987	}
988
989	return B_OK;
990}
991
992
993#endif // ELF32_COMPAT
994
995
996/*!	Resolves the \a symbol by linking against \a sharedImage if necessary.
997	Returns the resolved symbol's address in \a _symbolAddress.
998*/
999status_t
1000elf_resolve_symbol(struct elf_image_info *image, elf_sym *symbol,
1001	struct elf_image_info *sharedImage, elf_addr *_symbolAddress)
1002{
1003	// Local symbols references are always resolved to the given symbol.
1004	if (symbol->Bind() == STB_LOCAL) {
1005		*_symbolAddress = symbol->st_value + image->text_region.delta;
1006		return B_OK;
1007	}
1008
1009	// Non-local symbols we try to resolve to the kernel image first. Unless
1010	// the image is linked symbolically, then vice versa.
1011	elf_image_info* firstImage = sharedImage;
1012	elf_image_info* secondImage = image;
1013	if (image->symbolic)
1014		std::swap(firstImage, secondImage);
1015
1016	const char *symbolName = SYMNAME(image, symbol);
1017
1018	// get the version info
1019	const elf_version_info* versionInfo = NULL;
1020	if (image->symbol_versions != NULL) {
1021		uint32 index = symbol - image->syms;
1022		uint32 versionIndex = VER_NDX(image->symbol_versions[index]);
1023		if (versionIndex >= VER_NDX_INITIAL)
1024			versionInfo = image->versions + versionIndex;
1025	}
1026
1027	// find the symbol
1028	elf_image_info* foundImage = firstImage;
1029	elf_sym* foundSymbol = elf_find_symbol(firstImage, symbolName, versionInfo,
1030		false);
1031	if (foundSymbol == NULL
1032		|| foundSymbol->Bind() == STB_WEAK) {
1033		// Not found or found a weak definition -- try to resolve in the other
1034		// image.
1035		elf_sym* secondSymbol = elf_find_symbol(secondImage, symbolName,
1036			versionInfo, false);
1037		// If we found a symbol -- take it in case we didn't have a symbol
1038		// before or the new symbol is not weak.
1039		if (secondSymbol != NULL
1040			&& (foundSymbol == NULL
1041				|| secondSymbol->Bind() != STB_WEAK)) {
1042			foundImage = secondImage;
1043			foundSymbol = secondSymbol;
1044		}
1045	}
1046
1047	if (foundSymbol == NULL) {
1048		// Weak undefined symbols get a value of 0, if unresolved.
1049		if (symbol->Bind() == STB_WEAK) {
1050			*_symbolAddress = 0;
1051			return B_OK;
1052		}
1053
1054		dprintf("\"%s\": could not resolve symbol '%s'\n", image->name,
1055			symbolName);
1056		return B_MISSING_SYMBOL;
1057	}
1058
1059	// make sure they're the same type
1060	if (symbol->Type() != foundSymbol->Type()) {
1061		dprintf("elf_resolve_symbol: found symbol '%s' in image '%s' "
1062			"(requested by image '%s') but wrong type (%d vs. %d)\n",
1063			symbolName, foundImage->name, image->name,
1064			foundSymbol->Type(), symbol->Type());
1065		return B_MISSING_SYMBOL;
1066	}
1067
1068	*_symbolAddress = foundSymbol->st_value + foundImage->text_region.delta;
1069	return B_OK;
1070}
1071
1072
1073/*! Until we have shared library support, just this links against the kernel */
1074static int
1075elf_relocate(struct elf_image_info* image, struct elf_image_info* resolveImage)
1076{
1077	int status = B_NO_ERROR;
1078
1079	TRACE(("elf_relocate(%p (\"%s\"))\n", image, image->name));
1080
1081	// deal with the rels first
1082	if (image->rel) {
1083		TRACE(("total %i rel relocs\n", image->rel_len / (int)sizeof(elf_rel)));
1084
1085		status = arch_elf_relocate_rel(image, resolveImage, image->rel,
1086			image->rel_len);
1087		if (status < B_OK)
1088			return status;
1089	}
1090
1091	if (image->pltrel) {
1092		if (image->pltrel_type == DT_REL) {
1093			TRACE(("total %i plt-relocs\n",
1094				image->pltrel_len / (int)sizeof(elf_rel)));
1095			status = arch_elf_relocate_rel(image, resolveImage, image->pltrel,
1096				image->pltrel_len);
1097		} else {
1098			TRACE(("total %i plt-relocs\n",
1099				image->pltrel_len / (int)sizeof(elf_rela)));
1100			status = arch_elf_relocate_rela(image, resolveImage,
1101				(elf_rela *)image->pltrel, image->pltrel_len);
1102		}
1103		if (status < B_OK)
1104			return status;
1105	}
1106
1107	if (image->rela) {
1108		TRACE(("total %i rel relocs\n",
1109			image->rela_len / (int)sizeof(elf_rela)));
1110
1111		status = arch_elf_relocate_rela(image, resolveImage, image->rela,
1112			image->rela_len);
1113		if (status < B_OK)
1114			return status;
1115	}
1116
1117	return status;
1118}
1119
1120
1121static int
1122verify_eheader(elf_ehdr *elfHeader)
1123{
1124	if (memcmp(elfHeader->e_ident, ELFMAG, 4) != 0)
1125		return B_NOT_AN_EXECUTABLE;
1126
1127	if (elfHeader->e_ident[4] != ELF_CLASS)
1128		return B_NOT_AN_EXECUTABLE;
1129
1130	if (elfHeader->e_phoff == 0)
1131		return B_NOT_AN_EXECUTABLE;
1132
1133	if (elfHeader->e_phentsize < sizeof(elf_phdr))
1134		return B_NOT_AN_EXECUTABLE;
1135
1136	return 0;
1137}
1138
1139
1140#ifndef ELF32_COMPAT
1141
1142
1143static void
1144unload_elf_image(struct elf_image_info *image)
1145{
1146	if (atomic_add(&image->ref_count, -1) > 1)
1147		return;
1148
1149	TRACE(("unload image %" B_PRId32 ", %s\n", image->id, image->name));
1150
1151	unregister_elf_image(image);
1152	delete_elf_image(image);
1153}
1154
1155
1156static status_t
1157load_elf_symbol_table(int fd, struct elf_image_info *image)
1158{
1159	elf_ehdr *elfHeader = image->elf_header;
1160	elf_sym *symbolTable = NULL;
1161	elf_shdr *stringHeader = NULL;
1162	uint32 numSymbols = 0;
1163	char *stringTable;
1164	status_t status;
1165	ssize_t length;
1166	int32 i;
1167
1168	// get section headers
1169
1170	ssize_t size = elfHeader->e_shnum * elfHeader->e_shentsize;
1171	elf_shdr *sectionHeaders = (elf_shdr *)malloc(size);
1172	if (sectionHeaders == NULL) {
1173		dprintf("error allocating space for section headers\n");
1174		return B_NO_MEMORY;
1175	}
1176
1177	length = read_pos(fd, elfHeader->e_shoff, sectionHeaders, size);
1178	if (length < size) {
1179		TRACE(("error reading in program headers\n"));
1180		status = B_ERROR;
1181		goto error1;
1182	}
1183
1184	// find symbol table in section headers
1185
1186	for (i = 0; i < elfHeader->e_shnum; i++) {
1187		if (sectionHeaders[i].sh_type == SHT_SYMTAB) {
1188			stringHeader = &sectionHeaders[sectionHeaders[i].sh_link];
1189
1190			if (stringHeader->sh_type != SHT_STRTAB) {
1191				TRACE(("doesn't link to string table\n"));
1192				status = B_BAD_DATA;
1193				goto error1;
1194			}
1195
1196			// read in symbol table
1197			size = sectionHeaders[i].sh_size;
1198			symbolTable = (elf_sym *)malloc(size);
1199			if (symbolTable == NULL) {
1200				status = B_NO_MEMORY;
1201				goto error1;
1202			}
1203
1204			length
1205				= read_pos(fd, sectionHeaders[i].sh_offset, symbolTable, size);
1206			if (length < size) {
1207				TRACE(("error reading in symbol table\n"));
1208				status = B_ERROR;
1209				goto error2;
1210			}
1211
1212			numSymbols = size / sizeof(elf_sym);
1213			break;
1214		}
1215	}
1216
1217	if (symbolTable == NULL) {
1218		TRACE(("no symbol table\n"));
1219		status = B_BAD_VALUE;
1220		goto error1;
1221	}
1222
1223	// read in string table
1224
1225	stringTable = (char *)malloc(size = stringHeader->sh_size);
1226	if (stringTable == NULL) {
1227		status = B_NO_MEMORY;
1228		goto error2;
1229	}
1230
1231	length = read_pos(fd, stringHeader->sh_offset, stringTable, size);
1232	if (length < size) {
1233		TRACE(("error reading in string table\n"));
1234		status = B_ERROR;
1235		goto error3;
1236	}
1237
1238	TRACE(("loaded %" B_PRId32 " debug symbols\n", numSymbols));
1239
1240	// insert tables into image
1241	image->debug_symbols = symbolTable;
1242	image->num_debug_symbols = numSymbols;
1243	image->debug_string_table = stringTable;
1244
1245	free(sectionHeaders);
1246	return B_OK;
1247
1248error3:
1249	free(stringTable);
1250error2:
1251	free(symbolTable);
1252error1:
1253	free(sectionHeaders);
1254
1255	return status;
1256}
1257
1258
1259static status_t
1260insert_preloaded_image(preloaded_elf_image *preloadedImage, bool kernel)
1261{
1262	status_t status;
1263
1264	status = verify_eheader(&preloadedImage->elf_header);
1265	if (status != B_OK)
1266		return status;
1267
1268	elf_image_info *image = create_image_struct();
1269	if (image == NULL)
1270		return B_NO_MEMORY;
1271
1272	image->name = strdup(preloadedImage->name);
1273	image->dynamic_section = preloadedImage->dynamic_section.start;
1274
1275	image->text_region.id = preloadedImage->text_region.id;
1276	image->text_region.start = preloadedImage->text_region.start;
1277	image->text_region.size = preloadedImage->text_region.size;
1278	image->text_region.delta = preloadedImage->text_region.delta;
1279	image->data_region.id = preloadedImage->data_region.id;
1280	image->data_region.start = preloadedImage->data_region.start;
1281	image->data_region.size = preloadedImage->data_region.size;
1282	image->data_region.delta = preloadedImage->data_region.delta;
1283
1284	status = elf_parse_dynamic_section(image);
1285	if (status != B_OK)
1286		goto error1;
1287
1288	status = init_image_version_infos(image);
1289	if (status != B_OK)
1290		goto error1;
1291
1292	if (!kernel) {
1293		status = check_needed_image_versions(image);
1294		if (status != B_OK)
1295			goto error1;
1296
1297		status = elf_relocate(image, sKernelImage);
1298		if (status != B_OK)
1299			goto error1;
1300	} else
1301		sKernelImage = image;
1302
1303	// copy debug symbols to the kernel heap
1304	if (preloadedImage->debug_symbols != NULL) {
1305		int32 debugSymbolsSize = sizeof(elf_sym)
1306			* preloadedImage->num_debug_symbols;
1307		image->debug_symbols = (elf_sym*)malloc(debugSymbolsSize);
1308		if (image->debug_symbols != NULL) {
1309			memcpy(image->debug_symbols, preloadedImage->debug_symbols,
1310				debugSymbolsSize);
1311		}
1312	}
1313	image->num_debug_symbols = preloadedImage->num_debug_symbols;
1314
1315	// copy debug string table to the kernel heap
1316	if (preloadedImage->debug_string_table != NULL) {
1317		image->debug_string_table = (char*)malloc(
1318			preloadedImage->debug_string_table_size);
1319		if (image->debug_string_table != NULL) {
1320			memcpy((void*)image->debug_string_table,
1321				preloadedImage->debug_string_table,
1322				preloadedImage->debug_string_table_size);
1323		}
1324	}
1325
1326	register_elf_image(image);
1327	preloadedImage->id = image->id;
1328		// modules_init() uses this information to get the preloaded images
1329
1330	// we now no longer need to write to the text area anymore
1331	set_area_protection(image->text_region.id,
1332		B_KERNEL_READ_AREA | B_KERNEL_EXECUTE_AREA);
1333
1334	return B_OK;
1335
1336error1:
1337	delete_elf_image(image);
1338
1339	preloadedImage->id = -1;
1340
1341	return status;
1342}
1343
1344
1345//	#pragma mark - userland symbol lookup
1346
1347
1348class UserSymbolLookup {
1349public:
1350	static UserSymbolLookup& Default()
1351	{
1352		return sLookup;
1353	}
1354
1355	status_t Init(Team* team)
1356	{
1357		// find the runtime loader debug area
1358		VMArea* area;
1359		for (VMAddressSpace::AreaIterator it
1360					= team->address_space->GetAreaIterator();
1361				(area = it.Next()) != NULL;) {
1362			if (strcmp(area->name, RUNTIME_LOADER_DEBUG_AREA_NAME) == 0)
1363				break;
1364		}
1365
1366		if (area == NULL)
1367			return B_ERROR;
1368
1369		// copy the runtime loader data structure
1370		if (!_Read((runtime_loader_debug_area*)area->Base(), fDebugArea))
1371			return B_BAD_ADDRESS;
1372
1373		fTeam = team;
1374		return B_OK;
1375	}
1376
1377	status_t LookupSymbolAddress(addr_t address, addr_t *_baseAddress,
1378		const char **_symbolName, const char **_imageName, bool *_exactMatch)
1379	{
1380		// Note, that this function doesn't find all symbols that we would like
1381		// to find. E.g. static functions do not appear in the symbol table
1382		// as function symbols, but as sections without name and size. The
1383		// .symtab section together with the .strtab section, which apparently
1384		// differ from the tables referred to by the .dynamic section, also
1385		// contain proper names and sizes for those symbols. Therefore, to get
1386		// completely satisfying results, we would need to read those tables
1387		// from the shared object.
1388
1389		// get the image for the address
1390		image_t image;
1391		status_t error = _FindImageAtAddress(address, image);
1392		if (error != B_OK) {
1393			// commpage requires special treatment since kernel stores symbol
1394			// information
1395			addr_t commPageAddress = (addr_t)fTeam->commpage_address;
1396			if (address >= commPageAddress
1397				&& address < commPageAddress + COMMPAGE_SIZE) {
1398				if (*_imageName)
1399					*_imageName = "commpage";
1400				address -= (addr_t)commPageAddress;
1401				error = elf_debug_lookup_symbol_address(address, _baseAddress,
1402					_symbolName, NULL, _exactMatch);
1403				if (_baseAddress)
1404					*_baseAddress += (addr_t)fTeam->commpage_address;
1405			}
1406			return error;
1407		}
1408
1409		strlcpy(fImageName, image.name, sizeof(fImageName));
1410
1411		// symbol hash table size
1412		uint32 hashTabSize;
1413		if (!_Read(image.symhash, hashTabSize))
1414			return B_BAD_ADDRESS;
1415
1416		// remote pointers to hash buckets and chains
1417		const uint32* hashBuckets = image.symhash + 2;
1418		const uint32* hashChains = image.symhash + 2 + hashTabSize;
1419
1420		const elf_region_t& textRegion = image.regions[0];
1421
1422		// search the image for the symbol
1423		elf_sym symbolFound;
1424		addr_t deltaFound = INT_MAX;
1425		bool exactMatch = false;
1426
1427		// to get rid of the erroneous "uninitialized" warnings
1428		symbolFound.st_name = 0;
1429		symbolFound.st_value = 0;
1430
1431		for (uint32 i = 0; i < hashTabSize; i++) {
1432			uint32 bucket;
1433			if (!_Read(&hashBuckets[i], bucket))
1434				return B_BAD_ADDRESS;
1435
1436			for (uint32 j = bucket; j != STN_UNDEF;
1437					_Read(&hashChains[j], j) ? 0 : j = STN_UNDEF) {
1438
1439				elf_sym symbol;
1440				if (!_Read(image.syms + j, symbol))
1441					continue;
1442
1443				// The symbol table contains not only symbols referring to
1444				// functions and data symbols within the shared object, but also
1445				// referenced symbols of other shared objects, as well as
1446				// section and file references. We ignore everything but
1447				// function and data symbols that have an st_value != 0 (0
1448				// seems to be an indication for a symbol defined elsewhere
1449				// -- couldn't verify that in the specs though).
1450				if ((symbol.Type() != STT_FUNC && symbol.Type() != STT_OBJECT)
1451					|| symbol.st_value == 0
1452					|| symbol.st_value + symbol.st_size + textRegion.delta
1453						> textRegion.vmstart + textRegion.size) {
1454					continue;
1455				}
1456
1457				// skip symbols starting after the given address
1458				addr_t symbolAddress = symbol.st_value + textRegion.delta;
1459				if (symbolAddress > address)
1460					continue;
1461				addr_t symbolDelta = address - symbolAddress;
1462
1463				if (symbolDelta < deltaFound) {
1464					deltaFound = symbolDelta;
1465					symbolFound = symbol;
1466
1467					if (symbolDelta >= 0 && symbolDelta < symbol.st_size) {
1468						// exact match
1469						exactMatch = true;
1470						break;
1471					}
1472				}
1473			}
1474		}
1475
1476		if (_imageName)
1477			*_imageName = fImageName;
1478
1479		if (_symbolName) {
1480			*_symbolName = NULL;
1481
1482			if (deltaFound < INT_MAX) {
1483				if (_ReadString(image, symbolFound.st_name, fSymbolName,
1484						sizeof(fSymbolName))) {
1485					*_symbolName = fSymbolName;
1486				} else {
1487					// we can't get its name, so forget the symbol
1488					deltaFound = INT_MAX;
1489				}
1490			}
1491		}
1492
1493		if (_baseAddress) {
1494			if (deltaFound < INT_MAX)
1495				*_baseAddress = symbolFound.st_value + textRegion.delta;
1496			else
1497				*_baseAddress = textRegion.vmstart;
1498		}
1499
1500		if (_exactMatch)
1501			*_exactMatch = exactMatch;
1502
1503		return B_OK;
1504	}
1505
1506	status_t _FindImageAtAddress(addr_t address, image_t& image)
1507	{
1508		image_queue_t imageQueue;
1509		if (!_Read(fDebugArea.loaded_images, imageQueue))
1510			return B_BAD_ADDRESS;
1511
1512		image_t* imageAddress = imageQueue.head;
1513		while (imageAddress != NULL) {
1514			if (!_Read(imageAddress, image))
1515				return B_BAD_ADDRESS;
1516
1517			if (image.regions[0].vmstart <= address
1518				&& address < image.regions[0].vmstart + image.regions[0].size) {
1519				return B_OK;
1520			}
1521
1522			imageAddress = image.next;
1523		}
1524
1525		return B_ENTRY_NOT_FOUND;
1526	}
1527
1528	bool _ReadString(const image_t& image, uint32 offset, char* buffer,
1529		size_t bufferSize)
1530	{
1531		const char* address = image.strtab + offset;
1532
1533		if (!IS_USER_ADDRESS(address))
1534			return false;
1535
1536		if (debug_debugger_running()) {
1537			return debug_strlcpy(B_CURRENT_TEAM, buffer, address, bufferSize)
1538				>= 0;
1539		}
1540		return user_strlcpy(buffer, address, bufferSize) >= 0;
1541	}
1542
1543	template<typename T> bool _Read(const T* address, T& data);
1544		// gcc 2.95.3 doesn't like it defined in-place
1545
1546private:
1547	Team*						fTeam;
1548	runtime_loader_debug_area	fDebugArea;
1549	char						fImageName[B_OS_NAME_LENGTH];
1550	char						fSymbolName[256];
1551	static UserSymbolLookup		sLookup;
1552};
1553
1554
1555template<typename T>
1556bool
1557UserSymbolLookup::_Read(const T* address, T& data)
1558{
1559	if (!IS_USER_ADDRESS(address))
1560		return false;
1561
1562	if (debug_debugger_running())
1563		return debug_memcpy(B_CURRENT_TEAM, &data, address, sizeof(T)) == B_OK;
1564	return user_memcpy(&data, address, sizeof(T)) == B_OK;
1565}
1566
1567
1568UserSymbolLookup UserSymbolLookup::sLookup;
1569	// doesn't need construction, but has an Init() method
1570
1571
1572//	#pragma mark - public kernel API
1573
1574
1575status_t
1576get_image_symbol(image_id id, const char *name, int32 symbolClass,
1577	void **_symbol)
1578{
1579	struct elf_image_info *image;
1580	elf_sym *symbol;
1581	status_t status = B_OK;
1582
1583	TRACE(("get_image_symbol(%s)\n", name));
1584
1585	mutex_lock(&sImageMutex);
1586
1587	image = find_image(id);
1588	if (image == NULL) {
1589		status = B_BAD_IMAGE_ID;
1590		goto done;
1591	}
1592
1593	symbol = elf_find_symbol(image, name, NULL, true);
1594	if (symbol == NULL || symbol->st_shndx == SHN_UNDEF) {
1595		status = B_ENTRY_NOT_FOUND;
1596		goto done;
1597	}
1598
1599	// TODO: support the "symbolClass" parameter!
1600
1601	TRACE(("found: %lx (%lx + %lx)\n",
1602		symbol->st_value + image->text_region.delta,
1603		symbol->st_value, image->text_region.delta));
1604
1605	*_symbol = (void *)(symbol->st_value + image->text_region.delta);
1606
1607done:
1608	mutex_unlock(&sImageMutex);
1609	return status;
1610}
1611
1612
1613//	#pragma mark - kernel private API
1614
1615
1616/*!	Looks up a symbol by address in all images loaded in kernel space.
1617	Note, if you need to call this function outside a debugger, make
1618	sure you fix locking and the way it returns its information, first!
1619*/
1620status_t
1621elf_debug_lookup_symbol_address(addr_t address, addr_t *_baseAddress,
1622	const char **_symbolName, const char **_imageName, bool *_exactMatch)
1623{
1624	struct elf_image_info *image;
1625	elf_sym *symbolFound = NULL;
1626	const char *symbolName = NULL;
1627	addr_t deltaFound = INT_MAX;
1628	bool exactMatch = false;
1629	status_t status;
1630
1631	TRACE(("looking up %p\n", (void *)address));
1632
1633	if (!sInitialized)
1634		return B_ERROR;
1635
1636	//mutex_lock(&sImageMutex);
1637
1638	image = find_image_at_address(address);
1639		// get image that may contain the address
1640
1641	if (image != NULL) {
1642		addr_t symbolDelta;
1643		uint32 i;
1644		int32 j;
1645
1646		TRACE((" image %p, base = %p, size = %p\n", image,
1647			(void *)image->text_region.start, (void *)image->text_region.size));
1648
1649		if (image->debug_symbols != NULL) {
1650			// search extended debug symbol table (contains static symbols)
1651
1652			TRACE((" searching debug symbols...\n"));
1653
1654			for (i = 0; i < image->num_debug_symbols; i++) {
1655				elf_sym *symbol = &image->debug_symbols[i];
1656
1657				if (symbol->st_value == 0 || symbol->st_size
1658						>= image->text_region.size + image->data_region.size)
1659					continue;
1660
1661				symbolDelta
1662					= address - (symbol->st_value + image->text_region.delta);
1663				if (symbolDelta >= 0 && symbolDelta < symbol->st_size)
1664					exactMatch = true;
1665
1666				if (exactMatch || symbolDelta < deltaFound) {
1667					deltaFound = symbolDelta;
1668					symbolFound = symbol;
1669					symbolName = image->debug_string_table + symbol->st_name;
1670
1671					if (exactMatch)
1672						break;
1673				}
1674			}
1675		} else {
1676			// search standard symbol lookup table
1677
1678			TRACE((" searching standard symbols...\n"));
1679
1680			for (i = 0; i < HASHTABSIZE(image); i++) {
1681				for (j = HASHBUCKETS(image)[i]; j != STN_UNDEF;
1682						j = HASHCHAINS(image)[j]) {
1683					elf_sym *symbol = &image->syms[j];
1684
1685					if (symbol->st_value == 0
1686						|| symbol->st_size >= image->text_region.size
1687							+ image->data_region.size)
1688						continue;
1689
1690					symbolDelta = address - (long)(symbol->st_value
1691						+ image->text_region.delta);
1692					if (symbolDelta >= 0 && symbolDelta < symbol->st_size)
1693						exactMatch = true;
1694
1695					if (exactMatch || symbolDelta < deltaFound) {
1696						deltaFound = symbolDelta;
1697						symbolFound = symbol;
1698						symbolName = SYMNAME(image, symbol);
1699
1700						if (exactMatch)
1701							goto symbol_found;
1702					}
1703				}
1704			}
1705		}
1706	}
1707symbol_found:
1708
1709	if (symbolFound != NULL) {
1710		if (_symbolName)
1711			*_symbolName = symbolName;
1712		if (_imageName)
1713			*_imageName = image->name;
1714		if (_baseAddress)
1715			*_baseAddress = symbolFound->st_value + image->text_region.delta;
1716		if (_exactMatch)
1717			*_exactMatch = exactMatch;
1718
1719		status = B_OK;
1720	} else if (image != NULL) {
1721		TRACE(("symbol not found!\n"));
1722
1723		if (_symbolName)
1724			*_symbolName = NULL;
1725		if (_imageName)
1726			*_imageName = image->name;
1727		if (_baseAddress)
1728			*_baseAddress = image->text_region.start;
1729		if (_exactMatch)
1730			*_exactMatch = false;
1731
1732		status = B_OK;
1733	} else {
1734		TRACE(("image not found!\n"));
1735		status = B_ENTRY_NOT_FOUND;
1736	}
1737
1738	// Note, theoretically, all information we return back to our caller
1739	// would have to be locked - but since this function is only called
1740	// from the debugger, it's safe to do it this way
1741
1742	//mutex_unlock(&sImageMutex);
1743
1744	return status;
1745}
1746
1747
1748/*!	Tries to find a matching user symbol for the given address.
1749	Note that the given team's address space must already be in effect.
1750*/
1751status_t
1752elf_debug_lookup_user_symbol_address(Team* team, addr_t address,
1753	addr_t *_baseAddress, const char **_symbolName, const char **_imageName,
1754	bool *_exactMatch)
1755{
1756	if (team == NULL || team == team_get_kernel_team())
1757		return B_BAD_VALUE;
1758
1759	UserSymbolLookup& lookup = UserSymbolLookup::Default();
1760	status_t error = lookup.Init(team);
1761	if (error != B_OK)
1762		return error;
1763
1764	return lookup.LookupSymbolAddress(address, _baseAddress, _symbolName,
1765		_imageName, _exactMatch);
1766}
1767
1768
1769/*!	Looks up a symbol in all kernel images. Note, this function is thought to
1770	be used in the kernel debugger, and therefore doesn't perform any locking.
1771*/
1772addr_t
1773elf_debug_lookup_symbol(const char* searchName)
1774{
1775	struct elf_image_info *image = NULL;
1776
1777	ImageHash::Iterator iterator(sImagesHash);
1778	while (iterator.HasNext()) {
1779		image = iterator.Next();
1780		if (image->num_debug_symbols > 0) {
1781			// search extended debug symbol table (contains static symbols)
1782			for (uint32 i = 0; i < image->num_debug_symbols; i++) {
1783				elf_sym *symbol = &image->debug_symbols[i];
1784				const char *name = image->debug_string_table + symbol->st_name;
1785
1786				if (symbol->st_value > 0 && !strcmp(name, searchName))
1787					return symbol->st_value + image->text_region.delta;
1788			}
1789		} else {
1790			// search standard symbol lookup table
1791			for (uint32 i = 0; i < HASHTABSIZE(image); i++) {
1792				for (uint32 j = HASHBUCKETS(image)[i]; j != STN_UNDEF;
1793						j = HASHCHAINS(image)[j]) {
1794					elf_sym *symbol = &image->syms[j];
1795					const char *name = SYMNAME(image, symbol);
1796
1797					if (symbol->st_value > 0 && !strcmp(name, searchName))
1798						return symbol->st_value + image->text_region.delta;
1799				}
1800			}
1801		}
1802	}
1803
1804	return 0;
1805}
1806
1807
1808status_t
1809elf_lookup_kernel_symbol(const char* name, elf_symbol_info* info)
1810{
1811	// find the symbol
1812	elf_sym* foundSymbol = elf_find_symbol(sKernelImage, name, NULL, false);
1813	if (foundSymbol == NULL)
1814		return B_MISSING_SYMBOL;
1815
1816	info->address = foundSymbol->st_value + sKernelImage->text_region.delta;
1817	info->size = foundSymbol->st_size;
1818	return B_OK;
1819}
1820
1821
1822#endif // ELF32_COMPAT
1823
1824
1825status_t
1826elf_load_user_image(const char *path, Team *team, uint32 flags, addr_t *entry)
1827{
1828	elf_ehdr elfHeader;
1829	elf_phdr *programHeaders = NULL;
1830	char baseName[B_OS_NAME_LENGTH];
1831	status_t status;
1832	ssize_t length;
1833	int fd;
1834	int i;
1835	addr_t delta = 0;
1836	uint32 addressSpec = B_RANDOMIZED_BASE_ADDRESS;
1837	area_id* mappedAreas = NULL;
1838
1839	TRACE(("elf_load: entry path '%s', team %p\n", path, team));
1840
1841	fd = _kern_open(-1, path, O_RDONLY, 0);
1842	if (fd < 0)
1843		return fd;
1844
1845	struct stat st;
1846	status = _kern_read_stat(fd, NULL, false, &st, sizeof(st));
1847	if (status != B_OK)
1848		return status;
1849
1850	// read and verify the ELF header
1851
1852	length = _kern_read(fd, 0, &elfHeader, sizeof(elfHeader));
1853	if (length < B_OK) {
1854		status = length;
1855		goto error;
1856	}
1857
1858	if (length != sizeof(elfHeader)) {
1859		// short read
1860		status = B_NOT_AN_EXECUTABLE;
1861		goto error;
1862	}
1863	status = verify_eheader(&elfHeader);
1864	if (status < B_OK)
1865		goto error;
1866
1867#ifdef ELF_LOAD_USER_IMAGE_TEST_EXECUTABLE
1868	if ((flags & ELF_LOAD_USER_IMAGE_TEST_EXECUTABLE) != 0)
1869		return B_OK;
1870#endif
1871
1872	struct elf_image_info* image;
1873	image = create_image_struct();
1874	if (image == NULL) {
1875		status = B_NO_MEMORY;
1876		goto error;
1877	}
1878	image->elf_header = &elfHeader;
1879
1880	// read program header
1881
1882	programHeaders = (elf_phdr *)malloc(
1883		elfHeader.e_phnum * elfHeader.e_phentsize);
1884	if (programHeaders == NULL) {
1885		dprintf("error allocating space for program headers\n");
1886		status = B_NO_MEMORY;
1887		goto error2;
1888	}
1889
1890	TRACE(("reading in program headers at 0x%lx, length 0x%x\n",
1891		elfHeader.e_phoff, elfHeader.e_phnum * elfHeader.e_phentsize));
1892	length = _kern_read(fd, elfHeader.e_phoff, programHeaders,
1893		elfHeader.e_phnum * elfHeader.e_phentsize);
1894	if (length < B_OK) {
1895		status = length;
1896		dprintf("error reading in program headers\n");
1897		goto error2;
1898	}
1899	if (length != elfHeader.e_phnum * elfHeader.e_phentsize) {
1900		dprintf("short read while reading in program headers\n");
1901		status = -1;
1902		goto error2;
1903	}
1904
1905	// construct a nice name for the region we have to create below
1906	{
1907		int32 length;
1908
1909		const char *leaf = strrchr(path, '/');
1910		if (leaf == NULL)
1911			leaf = path;
1912		else
1913			leaf++;
1914
1915		length = strlen(leaf);
1916		if (length > B_OS_NAME_LENGTH - 16)
1917			snprintf(baseName, B_OS_NAME_LENGTH, "...%s", leaf + length + 16 - B_OS_NAME_LENGTH);
1918		else
1919			strcpy(baseName, leaf);
1920	}
1921
1922	// map the program's segments into memory, initially with rw access
1923	// correct area protection will be set after relocation
1924
1925	mappedAreas = (area_id*)malloc(sizeof(area_id) * elfHeader.e_phnum);
1926	if (mappedAreas == NULL) {
1927		status = B_NO_MEMORY;
1928		goto error2;
1929	}
1930
1931	extended_image_info imageInfo;
1932	memset(&imageInfo, 0, sizeof(imageInfo));
1933
1934	for (i = 0; i < elfHeader.e_phnum; i++) {
1935		char regionName[B_OS_NAME_LENGTH];
1936		char *regionAddress;
1937		char *originalRegionAddress;
1938		area_id id;
1939
1940		mappedAreas[i] = -1;
1941
1942		if (programHeaders[i].p_type == PT_DYNAMIC) {
1943			image->dynamic_section = programHeaders[i].p_vaddr;
1944			continue;
1945		}
1946
1947		if (programHeaders[i].p_type != PT_LOAD)
1948			continue;
1949
1950		regionAddress = (char *)(ROUNDDOWN(programHeaders[i].p_vaddr,
1951			B_PAGE_SIZE) + delta);
1952		originalRegionAddress = regionAddress;
1953
1954		if (programHeaders[i].p_flags & PF_WRITE) {
1955			// rw/data segment
1956			size_t memUpperBound = (programHeaders[i].p_vaddr % B_PAGE_SIZE)
1957				+ programHeaders[i].p_memsz;
1958			size_t fileUpperBound = (programHeaders[i].p_vaddr % B_PAGE_SIZE)
1959				+ programHeaders[i].p_filesz;
1960
1961			memUpperBound = ROUNDUP(memUpperBound, B_PAGE_SIZE);
1962			fileUpperBound = ROUNDUP(fileUpperBound, B_PAGE_SIZE);
1963
1964			snprintf(regionName, B_OS_NAME_LENGTH, "%s_seg%drw", baseName, i);
1965
1966			id = vm_map_file(team->id, regionName, (void **)&regionAddress,
1967				addressSpec, fileUpperBound,
1968				B_READ_AREA | B_WRITE_AREA, REGION_PRIVATE_MAP, false,
1969				fd, ROUNDDOWN(programHeaders[i].p_offset, B_PAGE_SIZE));
1970			if (id < B_OK) {
1971				dprintf("error mapping file data: %s!\n", strerror(id));
1972				status = B_NOT_AN_EXECUTABLE;
1973				goto error2;
1974			}
1975			mappedAreas[i] = id;
1976
1977			imageInfo.basic_info.data = regionAddress;
1978			imageInfo.basic_info.data_size = memUpperBound;
1979
1980			image->data_region.start = (addr_t)regionAddress;
1981			image->data_region.size = memUpperBound;
1982
1983			// clean garbage brought by mmap (the region behind the file,
1984			// at least parts of it are the bss and have to be zeroed)
1985			addr_t start = (addr_t)regionAddress
1986				+ (programHeaders[i].p_vaddr % B_PAGE_SIZE)
1987				+ programHeaders[i].p_filesz;
1988			size_t amount = fileUpperBound
1989				- (programHeaders[i].p_vaddr % B_PAGE_SIZE)
1990				- (programHeaders[i].p_filesz);
1991			set_ac();
1992			memset((void *)start, 0, amount);
1993			clear_ac();
1994
1995			// Check if we need extra storage for the bss - we have to do this if
1996			// the above region doesn't already comprise the memory size, too.
1997
1998			if (memUpperBound != fileUpperBound) {
1999				size_t bssSize = memUpperBound - fileUpperBound;
2000
2001				snprintf(regionName, B_OS_NAME_LENGTH, "%s_bss%d", baseName, i);
2002
2003				regionAddress += fileUpperBound;
2004				virtual_address_restrictions virtualRestrictions = {};
2005				virtualRestrictions.address = regionAddress;
2006				virtualRestrictions.address_specification = B_EXACT_ADDRESS;
2007				physical_address_restrictions physicalRestrictions = {};
2008				id = create_area_etc(team->id, regionName, bssSize, B_NO_LOCK,
2009					B_READ_AREA | B_WRITE_AREA, 0, 0, &virtualRestrictions,
2010					&physicalRestrictions, (void**)&regionAddress);
2011				if (id < B_OK) {
2012					dprintf("error allocating bss area: %s!\n", strerror(id));
2013					status = B_NOT_AN_EXECUTABLE;
2014					goto error2;
2015				}
2016			}
2017		} else {
2018			// assume ro/text segment
2019			snprintf(regionName, B_OS_NAME_LENGTH, "%s_seg%dro", baseName, i);
2020
2021			size_t segmentSize = ROUNDUP(programHeaders[i].p_memsz
2022				+ (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE);
2023
2024			id = vm_map_file(team->id, regionName, (void **)&regionAddress,
2025				addressSpec, segmentSize,
2026				B_READ_AREA | B_WRITE_AREA, REGION_PRIVATE_MAP, false, fd,
2027				ROUNDDOWN(programHeaders[i].p_offset, B_PAGE_SIZE));
2028			if (id < B_OK) {
2029				dprintf("error mapping file text: %s!\n", strerror(id));
2030				status = B_NOT_AN_EXECUTABLE;
2031				goto error2;
2032			}
2033
2034			mappedAreas[i] = id;
2035
2036			imageInfo.basic_info.text = regionAddress;
2037			imageInfo.basic_info.text_size = segmentSize;
2038
2039			image->text_region.start = (addr_t)regionAddress;
2040			image->text_region.size = segmentSize;
2041		}
2042
2043		if (addressSpec != B_EXACT_ADDRESS) {
2044			addressSpec = B_EXACT_ADDRESS;
2045			delta = regionAddress - originalRegionAddress;
2046		}
2047	}
2048
2049	image->data_region.delta = delta;
2050	image->text_region.delta = delta;
2051
2052	// modify the dynamic ptr by the delta of the regions
2053	image->dynamic_section += image->text_region.delta;
2054
2055	set_ac();
2056	status = elf_parse_dynamic_section(image);
2057	if (status != B_OK)
2058		goto error2;
2059
2060	status = elf_relocate(image, image);
2061	if (status != B_OK)
2062		goto error2;
2063
2064	clear_ac();
2065
2066	// set correct area protection
2067	for (i = 0; i < elfHeader.e_phnum; i++) {
2068		if (mappedAreas[i] == -1)
2069			continue;
2070
2071		uint32 protection = 0;
2072
2073		if (programHeaders[i].p_flags & PF_EXECUTE)
2074			protection |= B_EXECUTE_AREA;
2075		if (programHeaders[i].p_flags & PF_WRITE)
2076			protection |= B_WRITE_AREA;
2077		if (programHeaders[i].p_flags & PF_READ)
2078			protection |= B_READ_AREA;
2079
2080		status = vm_set_area_protection(team->id, mappedAreas[i], protection,
2081			true);
2082		if (status != B_OK)
2083			goto error2;
2084	}
2085
2086	// register the loaded image
2087	imageInfo.basic_info.type = B_LIBRARY_IMAGE;
2088	imageInfo.basic_info.device = st.st_dev;
2089	imageInfo.basic_info.node = st.st_ino;
2090	strlcpy(imageInfo.basic_info.name, path, sizeof(imageInfo.basic_info.name));
2091
2092	imageInfo.basic_info.api_version = B_HAIKU_VERSION;
2093	imageInfo.basic_info.abi = B_HAIKU_ABI;
2094		// TODO: Get the actual values for the shared object. Currently only
2095		// the runtime loader is loaded, so this is good enough for the time
2096		// being.
2097
2098	imageInfo.text_delta = delta;
2099	imageInfo.symbol_table = image->syms;
2100	imageInfo.symbol_hash = image->symhash;
2101	imageInfo.string_table = image->strtab;
2102
2103	imageInfo.basic_info.id = register_image(team, &imageInfo,
2104		sizeof(imageInfo));
2105	if (imageInfo.basic_info.id >= 0 && team_get_current_team_id() == team->id)
2106		user_debug_image_created(&imageInfo.basic_info);
2107		// Don't care, if registering fails. It's not crucial.
2108
2109	TRACE(("elf_load: done!\n"));
2110
2111	*entry = elfHeader.e_entry + delta;
2112	status = B_OK;
2113
2114error2:
2115	clear_ac();
2116	free(mappedAreas);
2117
2118	image->elf_header = NULL;
2119	delete_elf_image(image);
2120
2121error:
2122	free(programHeaders);
2123	_kern_close(fd);
2124
2125	return status;
2126}
2127
2128
2129#ifndef ELF32_COMPAT
2130
2131image_id
2132load_kernel_add_on(const char *path)
2133{
2134	elf_phdr *programHeaders;
2135	elf_ehdr *elfHeader;
2136	struct elf_image_info *image;
2137	const char *fileName;
2138	void *reservedAddress;
2139	size_t reservedSize;
2140	status_t status;
2141	ssize_t length;
2142	bool textSectionWritable = false;
2143	int executableHeaderCount = 0;
2144
2145	TRACE(("elf_load_kspace: entry path '%s'\n", path));
2146
2147	int fd = _kern_open(-1, path, O_RDONLY, 0);
2148	if (fd < 0)
2149		return fd;
2150
2151	struct vnode *vnode;
2152	status = vfs_get_vnode_from_fd(fd, true, &vnode);
2153	if (status < B_OK)
2154		goto error0;
2155
2156	// get the file name
2157	fileName = strrchr(path, '/');
2158	if (fileName == NULL)
2159		fileName = path;
2160	else
2161		fileName++;
2162
2163	// Prevent someone else from trying to load this image
2164	mutex_lock(&sImageLoadMutex);
2165
2166	// make sure it's not loaded already. Search by vnode
2167	image = find_image_by_vnode(vnode);
2168	if (image) {
2169		atomic_add(&image->ref_count, 1);
2170		goto done;
2171	}
2172
2173	elfHeader = (elf_ehdr *)malloc(sizeof(*elfHeader));
2174	if (!elfHeader) {
2175		status = B_NO_MEMORY;
2176		goto error;
2177	}
2178
2179	length = _kern_read(fd, 0, elfHeader, sizeof(*elfHeader));
2180	if (length < B_OK) {
2181		status = length;
2182		goto error1;
2183	}
2184	if (length != sizeof(*elfHeader)) {
2185		// short read
2186		status = B_NOT_AN_EXECUTABLE;
2187		goto error1;
2188	}
2189	status = verify_eheader(elfHeader);
2190	if (status < B_OK)
2191		goto error1;
2192
2193	image = create_image_struct();
2194	if (!image) {
2195		status = B_NO_MEMORY;
2196		goto error1;
2197	}
2198	image->vnode = vnode;
2199	image->elf_header = elfHeader;
2200	image->name = strdup(path);
2201	vnode = NULL;
2202
2203	programHeaders = (elf_phdr *)malloc(elfHeader->e_phnum
2204		* elfHeader->e_phentsize);
2205	if (programHeaders == NULL) {
2206		dprintf("%s: error allocating space for program headers\n", fileName);
2207		status = B_NO_MEMORY;
2208		goto error2;
2209	}
2210
2211	TRACE(("reading in program headers at 0x%lx, length 0x%x\n",
2212		elfHeader->e_phoff, elfHeader->e_phnum * elfHeader->e_phentsize));
2213
2214	length = _kern_read(fd, elfHeader->e_phoff, programHeaders,
2215		elfHeader->e_phnum * elfHeader->e_phentsize);
2216	if (length < B_OK) {
2217		status = length;
2218		TRACE(("%s: error reading in program headers\n", fileName));
2219		goto error3;
2220	}
2221	if (length != elfHeader->e_phnum * elfHeader->e_phentsize) {
2222		TRACE(("%s: short read while reading in program headers\n", fileName));
2223		status = B_ERROR;
2224		goto error3;
2225	}
2226
2227	// determine how much space we need for all loaded segments
2228
2229	reservedSize = 0;
2230	length = 0;
2231
2232	for (int32 i = 0; i < elfHeader->e_phnum; i++) {
2233		size_t end;
2234
2235		if (programHeaders[i].p_type != PT_LOAD)
2236			continue;
2237
2238		length += ROUNDUP(programHeaders[i].p_memsz
2239			+ (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE);
2240
2241		end = ROUNDUP(programHeaders[i].p_memsz + programHeaders[i].p_vaddr,
2242			B_PAGE_SIZE);
2243		if (end > reservedSize)
2244			reservedSize = end;
2245
2246		if (programHeaders[i].IsExecutable())
2247			executableHeaderCount++;
2248	}
2249
2250	// Check whether the segments have an unreasonable amount of unused space
2251	// inbetween.
2252	if ((ssize_t)reservedSize > length + 8 * 1024) {
2253		status = B_BAD_DATA;
2254		goto error1;
2255	}
2256
2257	// reserve that space and allocate the areas from that one
2258	if (vm_reserve_address_range(VMAddressSpace::KernelID(), &reservedAddress,
2259			B_ANY_KERNEL_ADDRESS, reservedSize, 0) < B_OK) {
2260		status = B_NO_MEMORY;
2261		goto error3;
2262	}
2263
2264	image->data_region.size = 0;
2265	image->text_region.size = 0;
2266
2267	for (int32 i = 0; i < elfHeader->e_phnum; i++) {
2268		char regionName[B_OS_NAME_LENGTH];
2269		elf_region *region;
2270
2271		TRACE(("looking at program header %" B_PRId32 "\n", i));
2272
2273		switch (programHeaders[i].p_type) {
2274			case PT_LOAD:
2275				break;
2276			case PT_DYNAMIC:
2277				image->dynamic_section = programHeaders[i].p_vaddr;
2278				continue;
2279			case PT_INTERP:
2280				// should check here for appropriate interpreter
2281				continue;
2282			case PT_PHDR:
2283			case PT_STACK:
2284				// we don't use it
2285				continue;
2286			case PT_EH_FRAME:
2287				// not implemented yet, but can be ignored
2288				continue;
2289			default:
2290				dprintf("%s: unhandled pheader type %#" B_PRIx32 "\n", fileName,
2291					programHeaders[i].p_type);
2292				continue;
2293		}
2294
2295		// we're here, so it must be a PT_LOAD segment
2296
2297		// Usually add-ons have two PT_LOAD headers: one for .data one or .text.
2298		// x86 and PPC may differ in permission bits for .data's PT_LOAD header
2299		// x86 is usually RW, PPC is RWE
2300
2301		// Some add-ons may have .text and .data concatenated in a single
2302		// PT_LOAD RWE header and we must map that to .text.
2303		if (programHeaders[i].IsReadWrite()
2304			&& (!programHeaders[i].IsExecutable()
2305				|| executableHeaderCount > 1)) {
2306			// this is the writable segment
2307			if (image->data_region.size != 0) {
2308				// we've already created this segment
2309				continue;
2310			}
2311			region = &image->data_region;
2312
2313			snprintf(regionName, B_OS_NAME_LENGTH, "%s_data", fileName);
2314		} else if (programHeaders[i].IsExecutable()) {
2315			// this is the non-writable segment
2316			if (image->text_region.size != 0) {
2317				// we've already created this segment
2318				continue;
2319			}
2320			region = &image->text_region;
2321
2322			// some programs may have .text and .data concatenated in a
2323			// single PT_LOAD section which is readable/writable/executable
2324			textSectionWritable = programHeaders[i].IsReadWrite();
2325			snprintf(regionName, B_OS_NAME_LENGTH, "%s_text", fileName);
2326		} else {
2327			dprintf("%s: weird program header flags %#" B_PRIx32 "\n", fileName,
2328				programHeaders[i].p_flags);
2329			continue;
2330		}
2331
2332		region->start = (addr_t)reservedAddress + ROUNDDOWN(
2333			programHeaders[i].p_vaddr, B_PAGE_SIZE);
2334		region->size = ROUNDUP(programHeaders[i].p_memsz
2335			+ (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE);
2336		region->id = create_area(regionName, (void **)&region->start,
2337			B_EXACT_ADDRESS, region->size, B_FULL_LOCK,
2338			B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
2339		if (region->id < B_OK) {
2340			dprintf("%s: error allocating area: %s\n", fileName,
2341				strerror(region->id));
2342			status = B_NOT_AN_EXECUTABLE;
2343			goto error4;
2344		}
2345		region->delta = -ROUNDDOWN(programHeaders[i].p_vaddr, B_PAGE_SIZE);
2346
2347		TRACE(("elf_load_kspace: created area \"%s\" at %p\n",
2348			regionName, (void *)region->start));
2349
2350		length = _kern_read(fd, programHeaders[i].p_offset,
2351			(void *)(region->start + (programHeaders[i].p_vaddr % B_PAGE_SIZE)),
2352			programHeaders[i].p_filesz);
2353		if (length < B_OK) {
2354			status = length;
2355			dprintf("%s: error reading in segment %" B_PRId32 "\n", fileName,
2356				i);
2357			goto error5;
2358		}
2359	}
2360
2361	image->data_region.delta += image->data_region.start;
2362	image->text_region.delta += image->text_region.start;
2363
2364	// modify the dynamic ptr by the delta of the regions
2365	image->dynamic_section += image->text_region.delta;
2366
2367	status = elf_parse_dynamic_section(image);
2368	if (status < B_OK)
2369		goto error5;
2370
2371	status = init_image_version_infos(image);
2372	if (status != B_OK)
2373		goto error5;
2374
2375	status = check_needed_image_versions(image);
2376	if (status != B_OK)
2377		goto error5;
2378
2379	status = elf_relocate(image, sKernelImage);
2380	if (status < B_OK)
2381		goto error5;
2382
2383	// We needed to read in the contents of the "text" area, but
2384	// now we can protect it read-only/execute, unless this is a
2385	// special image with concatenated .text and .data, when it
2386	// will also need write access.
2387	set_area_protection(image->text_region.id,
2388		B_KERNEL_READ_AREA | B_KERNEL_EXECUTE_AREA
2389		| (textSectionWritable ? B_KERNEL_WRITE_AREA : 0));
2390
2391	// There might be a hole between the two segments, and we don't need to
2392	// reserve this any longer
2393	vm_unreserve_address_range(VMAddressSpace::KernelID(), reservedAddress,
2394		reservedSize);
2395
2396	if (sLoadElfSymbols)
2397		load_elf_symbol_table(fd, image);
2398
2399	free(programHeaders);
2400	mutex_lock(&sImageMutex);
2401	register_elf_image(image);
2402	mutex_unlock(&sImageMutex);
2403
2404done:
2405	_kern_close(fd);
2406	mutex_unlock(&sImageLoadMutex);
2407
2408	return image->id;
2409
2410error5:
2411error4:
2412	vm_unreserve_address_range(VMAddressSpace::KernelID(), reservedAddress,
2413		reservedSize);
2414error3:
2415	free(programHeaders);
2416error2:
2417	delete_elf_image(image);
2418	elfHeader = NULL;
2419error1:
2420	free(elfHeader);
2421error:
2422	mutex_unlock(&sImageLoadMutex);
2423error0:
2424	dprintf("Could not load kernel add-on \"%s\": %s\n", path,
2425		strerror(status));
2426
2427	if (vnode)
2428		vfs_put_vnode(vnode);
2429	_kern_close(fd);
2430
2431	return status;
2432}
2433
2434
2435status_t
2436unload_kernel_add_on(image_id id)
2437{
2438	MutexLocker _(sImageLoadMutex);
2439	MutexLocker _2(sImageMutex);
2440
2441	elf_image_info *image = find_image(id);
2442	if (image == NULL)
2443		return B_BAD_IMAGE_ID;
2444
2445	unload_elf_image(image);
2446	return B_OK;
2447}
2448
2449
2450struct elf_image_info*
2451elf_get_kernel_image()
2452{
2453	return sKernelImage;
2454}
2455
2456
2457status_t
2458elf_get_image_info_for_address(addr_t address, image_info* info)
2459{
2460	MutexLocker _(sImageMutex);
2461	struct elf_image_info* elfInfo = find_image_at_address(address);
2462	if (elfInfo == NULL)
2463		return B_ENTRY_NOT_FOUND;
2464
2465	info->id = elfInfo->id;
2466	info->type = B_SYSTEM_IMAGE;
2467	info->sequence = 0;
2468	info->init_order = 0;
2469	info->init_routine = NULL;
2470	info->term_routine = NULL;
2471	info->device = -1;
2472	info->node = -1;
2473		// TODO: We could actually fill device/node in.
2474	strlcpy(info->name, elfInfo->name, sizeof(info->name));
2475	info->text = (void*)elfInfo->text_region.start;
2476	info->data = (void*)elfInfo->data_region.start;
2477	info->text_size = elfInfo->text_region.size;
2478	info->data_size = elfInfo->data_region.size;
2479
2480	return B_OK;
2481}
2482
2483
2484image_id
2485elf_create_memory_image(const char* imageName, addr_t text, size_t textSize,
2486	addr_t data, size_t dataSize)
2487{
2488	// allocate the image
2489	elf_image_info* image = create_image_struct();
2490	if (image == NULL)
2491		return B_NO_MEMORY;
2492	MemoryDeleter imageDeleter(image);
2493
2494	// allocate symbol and string tables -- we allocate an empty symbol table,
2495	// so that elf_debug_lookup_symbol_address() won't try the dynamic symbol
2496	// table, which we don't have.
2497	elf_sym* symbolTable = (elf_sym*)malloc(0);
2498	char* stringTable = (char*)malloc(1);
2499	MemoryDeleter symbolTableDeleter(symbolTable);
2500	MemoryDeleter stringTableDeleter(stringTable);
2501	if (symbolTable == NULL || stringTable == NULL)
2502		return B_NO_MEMORY;
2503
2504	// the string table always contains the empty string
2505	stringTable[0] = '\0';
2506
2507	image->debug_symbols = symbolTable;
2508	image->num_debug_symbols = 0;
2509	image->debug_string_table = stringTable;
2510
2511	// dup image name
2512	image->name = strdup(imageName);
2513	if (image->name == NULL)
2514		return B_NO_MEMORY;
2515
2516	// data and text region
2517	image->text_region.id = -1;
2518	image->text_region.start = text;
2519	image->text_region.size = textSize;
2520	image->text_region.delta = 0;
2521
2522	image->data_region.id = -1;
2523	image->data_region.start = data;
2524	image->data_region.size = dataSize;
2525	image->data_region.delta = 0;
2526
2527	mutex_lock(&sImageMutex);
2528	register_elf_image(image);
2529	image_id imageID = image->id;
2530	mutex_unlock(&sImageMutex);
2531
2532	// keep the allocated memory
2533	imageDeleter.Detach();
2534	symbolTableDeleter.Detach();
2535	stringTableDeleter.Detach();
2536
2537	return imageID;
2538}
2539
2540
2541status_t
2542elf_add_memory_image_symbol(image_id id, const char* name, addr_t address,
2543	size_t size, int32 type)
2544{
2545	MutexLocker _(sImageMutex);
2546
2547	// get the image
2548	struct elf_image_info* image = find_image(id);
2549	if (image == NULL)
2550		return B_ENTRY_NOT_FOUND;
2551
2552	// get the current string table size
2553	size_t stringTableSize = 1;
2554	if (image->num_debug_symbols > 0) {
2555		for (int32 i = image->num_debug_symbols - 1; i >= 0; i--) {
2556			int32 nameIndex = image->debug_symbols[i].st_name;
2557			if (nameIndex != 0) {
2558				stringTableSize = nameIndex
2559					+ strlen(image->debug_string_table + nameIndex) + 1;
2560				break;
2561			}
2562		}
2563	}
2564
2565	// enter the name in the string table
2566	char* stringTable = (char*)image->debug_string_table;
2567	size_t stringIndex = 0;
2568	if (name != NULL) {
2569		size_t nameSize = strlen(name) + 1;
2570		stringIndex = stringTableSize;
2571		stringTableSize += nameSize;
2572		stringTable = (char*)realloc((char*)image->debug_string_table,
2573			stringTableSize);
2574		if (stringTable == NULL)
2575			return B_NO_MEMORY;
2576		image->debug_string_table = stringTable;
2577		memcpy(stringTable + stringIndex, name, nameSize);
2578	}
2579
2580	// resize the symbol table
2581	int32 symbolCount = image->num_debug_symbols + 1;
2582	elf_sym* symbolTable = (elf_sym*)realloc(
2583		(elf_sym*)image->debug_symbols, sizeof(elf_sym) * symbolCount);
2584	if (symbolTable == NULL)
2585		return B_NO_MEMORY;
2586	image->debug_symbols = symbolTable;
2587
2588	// enter the symbol
2589	elf_sym& symbol = symbolTable[symbolCount - 1];
2590	symbol.SetInfo(STB_GLOBAL,
2591		type == B_SYMBOL_TYPE_DATA ? STT_OBJECT : STT_FUNC);
2592	symbol.st_name = stringIndex;
2593	symbol.st_value = address;
2594	symbol.st_size = size;
2595	symbol.st_other = 0;
2596	symbol.st_shndx = 0;
2597	image->num_debug_symbols++;
2598
2599	return B_OK;
2600}
2601
2602
2603/*!	Reads the symbol and string table for the kernel image with the given ID.
2604	\a _symbolCount and \a _stringTableSize are both in- and output parameters.
2605	When called they call the size of the buffers given by \a symbolTable and
2606	\a stringTable respectively. When the function returns successfully, they
2607	will contain the actual sizes (which can be greater than the original ones).
2608	The function will copy as much as possible into the buffers. For only
2609	getting the required buffer sizes, it can be invoked with \c NULL buffers.
2610	On success \a _imageDelta will contain the offset to be added to the symbol
2611	values in the table to get the actual symbol addresses.
2612*/
2613status_t
2614elf_read_kernel_image_symbols(image_id id, elf_sym* symbolTable,
2615	int32* _symbolCount, char* stringTable, size_t* _stringTableSize,
2616	addr_t* _imageDelta, bool kernel)
2617{
2618	// check params
2619	if (_symbolCount == NULL || _stringTableSize == NULL)
2620		return B_BAD_VALUE;
2621	if (!kernel) {
2622		if (!IS_USER_ADDRESS(_symbolCount) || !IS_USER_ADDRESS(_stringTableSize)
2623			|| (_imageDelta != NULL && !IS_USER_ADDRESS(_imageDelta))
2624			|| (symbolTable != NULL && !IS_USER_ADDRESS(symbolTable))
2625			|| (stringTable != NULL && !IS_USER_ADDRESS(stringTable))) {
2626			return B_BAD_ADDRESS;
2627		}
2628	}
2629
2630	// get buffer sizes
2631	int32 maxSymbolCount;
2632	size_t maxStringTableSize;
2633	if (kernel) {
2634		maxSymbolCount = *_symbolCount;
2635		maxStringTableSize = *_stringTableSize;
2636	} else {
2637		if (user_memcpy(&maxSymbolCount, _symbolCount, sizeof(maxSymbolCount))
2638				!= B_OK
2639			|| user_memcpy(&maxStringTableSize, _stringTableSize,
2640				sizeof(maxStringTableSize)) != B_OK) {
2641			return B_BAD_ADDRESS;
2642		}
2643	}
2644
2645	// find the image
2646	MutexLocker _(sImageMutex);
2647	struct elf_image_info* image = find_image(id);
2648	if (image == NULL)
2649		return B_ENTRY_NOT_FOUND;
2650
2651	// get the tables and infos
2652	addr_t imageDelta = image->text_region.delta;
2653	const elf_sym* symbols;
2654	int32 symbolCount;
2655	const char* strings;
2656
2657	if (image->debug_symbols != NULL) {
2658		symbols = image->debug_symbols;
2659		symbolCount = image->num_debug_symbols;
2660		strings = image->debug_string_table;
2661	} else {
2662		symbols = image->syms;
2663		symbolCount = image->symhash[1];
2664		strings = image->strtab;
2665	}
2666
2667	// The string table size isn't stored in the elf_image_info structure. Find
2668	// out by iterating through all symbols.
2669	size_t stringTableSize = 0;
2670	for (int32 i = 0; i < symbolCount; i++) {
2671		size_t index = symbols[i].st_name;
2672		if (index > stringTableSize)
2673			stringTableSize = index;
2674	}
2675	stringTableSize += strlen(strings + stringTableSize) + 1;
2676		// add size of the last string
2677
2678	// copy symbol table
2679	int32 symbolsToCopy = min_c(symbolCount, maxSymbolCount);
2680	if (symbolTable != NULL && symbolsToCopy > 0) {
2681		if (kernel) {
2682			memcpy(symbolTable, symbols, sizeof(elf_sym) * symbolsToCopy);
2683		} else if (user_memcpy(symbolTable, symbols,
2684				sizeof(elf_sym) * symbolsToCopy) != B_OK) {
2685			return B_BAD_ADDRESS;
2686		}
2687	}
2688
2689	// copy string table
2690	size_t stringsToCopy = min_c(stringTableSize, maxStringTableSize);
2691	if (stringTable != NULL && stringsToCopy > 0) {
2692		if (kernel) {
2693			memcpy(stringTable, strings, stringsToCopy);
2694		} else {
2695			if (user_memcpy(stringTable, strings, stringsToCopy)
2696					!= B_OK) {
2697				return B_BAD_ADDRESS;
2698			}
2699		}
2700	}
2701
2702	// copy sizes
2703	if (kernel) {
2704		*_symbolCount = symbolCount;
2705		*_stringTableSize = stringTableSize;
2706		if (_imageDelta != NULL)
2707			*_imageDelta = imageDelta;
2708	} else {
2709		if (user_memcpy(_symbolCount, &symbolCount, sizeof(symbolCount)) != B_OK
2710			|| user_memcpy(_stringTableSize, &stringTableSize,
2711					sizeof(stringTableSize)) != B_OK
2712			|| (_imageDelta != NULL && user_memcpy(_imageDelta, &imageDelta,
2713					sizeof(imageDelta)) != B_OK)) {
2714			return B_BAD_ADDRESS;
2715		}
2716	}
2717
2718	return B_OK;
2719}
2720
2721
2722status_t
2723elf_init(kernel_args* args)
2724{
2725	struct preloaded_image* image;
2726
2727	image_init();
2728
2729	if (void* handle = load_driver_settings("kernel")) {
2730		sLoadElfSymbols = get_driver_boolean_parameter(handle, "load_symbols",
2731			false, false);
2732
2733		unload_driver_settings(handle);
2734	}
2735
2736	sImagesHash = new(std::nothrow) ImageHash();
2737	if (sImagesHash == NULL)
2738		return B_NO_MEMORY;
2739	status_t init = sImagesHash->Init(IMAGE_HASH_SIZE);
2740	if (init != B_OK)
2741		return init;
2742
2743	// Build a image structure for the kernel, which has already been loaded.
2744	// The preloaded_images were already prepared by the VM.
2745	image = args->kernel_image;
2746	if (insert_preloaded_image(static_cast<preloaded_elf_image *>(image),
2747			true) < B_OK)
2748		panic("could not create kernel image.\n");
2749
2750	// Build image structures for all preloaded images.
2751	for (image = args->preloaded_images; image != NULL; image = image->next)
2752		insert_preloaded_image(static_cast<preloaded_elf_image *>(image),
2753			false);
2754
2755	add_debugger_command("ls", &dump_address_info,
2756		"lookup symbol for a particular address");
2757	add_debugger_command("symbols", &dump_symbols, "dump symbols for image");
2758	add_debugger_command("symbol", &dump_symbol, "search symbol in images");
2759	add_debugger_command_etc("image", &dump_image, "dump image info",
2760		"Prints info about the specified image.\n"
2761		"  <image>  - pointer to the semaphore structure, or ID\n"
2762		"           of the image to print info for.\n", 0);
2763
2764	sInitialized = true;
2765	return B_OK;
2766}
2767
2768
2769// #pragma mark -
2770
2771
2772/*!	Reads the symbol and string table for the kernel image with the given ID.
2773	\a _symbolCount and \a _stringTableSize are both in- and output parameters.
2774	When called they call the size of the buffers given by \a symbolTable and
2775	\a stringTable respectively. When the function returns successfully, they
2776	will contain the actual sizes (which can be greater than the original ones).
2777	The function will copy as much as possible into the buffers. For only
2778	getting the required buffer sizes, it can be invoked with \c NULL buffers.
2779	On success \a _imageDelta will contain the offset to be added to the symbol
2780	values in the table to get the actual symbol addresses.
2781*/
2782status_t
2783_user_read_kernel_image_symbols(image_id id, elf_sym* symbolTable,
2784	int32* _symbolCount, char* stringTable, size_t* _stringTableSize,
2785	addr_t* _imageDelta)
2786{
2787	return elf_read_kernel_image_symbols(id, symbolTable, _symbolCount,
2788		stringTable, _stringTableSize, _imageDelta, false);
2789}
2790
2791#endif // ELF32_COMPAT
2792
2793