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