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