xref: /haiku/src/system/kernel/elf.cpp (revision d9cebac2b77547b7064f22497514eecd2d047160)
1 /*
2  * Copyright 2002-2007, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
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 <debug.h>
22 #include <kimage.h>
23 #include <syscalls.h>
24 #include <team.h>
25 #include <thread.h>
26 #include <util/khash.h>
27 #include <vfs.h>
28 #include <vm.h>
29 #include <vm_address_space.h>
30 
31 #include <arch/cpu.h>
32 #include <arch/elf.h>
33 #include <elf_priv.h>
34 #include <boot/elf.h>
35 
36 //#define TRACE_ELF
37 #ifdef TRACE_ELF
38 #	define TRACE(x) dprintf x
39 #else
40 #	define TRACE(x) ;
41 #endif
42 
43 
44 // ToDo: this shall contain a list of linked images (one day)
45 //	this is a preparation for shared libraries in the kernel
46 //	and not yet used.
47 #if 0
48 typedef struct elf_linked_image {
49 	struct elf_linked_image *next;
50 	struct elf_image_info *image;
51 } elf_linked_image;
52 #endif
53 
54 #define IMAGE_HASH_SIZE 16
55 
56 static hash_table *sImagesHash;
57 
58 static struct elf_image_info *sKernelImage = NULL;
59 static mutex sImageMutex;		// guards sImagesHash
60 static mutex sImageLoadMutex;	// serializes loading/unloading add-ons
61 								// locking order sImageLoadMutex -> sImageMutex
62 static bool sInitialized = false;
63 
64 
65 /** calculates hash for an image using its ID */
66 
67 static uint32
68 image_hash(void *_image, const void *_key, uint32 range)
69 {
70 	struct elf_image_info *image = (struct elf_image_info *)_image;
71 	image_id id = (image_id)_key;
72 
73 	if (image != NULL)
74 		return image->id % range;
75 
76 	return (uint32)id % range;
77 }
78 
79 
80 /** compares an image to a given ID */
81 
82 static int
83 image_compare(void *_image, const void *_key)
84 {
85 	struct elf_image_info *image = (struct elf_image_info *)_image;
86 	image_id id = (image_id)_key;
87 
88 	return id - image->id;
89 }
90 
91 
92 static void
93 unregister_elf_image(struct elf_image_info *image)
94 {
95 	unregister_image(team_get_kernel_team(), image->id);
96 	hash_remove(sImagesHash, image);
97 }
98 
99 
100 static void
101 register_elf_image(struct elf_image_info *image)
102 {
103 	image_info imageInfo;
104 
105 	memset(&imageInfo, 0, sizeof(image_info));
106 	imageInfo.id = image->id;
107 	imageInfo.type = B_SYSTEM_IMAGE;
108 	strlcpy(imageInfo.name, image->name, sizeof(imageInfo.name));
109 
110 	imageInfo.text = (void *)image->text_region.start;
111 	imageInfo.text_size = image->text_region.size;
112 	imageInfo.data = (void *)image->data_region.start;
113 	imageInfo.data_size = image->data_region.size;
114 
115 	image->id = register_image(team_get_kernel_team(), &imageInfo, sizeof(image_info));
116 	hash_insert(sImagesHash, image);
117 }
118 
119 
120 /**	Note, you must lock the image mutex when you call this function. */
121 
122 static struct elf_image_info *
123 find_image_at_address(addr_t address)
124 {
125 	struct hash_iterator iterator;
126 	struct elf_image_info *image;
127 
128 	ASSERT_LOCKED_MUTEX(&sImageMutex);
129 
130 	hash_open(sImagesHash, &iterator);
131 
132 	// get image that may contain the address
133 
134 	while ((image = (elf_image_info *)hash_next(sImagesHash, &iterator)) != NULL) {
135 		if ((address >= image->text_region.start
136 				&& address <= (image->text_region.start + image->text_region.size))
137 			|| (address >= image->data_region.start
138 				&& address <= (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 	if (elf_debug_lookup_symbol_address(address, &baseAddress, &symbol,
162 			&imageName, &exactMatch) == B_OK) {
163 		kprintf("%p = %s + 0x%lx (%s)%s\n", (void *)address, symbol,
164 			address - baseAddress, imageName, exactMatch ? "" : " (nearest)");
165 	} else
166 		kprintf("There is no image loaded at this address!\n");
167 
168 	return 0;
169 }
170 
171 
172 static struct elf_image_info *
173 find_image(image_id id)
174 {
175 	return (elf_image_info *)hash_lookup(sImagesHash, (void *)id);
176 }
177 
178 
179 static struct elf_image_info *
180 find_image_by_vnode(void *vnode)
181 {
182 	struct hash_iterator iterator;
183 	struct elf_image_info *image;
184 
185 	mutex_lock(&sImageMutex);
186 	hash_open(sImagesHash, &iterator);
187 
188 	while ((image = (elf_image_info *)hash_next(sImagesHash, &iterator)) != NULL) {
189 		if (image->vnode == vnode)
190 			break;
191 	}
192 
193 	hash_close(sImagesHash, &iterator, false);
194 	mutex_unlock(&sImageMutex);
195 
196 	return image;
197 }
198 
199 
200 static struct elf_image_info *
201 create_image_struct()
202 {
203 	struct elf_image_info *image = (struct elf_image_info *)malloc(sizeof(struct elf_image_info));
204 	if (image == NULL)
205 		return NULL;
206 
207 	memset(image, 0, sizeof(struct elf_image_info));
208 
209 	image->text_region.id = -1;
210 	image->data_region.id = -1;
211 	image->ref_count = 1;
212 
213 	return image;
214 }
215 
216 
217 static uint32
218 elf_hash(const char *name)
219 {
220 	uint32 hash = 0;
221 	uint32 temp;
222 
223 	while (*name) {
224 		hash = (hash << 4) + (uint8)*name++;
225 		if ((temp = hash & 0xf0000000) != 0)
226 			hash ^= temp >> 24;
227 		hash &= ~temp;
228 	}
229 	return hash;
230 }
231 
232 
233 static const char *
234 get_symbol_type_string(struct Elf32_Sym *symbol)
235 {
236 	switch (ELF32_ST_TYPE(symbol->st_info)) {
237 		case STT_FUNC:
238 			return "func";
239 		case STT_OBJECT:
240 			return " obj";
241 		case STT_FILE:
242 			return "file";
243 		default:
244 			return "----";
245 	}
246 }
247 
248 
249 static const char *
250 get_symbol_bind_string(struct Elf32_Sym *symbol)
251 {
252 	switch (ELF32_ST_BIND(symbol->st_info)) {
253 		case STB_LOCAL:
254 			return "loc ";
255 		case STB_GLOBAL:
256 			return "glob";
257 		case STB_WEAK:
258 			return "weak";
259 		default:
260 			return "----";
261 	}
262 }
263 
264 
265 static int
266 dump_symbols(int argc, char **argv)
267 {
268 	struct elf_image_info *image = NULL;
269 	struct hash_iterator iterator;
270 	uint32 i;
271 
272 	// if the argument looks like a hex number, treat it as such
273 	if (argc > 1) {
274 		if (isdigit(argv[1][0])) {
275 			uint32 num = strtoul(argv[1], NULL, 0);
276 
277 			if (IS_KERNEL_ADDRESS(num)) {
278 				// find image at address
279 
280 				hash_open(sImagesHash, &iterator);
281 				while ((image = (elf_image_info *)hash_next(sImagesHash, &iterator)) != NULL) {
282 					if (image->text_region.start <= num
283 						&& image->text_region.start + image->text_region.size >= num)
284 						break;
285 				}
286 				hash_close(sImagesHash, &iterator, false);
287 
288 				if (image == NULL)
289 					kprintf("No image covers 0x%lx in the kernel!\n", num);
290 			} else {
291 				image = (elf_image_info *)hash_lookup(sImagesHash, (void *)num);
292 				if (image == NULL)
293 					kprintf("image 0x%lx doesn't exist in the kernel!\n", num);
294 			}
295 		} else {
296 			// look for image by name
297 			hash_open(sImagesHash, &iterator);
298 			while ((image = (elf_image_info *)hash_next(sImagesHash, &iterator)) != NULL) {
299 				if (!strcmp(image->name, argv[1]))
300 					break;
301 			}
302 			hash_close(sImagesHash, &iterator, false);
303 
304 			if (image == NULL)
305 				kprintf("No image \"%s\" found in kernel!\n", argv[1]);
306 		}
307 	} else {
308 		kprintf("usage: %s image_name/image_id/address_in_image\n", argv[0]);
309 		return 0;
310 	}
311 
312 	if (image == NULL)
313 		return -1;
314 
315 	// dump symbols
316 
317 	kprintf("Symbols of image %ld \"%s\":\nAddress  Type       Size Name\n", image->id, image->name);
318 
319 	if (image->num_debug_symbols > 0) {
320 		// search extended debug symbol table (contains static symbols)
321 		for (i = 0; i < image->num_debug_symbols; i++) {
322 			struct Elf32_Sym *symbol = &image->debug_symbols[i];
323 
324 			if (symbol->st_value == 0
325 				|| symbol->st_size >= image->text_region.size + image->data_region.size)
326 				continue;
327 
328 			kprintf("%08lx %s/%s %5ld %s\n", symbol->st_value + image->text_region.delta,
329 				get_symbol_type_string(symbol), get_symbol_bind_string(symbol), symbol->st_size,
330 				image->debug_string_table + symbol->st_name);
331 		}
332 	} else {
333 		int32 j;
334 
335 		// search standard symbol lookup table
336 		for (i = 0; i < HASHTABSIZE(image); i++) {
337 			for (j = HASHBUCKETS(image)[i]; j != STN_UNDEF; j = HASHCHAINS(image)[j]) {
338 				struct Elf32_Sym *symbol = &image->syms[j];
339 
340 				if (symbol->st_value == 0
341 					|| symbol->st_size >= image->text_region.size + image->data_region.size)
342 					continue;
343 
344 				kprintf("%08lx %s/%s %5ld %s\n", symbol->st_value + image->text_region.delta,
345 					get_symbol_type_string(symbol), get_symbol_bind_string(symbol),
346 					symbol->st_size, SYMNAME(image, symbol));
347 			}
348 		}
349 	}
350 
351 	return 0;
352 }
353 
354 
355 static void
356 dump_elf_region(struct elf_region *region, const char *name)
357 {
358 	kprintf("   %s.id 0x%lx\n", name, region->id);
359 	kprintf("   %s.start 0x%lx\n", name, region->start);
360 	kprintf("   %s.size 0x%lx\n", name, region->size);
361 	kprintf("   %s.delta %ld\n", name, region->delta);
362 }
363 
364 
365 static void
366 dump_image_info(struct elf_image_info *image)
367 {
368 	kprintf("elf_image_info at %p:\n", image);
369 	kprintf(" next %p\n", image->next);
370 	kprintf(" id 0x%lx\n", image->id);
371 	dump_elf_region(&image->text_region, "text");
372 	dump_elf_region(&image->data_region, "data");
373 	kprintf(" dynamic_section 0x%lx\n", image->dynamic_section);
374 	kprintf(" needed %p\n", image->needed);
375 	kprintf(" symhash %p\n", image->symhash);
376 	kprintf(" syms %p\n", image->syms);
377 	kprintf(" strtab %p\n", image->strtab);
378 	kprintf(" rel %p\n", image->rel);
379 	kprintf(" rel_len 0x%x\n", image->rel_len);
380 	kprintf(" rela %p\n", image->rela);
381 	kprintf(" rela_len 0x%x\n", image->rela_len);
382 	kprintf(" pltrel %p\n", image->pltrel);
383 	kprintf(" pltrel_len 0x%x\n", image->pltrel_len);
384 
385 	kprintf(" debug_symbols %p (%ld)\n", image->debug_symbols, image->num_debug_symbols);
386 }
387 
388 
389 static int
390 dump_image(int argc, char **argv)
391 {
392 	struct hash_iterator iterator;
393 	struct elf_image_info *image;
394 
395 	// if the argument looks like a hex number, treat it as such
396 	if (argc > 1) {
397 		uint32 num = strtoul(argv[1], NULL, 0);
398 
399 		if (IS_KERNEL_ADDRESS(num)) {
400 			// semi-hack
401 			dump_image_info((struct elf_image_info *)num);
402 		} else {
403 			image = (elf_image_info *)hash_lookup(sImagesHash, (void *)num);
404 			if (image == NULL)
405 				kprintf("image 0x%lx doesn't exist in the kernel!\n", num);
406 			else
407 				dump_image_info(image);
408 		}
409 		return 0;
410 	}
411 
412 	kprintf("loaded kernel images:\n");
413 
414 	hash_open(sImagesHash, &iterator);
415 
416 	while ((image = (elf_image_info *)hash_next(sImagesHash, &iterator)) != NULL) {
417 		kprintf("%p (%ld) %s\n", image, image->id, image->name);
418 	}
419 
420 	hash_close(sImagesHash, &iterator, false);
421 	return 0;
422 }
423 
424 
425 // Currently unused
426 #if 0
427 static
428 void dump_symbol(struct elf_image_info *image, struct Elf32_Sym *sym)
429 {
430 
431 	kprintf("symbol at %p, in image %p\n", sym, image);
432 
433 	kprintf(" name index %d, '%s'\n", sym->st_name, SYMNAME(image, sym));
434 	kprintf(" st_value 0x%x\n", sym->st_value);
435 	kprintf(" st_size %d\n", sym->st_size);
436 	kprintf(" st_info 0x%x\n", sym->st_info);
437 	kprintf(" st_other 0x%x\n", sym->st_other);
438 	kprintf(" st_shndx %d\n", sym->st_shndx);
439 }
440 #endif
441 
442 
443 static struct Elf32_Sym *
444 elf_find_symbol(struct elf_image_info *image, const char *name)
445 {
446 	uint32 hash;
447 	uint32 i;
448 
449 	if (!image->dynamic_section)
450 		return NULL;
451 
452 	hash = elf_hash(name) % HASHTABSIZE(image);
453 	for (i = HASHBUCKETS(image)[hash]; i != STN_UNDEF; i = HASHCHAINS(image)[i]) {
454 		if (!strcmp(SYMNAME(image, &image->syms[i]), name))
455 			return &image->syms[i];
456 	}
457 
458 	return NULL;
459 }
460 
461 
462 static status_t
463 elf_parse_dynamic_section(struct elf_image_info *image)
464 {
465 	struct Elf32_Dyn *d;
466 	int32 neededOffset = -1;
467 
468 	TRACE(("top of elf_parse_dynamic_section\n"));
469 
470 	image->symhash = 0;
471 	image->syms = 0;
472 	image->strtab = 0;
473 
474 	d = (struct Elf32_Dyn *)image->dynamic_section;
475 	if (!d)
476 		return B_ERROR;
477 
478 	for (int32 i = 0; d[i].d_tag != DT_NULL; i++) {
479 		switch (d[i].d_tag) {
480 			case DT_NEEDED:
481 				neededOffset = d[i].d_un.d_ptr + image->text_region.delta;
482 				break;
483 			case DT_HASH:
484 				image->symhash = (uint32 *)(d[i].d_un.d_ptr + image->text_region.delta);
485 				break;
486 			case DT_STRTAB:
487 				image->strtab = (char *)(d[i].d_un.d_ptr + image->text_region.delta);
488 				break;
489 			case DT_SYMTAB:
490 				image->syms = (struct Elf32_Sym *)(d[i].d_un.d_ptr + image->text_region.delta);
491 				break;
492 			case DT_REL:
493 				image->rel = (struct Elf32_Rel *)(d[i].d_un.d_ptr + image->text_region.delta);
494 				break;
495 			case DT_RELSZ:
496 				image->rel_len = d[i].d_un.d_val;
497 				break;
498 			case DT_RELA:
499 				image->rela = (struct Elf32_Rela *)(d[i].d_un.d_ptr + image->text_region.delta);
500 				break;
501 			case DT_RELASZ:
502 				image->rela_len = d[i].d_un.d_val;
503 				break;
504 			case DT_JMPREL:
505 				image->pltrel = (struct Elf32_Rel *)(d[i].d_un.d_ptr + image->text_region.delta);
506 				break;
507 			case DT_PLTRELSZ:
508 				image->pltrel_len = d[i].d_un.d_val;
509 				break;
510 			case DT_PLTREL:
511 				image->pltrel_type = d[i].d_un.d_val;
512 				break;
513 
514 			default:
515 				continue;
516 		}
517 	}
518 
519 	// lets make sure we found all the required sections
520 	if (!image->symhash || !image->syms || !image->strtab)
521 		return B_ERROR;
522 
523 	TRACE(("needed_offset = %d\n", neededOffset));
524 
525 	if (neededOffset >= 0)
526 		image->needed = STRING(image, neededOffset);
527 
528 	return B_OK;
529 }
530 
531 
532 /**	this function first tries to see if the first image and it's already resolved symbol is okay, otherwise
533  *	it tries to link against the shared_image
534  *	XXX gross hack and needs to be done better
535  */
536 
537 status_t
538 elf_resolve_symbol(struct elf_image_info *image, struct Elf32_Sym *sym,
539 	struct elf_image_info *shared_image, const char *sym_prepend, addr_t *sym_addr)
540 {
541 	struct Elf32_Sym *sym2;
542 	char new_symname[512];
543 
544 	switch (sym->st_shndx) {
545 		case SHN_UNDEF:
546 			// patch the symbol name
547 			strlcpy(new_symname, sym_prepend, sizeof(new_symname));
548 			strlcat(new_symname, SYMNAME(image, sym), sizeof(new_symname));
549 
550 			// it's undefined, must be outside this image, try the other image
551 			sym2 = elf_find_symbol(shared_image, new_symname);
552 			if (!sym2) {
553 				dprintf("\"%s\": could not resolve symbol '%s'\n",
554 					image->name, new_symname);
555 				return B_MISSING_SYMBOL;
556 			}
557 
558 			// make sure they're the same type
559 			if (ELF32_ST_TYPE(sym->st_info) != ELF32_ST_TYPE(sym2->st_info)) {
560 				dprintf("elf_resolve_symbol: found symbol '%s' in shared image but wrong type\n", new_symname);
561 				return B_MISSING_SYMBOL;
562 			}
563 
564 			if (ELF32_ST_BIND(sym2->st_info) != STB_GLOBAL && ELF32_ST_BIND(sym2->st_info) != STB_WEAK) {
565 				TRACE(("elf_resolve_symbol: found symbol '%s' but not exported\n", new_symname));
566 				return B_MISSING_SYMBOL;
567 			}
568 
569 			*sym_addr = sym2->st_value + shared_image->text_region.delta;
570 			return B_NO_ERROR;
571 		case SHN_ABS:
572 			*sym_addr = sym->st_value;
573 			return B_NO_ERROR;
574 		case SHN_COMMON:
575 			// ToDo: finish this
576 			TRACE(("elf_resolve_symbol: COMMON symbol, finish me!\n"));
577 			return B_ERROR;
578 		default:
579 			// standard symbol
580 			*sym_addr = sym->st_value + image->text_region.delta;
581 			return B_NO_ERROR;
582 	}
583 }
584 
585 
586 /** Until we have shared library support, just links against the kernel */
587 
588 static int
589 elf_relocate(struct elf_image_info *image, const char *sym_prepend)
590 {
591 	int status = B_NO_ERROR;
592 
593 	TRACE(("top of elf_relocate\n"));
594 
595 	// deal with the rels first
596 	if (image->rel) {
597 		TRACE(("total %i relocs\n", image->rel_len / (int)sizeof(struct Elf32_Rel)));
598 
599 		status = arch_elf_relocate_rel(image, sym_prepend, sKernelImage, image->rel, image->rel_len);
600 		if (status < B_OK)
601 			return status;
602 	}
603 
604 	if (image->pltrel) {
605 		TRACE(("total %i plt-relocs\n", image->pltrel_len / (int)sizeof(struct Elf32_Rel)));
606 
607 		if (image->pltrel_type == DT_REL)
608 			status = arch_elf_relocate_rel(image, sym_prepend, sKernelImage, image->pltrel, image->pltrel_len);
609 		else
610 			status = arch_elf_relocate_rela(image, sym_prepend, sKernelImage, (struct Elf32_Rela *)image->pltrel, image->pltrel_len);
611 		if (status < B_OK)
612 			return status;
613 	}
614 
615 	if (image->rela) {
616 		status = arch_elf_relocate_rela(image, sym_prepend, sKernelImage, image->rela, image->rela_len);
617 		if (status < B_OK)
618 			return status;
619 	}
620 
621 	return status;
622 }
623 
624 
625 static int
626 verify_eheader(struct Elf32_Ehdr *elfHeader)
627 {
628 	if (memcmp(elfHeader->e_ident, ELF_MAGIC, 4) != 0)
629 		return B_NOT_AN_EXECUTABLE;
630 
631 	if (elfHeader->e_ident[4] != ELFCLASS32)
632 		return B_NOT_AN_EXECUTABLE;
633 
634 	if (elfHeader->e_phoff == 0)
635 		return B_NOT_AN_EXECUTABLE;
636 
637 	if (elfHeader->e_phentsize < sizeof(struct Elf32_Phdr))
638 		return B_NOT_AN_EXECUTABLE;
639 
640 	return 0;
641 }
642 
643 
644 #if 0
645 static int
646 elf_unlink_relocs(struct elf_image_info *image)
647 {
648 	elf_linked_image *link, *next_link;
649 
650 	for (link = image->linked_images; link; link = next_link) {
651 		next_link = link->next;
652 		elf_unload_image(link->image);
653 		free(link);
654 	}
655 
656 	return B_NO_ERROR;
657 }
658 #endif
659 
660 
661 static status_t
662 unload_elf_image(struct elf_image_info *image)
663 {
664 	if (atomic_add(&image->ref_count, -1) > 0)
665 		return B_NO_ERROR;
666 
667 	//elf_unlink_relocs(image);
668 		// not yet used
669 
670 	delete_area(image->text_region.id);
671 	delete_area(image->data_region.id);
672 
673 	if (image->vnode)
674 		vfs_put_vnode(image->vnode);
675 
676 	unregister_elf_image(image);
677 
678 	free(image->elf_header);
679 	free(image->name);
680 	free(image);
681 
682 	return B_NO_ERROR;
683 }
684 
685 
686 static status_t
687 load_elf_symbol_table(int fd, struct elf_image_info *image)
688 {
689 	struct Elf32_Ehdr *elfHeader = image->elf_header;
690 	struct Elf32_Sym *symbolTable = NULL;
691 	struct Elf32_Shdr *stringHeader = NULL;
692 	uint32 numSymbols = 0;
693 	char *stringTable;
694 	status_t status;
695 	ssize_t length;
696 	int32 i;
697 
698 	// get section headers
699 
700 	ssize_t size = elfHeader->e_shnum * elfHeader->e_shentsize;
701 	struct Elf32_Shdr *sectionHeaders = (struct Elf32_Shdr *)malloc(size);
702 	if (sectionHeaders == NULL) {
703 		dprintf("error allocating space for section headers\n");
704 		return B_NO_MEMORY;
705 	}
706 
707 	length = read_pos(fd, elfHeader->e_shoff, sectionHeaders, size);
708 	if (length < size) {
709 		TRACE(("error reading in program headers\n"));
710 		status = B_ERROR;
711 		goto error1;
712 	}
713 
714 	// find symbol table in section headers
715 
716 	for (i = 0; i < elfHeader->e_shnum; i++) {
717 		if (sectionHeaders[i].sh_type == SHT_SYMTAB) {
718 			stringHeader = &sectionHeaders[sectionHeaders[i].sh_link];
719 
720 			if (stringHeader->sh_type != SHT_STRTAB) {
721 				TRACE(("doesn't link to string table\n"));
722 				status = B_BAD_DATA;
723 				goto error1;
724 			}
725 
726 			// read in symbol table
727 			symbolTable = (struct Elf32_Sym *)malloc(size = sectionHeaders[i].sh_size);
728 			if (symbolTable == NULL) {
729 				status = B_NO_MEMORY;
730 				goto error1;
731 			}
732 
733 			length = read_pos(fd, sectionHeaders[i].sh_offset, symbolTable, size);
734 			if (length < size) {
735 				TRACE(("error reading in symbol table\n"));
736 				status = B_ERROR;
737 				goto error1;
738 			}
739 
740 			numSymbols = size / sizeof(struct Elf32_Sym);
741 			break;
742 		}
743 	}
744 
745 	if (symbolTable == NULL) {
746 		TRACE(("no symbol table\n"));
747 		status = B_BAD_VALUE;
748 		goto error1;
749 	}
750 
751 	// read in string table
752 
753 	stringTable = (char *)malloc(size = stringHeader->sh_size);
754 	if (stringTable == NULL) {
755 		status = B_NO_MEMORY;
756 		goto error2;
757 	}
758 
759 	length = read_pos(fd, stringHeader->sh_offset, stringTable, size);
760 	if (length < size) {
761 		TRACE(("error reading in string table\n"));
762 		status = B_ERROR;
763 		goto error3;
764 	}
765 
766 	TRACE(("loaded debug %ld symbols\n", numSymbols));
767 
768 	// insert tables into image
769 	image->debug_symbols = symbolTable;
770 	image->num_debug_symbols = numSymbols;
771 	image->debug_string_table = stringTable;
772 
773 	free(sectionHeaders);
774 	return B_OK;
775 
776 error3:
777 	free(stringTable);
778 error2:
779 	free(symbolTable);
780 error1:
781 	free(sectionHeaders);
782 
783 	return status;
784 }
785 
786 
787 static status_t
788 insert_preloaded_image(struct preloaded_image *preloadedImage, bool kernel)
789 {
790 	struct elf_image_info *image;
791 	status_t status;
792 
793 	status = verify_eheader(&preloadedImage->elf_header);
794 	if (status < B_OK)
795 		return status;
796 
797 	image = create_image_struct();
798 	if (image == NULL)
799 		return B_NO_MEMORY;
800 
801 	image->name = strdup(preloadedImage->name);
802 	image->dynamic_section = preloadedImage->dynamic_section.start;
803 
804 	image->text_region = preloadedImage->text_region;
805 	image->data_region = preloadedImage->data_region;
806 
807 	status = elf_parse_dynamic_section(image);
808 	if (status < B_OK)
809 		goto error1;
810 
811 	if (!kernel) {
812 		status = elf_relocate(image, "");
813 		if (status < B_OK)
814 			goto error1;
815 	} else
816 		sKernelImage = image;
817 
818 	image->debug_symbols = preloadedImage->debug_symbols;
819 	image->num_debug_symbols = preloadedImage->num_debug_symbols;
820 	image->debug_string_table = preloadedImage->debug_string_table;
821 
822 	register_elf_image(image);
823 	preloadedImage->id = image->id;
824 		// modules_init() uses this information to get the preloaded images
825 
826 	// we now no longer need to write to the text area anymore
827 	set_area_protection(image->text_region.id,
828 		B_KERNEL_READ_AREA | B_KERNEL_EXECUTE_AREA);
829 
830 	return B_OK;
831 
832 error1:
833 	free(image);
834 
835 	// clean up preloaded image resources (this image won't be used anymore)
836 	delete_area(preloadedImage->text_region.id);
837 	delete_area(preloadedImage->data_region.id);
838 	preloadedImage->id = -1;
839 
840 	return status;
841 }
842 
843 
844 //	#pragma mark -
845 //	public kernel API
846 
847 
848 status_t
849 get_image_symbol(image_id id, const char *name, int32 sclass, void **_symbol)
850 {
851 	struct elf_image_info *image;
852 	struct Elf32_Sym *symbol;
853 	status_t status = B_OK;
854 
855 	TRACE(("get_image_symbol(%s)\n", name));
856 
857 	mutex_lock(&sImageMutex);
858 
859 	image = find_image(id);
860 	if (image == NULL) {
861 		status = B_BAD_IMAGE_ID;
862 		goto done;
863 	}
864 
865 	symbol = elf_find_symbol(image, name);
866 	if (symbol == NULL || symbol->st_shndx == SHN_UNDEF) {
867 		status = B_ENTRY_NOT_FOUND;
868 		goto done;
869 	}
870 
871 	// ToDo: support the "sclass" parameter!
872 
873 	TRACE(("found: %lx (%lx + %lx)\n", symbol->st_value + image->text_region.delta,
874 		symbol->st_value, image->text_region.delta));
875 
876 	*_symbol = (void *)(symbol->st_value + image->text_region.delta);
877 
878 done:
879 	mutex_unlock(&sImageMutex);
880 	return status;
881 }
882 
883 
884 //	#pragma mark -
885 //	kernel private API
886 
887 
888 /**	Looks up a symbol by address in all images loaded in kernel space.
889  *	Note, if you need to call this function outside a debugger, make
890  *	sure you fix locking and the way it returns its information, first!
891  */
892 
893 status_t
894 elf_debug_lookup_symbol_address(addr_t address, addr_t *_baseAddress,
895 	const char **_symbolName, const char **_imageName, bool *_exactMatch)
896 {
897 	struct elf_image_info *image;
898 	struct Elf32_Sym *symbolFound = NULL;
899 	const char *symbolName = NULL;
900 	addr_t deltaFound = INT_MAX;
901 	bool exactMatch = false;
902 	status_t status;
903 
904 	TRACE(("looking up %p\n", (void *)address));
905 
906 	if (!sInitialized)
907 		return B_ERROR;
908 
909 	//mutex_lock(&sImageMutex);
910 
911 	image = find_image_at_address(address);
912 		// get image that may contain the address
913 
914 	if (image != NULL) {
915 		addr_t symbolDelta;
916 		uint32 i;
917 		int32 j;
918 
919 		TRACE((" image %p, base = %p, size = %p\n", image,
920 			(void *)image->text_region.start, (void *)image->text_region.size));
921 
922 		if (image->debug_symbols != NULL) {
923 			// search extended debug symbol table (contains static symbols)
924 
925 			TRACE((" searching debug symbols...\n"));
926 
927 			for (i = 0; i < image->num_debug_symbols; i++) {
928 				struct Elf32_Sym *symbol = &image->debug_symbols[i];
929 
930 				if (symbol->st_value == 0
931 					|| symbol->st_size >= image->text_region.size + image->data_region.size)
932 					continue;
933 
934 				symbolDelta = address - (symbol->st_value + image->text_region.delta);
935 				if (symbolDelta >= 0 && symbolDelta < symbol->st_size)
936 					exactMatch = true;
937 
938 				if (exactMatch || symbolDelta < deltaFound) {
939 					deltaFound = symbolDelta;
940 					symbolFound = symbol;
941 					symbolName = image->debug_string_table + symbol->st_name;
942 
943 					if (exactMatch)
944 						break;
945 				}
946 			}
947 		} else {
948 			// search standard symbol lookup table
949 
950 			TRACE((" searching standard symbols...\n"));
951 
952 			for (i = 0; i < HASHTABSIZE(image); i++) {
953 				for (j = HASHBUCKETS(image)[i]; j != STN_UNDEF; j = HASHCHAINS(image)[j]) {
954 					struct Elf32_Sym *symbol = &image->syms[j];
955 
956 					if (symbol->st_value == 0
957 						|| symbol->st_size >= image->text_region.size + image->data_region.size)
958 						continue;
959 
960 					symbolDelta = address - (long)(symbol->st_value + image->text_region.delta);
961 					if (symbolDelta >= 0 && symbolDelta < symbol->st_size)
962 						exactMatch = true;
963 
964 					if (exactMatch || symbolDelta < deltaFound) {
965 						deltaFound = symbolDelta;
966 						symbolFound = symbol;
967 						symbolName = SYMNAME(image, symbol);
968 
969 						if (exactMatch)
970 							goto symbol_found;
971 					}
972 				}
973 			}
974 		}
975 	}
976 symbol_found:
977 
978 	if (symbolFound != NULL) {
979 		if (_symbolName)
980 			*_symbolName = symbolName;
981 		if (_imageName)
982 			*_imageName = image->name;
983 		if (_baseAddress)
984 			*_baseAddress = symbolFound->st_value + image->text_region.delta;
985 		if (_exactMatch)
986 			*_exactMatch = exactMatch;
987 
988 		status = B_OK;
989 	} else if (image != NULL) {
990 		TRACE(("symbol not found!\n"));
991 
992 		if (_symbolName)
993 			*_symbolName = NULL;
994 		if (_imageName)
995 			*_imageName = image->name;
996 		if (_baseAddress)
997 			*_baseAddress = image->text_region.start;
998 		if (_exactMatch)
999 			*_exactMatch = false;
1000 
1001 		status = B_OK;
1002 	} else {
1003 		TRACE(("image not found!\n"));
1004 		status = B_ENTRY_NOT_FOUND;
1005 	}
1006 
1007 	// Note, theoretically, all information we return back to our caller
1008 	// would have to be locked - but since this function is only called
1009 	// from the debugger, it's safe to do it this way
1010 
1011 	//mutex_unlock(&sImageMutex);
1012 
1013 	return status;
1014 }
1015 
1016 
1017 status_t
1018 elf_load_user_image(const char *path, struct team *team, int flags, addr_t *entry)
1019 {
1020 	struct Elf32_Ehdr elfHeader;
1021 	struct Elf32_Phdr *programHeaders = NULL;
1022 	char baseName[B_OS_NAME_LENGTH];
1023 	status_t status;
1024 	ssize_t length;
1025 	int fd;
1026 	int i;
1027 
1028 	TRACE(("elf_load: entry path '%s', team %p\n", path, team));
1029 
1030 	fd = _kern_open(-1, path, O_RDONLY, 0);
1031 	if (fd < 0)
1032 		return fd;
1033 
1034 	// read and verify the ELF header
1035 
1036 	length = _kern_read(fd, 0, &elfHeader, sizeof(elfHeader));
1037 	if (length < B_OK) {
1038 		status = length;
1039 		goto error;
1040 	}
1041 
1042 	if (length != sizeof(elfHeader)) {
1043 		// short read
1044 		status = B_NOT_AN_EXECUTABLE;
1045 		goto error;
1046 	}
1047 	status = verify_eheader(&elfHeader);
1048 	if (status < B_OK)
1049 		goto error;
1050 
1051 	// read program header
1052 
1053 	programHeaders = (struct Elf32_Phdr *)malloc(elfHeader.e_phnum * elfHeader.e_phentsize);
1054 	if (programHeaders == NULL) {
1055 		dprintf("error allocating space for program headers\n");
1056 		status = B_NO_MEMORY;
1057 		goto error;
1058 	}
1059 
1060 	TRACE(("reading in program headers at 0x%lx, length 0x%x\n", elfHeader.e_phoff, elfHeader.e_phnum * elfHeader.e_phentsize));
1061 	length = _kern_read(fd, elfHeader.e_phoff, programHeaders, elfHeader.e_phnum * elfHeader.e_phentsize);
1062 	if (length < B_OK) {
1063 		status = length;
1064 		dprintf("error reading in program headers\n");
1065 		goto error;
1066 	}
1067 	if (length != elfHeader.e_phnum * elfHeader.e_phentsize) {
1068 		dprintf("short read while reading in program headers\n");
1069 		status = -1;
1070 		goto error;
1071 	}
1072 
1073 	// construct a nice name for the region we have to create below
1074 	{
1075 		int32 length;
1076 
1077 		const char *leaf = strrchr(path, '/');
1078 		if (leaf == NULL)
1079 			leaf = path;
1080 		else
1081 			leaf++;
1082 
1083 		length = strlen(leaf);
1084 		if (length > B_OS_NAME_LENGTH - 8)
1085 			sprintf(baseName, "...%s", leaf + length + 8 - B_OS_NAME_LENGTH);
1086 		else
1087 			strcpy(baseName, leaf);
1088 	}
1089 
1090 	// map the program's segments into memory
1091 
1092 	for (i = 0; i < elfHeader.e_phnum; i++) {
1093 		char regionName[B_OS_NAME_LENGTH];
1094 		char *regionAddress;
1095 		area_id id;
1096 
1097 		if (programHeaders[i].p_type != PT_LOAD)
1098 			continue;
1099 
1100 		regionAddress = (char *)ROUNDOWN(programHeaders[i].p_vaddr, B_PAGE_SIZE);
1101 		if (programHeaders[i].p_flags & PF_WRITE) {
1102 			/*
1103 			 * rw/data segment
1104 			 */
1105 			uint32 memUpperBound = (programHeaders[i].p_vaddr % B_PAGE_SIZE) + programHeaders[i].p_memsz;
1106 			uint32 fileUpperBound = (programHeaders[i].p_vaddr % B_PAGE_SIZE) + programHeaders[i].p_filesz;
1107 
1108 			memUpperBound = ROUNDUP(memUpperBound, B_PAGE_SIZE);
1109 			fileUpperBound = ROUNDUP(fileUpperBound, B_PAGE_SIZE);
1110 
1111 			sprintf(regionName, "%s_seg%drw", baseName, i);
1112 
1113 			id = vm_map_file(team->id, regionName,
1114 				(void **)&regionAddress,
1115 				B_EXACT_ADDRESS,
1116 				fileUpperBound,
1117 				B_READ_AREA | B_WRITE_AREA, REGION_PRIVATE_MAP,
1118 				path, ROUNDOWN(programHeaders[i].p_offset, B_PAGE_SIZE));
1119 			if (id < B_OK) {
1120 				dprintf("error mapping file data: %s!\n", strerror(id));
1121 				status = B_NOT_AN_EXECUTABLE;
1122 				goto error;
1123 			}
1124 
1125 			// clean garbage brought by mmap (the region behind the file,
1126 			// at least parts of it are the bss and have to be zeroed)
1127 			{
1128 				uint32 start = (uint32)regionAddress
1129 					+ (programHeaders[i].p_vaddr % B_PAGE_SIZE)
1130 					+ programHeaders[i].p_filesz;
1131 				uint32 amount = fileUpperBound
1132 					- (programHeaders[i].p_vaddr % B_PAGE_SIZE)
1133 					- (programHeaders[i].p_filesz);
1134 				memset((void *)start, 0, amount);
1135 			}
1136 
1137 			// Check if we need extra storage for the bss - we have to do this if
1138 			// the above region doesn't already comprise the memory size, too.
1139 
1140 			if (memUpperBound != fileUpperBound) {
1141 				size_t bss_size = memUpperBound - fileUpperBound;
1142 
1143 				snprintf(regionName, B_OS_NAME_LENGTH, "%s_bss%d", baseName, i);
1144 
1145 				regionAddress += fileUpperBound;
1146 				id = create_area_etc(team, regionName, (void **)&regionAddress,
1147 					B_EXACT_ADDRESS, bss_size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
1148 				if (id < B_OK) {
1149 					dprintf("error allocating bss area: %s!\n", strerror(id));
1150 					status = B_NOT_AN_EXECUTABLE;
1151 					goto error;
1152 				}
1153 			}
1154 		} else {
1155 			/*
1156 			 * assume ro/text segment
1157 			 */
1158 			snprintf(regionName, B_OS_NAME_LENGTH, "%s_seg%dro", baseName, i);
1159 
1160 			id = vm_map_file(team->id, regionName,
1161 				(void **)&regionAddress,
1162 				B_EXACT_ADDRESS,
1163 				ROUNDUP(programHeaders[i].p_memsz + (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE),
1164 				B_READ_AREA | B_EXECUTE_AREA, REGION_PRIVATE_MAP,
1165 				path, ROUNDOWN(programHeaders[i].p_offset, B_PAGE_SIZE));
1166 			if (id < B_OK) {
1167 				dprintf("error mapping file text: %s!\n", strerror(id));
1168 				status = B_NOT_AN_EXECUTABLE;
1169 				goto error;
1170 			}
1171 		}
1172 	}
1173 
1174 	TRACE(("elf_load: done!\n"));
1175 
1176 	*entry = elfHeader.e_entry;
1177 
1178 	status = B_OK;
1179 
1180 error:
1181 	if (programHeaders)
1182 		free(programHeaders);
1183 	_kern_close(fd);
1184 
1185 	return status;
1186 }
1187 
1188 
1189 image_id
1190 load_kernel_add_on(const char *path)
1191 {
1192 	struct Elf32_Phdr *programHeaders;
1193 	struct Elf32_Ehdr *elfHeader;
1194 	struct elf_image_info *image;
1195 	const char *fileName;
1196 	void *reservedAddress;
1197 	addr_t start;
1198 	size_t reservedSize;
1199 	status_t status;
1200 	ssize_t length;
1201 
1202 	TRACE(("elf_load_kspace: entry path '%s'\n", path));
1203 
1204 	int fd = _kern_open(-1, path, O_RDONLY, 0);
1205 	if (fd < 0)
1206 		return fd;
1207 
1208 	struct vnode *vnode;
1209 	status = vfs_get_vnode_from_fd(fd, true, &vnode);
1210 	if (status < B_OK)
1211 		goto error0;
1212 
1213 	// get the file name
1214 	fileName = strrchr(path, '/');
1215 	if (fileName == NULL)
1216 		fileName = path;
1217 	else
1218 		fileName++;
1219 
1220 	// Prevent someone else from trying to load this image
1221 	mutex_lock(&sImageLoadMutex);
1222 
1223 	// make sure it's not loaded already. Search by vnode
1224 	image = find_image_by_vnode(vnode);
1225 	if (image) {
1226 		atomic_add(&image->ref_count, 1);
1227 		goto done;
1228 	}
1229 
1230 	elfHeader = (struct Elf32_Ehdr *)malloc(sizeof(*elfHeader));
1231 	if (!elfHeader) {
1232 		status = B_NO_MEMORY;
1233 		goto error;
1234 	}
1235 
1236 	length = _kern_read(fd, 0, elfHeader, sizeof(*elfHeader));
1237 	if (length < B_OK) {
1238 		status = length;
1239 		goto error1;
1240 	}
1241 	if (length != sizeof(*elfHeader)) {
1242 		// short read
1243 		status = B_NOT_AN_EXECUTABLE;
1244 		goto error1;
1245 	}
1246 	status = verify_eheader(elfHeader);
1247 	if (status < B_OK)
1248 		goto error1;
1249 
1250 	image = create_image_struct();
1251 	if (!image) {
1252 		status = B_NO_MEMORY;
1253 		goto error1;
1254 	}
1255 	image->vnode = vnode;
1256 	image->elf_header = elfHeader;
1257 	image->name = strdup(path);
1258 
1259 	programHeaders = (struct Elf32_Phdr *)malloc(elfHeader->e_phnum * elfHeader->e_phentsize);
1260 	if (programHeaders == NULL) {
1261 		dprintf("%s: error allocating space for program headers\n", fileName);
1262 		status = B_NO_MEMORY;
1263 		goto error2;
1264 	}
1265 
1266 	TRACE(("reading in program headers at 0x%lx, length 0x%x\n", elfHeader->e_phoff, elfHeader->e_phnum * elfHeader->e_phentsize));
1267 	length = _kern_read(fd, elfHeader->e_phoff, programHeaders, elfHeader->e_phnum * elfHeader->e_phentsize);
1268 	if (length < B_OK) {
1269 		status = length;
1270 		TRACE(("%s: error reading in program headers\n", fileName));
1271 		goto error3;
1272 	}
1273 	if (length != elfHeader->e_phnum * elfHeader->e_phentsize) {
1274 		TRACE(("%s: short read while reading in program headers\n", fileName));
1275 		status = B_ERROR;
1276 		goto error3;
1277 	}
1278 
1279 	// determine how much space we need for all loaded segments
1280 
1281 	reservedSize = 0;
1282 	length = 0;
1283 
1284 	for (int32 i = 0; i < elfHeader->e_phnum; i++) {
1285 		size_t end;
1286 
1287 		if (programHeaders[i].p_type != PT_LOAD)
1288 			continue;
1289 
1290 		length += ROUNDUP(programHeaders[i].p_memsz + (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE);
1291 
1292 		end = ROUNDUP(programHeaders[i].p_memsz + programHeaders[i].p_vaddr, B_PAGE_SIZE);
1293 		if (end > reservedSize)
1294 			reservedSize = end;
1295 	}
1296 
1297 	// Check whether the segments have an unreasonable amount of unused space
1298 	// inbetween.
1299 	if ((ssize_t)reservedSize > length + 8 * 1024) {
1300 		status = B_BAD_DATA;
1301 		goto error1;
1302 	}
1303 
1304 	// reserve that space and allocate the areas from that one
1305 	if (vm_reserve_address_range(vm_kernel_address_space_id(), &reservedAddress,
1306 			B_ANY_KERNEL_ADDRESS, reservedSize, 0) < B_OK)
1307 		goto error3;
1308 
1309 	start = (addr_t)reservedAddress;
1310 	image->data_region.size = 0;
1311 	image->text_region.size = 0;
1312 
1313 	for (int32 i = 0; i < elfHeader->e_phnum; i++) {
1314 		char regionName[B_OS_NAME_LENGTH];
1315 		elf_region *region;
1316 
1317 		TRACE(("looking at program header %d\n", i));
1318 
1319 		switch (programHeaders[i].p_type) {
1320 			case PT_LOAD:
1321 				break;
1322 			case PT_DYNAMIC:
1323 				image->dynamic_section = programHeaders[i].p_vaddr;
1324 				continue;
1325 			default:
1326 				dprintf("%s: unhandled pheader type 0x%lx\n", fileName, programHeaders[i].p_type);
1327 				continue;
1328 		}
1329 
1330 		// we're here, so it must be a PT_LOAD segment
1331 		if (programHeaders[i].IsReadWrite()) {
1332 			// this is the writable segment
1333 			if (image->data_region.size != 0) {
1334 				// we've already created this segment
1335 				continue;
1336 			}
1337 			region = &image->data_region;
1338 
1339 			snprintf(regionName, B_OS_NAME_LENGTH, "%s_data", fileName);
1340 		} else if (programHeaders[i].IsExecutable()) {
1341 			// this is the non-writable segment
1342 			if (image->text_region.size != 0) {
1343 				// we've already created this segment
1344 				continue;
1345 			}
1346 			region = &image->text_region;
1347 
1348 			snprintf(regionName, B_OS_NAME_LENGTH, "%s_text", fileName);
1349 		} else {
1350 			dprintf("%s: weird program header flags 0x%lx\n", fileName,
1351 				programHeaders[i].p_flags);
1352 			continue;
1353 		}
1354 
1355 		region->start = (addr_t)reservedAddress + ROUNDOWN(programHeaders[i].p_vaddr, B_PAGE_SIZE);
1356 		region->size = ROUNDUP(programHeaders[i].p_memsz
1357 			+ (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE);
1358 		region->id = create_area(regionName, (void **)&region->start, B_EXACT_ADDRESS,
1359 			region->size, B_FULL_LOCK, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
1360 		if (region->id < B_OK) {
1361 			dprintf("%s: error allocating area: %s\n", fileName, strerror(region->id));
1362 			status = B_NOT_AN_EXECUTABLE;
1363 			goto error4;
1364 		}
1365 		region->delta = -ROUNDOWN(programHeaders[i].p_vaddr, B_PAGE_SIZE);
1366 
1367 		TRACE(("elf_load_kspace: created area \"%s\" at %p\n",
1368 			regionName, (void *)region->start));
1369 
1370 		length = _kern_read(fd, programHeaders[i].p_offset,
1371 			(void *)(region->start + (programHeaders[i].p_vaddr % B_PAGE_SIZE)),
1372 			programHeaders[i].p_filesz);
1373 		if (length < B_OK) {
1374 			status = length;
1375 			dprintf("%s: error reading in segment %ld\n", fileName, i);
1376 			goto error5;
1377 		}
1378 	}
1379 
1380 	// get the segment order
1381 	elf_region *firstRegion;
1382 	elf_region *secondRegion;
1383 	if (image->text_region.start < image->data_region.start) {
1384 		firstRegion = &image->text_region;
1385 		secondRegion = &image->data_region;
1386 	} else {
1387 		firstRegion = &image->data_region;
1388 		secondRegion = &image->text_region;
1389 	}
1390 
1391 	image->data_region.delta += image->data_region.start;
1392 	image->text_region.delta += image->text_region.start;
1393 
1394 	// modify the dynamic ptr by the delta of the regions
1395 	image->dynamic_section += image->text_region.delta;
1396 
1397 	status = elf_parse_dynamic_section(image);
1398 	if (status < B_OK)
1399 		goto error5;
1400 
1401 	status = elf_relocate(image, "");
1402 	if (status < B_OK)
1403 		goto error5;
1404 
1405 	// We needed to read in the contents of the "text" area, but
1406 	// now we can protect it read-only/execute
1407 	set_area_protection(image->text_region.id, B_KERNEL_READ_AREA | B_KERNEL_EXECUTE_AREA);
1408 
1409 	// There might be a hole between the two segments, and we don't need to
1410 	// reserve this any longer
1411 	vm_unreserve_address_range(vm_kernel_address_space_id(), reservedAddress, reservedSize);
1412 
1413 	// ToDo: this should be enabled by kernel settings!
1414 	if (1)
1415 		load_elf_symbol_table(fd, image);
1416 
1417 	free(programHeaders);
1418 	register_elf_image(image);
1419 
1420 done:
1421 	_kern_close(fd);
1422 	mutex_unlock(&sImageLoadMutex);
1423 
1424 	return image->id;
1425 
1426 error5:
1427 	delete_area(image->data_region.id);
1428 	delete_area(image->text_region.id);
1429 error4:
1430 	vm_unreserve_address_range(vm_kernel_address_space_id(), reservedAddress, reservedSize);
1431 error3:
1432 	free(programHeaders);
1433 error2:
1434 	free(image);
1435 error1:
1436 	free(elfHeader);
1437 error:
1438 	mutex_unlock(&sImageLoadMutex);
1439 error0:
1440 	if (vnode)
1441 		vfs_put_vnode(vnode);
1442 	_kern_close(fd);
1443 
1444 	return status;
1445 }
1446 
1447 
1448 status_t
1449 unload_kernel_add_on(image_id id)
1450 {
1451 	struct elf_image_info *image;
1452 	status_t status;
1453 
1454 	mutex_lock(&sImageLoadMutex);
1455 	mutex_lock(&sImageMutex);
1456 
1457 	image = find_image(id);
1458 	if (image != NULL)
1459 		status = unload_elf_image(image);
1460 	else
1461 		status = B_BAD_IMAGE_ID;
1462 
1463 	mutex_unlock(&sImageMutex);
1464 	mutex_unlock(&sImageLoadMutex);
1465 
1466 	return status;
1467 }
1468 
1469 
1470 status_t
1471 elf_init(kernel_args *args)
1472 {
1473 	struct preloaded_image *image;
1474 
1475 	image_init();
1476 
1477 	mutex_init(&sImageMutex, "kimages_lock");
1478 	mutex_init(&sImageLoadMutex, "kimages_load_lock");
1479 
1480 	sImagesHash = hash_init(IMAGE_HASH_SIZE, 0, image_compare, image_hash);
1481 	if (sImagesHash == NULL)
1482 		return B_NO_MEMORY;
1483 
1484 	// Build a image structure for the kernel, which has already been loaded.
1485 	// The preloaded_images were already prepared by the VM.
1486 	if (insert_preloaded_image(&args->kernel_image, true) < B_OK)
1487 		panic("could not create kernel image.\n");
1488 
1489 	// Build image structures for all preloaded images.
1490 	for (image = args->preloaded_images; image != NULL; image = image->next) {
1491 		insert_preloaded_image(image, false);
1492 	}
1493 
1494 	add_debugger_command("ls", &dump_address_info, "lookup symbol for a particular address");
1495 	add_debugger_command("symbols", &dump_symbols, "dump symbols for image");
1496 	add_debugger_command("image", &dump_image, "dump image info");
1497 
1498 	sInitialized = true;
1499 	return B_OK;
1500 }
1501 
1502