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