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