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