xref: /haiku/src/system/kernel/elf.cpp (revision 2600324b57fa31cdea1627d584d314f2a579c4a8)
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 	uint32 hash;
527 	uint32 i;
528 
529 	if (!image->dynamic_section)
530 		return NULL;
531 
532 	hash = elf_hash(name) % HASHTABSIZE(image);
533 	for (i = HASHBUCKETS(image)[hash]; i != STN_UNDEF;
534 			i = HASHCHAINS(image)[i]) {
535 		if (!strcmp(SYMNAME(image, &image->syms[i]), name))
536 			return &image->syms[i];
537 	}
538 
539 	return NULL;
540 }
541 
542 
543 static status_t
544 elf_parse_dynamic_section(struct elf_image_info *image)
545 {
546 	struct Elf32_Dyn *d;
547 	int32 neededOffset = -1;
548 
549 	TRACE(("top of elf_parse_dynamic_section\n"));
550 
551 	image->symhash = 0;
552 	image->syms = 0;
553 	image->strtab = 0;
554 
555 	d = (struct Elf32_Dyn *)image->dynamic_section;
556 	if (!d)
557 		return B_ERROR;
558 
559 	for (int32 i = 0; d[i].d_tag != DT_NULL; i++) {
560 		switch (d[i].d_tag) {
561 			case DT_NEEDED:
562 				neededOffset = d[i].d_un.d_ptr + image->text_region.delta;
563 				break;
564 			case DT_HASH:
565 				image->symhash = (uint32 *)(d[i].d_un.d_ptr
566 					+ image->text_region.delta);
567 				break;
568 			case DT_STRTAB:
569 				image->strtab = (char *)(d[i].d_un.d_ptr
570 					+ image->text_region.delta);
571 				break;
572 			case DT_SYMTAB:
573 				image->syms = (struct Elf32_Sym *)(d[i].d_un.d_ptr
574 					+ image->text_region.delta);
575 				break;
576 			case DT_REL:
577 				image->rel = (struct Elf32_Rel *)(d[i].d_un.d_ptr
578 					+ image->text_region.delta);
579 				break;
580 			case DT_RELSZ:
581 				image->rel_len = d[i].d_un.d_val;
582 				break;
583 			case DT_RELA:
584 				image->rela = (struct Elf32_Rela *)(d[i].d_un.d_ptr
585 					+ image->text_region.delta);
586 				break;
587 			case DT_RELASZ:
588 				image->rela_len = d[i].d_un.d_val;
589 				break;
590 			case DT_JMPREL:
591 				image->pltrel = (struct Elf32_Rel *)(d[i].d_un.d_ptr
592 					+ image->text_region.delta);
593 				break;
594 			case DT_PLTRELSZ:
595 				image->pltrel_len = d[i].d_un.d_val;
596 				break;
597 			case DT_PLTREL:
598 				image->pltrel_type = d[i].d_un.d_val;
599 				break;
600 
601 			default:
602 				continue;
603 		}
604 	}
605 
606 	// lets make sure we found all the required sections
607 	if (!image->symhash || !image->syms || !image->strtab)
608 		return B_ERROR;
609 
610 	TRACE(("needed_offset = %ld\n", neededOffset));
611 
612 	if (neededOffset >= 0)
613 		image->needed = STRING(image, neededOffset);
614 
615 	return B_OK;
616 }
617 
618 
619 /*!	Resolves the \a symbol by linking against \a sharedImage if necessary.
620 	Returns the resolved symbol's address in \a _symbolAddress.
621 	TODO: eventually get rid of "symbolPrepend"
622 */
623 status_t
624 elf_resolve_symbol(struct elf_image_info *image, struct Elf32_Sym *symbol,
625 	struct elf_image_info *sharedImage, const char *symbolPrepend,
626 	addr_t *_symbolAddress)
627 {
628 	switch (symbol->st_shndx) {
629 		case SHN_UNDEF:
630 		{
631 			struct Elf32_Sym *newSymbol;
632 			char newNameBuffer[368];
633 			char *newName;
634 
635 			// patch the symbol name
636 			if (symbolPrepend) {
637 				newName = newNameBuffer;
638 				strlcpy(newName, symbolPrepend, sizeof(newName));
639 				strlcat(newName, SYMNAME(image, symbol), sizeof(newName));
640 			} else
641 				newName = SYMNAME(image, symbol);
642 
643 			// it's undefined, must be outside this image, try the other image
644 			newSymbol = elf_find_symbol(sharedImage, newName);
645 			if (newSymbol == NULL) {
646 				dprintf("\"%s\": could not resolve symbol '%s'\n",
647 					image->name, newName);
648 				return B_MISSING_SYMBOL;
649 			}
650 
651 			// make sure they're the same type
652 			if (ELF32_ST_TYPE(symbol->st_info)
653 					!= ELF32_ST_TYPE(newSymbol->st_info)) {
654 				dprintf("elf_resolve_symbol: found symbol '%s' in shared image "
655 					"but wrong type\n", newName);
656 				return B_MISSING_SYMBOL;
657 			}
658 
659 			if (ELF32_ST_BIND(newSymbol->st_info) != STB_GLOBAL
660 				&& ELF32_ST_BIND(newSymbol->st_info) != STB_WEAK) {
661 				TRACE(("elf_resolve_symbol: found symbol '%s' but not "
662 					"exported\n", newName));
663 				return B_MISSING_SYMBOL;
664 			}
665 
666 			*_symbolAddress = newSymbol->st_value
667 				+ sharedImage->text_region.delta;
668 			return B_OK;
669 		}
670 		case SHN_ABS:
671 			*_symbolAddress = symbol->st_value;
672 			return B_OK;
673 		case SHN_COMMON:
674 			// ToDo: finish this
675 			TRACE(("elf_resolve_symbol: COMMON symbol, finish me!\n"));
676 			return B_ERROR;
677 
678 		default:
679 			// standard symbol
680 			*_symbolAddress = symbol->st_value + image->text_region.delta;
681 			return B_OK;
682 	}
683 }
684 
685 
686 /*! Until we have shared library support, just this links against the kernel */
687 static int
688 elf_relocate(struct elf_image_info *image, const char *symbolPrepend)
689 {
690 	int status = B_NO_ERROR;
691 
692 	TRACE(("top of elf_relocate\n"));
693 
694 	// deal with the rels first
695 	if (image->rel) {
696 		TRACE(("total %i relocs\n",
697 			image->rel_len / (int)sizeof(struct Elf32_Rel)));
698 
699 		status = arch_elf_relocate_rel(image, symbolPrepend, sKernelImage,
700 			image->rel, image->rel_len);
701 		if (status < B_OK)
702 			return status;
703 	}
704 
705 	if (image->pltrel) {
706 		TRACE(("total %i plt-relocs\n",
707 			image->pltrel_len / (int)sizeof(struct Elf32_Rel)));
708 
709 		if (image->pltrel_type == DT_REL) {
710 			status = arch_elf_relocate_rel(image, symbolPrepend, sKernelImage,
711 				image->pltrel, image->pltrel_len);
712 		} else {
713 			status = arch_elf_relocate_rela(image, symbolPrepend, sKernelImage,
714 				(struct Elf32_Rela *)image->pltrel, image->pltrel_len);
715 		}
716 		if (status < B_OK)
717 			return status;
718 	}
719 
720 	if (image->rela) {
721 		status = arch_elf_relocate_rela(image, symbolPrepend, sKernelImage,
722 			image->rela, image->rela_len);
723 		if (status < B_OK)
724 			return status;
725 	}
726 
727 	return status;
728 }
729 
730 
731 static int
732 verify_eheader(struct Elf32_Ehdr *elfHeader)
733 {
734 	if (memcmp(elfHeader->e_ident, ELF_MAGIC, 4) != 0)
735 		return B_NOT_AN_EXECUTABLE;
736 
737 	if (elfHeader->e_ident[4] != ELFCLASS32)
738 		return B_NOT_AN_EXECUTABLE;
739 
740 	if (elfHeader->e_phoff == 0)
741 		return B_NOT_AN_EXECUTABLE;
742 
743 	if (elfHeader->e_phentsize < sizeof(struct Elf32_Phdr))
744 		return B_NOT_AN_EXECUTABLE;
745 
746 	return 0;
747 }
748 
749 
750 static status_t
751 unload_elf_image(struct elf_image_info *image)
752 {
753 	if (atomic_add(&image->ref_count, -1) > 1)
754 		return B_OK;
755 
756 	TRACE(("unload image %ld, %s\n", image->id, image->name));
757 
758 	delete_area(image->text_region.id);
759 	delete_area(image->data_region.id);
760 
761 	if (image->vnode)
762 		vfs_put_vnode(image->vnode);
763 
764 	unregister_elf_image(image);
765 
766 	free(image->debug_symbols);
767 	free((void*)image->debug_string_table);
768 	free(image->elf_header);
769 	free(image->name);
770 	free(image);
771 
772 	return B_NO_ERROR;
773 }
774 
775 
776 static status_t
777 load_elf_symbol_table(int fd, struct elf_image_info *image)
778 {
779 	struct Elf32_Ehdr *elfHeader = image->elf_header;
780 	struct Elf32_Sym *symbolTable = NULL;
781 	struct Elf32_Shdr *stringHeader = NULL;
782 	uint32 numSymbols = 0;
783 	char *stringTable;
784 	status_t status;
785 	ssize_t length;
786 	int32 i;
787 
788 	// get section headers
789 
790 	ssize_t size = elfHeader->e_shnum * elfHeader->e_shentsize;
791 	struct Elf32_Shdr *sectionHeaders = (struct Elf32_Shdr *)malloc(size);
792 	if (sectionHeaders == NULL) {
793 		dprintf("error allocating space for section headers\n");
794 		return B_NO_MEMORY;
795 	}
796 
797 	length = read_pos(fd, elfHeader->e_shoff, sectionHeaders, size);
798 	if (length < size) {
799 		TRACE(("error reading in program headers\n"));
800 		status = B_ERROR;
801 		goto error1;
802 	}
803 
804 	// find symbol table in section headers
805 
806 	for (i = 0; i < elfHeader->e_shnum; i++) {
807 		if (sectionHeaders[i].sh_type == SHT_SYMTAB) {
808 			stringHeader = &sectionHeaders[sectionHeaders[i].sh_link];
809 
810 			if (stringHeader->sh_type != SHT_STRTAB) {
811 				TRACE(("doesn't link to string table\n"));
812 				status = B_BAD_DATA;
813 				goto error1;
814 			}
815 
816 			// read in symbol table
817 			symbolTable
818 				= (struct Elf32_Sym *)malloc(size = sectionHeaders[i].sh_size);
819 			if (symbolTable == NULL) {
820 				status = B_NO_MEMORY;
821 				goto error1;
822 			}
823 
824 			length
825 				= read_pos(fd, sectionHeaders[i].sh_offset, symbolTable, size);
826 			if (length < size) {
827 				TRACE(("error reading in symbol table\n"));
828 				status = B_ERROR;
829 				goto error1;
830 			}
831 
832 			numSymbols = size / sizeof(struct Elf32_Sym);
833 			break;
834 		}
835 	}
836 
837 	if (symbolTable == NULL) {
838 		TRACE(("no symbol table\n"));
839 		status = B_BAD_VALUE;
840 		goto error1;
841 	}
842 
843 	// read in string table
844 
845 	stringTable = (char *)malloc(size = stringHeader->sh_size);
846 	if (stringTable == NULL) {
847 		status = B_NO_MEMORY;
848 		goto error2;
849 	}
850 
851 	length = read_pos(fd, stringHeader->sh_offset, stringTable, size);
852 	if (length < size) {
853 		TRACE(("error reading in string table\n"));
854 		status = B_ERROR;
855 		goto error3;
856 	}
857 
858 	TRACE(("loaded debug %ld symbols\n", numSymbols));
859 
860 	// insert tables into image
861 	image->debug_symbols = symbolTable;
862 	image->num_debug_symbols = numSymbols;
863 	image->debug_string_table = stringTable;
864 
865 	free(sectionHeaders);
866 	return B_OK;
867 
868 error3:
869 	free(stringTable);
870 error2:
871 	free(symbolTable);
872 error1:
873 	free(sectionHeaders);
874 
875 	return status;
876 }
877 
878 
879 static status_t
880 insert_preloaded_image(struct preloaded_image *preloadedImage, bool kernel)
881 {
882 	struct elf_image_info *image;
883 	status_t status;
884 
885 	status = verify_eheader(&preloadedImage->elf_header);
886 	if (status < B_OK)
887 		return status;
888 
889 	image = create_image_struct();
890 	if (image == NULL)
891 		return B_NO_MEMORY;
892 
893 	image->name = strdup(preloadedImage->name);
894 	image->dynamic_section = preloadedImage->dynamic_section.start;
895 
896 	image->text_region = preloadedImage->text_region;
897 	image->data_region = preloadedImage->data_region;
898 
899 	status = elf_parse_dynamic_section(image);
900 	if (status < B_OK)
901 		goto error1;
902 
903 	if (!kernel) {
904 		status = elf_relocate(image, NULL);
905 		if (status < B_OK)
906 			goto error1;
907 	} else
908 		sKernelImage = image;
909 
910 	// copy debug symbols to the kernel heap
911 	if (preloadedImage->debug_symbols != NULL) {
912 		int32 debugSymbolsSize = sizeof(Elf32_Sym)
913 			* preloadedImage->num_debug_symbols;
914 		image->debug_symbols = (Elf32_Sym*)malloc(debugSymbolsSize);
915 		if (image->debug_symbols != NULL) {
916 			memcpy(image->debug_symbols, preloadedImage->debug_symbols,
917 				debugSymbolsSize);
918 		}
919 	}
920 	image->num_debug_symbols = preloadedImage->num_debug_symbols;
921 
922 	// copy debug string table to the kernel heap
923 	if (preloadedImage->debug_string_table != NULL) {
924 		image->debug_string_table = (char*)malloc(
925 			preloadedImage->debug_string_table_size);
926 		if (image->debug_string_table != NULL) {
927 			memcpy((void*)image->debug_string_table,
928 				preloadedImage->debug_string_table,
929 				preloadedImage->debug_string_table_size);
930 		}
931 	}
932 
933 	register_elf_image(image);
934 	preloadedImage->id = image->id;
935 		// modules_init() uses this information to get the preloaded images
936 
937 	// we now no longer need to write to the text area anymore
938 	set_area_protection(image->text_region.id,
939 		B_KERNEL_READ_AREA | B_KERNEL_EXECUTE_AREA);
940 
941 	return B_OK;
942 
943 error1:
944 	free(image);
945 
946 	// clean up preloaded image resources (this image won't be used anymore)
947 	delete_area(preloadedImage->text_region.id);
948 	delete_area(preloadedImage->data_region.id);
949 	preloadedImage->id = -1;
950 
951 	return status;
952 }
953 
954 
955 //	#pragma mark - userland symbol lookup
956 
957 
958 class UserSymbolLookup {
959 public:
960 	static UserSymbolLookup& Default()
961 	{
962 		return sLookup;
963 	}
964 
965 	status_t Init(struct team* team)
966 	{
967 		// find the runtime loader debug area
968 		vm_area* area = team->address_space->areas;
969 		while (area != NULL) {
970 			if (strcmp(area->name, RUNTIME_LOADER_DEBUG_AREA_NAME) == 0)
971 				break;
972 			area = area->address_space_next;
973 		}
974 
975 		if (area == NULL)
976 			return B_ERROR;
977 
978 		// copy the runtime loader data structure
979 		if (!_Read((runtime_loader_debug_area*)area->base, fDebugArea))
980 			return B_BAD_ADDRESS;
981 
982 		return B_OK;
983 	}
984 
985 	status_t LookupSymbolAddress(addr_t address, addr_t *_baseAddress,
986 		const char **_symbolName, const char **_imageName, bool *_exactMatch)
987 	{
988 		// Note, that this function doesn't find all symbols that we would like
989 		// to find. E.g. static functions do not appear in the symbol table
990 		// as function symbols, but as sections without name and size. The
991 		// .symtab section together with the .strtab section, which apparently
992 		// differ from the tables referred to by the .dynamic section, also
993 		// contain proper names and sizes for those symbols. Therefore, to get
994 		// completely satisfying results, we would need to read those tables
995 		// from the shared object.
996 
997 		// get the image for the address
998 		image_t image;
999 		status_t error = _FindImageAtAddress(address, image);
1000 		if (error != B_OK)
1001 			return error;
1002 
1003 		strlcpy(fImageName, image.name, sizeof(fImageName));
1004 
1005 		// symbol hash table size
1006 		uint32 hashTabSize;
1007 		if (!_Read(image.symhash, hashTabSize))
1008 			return B_BAD_ADDRESS;
1009 
1010 		// remote pointers to hash buckets and chains
1011 		const uint32* hashBuckets = image.symhash + 2;
1012 		const uint32* hashChains = image.symhash + 2 + hashTabSize;
1013 
1014 		const elf_region_t& textRegion = image.regions[0];
1015 
1016 		// search the image for the symbol
1017 		Elf32_Sym symbolFound;
1018 		addr_t deltaFound = INT_MAX;
1019 		bool exactMatch = false;
1020 
1021 		// to get rid of the erroneous "uninitialized" warnings
1022 		symbolFound.st_name = 0;
1023 		symbolFound.st_value = 0;
1024 
1025 		for (uint32 i = 0; i < hashTabSize; i++) {
1026 			uint32 bucket;
1027 			if (!_Read(&hashBuckets[i], bucket))
1028 				return B_BAD_ADDRESS;
1029 
1030 			for (uint32 j = bucket; j != STN_UNDEF;
1031 					_Read(&hashChains[j], j) ? 0 : j = STN_UNDEF) {
1032 
1033 				Elf32_Sym symbol;
1034 				if (!_Read(image.syms + j, symbol))
1035 					continue;
1036 
1037 				// The symbol table contains not only symbols referring to
1038 				// functions and data symbols within the shared object, but also
1039 				// referenced symbols of other shared objects, as well as
1040 				// section and file references. We ignore everything but
1041 				// function and data symbols that have an st_value != 0 (0
1042 				// seems to be an indication for a symbol defined elsewhere
1043 				// -- couldn't verify that in the specs though).
1044 				if ((ELF32_ST_TYPE(symbol.st_info) != STT_FUNC
1045 						&& ELF32_ST_TYPE(symbol.st_info) != STT_OBJECT)
1046 					|| symbol.st_value == 0
1047 					|| symbol.st_value + symbol.st_size + textRegion.delta
1048 						> textRegion.vmstart + textRegion.size) {
1049 					continue;
1050 				}
1051 
1052 				// skip symbols starting after the given address
1053 				addr_t symbolAddress = symbol.st_value + textRegion.delta;
1054 				if (symbolAddress > address)
1055 					continue;
1056 				addr_t symbolDelta = address - symbolAddress;
1057 
1058 				if (symbolDelta < deltaFound) {
1059 					deltaFound = symbolDelta;
1060 					symbolFound = symbol;
1061 
1062 					if (symbolDelta >= 0 && symbolDelta < symbol.st_size) {
1063 						// exact match
1064 						exactMatch = true;
1065 						break;
1066 					}
1067 				}
1068 			}
1069 		}
1070 
1071 		if (_imageName)
1072 			*_imageName = fImageName;
1073 
1074 		if (_symbolName) {
1075 			*_symbolName = NULL;
1076 
1077 			if (deltaFound < INT_MAX) {
1078 				if (_ReadString(image, symbolFound.st_name, fSymbolName,
1079 						sizeof(fSymbolName))) {
1080 					*_symbolName = fSymbolName;
1081 				} else {
1082 					// we can't get its name, so forget the symbol
1083 					deltaFound = INT_MAX;
1084 				}
1085 			}
1086 		}
1087 
1088 		if (_baseAddress) {
1089 			if (deltaFound < INT_MAX)
1090 				*_baseAddress = symbolFound.st_value + textRegion.delta;
1091 			else
1092 				*_baseAddress = textRegion.vmstart;
1093 		}
1094 
1095 		if (_exactMatch)
1096 			*_exactMatch = exactMatch;
1097 
1098 		return B_OK;
1099 	}
1100 
1101 	status_t _FindImageAtAddress(addr_t address, image_t& image)
1102 	{
1103 		image_queue_t imageQueue;
1104 		if (!_Read(fDebugArea.loaded_images, imageQueue))
1105 			return B_BAD_ADDRESS;
1106 
1107 		image_t* imageAddress = imageQueue.head;
1108 		while (imageAddress != NULL) {
1109 			if (!_Read(imageAddress, image))
1110 				return B_BAD_ADDRESS;
1111 
1112 			if (image.regions[0].vmstart <= address
1113 				&& address < image.regions[0].vmstart + image.regions[0].size) {
1114 				return B_OK;
1115 			}
1116 
1117 			imageAddress = image.next;
1118 		}
1119 
1120 		return B_ENTRY_NOT_FOUND;
1121 	}
1122 
1123 	bool _ReadString(const image_t& image, uint32 offset, char* buffer,
1124 		size_t bufferSize)
1125 	{
1126 		const char* address = image.strtab + offset;
1127 
1128 		if (!IS_USER_ADDRESS(address))
1129 			return false;
1130 
1131 		return user_strlcpy(buffer, address, bufferSize) >= 0;
1132 	}
1133 
1134 	template<typename T> bool _Read(const T* address, T& data);
1135 		// gcc 2.95.3 doesn't like it defined in-place
1136 
1137 private:
1138 	runtime_loader_debug_area	fDebugArea;
1139 	char						fImageName[B_OS_NAME_LENGTH];
1140 	char						fSymbolName[256];
1141 	static UserSymbolLookup		sLookup;
1142 };
1143 
1144 
1145 template<typename T>
1146 bool
1147 UserSymbolLookup::_Read(const T* address, T& data)
1148 {
1149 	if (!IS_USER_ADDRESS(address))
1150 		return false;
1151 
1152 	return user_memcpy(&data, address, sizeof(T)) == B_OK;
1153 }
1154 
1155 
1156 UserSymbolLookup UserSymbolLookup::sLookup;
1157 	// doesn't need construction, but has an Init() method
1158 
1159 
1160 //	#pragma mark - public kernel API
1161 
1162 
1163 status_t
1164 get_image_symbol(image_id id, const char *name, int32 symbolClass,
1165 	void **_symbol)
1166 {
1167 	struct elf_image_info *image;
1168 	struct Elf32_Sym *symbol;
1169 	status_t status = B_OK;
1170 
1171 	TRACE(("get_image_symbol(%s)\n", name));
1172 
1173 	mutex_lock(&sImageMutex);
1174 
1175 	image = find_image(id);
1176 	if (image == NULL) {
1177 		status = B_BAD_IMAGE_ID;
1178 		goto done;
1179 	}
1180 
1181 	symbol = elf_find_symbol(image, name);
1182 	if (symbol == NULL || symbol->st_shndx == SHN_UNDEF) {
1183 		status = B_ENTRY_NOT_FOUND;
1184 		goto done;
1185 	}
1186 
1187 	// TODO: support the "symbolClass" parameter!
1188 
1189 	TRACE(("found: %lx (%lx + %lx)\n",
1190 		symbol->st_value + image->text_region.delta,
1191 		symbol->st_value, image->text_region.delta));
1192 
1193 	*_symbol = (void *)(symbol->st_value + image->text_region.delta);
1194 
1195 done:
1196 	mutex_unlock(&sImageMutex);
1197 	return status;
1198 }
1199 
1200 
1201 //	#pragma mark - kernel private API
1202 
1203 
1204 /*!	Looks up a symbol by address in all images loaded in kernel space.
1205 	Note, if you need to call this function outside a debugger, make
1206 	sure you fix locking and the way it returns its information, first!
1207 */
1208 status_t
1209 elf_debug_lookup_symbol_address(addr_t address, addr_t *_baseAddress,
1210 	const char **_symbolName, const char **_imageName, bool *_exactMatch)
1211 {
1212 	struct elf_image_info *image;
1213 	struct Elf32_Sym *symbolFound = NULL;
1214 	const char *symbolName = NULL;
1215 	addr_t deltaFound = INT_MAX;
1216 	bool exactMatch = false;
1217 	status_t status;
1218 
1219 	TRACE(("looking up %p\n", (void *)address));
1220 
1221 	if (!sInitialized)
1222 		return B_ERROR;
1223 
1224 	//mutex_lock(&sImageMutex);
1225 
1226 	image = find_image_at_address(address);
1227 		// get image that may contain the address
1228 
1229 	if (image != NULL) {
1230 		addr_t symbolDelta;
1231 		uint32 i;
1232 		int32 j;
1233 
1234 		TRACE((" image %p, base = %p, size = %p\n", image,
1235 			(void *)image->text_region.start, (void *)image->text_region.size));
1236 
1237 		if (image->debug_symbols != NULL) {
1238 			// search extended debug symbol table (contains static symbols)
1239 
1240 			TRACE((" searching debug symbols...\n"));
1241 
1242 			for (i = 0; i < image->num_debug_symbols; i++) {
1243 				struct Elf32_Sym *symbol = &image->debug_symbols[i];
1244 
1245 				if (symbol->st_value == 0 || symbol->st_size
1246 						>= image->text_region.size + image->data_region.size)
1247 					continue;
1248 
1249 				symbolDelta
1250 					= address - (symbol->st_value + image->text_region.delta);
1251 				if (symbolDelta >= 0 && symbolDelta < symbol->st_size)
1252 					exactMatch = true;
1253 
1254 				if (exactMatch || symbolDelta < deltaFound) {
1255 					deltaFound = symbolDelta;
1256 					symbolFound = symbol;
1257 					symbolName = image->debug_string_table + symbol->st_name;
1258 
1259 					if (exactMatch)
1260 						break;
1261 				}
1262 			}
1263 		} else {
1264 			// search standard symbol lookup table
1265 
1266 			TRACE((" searching standard symbols...\n"));
1267 
1268 			for (i = 0; i < HASHTABSIZE(image); i++) {
1269 				for (j = HASHBUCKETS(image)[i]; j != STN_UNDEF;
1270 						j = HASHCHAINS(image)[j]) {
1271 					struct Elf32_Sym *symbol = &image->syms[j];
1272 
1273 					if (symbol->st_value == 0
1274 						|| symbol->st_size >= image->text_region.size
1275 							+ image->data_region.size)
1276 						continue;
1277 
1278 					symbolDelta = address - (long)(symbol->st_value
1279 						+ image->text_region.delta);
1280 					if (symbolDelta >= 0 && symbolDelta < symbol->st_size)
1281 						exactMatch = true;
1282 
1283 					if (exactMatch || symbolDelta < deltaFound) {
1284 						deltaFound = symbolDelta;
1285 						symbolFound = symbol;
1286 						symbolName = SYMNAME(image, symbol);
1287 
1288 						if (exactMatch)
1289 							goto symbol_found;
1290 					}
1291 				}
1292 			}
1293 		}
1294 	}
1295 symbol_found:
1296 
1297 	if (symbolFound != NULL) {
1298 		if (_symbolName)
1299 			*_symbolName = symbolName;
1300 		if (_imageName)
1301 			*_imageName = image->name;
1302 		if (_baseAddress)
1303 			*_baseAddress = symbolFound->st_value + image->text_region.delta;
1304 		if (_exactMatch)
1305 			*_exactMatch = exactMatch;
1306 
1307 		status = B_OK;
1308 	} else if (image != NULL) {
1309 		TRACE(("symbol not found!\n"));
1310 
1311 		if (_symbolName)
1312 			*_symbolName = NULL;
1313 		if (_imageName)
1314 			*_imageName = image->name;
1315 		if (_baseAddress)
1316 			*_baseAddress = image->text_region.start;
1317 		if (_exactMatch)
1318 			*_exactMatch = false;
1319 
1320 		status = B_OK;
1321 	} else {
1322 		TRACE(("image not found!\n"));
1323 		status = B_ENTRY_NOT_FOUND;
1324 	}
1325 
1326 	// Note, theoretically, all information we return back to our caller
1327 	// would have to be locked - but since this function is only called
1328 	// from the debugger, it's safe to do it this way
1329 
1330 	//mutex_unlock(&sImageMutex);
1331 
1332 	return status;
1333 }
1334 
1335 
1336 /*!	Tries to find a matching user symbol for the given address.
1337 	Note that the given team's address space must already be in effect.
1338 */
1339 status_t
1340 elf_debug_lookup_user_symbol_address(struct team* team, addr_t address,
1341 	addr_t *_baseAddress, const char **_symbolName, const char **_imageName,
1342 	bool *_exactMatch)
1343 {
1344 	if (team == NULL || team == team_get_kernel_team())
1345 		return B_BAD_VALUE;
1346 
1347 	UserSymbolLookup& lookup = UserSymbolLookup::Default();
1348 	status_t error = lookup.Init(team);
1349 	if (error != B_OK)
1350 		return error;
1351 
1352 	return lookup.LookupSymbolAddress(address, _baseAddress, _symbolName,
1353 		_imageName, _exactMatch);
1354 }
1355 
1356 
1357 status_t
1358 elf_load_user_image(const char *path, struct team *team, int flags,
1359 	addr_t *entry)
1360 {
1361 	struct Elf32_Ehdr elfHeader;
1362 	struct Elf32_Phdr *programHeaders = NULL;
1363 	char baseName[B_OS_NAME_LENGTH];
1364 	status_t status;
1365 	ssize_t length;
1366 	int fd;
1367 	int i;
1368 
1369 	TRACE(("elf_load: entry path '%s', team %p\n", path, team));
1370 
1371 	fd = _kern_open(-1, path, O_RDONLY, 0);
1372 	if (fd < 0)
1373 		return fd;
1374 
1375 	struct stat st;
1376 	status = _kern_read_stat(fd, NULL, false, &st, sizeof(st));
1377 	if (status != B_OK)
1378 		return status;
1379 
1380 	// read and verify the ELF header
1381 
1382 	length = _kern_read(fd, 0, &elfHeader, sizeof(elfHeader));
1383 	if (length < B_OK) {
1384 		status = length;
1385 		goto error;
1386 	}
1387 
1388 	if (length != sizeof(elfHeader)) {
1389 		// short read
1390 		status = B_NOT_AN_EXECUTABLE;
1391 		goto error;
1392 	}
1393 	status = verify_eheader(&elfHeader);
1394 	if (status < B_OK)
1395 		goto error;
1396 
1397 	// read program header
1398 
1399 	programHeaders = (struct Elf32_Phdr *)malloc(
1400 		elfHeader.e_phnum * elfHeader.e_phentsize);
1401 	if (programHeaders == NULL) {
1402 		dprintf("error allocating space for program headers\n");
1403 		status = B_NO_MEMORY;
1404 		goto error;
1405 	}
1406 
1407 	TRACE(("reading in program headers at 0x%lx, length 0x%x\n",
1408 		elfHeader.e_phoff, elfHeader.e_phnum * elfHeader.e_phentsize));
1409 	length = _kern_read(fd, elfHeader.e_phoff, programHeaders,
1410 		elfHeader.e_phnum * elfHeader.e_phentsize);
1411 	if (length < B_OK) {
1412 		status = length;
1413 		dprintf("error reading in program headers\n");
1414 		goto error;
1415 	}
1416 	if (length != elfHeader.e_phnum * elfHeader.e_phentsize) {
1417 		dprintf("short read while reading in program headers\n");
1418 		status = -1;
1419 		goto error;
1420 	}
1421 
1422 	// construct a nice name for the region we have to create below
1423 	{
1424 		int32 length;
1425 
1426 		const char *leaf = strrchr(path, '/');
1427 		if (leaf == NULL)
1428 			leaf = path;
1429 		else
1430 			leaf++;
1431 
1432 		length = strlen(leaf);
1433 		if (length > B_OS_NAME_LENGTH - 8)
1434 			sprintf(baseName, "...%s", leaf + length + 8 - B_OS_NAME_LENGTH);
1435 		else
1436 			strcpy(baseName, leaf);
1437 	}
1438 
1439 	// map the program's segments into memory
1440 
1441 	image_info imageInfo;
1442 	memset(&imageInfo, 0, sizeof(image_info));
1443 
1444 	for (i = 0; i < elfHeader.e_phnum; i++) {
1445 		char regionName[B_OS_NAME_LENGTH];
1446 		char *regionAddress;
1447 		area_id id;
1448 
1449 		if (programHeaders[i].p_type != PT_LOAD)
1450 			continue;
1451 
1452 		regionAddress = (char *)ROUNDOWN(programHeaders[i].p_vaddr,
1453 			B_PAGE_SIZE);
1454 		if (programHeaders[i].p_flags & PF_WRITE) {
1455 			// rw/data segment
1456 			uint32 memUpperBound = (programHeaders[i].p_vaddr % B_PAGE_SIZE)
1457 				+ programHeaders[i].p_memsz;
1458 			uint32 fileUpperBound = (programHeaders[i].p_vaddr % B_PAGE_SIZE)
1459 				+ programHeaders[i].p_filesz;
1460 
1461 			memUpperBound = ROUNDUP(memUpperBound, B_PAGE_SIZE);
1462 			fileUpperBound = ROUNDUP(fileUpperBound, B_PAGE_SIZE);
1463 
1464 			sprintf(regionName, "%s_seg%drw", baseName, i);
1465 
1466 			id = vm_map_file(team->id, regionName, (void **)&regionAddress,
1467 				B_EXACT_ADDRESS, fileUpperBound,
1468 				B_READ_AREA | B_WRITE_AREA, REGION_PRIVATE_MAP,
1469 				fd, ROUNDOWN(programHeaders[i].p_offset, B_PAGE_SIZE));
1470 			if (id < B_OK) {
1471 				dprintf("error mapping file data: %s!\n", strerror(id));
1472 				status = B_NOT_AN_EXECUTABLE;
1473 				goto error;
1474 			}
1475 
1476 			imageInfo.data = regionAddress;
1477 			imageInfo.data_size = memUpperBound;
1478 
1479 			// clean garbage brought by mmap (the region behind the file,
1480 			// at least parts of it are the bss and have to be zeroed)
1481 			uint32 start = (uint32)regionAddress
1482 				+ (programHeaders[i].p_vaddr % B_PAGE_SIZE)
1483 				+ programHeaders[i].p_filesz;
1484 			uint32 amount = fileUpperBound
1485 				- (programHeaders[i].p_vaddr % B_PAGE_SIZE)
1486 				- (programHeaders[i].p_filesz);
1487 			memset((void *)start, 0, amount);
1488 
1489 			// Check if we need extra storage for the bss - we have to do this if
1490 			// the above region doesn't already comprise the memory size, too.
1491 
1492 			if (memUpperBound != fileUpperBound) {
1493 				size_t bssSize = memUpperBound - fileUpperBound;
1494 
1495 				snprintf(regionName, B_OS_NAME_LENGTH, "%s_bss%d", baseName, i);
1496 
1497 				regionAddress += fileUpperBound;
1498 				id = create_area_etc(team->id, regionName,
1499 					(void **)&regionAddress, B_EXACT_ADDRESS, bssSize,
1500 					B_NO_LOCK, B_READ_AREA | B_WRITE_AREA, 0);
1501 				if (id < B_OK) {
1502 					dprintf("error allocating bss area: %s!\n", strerror(id));
1503 					status = B_NOT_AN_EXECUTABLE;
1504 					goto error;
1505 				}
1506 			}
1507 		} else {
1508 			// assume ro/text segment
1509 			snprintf(regionName, B_OS_NAME_LENGTH, "%s_seg%dro", baseName, i);
1510 
1511 			size_t segmentSize = ROUNDUP(programHeaders[i].p_memsz
1512 				+ (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE);
1513 
1514 			id = vm_map_file(team->id, regionName, (void **)&regionAddress,
1515 				B_EXACT_ADDRESS, segmentSize,
1516 				B_READ_AREA | B_EXECUTE_AREA, REGION_PRIVATE_MAP,
1517 				fd, ROUNDOWN(programHeaders[i].p_offset, B_PAGE_SIZE));
1518 			if (id < B_OK) {
1519 				dprintf("error mapping file text: %s!\n", strerror(id));
1520 				status = B_NOT_AN_EXECUTABLE;
1521 				goto error;
1522 			}
1523 
1524 			imageInfo.text = regionAddress;
1525 			imageInfo.text_size = segmentSize;
1526 		}
1527 	}
1528 
1529 	// register the loaded image
1530 	imageInfo.type = B_LIBRARY_IMAGE;
1531     imageInfo.device = st.st_dev;
1532     imageInfo.node = st.st_ino;
1533 	strlcpy(imageInfo.name, path, sizeof(imageInfo.name));
1534 
1535 	imageInfo.id = register_image(team, &imageInfo, sizeof(image_info));
1536 	if (imageInfo.id >= 0 && team_get_current_team_id() == team->id)
1537 		user_debug_image_created(&imageInfo);
1538 		// Don't care, if registering fails. It's not crucial.
1539 
1540 	TRACE(("elf_load: done!\n"));
1541 
1542 	*entry = elfHeader.e_entry;
1543 	status = B_OK;
1544 
1545 error:
1546 	if (programHeaders)
1547 		free(programHeaders);
1548 	_kern_close(fd);
1549 
1550 	return status;
1551 }
1552 
1553 
1554 image_id
1555 load_kernel_add_on(const char *path)
1556 {
1557 	struct Elf32_Phdr *programHeaders;
1558 	struct Elf32_Ehdr *elfHeader;
1559 	struct elf_image_info *image;
1560 	const char *fileName;
1561 	void *reservedAddress;
1562 	addr_t start;
1563 	size_t reservedSize;
1564 	status_t status;
1565 	ssize_t length;
1566 
1567 	TRACE(("elf_load_kspace: entry path '%s'\n", path));
1568 
1569 	int fd = _kern_open(-1, path, O_RDONLY, 0);
1570 	if (fd < 0)
1571 		return fd;
1572 
1573 	struct vnode *vnode;
1574 	status = vfs_get_vnode_from_fd(fd, true, &vnode);
1575 	if (status < B_OK)
1576 		goto error0;
1577 
1578 	// get the file name
1579 	fileName = strrchr(path, '/');
1580 	if (fileName == NULL)
1581 		fileName = path;
1582 	else
1583 		fileName++;
1584 
1585 	// Prevent someone else from trying to load this image
1586 	mutex_lock(&sImageLoadMutex);
1587 
1588 	// make sure it's not loaded already. Search by vnode
1589 	image = find_image_by_vnode(vnode);
1590 	if (image) {
1591 		atomic_add(&image->ref_count, 1);
1592 		goto done;
1593 	}
1594 
1595 	elfHeader = (struct Elf32_Ehdr *)malloc(sizeof(*elfHeader));
1596 	if (!elfHeader) {
1597 		status = B_NO_MEMORY;
1598 		goto error;
1599 	}
1600 
1601 	length = _kern_read(fd, 0, elfHeader, sizeof(*elfHeader));
1602 	if (length < B_OK) {
1603 		status = length;
1604 		goto error1;
1605 	}
1606 	if (length != sizeof(*elfHeader)) {
1607 		// short read
1608 		status = B_NOT_AN_EXECUTABLE;
1609 		goto error1;
1610 	}
1611 	status = verify_eheader(elfHeader);
1612 	if (status < B_OK)
1613 		goto error1;
1614 
1615 	image = create_image_struct();
1616 	if (!image) {
1617 		status = B_NO_MEMORY;
1618 		goto error1;
1619 	}
1620 	image->vnode = vnode;
1621 	image->elf_header = elfHeader;
1622 	image->name = strdup(path);
1623 
1624 	programHeaders = (struct Elf32_Phdr *)malloc(elfHeader->e_phnum
1625 		* elfHeader->e_phentsize);
1626 	if (programHeaders == NULL) {
1627 		dprintf("%s: error allocating space for program headers\n", fileName);
1628 		status = B_NO_MEMORY;
1629 		goto error2;
1630 	}
1631 
1632 	TRACE(("reading in program headers at 0x%lx, length 0x%x\n",
1633 		elfHeader->e_phoff, elfHeader->e_phnum * elfHeader->e_phentsize));
1634 
1635 	length = _kern_read(fd, elfHeader->e_phoff, programHeaders,
1636 		elfHeader->e_phnum * elfHeader->e_phentsize);
1637 	if (length < B_OK) {
1638 		status = length;
1639 		TRACE(("%s: error reading in program headers\n", fileName));
1640 		goto error3;
1641 	}
1642 	if (length != elfHeader->e_phnum * elfHeader->e_phentsize) {
1643 		TRACE(("%s: short read while reading in program headers\n", fileName));
1644 		status = B_ERROR;
1645 		goto error3;
1646 	}
1647 
1648 	// determine how much space we need for all loaded segments
1649 
1650 	reservedSize = 0;
1651 	length = 0;
1652 
1653 	for (int32 i = 0; i < elfHeader->e_phnum; i++) {
1654 		size_t end;
1655 
1656 		if (programHeaders[i].p_type != PT_LOAD)
1657 			continue;
1658 
1659 		length += ROUNDUP(programHeaders[i].p_memsz
1660 			+ (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE);
1661 
1662 		end = ROUNDUP(programHeaders[i].p_memsz + programHeaders[i].p_vaddr,
1663 			B_PAGE_SIZE);
1664 		if (end > reservedSize)
1665 			reservedSize = end;
1666 	}
1667 
1668 	// Check whether the segments have an unreasonable amount of unused space
1669 	// inbetween.
1670 	if ((ssize_t)reservedSize > length + 8 * 1024) {
1671 		status = B_BAD_DATA;
1672 		goto error1;
1673 	}
1674 
1675 	// reserve that space and allocate the areas from that one
1676 	if (vm_reserve_address_range(vm_kernel_address_space_id(), &reservedAddress,
1677 			B_ANY_KERNEL_ADDRESS, reservedSize, 0) < B_OK) {
1678 		status = B_NO_MEMORY;
1679 		goto error3;
1680 	}
1681 
1682 	start = (addr_t)reservedAddress;
1683 	image->data_region.size = 0;
1684 	image->text_region.size = 0;
1685 
1686 	for (int32 i = 0; i < elfHeader->e_phnum; i++) {
1687 		char regionName[B_OS_NAME_LENGTH];
1688 		elf_region *region;
1689 
1690 		TRACE(("looking at program header %ld\n", i));
1691 
1692 		switch (programHeaders[i].p_type) {
1693 			case PT_LOAD:
1694 				break;
1695 			case PT_DYNAMIC:
1696 				image->dynamic_section = programHeaders[i].p_vaddr;
1697 				continue;
1698 			default:
1699 				dprintf("%s: unhandled pheader type 0x%lx\n", fileName,
1700 					programHeaders[i].p_type);
1701 				continue;
1702 		}
1703 
1704 		// we're here, so it must be a PT_LOAD segment
1705 		if (programHeaders[i].IsReadWrite()) {
1706 			// this is the writable segment
1707 			if (image->data_region.size != 0) {
1708 				// we've already created this segment
1709 				continue;
1710 			}
1711 			region = &image->data_region;
1712 
1713 			snprintf(regionName, B_OS_NAME_LENGTH, "%s_data", fileName);
1714 		} else if (programHeaders[i].IsExecutable()) {
1715 			// this is the non-writable segment
1716 			if (image->text_region.size != 0) {
1717 				// we've already created this segment
1718 				continue;
1719 			}
1720 			region = &image->text_region;
1721 
1722 			snprintf(regionName, B_OS_NAME_LENGTH, "%s_text", fileName);
1723 		} else {
1724 			dprintf("%s: weird program header flags 0x%lx\n", fileName,
1725 				programHeaders[i].p_flags);
1726 			continue;
1727 		}
1728 
1729 		region->start = (addr_t)reservedAddress + ROUNDOWN(
1730 			programHeaders[i].p_vaddr, B_PAGE_SIZE);
1731 		region->size = ROUNDUP(programHeaders[i].p_memsz
1732 			+ (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE);
1733 		region->id = create_area(regionName, (void **)&region->start,
1734 			B_EXACT_ADDRESS, region->size, B_FULL_LOCK,
1735 			B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
1736 		if (region->id < B_OK) {
1737 			dprintf("%s: error allocating area: %s\n", fileName,
1738 				strerror(region->id));
1739 			status = B_NOT_AN_EXECUTABLE;
1740 			goto error4;
1741 		}
1742 		region->delta = -ROUNDOWN(programHeaders[i].p_vaddr, B_PAGE_SIZE);
1743 
1744 		TRACE(("elf_load_kspace: created area \"%s\" at %p\n",
1745 			regionName, (void *)region->start));
1746 
1747 		length = _kern_read(fd, programHeaders[i].p_offset,
1748 			(void *)(region->start + (programHeaders[i].p_vaddr % B_PAGE_SIZE)),
1749 			programHeaders[i].p_filesz);
1750 		if (length < B_OK) {
1751 			status = length;
1752 			dprintf("%s: error reading in segment %ld\n", fileName, i);
1753 			goto error5;
1754 		}
1755 	}
1756 
1757 	// get the segment order
1758 	elf_region *firstRegion;
1759 	elf_region *secondRegion;
1760 	if (image->text_region.start < image->data_region.start) {
1761 		firstRegion = &image->text_region;
1762 		secondRegion = &image->data_region;
1763 	} else {
1764 		firstRegion = &image->data_region;
1765 		secondRegion = &image->text_region;
1766 	}
1767 
1768 	image->data_region.delta += image->data_region.start;
1769 	image->text_region.delta += image->text_region.start;
1770 
1771 	// modify the dynamic ptr by the delta of the regions
1772 	image->dynamic_section += image->text_region.delta;
1773 
1774 	status = elf_parse_dynamic_section(image);
1775 	if (status < B_OK)
1776 		goto error5;
1777 
1778 	status = elf_relocate(image, NULL);
1779 	if (status < B_OK)
1780 		goto error5;
1781 
1782 	// We needed to read in the contents of the "text" area, but
1783 	// now we can protect it read-only/execute
1784 	set_area_protection(image->text_region.id,
1785 		B_KERNEL_READ_AREA | B_KERNEL_EXECUTE_AREA);
1786 
1787 	// There might be a hole between the two segments, and we don't need to
1788 	// reserve this any longer
1789 	vm_unreserve_address_range(vm_kernel_address_space_id(), reservedAddress,
1790 		reservedSize);
1791 
1792 	// ToDo: this should be enabled by kernel settings!
1793 	if (1)
1794 		load_elf_symbol_table(fd, image);
1795 
1796 	free(programHeaders);
1797 	mutex_lock(&sImageMutex);
1798 	register_elf_image(image);
1799 	mutex_unlock(&sImageMutex);
1800 
1801 done:
1802 	_kern_close(fd);
1803 	mutex_unlock(&sImageLoadMutex);
1804 
1805 	return image->id;
1806 
1807 error5:
1808 	delete_area(image->data_region.id);
1809 	delete_area(image->text_region.id);
1810 error4:
1811 	vm_unreserve_address_range(vm_kernel_address_space_id(), reservedAddress,
1812 		reservedSize);
1813 error3:
1814 	free(programHeaders);
1815 error2:
1816 	free(image);
1817 error1:
1818 	free(elfHeader);
1819 error:
1820 	mutex_unlock(&sImageLoadMutex);
1821 error0:
1822 	dprintf("Could not load kernel add-on \"%s\": %s\n", path,
1823 		strerror(status));
1824 
1825 	if (vnode)
1826 		vfs_put_vnode(vnode);
1827 	_kern_close(fd);
1828 
1829 	return status;
1830 }
1831 
1832 
1833 status_t
1834 unload_kernel_add_on(image_id id)
1835 {
1836 	struct elf_image_info *image;
1837 	status_t status;
1838 
1839 	mutex_lock(&sImageLoadMutex);
1840 	mutex_lock(&sImageMutex);
1841 
1842 	image = find_image(id);
1843 	if (image != NULL)
1844 		status = unload_elf_image(image);
1845 	else
1846 		status = B_BAD_IMAGE_ID;
1847 
1848 	mutex_unlock(&sImageMutex);
1849 	mutex_unlock(&sImageLoadMutex);
1850 
1851 	return status;
1852 }
1853 
1854 
1855 status_t
1856 elf_get_image_info_for_address(addr_t address, image_info* info)
1857 {
1858 	MutexLocker _(sImageMutex);
1859 	struct elf_image_info* elfInfo = find_image_at_address(address);
1860 	if (elfInfo == NULL)
1861 		return B_ENTRY_NOT_FOUND;
1862 
1863 	info->id = elfInfo->id;
1864     info->type = B_SYSTEM_IMAGE;
1865     info->sequence = 0;
1866     info->init_order = 0;
1867     info->init_routine = NULL;
1868     info->term_routine = NULL;
1869     info->device = -1;
1870     info->node = -1;
1871 		// TODO: We could actually fill device/node in.
1872 	strlcpy(info->name, elfInfo->name, sizeof(info->name));
1873     info->text = (void*)elfInfo->text_region.start;
1874     info->data = (void*)elfInfo->data_region.start;
1875     info->text_size = elfInfo->text_region.size;
1876     info->data_size = elfInfo->data_region.size;
1877 
1878 	return B_OK;
1879 }
1880 
1881 
1882 image_id
1883 elf_create_memory_image(const char* imageName, addr_t text, size_t textSize,
1884 	addr_t data, size_t dataSize)
1885 {
1886 	// allocate the image
1887 	elf_image_info* image = create_image_struct();
1888 	if (image == NULL)
1889 		return B_NO_MEMORY;
1890 	MemoryDeleter imageDeleter(image);
1891 
1892 	// allocate symbol and string tables -- we allocate an empty symbol table,
1893 	// so that elf_debug_lookup_symbol_address() won't try the dynamic symbol
1894 	// table, which we don't have.
1895 	Elf32_Sym* symbolTable = (Elf32_Sym*)malloc(0);
1896 	char* stringTable = (char*)malloc(1);
1897 	MemoryDeleter symbolTableDeleter(symbolTable);
1898 	MemoryDeleter stringTableDeleter(stringTable);
1899 	if (symbolTable == NULL || stringTable == NULL)
1900 		return B_NO_MEMORY;
1901 
1902 	// the string table always contains the empty string
1903 	stringTable[0] = '\0';
1904 
1905 	image->debug_symbols = symbolTable;
1906 	image->num_debug_symbols = 0;
1907 	image->debug_string_table = stringTable;
1908 
1909 	// dup image name
1910 	image->name = strdup(imageName);
1911 	if (image->name == NULL)
1912 		return B_NO_MEMORY;
1913 
1914 	// data and text region
1915 	image->text_region.id = -1;
1916 	image->text_region.start = text;
1917 	image->text_region.size = textSize;
1918 	image->text_region.delta = 0;
1919 
1920 	image->data_region.id = -1;
1921 	image->data_region.start = data;
1922 	image->data_region.size = dataSize;
1923 	image->data_region.delta = 0;
1924 
1925 	mutex_lock(&sImageMutex);
1926 	register_elf_image(image);
1927 	image_id imageID = image->id;
1928 	mutex_unlock(&sImageMutex);
1929 
1930 	// keep the allocated memory
1931 	imageDeleter.Detach();
1932 	symbolTableDeleter.Detach();
1933 	stringTableDeleter.Detach();
1934 
1935 	return imageID;
1936 }
1937 
1938 
1939 status_t
1940 elf_add_memory_image_symbol(image_id id, const char* name, addr_t address,
1941 	size_t size, int32 type)
1942 {
1943 	MutexLocker _(sImageMutex);
1944 
1945 	// get the image
1946 	struct elf_image_info* image = find_image(id);
1947 	if (image == NULL)
1948 		return B_ENTRY_NOT_FOUND;
1949 
1950 	// get the current string table size
1951 	size_t stringTableSize = 1;
1952 	if (image->num_debug_symbols > 0) {
1953 		for (uint32 i = image->num_debug_symbols - 1; i >= 0; i--) {
1954 			int32 nameIndex = image->debug_symbols[i].st_name;
1955 			if (nameIndex != 0) {
1956 				stringTableSize = nameIndex
1957 					+ strlen(image->debug_string_table + nameIndex) + 1;
1958 				break;
1959 			}
1960 		}
1961 	}
1962 
1963 	// enter the name in the string table
1964 	char* stringTable = (char*)image->debug_string_table;
1965 	size_t stringIndex = 0;
1966 	if (name != NULL) {
1967 		size_t nameSize = strlen(name) + 1;
1968 		stringIndex = stringTableSize;
1969 		stringTableSize += nameSize;
1970 		stringTable = (char*)realloc((char*)image->debug_string_table,
1971 			stringTableSize);
1972 		if (stringTable == NULL)
1973 			return B_NO_MEMORY;
1974 		image->debug_string_table = stringTable;
1975 		memcpy(stringTable + stringIndex, name, nameSize);
1976 	}
1977 
1978 	// resize the symbol table
1979 	int32 symbolCount = image->num_debug_symbols + 1;
1980 	Elf32_Sym* symbolTable = (Elf32_Sym*)realloc(
1981 		(Elf32_Sym*)image->debug_symbols, sizeof(Elf32_Sym) * symbolCount);
1982 	if (symbolTable == NULL)
1983 		return B_NO_MEMORY;
1984 	image->debug_symbols = symbolTable;
1985 
1986 	// enter the symbol
1987 	Elf32_Sym& symbol = symbolTable[symbolCount - 1];
1988 	uint32 symbolType = type == B_SYMBOL_TYPE_DATA ? STT_OBJECT : STT_FUNC;
1989 	symbol.st_name = stringIndex;
1990 	symbol.st_value = address;
1991 	symbol.st_size = size;
1992 	symbol.st_info = ELF32_ST_INFO(STB_GLOBAL, symbolType);
1993 	symbol.st_other = 0;
1994 	symbol.st_shndx = 0;
1995 	image->num_debug_symbols++;
1996 
1997 	return B_OK;
1998 }
1999 
2000 
2001 status_t
2002 elf_init(kernel_args *args)
2003 {
2004 	struct preloaded_image *image;
2005 
2006 	image_init();
2007 
2008 	sImagesHash = hash_init(IMAGE_HASH_SIZE, 0, image_compare, image_hash);
2009 	if (sImagesHash == NULL)
2010 		return B_NO_MEMORY;
2011 
2012 	// Build a image structure for the kernel, which has already been loaded.
2013 	// The preloaded_images were already prepared by the VM.
2014 	if (insert_preloaded_image(&args->kernel_image, true) < B_OK)
2015 		panic("could not create kernel image.\n");
2016 
2017 	// Build image structures for all preloaded images.
2018 	for (image = args->preloaded_images; image != NULL; image = image->next) {
2019 		insert_preloaded_image(image, false);
2020 	}
2021 
2022 	add_debugger_command("ls", &dump_address_info,
2023 		"lookup symbol for a particular address");
2024 	add_debugger_command("symbols", &dump_symbols, "dump symbols for image");
2025 	add_debugger_command("symbol", &dump_symbol, "search symbol in images");
2026 	add_debugger_command("image", &dump_image, "dump image info");
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