xref: /haiku/src/system/kernel/elf.cpp (revision 1214ef1b2100f2b3299fc9d8d6142e46f70a4c3f)
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 static uint32
67 image_hash(void *_image, const void *_key, uint32 range)
68 {
69 	struct elf_image_info *image = (struct elf_image_info *)_image;
70 	image_id id = (image_id)_key;
71 
72 	if (image != NULL)
73 		return image->id % range;
74 
75 	return (uint32)id % range;
76 }
77 
78 
79 /*!	Compares an image to a given ID */
80 static int
81 image_compare(void *_image, const void *_key)
82 {
83 	struct elf_image_info *image = (struct elf_image_info *)_image;
84 	image_id id = (image_id)_key;
85 
86 	return id - image->id;
87 }
88 
89 
90 static void
91 unregister_elf_image(struct elf_image_info *image)
92 {
93 	unregister_image(team_get_kernel_team(), image->id);
94 	hash_remove(sImagesHash, image);
95 }
96 
97 
98 static void
99 register_elf_image(struct elf_image_info *image)
100 {
101 	image_info imageInfo;
102 
103 	memset(&imageInfo, 0, sizeof(image_info));
104 	imageInfo.id = image->id;
105 	imageInfo.type = B_SYSTEM_IMAGE;
106 	strlcpy(imageInfo.name, image->name, sizeof(imageInfo.name));
107 
108 	imageInfo.text = (void *)image->text_region.start;
109 	imageInfo.text_size = image->text_region.size;
110 	imageInfo.data = (void *)image->data_region.start;
111 	imageInfo.data_size = image->data_region.size;
112 
113 	image->id = register_image(team_get_kernel_team(), &imageInfo, sizeof(image_info));
114 	hash_insert(sImagesHash, image);
115 }
116 
117 
118 /*!	Note, you must lock the image mutex when you call this function. */
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
482 					+ image->text_region.delta);
483 				break;
484 			case DT_STRTAB:
485 				image->strtab = (char *)(d[i].d_un.d_ptr
486 					+ image->text_region.delta);
487 				break;
488 			case DT_SYMTAB:
489 				image->syms = (struct Elf32_Sym *)(d[i].d_un.d_ptr
490 					+ image->text_region.delta);
491 				break;
492 			case DT_REL:
493 				image->rel = (struct Elf32_Rel *)(d[i].d_un.d_ptr
494 					+ image->text_region.delta);
495 				break;
496 			case DT_RELSZ:
497 				image->rel_len = d[i].d_un.d_val;
498 				break;
499 			case DT_RELA:
500 				image->rela = (struct Elf32_Rela *)(d[i].d_un.d_ptr
501 					+ image->text_region.delta);
502 				break;
503 			case DT_RELASZ:
504 				image->rela_len = d[i].d_un.d_val;
505 				break;
506 			case DT_JMPREL:
507 				image->pltrel = (struct Elf32_Rel *)(d[i].d_un.d_ptr
508 					+ image->text_region.delta);
509 				break;
510 			case DT_PLTRELSZ:
511 				image->pltrel_len = d[i].d_un.d_val;
512 				break;
513 			case DT_PLTREL:
514 				image->pltrel_type = d[i].d_un.d_val;
515 				break;
516 
517 			default:
518 				continue;
519 		}
520 	}
521 
522 	// lets make sure we found all the required sections
523 	if (!image->symhash || !image->syms || !image->strtab)
524 		return B_ERROR;
525 
526 	TRACE(("needed_offset = %ld\n", neededOffset));
527 
528 	if (neededOffset >= 0)
529 		image->needed = STRING(image, neededOffset);
530 
531 	return B_OK;
532 }
533 
534 
535 /*!	Resolves the \a symbol by linking against \a sharedImage if necessary.
536 	Returns the resolved symbol's address in \a _symbolAddress.
537 	TODO: eventually get rid of "symbolPrepend"
538 */
539 status_t
540 elf_resolve_symbol(struct elf_image_info *image, struct Elf32_Sym *symbol,
541 	struct elf_image_info *sharedImage, const char *symbolPrepend,
542 	addr_t *_symbolAddress)
543 {
544 	switch (symbol->st_shndx) {
545 		case SHN_UNDEF:
546 		{
547 			struct Elf32_Sym *newSymbol;
548 			char newNameBuffer[368];
549 			char *newName;
550 
551 			// patch the symbol name
552 			if (symbolPrepend) {
553 				newName = newNameBuffer;
554 				strlcpy(newName, symbolPrepend, sizeof(newName));
555 				strlcat(newName, SYMNAME(image, symbol), sizeof(newName));
556 			} else
557 				newName = SYMNAME(image, symbol);
558 
559 			// it's undefined, must be outside this image, try the other image
560 			newSymbol = elf_find_symbol(sharedImage, newName);
561 			if (newSymbol == NULL) {
562 				dprintf("\"%s\": could not resolve symbol '%s'\n",
563 					image->name, newName);
564 				return B_MISSING_SYMBOL;
565 			}
566 
567 			// make sure they're the same type
568 			if (ELF32_ST_TYPE(symbol->st_info)
569 					!= ELF32_ST_TYPE(newSymbol->st_info)) {
570 				dprintf("elf_resolve_symbol: found symbol '%s' in shared image but wrong type\n", newName);
571 				return B_MISSING_SYMBOL;
572 			}
573 
574 			if (ELF32_ST_BIND(newSymbol->st_info) != STB_GLOBAL
575 				&& ELF32_ST_BIND(newSymbol->st_info) != STB_WEAK) {
576 				TRACE(("elf_resolve_symbol: found symbol '%s' but not exported\n", newName));
577 				return B_MISSING_SYMBOL;
578 			}
579 
580 			*_symbolAddress = newSymbol->st_value
581 				+ sharedImage->text_region.delta;
582 			return B_OK;
583 		}
584 		case SHN_ABS:
585 			*_symbolAddress = symbol->st_value;
586 			return B_OK;
587 		case SHN_COMMON:
588 			// ToDo: finish this
589 			TRACE(("elf_resolve_symbol: COMMON symbol, finish me!\n"));
590 			return B_ERROR;
591 
592 		default:
593 			// standard symbol
594 			*_symbolAddress = symbol->st_value + image->text_region.delta;
595 			return B_OK;
596 	}
597 }
598 
599 
600 /*! Until we have shared library support, just links against the kernel */
601 static int
602 elf_relocate(struct elf_image_info *image, const char *symbolPrepend)
603 {
604 	int status = B_NO_ERROR;
605 
606 	TRACE(("top of elf_relocate\n"));
607 
608 	// deal with the rels first
609 	if (image->rel) {
610 		TRACE(("total %i relocs\n",
611 			image->rel_len / (int)sizeof(struct Elf32_Rel)));
612 
613 		status = arch_elf_relocate_rel(image, symbolPrepend, sKernelImage,
614 			image->rel, image->rel_len);
615 		if (status < B_OK)
616 			return status;
617 	}
618 
619 	if (image->pltrel) {
620 		TRACE(("total %i plt-relocs\n",
621 			image->pltrel_len / (int)sizeof(struct Elf32_Rel)));
622 
623 		if (image->pltrel_type == DT_REL) {
624 			status = arch_elf_relocate_rel(image, symbolPrepend, sKernelImage,
625 				image->pltrel, image->pltrel_len);
626 		} else {
627 			status = arch_elf_relocate_rela(image, symbolPrepend, sKernelImage,
628 				(struct Elf32_Rela *)image->pltrel, image->pltrel_len);
629 		}
630 		if (status < B_OK)
631 			return status;
632 	}
633 
634 	if (image->rela) {
635 		status = arch_elf_relocate_rela(image, symbolPrepend, sKernelImage,
636 			image->rela, image->rela_len);
637 		if (status < B_OK)
638 			return status;
639 	}
640 
641 	return status;
642 }
643 
644 
645 static int
646 verify_eheader(struct Elf32_Ehdr *elfHeader)
647 {
648 	if (memcmp(elfHeader->e_ident, ELF_MAGIC, 4) != 0)
649 		return B_NOT_AN_EXECUTABLE;
650 
651 	if (elfHeader->e_ident[4] != ELFCLASS32)
652 		return B_NOT_AN_EXECUTABLE;
653 
654 	if (elfHeader->e_phoff == 0)
655 		return B_NOT_AN_EXECUTABLE;
656 
657 	if (elfHeader->e_phentsize < sizeof(struct Elf32_Phdr))
658 		return B_NOT_AN_EXECUTABLE;
659 
660 	return 0;
661 }
662 
663 
664 #if 0
665 static int
666 elf_unlink_relocs(struct elf_image_info *image)
667 {
668 	elf_linked_image *link, *next_link;
669 
670 	for (link = image->linked_images; link; link = next_link) {
671 		next_link = link->next;
672 		elf_unload_image(link->image);
673 		free(link);
674 	}
675 
676 	return B_NO_ERROR;
677 }
678 #endif
679 
680 
681 static status_t
682 unload_elf_image(struct elf_image_info *image)
683 {
684 	if (atomic_add(&image->ref_count, -1) > 0)
685 		return B_NO_ERROR;
686 
687 	//elf_unlink_relocs(image);
688 		// not yet used
689 
690 	delete_area(image->text_region.id);
691 	delete_area(image->data_region.id);
692 
693 	if (image->vnode)
694 		vfs_put_vnode(image->vnode);
695 
696 	unregister_elf_image(image);
697 
698 	free(image->elf_header);
699 	free(image->name);
700 	free(image);
701 
702 	return B_NO_ERROR;
703 }
704 
705 
706 static status_t
707 load_elf_symbol_table(int fd, struct elf_image_info *image)
708 {
709 	struct Elf32_Ehdr *elfHeader = image->elf_header;
710 	struct Elf32_Sym *symbolTable = NULL;
711 	struct Elf32_Shdr *stringHeader = NULL;
712 	uint32 numSymbols = 0;
713 	char *stringTable;
714 	status_t status;
715 	ssize_t length;
716 	int32 i;
717 
718 	// get section headers
719 
720 	ssize_t size = elfHeader->e_shnum * elfHeader->e_shentsize;
721 	struct Elf32_Shdr *sectionHeaders = (struct Elf32_Shdr *)malloc(size);
722 	if (sectionHeaders == NULL) {
723 		dprintf("error allocating space for section headers\n");
724 		return B_NO_MEMORY;
725 	}
726 
727 	length = read_pos(fd, elfHeader->e_shoff, sectionHeaders, size);
728 	if (length < size) {
729 		TRACE(("error reading in program headers\n"));
730 		status = B_ERROR;
731 		goto error1;
732 	}
733 
734 	// find symbol table in section headers
735 
736 	for (i = 0; i < elfHeader->e_shnum; i++) {
737 		if (sectionHeaders[i].sh_type == SHT_SYMTAB) {
738 			stringHeader = &sectionHeaders[sectionHeaders[i].sh_link];
739 
740 			if (stringHeader->sh_type != SHT_STRTAB) {
741 				TRACE(("doesn't link to string table\n"));
742 				status = B_BAD_DATA;
743 				goto error1;
744 			}
745 
746 			// read in symbol table
747 			symbolTable = (struct Elf32_Sym *)malloc(size = sectionHeaders[i].sh_size);
748 			if (symbolTable == NULL) {
749 				status = B_NO_MEMORY;
750 				goto error1;
751 			}
752 
753 			length = read_pos(fd, sectionHeaders[i].sh_offset, symbolTable, size);
754 			if (length < size) {
755 				TRACE(("error reading in symbol table\n"));
756 				status = B_ERROR;
757 				goto error1;
758 			}
759 
760 			numSymbols = size / sizeof(struct Elf32_Sym);
761 			break;
762 		}
763 	}
764 
765 	if (symbolTable == NULL) {
766 		TRACE(("no symbol table\n"));
767 		status = B_BAD_VALUE;
768 		goto error1;
769 	}
770 
771 	// read in string table
772 
773 	stringTable = (char *)malloc(size = stringHeader->sh_size);
774 	if (stringTable == NULL) {
775 		status = B_NO_MEMORY;
776 		goto error2;
777 	}
778 
779 	length = read_pos(fd, stringHeader->sh_offset, stringTable, size);
780 	if (length < size) {
781 		TRACE(("error reading in string table\n"));
782 		status = B_ERROR;
783 		goto error3;
784 	}
785 
786 	TRACE(("loaded debug %ld symbols\n", numSymbols));
787 
788 	// insert tables into image
789 	image->debug_symbols = symbolTable;
790 	image->num_debug_symbols = numSymbols;
791 	image->debug_string_table = stringTable;
792 
793 	free(sectionHeaders);
794 	return B_OK;
795 
796 error3:
797 	free(stringTable);
798 error2:
799 	free(symbolTable);
800 error1:
801 	free(sectionHeaders);
802 
803 	return status;
804 }
805 
806 
807 static status_t
808 insert_preloaded_image(struct preloaded_image *preloadedImage, bool kernel)
809 {
810 	struct elf_image_info *image;
811 	status_t status;
812 
813 	status = verify_eheader(&preloadedImage->elf_header);
814 	if (status < B_OK)
815 		return status;
816 
817 	image = create_image_struct();
818 	if (image == NULL)
819 		return B_NO_MEMORY;
820 
821 	image->name = strdup(preloadedImage->name);
822 	image->dynamic_section = preloadedImage->dynamic_section.start;
823 
824 	image->text_region = preloadedImage->text_region;
825 	image->data_region = preloadedImage->data_region;
826 
827 	status = elf_parse_dynamic_section(image);
828 	if (status < B_OK)
829 		goto error1;
830 
831 	if (!kernel) {
832 		status = elf_relocate(image, NULL);
833 		if (status < B_OK)
834 			goto error1;
835 	} else
836 		sKernelImage = image;
837 
838 	image->debug_symbols = preloadedImage->debug_symbols;
839 	image->num_debug_symbols = preloadedImage->num_debug_symbols;
840 	image->debug_string_table = preloadedImage->debug_string_table;
841 
842 	register_elf_image(image);
843 	preloadedImage->id = image->id;
844 		// modules_init() uses this information to get the preloaded images
845 
846 	// we now no longer need to write to the text area anymore
847 	set_area_protection(image->text_region.id,
848 		B_KERNEL_READ_AREA | B_KERNEL_EXECUTE_AREA);
849 
850 	return B_OK;
851 
852 error1:
853 	free(image);
854 
855 	// clean up preloaded image resources (this image won't be used anymore)
856 	delete_area(preloadedImage->text_region.id);
857 	delete_area(preloadedImage->data_region.id);
858 	preloadedImage->id = -1;
859 
860 	return status;
861 }
862 
863 
864 //	#pragma mark - public kernel API
865 
866 
867 status_t
868 get_image_symbol(image_id id, const char *name, int32 sclass, void **_symbol)
869 {
870 	struct elf_image_info *image;
871 	struct Elf32_Sym *symbol;
872 	status_t status = B_OK;
873 
874 	TRACE(("get_image_symbol(%s)\n", name));
875 
876 	mutex_lock(&sImageMutex);
877 
878 	image = find_image(id);
879 	if (image == NULL) {
880 		status = B_BAD_IMAGE_ID;
881 		goto done;
882 	}
883 
884 	symbol = elf_find_symbol(image, name);
885 	if (symbol == NULL || symbol->st_shndx == SHN_UNDEF) {
886 		status = B_ENTRY_NOT_FOUND;
887 		goto done;
888 	}
889 
890 	// ToDo: support the "sclass" parameter!
891 
892 	TRACE(("found: %lx (%lx + %lx)\n", symbol->st_value + image->text_region.delta,
893 		symbol->st_value, image->text_region.delta));
894 
895 	*_symbol = (void *)(symbol->st_value + image->text_region.delta);
896 
897 done:
898 	mutex_unlock(&sImageMutex);
899 	return status;
900 }
901 
902 
903 //	#pragma mark - kernel private API
904 
905 
906 /*!	Looks up a symbol by address in all images loaded in kernel space.
907 	Note, if you need to call this function outside a debugger, make
908 	sure you fix locking and the way it returns its information, first!
909 */
910 status_t
911 elf_debug_lookup_symbol_address(addr_t address, addr_t *_baseAddress,
912 	const char **_symbolName, const char **_imageName, bool *_exactMatch)
913 {
914 	struct elf_image_info *image;
915 	struct Elf32_Sym *symbolFound = NULL;
916 	const char *symbolName = NULL;
917 	addr_t deltaFound = INT_MAX;
918 	bool exactMatch = false;
919 	status_t status;
920 
921 	TRACE(("looking up %p\n", (void *)address));
922 
923 	if (!sInitialized)
924 		return B_ERROR;
925 
926 	//mutex_lock(&sImageMutex);
927 
928 	image = find_image_at_address(address);
929 		// get image that may contain the address
930 
931 	if (image != NULL) {
932 		addr_t symbolDelta;
933 		uint32 i;
934 		int32 j;
935 
936 		TRACE((" image %p, base = %p, size = %p\n", image,
937 			(void *)image->text_region.start, (void *)image->text_region.size));
938 
939 		if (image->debug_symbols != NULL) {
940 			// search extended debug symbol table (contains static symbols)
941 
942 			TRACE((" searching debug symbols...\n"));
943 
944 			for (i = 0; i < image->num_debug_symbols; i++) {
945 				struct Elf32_Sym *symbol = &image->debug_symbols[i];
946 
947 				if (symbol->st_value == 0
948 					|| symbol->st_size >= image->text_region.size + image->data_region.size)
949 					continue;
950 
951 				symbolDelta = address - (symbol->st_value + image->text_region.delta);
952 				if (symbolDelta >= 0 && symbolDelta < symbol->st_size)
953 					exactMatch = true;
954 
955 				if (exactMatch || symbolDelta < deltaFound) {
956 					deltaFound = symbolDelta;
957 					symbolFound = symbol;
958 					symbolName = image->debug_string_table + symbol->st_name;
959 
960 					if (exactMatch)
961 						break;
962 				}
963 			}
964 		} else {
965 			// search standard symbol lookup table
966 
967 			TRACE((" searching standard symbols...\n"));
968 
969 			for (i = 0; i < HASHTABSIZE(image); i++) {
970 				for (j = HASHBUCKETS(image)[i]; j != STN_UNDEF; j = HASHCHAINS(image)[j]) {
971 					struct Elf32_Sym *symbol = &image->syms[j];
972 
973 					if (symbol->st_value == 0
974 						|| symbol->st_size >= image->text_region.size + image->data_region.size)
975 						continue;
976 
977 					symbolDelta = address - (long)(symbol->st_value + image->text_region.delta);
978 					if (symbolDelta >= 0 && symbolDelta < symbol->st_size)
979 						exactMatch = true;
980 
981 					if (exactMatch || symbolDelta < deltaFound) {
982 						deltaFound = symbolDelta;
983 						symbolFound = symbol;
984 						symbolName = SYMNAME(image, symbol);
985 
986 						if (exactMatch)
987 							goto symbol_found;
988 					}
989 				}
990 			}
991 		}
992 	}
993 symbol_found:
994 
995 	if (symbolFound != NULL) {
996 		if (_symbolName)
997 			*_symbolName = symbolName;
998 		if (_imageName)
999 			*_imageName = image->name;
1000 		if (_baseAddress)
1001 			*_baseAddress = symbolFound->st_value + image->text_region.delta;
1002 		if (_exactMatch)
1003 			*_exactMatch = exactMatch;
1004 
1005 		status = B_OK;
1006 	} else if (image != NULL) {
1007 		TRACE(("symbol not found!\n"));
1008 
1009 		if (_symbolName)
1010 			*_symbolName = NULL;
1011 		if (_imageName)
1012 			*_imageName = image->name;
1013 		if (_baseAddress)
1014 			*_baseAddress = image->text_region.start;
1015 		if (_exactMatch)
1016 			*_exactMatch = false;
1017 
1018 		status = B_OK;
1019 	} else {
1020 		TRACE(("image not found!\n"));
1021 		status = B_ENTRY_NOT_FOUND;
1022 	}
1023 
1024 	// Note, theoretically, all information we return back to our caller
1025 	// would have to be locked - but since this function is only called
1026 	// from the debugger, it's safe to do it this way
1027 
1028 	//mutex_unlock(&sImageMutex);
1029 
1030 	return status;
1031 }
1032 
1033 
1034 status_t
1035 elf_load_user_image(const char *path, struct team *team, int flags, addr_t *entry)
1036 {
1037 	struct Elf32_Ehdr elfHeader;
1038 	struct Elf32_Phdr *programHeaders = NULL;
1039 	char baseName[B_OS_NAME_LENGTH];
1040 	status_t status;
1041 	ssize_t length;
1042 	int fd;
1043 	int i;
1044 
1045 	TRACE(("elf_load: entry path '%s', team %p\n", path, team));
1046 
1047 	fd = _kern_open(-1, path, O_RDONLY, 0);
1048 	if (fd < 0)
1049 		return fd;
1050 
1051 	// read and verify the ELF header
1052 
1053 	length = _kern_read(fd, 0, &elfHeader, sizeof(elfHeader));
1054 	if (length < B_OK) {
1055 		status = length;
1056 		goto error;
1057 	}
1058 
1059 	if (length != sizeof(elfHeader)) {
1060 		// short read
1061 		status = B_NOT_AN_EXECUTABLE;
1062 		goto error;
1063 	}
1064 	status = verify_eheader(&elfHeader);
1065 	if (status < B_OK)
1066 		goto error;
1067 
1068 	// read program header
1069 
1070 	programHeaders = (struct Elf32_Phdr *)malloc(elfHeader.e_phnum * elfHeader.e_phentsize);
1071 	if (programHeaders == NULL) {
1072 		dprintf("error allocating space for program headers\n");
1073 		status = B_NO_MEMORY;
1074 		goto error;
1075 	}
1076 
1077 	TRACE(("reading in program headers at 0x%lx, length 0x%x\n", elfHeader.e_phoff, elfHeader.e_phnum * elfHeader.e_phentsize));
1078 	length = _kern_read(fd, elfHeader.e_phoff, programHeaders, elfHeader.e_phnum * elfHeader.e_phentsize);
1079 	if (length < B_OK) {
1080 		status = length;
1081 		dprintf("error reading in program headers\n");
1082 		goto error;
1083 	}
1084 	if (length != elfHeader.e_phnum * elfHeader.e_phentsize) {
1085 		dprintf("short read while reading in program headers\n");
1086 		status = -1;
1087 		goto error;
1088 	}
1089 
1090 	// construct a nice name for the region we have to create below
1091 	{
1092 		int32 length;
1093 
1094 		const char *leaf = strrchr(path, '/');
1095 		if (leaf == NULL)
1096 			leaf = path;
1097 		else
1098 			leaf++;
1099 
1100 		length = strlen(leaf);
1101 		if (length > B_OS_NAME_LENGTH - 8)
1102 			sprintf(baseName, "...%s", leaf + length + 8 - B_OS_NAME_LENGTH);
1103 		else
1104 			strcpy(baseName, leaf);
1105 	}
1106 
1107 	// map the program's segments into memory
1108 
1109 	for (i = 0; i < elfHeader.e_phnum; i++) {
1110 		char regionName[B_OS_NAME_LENGTH];
1111 		char *regionAddress;
1112 		area_id id;
1113 
1114 		if (programHeaders[i].p_type != PT_LOAD)
1115 			continue;
1116 
1117 		regionAddress = (char *)ROUNDOWN(programHeaders[i].p_vaddr, B_PAGE_SIZE);
1118 		if (programHeaders[i].p_flags & PF_WRITE) {
1119 			/*
1120 			 * rw/data segment
1121 			 */
1122 			uint32 memUpperBound = (programHeaders[i].p_vaddr % B_PAGE_SIZE) + programHeaders[i].p_memsz;
1123 			uint32 fileUpperBound = (programHeaders[i].p_vaddr % B_PAGE_SIZE) + programHeaders[i].p_filesz;
1124 
1125 			memUpperBound = ROUNDUP(memUpperBound, B_PAGE_SIZE);
1126 			fileUpperBound = ROUNDUP(fileUpperBound, B_PAGE_SIZE);
1127 
1128 			sprintf(regionName, "%s_seg%drw", baseName, i);
1129 
1130 			id = vm_map_file(team->id, regionName,
1131 				(void **)&regionAddress,
1132 				B_EXACT_ADDRESS,
1133 				fileUpperBound,
1134 				B_READ_AREA | B_WRITE_AREA, REGION_PRIVATE_MAP,
1135 				path, ROUNDOWN(programHeaders[i].p_offset, B_PAGE_SIZE));
1136 			if (id < B_OK) {
1137 				dprintf("error mapping file data: %s!\n", strerror(id));
1138 				status = B_NOT_AN_EXECUTABLE;
1139 				goto error;
1140 			}
1141 
1142 			// clean garbage brought by mmap (the region behind the file,
1143 			// at least parts of it are the bss and have to be zeroed)
1144 			{
1145 				uint32 start = (uint32)regionAddress
1146 					+ (programHeaders[i].p_vaddr % B_PAGE_SIZE)
1147 					+ programHeaders[i].p_filesz;
1148 				uint32 amount = fileUpperBound
1149 					- (programHeaders[i].p_vaddr % B_PAGE_SIZE)
1150 					- (programHeaders[i].p_filesz);
1151 				memset((void *)start, 0, amount);
1152 			}
1153 
1154 			// Check if we need extra storage for the bss - we have to do this if
1155 			// the above region doesn't already comprise the memory size, too.
1156 
1157 			if (memUpperBound != fileUpperBound) {
1158 				size_t bss_size = memUpperBound - fileUpperBound;
1159 
1160 				snprintf(regionName, B_OS_NAME_LENGTH, "%s_bss%d", baseName, i);
1161 
1162 				regionAddress += fileUpperBound;
1163 				id = create_area_etc(team, regionName, (void **)&regionAddress,
1164 					B_EXACT_ADDRESS, bss_size, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
1165 				if (id < B_OK) {
1166 					dprintf("error allocating bss area: %s!\n", strerror(id));
1167 					status = B_NOT_AN_EXECUTABLE;
1168 					goto error;
1169 				}
1170 			}
1171 		} else {
1172 			/*
1173 			 * assume ro/text segment
1174 			 */
1175 			snprintf(regionName, B_OS_NAME_LENGTH, "%s_seg%dro", baseName, i);
1176 
1177 			id = vm_map_file(team->id, regionName,
1178 				(void **)&regionAddress,
1179 				B_EXACT_ADDRESS,
1180 				ROUNDUP(programHeaders[i].p_memsz + (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE),
1181 				B_READ_AREA | B_EXECUTE_AREA, REGION_PRIVATE_MAP,
1182 				path, ROUNDOWN(programHeaders[i].p_offset, B_PAGE_SIZE));
1183 			if (id < B_OK) {
1184 				dprintf("error mapping file text: %s!\n", strerror(id));
1185 				status = B_NOT_AN_EXECUTABLE;
1186 				goto error;
1187 			}
1188 		}
1189 	}
1190 
1191 	TRACE(("elf_load: done!\n"));
1192 
1193 	*entry = elfHeader.e_entry;
1194 
1195 	status = B_OK;
1196 
1197 error:
1198 	if (programHeaders)
1199 		free(programHeaders);
1200 	_kern_close(fd);
1201 
1202 	return status;
1203 }
1204 
1205 
1206 image_id
1207 load_kernel_add_on(const char *path)
1208 {
1209 	struct Elf32_Phdr *programHeaders;
1210 	struct Elf32_Ehdr *elfHeader;
1211 	struct elf_image_info *image;
1212 	const char *fileName;
1213 	void *reservedAddress;
1214 	addr_t start;
1215 	size_t reservedSize;
1216 	status_t status;
1217 	ssize_t length;
1218 
1219 	TRACE(("elf_load_kspace: entry path '%s'\n", path));
1220 
1221 	int fd = _kern_open(-1, path, O_RDONLY, 0);
1222 	if (fd < 0)
1223 		return fd;
1224 
1225 	struct vnode *vnode;
1226 	status = vfs_get_vnode_from_fd(fd, true, &vnode);
1227 	if (status < B_OK)
1228 		goto error0;
1229 
1230 	// get the file name
1231 	fileName = strrchr(path, '/');
1232 	if (fileName == NULL)
1233 		fileName = path;
1234 	else
1235 		fileName++;
1236 
1237 	// Prevent someone else from trying to load this image
1238 	mutex_lock(&sImageLoadMutex);
1239 
1240 	// make sure it's not loaded already. Search by vnode
1241 	image = find_image_by_vnode(vnode);
1242 	if (image) {
1243 		atomic_add(&image->ref_count, 1);
1244 		goto done;
1245 	}
1246 
1247 	elfHeader = (struct Elf32_Ehdr *)malloc(sizeof(*elfHeader));
1248 	if (!elfHeader) {
1249 		status = B_NO_MEMORY;
1250 		goto error;
1251 	}
1252 
1253 	length = _kern_read(fd, 0, elfHeader, sizeof(*elfHeader));
1254 	if (length < B_OK) {
1255 		status = length;
1256 		goto error1;
1257 	}
1258 	if (length != sizeof(*elfHeader)) {
1259 		// short read
1260 		status = B_NOT_AN_EXECUTABLE;
1261 		goto error1;
1262 	}
1263 	status = verify_eheader(elfHeader);
1264 	if (status < B_OK)
1265 		goto error1;
1266 
1267 	image = create_image_struct();
1268 	if (!image) {
1269 		status = B_NO_MEMORY;
1270 		goto error1;
1271 	}
1272 	image->vnode = vnode;
1273 	image->elf_header = elfHeader;
1274 	image->name = strdup(path);
1275 
1276 	programHeaders = (struct Elf32_Phdr *)malloc(elfHeader->e_phnum
1277 		* elfHeader->e_phentsize);
1278 	if (programHeaders == NULL) {
1279 		dprintf("%s: error allocating space for program headers\n", fileName);
1280 		status = B_NO_MEMORY;
1281 		goto error2;
1282 	}
1283 
1284 	TRACE(("reading in program headers at 0x%lx, length 0x%x\n",
1285 		elfHeader->e_phoff, elfHeader->e_phnum * elfHeader->e_phentsize));
1286 
1287 	length = _kern_read(fd, elfHeader->e_phoff, programHeaders,
1288 		elfHeader->e_phnum * elfHeader->e_phentsize);
1289 	if (length < B_OK) {
1290 		status = length;
1291 		TRACE(("%s: error reading in program headers\n", fileName));
1292 		goto error3;
1293 	}
1294 	if (length != elfHeader->e_phnum * elfHeader->e_phentsize) {
1295 		TRACE(("%s: short read while reading in program headers\n", fileName));
1296 		status = B_ERROR;
1297 		goto error3;
1298 	}
1299 
1300 	// determine how much space we need for all loaded segments
1301 
1302 	reservedSize = 0;
1303 	length = 0;
1304 
1305 	for (int32 i = 0; i < elfHeader->e_phnum; i++) {
1306 		size_t end;
1307 
1308 		if (programHeaders[i].p_type != PT_LOAD)
1309 			continue;
1310 
1311 		length += ROUNDUP(programHeaders[i].p_memsz
1312 			+ (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE);
1313 
1314 		end = ROUNDUP(programHeaders[i].p_memsz + programHeaders[i].p_vaddr,
1315 			B_PAGE_SIZE);
1316 		if (end > reservedSize)
1317 			reservedSize = end;
1318 	}
1319 
1320 	// Check whether the segments have an unreasonable amount of unused space
1321 	// inbetween.
1322 	if ((ssize_t)reservedSize > length + 8 * 1024) {
1323 		status = B_BAD_DATA;
1324 		goto error1;
1325 	}
1326 
1327 	// reserve that space and allocate the areas from that one
1328 	if (vm_reserve_address_range(vm_kernel_address_space_id(), &reservedAddress,
1329 			B_ANY_KERNEL_ADDRESS, reservedSize, 0) < B_OK) {
1330 		status = B_NO_MEMORY;
1331 		goto error3;
1332 	}
1333 
1334 	start = (addr_t)reservedAddress;
1335 	image->data_region.size = 0;
1336 	image->text_region.size = 0;
1337 
1338 	for (int32 i = 0; i < elfHeader->e_phnum; i++) {
1339 		char regionName[B_OS_NAME_LENGTH];
1340 		elf_region *region;
1341 
1342 		TRACE(("looking at program header %ld\n", i));
1343 
1344 		switch (programHeaders[i].p_type) {
1345 			case PT_LOAD:
1346 				break;
1347 			case PT_DYNAMIC:
1348 				image->dynamic_section = programHeaders[i].p_vaddr;
1349 				continue;
1350 			default:
1351 				dprintf("%s: unhandled pheader type 0x%lx\n", fileName,
1352 					programHeaders[i].p_type);
1353 				continue;
1354 		}
1355 
1356 		// we're here, so it must be a PT_LOAD segment
1357 		if (programHeaders[i].IsReadWrite()) {
1358 			// this is the writable segment
1359 			if (image->data_region.size != 0) {
1360 				// we've already created this segment
1361 				continue;
1362 			}
1363 			region = &image->data_region;
1364 
1365 			snprintf(regionName, B_OS_NAME_LENGTH, "%s_data", fileName);
1366 		} else if (programHeaders[i].IsExecutable()) {
1367 			// this is the non-writable segment
1368 			if (image->text_region.size != 0) {
1369 				// we've already created this segment
1370 				continue;
1371 			}
1372 			region = &image->text_region;
1373 
1374 			snprintf(regionName, B_OS_NAME_LENGTH, "%s_text", fileName);
1375 		} else {
1376 			dprintf("%s: weird program header flags 0x%lx\n", fileName,
1377 				programHeaders[i].p_flags);
1378 			continue;
1379 		}
1380 
1381 		region->start = (addr_t)reservedAddress + ROUNDOWN(
1382 			programHeaders[i].p_vaddr, B_PAGE_SIZE);
1383 		region->size = ROUNDUP(programHeaders[i].p_memsz
1384 			+ (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE);
1385 		region->id = create_area(regionName, (void **)&region->start,
1386 			B_EXACT_ADDRESS, region->size, B_FULL_LOCK,
1387 			B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
1388 		if (region->id < B_OK) {
1389 			dprintf("%s: error allocating area: %s\n", fileName,
1390 				strerror(region->id));
1391 			status = B_NOT_AN_EXECUTABLE;
1392 			goto error4;
1393 		}
1394 		region->delta = -ROUNDOWN(programHeaders[i].p_vaddr, B_PAGE_SIZE);
1395 
1396 		TRACE(("elf_load_kspace: created area \"%s\" at %p\n",
1397 			regionName, (void *)region->start));
1398 
1399 		length = _kern_read(fd, programHeaders[i].p_offset,
1400 			(void *)(region->start + (programHeaders[i].p_vaddr % B_PAGE_SIZE)),
1401 			programHeaders[i].p_filesz);
1402 		if (length < B_OK) {
1403 			status = length;
1404 			dprintf("%s: error reading in segment %ld\n", fileName, i);
1405 			goto error5;
1406 		}
1407 	}
1408 
1409 	// get the segment order
1410 	elf_region *firstRegion;
1411 	elf_region *secondRegion;
1412 	if (image->text_region.start < image->data_region.start) {
1413 		firstRegion = &image->text_region;
1414 		secondRegion = &image->data_region;
1415 	} else {
1416 		firstRegion = &image->data_region;
1417 		secondRegion = &image->text_region;
1418 	}
1419 
1420 	image->data_region.delta += image->data_region.start;
1421 	image->text_region.delta += image->text_region.start;
1422 
1423 	// modify the dynamic ptr by the delta of the regions
1424 	image->dynamic_section += image->text_region.delta;
1425 
1426 	status = elf_parse_dynamic_section(image);
1427 	if (status < B_OK)
1428 		goto error5;
1429 
1430 	status = elf_relocate(image, NULL);
1431 	if (status < B_OK)
1432 		goto error5;
1433 
1434 	// We needed to read in the contents of the "text" area, but
1435 	// now we can protect it read-only/execute
1436 	set_area_protection(image->text_region.id,
1437 		B_KERNEL_READ_AREA | B_KERNEL_EXECUTE_AREA);
1438 
1439 	// There might be a hole between the two segments, and we don't need to
1440 	// reserve this any longer
1441 	vm_unreserve_address_range(vm_kernel_address_space_id(), reservedAddress,
1442 		reservedSize);
1443 
1444 	// ToDo: this should be enabled by kernel settings!
1445 	if (1)
1446 		load_elf_symbol_table(fd, image);
1447 
1448 	free(programHeaders);
1449 	register_elf_image(image);
1450 
1451 done:
1452 	_kern_close(fd);
1453 	mutex_unlock(&sImageLoadMutex);
1454 
1455 	return image->id;
1456 
1457 error5:
1458 	delete_area(image->data_region.id);
1459 	delete_area(image->text_region.id);
1460 error4:
1461 	vm_unreserve_address_range(vm_kernel_address_space_id(), reservedAddress,
1462 		reservedSize);
1463 error3:
1464 	free(programHeaders);
1465 error2:
1466 	free(image);
1467 error1:
1468 	free(elfHeader);
1469 error:
1470 	mutex_unlock(&sImageLoadMutex);
1471 error0:
1472 	dprintf("Could not load kernel add-on \"%s\": %s\n", path,
1473 		strerror(status));
1474 
1475 	if (vnode)
1476 		vfs_put_vnode(vnode);
1477 	_kern_close(fd);
1478 
1479 	return status;
1480 }
1481 
1482 
1483 status_t
1484 unload_kernel_add_on(image_id id)
1485 {
1486 	struct elf_image_info *image;
1487 	status_t status;
1488 
1489 	mutex_lock(&sImageLoadMutex);
1490 	mutex_lock(&sImageMutex);
1491 
1492 	image = find_image(id);
1493 	if (image != NULL)
1494 		status = unload_elf_image(image);
1495 	else
1496 		status = B_BAD_IMAGE_ID;
1497 
1498 	mutex_unlock(&sImageMutex);
1499 	mutex_unlock(&sImageLoadMutex);
1500 
1501 	return status;
1502 }
1503 
1504 
1505 status_t
1506 elf_init(kernel_args *args)
1507 {
1508 	struct preloaded_image *image;
1509 
1510 	image_init();
1511 
1512 	mutex_init(&sImageMutex, "kimages_lock");
1513 	mutex_init(&sImageLoadMutex, "kimages_load_lock");
1514 
1515 	sImagesHash = hash_init(IMAGE_HASH_SIZE, 0, image_compare, image_hash);
1516 	if (sImagesHash == NULL)
1517 		return B_NO_MEMORY;
1518 
1519 	// Build a image structure for the kernel, which has already been loaded.
1520 	// The preloaded_images were already prepared by the VM.
1521 	if (insert_preloaded_image(&args->kernel_image, true) < B_OK)
1522 		panic("could not create kernel image.\n");
1523 
1524 	// Build image structures for all preloaded images.
1525 	for (image = args->preloaded_images; image != NULL; image = image->next) {
1526 		insert_preloaded_image(image, false);
1527 	}
1528 
1529 	add_debugger_command("ls", &dump_address_info, "lookup symbol for a particular address");
1530 	add_debugger_command("symbols", &dump_symbols, "dump symbols for image");
1531 	add_debugger_command("image", &dump_image, "dump image info");
1532 
1533 	sInitialized = true;
1534 	return B_OK;
1535 }
1536 
1537