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