xref: /haiku/src/system/kernel/elf.cpp (revision 4c8e85b316c35a9161f5a1c50ad70bc91c83a76f)
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 
59 namespace {
60 
61 #define IMAGE_HASH_SIZE 16
62 
63 struct 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 
83 typedef BOpenHashTable<ImageHashDefinition> ImageHash;
84 
85 } // namespace
86 
87 
88 #ifndef ELF32_COMPAT
89 
90 static ImageHash *sImagesHash;
91 
92 static struct elf_image_info *sKernelImage = NULL;
93 static mutex sImageMutex = MUTEX_INITIALIZER("kimages_lock");
94 	// guards sImagesHash
95 static mutex sImageLoadMutex = MUTEX_INITIALIZER("kimages_load_lock");
96 	// serializes loading/unloading add-ons locking order
97 	// sImageLoadMutex -> sImageMutex
98 static bool sLoadElfSymbols = false;
99 static bool sInitialized = false;
100 
101 
102 static elf_sym *elf_find_symbol(struct elf_image_info *image, const char *name,
103 	const elf_version_info *version, bool lookupDefault);
104 
105 
106 static void
107 unregister_elf_image(struct elf_image_info *image)
108 {
109 	unregister_image(team_get_kernel_team(), image->id);
110 	sImagesHash->Remove(image);
111 }
112 
113 
114 static void
115 register_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. */
177 static struct elf_image_info *
178 find_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 
203 static int
204 dump_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 
238 static struct elf_image_info *
239 find_image(image_id id)
240 {
241 	return sImagesHash->Lookup(id);
242 }
243 
244 
245 static struct elf_image_info *
246 find_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 
264 static struct elf_image_info *
265 create_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 
282 static void
283 delete_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 
303 static uint32
304 elf_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 
319 static const char *
320 get_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 
335 static const char *
336 get_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 */
355 static int
356 dump_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 
410 static int
411 dump_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 
513 static void
514 dump_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 
523 static void
524 dump_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 
548 static int
549 dump_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
586 void 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 
604 static elf_sym *
605 elf_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 
712 static status_t
713 elf_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 
819 static status_t
820 assert_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 
857 static status_t
858 init_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 
963 static status_t
964 check_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 */
999 status_t
1000 elf_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 */
1074 static int
1075 elf_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 
1121 static int
1122 verify_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 
1143 static void
1144 unload_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 
1156 static status_t
1157 load_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 
1248 error3:
1249 	free(stringTable);
1250 error2:
1251 	free(symbolTable);
1252 error1:
1253 	free(sectionHeaders);
1254 
1255 	return status;
1256 }
1257 
1258 
1259 static status_t
1260 insert_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 
1336 error1:
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 
1348 class UserSymbolLookup {
1349 public:
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 
1546 private:
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 
1555 template<typename T>
1556 bool
1557 UserSymbolLookup::_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 
1568 UserSymbolLookup UserSymbolLookup::sLookup;
1569 	// doesn't need construction, but has an Init() method
1570 
1571 
1572 //	#pragma mark - public kernel API
1573 
1574 
1575 status_t
1576 get_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 
1607 done:
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 */
1620 status_t
1621 elf_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 	}
1707 symbol_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 */
1751 status_t
1752 elf_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 */
1772 addr_t
1773 elf_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 
1808 status_t
1809 elf_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 
1825 status_t
1826 elf_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 
2114 error2:
2115 	clear_ac();
2116 	free(mappedAreas);
2117 
2118 	image->elf_header = NULL;
2119 	delete_elf_image(image);
2120 
2121 error:
2122 	free(programHeaders);
2123 	_kern_close(fd);
2124 
2125 	return status;
2126 }
2127 
2128 
2129 #ifndef ELF32_COMPAT
2130 
2131 image_id
2132 load_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 			case PT_ARM_UNWIND:
2290 				continue;
2291 			default:
2292 				dprintf("%s: unhandled pheader type %#" B_PRIx32 "\n", fileName,
2293 					programHeaders[i].p_type);
2294 				continue;
2295 		}
2296 
2297 		// we're here, so it must be a PT_LOAD segment
2298 
2299 		// Usually add-ons have two PT_LOAD headers: one for .data one or .text.
2300 		// x86 and PPC may differ in permission bits for .data's PT_LOAD header
2301 		// x86 is usually RW, PPC is RWE
2302 
2303 		// Some add-ons may have .text and .data concatenated in a single
2304 		// PT_LOAD RWE header and we must map that to .text.
2305 		if (programHeaders[i].IsReadWrite()
2306 			&& (!programHeaders[i].IsExecutable()
2307 				|| executableHeaderCount > 1)) {
2308 			// this is the writable segment
2309 			if (image->data_region.size != 0) {
2310 				// we've already created this segment
2311 				continue;
2312 			}
2313 			region = &image->data_region;
2314 
2315 			snprintf(regionName, B_OS_NAME_LENGTH, "%s_data", fileName);
2316 		} else if (programHeaders[i].IsExecutable()) {
2317 			// this is the non-writable segment
2318 			if (image->text_region.size != 0) {
2319 				// we've already created this segment
2320 				continue;
2321 			}
2322 			region = &image->text_region;
2323 
2324 			// some programs may have .text and .data concatenated in a
2325 			// single PT_LOAD section which is readable/writable/executable
2326 			textSectionWritable = programHeaders[i].IsReadWrite();
2327 			snprintf(regionName, B_OS_NAME_LENGTH, "%s_text", fileName);
2328 		} else {
2329 			dprintf("%s: weird program header flags %#" B_PRIx32 "\n", fileName,
2330 				programHeaders[i].p_flags);
2331 			continue;
2332 		}
2333 
2334 		region->start = (addr_t)reservedAddress + ROUNDDOWN(
2335 			programHeaders[i].p_vaddr, B_PAGE_SIZE);
2336 		region->size = ROUNDUP(programHeaders[i].p_memsz
2337 			+ (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE);
2338 		region->id = create_area(regionName, (void **)&region->start,
2339 			B_EXACT_ADDRESS, region->size, B_FULL_LOCK,
2340 			B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
2341 		if (region->id < B_OK) {
2342 			dprintf("%s: error allocating area: %s\n", fileName,
2343 				strerror(region->id));
2344 			status = B_NOT_AN_EXECUTABLE;
2345 			goto error4;
2346 		}
2347 		region->delta = -ROUNDDOWN(programHeaders[i].p_vaddr, B_PAGE_SIZE);
2348 
2349 		TRACE(("elf_load_kspace: created area \"%s\" at %p\n",
2350 			regionName, (void *)region->start));
2351 
2352 		length = _kern_read(fd, programHeaders[i].p_offset,
2353 			(void *)(region->start + (programHeaders[i].p_vaddr % B_PAGE_SIZE)),
2354 			programHeaders[i].p_filesz);
2355 		if (length < B_OK) {
2356 			status = length;
2357 			dprintf("%s: error reading in segment %" B_PRId32 "\n", fileName,
2358 				i);
2359 			goto error5;
2360 		}
2361 	}
2362 
2363 	image->data_region.delta += image->data_region.start;
2364 	image->text_region.delta += image->text_region.start;
2365 
2366 	// modify the dynamic ptr by the delta of the regions
2367 	image->dynamic_section += image->text_region.delta;
2368 
2369 	status = elf_parse_dynamic_section(image);
2370 	if (status < B_OK)
2371 		goto error5;
2372 
2373 	status = init_image_version_infos(image);
2374 	if (status != B_OK)
2375 		goto error5;
2376 
2377 	status = check_needed_image_versions(image);
2378 	if (status != B_OK)
2379 		goto error5;
2380 
2381 	status = elf_relocate(image, sKernelImage);
2382 	if (status < B_OK)
2383 		goto error5;
2384 
2385 	// We needed to read in the contents of the "text" area, but
2386 	// now we can protect it read-only/execute, unless this is a
2387 	// special image with concatenated .text and .data, when it
2388 	// will also need write access.
2389 	set_area_protection(image->text_region.id,
2390 		B_KERNEL_READ_AREA | B_KERNEL_EXECUTE_AREA
2391 		| (textSectionWritable ? B_KERNEL_WRITE_AREA : 0));
2392 
2393 	// There might be a hole between the two segments, and we don't need to
2394 	// reserve this any longer
2395 	vm_unreserve_address_range(VMAddressSpace::KernelID(), reservedAddress,
2396 		reservedSize);
2397 
2398 	if (sLoadElfSymbols)
2399 		load_elf_symbol_table(fd, image);
2400 
2401 	free(programHeaders);
2402 	mutex_lock(&sImageMutex);
2403 	register_elf_image(image);
2404 	mutex_unlock(&sImageMutex);
2405 
2406 done:
2407 	_kern_close(fd);
2408 	mutex_unlock(&sImageLoadMutex);
2409 
2410 	return image->id;
2411 
2412 error5:
2413 error4:
2414 	vm_unreserve_address_range(VMAddressSpace::KernelID(), reservedAddress,
2415 		reservedSize);
2416 error3:
2417 	free(programHeaders);
2418 error2:
2419 	delete_elf_image(image);
2420 	elfHeader = NULL;
2421 error1:
2422 	free(elfHeader);
2423 error:
2424 	mutex_unlock(&sImageLoadMutex);
2425 error0:
2426 	dprintf("Could not load kernel add-on \"%s\": %s\n", path,
2427 		strerror(status));
2428 
2429 	if (vnode)
2430 		vfs_put_vnode(vnode);
2431 	_kern_close(fd);
2432 
2433 	return status;
2434 }
2435 
2436 
2437 status_t
2438 unload_kernel_add_on(image_id id)
2439 {
2440 	MutexLocker _(sImageLoadMutex);
2441 	MutexLocker _2(sImageMutex);
2442 
2443 	elf_image_info *image = find_image(id);
2444 	if (image == NULL)
2445 		return B_BAD_IMAGE_ID;
2446 
2447 	unload_elf_image(image);
2448 	return B_OK;
2449 }
2450 
2451 
2452 struct elf_image_info*
2453 elf_get_kernel_image()
2454 {
2455 	return sKernelImage;
2456 }
2457 
2458 
2459 status_t
2460 elf_get_image_info_for_address(addr_t address, image_info* info)
2461 {
2462 	MutexLocker _(sImageMutex);
2463 	struct elf_image_info* elfInfo = find_image_at_address(address);
2464 	if (elfInfo == NULL)
2465 		return B_ENTRY_NOT_FOUND;
2466 
2467 	info->id = elfInfo->id;
2468 	info->type = B_SYSTEM_IMAGE;
2469 	info->sequence = 0;
2470 	info->init_order = 0;
2471 	info->init_routine = NULL;
2472 	info->term_routine = NULL;
2473 	info->device = -1;
2474 	info->node = -1;
2475 		// TODO: We could actually fill device/node in.
2476 	strlcpy(info->name, elfInfo->name, sizeof(info->name));
2477 	info->text = (void*)elfInfo->text_region.start;
2478 	info->data = (void*)elfInfo->data_region.start;
2479 	info->text_size = elfInfo->text_region.size;
2480 	info->data_size = elfInfo->data_region.size;
2481 
2482 	return B_OK;
2483 }
2484 
2485 
2486 image_id
2487 elf_create_memory_image(const char* imageName, addr_t text, size_t textSize,
2488 	addr_t data, size_t dataSize)
2489 {
2490 	// allocate the image
2491 	elf_image_info* image = create_image_struct();
2492 	if (image == NULL)
2493 		return B_NO_MEMORY;
2494 	MemoryDeleter imageDeleter(image);
2495 
2496 	// allocate symbol and string tables -- we allocate an empty symbol table,
2497 	// so that elf_debug_lookup_symbol_address() won't try the dynamic symbol
2498 	// table, which we don't have.
2499 	elf_sym* symbolTable = (elf_sym*)malloc(0);
2500 	char* stringTable = (char*)malloc(1);
2501 	MemoryDeleter symbolTableDeleter(symbolTable);
2502 	MemoryDeleter stringTableDeleter(stringTable);
2503 	if (symbolTable == NULL || stringTable == NULL)
2504 		return B_NO_MEMORY;
2505 
2506 	// the string table always contains the empty string
2507 	stringTable[0] = '\0';
2508 
2509 	image->debug_symbols = symbolTable;
2510 	image->num_debug_symbols = 0;
2511 	image->debug_string_table = stringTable;
2512 
2513 	// dup image name
2514 	image->name = strdup(imageName);
2515 	if (image->name == NULL)
2516 		return B_NO_MEMORY;
2517 
2518 	// data and text region
2519 	image->text_region.id = -1;
2520 	image->text_region.start = text;
2521 	image->text_region.size = textSize;
2522 	image->text_region.delta = 0;
2523 
2524 	image->data_region.id = -1;
2525 	image->data_region.start = data;
2526 	image->data_region.size = dataSize;
2527 	image->data_region.delta = 0;
2528 
2529 	mutex_lock(&sImageMutex);
2530 	register_elf_image(image);
2531 	image_id imageID = image->id;
2532 	mutex_unlock(&sImageMutex);
2533 
2534 	// keep the allocated memory
2535 	imageDeleter.Detach();
2536 	symbolTableDeleter.Detach();
2537 	stringTableDeleter.Detach();
2538 
2539 	return imageID;
2540 }
2541 
2542 
2543 status_t
2544 elf_add_memory_image_symbol(image_id id, const char* name, addr_t address,
2545 	size_t size, int32 type)
2546 {
2547 	MutexLocker _(sImageMutex);
2548 
2549 	// get the image
2550 	struct elf_image_info* image = find_image(id);
2551 	if (image == NULL)
2552 		return B_ENTRY_NOT_FOUND;
2553 
2554 	// get the current string table size
2555 	size_t stringTableSize = 1;
2556 	if (image->num_debug_symbols > 0) {
2557 		for (int32 i = image->num_debug_symbols - 1; i >= 0; i--) {
2558 			int32 nameIndex = image->debug_symbols[i].st_name;
2559 			if (nameIndex != 0) {
2560 				stringTableSize = nameIndex
2561 					+ strlen(image->debug_string_table + nameIndex) + 1;
2562 				break;
2563 			}
2564 		}
2565 	}
2566 
2567 	// enter the name in the string table
2568 	char* stringTable = (char*)image->debug_string_table;
2569 	size_t stringIndex = 0;
2570 	if (name != NULL) {
2571 		size_t nameSize = strlen(name) + 1;
2572 		stringIndex = stringTableSize;
2573 		stringTableSize += nameSize;
2574 		stringTable = (char*)realloc((char*)image->debug_string_table,
2575 			stringTableSize);
2576 		if (stringTable == NULL)
2577 			return B_NO_MEMORY;
2578 		image->debug_string_table = stringTable;
2579 		memcpy(stringTable + stringIndex, name, nameSize);
2580 	}
2581 
2582 	// resize the symbol table
2583 	int32 symbolCount = image->num_debug_symbols + 1;
2584 	elf_sym* symbolTable = (elf_sym*)realloc(
2585 		(elf_sym*)image->debug_symbols, sizeof(elf_sym) * symbolCount);
2586 	if (symbolTable == NULL)
2587 		return B_NO_MEMORY;
2588 	image->debug_symbols = symbolTable;
2589 
2590 	// enter the symbol
2591 	elf_sym& symbol = symbolTable[symbolCount - 1];
2592 	symbol.SetInfo(STB_GLOBAL,
2593 		type == B_SYMBOL_TYPE_DATA ? STT_OBJECT : STT_FUNC);
2594 	symbol.st_name = stringIndex;
2595 	symbol.st_value = address;
2596 	symbol.st_size = size;
2597 	symbol.st_other = 0;
2598 	symbol.st_shndx = 0;
2599 	image->num_debug_symbols++;
2600 
2601 	return B_OK;
2602 }
2603 
2604 
2605 /*!	Reads the symbol and string table for the kernel image with the given ID.
2606 	\a _symbolCount and \a _stringTableSize are both in- and output parameters.
2607 	When called they call the size of the buffers given by \a symbolTable and
2608 	\a stringTable respectively. When the function returns successfully, they
2609 	will contain the actual sizes (which can be greater than the original ones).
2610 	The function will copy as much as possible into the buffers. For only
2611 	getting the required buffer sizes, it can be invoked with \c NULL buffers.
2612 	On success \a _imageDelta will contain the offset to be added to the symbol
2613 	values in the table to get the actual symbol addresses.
2614 */
2615 status_t
2616 elf_read_kernel_image_symbols(image_id id, elf_sym* symbolTable,
2617 	int32* _symbolCount, char* stringTable, size_t* _stringTableSize,
2618 	addr_t* _imageDelta, bool kernel)
2619 {
2620 	// check params
2621 	if (_symbolCount == NULL || _stringTableSize == NULL)
2622 		return B_BAD_VALUE;
2623 	if (!kernel) {
2624 		if (!IS_USER_ADDRESS(_symbolCount) || !IS_USER_ADDRESS(_stringTableSize)
2625 			|| (_imageDelta != NULL && !IS_USER_ADDRESS(_imageDelta))
2626 			|| (symbolTable != NULL && !IS_USER_ADDRESS(symbolTable))
2627 			|| (stringTable != NULL && !IS_USER_ADDRESS(stringTable))) {
2628 			return B_BAD_ADDRESS;
2629 		}
2630 	}
2631 
2632 	// get buffer sizes
2633 	int32 maxSymbolCount;
2634 	size_t maxStringTableSize;
2635 	if (kernel) {
2636 		maxSymbolCount = *_symbolCount;
2637 		maxStringTableSize = *_stringTableSize;
2638 	} else {
2639 		if (user_memcpy(&maxSymbolCount, _symbolCount, sizeof(maxSymbolCount))
2640 				!= B_OK
2641 			|| user_memcpy(&maxStringTableSize, _stringTableSize,
2642 				sizeof(maxStringTableSize)) != B_OK) {
2643 			return B_BAD_ADDRESS;
2644 		}
2645 	}
2646 
2647 	// find the image
2648 	MutexLocker _(sImageMutex);
2649 	struct elf_image_info* image = find_image(id);
2650 	if (image == NULL)
2651 		return B_ENTRY_NOT_FOUND;
2652 
2653 	// get the tables and infos
2654 	addr_t imageDelta = image->text_region.delta;
2655 	const elf_sym* symbols;
2656 	int32 symbolCount;
2657 	const char* strings;
2658 
2659 	if (image->debug_symbols != NULL) {
2660 		symbols = image->debug_symbols;
2661 		symbolCount = image->num_debug_symbols;
2662 		strings = image->debug_string_table;
2663 	} else {
2664 		symbols = image->syms;
2665 		symbolCount = image->symhash[1];
2666 		strings = image->strtab;
2667 	}
2668 
2669 	// The string table size isn't stored in the elf_image_info structure. Find
2670 	// out by iterating through all symbols.
2671 	size_t stringTableSize = 0;
2672 	for (int32 i = 0; i < symbolCount; i++) {
2673 		size_t index = symbols[i].st_name;
2674 		if (index > stringTableSize)
2675 			stringTableSize = index;
2676 	}
2677 	stringTableSize += strlen(strings + stringTableSize) + 1;
2678 		// add size of the last string
2679 
2680 	// copy symbol table
2681 	int32 symbolsToCopy = min_c(symbolCount, maxSymbolCount);
2682 	if (symbolTable != NULL && symbolsToCopy > 0) {
2683 		if (kernel) {
2684 			memcpy(symbolTable, symbols, sizeof(elf_sym) * symbolsToCopy);
2685 		} else if (user_memcpy(symbolTable, symbols,
2686 				sizeof(elf_sym) * symbolsToCopy) != B_OK) {
2687 			return B_BAD_ADDRESS;
2688 		}
2689 	}
2690 
2691 	// copy string table
2692 	size_t stringsToCopy = min_c(stringTableSize, maxStringTableSize);
2693 	if (stringTable != NULL && stringsToCopy > 0) {
2694 		if (kernel) {
2695 			memcpy(stringTable, strings, stringsToCopy);
2696 		} else {
2697 			if (user_memcpy(stringTable, strings, stringsToCopy)
2698 					!= B_OK) {
2699 				return B_BAD_ADDRESS;
2700 			}
2701 		}
2702 	}
2703 
2704 	// copy sizes
2705 	if (kernel) {
2706 		*_symbolCount = symbolCount;
2707 		*_stringTableSize = stringTableSize;
2708 		if (_imageDelta != NULL)
2709 			*_imageDelta = imageDelta;
2710 	} else {
2711 		if (user_memcpy(_symbolCount, &symbolCount, sizeof(symbolCount)) != B_OK
2712 			|| user_memcpy(_stringTableSize, &stringTableSize,
2713 					sizeof(stringTableSize)) != B_OK
2714 			|| (_imageDelta != NULL && user_memcpy(_imageDelta, &imageDelta,
2715 					sizeof(imageDelta)) != B_OK)) {
2716 			return B_BAD_ADDRESS;
2717 		}
2718 	}
2719 
2720 	return B_OK;
2721 }
2722 
2723 
2724 status_t
2725 elf_init(kernel_args* args)
2726 {
2727 	struct preloaded_image* image;
2728 
2729 	image_init();
2730 
2731 	if (void* handle = load_driver_settings("kernel")) {
2732 		sLoadElfSymbols = get_driver_boolean_parameter(handle, "load_symbols",
2733 			false, false);
2734 
2735 		unload_driver_settings(handle);
2736 	}
2737 
2738 	sImagesHash = new(std::nothrow) ImageHash();
2739 	if (sImagesHash == NULL)
2740 		return B_NO_MEMORY;
2741 	status_t init = sImagesHash->Init(IMAGE_HASH_SIZE);
2742 	if (init != B_OK)
2743 		return init;
2744 
2745 	// Build a image structure for the kernel, which has already been loaded.
2746 	// The preloaded_images were already prepared by the VM.
2747 	image = args->kernel_image;
2748 	if (insert_preloaded_image(static_cast<preloaded_elf_image *>(image),
2749 			true) < B_OK)
2750 		panic("could not create kernel image.\n");
2751 
2752 	// Build image structures for all preloaded images.
2753 	for (image = args->preloaded_images; image != NULL; image = image->next)
2754 		insert_preloaded_image(static_cast<preloaded_elf_image *>(image),
2755 			false);
2756 
2757 	add_debugger_command("ls", &dump_address_info,
2758 		"lookup symbol for a particular address");
2759 	add_debugger_command("symbols", &dump_symbols, "dump symbols for image");
2760 	add_debugger_command("symbol", &dump_symbol, "search symbol in images");
2761 	add_debugger_command_etc("image", &dump_image, "dump image info",
2762 		"Prints info about the specified image.\n"
2763 		"  <image>  - pointer to the semaphore structure, or ID\n"
2764 		"           of the image to print info for.\n", 0);
2765 
2766 	sInitialized = true;
2767 	return B_OK;
2768 }
2769 
2770 
2771 // #pragma mark -
2772 
2773 
2774 /*!	Reads the symbol and string table for the kernel image with the given ID.
2775 	\a _symbolCount and \a _stringTableSize are both in- and output parameters.
2776 	When called they call the size of the buffers given by \a symbolTable and
2777 	\a stringTable respectively. When the function returns successfully, they
2778 	will contain the actual sizes (which can be greater than the original ones).
2779 	The function will copy as much as possible into the buffers. For only
2780 	getting the required buffer sizes, it can be invoked with \c NULL buffers.
2781 	On success \a _imageDelta will contain the offset to be added to the symbol
2782 	values in the table to get the actual symbol addresses.
2783 */
2784 status_t
2785 _user_read_kernel_image_symbols(image_id id, elf_sym* symbolTable,
2786 	int32* _symbolCount, char* stringTable, size_t* _stringTableSize,
2787 	addr_t* _imageDelta)
2788 {
2789 	return elf_read_kernel_image_symbols(id, symbolTable, _symbolCount,
2790 		stringTable, _stringTableSize, _imageDelta, false);
2791 }
2792 
2793 #endif // ELF32_COMPAT
2794 
2795