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