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