xref: /haiku/src/system/kernel/elf.cpp (revision 0562493379cd52eb7103531f895f10bb8e77c085)
1 /*
2  * Copyright 2002-2008, Axel Dörfler, axeld@pinc-software.de.
3  * Distributed under the terms of the MIT License.
4  *
5  * Copyright 2001, Travis Geiselbrecht. All rights reserved.
6  * Distributed under the terms of the NewOS License.
7  */
8 
9 /*!	Contains the ELF loader */
10 
11 #include <elf.h>
12 
13 #include <OS.h>
14 
15 #include <unistd.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <stdio.h>
19 #include <ctype.h>
20 
21 #include <AutoDeleter.h>
22 #include <debug.h>
23 #include <kernel.h>
24 #include <kimage.h>
25 #include <syscalls.h>
26 #include <team.h>
27 #include <thread.h>
28 #include <runtime_loader.h>
29 #include <util/AutoLock.h>
30 #include <util/khash.h>
31 #include <vfs.h>
32 #include <vm.h>
33 #include <vm_address_space.h>
34 #include <vm_types.h>
35 
36 #include <arch/cpu.h>
37 #include <arch/elf.h>
38 #include <elf_priv.h>
39 #include <boot/elf.h>
40 
41 //#define TRACE_ELF
42 #ifdef TRACE_ELF
43 #	define TRACE(x) dprintf x
44 #else
45 #	define TRACE(x) ;
46 #endif
47 
48 
49 #define IMAGE_HASH_SIZE 16
50 
51 static hash_table *sImagesHash;
52 
53 static struct elf_image_info *sKernelImage = NULL;
54 static mutex sImageMutex = MUTEX_INITIALIZER("kimages_lock");
55 	// guards sImagesHash
56 static mutex sImageLoadMutex = MUTEX_INITIALIZER("kimages_load_lock");
57 	// serializes loading/unloading add-ons locking order
58 	// sImageLoadMutex -> sImageMutex
59 static bool sInitialized = false;
60 
61 
62 /*! Calculates hash for an image using its ID */
63 static uint32
64 image_hash(void *_image, const void *_key, uint32 range)
65 {
66 	struct elf_image_info *image = (struct elf_image_info *)_image;
67 	image_id id = (image_id)_key;
68 
69 	if (image != NULL)
70 		return image->id % range;
71 
72 	return (uint32)id % range;
73 }
74 
75 
76 /*!	Compares an image to a given ID */
77 static int
78 image_compare(void *_image, const void *_key)
79 {
80 	struct elf_image_info *image = (struct elf_image_info *)_image;
81 	image_id id = (image_id)_key;
82 
83 	return id - image->id;
84 }
85 
86 
87 static void
88 unregister_elf_image(struct elf_image_info *image)
89 {
90 	unregister_image(team_get_kernel_team(), image->id);
91 	hash_remove(sImagesHash, image);
92 }
93 
94 
95 static void
96 register_elf_image(struct elf_image_info *image)
97 {
98 	image_info imageInfo;
99 
100 	memset(&imageInfo, 0, sizeof(image_info));
101 	imageInfo.id = image->id;
102 	imageInfo.type = B_SYSTEM_IMAGE;
103 	strlcpy(imageInfo.name, image->name, sizeof(imageInfo.name));
104 
105 	imageInfo.text = (void *)image->text_region.start;
106 	imageInfo.text_size = image->text_region.size;
107 	imageInfo.data = (void *)image->data_region.start;
108 	imageInfo.data_size = image->data_region.size;
109 
110 	image->id = register_image(team_get_kernel_team(), &imageInfo,
111 		sizeof(image_info));
112 	hash_insert(sImagesHash, image);
113 }
114 
115 
116 /*!	Note, you must lock the image mutex when you call this function. */
117 static struct elf_image_info *
118 find_image_at_address(addr_t address)
119 {
120 	struct hash_iterator iterator;
121 	struct elf_image_info *image;
122 
123 #if KDEBUG
124 	if (!debug_debugger_running())
125 		ASSERT_LOCKED_MUTEX(&sImageMutex);
126 #endif
127 
128 	hash_open(sImagesHash, &iterator);
129 
130 	// get image that may contain the address
131 
132 	while ((image = (elf_image_info *)hash_next(sImagesHash, &iterator))
133 			!= NULL) {
134 		if ((address >= image->text_region.start && address
135 				<= (image->text_region.start + image->text_region.size))
136 			|| (address >= image->data_region.start
137 				&& address
138 					<= (image->data_region.start + image->data_region.size)))
139 			break;
140 	}
141 
142 	hash_close(sImagesHash, &iterator, false);
143 	return image;
144 }
145 
146 
147 static int
148 dump_address_info(int argc, char **argv)
149 {
150 	const char *symbol, *imageName;
151 	bool exactMatch;
152 	addr_t address, baseAddress;
153 
154 	if (argc < 2) {
155 		kprintf("usage: ls <address>\n");
156 		return 0;
157 	}
158 
159 	address = strtoul(argv[1], NULL, 16);
160 
161 	status_t error;
162 
163 	if (IS_KERNEL_ADDRESS(address)) {
164 		error = elf_debug_lookup_symbol_address(address, &baseAddress, &symbol,
165 			&imageName, &exactMatch);
166 	} else {
167 		error = elf_debug_lookup_user_symbol_address(
168 			debug_get_debugged_thread()->team, address, &baseAddress, &symbol,
169 			&imageName, &exactMatch);
170 	}
171 
172 	if (error == B_OK) {
173 		kprintf("%p = %s + 0x%lx (%s)%s\n", (void*)address, symbol,
174 			address - baseAddress, imageName, exactMatch ? "" : " (nearest)");
175 	} else
176 		kprintf("There is no image loaded at this address!\n");
177 
178 	return 0;
179 }
180 
181 
182 static struct elf_image_info *
183 find_image(image_id id)
184 {
185 	return (elf_image_info *)hash_lookup(sImagesHash, (void *)id);
186 }
187 
188 
189 static struct elf_image_info *
190 find_image_by_vnode(void *vnode)
191 {
192 	struct hash_iterator iterator;
193 	struct elf_image_info *image;
194 
195 	mutex_lock(&sImageMutex);
196 	hash_open(sImagesHash, &iterator);
197 
198 	while ((image = (elf_image_info *)hash_next(sImagesHash, &iterator))
199 			!= NULL) {
200 		if (image->vnode == vnode)
201 			break;
202 	}
203 
204 	hash_close(sImagesHash, &iterator, false);
205 	mutex_unlock(&sImageMutex);
206 
207 	return image;
208 }
209 
210 
211 static struct elf_image_info *
212 create_image_struct()
213 {
214 	struct elf_image_info *image
215 		= (struct elf_image_info *)malloc(sizeof(struct elf_image_info));
216 	if (image == NULL)
217 		return NULL;
218 
219 	memset(image, 0, sizeof(struct elf_image_info));
220 
221 	image->text_region.id = -1;
222 	image->data_region.id = -1;
223 	image->ref_count = 1;
224 
225 	return image;
226 }
227 
228 
229 static uint32
230 elf_hash(const char *name)
231 {
232 	uint32 hash = 0;
233 	uint32 temp;
234 
235 	while (*name) {
236 		hash = (hash << 4) + (uint8)*name++;
237 		if ((temp = hash & 0xf0000000) != 0)
238 			hash ^= temp >> 24;
239 		hash &= ~temp;
240 	}
241 	return hash;
242 }
243 
244 
245 static const char *
246 get_symbol_type_string(struct Elf32_Sym *symbol)
247 {
248 	switch (ELF32_ST_TYPE(symbol->st_info)) {
249 		case STT_FUNC:
250 			return "func";
251 		case STT_OBJECT:
252 			return " obj";
253 		case STT_FILE:
254 			return "file";
255 		default:
256 			return "----";
257 	}
258 }
259 
260 
261 static const char *
262 get_symbol_bind_string(struct Elf32_Sym *symbol)
263 {
264 	switch (ELF32_ST_BIND(symbol->st_info)) {
265 		case STB_LOCAL:
266 			return "loc ";
267 		case STB_GLOBAL:
268 			return "glob";
269 		case STB_WEAK:
270 			return "weak";
271 		default:
272 			return "----";
273 	}
274 }
275 
276 
277 /*!	Searches a symbol (pattern) in all kernel images */
278 static int
279 dump_symbol(int argc, char **argv)
280 {
281 	if (argc != 2 || !strcmp(argv[1], "--help")) {
282 		kprintf("usage: %s <symbol-name>\n", argv[0]);
283 		return 0;
284 	}
285 
286 	struct elf_image_info *image = NULL;
287 	struct hash_iterator iterator;
288 	const char *pattern = argv[1];
289 
290 	void* symbolAddress = NULL;
291 
292 	hash_open(sImagesHash, &iterator);
293 	while ((image = (elf_image_info *)hash_next(sImagesHash, &iterator))
294 			!= NULL) {
295 		if (image->num_debug_symbols > 0) {
296 			// search extended debug symbol table (contains static symbols)
297 			for (uint32 i = 0; i < image->num_debug_symbols; i++) {
298 				struct Elf32_Sym *symbol = &image->debug_symbols[i];
299 				const char *name = image->debug_string_table + symbol->st_name;
300 
301 				if (symbol->st_value > 0 && strstr(name, pattern) != 0) {
302 					symbolAddress
303 						= (void*)(symbol->st_value + image->text_region.delta);
304 					kprintf("%p %5lu %s:%s\n", symbolAddress, symbol->st_size,
305 						image->name, name);
306 				}
307 			}
308 		} else {
309 			// search standard symbol lookup table
310 			for (uint32 i = 0; i < HASHTABSIZE(image); i++) {
311 				for (uint32 j = HASHBUCKETS(image)[i]; j != STN_UNDEF;
312 						j = HASHCHAINS(image)[j]) {
313 					struct Elf32_Sym *symbol = &image->syms[j];
314 					const char *name = SYMNAME(image, symbol);
315 
316 					if (symbol->st_value > 0 && strstr(name, pattern) != 0) {
317 						symbolAddress = (void*)(symbol->st_value
318 							+ image->text_region.delta);
319 						kprintf("%p %5lu %s:%s\n", symbolAddress,
320 							symbol->st_size, image->name, name);
321 					}
322 				}
323 			}
324 		}
325 	}
326 	hash_close(sImagesHash, &iterator, false);
327 
328 	if (symbolAddress != NULL)
329 		set_debug_variable("_", (addr_t)symbolAddress);
330 
331 	return 0;
332 }
333 
334 
335 static int
336 dump_symbols(int argc, char **argv)
337 {
338 	struct elf_image_info *image = NULL;
339 	struct hash_iterator iterator;
340 	uint32 i;
341 
342 	// if the argument looks like a hex number, treat it as such
343 	if (argc > 1) {
344 		if (isdigit(argv[1][0])) {
345 			uint32 num = strtoul(argv[1], NULL, 0);
346 
347 			if (IS_KERNEL_ADDRESS(num)) {
348 				// find image at address
349 
350 				hash_open(sImagesHash, &iterator);
351 				while ((image = (elf_image_info *)hash_next(sImagesHash,
352 						&iterator)) != NULL) {
353 					if (image->text_region.start <= num
354 						&& image->text_region.start + image->text_region.size
355 							>= num)
356 						break;
357 				}
358 				hash_close(sImagesHash, &iterator, false);
359 
360 				if (image == NULL)
361 					kprintf("No image covers 0x%lx in the kernel!\n", num);
362 			} else {
363 				image = (elf_image_info *)hash_lookup(sImagesHash, (void *)num);
364 				if (image == NULL)
365 					kprintf("image 0x%lx doesn't exist in the kernel!\n", num);
366 			}
367 		} else {
368 			// look for image by name
369 			hash_open(sImagesHash, &iterator);
370 			while ((image = (elf_image_info *)hash_next(sImagesHash,
371 					&iterator)) != NULL) {
372 				if (!strcmp(image->name, argv[1]))
373 					break;
374 			}
375 			hash_close(sImagesHash, &iterator, false);
376 
377 			if (image == NULL)
378 				kprintf("No image \"%s\" found in kernel!\n", argv[1]);
379 		}
380 	} else {
381 		kprintf("usage: %s image_name/image_id/address_in_image\n", argv[0]);
382 		return 0;
383 	}
384 
385 	if (image == NULL)
386 		return -1;
387 
388 	// dump symbols
389 
390 	kprintf("Symbols of image %ld \"%s\":\nAddress  Type       Size Name\n",
391 		image->id, image->name);
392 
393 	if (image->num_debug_symbols > 0) {
394 		// search extended debug symbol table (contains static symbols)
395 		for (i = 0; i < image->num_debug_symbols; i++) {
396 			struct Elf32_Sym *symbol = &image->debug_symbols[i];
397 
398 			if (symbol->st_value == 0 || symbol->st_size
399 					>= image->text_region.size + image->data_region.size)
400 				continue;
401 
402 			kprintf("%08lx %s/%s %5ld %s\n",
403 				symbol->st_value + image->text_region.delta,
404 				get_symbol_type_string(symbol), get_symbol_bind_string(symbol),
405 				symbol->st_size, image->debug_string_table + symbol->st_name);
406 		}
407 	} else {
408 		int32 j;
409 
410 		// search standard symbol lookup table
411 		for (i = 0; i < HASHTABSIZE(image); i++) {
412 			for (j = HASHBUCKETS(image)[i]; j != STN_UNDEF;
413 					j = HASHCHAINS(image)[j]) {
414 				struct Elf32_Sym *symbol = &image->syms[j];
415 
416 				if (symbol->st_value == 0 || symbol->st_size
417 						>= image->text_region.size + image->data_region.size)
418 					continue;
419 
420 				kprintf("%08lx %s/%s %5ld %s\n",
421 					symbol->st_value + image->text_region.delta,
422 					get_symbol_type_string(symbol),
423 					get_symbol_bind_string(symbol),
424 					symbol->st_size, SYMNAME(image, symbol));
425 			}
426 		}
427 	}
428 
429 	return 0;
430 }
431 
432 
433 static void
434 dump_elf_region(struct elf_region *region, const char *name)
435 {
436 	kprintf("   %s.id %ld\n", name, region->id);
437 	kprintf("   %s.start 0x%lx\n", name, region->start);
438 	kprintf("   %s.size 0x%lx\n", name, region->size);
439 	kprintf("   %s.delta %ld\n", name, region->delta);
440 }
441 
442 
443 static void
444 dump_image_info(struct elf_image_info *image)
445 {
446 	kprintf("elf_image_info at %p:\n", image);
447 	kprintf(" next %p\n", image->next);
448 	kprintf(" id %ld\n", image->id);
449 	dump_elf_region(&image->text_region, "text");
450 	dump_elf_region(&image->data_region, "data");
451 	kprintf(" dynamic_section 0x%lx\n", image->dynamic_section);
452 	kprintf(" needed %p\n", image->needed);
453 	kprintf(" symhash %p\n", image->symhash);
454 	kprintf(" syms %p\n", image->syms);
455 	kprintf(" strtab %p\n", image->strtab);
456 	kprintf(" rel %p\n", image->rel);
457 	kprintf(" rel_len 0x%x\n", image->rel_len);
458 	kprintf(" rela %p\n", image->rela);
459 	kprintf(" rela_len 0x%x\n", image->rela_len);
460 	kprintf(" pltrel %p\n", image->pltrel);
461 	kprintf(" pltrel_len 0x%x\n", image->pltrel_len);
462 
463 	kprintf(" debug_symbols %p (%ld)\n",
464 		image->debug_symbols, image->num_debug_symbols);
465 }
466 
467 
468 static int
469 dump_image(int argc, char **argv)
470 {
471 	struct hash_iterator iterator;
472 	struct elf_image_info *image;
473 
474 	// if the argument looks like a hex number, treat it as such
475 	if (argc > 1) {
476 		uint32 num = strtoul(argv[1], NULL, 0);
477 
478 		if (IS_KERNEL_ADDRESS(num)) {
479 			// semi-hack
480 			dump_image_info((struct elf_image_info *)num);
481 		} else {
482 			image = (elf_image_info *)hash_lookup(sImagesHash, (void *)num);
483 			if (image == NULL)
484 				kprintf("image 0x%lx doesn't exist in the kernel!\n", num);
485 			else
486 				dump_image_info(image);
487 		}
488 		return 0;
489 	}
490 
491 	kprintf("loaded kernel images:\n");
492 
493 	hash_open(sImagesHash, &iterator);
494 
495 	while ((image = (elf_image_info *)hash_next(sImagesHash, &iterator))
496 			!= NULL) {
497 		kprintf("%p (%ld) %s\n", image, image->id, image->name);
498 	}
499 
500 	hash_close(sImagesHash, &iterator, false);
501 	return 0;
502 }
503 
504 
505 // Currently unused
506 #if 0
507 static
508 void dump_symbol(struct elf_image_info *image, struct Elf32_Sym *sym)
509 {
510 
511 	kprintf("symbol at %p, in image %p\n", sym, image);
512 
513 	kprintf(" name index %d, '%s'\n", sym->st_name, SYMNAME(image, sym));
514 	kprintf(" st_value 0x%x\n", sym->st_value);
515 	kprintf(" st_size %d\n", sym->st_size);
516 	kprintf(" st_info 0x%x\n", sym->st_info);
517 	kprintf(" st_other 0x%x\n", sym->st_other);
518 	kprintf(" st_shndx %d\n", sym->st_shndx);
519 }
520 #endif
521 
522 
523 static struct Elf32_Sym *
524 elf_find_symbol(struct elf_image_info *image, const char *name)
525 {
526 	if (image->dynamic_section == 0 || HASHTABSIZE(image) == 0)
527 		return NULL;
528 
529 	uint32 hash = elf_hash(name) % HASHTABSIZE(image);
530 	for (uint32 i = HASHBUCKETS(image)[hash]; i != STN_UNDEF;
531 			i = HASHCHAINS(image)[i]) {
532 		if (!strcmp(SYMNAME(image, &image->syms[i]), name))
533 			return &image->syms[i];
534 	}
535 
536 	return NULL;
537 }
538 
539 
540 static status_t
541 elf_parse_dynamic_section(struct elf_image_info *image)
542 {
543 	struct Elf32_Dyn *d;
544 	int32 neededOffset = -1;
545 
546 	TRACE(("top of elf_parse_dynamic_section\n"));
547 
548 	image->symhash = 0;
549 	image->syms = 0;
550 	image->strtab = 0;
551 
552 	d = (struct Elf32_Dyn *)image->dynamic_section;
553 	if (!d)
554 		return B_ERROR;
555 
556 	for (int32 i = 0; d[i].d_tag != DT_NULL; i++) {
557 		switch (d[i].d_tag) {
558 			case DT_NEEDED:
559 				neededOffset = d[i].d_un.d_ptr + image->text_region.delta;
560 				break;
561 			case DT_HASH:
562 				image->symhash = (uint32 *)(d[i].d_un.d_ptr
563 					+ image->text_region.delta);
564 				break;
565 			case DT_STRTAB:
566 				image->strtab = (char *)(d[i].d_un.d_ptr
567 					+ image->text_region.delta);
568 				break;
569 			case DT_SYMTAB:
570 				image->syms = (struct Elf32_Sym *)(d[i].d_un.d_ptr
571 					+ image->text_region.delta);
572 				break;
573 			case DT_REL:
574 				image->rel = (struct Elf32_Rel *)(d[i].d_un.d_ptr
575 					+ image->text_region.delta);
576 				break;
577 			case DT_RELSZ:
578 				image->rel_len = d[i].d_un.d_val;
579 				break;
580 			case DT_RELA:
581 				image->rela = (struct Elf32_Rela *)(d[i].d_un.d_ptr
582 					+ image->text_region.delta);
583 				break;
584 			case DT_RELASZ:
585 				image->rela_len = d[i].d_un.d_val;
586 				break;
587 			case DT_JMPREL:
588 				image->pltrel = (struct Elf32_Rel *)(d[i].d_un.d_ptr
589 					+ image->text_region.delta);
590 				break;
591 			case DT_PLTRELSZ:
592 				image->pltrel_len = d[i].d_un.d_val;
593 				break;
594 			case DT_PLTREL:
595 				image->pltrel_type = d[i].d_un.d_val;
596 				break;
597 
598 			default:
599 				continue;
600 		}
601 	}
602 
603 	// lets make sure we found all the required sections
604 	if (!image->symhash || !image->syms || !image->strtab)
605 		return B_ERROR;
606 
607 	TRACE(("needed_offset = %ld\n", neededOffset));
608 
609 	if (neededOffset >= 0)
610 		image->needed = STRING(image, neededOffset);
611 
612 	return B_OK;
613 }
614 
615 
616 /*!	Resolves the \a symbol by linking against \a sharedImage if necessary.
617 	Returns the resolved symbol's address in \a _symbolAddress.
618 	TODO: eventually get rid of "symbolPrepend"
619 */
620 status_t
621 elf_resolve_symbol(struct elf_image_info *image, struct Elf32_Sym *symbol,
622 	struct elf_image_info *sharedImage, const char *symbolPrepend,
623 	addr_t *_symbolAddress)
624 {
625 	switch (symbol->st_shndx) {
626 		case SHN_UNDEF:
627 		{
628 			struct Elf32_Sym *newSymbol;
629 			char newNameBuffer[368];
630 			char *newName;
631 
632 			// patch the symbol name
633 			if (symbolPrepend) {
634 				newName = newNameBuffer;
635 				strlcpy(newName, symbolPrepend, sizeof(newName));
636 				strlcat(newName, SYMNAME(image, symbol), sizeof(newName));
637 			} else
638 				newName = SYMNAME(image, symbol);
639 
640 			// it's undefined, must be outside this image, try the other image
641 			newSymbol = elf_find_symbol(sharedImage, newName);
642 			if (newSymbol == NULL) {
643 				dprintf("\"%s\": could not resolve symbol '%s'\n",
644 					image->name, newName);
645 				return B_MISSING_SYMBOL;
646 			}
647 
648 			// make sure they're the same type
649 			if (ELF32_ST_TYPE(symbol->st_info)
650 					!= ELF32_ST_TYPE(newSymbol->st_info)) {
651 				dprintf("elf_resolve_symbol: found symbol '%s' in shared image "
652 					"but wrong type\n", newName);
653 				return B_MISSING_SYMBOL;
654 			}
655 
656 			if (ELF32_ST_BIND(newSymbol->st_info) != STB_GLOBAL
657 				&& ELF32_ST_BIND(newSymbol->st_info) != STB_WEAK) {
658 				TRACE(("elf_resolve_symbol: found symbol '%s' but not "
659 					"exported\n", newName));
660 				return B_MISSING_SYMBOL;
661 			}
662 
663 			*_symbolAddress = newSymbol->st_value
664 				+ sharedImage->text_region.delta;
665 			return B_OK;
666 		}
667 		case SHN_ABS:
668 			*_symbolAddress = symbol->st_value;
669 			return B_OK;
670 		case SHN_COMMON:
671 			// ToDo: finish this
672 			TRACE(("elf_resolve_symbol: COMMON symbol, finish me!\n"));
673 			return B_ERROR;
674 
675 		default:
676 			// standard symbol
677 			*_symbolAddress = symbol->st_value + image->text_region.delta;
678 			return B_OK;
679 	}
680 }
681 
682 
683 /*! Until we have shared library support, just this links against the kernel */
684 static int
685 elf_relocate(struct elf_image_info *image, const char *symbolPrepend)
686 {
687 	int status = B_NO_ERROR;
688 
689 	TRACE(("top of elf_relocate\n"));
690 
691 	// deal with the rels first
692 	if (image->rel) {
693 		TRACE(("total %i relocs\n",
694 			image->rel_len / (int)sizeof(struct Elf32_Rel)));
695 
696 		status = arch_elf_relocate_rel(image, symbolPrepend, sKernelImage,
697 			image->rel, image->rel_len);
698 		if (status < B_OK)
699 			return status;
700 	}
701 
702 	if (image->pltrel) {
703 		TRACE(("total %i plt-relocs\n",
704 			image->pltrel_len / (int)sizeof(struct Elf32_Rel)));
705 
706 		if (image->pltrel_type == DT_REL) {
707 			status = arch_elf_relocate_rel(image, symbolPrepend, sKernelImage,
708 				image->pltrel, image->pltrel_len);
709 		} else {
710 			status = arch_elf_relocate_rela(image, symbolPrepend, sKernelImage,
711 				(struct Elf32_Rela *)image->pltrel, image->pltrel_len);
712 		}
713 		if (status < B_OK)
714 			return status;
715 	}
716 
717 	if (image->rela) {
718 		status = arch_elf_relocate_rela(image, symbolPrepend, sKernelImage,
719 			image->rela, image->rela_len);
720 		if (status < B_OK)
721 			return status;
722 	}
723 
724 	return status;
725 }
726 
727 
728 static int
729 verify_eheader(struct Elf32_Ehdr *elfHeader)
730 {
731 	if (memcmp(elfHeader->e_ident, ELF_MAGIC, 4) != 0)
732 		return B_NOT_AN_EXECUTABLE;
733 
734 	if (elfHeader->e_ident[4] != ELFCLASS32)
735 		return B_NOT_AN_EXECUTABLE;
736 
737 	if (elfHeader->e_phoff == 0)
738 		return B_NOT_AN_EXECUTABLE;
739 
740 	if (elfHeader->e_phentsize < sizeof(struct Elf32_Phdr))
741 		return B_NOT_AN_EXECUTABLE;
742 
743 	return 0;
744 }
745 
746 
747 static status_t
748 unload_elf_image(struct elf_image_info *image)
749 {
750 	if (atomic_add(&image->ref_count, -1) > 1)
751 		return B_OK;
752 
753 	TRACE(("unload image %ld, %s\n", image->id, image->name));
754 
755 	delete_area(image->text_region.id);
756 	delete_area(image->data_region.id);
757 
758 	if (image->vnode)
759 		vfs_put_vnode(image->vnode);
760 
761 	unregister_elf_image(image);
762 
763 	free(image->debug_symbols);
764 	free((void*)image->debug_string_table);
765 	free(image->elf_header);
766 	free(image->name);
767 	free(image);
768 
769 	return B_NO_ERROR;
770 }
771 
772 
773 static status_t
774 load_elf_symbol_table(int fd, struct elf_image_info *image)
775 {
776 	struct Elf32_Ehdr *elfHeader = image->elf_header;
777 	struct Elf32_Sym *symbolTable = NULL;
778 	struct Elf32_Shdr *stringHeader = NULL;
779 	uint32 numSymbols = 0;
780 	char *stringTable;
781 	status_t status;
782 	ssize_t length;
783 	int32 i;
784 
785 	// get section headers
786 
787 	ssize_t size = elfHeader->e_shnum * elfHeader->e_shentsize;
788 	struct Elf32_Shdr *sectionHeaders = (struct Elf32_Shdr *)malloc(size);
789 	if (sectionHeaders == NULL) {
790 		dprintf("error allocating space for section headers\n");
791 		return B_NO_MEMORY;
792 	}
793 
794 	length = read_pos(fd, elfHeader->e_shoff, sectionHeaders, size);
795 	if (length < size) {
796 		TRACE(("error reading in program headers\n"));
797 		status = B_ERROR;
798 		goto error1;
799 	}
800 
801 	// find symbol table in section headers
802 
803 	for (i = 0; i < elfHeader->e_shnum; i++) {
804 		if (sectionHeaders[i].sh_type == SHT_SYMTAB) {
805 			stringHeader = &sectionHeaders[sectionHeaders[i].sh_link];
806 
807 			if (stringHeader->sh_type != SHT_STRTAB) {
808 				TRACE(("doesn't link to string table\n"));
809 				status = B_BAD_DATA;
810 				goto error1;
811 			}
812 
813 			// read in symbol table
814 			symbolTable
815 				= (struct Elf32_Sym *)malloc(size = sectionHeaders[i].sh_size);
816 			if (symbolTable == NULL) {
817 				status = B_NO_MEMORY;
818 				goto error1;
819 			}
820 
821 			length
822 				= read_pos(fd, sectionHeaders[i].sh_offset, symbolTable, size);
823 			if (length < size) {
824 				TRACE(("error reading in symbol table\n"));
825 				status = B_ERROR;
826 				goto error1;
827 			}
828 
829 			numSymbols = size / sizeof(struct Elf32_Sym);
830 			break;
831 		}
832 	}
833 
834 	if (symbolTable == NULL) {
835 		TRACE(("no symbol table\n"));
836 		status = B_BAD_VALUE;
837 		goto error1;
838 	}
839 
840 	// read in string table
841 
842 	stringTable = (char *)malloc(size = stringHeader->sh_size);
843 	if (stringTable == NULL) {
844 		status = B_NO_MEMORY;
845 		goto error2;
846 	}
847 
848 	length = read_pos(fd, stringHeader->sh_offset, stringTable, size);
849 	if (length < size) {
850 		TRACE(("error reading in string table\n"));
851 		status = B_ERROR;
852 		goto error3;
853 	}
854 
855 	TRACE(("loaded debug %ld symbols\n", numSymbols));
856 
857 	// insert tables into image
858 	image->debug_symbols = symbolTable;
859 	image->num_debug_symbols = numSymbols;
860 	image->debug_string_table = stringTable;
861 
862 	free(sectionHeaders);
863 	return B_OK;
864 
865 error3:
866 	free(stringTable);
867 error2:
868 	free(symbolTable);
869 error1:
870 	free(sectionHeaders);
871 
872 	return status;
873 }
874 
875 
876 static status_t
877 insert_preloaded_image(struct preloaded_image *preloadedImage, bool kernel)
878 {
879 	struct elf_image_info *image;
880 	status_t status;
881 
882 	status = verify_eheader(&preloadedImage->elf_header);
883 	if (status < B_OK)
884 		return status;
885 
886 	image = create_image_struct();
887 	if (image == NULL)
888 		return B_NO_MEMORY;
889 
890 	image->name = strdup(preloadedImage->name);
891 	image->dynamic_section = preloadedImage->dynamic_section.start;
892 
893 	image->text_region = preloadedImage->text_region;
894 	image->data_region = preloadedImage->data_region;
895 
896 	status = elf_parse_dynamic_section(image);
897 	if (status < B_OK)
898 		goto error1;
899 
900 	if (!kernel) {
901 		status = elf_relocate(image, NULL);
902 		if (status < B_OK)
903 			goto error1;
904 	} else
905 		sKernelImage = image;
906 
907 	// copy debug symbols to the kernel heap
908 	if (preloadedImage->debug_symbols != NULL) {
909 		int32 debugSymbolsSize = sizeof(Elf32_Sym)
910 			* preloadedImage->num_debug_symbols;
911 		image->debug_symbols = (Elf32_Sym*)malloc(debugSymbolsSize);
912 		if (image->debug_symbols != NULL) {
913 			memcpy(image->debug_symbols, preloadedImage->debug_symbols,
914 				debugSymbolsSize);
915 		}
916 	}
917 	image->num_debug_symbols = preloadedImage->num_debug_symbols;
918 
919 	// copy debug string table to the kernel heap
920 	if (preloadedImage->debug_string_table != NULL) {
921 		image->debug_string_table = (char*)malloc(
922 			preloadedImage->debug_string_table_size);
923 		if (image->debug_string_table != NULL) {
924 			memcpy((void*)image->debug_string_table,
925 				preloadedImage->debug_string_table,
926 				preloadedImage->debug_string_table_size);
927 		}
928 	}
929 
930 	register_elf_image(image);
931 	preloadedImage->id = image->id;
932 		// modules_init() uses this information to get the preloaded images
933 
934 	// we now no longer need to write to the text area anymore
935 	set_area_protection(image->text_region.id,
936 		B_KERNEL_READ_AREA | B_KERNEL_EXECUTE_AREA);
937 
938 	return B_OK;
939 
940 error1:
941 	free(image);
942 
943 	// clean up preloaded image resources (this image won't be used anymore)
944 	delete_area(preloadedImage->text_region.id);
945 	delete_area(preloadedImage->data_region.id);
946 	preloadedImage->id = -1;
947 
948 	return status;
949 }
950 
951 
952 //	#pragma mark - userland symbol lookup
953 
954 
955 class UserSymbolLookup {
956 public:
957 	static UserSymbolLookup& Default()
958 	{
959 		return sLookup;
960 	}
961 
962 	status_t Init(struct team* team)
963 	{
964 		// find the runtime loader debug area
965 		vm_area* area = team->address_space->areas;
966 		while (area != NULL) {
967 			if (strcmp(area->name, RUNTIME_LOADER_DEBUG_AREA_NAME) == 0)
968 				break;
969 			area = area->address_space_next;
970 		}
971 
972 		if (area == NULL)
973 			return B_ERROR;
974 
975 		// copy the runtime loader data structure
976 		if (!_Read((runtime_loader_debug_area*)area->base, fDebugArea))
977 			return B_BAD_ADDRESS;
978 
979 		return B_OK;
980 	}
981 
982 	status_t LookupSymbolAddress(addr_t address, addr_t *_baseAddress,
983 		const char **_symbolName, const char **_imageName, bool *_exactMatch)
984 	{
985 		// Note, that this function doesn't find all symbols that we would like
986 		// to find. E.g. static functions do not appear in the symbol table
987 		// as function symbols, but as sections without name and size. The
988 		// .symtab section together with the .strtab section, which apparently
989 		// differ from the tables referred to by the .dynamic section, also
990 		// contain proper names and sizes for those symbols. Therefore, to get
991 		// completely satisfying results, we would need to read those tables
992 		// from the shared object.
993 
994 		// get the image for the address
995 		image_t image;
996 		status_t error = _FindImageAtAddress(address, image);
997 		if (error != B_OK)
998 			return error;
999 
1000 		strlcpy(fImageName, image.name, sizeof(fImageName));
1001 
1002 		// symbol hash table size
1003 		uint32 hashTabSize;
1004 		if (!_Read(image.symhash, hashTabSize))
1005 			return B_BAD_ADDRESS;
1006 
1007 		// remote pointers to hash buckets and chains
1008 		const uint32* hashBuckets = image.symhash + 2;
1009 		const uint32* hashChains = image.symhash + 2 + hashTabSize;
1010 
1011 		const elf_region_t& textRegion = image.regions[0];
1012 
1013 		// search the image for the symbol
1014 		Elf32_Sym symbolFound;
1015 		addr_t deltaFound = INT_MAX;
1016 		bool exactMatch = false;
1017 
1018 		// to get rid of the erroneous "uninitialized" warnings
1019 		symbolFound.st_name = 0;
1020 		symbolFound.st_value = 0;
1021 
1022 		for (uint32 i = 0; i < hashTabSize; i++) {
1023 			uint32 bucket;
1024 			if (!_Read(&hashBuckets[i], bucket))
1025 				return B_BAD_ADDRESS;
1026 
1027 			for (uint32 j = bucket; j != STN_UNDEF;
1028 					_Read(&hashChains[j], j) ? 0 : j = STN_UNDEF) {
1029 
1030 				Elf32_Sym symbol;
1031 				if (!_Read(image.syms + j, symbol))
1032 					continue;
1033 
1034 				// The symbol table contains not only symbols referring to
1035 				// functions and data symbols within the shared object, but also
1036 				// referenced symbols of other shared objects, as well as
1037 				// section and file references. We ignore everything but
1038 				// function and data symbols that have an st_value != 0 (0
1039 				// seems to be an indication for a symbol defined elsewhere
1040 				// -- couldn't verify that in the specs though).
1041 				if ((ELF32_ST_TYPE(symbol.st_info) != STT_FUNC
1042 						&& ELF32_ST_TYPE(symbol.st_info) != STT_OBJECT)
1043 					|| symbol.st_value == 0
1044 					|| symbol.st_value + symbol.st_size + textRegion.delta
1045 						> textRegion.vmstart + textRegion.size) {
1046 					continue;
1047 				}
1048 
1049 				// skip symbols starting after the given address
1050 				addr_t symbolAddress = symbol.st_value + textRegion.delta;
1051 				if (symbolAddress > address)
1052 					continue;
1053 				addr_t symbolDelta = address - symbolAddress;
1054 
1055 				if (symbolDelta < deltaFound) {
1056 					deltaFound = symbolDelta;
1057 					symbolFound = symbol;
1058 
1059 					if (symbolDelta >= 0 && symbolDelta < symbol.st_size) {
1060 						// exact match
1061 						exactMatch = true;
1062 						break;
1063 					}
1064 				}
1065 			}
1066 		}
1067 
1068 		if (_imageName)
1069 			*_imageName = fImageName;
1070 
1071 		if (_symbolName) {
1072 			*_symbolName = NULL;
1073 
1074 			if (deltaFound < INT_MAX) {
1075 				if (_ReadString(image, symbolFound.st_name, fSymbolName,
1076 						sizeof(fSymbolName))) {
1077 					*_symbolName = fSymbolName;
1078 				} else {
1079 					// we can't get its name, so forget the symbol
1080 					deltaFound = INT_MAX;
1081 				}
1082 			}
1083 		}
1084 
1085 		if (_baseAddress) {
1086 			if (deltaFound < INT_MAX)
1087 				*_baseAddress = symbolFound.st_value + textRegion.delta;
1088 			else
1089 				*_baseAddress = textRegion.vmstart;
1090 		}
1091 
1092 		if (_exactMatch)
1093 			*_exactMatch = exactMatch;
1094 
1095 		return B_OK;
1096 	}
1097 
1098 	status_t _FindImageAtAddress(addr_t address, image_t& image)
1099 	{
1100 		image_queue_t imageQueue;
1101 		if (!_Read(fDebugArea.loaded_images, imageQueue))
1102 			return B_BAD_ADDRESS;
1103 
1104 		image_t* imageAddress = imageQueue.head;
1105 		while (imageAddress != NULL) {
1106 			if (!_Read(imageAddress, image))
1107 				return B_BAD_ADDRESS;
1108 
1109 			if (image.regions[0].vmstart <= address
1110 				&& address < image.regions[0].vmstart + image.regions[0].size) {
1111 				return B_OK;
1112 			}
1113 
1114 			imageAddress = image.next;
1115 		}
1116 
1117 		return B_ENTRY_NOT_FOUND;
1118 	}
1119 
1120 	bool _ReadString(const image_t& image, uint32 offset, char* buffer,
1121 		size_t bufferSize)
1122 	{
1123 		const char* address = image.strtab + offset;
1124 
1125 		if (!IS_USER_ADDRESS(address))
1126 			return false;
1127 
1128 		return user_strlcpy(buffer, address, bufferSize) >= 0;
1129 	}
1130 
1131 	template<typename T> bool _Read(const T* address, T& data);
1132 		// gcc 2.95.3 doesn't like it defined in-place
1133 
1134 private:
1135 	runtime_loader_debug_area	fDebugArea;
1136 	char						fImageName[B_OS_NAME_LENGTH];
1137 	char						fSymbolName[256];
1138 	static UserSymbolLookup		sLookup;
1139 };
1140 
1141 
1142 template<typename T>
1143 bool
1144 UserSymbolLookup::_Read(const T* address, T& data)
1145 {
1146 	if (!IS_USER_ADDRESS(address))
1147 		return false;
1148 
1149 	return user_memcpy(&data, address, sizeof(T)) == B_OK;
1150 }
1151 
1152 
1153 UserSymbolLookup UserSymbolLookup::sLookup;
1154 	// doesn't need construction, but has an Init() method
1155 
1156 
1157 //	#pragma mark - public kernel API
1158 
1159 
1160 status_t
1161 get_image_symbol(image_id id, const char *name, int32 symbolClass,
1162 	void **_symbol)
1163 {
1164 	struct elf_image_info *image;
1165 	struct Elf32_Sym *symbol;
1166 	status_t status = B_OK;
1167 
1168 	TRACE(("get_image_symbol(%s)\n", name));
1169 
1170 	mutex_lock(&sImageMutex);
1171 
1172 	image = find_image(id);
1173 	if (image == NULL) {
1174 		status = B_BAD_IMAGE_ID;
1175 		goto done;
1176 	}
1177 
1178 	symbol = elf_find_symbol(image, name);
1179 	if (symbol == NULL || symbol->st_shndx == SHN_UNDEF) {
1180 		status = B_ENTRY_NOT_FOUND;
1181 		goto done;
1182 	}
1183 
1184 	// TODO: support the "symbolClass" parameter!
1185 
1186 	TRACE(("found: %lx (%lx + %lx)\n",
1187 		symbol->st_value + image->text_region.delta,
1188 		symbol->st_value, image->text_region.delta));
1189 
1190 	*_symbol = (void *)(symbol->st_value + image->text_region.delta);
1191 
1192 done:
1193 	mutex_unlock(&sImageMutex);
1194 	return status;
1195 }
1196 
1197 
1198 //	#pragma mark - kernel private API
1199 
1200 
1201 /*!	Looks up a symbol by address in all images loaded in kernel space.
1202 	Note, if you need to call this function outside a debugger, make
1203 	sure you fix locking and the way it returns its information, first!
1204 */
1205 status_t
1206 elf_debug_lookup_symbol_address(addr_t address, addr_t *_baseAddress,
1207 	const char **_symbolName, const char **_imageName, bool *_exactMatch)
1208 {
1209 	struct elf_image_info *image;
1210 	struct Elf32_Sym *symbolFound = NULL;
1211 	const char *symbolName = NULL;
1212 	addr_t deltaFound = INT_MAX;
1213 	bool exactMatch = false;
1214 	status_t status;
1215 
1216 	TRACE(("looking up %p\n", (void *)address));
1217 
1218 	if (!sInitialized)
1219 		return B_ERROR;
1220 
1221 	//mutex_lock(&sImageMutex);
1222 
1223 	image = find_image_at_address(address);
1224 		// get image that may contain the address
1225 
1226 	if (image != NULL) {
1227 		addr_t symbolDelta;
1228 		uint32 i;
1229 		int32 j;
1230 
1231 		TRACE((" image %p, base = %p, size = %p\n", image,
1232 			(void *)image->text_region.start, (void *)image->text_region.size));
1233 
1234 		if (image->debug_symbols != NULL) {
1235 			// search extended debug symbol table (contains static symbols)
1236 
1237 			TRACE((" searching debug symbols...\n"));
1238 
1239 			for (i = 0; i < image->num_debug_symbols; i++) {
1240 				struct Elf32_Sym *symbol = &image->debug_symbols[i];
1241 
1242 				if (symbol->st_value == 0 || symbol->st_size
1243 						>= image->text_region.size + image->data_region.size)
1244 					continue;
1245 
1246 				symbolDelta
1247 					= address - (symbol->st_value + image->text_region.delta);
1248 				if (symbolDelta >= 0 && symbolDelta < symbol->st_size)
1249 					exactMatch = true;
1250 
1251 				if (exactMatch || symbolDelta < deltaFound) {
1252 					deltaFound = symbolDelta;
1253 					symbolFound = symbol;
1254 					symbolName = image->debug_string_table + symbol->st_name;
1255 
1256 					if (exactMatch)
1257 						break;
1258 				}
1259 			}
1260 		} else {
1261 			// search standard symbol lookup table
1262 
1263 			TRACE((" searching standard symbols...\n"));
1264 
1265 			for (i = 0; i < HASHTABSIZE(image); i++) {
1266 				for (j = HASHBUCKETS(image)[i]; j != STN_UNDEF;
1267 						j = HASHCHAINS(image)[j]) {
1268 					struct Elf32_Sym *symbol = &image->syms[j];
1269 
1270 					if (symbol->st_value == 0
1271 						|| symbol->st_size >= image->text_region.size
1272 							+ image->data_region.size)
1273 						continue;
1274 
1275 					symbolDelta = address - (long)(symbol->st_value
1276 						+ image->text_region.delta);
1277 					if (symbolDelta >= 0 && symbolDelta < symbol->st_size)
1278 						exactMatch = true;
1279 
1280 					if (exactMatch || symbolDelta < deltaFound) {
1281 						deltaFound = symbolDelta;
1282 						symbolFound = symbol;
1283 						symbolName = SYMNAME(image, symbol);
1284 
1285 						if (exactMatch)
1286 							goto symbol_found;
1287 					}
1288 				}
1289 			}
1290 		}
1291 	}
1292 symbol_found:
1293 
1294 	if (symbolFound != NULL) {
1295 		if (_symbolName)
1296 			*_symbolName = symbolName;
1297 		if (_imageName)
1298 			*_imageName = image->name;
1299 		if (_baseAddress)
1300 			*_baseAddress = symbolFound->st_value + image->text_region.delta;
1301 		if (_exactMatch)
1302 			*_exactMatch = exactMatch;
1303 
1304 		status = B_OK;
1305 	} else if (image != NULL) {
1306 		TRACE(("symbol not found!\n"));
1307 
1308 		if (_symbolName)
1309 			*_symbolName = NULL;
1310 		if (_imageName)
1311 			*_imageName = image->name;
1312 		if (_baseAddress)
1313 			*_baseAddress = image->text_region.start;
1314 		if (_exactMatch)
1315 			*_exactMatch = false;
1316 
1317 		status = B_OK;
1318 	} else {
1319 		TRACE(("image not found!\n"));
1320 		status = B_ENTRY_NOT_FOUND;
1321 	}
1322 
1323 	// Note, theoretically, all information we return back to our caller
1324 	// would have to be locked - but since this function is only called
1325 	// from the debugger, it's safe to do it this way
1326 
1327 	//mutex_unlock(&sImageMutex);
1328 
1329 	return status;
1330 }
1331 
1332 
1333 /*!	Tries to find a matching user symbol for the given address.
1334 	Note that the given team's address space must already be in effect.
1335 */
1336 status_t
1337 elf_debug_lookup_user_symbol_address(struct team* team, addr_t address,
1338 	addr_t *_baseAddress, const char **_symbolName, const char **_imageName,
1339 	bool *_exactMatch)
1340 {
1341 	if (team == NULL || team == team_get_kernel_team())
1342 		return B_BAD_VALUE;
1343 
1344 	UserSymbolLookup& lookup = UserSymbolLookup::Default();
1345 	status_t error = lookup.Init(team);
1346 	if (error != B_OK)
1347 		return error;
1348 
1349 	return lookup.LookupSymbolAddress(address, _baseAddress, _symbolName,
1350 		_imageName, _exactMatch);
1351 }
1352 
1353 
1354 status_t
1355 elf_load_user_image(const char *path, struct team *team, int flags,
1356 	addr_t *entry)
1357 {
1358 	struct Elf32_Ehdr elfHeader;
1359 	struct Elf32_Phdr *programHeaders = NULL;
1360 	char baseName[B_OS_NAME_LENGTH];
1361 	status_t status;
1362 	ssize_t length;
1363 	int fd;
1364 	int i;
1365 
1366 	TRACE(("elf_load: entry path '%s', team %p\n", path, team));
1367 
1368 	fd = _kern_open(-1, path, O_RDONLY, 0);
1369 	if (fd < 0)
1370 		return fd;
1371 
1372 	struct stat st;
1373 	status = _kern_read_stat(fd, NULL, false, &st, sizeof(st));
1374 	if (status != B_OK)
1375 		return status;
1376 
1377 	// read and verify the ELF header
1378 
1379 	length = _kern_read(fd, 0, &elfHeader, sizeof(elfHeader));
1380 	if (length < B_OK) {
1381 		status = length;
1382 		goto error;
1383 	}
1384 
1385 	if (length != sizeof(elfHeader)) {
1386 		// short read
1387 		status = B_NOT_AN_EXECUTABLE;
1388 		goto error;
1389 	}
1390 	status = verify_eheader(&elfHeader);
1391 	if (status < B_OK)
1392 		goto error;
1393 
1394 	// read program header
1395 
1396 	programHeaders = (struct Elf32_Phdr *)malloc(
1397 		elfHeader.e_phnum * elfHeader.e_phentsize);
1398 	if (programHeaders == NULL) {
1399 		dprintf("error allocating space for program headers\n");
1400 		status = B_NO_MEMORY;
1401 		goto error;
1402 	}
1403 
1404 	TRACE(("reading in program headers at 0x%lx, length 0x%x\n",
1405 		elfHeader.e_phoff, elfHeader.e_phnum * elfHeader.e_phentsize));
1406 	length = _kern_read(fd, elfHeader.e_phoff, programHeaders,
1407 		elfHeader.e_phnum * elfHeader.e_phentsize);
1408 	if (length < B_OK) {
1409 		status = length;
1410 		dprintf("error reading in program headers\n");
1411 		goto error;
1412 	}
1413 	if (length != elfHeader.e_phnum * elfHeader.e_phentsize) {
1414 		dprintf("short read while reading in program headers\n");
1415 		status = -1;
1416 		goto error;
1417 	}
1418 
1419 	// construct a nice name for the region we have to create below
1420 	{
1421 		int32 length;
1422 
1423 		const char *leaf = strrchr(path, '/');
1424 		if (leaf == NULL)
1425 			leaf = path;
1426 		else
1427 			leaf++;
1428 
1429 		length = strlen(leaf);
1430 		if (length > B_OS_NAME_LENGTH - 8)
1431 			sprintf(baseName, "...%s", leaf + length + 8 - B_OS_NAME_LENGTH);
1432 		else
1433 			strcpy(baseName, leaf);
1434 	}
1435 
1436 	// map the program's segments into memory
1437 
1438 	image_info imageInfo;
1439 	memset(&imageInfo, 0, sizeof(image_info));
1440 
1441 	for (i = 0; i < elfHeader.e_phnum; i++) {
1442 		char regionName[B_OS_NAME_LENGTH];
1443 		char *regionAddress;
1444 		area_id id;
1445 
1446 		if (programHeaders[i].p_type != PT_LOAD)
1447 			continue;
1448 
1449 		regionAddress = (char *)ROUNDOWN(programHeaders[i].p_vaddr,
1450 			B_PAGE_SIZE);
1451 		if (programHeaders[i].p_flags & PF_WRITE) {
1452 			// rw/data segment
1453 			uint32 memUpperBound = (programHeaders[i].p_vaddr % B_PAGE_SIZE)
1454 				+ programHeaders[i].p_memsz;
1455 			uint32 fileUpperBound = (programHeaders[i].p_vaddr % B_PAGE_SIZE)
1456 				+ programHeaders[i].p_filesz;
1457 
1458 			memUpperBound = ROUNDUP(memUpperBound, B_PAGE_SIZE);
1459 			fileUpperBound = ROUNDUP(fileUpperBound, B_PAGE_SIZE);
1460 
1461 			sprintf(regionName, "%s_seg%drw", baseName, i);
1462 
1463 			id = vm_map_file(team->id, regionName, (void **)&regionAddress,
1464 				B_EXACT_ADDRESS, fileUpperBound,
1465 				B_READ_AREA | B_WRITE_AREA, REGION_PRIVATE_MAP,
1466 				fd, ROUNDOWN(programHeaders[i].p_offset, B_PAGE_SIZE));
1467 			if (id < B_OK) {
1468 				dprintf("error mapping file data: %s!\n", strerror(id));
1469 				status = B_NOT_AN_EXECUTABLE;
1470 				goto error;
1471 			}
1472 
1473 			imageInfo.data = regionAddress;
1474 			imageInfo.data_size = memUpperBound;
1475 
1476 			// clean garbage brought by mmap (the region behind the file,
1477 			// at least parts of it are the bss and have to be zeroed)
1478 			uint32 start = (uint32)regionAddress
1479 				+ (programHeaders[i].p_vaddr % B_PAGE_SIZE)
1480 				+ programHeaders[i].p_filesz;
1481 			uint32 amount = fileUpperBound
1482 				- (programHeaders[i].p_vaddr % B_PAGE_SIZE)
1483 				- (programHeaders[i].p_filesz);
1484 			memset((void *)start, 0, amount);
1485 
1486 			// Check if we need extra storage for the bss - we have to do this if
1487 			// the above region doesn't already comprise the memory size, too.
1488 
1489 			if (memUpperBound != fileUpperBound) {
1490 				size_t bssSize = memUpperBound - fileUpperBound;
1491 
1492 				snprintf(regionName, B_OS_NAME_LENGTH, "%s_bss%d", baseName, i);
1493 
1494 				regionAddress += fileUpperBound;
1495 				id = create_area_etc(team->id, regionName,
1496 					(void **)&regionAddress, B_EXACT_ADDRESS, bssSize,
1497 					B_NO_LOCK, B_READ_AREA | B_WRITE_AREA, 0);
1498 				if (id < B_OK) {
1499 					dprintf("error allocating bss area: %s!\n", strerror(id));
1500 					status = B_NOT_AN_EXECUTABLE;
1501 					goto error;
1502 				}
1503 			}
1504 		} else {
1505 			// assume ro/text segment
1506 			snprintf(regionName, B_OS_NAME_LENGTH, "%s_seg%dro", baseName, i);
1507 
1508 			size_t segmentSize = ROUNDUP(programHeaders[i].p_memsz
1509 				+ (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE);
1510 
1511 			id = vm_map_file(team->id, regionName, (void **)&regionAddress,
1512 				B_EXACT_ADDRESS, segmentSize,
1513 				B_READ_AREA | B_EXECUTE_AREA, REGION_PRIVATE_MAP,
1514 				fd, ROUNDOWN(programHeaders[i].p_offset, B_PAGE_SIZE));
1515 			if (id < B_OK) {
1516 				dprintf("error mapping file text: %s!\n", strerror(id));
1517 				status = B_NOT_AN_EXECUTABLE;
1518 				goto error;
1519 			}
1520 
1521 			imageInfo.text = regionAddress;
1522 			imageInfo.text_size = segmentSize;
1523 		}
1524 	}
1525 
1526 	// register the loaded image
1527 	imageInfo.type = B_LIBRARY_IMAGE;
1528     imageInfo.device = st.st_dev;
1529     imageInfo.node = st.st_ino;
1530 	strlcpy(imageInfo.name, path, sizeof(imageInfo.name));
1531 
1532 	imageInfo.id = register_image(team, &imageInfo, sizeof(image_info));
1533 	if (imageInfo.id >= 0 && team_get_current_team_id() == team->id)
1534 		user_debug_image_created(&imageInfo);
1535 		// Don't care, if registering fails. It's not crucial.
1536 
1537 	TRACE(("elf_load: done!\n"));
1538 
1539 	*entry = elfHeader.e_entry;
1540 	status = B_OK;
1541 
1542 error:
1543 	if (programHeaders)
1544 		free(programHeaders);
1545 	_kern_close(fd);
1546 
1547 	return status;
1548 }
1549 
1550 
1551 image_id
1552 load_kernel_add_on(const char *path)
1553 {
1554 	struct Elf32_Phdr *programHeaders;
1555 	struct Elf32_Ehdr *elfHeader;
1556 	struct elf_image_info *image;
1557 	const char *fileName;
1558 	void *reservedAddress;
1559 	addr_t start;
1560 	size_t reservedSize;
1561 	status_t status;
1562 	ssize_t length;
1563 
1564 	TRACE(("elf_load_kspace: entry path '%s'\n", path));
1565 
1566 	int fd = _kern_open(-1, path, O_RDONLY, 0);
1567 	if (fd < 0)
1568 		return fd;
1569 
1570 	struct vnode *vnode;
1571 	status = vfs_get_vnode_from_fd(fd, true, &vnode);
1572 	if (status < B_OK)
1573 		goto error0;
1574 
1575 	// get the file name
1576 	fileName = strrchr(path, '/');
1577 	if (fileName == NULL)
1578 		fileName = path;
1579 	else
1580 		fileName++;
1581 
1582 	// Prevent someone else from trying to load this image
1583 	mutex_lock(&sImageLoadMutex);
1584 
1585 	// make sure it's not loaded already. Search by vnode
1586 	image = find_image_by_vnode(vnode);
1587 	if (image) {
1588 		atomic_add(&image->ref_count, 1);
1589 		goto done;
1590 	}
1591 
1592 	elfHeader = (struct Elf32_Ehdr *)malloc(sizeof(*elfHeader));
1593 	if (!elfHeader) {
1594 		status = B_NO_MEMORY;
1595 		goto error;
1596 	}
1597 
1598 	length = _kern_read(fd, 0, elfHeader, sizeof(*elfHeader));
1599 	if (length < B_OK) {
1600 		status = length;
1601 		goto error1;
1602 	}
1603 	if (length != sizeof(*elfHeader)) {
1604 		// short read
1605 		status = B_NOT_AN_EXECUTABLE;
1606 		goto error1;
1607 	}
1608 	status = verify_eheader(elfHeader);
1609 	if (status < B_OK)
1610 		goto error1;
1611 
1612 	image = create_image_struct();
1613 	if (!image) {
1614 		status = B_NO_MEMORY;
1615 		goto error1;
1616 	}
1617 	image->vnode = vnode;
1618 	image->elf_header = elfHeader;
1619 	image->name = strdup(path);
1620 
1621 	programHeaders = (struct Elf32_Phdr *)malloc(elfHeader->e_phnum
1622 		* elfHeader->e_phentsize);
1623 	if (programHeaders == NULL) {
1624 		dprintf("%s: error allocating space for program headers\n", fileName);
1625 		status = B_NO_MEMORY;
1626 		goto error2;
1627 	}
1628 
1629 	TRACE(("reading in program headers at 0x%lx, length 0x%x\n",
1630 		elfHeader->e_phoff, elfHeader->e_phnum * elfHeader->e_phentsize));
1631 
1632 	length = _kern_read(fd, elfHeader->e_phoff, programHeaders,
1633 		elfHeader->e_phnum * elfHeader->e_phentsize);
1634 	if (length < B_OK) {
1635 		status = length;
1636 		TRACE(("%s: error reading in program headers\n", fileName));
1637 		goto error3;
1638 	}
1639 	if (length != elfHeader->e_phnum * elfHeader->e_phentsize) {
1640 		TRACE(("%s: short read while reading in program headers\n", fileName));
1641 		status = B_ERROR;
1642 		goto error3;
1643 	}
1644 
1645 	// determine how much space we need for all loaded segments
1646 
1647 	reservedSize = 0;
1648 	length = 0;
1649 
1650 	for (int32 i = 0; i < elfHeader->e_phnum; i++) {
1651 		size_t end;
1652 
1653 		if (programHeaders[i].p_type != PT_LOAD)
1654 			continue;
1655 
1656 		length += ROUNDUP(programHeaders[i].p_memsz
1657 			+ (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE);
1658 
1659 		end = ROUNDUP(programHeaders[i].p_memsz + programHeaders[i].p_vaddr,
1660 			B_PAGE_SIZE);
1661 		if (end > reservedSize)
1662 			reservedSize = end;
1663 	}
1664 
1665 	// Check whether the segments have an unreasonable amount of unused space
1666 	// inbetween.
1667 	if ((ssize_t)reservedSize > length + 8 * 1024) {
1668 		status = B_BAD_DATA;
1669 		goto error1;
1670 	}
1671 
1672 	// reserve that space and allocate the areas from that one
1673 	if (vm_reserve_address_range(vm_kernel_address_space_id(), &reservedAddress,
1674 			B_ANY_KERNEL_ADDRESS, reservedSize, 0) < B_OK) {
1675 		status = B_NO_MEMORY;
1676 		goto error3;
1677 	}
1678 
1679 	start = (addr_t)reservedAddress;
1680 	image->data_region.size = 0;
1681 	image->text_region.size = 0;
1682 
1683 	for (int32 i = 0; i < elfHeader->e_phnum; i++) {
1684 		char regionName[B_OS_NAME_LENGTH];
1685 		elf_region *region;
1686 
1687 		TRACE(("looking at program header %ld\n", i));
1688 
1689 		switch (programHeaders[i].p_type) {
1690 			case PT_LOAD:
1691 				break;
1692 			case PT_DYNAMIC:
1693 				image->dynamic_section = programHeaders[i].p_vaddr;
1694 				continue;
1695 			default:
1696 				dprintf("%s: unhandled pheader type 0x%lx\n", fileName,
1697 					programHeaders[i].p_type);
1698 				continue;
1699 		}
1700 
1701 		// we're here, so it must be a PT_LOAD segment
1702 		if (programHeaders[i].IsReadWrite()) {
1703 			// this is the writable segment
1704 			if (image->data_region.size != 0) {
1705 				// we've already created this segment
1706 				continue;
1707 			}
1708 			region = &image->data_region;
1709 
1710 			snprintf(regionName, B_OS_NAME_LENGTH, "%s_data", fileName);
1711 		} else if (programHeaders[i].IsExecutable()) {
1712 			// this is the non-writable segment
1713 			if (image->text_region.size != 0) {
1714 				// we've already created this segment
1715 				continue;
1716 			}
1717 			region = &image->text_region;
1718 
1719 			snprintf(regionName, B_OS_NAME_LENGTH, "%s_text", fileName);
1720 		} else {
1721 			dprintf("%s: weird program header flags 0x%lx\n", fileName,
1722 				programHeaders[i].p_flags);
1723 			continue;
1724 		}
1725 
1726 		region->start = (addr_t)reservedAddress + ROUNDOWN(
1727 			programHeaders[i].p_vaddr, B_PAGE_SIZE);
1728 		region->size = ROUNDUP(programHeaders[i].p_memsz
1729 			+ (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE);
1730 		region->id = create_area(regionName, (void **)&region->start,
1731 			B_EXACT_ADDRESS, region->size, B_FULL_LOCK,
1732 			B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
1733 		if (region->id < B_OK) {
1734 			dprintf("%s: error allocating area: %s\n", fileName,
1735 				strerror(region->id));
1736 			status = B_NOT_AN_EXECUTABLE;
1737 			goto error4;
1738 		}
1739 		region->delta = -ROUNDOWN(programHeaders[i].p_vaddr, B_PAGE_SIZE);
1740 
1741 		TRACE(("elf_load_kspace: created area \"%s\" at %p\n",
1742 			regionName, (void *)region->start));
1743 
1744 		length = _kern_read(fd, programHeaders[i].p_offset,
1745 			(void *)(region->start + (programHeaders[i].p_vaddr % B_PAGE_SIZE)),
1746 			programHeaders[i].p_filesz);
1747 		if (length < B_OK) {
1748 			status = length;
1749 			dprintf("%s: error reading in segment %ld\n", fileName, i);
1750 			goto error5;
1751 		}
1752 	}
1753 
1754 	// get the segment order
1755 	elf_region *firstRegion;
1756 	elf_region *secondRegion;
1757 	if (image->text_region.start < image->data_region.start) {
1758 		firstRegion = &image->text_region;
1759 		secondRegion = &image->data_region;
1760 	} else {
1761 		firstRegion = &image->data_region;
1762 		secondRegion = &image->text_region;
1763 	}
1764 
1765 	image->data_region.delta += image->data_region.start;
1766 	image->text_region.delta += image->text_region.start;
1767 
1768 	// modify the dynamic ptr by the delta of the regions
1769 	image->dynamic_section += image->text_region.delta;
1770 
1771 	status = elf_parse_dynamic_section(image);
1772 	if (status < B_OK)
1773 		goto error5;
1774 
1775 	status = elf_relocate(image, NULL);
1776 	if (status < B_OK)
1777 		goto error5;
1778 
1779 	// We needed to read in the contents of the "text" area, but
1780 	// now we can protect it read-only/execute
1781 	set_area_protection(image->text_region.id,
1782 		B_KERNEL_READ_AREA | B_KERNEL_EXECUTE_AREA);
1783 
1784 	// There might be a hole between the two segments, and we don't need to
1785 	// reserve this any longer
1786 	vm_unreserve_address_range(vm_kernel_address_space_id(), reservedAddress,
1787 		reservedSize);
1788 
1789 	// ToDo: this should be enabled by kernel settings!
1790 	if (1)
1791 		load_elf_symbol_table(fd, image);
1792 
1793 	free(programHeaders);
1794 	mutex_lock(&sImageMutex);
1795 	register_elf_image(image);
1796 	mutex_unlock(&sImageMutex);
1797 
1798 done:
1799 	_kern_close(fd);
1800 	mutex_unlock(&sImageLoadMutex);
1801 
1802 	return image->id;
1803 
1804 error5:
1805 	delete_area(image->data_region.id);
1806 	delete_area(image->text_region.id);
1807 error4:
1808 	vm_unreserve_address_range(vm_kernel_address_space_id(), reservedAddress,
1809 		reservedSize);
1810 error3:
1811 	free(programHeaders);
1812 error2:
1813 	free(image);
1814 error1:
1815 	free(elfHeader);
1816 error:
1817 	mutex_unlock(&sImageLoadMutex);
1818 error0:
1819 	dprintf("Could not load kernel add-on \"%s\": %s\n", path,
1820 		strerror(status));
1821 
1822 	if (vnode)
1823 		vfs_put_vnode(vnode);
1824 	_kern_close(fd);
1825 
1826 	return status;
1827 }
1828 
1829 
1830 status_t
1831 unload_kernel_add_on(image_id id)
1832 {
1833 	struct elf_image_info *image;
1834 	status_t status;
1835 
1836 	mutex_lock(&sImageLoadMutex);
1837 	mutex_lock(&sImageMutex);
1838 
1839 	image = find_image(id);
1840 	if (image != NULL)
1841 		status = unload_elf_image(image);
1842 	else
1843 		status = B_BAD_IMAGE_ID;
1844 
1845 	mutex_unlock(&sImageMutex);
1846 	mutex_unlock(&sImageLoadMutex);
1847 
1848 	return status;
1849 }
1850 
1851 
1852 status_t
1853 elf_get_image_info_for_address(addr_t address, image_info* info)
1854 {
1855 	MutexLocker _(sImageMutex);
1856 	struct elf_image_info* elfInfo = find_image_at_address(address);
1857 	if (elfInfo == NULL)
1858 		return B_ENTRY_NOT_FOUND;
1859 
1860 	info->id = elfInfo->id;
1861     info->type = B_SYSTEM_IMAGE;
1862     info->sequence = 0;
1863     info->init_order = 0;
1864     info->init_routine = NULL;
1865     info->term_routine = NULL;
1866     info->device = -1;
1867     info->node = -1;
1868 		// TODO: We could actually fill device/node in.
1869 	strlcpy(info->name, elfInfo->name, sizeof(info->name));
1870     info->text = (void*)elfInfo->text_region.start;
1871     info->data = (void*)elfInfo->data_region.start;
1872     info->text_size = elfInfo->text_region.size;
1873     info->data_size = elfInfo->data_region.size;
1874 
1875 	return B_OK;
1876 }
1877 
1878 
1879 image_id
1880 elf_create_memory_image(const char* imageName, addr_t text, size_t textSize,
1881 	addr_t data, size_t dataSize)
1882 {
1883 	// allocate the image
1884 	elf_image_info* image = create_image_struct();
1885 	if (image == NULL)
1886 		return B_NO_MEMORY;
1887 	MemoryDeleter imageDeleter(image);
1888 
1889 	// allocate symbol and string tables -- we allocate an empty symbol table,
1890 	// so that elf_debug_lookup_symbol_address() won't try the dynamic symbol
1891 	// table, which we don't have.
1892 	Elf32_Sym* symbolTable = (Elf32_Sym*)malloc(0);
1893 	char* stringTable = (char*)malloc(1);
1894 	MemoryDeleter symbolTableDeleter(symbolTable);
1895 	MemoryDeleter stringTableDeleter(stringTable);
1896 	if (symbolTable == NULL || stringTable == NULL)
1897 		return B_NO_MEMORY;
1898 
1899 	// the string table always contains the empty string
1900 	stringTable[0] = '\0';
1901 
1902 	image->debug_symbols = symbolTable;
1903 	image->num_debug_symbols = 0;
1904 	image->debug_string_table = stringTable;
1905 
1906 	// dup image name
1907 	image->name = strdup(imageName);
1908 	if (image->name == NULL)
1909 		return B_NO_MEMORY;
1910 
1911 	// data and text region
1912 	image->text_region.id = -1;
1913 	image->text_region.start = text;
1914 	image->text_region.size = textSize;
1915 	image->text_region.delta = 0;
1916 
1917 	image->data_region.id = -1;
1918 	image->data_region.start = data;
1919 	image->data_region.size = dataSize;
1920 	image->data_region.delta = 0;
1921 
1922 	mutex_lock(&sImageMutex);
1923 	register_elf_image(image);
1924 	image_id imageID = image->id;
1925 	mutex_unlock(&sImageMutex);
1926 
1927 	// keep the allocated memory
1928 	imageDeleter.Detach();
1929 	symbolTableDeleter.Detach();
1930 	stringTableDeleter.Detach();
1931 
1932 	return imageID;
1933 }
1934 
1935 
1936 status_t
1937 elf_add_memory_image_symbol(image_id id, const char* name, addr_t address,
1938 	size_t size, int32 type)
1939 {
1940 	MutexLocker _(sImageMutex);
1941 
1942 	// get the image
1943 	struct elf_image_info* image = find_image(id);
1944 	if (image == NULL)
1945 		return B_ENTRY_NOT_FOUND;
1946 
1947 	// get the current string table size
1948 	size_t stringTableSize = 1;
1949 	if (image->num_debug_symbols > 0) {
1950 		for (uint32 i = image->num_debug_symbols - 1; i >= 0; i--) {
1951 			int32 nameIndex = image->debug_symbols[i].st_name;
1952 			if (nameIndex != 0) {
1953 				stringTableSize = nameIndex
1954 					+ strlen(image->debug_string_table + nameIndex) + 1;
1955 				break;
1956 			}
1957 		}
1958 	}
1959 
1960 	// enter the name in the string table
1961 	char* stringTable = (char*)image->debug_string_table;
1962 	size_t stringIndex = 0;
1963 	if (name != NULL) {
1964 		size_t nameSize = strlen(name) + 1;
1965 		stringIndex = stringTableSize;
1966 		stringTableSize += nameSize;
1967 		stringTable = (char*)realloc((char*)image->debug_string_table,
1968 			stringTableSize);
1969 		if (stringTable == NULL)
1970 			return B_NO_MEMORY;
1971 		image->debug_string_table = stringTable;
1972 		memcpy(stringTable + stringIndex, name, nameSize);
1973 	}
1974 
1975 	// resize the symbol table
1976 	int32 symbolCount = image->num_debug_symbols + 1;
1977 	Elf32_Sym* symbolTable = (Elf32_Sym*)realloc(
1978 		(Elf32_Sym*)image->debug_symbols, sizeof(Elf32_Sym) * symbolCount);
1979 	if (symbolTable == NULL)
1980 		return B_NO_MEMORY;
1981 	image->debug_symbols = symbolTable;
1982 
1983 	// enter the symbol
1984 	Elf32_Sym& symbol = symbolTable[symbolCount - 1];
1985 	uint32 symbolType = type == B_SYMBOL_TYPE_DATA ? STT_OBJECT : STT_FUNC;
1986 	symbol.st_name = stringIndex;
1987 	symbol.st_value = address;
1988 	symbol.st_size = size;
1989 	symbol.st_info = ELF32_ST_INFO(STB_GLOBAL, symbolType);
1990 	symbol.st_other = 0;
1991 	symbol.st_shndx = 0;
1992 	image->num_debug_symbols++;
1993 
1994 	return B_OK;
1995 }
1996 
1997 
1998 status_t
1999 elf_init(kernel_args *args)
2000 {
2001 	struct preloaded_image *image;
2002 
2003 	image_init();
2004 
2005 	sImagesHash = hash_init(IMAGE_HASH_SIZE, 0, image_compare, image_hash);
2006 	if (sImagesHash == NULL)
2007 		return B_NO_MEMORY;
2008 
2009 	// Build a image structure for the kernel, which has already been loaded.
2010 	// The preloaded_images were already prepared by the VM.
2011 	if (insert_preloaded_image(&args->kernel_image, true) < B_OK)
2012 		panic("could not create kernel image.\n");
2013 
2014 	// Build image structures for all preloaded images.
2015 	for (image = args->preloaded_images; image != NULL; image = image->next) {
2016 		insert_preloaded_image(image, false);
2017 	}
2018 
2019 	add_debugger_command("ls", &dump_address_info,
2020 		"lookup symbol for a particular address");
2021 	add_debugger_command("symbols", &dump_symbols, "dump symbols for image");
2022 	add_debugger_command("symbol", &dump_symbol, "search symbol in images");
2023 	add_debugger_command_etc("image", &dump_image, "dump image info",
2024 		"Prints info about the specified image.\n"
2025 		"  <image>  - pointer to the semaphore structure, or ID\n"
2026 		"           of the image to print info for.\n", 0);
2027 
2028 	sInitialized = true;
2029 	return B_OK;
2030 }
2031 
2032 
2033 // #pragma mark -
2034 
2035 
2036 /*!	Reads the symbol and string table for the kernel image with the given ID.
2037 	\a _symbolCount and \a _stringTableSize are both in- and output parameters.
2038 	When called they call the size of the buffers given by \a symbolTable and
2039 	\a stringTable respectively. When the function returns successfully, they
2040 	will contain the actual sizes (which can be greater than the original ones).
2041 	The function will copy as much as possible into the buffers. For only
2042 	getting the required buffer sizes, it can be invoked with \c NULL buffers.
2043 	On success \a _imageDelta will contain the offset to be added to the symbol
2044 	values in the table to get the actual symbol addresses.
2045 */
2046 status_t
2047 _user_read_kernel_image_symbols(image_id id, struct Elf32_Sym* symbolTable,
2048 	int32* _symbolCount, char* stringTable, size_t* _stringTableSize,
2049 	addr_t* _imageDelta)
2050 {
2051 	// check params
2052 	if (_symbolCount == NULL || _stringTableSize == NULL)
2053 		return B_BAD_VALUE;
2054 	if (!IS_USER_ADDRESS(_symbolCount) || !IS_USER_ADDRESS(_stringTableSize)
2055 		|| (_imageDelta != NULL && !IS_USER_ADDRESS(_imageDelta))
2056 		|| (symbolTable != NULL && !IS_USER_ADDRESS(symbolTable))
2057 		|| (stringTable != NULL && !IS_USER_ADDRESS(stringTable))) {
2058 		return B_BAD_ADDRESS;
2059 	}
2060 
2061 	// get buffer sizes
2062 	int32 maxSymbolCount;
2063 	size_t maxStringTableSize;
2064 	if (user_memcpy(&maxSymbolCount, _symbolCount, sizeof(maxSymbolCount))
2065 			!= B_OK
2066 		|| user_memcpy(&maxStringTableSize, _stringTableSize,
2067 			sizeof(maxStringTableSize)) != B_OK) {
2068 		return B_BAD_ADDRESS;
2069 	}
2070 
2071 	// find the image
2072 	MutexLocker _(sImageMutex);
2073 	struct elf_image_info* image = find_image(id);
2074 	if (image == NULL)
2075 		return B_ENTRY_NOT_FOUND;
2076 
2077 	// get the tables and infos
2078 	addr_t imageDelta = image->text_region.delta;
2079 	const Elf32_Sym* symbols;
2080 	int32 symbolCount;
2081 	const char* strings;
2082 
2083 	if (image->debug_symbols != NULL) {
2084 		symbols = image->debug_symbols;
2085 		symbolCount = image->num_debug_symbols;
2086 		strings = image->debug_string_table;
2087 	} else {
2088 		symbols = image->syms;
2089 		symbolCount = image->symhash[1];
2090 		strings = image->strtab;
2091 	}
2092 
2093 	// The string table size isn't stored in the elf_image_info structure. Find
2094 	// out by iterating through all symbols.
2095 	size_t stringTableSize = 0;
2096 	for (int32 i = 0; i < symbolCount; i++) {
2097 		size_t index = symbols[i].st_name;
2098 		if (index > stringTableSize)
2099 			stringTableSize = index;
2100 	}
2101 	stringTableSize += strlen(strings + stringTableSize) + 1;
2102 		// add size of the last string
2103 
2104 	// copy symbol table
2105 	int32 symbolsToCopy = min_c(symbolCount, maxSymbolCount);
2106 	if (symbolTable != NULL && symbolsToCopy > 0) {
2107 		if (user_memcpy(symbolTable, symbols, sizeof(Elf32_Sym) * symbolsToCopy)
2108 				!= B_OK) {
2109 			return B_BAD_ADDRESS;
2110 		}
2111 	}
2112 
2113 	// copy string table
2114 	size_t stringsToCopy = min_c(stringTableSize, maxStringTableSize);
2115 	if (stringTable != NULL && stringsToCopy > 0) {
2116 		if (user_memcpy(stringTable, strings, stringsToCopy)
2117 				!= B_OK) {
2118 			return B_BAD_ADDRESS;
2119 		}
2120 	}
2121 
2122 	// copy sizes
2123 	if (user_memcpy(_symbolCount, &symbolCount, sizeof(symbolCount)) != B_OK
2124 		|| user_memcpy(_stringTableSize, &stringTableSize,
2125 				sizeof(stringTableSize)) != B_OK
2126 		|| (_imageDelta != NULL && user_memcpy(_imageDelta, &imageDelta,
2127 				sizeof(imageDelta)) != B_OK)) {
2128 		return B_BAD_ADDRESS;
2129 	}
2130 
2131 	return B_OK;
2132 }
2133