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