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