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