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