xref: /haiku/src/system/kernel/elf.cpp (revision f23596149e0d173463f70629581aa10cc305d32e)
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 	// we now no longer need to write to the text area anymore
824 	set_area_protection(image->text_region.id,
825 		B_KERNEL_READ_AREA | B_KERNEL_EXECUTE_AREA);
826 
827 	return B_OK;
828 
829 error1:
830 	free(image);
831 
832 	// clean up preloaded image resources (this image won't be used anymore)
833 	delete_area(preloadedImage->text_region.id);
834 	delete_area(preloadedImage->data_region.id);
835 	preloadedImage->id = -1;
836 
837 	return status;
838 }
839 
840 
841 //	#pragma mark -
842 //	public kernel API
843 
844 
845 status_t
846 get_image_symbol(image_id id, const char *name, int32 sclass, void **_symbol)
847 {
848 	struct elf_image_info *image;
849 	struct Elf32_Sym *symbol;
850 	status_t status = B_OK;
851 
852 	TRACE(("get_image_symbol(%s)\n", name));
853 
854 	mutex_lock(&sImageMutex);
855 
856 	image = find_image(id);
857 	if (image == NULL) {
858 		status = B_BAD_IMAGE_ID;
859 		goto done;
860 	}
861 
862 	symbol = elf_find_symbol(image, name);
863 	if (symbol == NULL || symbol->st_shndx == SHN_UNDEF) {
864 		status = B_ENTRY_NOT_FOUND;
865 		goto done;
866 	}
867 
868 	// ToDo: support the "sclass" parameter!
869 
870 	TRACE(("found: %lx (%lx + %lx)\n", symbol->st_value + image->text_region.delta,
871 		symbol->st_value, image->text_region.delta));
872 
873 	*_symbol = (void *)(symbol->st_value + image->text_region.delta);
874 
875 done:
876 	mutex_unlock(&sImageMutex);
877 	return status;
878 }
879 
880 
881 //	#pragma mark -
882 //	kernel private API
883 
884 
885 /**	Looks up a symbol by address in all images loaded in kernel space.
886  *	Note, if you need to call this function outside a debugger, make
887  *	sure you fix locking and the way it returns its information, first!
888  */
889 
890 status_t
891 elf_debug_lookup_symbol_address(addr_t address, addr_t *_baseAddress,
892 	const char **_symbolName, const char **_imageName, bool *_exactMatch)
893 {
894 	struct elf_image_info *image;
895 	struct Elf32_Sym *symbolFound = NULL;
896 	const char *symbolName = NULL;
897 	addr_t deltaFound = INT_MAX;
898 	bool exactMatch = false;
899 	status_t status;
900 
901 	TRACE(("looking up %p\n", (void *)address));
902 
903 	if (!sInitialized)
904 		return B_ERROR;
905 
906 	//mutex_lock(&sImageMutex);
907 
908 	image = find_image_at_address(address);
909 		// get image that may contain the address
910 
911 	if (image != NULL) {
912 		addr_t symbolDelta;
913 		uint32 i;
914 		int32 j;
915 
916 		TRACE((" image %p, base = %p, size = %p\n", image,
917 			(void *)image->text_region.start, (void *)image->text_region.size));
918 
919 		if (image->debug_symbols != NULL) {
920 			// search extended debug symbol table (contains static symbols)
921 
922 			TRACE((" searching debug symbols...\n"));
923 
924 			for (i = 0; i < image->num_debug_symbols; i++) {
925 				struct Elf32_Sym *symbol = &image->debug_symbols[i];
926 
927 				if (symbol->st_value == 0
928 					|| symbol->st_size >= image->text_region.size + image->data_region.size)
929 					continue;
930 
931 				symbolDelta = address - (symbol->st_value + image->text_region.delta);
932 				if (symbolDelta >= 0 && symbolDelta < symbol->st_size)
933 					exactMatch = true;
934 
935 				if (exactMatch || symbolDelta < deltaFound) {
936 					deltaFound = symbolDelta;
937 					symbolFound = symbol;
938 					symbolName = image->debug_string_table + symbol->st_name;
939 
940 					if (exactMatch)
941 						break;
942 				}
943 			}
944 		} else {
945 			// search standard symbol lookup table
946 
947 			TRACE((" searching standard symbols...\n"));
948 
949 			for (i = 0; i < HASHTABSIZE(image); i++) {
950 				for (j = HASHBUCKETS(image)[i]; j != STN_UNDEF; j = HASHCHAINS(image)[j]) {
951 					struct Elf32_Sym *symbol = &image->syms[j];
952 
953 					if (symbol->st_value == 0
954 						|| symbol->st_size >= image->text_region.size + image->data_region.size)
955 						continue;
956 
957 					symbolDelta = address - (long)(symbol->st_value + image->text_region.delta);
958 					if (symbolDelta >= 0 && symbolDelta < symbol->st_size)
959 						exactMatch = true;
960 
961 					if (exactMatch || symbolDelta < deltaFound) {
962 						deltaFound = symbolDelta;
963 						symbolFound = symbol;
964 						symbolName = SYMNAME(image, symbol);
965 
966 						if (exactMatch)
967 							goto symbol_found;
968 					}
969 				}
970 			}
971 		}
972 	}
973 symbol_found:
974 
975 	if (symbolFound != NULL) {
976 		if (_symbolName)
977 			*_symbolName = symbolName;
978 		if (_imageName)
979 			*_imageName = image->name;
980 		if (_baseAddress)
981 			*_baseAddress = symbolFound->st_value + image->text_region.delta;
982 		if (_exactMatch)
983 			*_exactMatch = exactMatch;
984 
985 		status = B_OK;
986 	} else if (image != NULL) {
987 		TRACE(("symbol not found!\n"));
988 
989 		if (_symbolName)
990 			*_symbolName = NULL;
991 		if (_imageName)
992 			*_imageName = image->name;
993 		if (_baseAddress)
994 			*_baseAddress = image->text_region.start;
995 		if (_exactMatch)
996 			*_exactMatch = false;
997 
998 		status = B_OK;
999 	} else {
1000 		TRACE(("image not found!\n"));
1001 		status = B_ENTRY_NOT_FOUND;
1002 	}
1003 
1004 	// Note, theoretically, all information we return back to our caller
1005 	// would have to be locked - but since this function is only called
1006 	// from the debugger, it's safe to do it this way
1007 
1008 	//mutex_unlock(&sImageMutex);
1009 
1010 	return status;
1011 }
1012 
1013 
1014 status_t
1015 elf_load_user_image(const char *path, struct team *team, int flags, addr_t *entry)
1016 {
1017 	struct Elf32_Ehdr elfHeader;
1018 	struct Elf32_Phdr *programHeaders = NULL;
1019 	char baseName[B_OS_NAME_LENGTH];
1020 	status_t status;
1021 	ssize_t length;
1022 	int fd;
1023 	int i;
1024 
1025 	TRACE(("elf_load: entry path '%s', team %p\n", path, team));
1026 
1027 	fd = _kern_open(-1, path, O_RDONLY, 0);
1028 	if (fd < 0)
1029 		return fd;
1030 
1031 	// read and verify the ELF header
1032 
1033 	length = _kern_read(fd, 0, &elfHeader, sizeof(elfHeader));
1034 	if (length < B_OK) {
1035 		status = length;
1036 		goto error;
1037 	}
1038 
1039 	if (length != sizeof(elfHeader)) {
1040 		// short read
1041 		status = B_NOT_AN_EXECUTABLE;
1042 		goto error;
1043 	}
1044 	status = verify_eheader(&elfHeader);
1045 	if (status < B_OK)
1046 		goto error;
1047 
1048 	// read program header
1049 
1050 	programHeaders = (struct Elf32_Phdr *)malloc(elfHeader.e_phnum * elfHeader.e_phentsize);
1051 	if (programHeaders == NULL) {
1052 		dprintf("error allocating space for program headers\n");
1053 		status = B_NO_MEMORY;
1054 		goto error;
1055 	}
1056 
1057 	TRACE(("reading in program headers at 0x%lx, length 0x%x\n", elfHeader.e_phoff, elfHeader.e_phnum * elfHeader.e_phentsize));
1058 	length = _kern_read(fd, elfHeader.e_phoff, programHeaders, elfHeader.e_phnum * elfHeader.e_phentsize);
1059 	if (length < B_OK) {
1060 		status = length;
1061 		dprintf("error reading in program headers\n");
1062 		goto error;
1063 	}
1064 	if (length != elfHeader.e_phnum * elfHeader.e_phentsize) {
1065 		dprintf("short read while reading in program headers\n");
1066 		status = -1;
1067 		goto error;
1068 	}
1069 
1070 	// construct a nice name for the region we have to create below
1071 	{
1072 		int32 length;
1073 
1074 		const char *leaf = strrchr(path, '/');
1075 		if (leaf == NULL)
1076 			leaf = path;
1077 		else
1078 			leaf++;
1079 
1080 		length = strlen(leaf);
1081 		if (length > B_OS_NAME_LENGTH - 8)
1082 			sprintf(baseName, "...%s", leaf + length + 8 - B_OS_NAME_LENGTH);
1083 		else
1084 			strcpy(baseName, leaf);
1085 	}
1086 
1087 	// map the program's segments into memory
1088 
1089 	for (i = 0; i < elfHeader.e_phnum; i++) {
1090 		char regionName[B_OS_NAME_LENGTH];
1091 		char *regionAddress;
1092 		area_id id;
1093 
1094 		if (programHeaders[i].p_type != PT_LOAD)
1095 			continue;
1096 
1097 		regionAddress = (char *)ROUNDOWN(programHeaders[i].p_vaddr, B_PAGE_SIZE);
1098 		if (programHeaders[i].p_flags & PF_WRITE) {
1099 			/*
1100 			 * rw/data segment
1101 			 */
1102 			uint32 memUpperBound = (programHeaders[i].p_vaddr % B_PAGE_SIZE) + programHeaders[i].p_memsz;
1103 			uint32 fileUpperBound = (programHeaders[i].p_vaddr % B_PAGE_SIZE) + programHeaders[i].p_filesz;
1104 
1105 			memUpperBound = ROUNDUP(memUpperBound, B_PAGE_SIZE);
1106 			fileUpperBound = ROUNDUP(fileUpperBound, B_PAGE_SIZE);
1107 
1108 			sprintf(regionName, "%s_seg%drw", baseName, i);
1109 
1110 			id = vm_map_file(team->id, regionName,
1111 				(void **)&regionAddress,
1112 				B_EXACT_ADDRESS,
1113 				fileUpperBound,
1114 				B_READ_AREA | B_WRITE_AREA, REGION_PRIVATE_MAP,
1115 				path, ROUNDOWN(programHeaders[i].p_offset, B_PAGE_SIZE));
1116 			if (id < B_OK) {
1117 				dprintf("error mapping file data: %s!\n", strerror(id));
1118 				status = B_NOT_AN_EXECUTABLE;
1119 				goto error;
1120 			}
1121 
1122 			// clean garbage brought by mmap (the region behind the file,
1123 			// at least parts of it are the bss and have to be zeroed)
1124 			{
1125 				uint32 start = (uint32)regionAddress
1126 					+ (programHeaders[i].p_vaddr % B_PAGE_SIZE)
1127 					+ programHeaders[i].p_filesz;
1128 				uint32 amount = fileUpperBound
1129 					- (programHeaders[i].p_vaddr % B_PAGE_SIZE)
1130 					- (programHeaders[i].p_filesz);
1131 				memset((void *)start, 0, amount);
1132 			}
1133 
1134 			// Check if we need extra storage for the bss - we have to do this if
1135 			// the above region doesn't already comprise the memory size, too.
1136 
1137 			if (memUpperBound != fileUpperBound) {
1138 				size_t bss_size = memUpperBound - fileUpperBound;
1139 
1140 				snprintf(regionName, B_OS_NAME_LENGTH, "%s_bss%d", baseName, i);
1141 
1142 				regionAddress += fileUpperBound;
1143 				id = create_area_etc(team, regionName, (void **)&regionAddress,
1144 					B_EXACT_ADDRESS, bss_size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
1145 				if (id < B_OK) {
1146 					dprintf("error allocating bss area: %s!\n", strerror(id));
1147 					status = B_NOT_AN_EXECUTABLE;
1148 					goto error;
1149 				}
1150 			}
1151 		} else {
1152 			/*
1153 			 * assume ro/text segment
1154 			 */
1155 			snprintf(regionName, B_OS_NAME_LENGTH, "%s_seg%dro", baseName, i);
1156 
1157 			id = vm_map_file(team->id, regionName,
1158 				(void **)&regionAddress,
1159 				B_EXACT_ADDRESS,
1160 				ROUNDUP(programHeaders[i].p_memsz + (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE),
1161 				B_READ_AREA | B_EXECUTE_AREA, REGION_PRIVATE_MAP,
1162 				path, ROUNDOWN(programHeaders[i].p_offset, B_PAGE_SIZE));
1163 			if (id < B_OK) {
1164 				dprintf("error mapping file text: %s!\n", strerror(id));
1165 				status = B_NOT_AN_EXECUTABLE;
1166 				goto error;
1167 			}
1168 		}
1169 	}
1170 
1171 	TRACE(("elf_load: done!\n"));
1172 
1173 	*entry = elfHeader.e_entry;
1174 
1175 	status = B_OK;
1176 
1177 error:
1178 	if (programHeaders)
1179 		free(programHeaders);
1180 	_kern_close(fd);
1181 
1182 	return status;
1183 }
1184 
1185 
1186 image_id
1187 load_kernel_add_on(const char *path)
1188 {
1189 	struct Elf32_Phdr *programHeaders;
1190 	struct Elf32_Ehdr *elfHeader;
1191 	struct elf_image_info *image;
1192 	const char *fileName;
1193 	void *vnode = NULL;
1194 	void *reservedAddress;
1195 	addr_t start;
1196 	size_t reservedSize;
1197 	status_t status;
1198 	int fd;
1199 	ssize_t length;
1200 
1201 	TRACE(("elf_load_kspace: entry path '%s'\n", path));
1202 
1203 	fd = _kern_open(-1, path, O_RDONLY, 0);
1204 	if (fd < 0)
1205 		return fd;
1206 
1207 	status = vfs_get_vnode_from_fd(fd, true, &vnode);
1208 	if (status < B_OK)
1209 		goto error0;
1210 
1211 	// get the file name
1212 	fileName = strrchr(path, '/');
1213 	if (fileName == NULL)
1214 		fileName = path;
1215 	else
1216 		fileName++;
1217 
1218 	// Prevent someone else from trying to load this image
1219 	mutex_lock(&sImageLoadMutex);
1220 
1221 	// make sure it's not loaded already. Search by vnode
1222 	image = find_image_by_vnode(vnode);
1223 	if (image) {
1224 		atomic_add(&image->ref_count, 1);
1225 		goto done;
1226 	}
1227 
1228 	elfHeader = (struct Elf32_Ehdr *)malloc(sizeof(*elfHeader));
1229 	if (!elfHeader) {
1230 		status = B_NO_MEMORY;
1231 		goto error;
1232 	}
1233 
1234 	length = _kern_read(fd, 0, elfHeader, sizeof(*elfHeader));
1235 	if (length < B_OK) {
1236 		status = length;
1237 		goto error1;
1238 	}
1239 	if (length != sizeof(*elfHeader)) {
1240 		// short read
1241 		status = B_NOT_AN_EXECUTABLE;
1242 		goto error1;
1243 	}
1244 	status = verify_eheader(elfHeader);
1245 	if (status < B_OK)
1246 		goto error1;
1247 
1248 	image = create_image_struct();
1249 	if (!image) {
1250 		status = B_NO_MEMORY;
1251 		goto error1;
1252 	}
1253 	image->vnode = vnode;
1254 	image->elf_header = elfHeader;
1255 	image->name = strdup(path);
1256 
1257 	programHeaders = (struct Elf32_Phdr *)malloc(elfHeader->e_phnum * elfHeader->e_phentsize);
1258 	if (programHeaders == NULL) {
1259 		dprintf("%s: error allocating space for program headers\n", fileName);
1260 		status = B_NO_MEMORY;
1261 		goto error2;
1262 	}
1263 
1264 	TRACE(("reading in program headers at 0x%lx, length 0x%x\n", elfHeader->e_phoff, elfHeader->e_phnum * elfHeader->e_phentsize));
1265 	length = _kern_read(fd, elfHeader->e_phoff, programHeaders, elfHeader->e_phnum * elfHeader->e_phentsize);
1266 	if (length < B_OK) {
1267 		status = length;
1268 		TRACE(("%s: error reading in program headers\n", fileName));
1269 		goto error3;
1270 	}
1271 	if (length != elfHeader->e_phnum * elfHeader->e_phentsize) {
1272 		TRACE(("%s: short read while reading in program headers\n", fileName));
1273 		status = B_ERROR;
1274 		goto error3;
1275 	}
1276 
1277 	// determine how much space we need for all loaded segments
1278 
1279 	reservedSize = 0;
1280 	length = 0;
1281 
1282 	for (int32 i = 0; i < elfHeader->e_phnum; i++) {
1283 		size_t end;
1284 
1285 		if (programHeaders[i].p_type != PT_LOAD)
1286 			continue;
1287 
1288 		length += ROUNDUP(programHeaders[i].p_memsz + (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE);
1289 
1290 		end = ROUNDUP(programHeaders[i].p_memsz + programHeaders[i].p_vaddr, B_PAGE_SIZE);
1291 		if (end > reservedSize)
1292 			reservedSize = end;
1293 	}
1294 
1295 	// Check whether the segments have an unreasonable amount of unused space
1296 	// inbetween.
1297 	if ((ssize_t)reservedSize > length + 8 * 1024) {
1298 		status = B_BAD_DATA;
1299 		goto error1;
1300 	}
1301 
1302 	// reserve that space and allocate the areas from that one
1303 	if (vm_reserve_address_range(vm_kernel_address_space_id(), &reservedAddress,
1304 			B_ANY_KERNEL_ADDRESS, reservedSize, 0) < B_OK)
1305 		goto error3;
1306 
1307 	start = (addr_t)reservedAddress;
1308 	image->data_region.size = 0;
1309 	image->text_region.size = 0;
1310 
1311 	for (int32 i = 0; i < elfHeader->e_phnum; i++) {
1312 		char regionName[B_OS_NAME_LENGTH];
1313 		elf_region *region;
1314 
1315 		TRACE(("looking at program header %d\n", i));
1316 
1317 		switch (programHeaders[i].p_type) {
1318 			case PT_LOAD:
1319 				break;
1320 			case PT_DYNAMIC:
1321 				image->dynamic_section = programHeaders[i].p_vaddr;
1322 				continue;
1323 			default:
1324 				dprintf("%s: unhandled pheader type 0x%lx\n", fileName, programHeaders[i].p_type);
1325 				continue;
1326 		}
1327 
1328 		// we're here, so it must be a PT_LOAD segment
1329 		if (programHeaders[i].IsReadWrite()) {
1330 			// this is the writable segment
1331 			if (image->data_region.size != 0) {
1332 				// we've already created this segment
1333 				continue;
1334 			}
1335 			region = &image->data_region;
1336 
1337 			snprintf(regionName, B_OS_NAME_LENGTH, "%s_data", fileName);
1338 		} else if (programHeaders[i].IsExecutable()) {
1339 			// this is the non-writable segment
1340 			if (image->text_region.size != 0) {
1341 				// we've already created this segment
1342 				continue;
1343 			}
1344 			region = &image->text_region;
1345 
1346 			snprintf(regionName, B_OS_NAME_LENGTH, "%s_text", fileName);
1347 		} else {
1348 			dprintf("%s: weird program header flags 0x%lx\n", fileName,
1349 				programHeaders[i].p_flags);
1350 			continue;
1351 		}
1352 
1353 		region->start = (addr_t)reservedAddress + ROUNDOWN(programHeaders[i].p_vaddr, B_PAGE_SIZE);
1354 		region->size = ROUNDUP(programHeaders[i].p_memsz
1355 			+ (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE);
1356 		region->id = create_area(regionName, (void **)&region->start, B_EXACT_ADDRESS,
1357 			region->size, B_FULL_LOCK, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
1358 		if (region->id < B_OK) {
1359 			dprintf("%s: error allocating area: %s\n", fileName, strerror(region->id));
1360 			status = B_NOT_AN_EXECUTABLE;
1361 			goto error4;
1362 		}
1363 		region->delta = -ROUNDOWN(programHeaders[i].p_vaddr, B_PAGE_SIZE);
1364 
1365 		TRACE(("elf_load_kspace: created area \"%s\" at %p\n",
1366 			regionName, (void *)region->start));
1367 
1368 		length = _kern_read(fd, programHeaders[i].p_offset,
1369 			(void *)(region->start + (programHeaders[i].p_vaddr % B_PAGE_SIZE)),
1370 			programHeaders[i].p_filesz);
1371 		if (length < B_OK) {
1372 			status = length;
1373 			dprintf("%s: error reading in segment %ld\n", fileName, i);
1374 			goto error5;
1375 		}
1376 	}
1377 
1378 	// get the segment order
1379 	elf_region *firstRegion;
1380 	elf_region *secondRegion;
1381 	if (image->text_region.start < image->data_region.start) {
1382 		firstRegion = &image->text_region;
1383 		secondRegion = &image->data_region;
1384 	} else {
1385 		firstRegion = &image->data_region;
1386 		secondRegion = &image->text_region;
1387 	}
1388 
1389 	image->data_region.delta += image->data_region.start;
1390 	image->text_region.delta += image->text_region.start;
1391 
1392 	// modify the dynamic ptr by the delta of the regions
1393 	image->dynamic_section += image->text_region.delta;
1394 
1395 	status = elf_parse_dynamic_section(image);
1396 	if (status < B_OK)
1397 		goto error5;
1398 
1399 	status = elf_relocate(image, "");
1400 	if (status < B_OK)
1401 		goto error5;
1402 
1403 	// We needed to read in the contents of the "text" area, but
1404 	// now we can protect it read-only/execute
1405 	set_area_protection(image->text_region.id, B_KERNEL_READ_AREA | B_KERNEL_EXECUTE_AREA);
1406 
1407 	// There might be a hole between the two segments, and we don't need to
1408 	// reserve this any longer
1409 	vm_unreserve_address_range(vm_kernel_address_space_id(), reservedAddress, reservedSize);
1410 
1411 	// ToDo: this should be enabled by kernel settings!
1412 	if (1)
1413 		load_elf_symbol_table(fd, image);
1414 
1415 	free(programHeaders);
1416 	register_elf_image(image);
1417 
1418 done:
1419 	_kern_close(fd);
1420 	mutex_unlock(&sImageLoadMutex);
1421 
1422 	return image->id;
1423 
1424 error5:
1425 	delete_area(image->data_region.id);
1426 	delete_area(image->text_region.id);
1427 error4:
1428 	vm_unreserve_address_range(vm_kernel_address_space_id(), reservedAddress, reservedSize);
1429 error3:
1430 	free(programHeaders);
1431 error2:
1432 	free(image);
1433 error1:
1434 	free(elfHeader);
1435 error:
1436 	mutex_unlock(&sImageLoadMutex);
1437 error0:
1438 	if (vnode)
1439 		vfs_put_vnode(vnode);
1440 	_kern_close(fd);
1441 
1442 	return status;
1443 }
1444 
1445 
1446 status_t
1447 unload_kernel_add_on(image_id id)
1448 {
1449 	struct elf_image_info *image;
1450 	status_t status;
1451 
1452 	mutex_lock(&sImageMutex);
1453 
1454 	image = find_image(id);
1455 	if (image != NULL) {
1456 		mutex_lock(&sImageLoadMutex);
1457 
1458 		status = unload_elf_image(image);
1459 
1460 		mutex_unlock(&sImageLoadMutex);
1461 	} else
1462 		status = B_BAD_IMAGE_ID;
1463 
1464 	mutex_unlock(&sImageMutex);
1465 	return status;
1466 }
1467 
1468 
1469 status_t
1470 elf_init(kernel_args *args)
1471 {
1472 	struct preloaded_image *image;
1473 
1474 	image_init();
1475 
1476 	mutex_init(&sImageMutex, "kimages_lock");
1477 	mutex_init(&sImageLoadMutex, "kimages_load_lock");
1478 
1479 	sImagesHash = hash_init(IMAGE_HASH_SIZE, 0, image_compare, image_hash);
1480 	if (sImagesHash == NULL)
1481 		return B_NO_MEMORY;
1482 
1483 	// Build a image structure for the kernel, which has already been loaded.
1484 	// The preloaded_images were already prepared by the VM.
1485 	if (insert_preloaded_image(&args->kernel_image, true) < B_OK)
1486 		panic("could not create kernel image.\n");
1487 
1488 	// Build image structures for all preloaded images.
1489 	for (image = args->preloaded_images; image != NULL; image = image->next) {
1490 		insert_preloaded_image(image, false);
1491 	}
1492 
1493 	add_debugger_command("ls", &dump_address_info, "lookup symbol for a particular address");
1494 	add_debugger_command("symbols", &dump_symbols, "dump symbols for image");
1495 	add_debugger_command("image", &dump_image, "dump image info");
1496 
1497 	sInitialized = true;
1498 	return B_OK;
1499 }
1500 
1501