xref: /haiku/src/system/kernel/elf.cpp (revision 909af08f4328301fbdef1ffb41f566c3b5bec0c7)
1 /*
2  * Copyright 2018, Jérôme Duval, jerome.duval@gmail.com.
3  * Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
4  * Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de.
5  * Distributed under the terms of the MIT License.
6  *
7  * Copyright 2001, Travis Geiselbrecht. All rights reserved.
8  * Distributed under the terms of the NewOS License.
9  */
10 
11 /*!	Contains the ELF loader */
12 
13 
14 #include <elf.h>
15 
16 #include <OS.h>
17 
18 #include <unistd.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <stdio.h>
22 #include <ctype.h>
23 
24 #include <algorithm>
25 
26 #include <AutoDeleter.h>
27 #include <BytePointer.h>
28 #include <commpage.h>
29 #include <driver_settings.h>
30 #include <boot/kernel_args.h>
31 #include <debug.h>
32 #include <image_defs.h>
33 #include <kernel.h>
34 #include <kimage.h>
35 #include <syscalls.h>
36 #include <team.h>
37 #include <thread.h>
38 #include <runtime_loader.h>
39 #include <util/AutoLock.h>
40 #include <StackOrHeapArray.h>
41 #include <vfs.h>
42 #include <vm/vm.h>
43 #include <vm/vm_types.h>
44 #include <vm/VMAddressSpace.h>
45 #include <vm/VMArea.h>
46 
47 #include <arch/cpu.h>
48 #include <arch/elf.h>
49 #include <elf_priv.h>
50 #include <boot/elf.h>
51 
52 //#define TRACE_ELF
53 #ifdef TRACE_ELF
54 #	define TRACE(x) dprintf x
55 #else
56 #	define TRACE(x) ;
57 #endif
58 
59 
60 namespace {
61 
62 #define IMAGE_HASH_SIZE 16
63 
64 struct ImageHashDefinition {
65 	typedef struct elf_image_info ValueType;
66 	typedef image_id KeyType;
67 
68 	size_t Hash(ValueType* entry) const
69 		{ return HashKey(entry->id); }
70 	ValueType*& GetLink(ValueType* entry) const
71 		{ return entry->next; }
72 
73 	size_t HashKey(KeyType key) const
74 	{
75 		return (size_t)key;
76 	}
77 
78 	bool Compare(KeyType key, ValueType* entry) const
79 	{
80 		return key == entry->id;
81 	}
82 };
83 
84 typedef BOpenHashTable<ImageHashDefinition> ImageHash;
85 
86 } // namespace
87 
88 
89 #ifndef ELF32_COMPAT
90 
91 static ImageHash *sImagesHash;
92 
93 static struct elf_image_info *sKernelImage = NULL;
94 static mutex sImageMutex = MUTEX_INITIALIZER("kimages_lock");
95 	// guards sImagesHash
96 static mutex sImageLoadMutex = MUTEX_INITIALIZER("kimages_load_lock");
97 	// serializes loading/unloading add-ons locking order
98 	// sImageLoadMutex -> sImageMutex
99 static bool sLoadElfSymbols = false;
100 static bool sInitialized = false;
101 
102 
103 static elf_sym *elf_find_symbol(struct elf_image_info *image, const char *name,
104 	const elf_version_info *version, bool lookupDefault);
105 
106 
107 static void
108 unregister_elf_image(struct elf_image_info *image)
109 {
110 	unregister_image(team_get_kernel_team(), image->id);
111 	sImagesHash->Remove(image);
112 }
113 
114 
115 static void
116 register_elf_image(struct elf_image_info *image)
117 {
118 	extended_image_info imageInfo;
119 
120 	memset(&imageInfo, 0, sizeof(imageInfo));
121 	imageInfo.basic_info.id = image->id;
122 	imageInfo.basic_info.type = B_SYSTEM_IMAGE;
123 	strlcpy(imageInfo.basic_info.name, image->name,
124 		sizeof(imageInfo.basic_info.name));
125 
126 	imageInfo.basic_info.text = (void *)image->text_region.start;
127 	imageInfo.basic_info.text_size = image->text_region.size;
128 	imageInfo.basic_info.data = (void *)image->data_region.start;
129 	imageInfo.basic_info.data_size = image->data_region.size;
130 
131 	if (image->text_region.id >= 0) {
132 		// evaluate the API/ABI version symbols
133 
134 		// Haiku API version
135 		imageInfo.basic_info.api_version = 0;
136 		elf_sym* symbol = elf_find_symbol(image,
137 			B_SHARED_OBJECT_HAIKU_VERSION_VARIABLE_NAME, NULL, true);
138 		if (symbol != NULL && symbol->st_shndx != SHN_UNDEF
139 			&& symbol->st_value > 0
140 			&& symbol->Type() == STT_OBJECT
141 			&& symbol->st_size >= sizeof(uint32)) {
142 			addr_t symbolAddress = symbol->st_value + image->text_region.delta;
143 			if (symbolAddress >= image->text_region.start
144 				&& symbolAddress - image->text_region.start + sizeof(uint32)
145 					<= image->text_region.size) {
146 				imageInfo.basic_info.api_version = *(uint32*)symbolAddress;
147 			}
148 		}
149 
150 		// Haiku ABI
151 		imageInfo.basic_info.abi = 0;
152 		symbol = elf_find_symbol(image,
153 			B_SHARED_OBJECT_HAIKU_ABI_VARIABLE_NAME, NULL, true);
154 		if (symbol != NULL && symbol->st_shndx != SHN_UNDEF
155 			&& symbol->st_value > 0
156 			&& symbol->Type() == STT_OBJECT
157 			&& symbol->st_size >= sizeof(uint32)) {
158 			addr_t symbolAddress = symbol->st_value + image->text_region.delta;
159 			if (symbolAddress >= image->text_region.start
160 				&& symbolAddress - image->text_region.start + sizeof(uint32)
161 					<= image->text_region.size) {
162 				imageInfo.basic_info.api_version = *(uint32*)symbolAddress;
163 			}
164 		}
165 	} else {
166 		// in-memory image -- use the current values
167 		imageInfo.basic_info.api_version = B_HAIKU_VERSION;
168 		imageInfo.basic_info.abi = B_HAIKU_ABI;
169 	}
170 
171 	image->id = register_image(team_get_kernel_team(), &imageInfo,
172 		sizeof(imageInfo));
173 	sImagesHash->Insert(image);
174 }
175 
176 
177 /*!	Note, you must lock the image mutex when you call this function. */
178 static struct elf_image_info *
179 find_image_at_address(addr_t address)
180 {
181 #if KDEBUG
182 	if (!debug_debugger_running())
183 		ASSERT_LOCKED_MUTEX(&sImageMutex);
184 #endif
185 
186 	ImageHash::Iterator iterator(sImagesHash);
187 
188 	// get image that may contain the address
189 
190 	while (iterator.HasNext()) {
191 		struct elf_image_info* image = iterator.Next();
192 		if ((address >= image->text_region.start && address
193 				<= (image->text_region.start + image->text_region.size))
194 			|| (address >= image->data_region.start
195 				&& address
196 					<= (image->data_region.start + image->data_region.size)))
197 			return image;
198 	}
199 
200 	return NULL;
201 }
202 
203 
204 static int
205 dump_address_info(int argc, char **argv)
206 {
207 	const char *symbol, *imageName;
208 	bool exactMatch;
209 	addr_t address, baseAddress;
210 
211 	if (argc < 2) {
212 		kprintf("usage: ls <address>\n");
213 		return 0;
214 	}
215 
216 	address = strtoul(argv[1], NULL, 16);
217 
218 	status_t error;
219 
220 	if (IS_KERNEL_ADDRESS(address)) {
221 		error = elf_debug_lookup_symbol_address(address, &baseAddress, &symbol,
222 			&imageName, &exactMatch);
223 	} else {
224 		error = elf_debug_lookup_user_symbol_address(
225 			debug_get_debugged_thread()->team, address, &baseAddress, &symbol,
226 			&imageName, &exactMatch);
227 	}
228 
229 	if (error == B_OK) {
230 		kprintf("%p = %s + 0x%lx (%s)%s\n", (void*)address, symbol,
231 			address - baseAddress, imageName, exactMatch ? "" : " (nearest)");
232 	} else
233 		kprintf("There is no image loaded at this address!\n");
234 
235 	return 0;
236 }
237 
238 
239 static struct elf_image_info *
240 find_image(image_id id)
241 {
242 	return sImagesHash->Lookup(id);
243 }
244 
245 
246 static struct elf_image_info *
247 find_image_by_vnode(void *vnode)
248 {
249 	MutexLocker locker(sImageMutex);
250 
251 	ImageHash::Iterator iterator(sImagesHash);
252 	while (iterator.HasNext()) {
253 		struct elf_image_info* image = iterator.Next();
254 		if (image->vnode == vnode)
255 			return image;
256 	}
257 
258 	return NULL;
259 }
260 
261 
262 #endif // ELF32_COMPAT
263 
264 
265 static struct elf_image_info *
266 create_image_struct()
267 {
268 	struct elf_image_info *image
269 		= (struct elf_image_info *)malloc(sizeof(struct elf_image_info));
270 	if (image == NULL)
271 		return NULL;
272 
273 	memset(image, 0, sizeof(struct elf_image_info));
274 
275 	image->text_region.id = -1;
276 	image->data_region.id = -1;
277 	image->ref_count = 1;
278 
279 	return image;
280 }
281 
282 
283 static void
284 delete_elf_image(struct elf_image_info *image)
285 {
286 	if (image->text_region.id >= 0)
287 		delete_area(image->text_region.id);
288 
289 	if (image->data_region.id >= 0)
290 		delete_area(image->data_region.id);
291 
292 	if (image->vnode)
293 		vfs_put_vnode(image->vnode);
294 
295 	free(image->versions);
296 	free(image->debug_symbols);
297 	free((void*)image->debug_string_table);
298 	free(image->elf_header);
299 	free(image->name);
300 	free(image);
301 }
302 
303 
304 static const char *
305 get_symbol_type_string(elf_sym *symbol)
306 {
307 	switch (symbol->Type()) {
308 		case STT_FUNC:
309 			return "func";
310 		case STT_OBJECT:
311 			return " obj";
312 		case STT_FILE:
313 			return "file";
314 		default:
315 			return "----";
316 	}
317 }
318 
319 
320 static const char *
321 get_symbol_bind_string(elf_sym *symbol)
322 {
323 	switch (symbol->Bind()) {
324 		case STB_LOCAL:
325 			return "loc ";
326 		case STB_GLOBAL:
327 			return "glob";
328 		case STB_WEAK:
329 			return "weak";
330 		default:
331 			return "----";
332 	}
333 }
334 
335 
336 #ifndef ELF32_COMPAT
337 
338 
339 /*!	Searches a symbol (pattern) in all kernel images */
340 static int
341 dump_symbol(int argc, char **argv)
342 {
343 	if (argc != 2 || !strcmp(argv[1], "--help")) {
344 		kprintf("usage: %s <symbol-name>\n", argv[0]);
345 		return 0;
346 	}
347 
348 	struct elf_image_info *image = NULL;
349 	const char *pattern = argv[1];
350 
351 	void* symbolAddress = NULL;
352 
353 	ImageHash::Iterator iterator(sImagesHash);
354 	while (iterator.HasNext()) {
355 		image = iterator.Next();
356 		if (image->num_debug_symbols > 0) {
357 			// search extended debug symbol table (contains static symbols)
358 			for (uint32 i = 0; i < image->num_debug_symbols; i++) {
359 				elf_sym *symbol = &image->debug_symbols[i];
360 				const char *name = image->debug_string_table + symbol->st_name;
361 
362 				if (symbol->st_value > 0 && strstr(name, pattern) != 0) {
363 					symbolAddress
364 						= (void*)(symbol->st_value + image->text_region.delta);
365 					kprintf("%p %5lu %s:%s\n", symbolAddress, symbol->st_size,
366 						image->name, name);
367 				}
368 			}
369 		} else {
370 			// search standard symbol lookup table
371 			for (uint32 i = 0; i < HASHTABSIZE(image); i++) {
372 				for (uint32 j = HASHBUCKETS(image)[i]; j != STN_UNDEF;
373 						j = HASHCHAINS(image)[j]) {
374 					elf_sym *symbol = &image->syms[j];
375 					const char *name = SYMNAME(image, symbol);
376 
377 					if (symbol->st_value > 0 && strstr(name, pattern) != 0) {
378 						symbolAddress = (void*)(symbol->st_value
379 							+ image->text_region.delta);
380 						kprintf("%p %5lu %s:%s\n", symbolAddress,
381 							symbol->st_size, image->name, name);
382 					}
383 				}
384 			}
385 		}
386 	}
387 
388 	if (symbolAddress != NULL)
389 		set_debug_variable("_", (addr_t)symbolAddress);
390 
391 	return 0;
392 }
393 
394 
395 static int
396 dump_symbols(int argc, char **argv)
397 {
398 	struct elf_image_info *image = NULL;
399 	uint32 i;
400 
401 	// if the argument looks like a hex number, treat it as such
402 	if (argc > 1) {
403 		if (isdigit(argv[1][0])) {
404 			addr_t num = strtoul(argv[1], NULL, 0);
405 
406 			if (IS_KERNEL_ADDRESS(num)) {
407 				// find image at address
408 
409 				ImageHash::Iterator iterator(sImagesHash);
410 				while (iterator.HasNext()) {
411 					elf_image_info* current = iterator.Next();
412 					if (current->text_region.start <= num
413 						&& current->text_region.start
414 							+ current->text_region.size	>= num) {
415 						image = current;
416 						break;
417 					}
418 				}
419 
420 				if (image == NULL) {
421 					kprintf("No image covers %#" B_PRIxADDR " in the kernel!\n",
422 						num);
423 				}
424 			} else {
425 				image = sImagesHash->Lookup(num);
426 				if (image == NULL) {
427 					kprintf("image %#" B_PRIxADDR " doesn't exist in the "
428 						"kernel!\n", num);
429 				}
430 			}
431 		} else {
432 			// look for image by name
433 			ImageHash::Iterator iterator(sImagesHash);
434 			while (iterator.HasNext()) {
435 				elf_image_info* current = iterator.Next();
436 				if (!strcmp(current->name, argv[1])) {
437 					image = current;
438 					break;
439 				}
440 			}
441 
442 			if (image == NULL)
443 				kprintf("No image \"%s\" found in kernel!\n", argv[1]);
444 		}
445 	} else {
446 		kprintf("usage: %s image_name/image_id/address_in_image\n", argv[0]);
447 		return 0;
448 	}
449 
450 	if (image == NULL)
451 		return -1;
452 
453 	// dump symbols
454 
455 	kprintf("Symbols of image %" B_PRId32 " \"%s\":\n", image->id, image->name);
456 	kprintf("%-*s Type       Size Name\n", B_PRINTF_POINTER_WIDTH, "Address");
457 
458 	if (image->num_debug_symbols > 0) {
459 		// search extended debug symbol table (contains static symbols)
460 		for (i = 0; i < image->num_debug_symbols; i++) {
461 			elf_sym *symbol = &image->debug_symbols[i];
462 
463 			if (symbol->st_value == 0 || symbol->st_size
464 					>= image->text_region.size + image->data_region.size)
465 				continue;
466 
467 			kprintf("%0*lx %s/%s %5ld %s\n", B_PRINTF_POINTER_WIDTH,
468 				symbol->st_value + image->text_region.delta,
469 				get_symbol_type_string(symbol), get_symbol_bind_string(symbol),
470 				symbol->st_size, image->debug_string_table + symbol->st_name);
471 		}
472 	} else {
473 		int32 j;
474 
475 		// search standard symbol lookup table
476 		for (i = 0; i < HASHTABSIZE(image); i++) {
477 			for (j = HASHBUCKETS(image)[i]; j != STN_UNDEF;
478 					j = HASHCHAINS(image)[j]) {
479 				elf_sym *symbol = &image->syms[j];
480 
481 				if (symbol->st_value == 0 || symbol->st_size
482 						>= image->text_region.size + image->data_region.size)
483 					continue;
484 
485 				kprintf("%08lx %s/%s %5ld %s\n",
486 					symbol->st_value + image->text_region.delta,
487 					get_symbol_type_string(symbol),
488 					get_symbol_bind_string(symbol),
489 					symbol->st_size, SYMNAME(image, symbol));
490 			}
491 		}
492 	}
493 
494 	return 0;
495 }
496 
497 
498 static void
499 dump_elf_region(struct elf_region *region, const char *name)
500 {
501 	kprintf("   %s.id %" B_PRId32 "\n", name, region->id);
502 	kprintf("   %s.start %#" B_PRIxADDR "\n", name, region->start);
503 	kprintf("   %s.size %#" B_PRIxSIZE "\n", name, region->size);
504 	kprintf("   %s.delta %ld\n", name, region->delta);
505 }
506 
507 
508 static void
509 dump_image_info(struct elf_image_info *image)
510 {
511 	kprintf("elf_image_info at %p:\n", image);
512 	kprintf(" next %p\n", image->next);
513 	kprintf(" id %" B_PRId32 "\n", image->id);
514 	dump_elf_region(&image->text_region, "text");
515 	dump_elf_region(&image->data_region, "data");
516 	kprintf(" dynamic_section %#" B_PRIxADDR "\n", image->dynamic_section);
517 	kprintf(" needed %p\n", image->needed);
518 	kprintf(" symhash %p\n", image->symhash);
519 	kprintf(" syms %p\n", image->syms);
520 	kprintf(" strtab %p\n", image->strtab);
521 	kprintf(" rel %p\n", image->rel);
522 	kprintf(" rel_len %#x\n", image->rel_len);
523 	kprintf(" rela %p\n", image->rela);
524 	kprintf(" rela_len %#x\n", image->rela_len);
525 	kprintf(" pltrel %p\n", image->pltrel);
526 	kprintf(" pltrel_len %#x\n", image->pltrel_len);
527 
528 	kprintf(" debug_symbols %p (%" B_PRIu32 ")\n",
529 		image->debug_symbols, image->num_debug_symbols);
530 }
531 
532 
533 static int
534 dump_image(int argc, char **argv)
535 {
536 	struct elf_image_info *image;
537 
538 	// if the argument looks like a hex number, treat it as such
539 	if (argc > 1) {
540 		addr_t num = strtoul(argv[1], NULL, 0);
541 
542 		if (IS_KERNEL_ADDRESS(num)) {
543 			// semi-hack
544 			dump_image_info((struct elf_image_info *)num);
545 		} else {
546 			image = sImagesHash->Lookup(num);
547 			if (image == NULL) {
548 				kprintf("image %#" B_PRIxADDR " doesn't exist in the kernel!\n",
549 					num);
550 			} else
551 				dump_image_info(image);
552 		}
553 		return 0;
554 	}
555 
556 	kprintf("loaded kernel images:\n");
557 
558 	ImageHash::Iterator iterator(sImagesHash);
559 
560 	while (iterator.HasNext()) {
561 		image = iterator.Next();
562 		kprintf("%p (%" B_PRId32 ") %s\n", image, image->id, image->name);
563 	}
564 
565 	return 0;
566 }
567 
568 
569 // Currently unused
570 /*static
571 void dump_symbol(struct elf_image_info *image, elf_sym *sym)
572 {
573 
574 	kprintf("symbol at %p, in image %p\n", sym, image);
575 
576 	kprintf(" name index %d, '%s'\n", sym->st_name, SYMNAME(image, sym));
577 	kprintf(" st_value 0x%x\n", sym->st_value);
578 	kprintf(" st_size %d\n", sym->st_size);
579 	kprintf(" st_info 0x%x\n", sym->st_info);
580 	kprintf(" st_other 0x%x\n", sym->st_other);
581 	kprintf(" st_shndx %d\n", sym->st_shndx);
582 }
583 */
584 
585 
586 #endif // ELF32_COMPAT
587 
588 
589 static uint32
590 elf_hash(const char* _name)
591 {
592 	const uint8* name = (const uint8*)_name;
593 
594 	uint32 h = 0;
595 	while (*name != '\0') {
596 		h = (h << 4) + *name++;
597 		h ^= (h >> 24) & 0xf0;
598 	}
599 	return (h & 0x0fffffff);
600 }
601 
602 
603 static elf_sym *
604 elf_find_symbol(struct elf_image_info *image, const char *name,
605 	const elf_version_info *lookupVersion, bool lookupDefault)
606 {
607 	if (image->dynamic_section == 0 || HASHTABSIZE(image) == 0)
608 		return NULL;
609 
610 	elf_sym* versionedSymbol = NULL;
611 	uint32 versionedSymbolCount = 0;
612 
613 	uint32 hash = elf_hash(name) % HASHTABSIZE(image);
614 	for (uint32 i = HASHBUCKETS(image)[hash]; i != STN_UNDEF;
615 			i = HASHCHAINS(image)[i]) {
616 		elf_sym* symbol = &image->syms[i];
617 
618 		// consider only symbols with the right name and binding
619 		if (symbol->st_shndx == SHN_UNDEF
620 			|| ((symbol->Bind() != STB_GLOBAL) && (symbol->Bind() != STB_WEAK))
621 			|| strcmp(SYMNAME(image, symbol), name) != 0) {
622 			continue;
623 		}
624 
625 		// check the version
626 
627 		// Handle the simple cases -- the image doesn't have version
628 		// information -- first.
629 		if (image->symbol_versions == NULL) {
630 			if (lookupVersion == NULL) {
631 				// No specific symbol version was requested either, so the
632 				// symbol is just fine.
633 				return symbol;
634 			}
635 
636 			// A specific version is requested. Since the only possible
637 			// dependency is the kernel itself, the add-on was obviously linked
638 			// against a newer kernel.
639 			dprintf("Kernel add-on requires version support, but the kernel "
640 				"is too old.\n");
641 			return NULL;
642 		}
643 
644 		// The image has version information. Let's see what we've got.
645 		uint32 versionID = image->symbol_versions[i];
646 		uint32 versionIndex = VER_NDX(versionID);
647 		elf_version_info& version = image->versions[versionIndex];
648 
649 		// skip local versions
650 		if (versionIndex == VER_NDX_LOCAL)
651 			continue;
652 
653 		if (lookupVersion != NULL) {
654 			// a specific version is requested
655 
656 			// compare the versions
657 			if (version.hash == lookupVersion->hash
658 				&& strcmp(version.name, lookupVersion->name) == 0) {
659 				// versions match
660 				return symbol;
661 			}
662 
663 			// The versions don't match. We're still fine with the
664 			// base version, if it is public and we're not looking for
665 			// the default version.
666 			if ((versionID & VER_NDX_FLAG_HIDDEN) == 0
667 				&& versionIndex == VER_NDX_GLOBAL
668 				&& !lookupDefault) {
669 				// TODO: Revise the default version case! That's how
670 				// FreeBSD implements it, but glibc doesn't handle it
671 				// specially.
672 				return symbol;
673 			}
674 		} else {
675 			// No specific version requested, but the image has version
676 			// information. This can happen in either of these cases:
677 			//
678 			// * The dependent object was linked against an older version
679 			//   of the now versioned dependency.
680 			// * The symbol is looked up via find_image_symbol() or dlsym().
681 			//
682 			// In the first case we return the base version of the symbol
683 			// (VER_NDX_GLOBAL or VER_NDX_INITIAL), or, if that doesn't
684 			// exist, the unique, non-hidden versioned symbol.
685 			//
686 			// In the second case we want to return the public default
687 			// version of the symbol. The handling is pretty similar to the
688 			// first case, with the exception that we treat VER_NDX_INITIAL
689 			// as regular version.
690 
691 			// VER_NDX_GLOBAL is always good, VER_NDX_INITIAL is fine, if
692 			// we don't look for the default version.
693 			if (versionIndex == VER_NDX_GLOBAL
694 				|| (!lookupDefault && versionIndex == VER_NDX_INITIAL)) {
695 				return symbol;
696 			}
697 
698 			// If not hidden, remember the version -- we'll return it, if
699 			// it is the only one.
700 			if ((versionID & VER_NDX_FLAG_HIDDEN) == 0) {
701 				versionedSymbolCount++;
702 				versionedSymbol = symbol;
703 			}
704 		}
705 	}
706 
707 	return versionedSymbolCount == 1 ? versionedSymbol : NULL;
708 }
709 
710 
711 static status_t
712 elf_parse_dynamic_section(struct elf_image_info *image)
713 {
714 	elf_dyn *d;
715 	ssize_t neededOffset = -1;
716 
717 	TRACE(("top of elf_parse_dynamic_section\n"));
718 
719 	image->symhash = 0;
720 	image->syms = 0;
721 	image->strtab = 0;
722 
723 	d = (elf_dyn *)image->dynamic_section;
724 	if (!d)
725 		return B_ERROR;
726 
727 	for (int32 i = 0; d[i].d_tag != DT_NULL; i++) {
728 		switch (d[i].d_tag) {
729 			case DT_NEEDED:
730 				neededOffset = d[i].d_un.d_ptr + image->text_region.delta;
731 				break;
732 			case DT_HASH:
733 				image->symhash = (uint32 *)(d[i].d_un.d_ptr
734 					+ image->text_region.delta);
735 				break;
736 			case DT_STRTAB:
737 				image->strtab = (char *)(d[i].d_un.d_ptr
738 					+ image->text_region.delta);
739 				break;
740 			case DT_SYMTAB:
741 				image->syms = (elf_sym *)(d[i].d_un.d_ptr
742 					+ image->text_region.delta);
743 				break;
744 			case DT_REL:
745 				image->rel = (elf_rel *)(d[i].d_un.d_ptr
746 					+ image->text_region.delta);
747 				break;
748 			case DT_RELSZ:
749 				image->rel_len = d[i].d_un.d_val;
750 				break;
751 			case DT_RELA:
752 				image->rela = (elf_rela *)(d[i].d_un.d_ptr
753 					+ image->text_region.delta);
754 				break;
755 			case DT_RELASZ:
756 				image->rela_len = d[i].d_un.d_val;
757 				break;
758 			case DT_JMPREL:
759 				image->pltrel = (elf_rel *)(d[i].d_un.d_ptr
760 					+ image->text_region.delta);
761 				break;
762 			case DT_PLTRELSZ:
763 				image->pltrel_len = d[i].d_un.d_val;
764 				break;
765 			case DT_PLTREL:
766 				image->pltrel_type = d[i].d_un.d_val;
767 				break;
768 			case DT_VERSYM:
769 				image->symbol_versions = (elf_versym*)
770 					(d[i].d_un.d_ptr + image->text_region.delta);
771 				break;
772 			case DT_VERDEF:
773 				image->version_definitions = (elf_verdef*)
774 					(d[i].d_un.d_ptr + image->text_region.delta);
775 				break;
776 			case DT_VERDEFNUM:
777 				image->num_version_definitions = d[i].d_un.d_val;
778 				break;
779 			case DT_VERNEED:
780 				image->needed_versions = (elf_verneed*)
781 					(d[i].d_un.d_ptr + image->text_region.delta);
782 				break;
783 			case DT_VERNEEDNUM:
784 				image->num_needed_versions = d[i].d_un.d_val;
785 				break;
786 			case DT_SYMBOLIC:
787 				image->symbolic = true;
788 				break;
789 			case DT_FLAGS:
790 			{
791 				uint32 flags = d[i].d_un.d_val;
792 				if ((flags & DF_SYMBOLIC) != 0)
793 					image->symbolic = true;
794 				break;
795 			}
796 
797 			default:
798 				continue;
799 		}
800 	}
801 
802 	// lets make sure we found all the required sections
803 	if (!image->symhash || !image->syms || !image->strtab)
804 		return B_ERROR;
805 
806 	TRACE(("needed_offset = %ld\n", neededOffset));
807 
808 	if (neededOffset >= 0)
809 		image->needed = STRING(image, neededOffset);
810 
811 	return B_OK;
812 }
813 
814 
815 #ifndef ELF32_COMPAT
816 
817 
818 static status_t
819 assert_defined_image_version(elf_image_info* dependentImage,
820 	elf_image_info* image, const elf_version_info& neededVersion, bool weak)
821 {
822 	// If the image doesn't have version definitions, we print a warning and
823 	// succeed. Weird, but that's how glibc does it. Not unlikely we'll fail
824 	// later when resolving versioned symbols.
825 	if (image->version_definitions == NULL) {
826 		dprintf("%s: No version information available (required by %s)\n",
827 			image->name, dependentImage->name);
828 		return B_OK;
829 	}
830 
831 	// iterate through the defined versions to find the given one
832 	BytePointer<elf_verdef> definition(image->version_definitions);
833 	for (uint32 i = 0; i < image->num_version_definitions; i++) {
834 		uint32 versionIndex = VER_NDX(definition->vd_ndx);
835 		elf_version_info& info = image->versions[versionIndex];
836 
837 		if (neededVersion.hash == info.hash
838 			&& strcmp(neededVersion.name, info.name) == 0) {
839 			return B_OK;
840 		}
841 
842 		definition += definition->vd_next;
843 	}
844 
845 	// version not found -- fail, if not weak
846 	if (!weak) {
847 		dprintf("%s: version \"%s\" not found (required by %s)\n", image->name,
848 			neededVersion.name, dependentImage->name);
849 		return B_MISSING_SYMBOL;
850 	}
851 
852 	return B_OK;
853 }
854 
855 
856 static status_t
857 init_image_version_infos(elf_image_info* image)
858 {
859 	// First find out how many version infos we need -- i.e. get the greatest
860 	// version index from the defined and needed versions (they use the same
861 	// index namespace).
862 	uint32 maxIndex = 0;
863 
864 	if (image->version_definitions != NULL) {
865 		BytePointer<elf_verdef> definition(image->version_definitions);
866 		for (uint32 i = 0; i < image->num_version_definitions; i++) {
867 			if (definition->vd_version != 1) {
868 				dprintf("Unsupported version definition revision: %u\n",
869 					definition->vd_version);
870 				return B_BAD_VALUE;
871 			}
872 
873 			uint32 versionIndex = VER_NDX(definition->vd_ndx);
874 			if (versionIndex > maxIndex)
875 				maxIndex = versionIndex;
876 
877 			definition += definition->vd_next;
878 		}
879 	}
880 
881 	if (image->needed_versions != NULL) {
882 		BytePointer<elf_verneed> needed(image->needed_versions);
883 		for (uint32 i = 0; i < image->num_needed_versions; i++) {
884 			if (needed->vn_version != 1) {
885 				dprintf("Unsupported version needed revision: %u\n",
886 					needed->vn_version);
887 				return B_BAD_VALUE;
888 			}
889 
890 			BytePointer<elf_vernaux> vernaux(needed + needed->vn_aux);
891 			for (uint32 k = 0; k < needed->vn_cnt; k++) {
892 				uint32 versionIndex = VER_NDX(vernaux->vna_other);
893 				if (versionIndex > maxIndex)
894 					maxIndex = versionIndex;
895 
896 				vernaux += vernaux->vna_next;
897 			}
898 
899 			needed += needed->vn_next;
900 		}
901 	}
902 
903 	if (maxIndex == 0)
904 		return B_OK;
905 
906 	// allocate the version infos
907 	image->versions
908 		= (elf_version_info*)malloc(sizeof(elf_version_info) * (maxIndex + 1));
909 	if (image->versions == NULL) {
910 		dprintf("Memory shortage in init_image_version_infos()\n");
911 		return B_NO_MEMORY;
912 	}
913 	image->num_versions = maxIndex + 1;
914 
915 	// init the version infos
916 
917 	// version definitions
918 	if (image->version_definitions != NULL) {
919 		BytePointer<elf_verdef> definition(image->version_definitions);
920 		for (uint32 i = 0; i < image->num_version_definitions; i++) {
921 			if (definition->vd_cnt > 0
922 				&& (definition->vd_flags & VER_FLG_BASE) == 0) {
923 				BytePointer<elf_verdaux> verdaux(definition
924 					+ definition->vd_aux);
925 
926 				uint32 versionIndex = VER_NDX(definition->vd_ndx);
927 				elf_version_info& info = image->versions[versionIndex];
928 				info.hash = definition->vd_hash;
929 				info.name = STRING(image, verdaux->vda_name);
930 				info.file_name = NULL;
931 			}
932 
933 			definition += definition->vd_next;
934 		}
935 	}
936 
937 	// needed versions
938 	if (image->needed_versions != NULL) {
939 		BytePointer<elf_verneed> needed(image->needed_versions);
940 		for (uint32 i = 0; i < image->num_needed_versions; i++) {
941 			const char* fileName = STRING(image, needed->vn_file);
942 
943 			BytePointer<elf_vernaux> vernaux(needed + needed->vn_aux);
944 			for (uint32 k = 0; k < needed->vn_cnt; k++) {
945 				uint32 versionIndex = VER_NDX(vernaux->vna_other);
946 				elf_version_info& info = image->versions[versionIndex];
947 				info.hash = vernaux->vna_hash;
948 				info.name = STRING(image, vernaux->vna_name);
949 				info.file_name = fileName;
950 
951 				vernaux += vernaux->vna_next;
952 			}
953 
954 			needed += needed->vn_next;
955 		}
956 	}
957 
958 	return B_OK;
959 }
960 
961 
962 static status_t
963 check_needed_image_versions(elf_image_info* image)
964 {
965 	if (image->needed_versions == NULL)
966 		return B_OK;
967 
968 	BytePointer<elf_verneed> needed(image->needed_versions);
969 	for (uint32 i = 0; i < image->num_needed_versions; i++) {
970 		elf_image_info* dependency = sKernelImage;
971 
972 		BytePointer<elf_vernaux> vernaux(needed + needed->vn_aux);
973 		for (uint32 k = 0; k < needed->vn_cnt; k++) {
974 			uint32 versionIndex = VER_NDX(vernaux->vna_other);
975 			elf_version_info& info = image->versions[versionIndex];
976 
977 			status_t error = assert_defined_image_version(image, dependency,
978 				info, (vernaux->vna_flags & VER_FLG_WEAK) != 0);
979 			if (error != B_OK)
980 				return error;
981 
982 			vernaux += vernaux->vna_next;
983 		}
984 
985 		needed += needed->vn_next;
986 	}
987 
988 	return B_OK;
989 }
990 
991 
992 #endif // ELF32_COMPAT
993 
994 
995 /*!	Resolves the \a symbol by linking against \a sharedImage if necessary.
996 	Returns the resolved symbol's address in \a _symbolAddress.
997 */
998 status_t
999 elf_resolve_symbol(struct elf_image_info *image, elf_sym *symbol,
1000 	struct elf_image_info *sharedImage, elf_addr *_symbolAddress)
1001 {
1002 	// Local symbols references are always resolved to the given symbol.
1003 	if (symbol->Bind() == STB_LOCAL) {
1004 		*_symbolAddress = symbol->st_value + image->text_region.delta;
1005 		return B_OK;
1006 	}
1007 
1008 	// Non-local symbols we try to resolve to the kernel image first. Unless
1009 	// the image is linked symbolically, then vice versa.
1010 	elf_image_info* firstImage = sharedImage;
1011 	elf_image_info* secondImage = image;
1012 	if (image->symbolic)
1013 		std::swap(firstImage, secondImage);
1014 
1015 	const char *symbolName = SYMNAME(image, symbol);
1016 
1017 	// get the version info
1018 	const elf_version_info* versionInfo = NULL;
1019 	if (image->symbol_versions != NULL) {
1020 		uint32 index = symbol - image->syms;
1021 		uint32 versionIndex = VER_NDX(image->symbol_versions[index]);
1022 		if (versionIndex >= VER_NDX_INITIAL)
1023 			versionInfo = image->versions + versionIndex;
1024 	}
1025 
1026 	// find the symbol
1027 	elf_image_info* foundImage = firstImage;
1028 	elf_sym* foundSymbol = elf_find_symbol(firstImage, symbolName, versionInfo,
1029 		false);
1030 	if (foundSymbol == NULL
1031 		|| foundSymbol->Bind() == STB_WEAK) {
1032 		// Not found or found a weak definition -- try to resolve in the other
1033 		// image.
1034 		elf_sym* secondSymbol = elf_find_symbol(secondImage, symbolName,
1035 			versionInfo, false);
1036 		// If we found a symbol -- take it in case we didn't have a symbol
1037 		// before or the new symbol is not weak.
1038 		if (secondSymbol != NULL
1039 			&& (foundSymbol == NULL
1040 				|| secondSymbol->Bind() != STB_WEAK)) {
1041 			foundImage = secondImage;
1042 			foundSymbol = secondSymbol;
1043 		}
1044 	}
1045 
1046 	if (foundSymbol == NULL) {
1047 		// Weak undefined symbols get a value of 0, if unresolved.
1048 		if (symbol->Bind() == STB_WEAK) {
1049 			*_symbolAddress = 0;
1050 			return B_OK;
1051 		}
1052 
1053 		dprintf("\"%s\": could not resolve symbol '%s'\n", image->name,
1054 			symbolName);
1055 		return B_MISSING_SYMBOL;
1056 	}
1057 
1058 	// make sure they're the same type
1059 	if (symbol->Type() != foundSymbol->Type()) {
1060 		dprintf("elf_resolve_symbol: found symbol '%s' in image '%s' "
1061 			"(requested by image '%s') but wrong type (%d vs. %d)\n",
1062 			symbolName, foundImage->name, image->name,
1063 			foundSymbol->Type(), symbol->Type());
1064 		return B_MISSING_SYMBOL;
1065 	}
1066 
1067 	*_symbolAddress = foundSymbol->st_value + foundImage->text_region.delta;
1068 	return B_OK;
1069 }
1070 
1071 
1072 /*! Until we have shared library support, just this links against the kernel */
1073 static int
1074 elf_relocate(struct elf_image_info* image, struct elf_image_info* resolveImage)
1075 {
1076 	int status = B_NO_ERROR;
1077 
1078 	TRACE(("elf_relocate(%p (\"%s\"))\n", image, image->name));
1079 
1080 	// deal with the rels first
1081 	if (image->rel) {
1082 		TRACE(("total %i rel relocs\n", image->rel_len / (int)sizeof(elf_rel)));
1083 
1084 		status = arch_elf_relocate_rel(image, resolveImage, image->rel,
1085 			image->rel_len);
1086 		if (status < B_OK)
1087 			return status;
1088 	}
1089 
1090 	if (image->pltrel) {
1091 		if (image->pltrel_type == DT_REL) {
1092 			TRACE(("total %i plt-relocs\n",
1093 				image->pltrel_len / (int)sizeof(elf_rel)));
1094 			status = arch_elf_relocate_rel(image, resolveImage, image->pltrel,
1095 				image->pltrel_len);
1096 		} else {
1097 			TRACE(("total %i plt-relocs\n",
1098 				image->pltrel_len / (int)sizeof(elf_rela)));
1099 			status = arch_elf_relocate_rela(image, resolveImage,
1100 				(elf_rela *)image->pltrel, image->pltrel_len);
1101 		}
1102 		if (status < B_OK)
1103 			return status;
1104 	}
1105 
1106 	if (image->rela) {
1107 		TRACE(("total %i rel relocs\n",
1108 			image->rela_len / (int)sizeof(elf_rela)));
1109 
1110 		status = arch_elf_relocate_rela(image, resolveImage, image->rela,
1111 			image->rela_len);
1112 		if (status < B_OK)
1113 			return status;
1114 	}
1115 
1116 	return status;
1117 }
1118 
1119 
1120 static int
1121 verify_eheader(elf_ehdr *elfHeader)
1122 {
1123 	if (memcmp(elfHeader->e_ident, ELFMAG, 4) != 0)
1124 		return B_NOT_AN_EXECUTABLE;
1125 
1126 	if (elfHeader->e_ident[4] != ELF_CLASS)
1127 		return B_NOT_AN_EXECUTABLE;
1128 
1129 	if (elfHeader->e_phoff == 0)
1130 		return B_NOT_AN_EXECUTABLE;
1131 
1132 	if (elfHeader->e_phentsize < sizeof(elf_phdr))
1133 		return B_NOT_AN_EXECUTABLE;
1134 
1135 	return 0;
1136 }
1137 
1138 
1139 #ifndef ELF32_COMPAT
1140 
1141 
1142 static void
1143 unload_elf_image(struct elf_image_info *image)
1144 {
1145 	if (atomic_add(&image->ref_count, -1) > 1)
1146 		return;
1147 
1148 	TRACE(("unload image %" B_PRId32 ", %s\n", image->id, image->name));
1149 
1150 	unregister_elf_image(image);
1151 	delete_elf_image(image);
1152 }
1153 
1154 
1155 static status_t
1156 load_elf_symbol_table(int fd, struct elf_image_info *image)
1157 {
1158 	elf_ehdr *elfHeader = image->elf_header;
1159 	elf_sym *symbolTable = NULL;
1160 	elf_shdr *stringHeader = NULL;
1161 	uint32 numSymbols = 0;
1162 	char *stringTable;
1163 	status_t status;
1164 	ssize_t length;
1165 	int32 i;
1166 
1167 	// get section headers
1168 
1169 	ssize_t size = elfHeader->e_shnum * elfHeader->e_shentsize;
1170 	elf_shdr *sectionHeaders = (elf_shdr *)malloc(size);
1171 	if (sectionHeaders == NULL) {
1172 		dprintf("error allocating space for section headers\n");
1173 		return B_NO_MEMORY;
1174 	}
1175 
1176 	length = read_pos(fd, elfHeader->e_shoff, sectionHeaders, size);
1177 	if (length < size) {
1178 		TRACE(("error reading in program headers\n"));
1179 		status = B_ERROR;
1180 		goto error1;
1181 	}
1182 
1183 	// find symbol table in section headers
1184 
1185 	for (i = 0; i < elfHeader->e_shnum; i++) {
1186 		if (sectionHeaders[i].sh_type == SHT_SYMTAB) {
1187 			stringHeader = &sectionHeaders[sectionHeaders[i].sh_link];
1188 
1189 			if (stringHeader->sh_type != SHT_STRTAB) {
1190 				TRACE(("doesn't link to string table\n"));
1191 				status = B_BAD_DATA;
1192 				goto error1;
1193 			}
1194 
1195 			// read in symbol table
1196 			size = sectionHeaders[i].sh_size;
1197 			symbolTable = (elf_sym *)malloc(size);
1198 			if (symbolTable == NULL) {
1199 				status = B_NO_MEMORY;
1200 				goto error1;
1201 			}
1202 
1203 			length
1204 				= read_pos(fd, sectionHeaders[i].sh_offset, symbolTable, size);
1205 			if (length < size) {
1206 				TRACE(("error reading in symbol table\n"));
1207 				status = B_ERROR;
1208 				goto error2;
1209 			}
1210 
1211 			numSymbols = size / sizeof(elf_sym);
1212 			break;
1213 		}
1214 	}
1215 
1216 	if (symbolTable == NULL) {
1217 		TRACE(("no symbol table\n"));
1218 		status = B_BAD_VALUE;
1219 		goto error1;
1220 	}
1221 
1222 	// read in string table
1223 
1224 	stringTable = (char *)malloc(size = stringHeader->sh_size);
1225 	if (stringTable == NULL) {
1226 		status = B_NO_MEMORY;
1227 		goto error2;
1228 	}
1229 
1230 	length = read_pos(fd, stringHeader->sh_offset, stringTable, size);
1231 	if (length < size) {
1232 		TRACE(("error reading in string table\n"));
1233 		status = B_ERROR;
1234 		goto error3;
1235 	}
1236 
1237 	TRACE(("loaded %" B_PRId32 " debug symbols\n", numSymbols));
1238 
1239 	// insert tables into image
1240 	image->debug_symbols = symbolTable;
1241 	image->num_debug_symbols = numSymbols;
1242 	image->debug_string_table = stringTable;
1243 
1244 	free(sectionHeaders);
1245 	return B_OK;
1246 
1247 error3:
1248 	free(stringTable);
1249 error2:
1250 	free(symbolTable);
1251 error1:
1252 	free(sectionHeaders);
1253 
1254 	return status;
1255 }
1256 
1257 
1258 static status_t
1259 insert_preloaded_image(preloaded_elf_image *preloadedImage, bool kernel)
1260 {
1261 	status_t status;
1262 
1263 	status = verify_eheader(&preloadedImage->elf_header);
1264 	if (status != B_OK)
1265 		return status;
1266 
1267 	elf_image_info *image = create_image_struct();
1268 	if (image == NULL)
1269 		return B_NO_MEMORY;
1270 
1271 	image->name = strdup(preloadedImage->name);
1272 	image->dynamic_section = preloadedImage->dynamic_section.start;
1273 
1274 	image->text_region.id = preloadedImage->text_region.id;
1275 	image->text_region.start = preloadedImage->text_region.start;
1276 	image->text_region.size = preloadedImage->text_region.size;
1277 	image->text_region.delta = preloadedImage->text_region.delta;
1278 	image->data_region.id = preloadedImage->data_region.id;
1279 	image->data_region.start = preloadedImage->data_region.start;
1280 	image->data_region.size = preloadedImage->data_region.size;
1281 	image->data_region.delta = preloadedImage->data_region.delta;
1282 
1283 	status = elf_parse_dynamic_section(image);
1284 	if (status != B_OK)
1285 		goto error1;
1286 
1287 	status = init_image_version_infos(image);
1288 	if (status != B_OK)
1289 		goto error1;
1290 
1291 	if (!kernel) {
1292 		status = check_needed_image_versions(image);
1293 		if (status != B_OK)
1294 			goto error1;
1295 
1296 		status = elf_relocate(image, sKernelImage);
1297 		if (status != B_OK)
1298 			goto error1;
1299 	} else
1300 		sKernelImage = image;
1301 
1302 	// copy debug symbols to the kernel heap
1303 	if (preloadedImage->debug_symbols != NULL) {
1304 		int32 debugSymbolsSize = sizeof(elf_sym)
1305 			* preloadedImage->num_debug_symbols;
1306 		image->debug_symbols = (elf_sym*)malloc(debugSymbolsSize);
1307 		if (image->debug_symbols != NULL) {
1308 			memcpy(image->debug_symbols, preloadedImage->debug_symbols,
1309 				debugSymbolsSize);
1310 		}
1311 	}
1312 	image->num_debug_symbols = preloadedImage->num_debug_symbols;
1313 
1314 	// copy debug string table to the kernel heap
1315 	if (preloadedImage->debug_string_table != NULL) {
1316 		image->debug_string_table = (char*)malloc(
1317 			preloadedImage->debug_string_table_size);
1318 		if (image->debug_string_table != NULL) {
1319 			memcpy((void*)image->debug_string_table,
1320 				preloadedImage->debug_string_table,
1321 				preloadedImage->debug_string_table_size);
1322 		}
1323 	}
1324 
1325 	register_elf_image(image);
1326 	preloadedImage->id = image->id;
1327 		// modules_init() uses this information to get the preloaded images
1328 
1329 	// we now no longer need to write to the text area anymore
1330 	set_area_protection(image->text_region.id,
1331 		B_KERNEL_READ_AREA | B_KERNEL_EXECUTE_AREA);
1332 
1333 	return B_OK;
1334 
1335 error1:
1336 	delete_elf_image(image);
1337 
1338 	preloadedImage->id = -1;
1339 
1340 	return status;
1341 }
1342 
1343 
1344 //	#pragma mark - userland symbol lookup
1345 
1346 
1347 class UserSymbolLookup {
1348 public:
1349 	static UserSymbolLookup& Default()
1350 	{
1351 		return sLookup;
1352 	}
1353 
1354 	status_t Init(Team* team)
1355 	{
1356 		// find the runtime loader debug area
1357 		VMArea* area;
1358 		for (VMAddressSpace::AreaIterator it
1359 					= team->address_space->GetAreaIterator();
1360 				(area = it.Next()) != NULL;) {
1361 			if (strcmp(area->name, RUNTIME_LOADER_DEBUG_AREA_NAME) == 0)
1362 				break;
1363 		}
1364 
1365 		if (area == NULL)
1366 			return B_ERROR;
1367 
1368 		// copy the runtime loader data structure
1369 		if (!_Read((runtime_loader_debug_area*)area->Base(), fDebugArea))
1370 			return B_BAD_ADDRESS;
1371 
1372 		fTeam = team;
1373 		return B_OK;
1374 	}
1375 
1376 	status_t LookupSymbolAddress(addr_t address, addr_t *_baseAddress,
1377 		const char **_symbolName, const char **_imageName, bool *_exactMatch)
1378 	{
1379 		// Note, that this function doesn't find all symbols that we would like
1380 		// to find. E.g. static functions do not appear in the symbol table
1381 		// as function symbols, but as sections without name and size. The
1382 		// .symtab section together with the .strtab section, which apparently
1383 		// differ from the tables referred to by the .dynamic section, also
1384 		// contain proper names and sizes for those symbols. Therefore, to get
1385 		// completely satisfying results, we would need to read those tables
1386 		// from the shared object.
1387 
1388 		// get the image for the address
1389 		image_t image;
1390 		status_t error = _FindImageAtAddress(address, image);
1391 		if (error != B_OK) {
1392 			// commpage requires special treatment since kernel stores symbol
1393 			// information
1394 			addr_t commPageAddress = (addr_t)fTeam->commpage_address;
1395 			if (address >= commPageAddress
1396 				&& address < commPageAddress + COMMPAGE_SIZE) {
1397 				if (*_imageName)
1398 					*_imageName = "commpage";
1399 				address -= (addr_t)commPageAddress;
1400 				error = elf_debug_lookup_symbol_address(address, _baseAddress,
1401 					_symbolName, NULL, _exactMatch);
1402 				if (_baseAddress)
1403 					*_baseAddress += (addr_t)fTeam->commpage_address;
1404 			}
1405 			return error;
1406 		}
1407 
1408 		strlcpy(fImageName, image.name, sizeof(fImageName));
1409 
1410 		// symbol hash table size
1411 		uint32 hashTabSize;
1412 		if (!_Read(image.symhash, hashTabSize))
1413 			return B_BAD_ADDRESS;
1414 
1415 		// remote pointers to hash buckets and chains
1416 		const uint32* hashBuckets = image.symhash + 2;
1417 		const uint32* hashChains = image.symhash + 2 + hashTabSize;
1418 
1419 		const elf_region_t& textRegion = image.regions[0];
1420 
1421 		// search the image for the symbol
1422 		elf_sym symbolFound;
1423 		addr_t deltaFound = INT_MAX;
1424 		bool exactMatch = false;
1425 
1426 		// to get rid of the erroneous "uninitialized" warnings
1427 		symbolFound.st_name = 0;
1428 		symbolFound.st_value = 0;
1429 
1430 		for (uint32 i = 0; i < hashTabSize; i++) {
1431 			uint32 bucket;
1432 			if (!_Read(&hashBuckets[i], bucket))
1433 				return B_BAD_ADDRESS;
1434 
1435 			for (uint32 j = bucket; j != STN_UNDEF;
1436 					_Read(&hashChains[j], j) ? 0 : j = STN_UNDEF) {
1437 
1438 				elf_sym symbol;
1439 				if (!_Read(image.syms + j, symbol))
1440 					continue;
1441 
1442 				// The symbol table contains not only symbols referring to
1443 				// functions and data symbols within the shared object, but also
1444 				// referenced symbols of other shared objects, as well as
1445 				// section and file references. We ignore everything but
1446 				// function and data symbols that have an st_value != 0 (0
1447 				// seems to be an indication for a symbol defined elsewhere
1448 				// -- couldn't verify that in the specs though).
1449 				if ((symbol.Type() != STT_FUNC && symbol.Type() != STT_OBJECT)
1450 					|| symbol.st_value == 0
1451 					|| symbol.st_value + symbol.st_size + textRegion.delta
1452 						> textRegion.vmstart + textRegion.size) {
1453 					continue;
1454 				}
1455 
1456 				// skip symbols starting after the given address
1457 				addr_t symbolAddress = symbol.st_value + textRegion.delta;
1458 				if (symbolAddress > address)
1459 					continue;
1460 				addr_t symbolDelta = address - symbolAddress;
1461 
1462 				if (symbolDelta < deltaFound) {
1463 					deltaFound = symbolDelta;
1464 					symbolFound = symbol;
1465 
1466 					if (symbolDelta >= 0 && symbolDelta < symbol.st_size) {
1467 						// exact match
1468 						exactMatch = true;
1469 						break;
1470 					}
1471 				}
1472 			}
1473 		}
1474 
1475 		if (_imageName)
1476 			*_imageName = fImageName;
1477 
1478 		if (_symbolName) {
1479 			*_symbolName = NULL;
1480 
1481 			if (deltaFound < INT_MAX) {
1482 				if (_ReadString(image, symbolFound.st_name, fSymbolName,
1483 						sizeof(fSymbolName))) {
1484 					*_symbolName = fSymbolName;
1485 				} else {
1486 					// we can't get its name, so forget the symbol
1487 					deltaFound = INT_MAX;
1488 				}
1489 			}
1490 		}
1491 
1492 		if (_baseAddress) {
1493 			if (deltaFound < INT_MAX)
1494 				*_baseAddress = symbolFound.st_value + textRegion.delta;
1495 			else
1496 				*_baseAddress = textRegion.vmstart;
1497 		}
1498 
1499 		if (_exactMatch)
1500 			*_exactMatch = exactMatch;
1501 
1502 		return B_OK;
1503 	}
1504 
1505 	status_t _FindImageAtAddress(addr_t address, image_t& image)
1506 	{
1507 		image_queue_t imageQueue;
1508 		if (!_Read(fDebugArea.loaded_images, imageQueue))
1509 			return B_BAD_ADDRESS;
1510 
1511 		image_t* imageAddress = imageQueue.head;
1512 		while (imageAddress != NULL) {
1513 			if (!_Read(imageAddress, image))
1514 				return B_BAD_ADDRESS;
1515 
1516 			if (image.regions[0].vmstart <= address
1517 				&& address < image.regions[0].vmstart + image.regions[0].size) {
1518 				return B_OK;
1519 			}
1520 
1521 			imageAddress = image.next;
1522 		}
1523 
1524 		return B_ENTRY_NOT_FOUND;
1525 	}
1526 
1527 	bool _ReadString(const image_t& image, uint32 offset, char* buffer,
1528 		size_t bufferSize)
1529 	{
1530 		const char* address = image.strtab + offset;
1531 
1532 		if (!IS_USER_ADDRESS(address))
1533 			return false;
1534 
1535 		if (debug_debugger_running()) {
1536 			return debug_strlcpy(B_CURRENT_TEAM, buffer, address, bufferSize)
1537 				>= 0;
1538 		}
1539 		return user_strlcpy(buffer, address, bufferSize) >= 0;
1540 	}
1541 
1542 	template<typename T> bool _Read(const T* address, T& data);
1543 		// gcc 2.95.3 doesn't like it defined in-place
1544 
1545 private:
1546 	Team*						fTeam;
1547 	runtime_loader_debug_area	fDebugArea;
1548 	char						fImageName[B_OS_NAME_LENGTH];
1549 	char						fSymbolName[256];
1550 	static UserSymbolLookup		sLookup;
1551 };
1552 
1553 
1554 template<typename T>
1555 bool
1556 UserSymbolLookup::_Read(const T* address, T& data)
1557 {
1558 	if (!IS_USER_ADDRESS(address))
1559 		return false;
1560 
1561 	if (debug_debugger_running())
1562 		return debug_memcpy(B_CURRENT_TEAM, &data, address, sizeof(T)) == B_OK;
1563 	return user_memcpy(&data, address, sizeof(T)) == B_OK;
1564 }
1565 
1566 
1567 UserSymbolLookup UserSymbolLookup::sLookup;
1568 	// doesn't need construction, but has an Init() method
1569 
1570 
1571 //	#pragma mark - public kernel API
1572 
1573 
1574 status_t
1575 get_image_symbol(image_id id, const char *name, int32 symbolClass,
1576 	void **_symbol)
1577 {
1578 	struct elf_image_info *image;
1579 	elf_sym *symbol;
1580 	status_t status = B_OK;
1581 
1582 	TRACE(("get_image_symbol(%s)\n", name));
1583 
1584 	mutex_lock(&sImageMutex);
1585 
1586 	image = find_image(id);
1587 	if (image == NULL) {
1588 		status = B_BAD_IMAGE_ID;
1589 		goto done;
1590 	}
1591 
1592 	symbol = elf_find_symbol(image, name, NULL, true);
1593 	if (symbol == NULL || symbol->st_shndx == SHN_UNDEF) {
1594 		status = B_ENTRY_NOT_FOUND;
1595 		goto done;
1596 	}
1597 
1598 	// TODO: support the "symbolClass" parameter!
1599 
1600 	TRACE(("found: %lx (%lx + %lx)\n",
1601 		symbol->st_value + image->text_region.delta,
1602 		symbol->st_value, image->text_region.delta));
1603 
1604 	*_symbol = (void *)(symbol->st_value + image->text_region.delta);
1605 
1606 done:
1607 	mutex_unlock(&sImageMutex);
1608 	return status;
1609 }
1610 
1611 
1612 //	#pragma mark - kernel private API
1613 
1614 
1615 /*!	Looks up a symbol by address in all images loaded in kernel space.
1616 	Note, if you need to call this function outside a debugger, make
1617 	sure you fix locking and the way it returns its information, first!
1618 */
1619 status_t
1620 elf_debug_lookup_symbol_address(addr_t address, addr_t *_baseAddress,
1621 	const char **_symbolName, const char **_imageName, bool *_exactMatch)
1622 {
1623 	struct elf_image_info *image;
1624 	elf_sym *symbolFound = NULL;
1625 	const char *symbolName = NULL;
1626 	addr_t deltaFound = INT_MAX;
1627 	bool exactMatch = false;
1628 	status_t status;
1629 
1630 	TRACE(("looking up %p\n", (void *)address));
1631 
1632 	if (!sInitialized)
1633 		return B_ERROR;
1634 
1635 	//mutex_lock(&sImageMutex);
1636 
1637 	image = find_image_at_address(address);
1638 		// get image that may contain the address
1639 
1640 	if (image != NULL) {
1641 		addr_t symbolDelta;
1642 		uint32 i;
1643 		int32 j;
1644 
1645 		TRACE((" image %p, base = %p, size = %p\n", image,
1646 			(void *)image->text_region.start, (void *)image->text_region.size));
1647 
1648 		if (image->debug_symbols != NULL) {
1649 			// search extended debug symbol table (contains static symbols)
1650 
1651 			TRACE((" searching debug symbols...\n"));
1652 
1653 			for (i = 0; i < image->num_debug_symbols; i++) {
1654 				elf_sym *symbol = &image->debug_symbols[i];
1655 
1656 				if (symbol->st_value == 0 || symbol->st_size
1657 						>= image->text_region.size + image->data_region.size)
1658 					continue;
1659 
1660 				symbolDelta
1661 					= address - (symbol->st_value + image->text_region.delta);
1662 				if (symbolDelta >= 0 && symbolDelta < symbol->st_size)
1663 					exactMatch = true;
1664 
1665 				if (exactMatch || symbolDelta < deltaFound) {
1666 					deltaFound = symbolDelta;
1667 					symbolFound = symbol;
1668 					symbolName = image->debug_string_table + symbol->st_name;
1669 
1670 					if (exactMatch)
1671 						break;
1672 				}
1673 			}
1674 		} else {
1675 			// search standard symbol lookup table
1676 
1677 			TRACE((" searching standard symbols...\n"));
1678 
1679 			for (i = 0; i < HASHTABSIZE(image); i++) {
1680 				for (j = HASHBUCKETS(image)[i]; j != STN_UNDEF;
1681 						j = HASHCHAINS(image)[j]) {
1682 					elf_sym *symbol = &image->syms[j];
1683 
1684 					if (symbol->st_value == 0
1685 						|| symbol->st_size >= image->text_region.size
1686 							+ image->data_region.size)
1687 						continue;
1688 
1689 					symbolDelta = address - (long)(symbol->st_value
1690 						+ image->text_region.delta);
1691 					if (symbolDelta >= 0 && symbolDelta < symbol->st_size)
1692 						exactMatch = true;
1693 
1694 					if (exactMatch || symbolDelta < deltaFound) {
1695 						deltaFound = symbolDelta;
1696 						symbolFound = symbol;
1697 						symbolName = SYMNAME(image, symbol);
1698 
1699 						if (exactMatch)
1700 							goto symbol_found;
1701 					}
1702 				}
1703 			}
1704 		}
1705 	}
1706 symbol_found:
1707 
1708 	if (symbolFound != NULL) {
1709 		if (_symbolName)
1710 			*_symbolName = symbolName;
1711 		if (_imageName)
1712 			*_imageName = image->name;
1713 		if (_baseAddress)
1714 			*_baseAddress = symbolFound->st_value + image->text_region.delta;
1715 		if (_exactMatch)
1716 			*_exactMatch = exactMatch;
1717 
1718 		status = B_OK;
1719 	} else if (image != NULL) {
1720 		TRACE(("symbol not found!\n"));
1721 
1722 		if (_symbolName)
1723 			*_symbolName = NULL;
1724 		if (_imageName)
1725 			*_imageName = image->name;
1726 		if (_baseAddress)
1727 			*_baseAddress = image->text_region.start;
1728 		if (_exactMatch)
1729 			*_exactMatch = false;
1730 
1731 		status = B_OK;
1732 	} else {
1733 		TRACE(("image not found!\n"));
1734 		status = B_ENTRY_NOT_FOUND;
1735 	}
1736 
1737 	// Note, theoretically, all information we return back to our caller
1738 	// would have to be locked - but since this function is only called
1739 	// from the debugger, it's safe to do it this way
1740 
1741 	//mutex_unlock(&sImageMutex);
1742 
1743 	return status;
1744 }
1745 
1746 
1747 /*!	Tries to find a matching user symbol for the given address.
1748 	Note that the given team's address space must already be in effect.
1749 */
1750 status_t
1751 elf_debug_lookup_user_symbol_address(Team* team, addr_t address,
1752 	addr_t *_baseAddress, const char **_symbolName, const char **_imageName,
1753 	bool *_exactMatch)
1754 {
1755 	if (team == NULL || team == team_get_kernel_team())
1756 		return B_BAD_VALUE;
1757 
1758 	UserSymbolLookup& lookup = UserSymbolLookup::Default();
1759 	status_t error = lookup.Init(team);
1760 	if (error != B_OK)
1761 		return error;
1762 
1763 	return lookup.LookupSymbolAddress(address, _baseAddress, _symbolName,
1764 		_imageName, _exactMatch);
1765 }
1766 
1767 
1768 /*!	Looks up a symbol in all kernel images. Note, this function is thought to
1769 	be used in the kernel debugger, and therefore doesn't perform any locking.
1770 */
1771 addr_t
1772 elf_debug_lookup_symbol(const char* searchName)
1773 {
1774 	struct elf_image_info *image = NULL;
1775 
1776 	ImageHash::Iterator iterator(sImagesHash);
1777 	while (iterator.HasNext()) {
1778 		image = iterator.Next();
1779 		if (image->num_debug_symbols > 0) {
1780 			// search extended debug symbol table (contains static symbols)
1781 			for (uint32 i = 0; i < image->num_debug_symbols; i++) {
1782 				elf_sym *symbol = &image->debug_symbols[i];
1783 				const char *name = image->debug_string_table + symbol->st_name;
1784 
1785 				if (symbol->st_value > 0 && !strcmp(name, searchName))
1786 					return symbol->st_value + image->text_region.delta;
1787 			}
1788 		} else {
1789 			// search standard symbol lookup table
1790 			for (uint32 i = 0; i < HASHTABSIZE(image); i++) {
1791 				for (uint32 j = HASHBUCKETS(image)[i]; j != STN_UNDEF;
1792 						j = HASHCHAINS(image)[j]) {
1793 					elf_sym *symbol = &image->syms[j];
1794 					const char *name = SYMNAME(image, symbol);
1795 
1796 					if (symbol->st_value > 0 && !strcmp(name, searchName))
1797 						return symbol->st_value + image->text_region.delta;
1798 				}
1799 			}
1800 		}
1801 	}
1802 
1803 	return 0;
1804 }
1805 
1806 
1807 status_t
1808 elf_lookup_kernel_symbol(const char* name, elf_symbol_info* info)
1809 {
1810 	// find the symbol
1811 	elf_sym* foundSymbol = elf_find_symbol(sKernelImage, name, NULL, false);
1812 	if (foundSymbol == NULL)
1813 		return B_MISSING_SYMBOL;
1814 
1815 	info->address = foundSymbol->st_value + sKernelImage->text_region.delta;
1816 	info->size = foundSymbol->st_size;
1817 	return B_OK;
1818 }
1819 
1820 
1821 #endif // ELF32_COMPAT
1822 
1823 
1824 status_t
1825 elf_load_user_image(const char *path, Team *team, uint32 flags, addr_t *entry)
1826 {
1827 	elf_ehdr elfHeader;
1828 	char baseName[B_OS_NAME_LENGTH];
1829 	status_t status;
1830 	ssize_t length;
1831 
1832 	TRACE(("elf_load: entry path '%s', team %p\n", path, team));
1833 
1834 	int fd = _kern_open(-1, path, O_RDONLY, 0);
1835 	if (fd < 0)
1836 		return fd;
1837 	FileDescriptorCloser fdCloser(fd);
1838 
1839 	struct stat st;
1840 	status = _kern_read_stat(fd, NULL, false, &st, sizeof(st));
1841 	if (status != B_OK)
1842 		return status;
1843 
1844 	// read and verify the ELF header
1845 
1846 	length = _kern_read(fd, 0, &elfHeader, sizeof(elfHeader));
1847 	if (length < B_OK)
1848 		return length;
1849 
1850 	if (length != sizeof(elfHeader)) {
1851 		// short read
1852 		return B_NOT_AN_EXECUTABLE;
1853 	}
1854 	status = verify_eheader(&elfHeader);
1855 	if (status < B_OK)
1856 		return status;
1857 
1858 #ifdef ELF_LOAD_USER_IMAGE_TEST_EXECUTABLE
1859 	if ((flags & ELF_LOAD_USER_IMAGE_TEST_EXECUTABLE) != 0)
1860 		return B_OK;
1861 #endif
1862 
1863 	struct elf_image_info* image;
1864 	image = create_image_struct();
1865 	if (image == NULL)
1866 		return B_NO_MEMORY;
1867 	CObjectDeleter<elf_image_info, void, delete_elf_image> imageDeleter(image);
1868 
1869 	struct ElfHeaderUnsetter {
1870 		ElfHeaderUnsetter(elf_image_info* image)
1871 			: fImage(image)
1872 		{
1873 		}
1874 		~ElfHeaderUnsetter()
1875 		{
1876 			fImage->elf_header = NULL;
1877 		}
1878 
1879 		elf_image_info* fImage;
1880 	} headerUnsetter(image);
1881 	image->elf_header = &elfHeader;
1882 
1883 	// read program header
1884 
1885 	elf_phdr *programHeaders = (elf_phdr *)malloc(
1886 		elfHeader.e_phnum * elfHeader.e_phentsize);
1887 	if (programHeaders == NULL) {
1888 		dprintf("error allocating space for program headers\n");
1889 		return B_NO_MEMORY;
1890 	}
1891 	MemoryDeleter headersDeleter(programHeaders);
1892 
1893 	TRACE(("reading in program headers at 0x%lx, length 0x%x\n",
1894 		elfHeader.e_phoff, elfHeader.e_phnum * elfHeader.e_phentsize));
1895 	length = _kern_read(fd, elfHeader.e_phoff, programHeaders,
1896 		elfHeader.e_phnum * elfHeader.e_phentsize);
1897 	if (length < B_OK) {
1898 		dprintf("error reading in program headers\n");
1899 		return length;
1900 	}
1901 	if (length != elfHeader.e_phnum * elfHeader.e_phentsize) {
1902 		dprintf("short read while reading in program headers\n");
1903 		return B_ERROR;
1904 	}
1905 
1906 	// construct a nice name for the region we have to create below
1907 	{
1908 		int32 length;
1909 
1910 		const char *leaf = strrchr(path, '/');
1911 		if (leaf == NULL)
1912 			leaf = path;
1913 		else
1914 			leaf++;
1915 
1916 		length = strlen(leaf);
1917 		if (length > B_OS_NAME_LENGTH - 16)
1918 			snprintf(baseName, B_OS_NAME_LENGTH, "...%s", leaf + length + 16 - B_OS_NAME_LENGTH);
1919 		else
1920 			strcpy(baseName, leaf);
1921 	}
1922 
1923 	// map the program's segments into memory, initially with rw access
1924 	// correct area protection will be set after relocation
1925 
1926 	BStackOrHeapArray<area_id, 8> mappedAreas(elfHeader.e_phnum);
1927 	if (!mappedAreas.IsValid())
1928 		return B_NO_MEMORY;
1929 
1930 	extended_image_info imageInfo;
1931 	memset(&imageInfo, 0, sizeof(imageInfo));
1932 
1933 	addr_t delta = 0;
1934 	uint32 addressSpec = B_RANDOMIZED_BASE_ADDRESS;
1935 	for (int i = 0; i < elfHeader.e_phnum; i++) {
1936 		char regionName[B_OS_NAME_LENGTH];
1937 		char *regionAddress;
1938 		char *originalRegionAddress;
1939 		area_id id;
1940 
1941 		mappedAreas[i] = -1;
1942 
1943 		if (programHeaders[i].p_type == PT_DYNAMIC) {
1944 			image->dynamic_section = programHeaders[i].p_vaddr;
1945 			continue;
1946 		}
1947 
1948 		if (programHeaders[i].p_type != PT_LOAD)
1949 			continue;
1950 
1951 		regionAddress = (char *)(ROUNDDOWN(programHeaders[i].p_vaddr,
1952 			B_PAGE_SIZE) + delta);
1953 		originalRegionAddress = regionAddress;
1954 
1955 		if (programHeaders[i].p_flags & PF_WRITE) {
1956 			// rw/data segment
1957 			size_t memUpperBound = (programHeaders[i].p_vaddr % B_PAGE_SIZE)
1958 				+ programHeaders[i].p_memsz;
1959 			size_t fileUpperBound = (programHeaders[i].p_vaddr % B_PAGE_SIZE)
1960 				+ programHeaders[i].p_filesz;
1961 
1962 			memUpperBound = ROUNDUP(memUpperBound, B_PAGE_SIZE);
1963 			fileUpperBound = ROUNDUP(fileUpperBound, B_PAGE_SIZE);
1964 
1965 			snprintf(regionName, B_OS_NAME_LENGTH, "%s_seg%drw", baseName, i);
1966 
1967 			id = vm_map_file(team->id, regionName, (void **)&regionAddress,
1968 				addressSpec, fileUpperBound,
1969 				B_READ_AREA | B_WRITE_AREA, REGION_PRIVATE_MAP, false,
1970 				fd, ROUNDDOWN(programHeaders[i].p_offset, B_PAGE_SIZE));
1971 			if (id < B_OK) {
1972 				dprintf("error mapping file data: %s!\n", strerror(id));
1973 				return B_NOT_AN_EXECUTABLE;
1974 			}
1975 			mappedAreas[i] = id;
1976 
1977 			imageInfo.basic_info.data = regionAddress;
1978 			imageInfo.basic_info.data_size = memUpperBound;
1979 
1980 			image->data_region.start = (addr_t)regionAddress;
1981 			image->data_region.size = memUpperBound;
1982 
1983 			// clean garbage brought by mmap (the region behind the file,
1984 			// at least parts of it are the bss and have to be zeroed)
1985 			addr_t start = (addr_t)regionAddress
1986 				+ (programHeaders[i].p_vaddr % B_PAGE_SIZE)
1987 				+ programHeaders[i].p_filesz;
1988 			size_t amount = fileUpperBound
1989 				- (programHeaders[i].p_vaddr % B_PAGE_SIZE)
1990 				- (programHeaders[i].p_filesz);
1991 			set_ac();
1992 			memset((void *)start, 0, amount);
1993 			clear_ac();
1994 
1995 			// Check if we need extra storage for the bss - we have to do this if
1996 			// the above region doesn't already comprise the memory size, too.
1997 
1998 			if (memUpperBound != fileUpperBound) {
1999 				size_t bssSize = memUpperBound - fileUpperBound;
2000 
2001 				snprintf(regionName, B_OS_NAME_LENGTH, "%s_bss%d", baseName, i);
2002 
2003 				regionAddress += fileUpperBound;
2004 				virtual_address_restrictions virtualRestrictions = {};
2005 				virtualRestrictions.address = regionAddress;
2006 				virtualRestrictions.address_specification = B_EXACT_ADDRESS;
2007 				physical_address_restrictions physicalRestrictions = {};
2008 				id = create_area_etc(team->id, regionName, bssSize, B_NO_LOCK,
2009 					B_READ_AREA | B_WRITE_AREA, 0, 0, &virtualRestrictions,
2010 					&physicalRestrictions, (void**)&regionAddress);
2011 				if (id < B_OK) {
2012 					dprintf("error allocating bss area: %s!\n", strerror(id));
2013 					return B_NOT_AN_EXECUTABLE;
2014 				}
2015 			}
2016 		} else {
2017 			// assume ro/text segment
2018 			snprintf(regionName, B_OS_NAME_LENGTH, "%s_seg%dro", baseName, i);
2019 
2020 			size_t segmentSize = ROUNDUP(programHeaders[i].p_memsz
2021 				+ (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE);
2022 
2023 			id = vm_map_file(team->id, regionName, (void **)&regionAddress,
2024 				addressSpec, segmentSize,
2025 				B_READ_AREA | B_WRITE_AREA, REGION_PRIVATE_MAP, false, fd,
2026 				ROUNDDOWN(programHeaders[i].p_offset, B_PAGE_SIZE));
2027 			if (id < B_OK) {
2028 				dprintf("error mapping file text: %s!\n", strerror(id));
2029 				return B_NOT_AN_EXECUTABLE;
2030 			}
2031 
2032 			mappedAreas[i] = id;
2033 
2034 			imageInfo.basic_info.text = regionAddress;
2035 			imageInfo.basic_info.text_size = segmentSize;
2036 
2037 			image->text_region.start = (addr_t)regionAddress;
2038 			image->text_region.size = segmentSize;
2039 		}
2040 
2041 		if (addressSpec != B_EXACT_ADDRESS) {
2042 			addressSpec = B_EXACT_ADDRESS;
2043 			delta = regionAddress - originalRegionAddress;
2044 		}
2045 	}
2046 
2047 	image->data_region.delta = delta;
2048 	image->text_region.delta = delta;
2049 
2050 	// modify the dynamic ptr by the delta of the regions
2051 	image->dynamic_section += image->text_region.delta;
2052 
2053 	set_ac();
2054 	status = elf_parse_dynamic_section(image);
2055 	if (status != B_OK) {
2056 		clear_ac();
2057 		return status;
2058 	}
2059 
2060 	status = elf_relocate(image, image);
2061 	if (status != B_OK) {
2062 		clear_ac();
2063 		return status;
2064 	}
2065 
2066 	clear_ac();
2067 
2068 	// set correct area protection
2069 	for (int i = 0; i < elfHeader.e_phnum; i++) {
2070 		if (mappedAreas[i] == -1)
2071 			continue;
2072 
2073 		uint32 protection = 0;
2074 
2075 		if (programHeaders[i].p_flags & PF_EXECUTE)
2076 			protection |= B_EXECUTE_AREA;
2077 		if (programHeaders[i].p_flags & PF_WRITE)
2078 			protection |= B_WRITE_AREA;
2079 		if (programHeaders[i].p_flags & PF_READ)
2080 			protection |= B_READ_AREA;
2081 
2082 		status = vm_set_area_protection(team->id, mappedAreas[i], protection,
2083 			true);
2084 		if (status != B_OK)
2085 			return status;
2086 	}
2087 
2088 	// register the loaded image
2089 	imageInfo.basic_info.type = B_LIBRARY_IMAGE;
2090 	imageInfo.basic_info.device = st.st_dev;
2091 	imageInfo.basic_info.node = st.st_ino;
2092 	strlcpy(imageInfo.basic_info.name, path, sizeof(imageInfo.basic_info.name));
2093 
2094 	imageInfo.basic_info.api_version = B_HAIKU_VERSION;
2095 	imageInfo.basic_info.abi = B_HAIKU_ABI;
2096 		// TODO: Get the actual values for the shared object. Currently only
2097 		// the runtime loader is loaded, so this is good enough for the time
2098 		// being.
2099 
2100 	imageInfo.text_delta = delta;
2101 	imageInfo.symbol_table = image->syms;
2102 	imageInfo.symbol_hash = image->symhash;
2103 	imageInfo.string_table = image->strtab;
2104 
2105 	imageInfo.basic_info.id = register_image(team, &imageInfo,
2106 		sizeof(imageInfo));
2107 	if (imageInfo.basic_info.id >= 0 && team_get_current_team_id() == team->id)
2108 		user_debug_image_created(&imageInfo.basic_info);
2109 		// Don't care, if registering fails. It's not crucial.
2110 
2111 	TRACE(("elf_load: done!\n"));
2112 
2113 	*entry = elfHeader.e_entry + delta;
2114 	return B_OK;
2115 }
2116 
2117 
2118 #ifndef ELF32_COMPAT
2119 
2120 image_id
2121 load_kernel_add_on(const char *path)
2122 {
2123 	elf_phdr *programHeaders;
2124 	elf_ehdr *elfHeader;
2125 	struct elf_image_info *image;
2126 	const char *fileName;
2127 	void *reservedAddress;
2128 	size_t reservedSize;
2129 	status_t status;
2130 	ssize_t length;
2131 	bool textSectionWritable = false;
2132 	int executableHeaderCount = 0;
2133 
2134 	TRACE(("elf_load_kspace: entry path '%s'\n", path));
2135 
2136 	int fd = _kern_open(-1, path, O_RDONLY, 0);
2137 	if (fd < 0)
2138 		return fd;
2139 
2140 	struct vnode *vnode;
2141 	status = vfs_get_vnode_from_fd(fd, true, &vnode);
2142 	if (status < B_OK)
2143 		goto error0;
2144 
2145 	// get the file name
2146 	fileName = strrchr(path, '/');
2147 	if (fileName == NULL)
2148 		fileName = path;
2149 	else
2150 		fileName++;
2151 
2152 	// Prevent someone else from trying to load this image
2153 	mutex_lock(&sImageLoadMutex);
2154 
2155 	// make sure it's not loaded already. Search by vnode
2156 	image = find_image_by_vnode(vnode);
2157 	if (image) {
2158 		atomic_add(&image->ref_count, 1);
2159 		goto done;
2160 	}
2161 
2162 	elfHeader = (elf_ehdr *)malloc(sizeof(*elfHeader));
2163 	if (!elfHeader) {
2164 		status = B_NO_MEMORY;
2165 		goto error;
2166 	}
2167 
2168 	length = _kern_read(fd, 0, elfHeader, sizeof(*elfHeader));
2169 	if (length < B_OK) {
2170 		status = length;
2171 		goto error1;
2172 	}
2173 	if (length != sizeof(*elfHeader)) {
2174 		// short read
2175 		status = B_NOT_AN_EXECUTABLE;
2176 		goto error1;
2177 	}
2178 	status = verify_eheader(elfHeader);
2179 	if (status < B_OK)
2180 		goto error1;
2181 
2182 	image = create_image_struct();
2183 	if (!image) {
2184 		status = B_NO_MEMORY;
2185 		goto error1;
2186 	}
2187 	image->vnode = vnode;
2188 	image->elf_header = elfHeader;
2189 	image->name = strdup(path);
2190 	vnode = NULL;
2191 
2192 	programHeaders = (elf_phdr *)malloc(elfHeader->e_phnum
2193 		* elfHeader->e_phentsize);
2194 	if (programHeaders == NULL) {
2195 		dprintf("%s: error allocating space for program headers\n", fileName);
2196 		status = B_NO_MEMORY;
2197 		goto error2;
2198 	}
2199 
2200 	TRACE(("reading in program headers at 0x%lx, length 0x%x\n",
2201 		elfHeader->e_phoff, elfHeader->e_phnum * elfHeader->e_phentsize));
2202 
2203 	length = _kern_read(fd, elfHeader->e_phoff, programHeaders,
2204 		elfHeader->e_phnum * elfHeader->e_phentsize);
2205 	if (length < B_OK) {
2206 		status = length;
2207 		TRACE(("%s: error reading in program headers\n", fileName));
2208 		goto error3;
2209 	}
2210 	if (length != elfHeader->e_phnum * elfHeader->e_phentsize) {
2211 		TRACE(("%s: short read while reading in program headers\n", fileName));
2212 		status = B_ERROR;
2213 		goto error3;
2214 	}
2215 
2216 	// determine how much space we need for all loaded segments
2217 
2218 	reservedSize = 0;
2219 	length = 0;
2220 
2221 	for (int32 i = 0; i < elfHeader->e_phnum; i++) {
2222 		size_t end;
2223 
2224 		if (programHeaders[i].p_type != PT_LOAD)
2225 			continue;
2226 
2227 		length += ROUNDUP(programHeaders[i].p_memsz
2228 			+ (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE);
2229 
2230 		end = ROUNDUP(programHeaders[i].p_memsz + programHeaders[i].p_vaddr,
2231 			B_PAGE_SIZE);
2232 		if (end > reservedSize)
2233 			reservedSize = end;
2234 
2235 		if (programHeaders[i].IsExecutable())
2236 			executableHeaderCount++;
2237 	}
2238 
2239 	// Check whether the segments have an unreasonable amount of unused space
2240 	// inbetween.
2241 	if ((ssize_t)reservedSize > length + 8 * 1024) {
2242 		status = B_BAD_DATA;
2243 		goto error1;
2244 	}
2245 
2246 	// reserve that space and allocate the areas from that one
2247 	if (vm_reserve_address_range(VMAddressSpace::KernelID(), &reservedAddress,
2248 			B_ANY_KERNEL_ADDRESS, reservedSize, 0) < B_OK) {
2249 		status = B_NO_MEMORY;
2250 		goto error3;
2251 	}
2252 
2253 	image->data_region.size = 0;
2254 	image->text_region.size = 0;
2255 
2256 	for (int32 i = 0; i < elfHeader->e_phnum; i++) {
2257 		char regionName[B_OS_NAME_LENGTH];
2258 		elf_region *region;
2259 
2260 		TRACE(("looking at program header %" B_PRId32 "\n", i));
2261 
2262 		switch (programHeaders[i].p_type) {
2263 			case PT_LOAD:
2264 				break;
2265 			case PT_DYNAMIC:
2266 				image->dynamic_section = programHeaders[i].p_vaddr;
2267 				continue;
2268 			case PT_INTERP:
2269 				// should check here for appropriate interpreter
2270 				continue;
2271 			case PT_PHDR:
2272 			case PT_STACK:
2273 				// we don't use it
2274 				continue;
2275 			case PT_EH_FRAME:
2276 				// not implemented yet, but can be ignored
2277 				continue;
2278 			case PT_ARM_UNWIND:
2279 				continue;
2280 			case PT_RISCV_ATTRIBUTES:
2281 				// TODO: check ABI compatibility attributes
2282 				continue;
2283 			default:
2284 				dprintf("%s: unhandled pheader type %#" B_PRIx32 "\n", fileName,
2285 					programHeaders[i].p_type);
2286 				continue;
2287 		}
2288 
2289 		// we're here, so it must be a PT_LOAD segment
2290 
2291 		// Usually add-ons have two PT_LOAD headers: one for .data one or .text.
2292 		// x86 and PPC may differ in permission bits for .data's PT_LOAD header
2293 		// x86 is usually RW, PPC is RWE
2294 
2295 		// Some add-ons may have .text and .data concatenated in a single
2296 		// PT_LOAD RWE header and we must map that to .text.
2297 		if (programHeaders[i].IsReadWrite()
2298 			&& (!programHeaders[i].IsExecutable()
2299 				|| executableHeaderCount > 1)) {
2300 			// this is the writable segment
2301 			if (image->data_region.size != 0) {
2302 				// we've already created this segment
2303 				continue;
2304 			}
2305 			region = &image->data_region;
2306 
2307 			snprintf(regionName, B_OS_NAME_LENGTH, "%s_data", fileName);
2308 		} else if (programHeaders[i].IsExecutable()) {
2309 			// this is the non-writable segment
2310 			if (image->text_region.size != 0) {
2311 				// we've already created this segment
2312 				continue;
2313 			}
2314 			region = &image->text_region;
2315 
2316 			// some programs may have .text and .data concatenated in a
2317 			// single PT_LOAD section which is readable/writable/executable
2318 			textSectionWritable = programHeaders[i].IsReadWrite();
2319 			snprintf(regionName, B_OS_NAME_LENGTH, "%s_text", fileName);
2320 		} else {
2321 			dprintf("%s: weird program header flags %#" B_PRIx32 "\n", fileName,
2322 				programHeaders[i].p_flags);
2323 			continue;
2324 		}
2325 
2326 		region->start = (addr_t)reservedAddress + ROUNDDOWN(
2327 			programHeaders[i].p_vaddr, B_PAGE_SIZE);
2328 		region->size = ROUNDUP(programHeaders[i].p_memsz
2329 			+ (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE);
2330 		region->id = create_area(regionName, (void **)&region->start,
2331 			B_EXACT_ADDRESS, region->size, B_FULL_LOCK,
2332 			B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
2333 		if (region->id < B_OK) {
2334 			dprintf("%s: error allocating area: %s\n", fileName,
2335 				strerror(region->id));
2336 			status = B_NOT_AN_EXECUTABLE;
2337 			goto error4;
2338 		}
2339 		region->delta = -ROUNDDOWN(programHeaders[i].p_vaddr, B_PAGE_SIZE);
2340 
2341 		TRACE(("elf_load_kspace: created area \"%s\" at %p\n",
2342 			regionName, (void *)region->start));
2343 
2344 		length = _kern_read(fd, programHeaders[i].p_offset,
2345 			(void *)(region->start + (programHeaders[i].p_vaddr % B_PAGE_SIZE)),
2346 			programHeaders[i].p_filesz);
2347 		if (length < B_OK) {
2348 			status = length;
2349 			dprintf("%s: error reading in segment %" B_PRId32 "\n", fileName,
2350 				i);
2351 			goto error5;
2352 		}
2353 	}
2354 
2355 	image->data_region.delta += image->data_region.start;
2356 	image->text_region.delta += image->text_region.start;
2357 
2358 	// modify the dynamic ptr by the delta of the regions
2359 	image->dynamic_section += image->text_region.delta;
2360 
2361 	status = elf_parse_dynamic_section(image);
2362 	if (status < B_OK)
2363 		goto error5;
2364 
2365 	status = init_image_version_infos(image);
2366 	if (status != B_OK)
2367 		goto error5;
2368 
2369 	status = check_needed_image_versions(image);
2370 	if (status != B_OK)
2371 		goto error5;
2372 
2373 	status = elf_relocate(image, sKernelImage);
2374 	if (status < B_OK)
2375 		goto error5;
2376 
2377 	// We needed to read in the contents of the "text" area, but
2378 	// now we can protect it read-only/execute, unless this is a
2379 	// special image with concatenated .text and .data, when it
2380 	// will also need write access.
2381 	set_area_protection(image->text_region.id,
2382 		B_KERNEL_READ_AREA | B_KERNEL_EXECUTE_AREA
2383 		| (textSectionWritable ? B_KERNEL_WRITE_AREA : 0));
2384 
2385 	// There might be a hole between the two segments, and we don't need to
2386 	// reserve this any longer
2387 	vm_unreserve_address_range(VMAddressSpace::KernelID(), reservedAddress,
2388 		reservedSize);
2389 
2390 	if (sLoadElfSymbols)
2391 		load_elf_symbol_table(fd, image);
2392 
2393 	free(programHeaders);
2394 	mutex_lock(&sImageMutex);
2395 	register_elf_image(image);
2396 	mutex_unlock(&sImageMutex);
2397 
2398 done:
2399 	_kern_close(fd);
2400 	mutex_unlock(&sImageLoadMutex);
2401 
2402 	return image->id;
2403 
2404 error5:
2405 error4:
2406 	vm_unreserve_address_range(VMAddressSpace::KernelID(), reservedAddress,
2407 		reservedSize);
2408 error3:
2409 	free(programHeaders);
2410 error2:
2411 	delete_elf_image(image);
2412 	elfHeader = NULL;
2413 error1:
2414 	free(elfHeader);
2415 error:
2416 	mutex_unlock(&sImageLoadMutex);
2417 error0:
2418 	dprintf("Could not load kernel add-on \"%s\": %s\n", path,
2419 		strerror(status));
2420 
2421 	if (vnode)
2422 		vfs_put_vnode(vnode);
2423 	_kern_close(fd);
2424 
2425 	return status;
2426 }
2427 
2428 
2429 status_t
2430 unload_kernel_add_on(image_id id)
2431 {
2432 	MutexLocker _(sImageLoadMutex);
2433 	MutexLocker _2(sImageMutex);
2434 
2435 	elf_image_info *image = find_image(id);
2436 	if (image == NULL)
2437 		return B_BAD_IMAGE_ID;
2438 
2439 	unload_elf_image(image);
2440 	return B_OK;
2441 }
2442 
2443 
2444 struct elf_image_info*
2445 elf_get_kernel_image()
2446 {
2447 	return sKernelImage;
2448 }
2449 
2450 
2451 status_t
2452 elf_get_image_info_for_address(addr_t address, image_info* info)
2453 {
2454 	MutexLocker _(sImageMutex);
2455 	struct elf_image_info* elfInfo = find_image_at_address(address);
2456 	if (elfInfo == NULL)
2457 		return B_ENTRY_NOT_FOUND;
2458 
2459 	info->id = elfInfo->id;
2460 	info->type = B_SYSTEM_IMAGE;
2461 	info->sequence = 0;
2462 	info->init_order = 0;
2463 	info->init_routine = NULL;
2464 	info->term_routine = NULL;
2465 	info->device = -1;
2466 	info->node = -1;
2467 		// TODO: We could actually fill device/node in.
2468 	strlcpy(info->name, elfInfo->name, sizeof(info->name));
2469 	info->text = (void*)elfInfo->text_region.start;
2470 	info->data = (void*)elfInfo->data_region.start;
2471 	info->text_size = elfInfo->text_region.size;
2472 	info->data_size = elfInfo->data_region.size;
2473 
2474 	return B_OK;
2475 }
2476 
2477 
2478 image_id
2479 elf_create_memory_image(const char* imageName, addr_t text, size_t textSize,
2480 	addr_t data, size_t dataSize)
2481 {
2482 	// allocate the image
2483 	elf_image_info* image = create_image_struct();
2484 	if (image == NULL)
2485 		return B_NO_MEMORY;
2486 	MemoryDeleter imageDeleter(image);
2487 
2488 	// allocate symbol and string tables -- we allocate an empty symbol table,
2489 	// so that elf_debug_lookup_symbol_address() won't try the dynamic symbol
2490 	// table, which we don't have.
2491 	elf_sym* symbolTable = (elf_sym*)malloc(0);
2492 	char* stringTable = (char*)malloc(1);
2493 	MemoryDeleter symbolTableDeleter(symbolTable);
2494 	MemoryDeleter stringTableDeleter(stringTable);
2495 	if (symbolTable == NULL || stringTable == NULL)
2496 		return B_NO_MEMORY;
2497 
2498 	// the string table always contains the empty string
2499 	stringTable[0] = '\0';
2500 
2501 	image->debug_symbols = symbolTable;
2502 	image->num_debug_symbols = 0;
2503 	image->debug_string_table = stringTable;
2504 
2505 	// dup image name
2506 	image->name = strdup(imageName);
2507 	if (image->name == NULL)
2508 		return B_NO_MEMORY;
2509 
2510 	// data and text region
2511 	image->text_region.id = -1;
2512 	image->text_region.start = text;
2513 	image->text_region.size = textSize;
2514 	image->text_region.delta = 0;
2515 
2516 	image->data_region.id = -1;
2517 	image->data_region.start = data;
2518 	image->data_region.size = dataSize;
2519 	image->data_region.delta = 0;
2520 
2521 	mutex_lock(&sImageMutex);
2522 	register_elf_image(image);
2523 	image_id imageID = image->id;
2524 	mutex_unlock(&sImageMutex);
2525 
2526 	// keep the allocated memory
2527 	imageDeleter.Detach();
2528 	symbolTableDeleter.Detach();
2529 	stringTableDeleter.Detach();
2530 
2531 	return imageID;
2532 }
2533 
2534 
2535 status_t
2536 elf_add_memory_image_symbol(image_id id, const char* name, addr_t address,
2537 	size_t size, int32 type)
2538 {
2539 	MutexLocker _(sImageMutex);
2540 
2541 	// get the image
2542 	struct elf_image_info* image = find_image(id);
2543 	if (image == NULL)
2544 		return B_ENTRY_NOT_FOUND;
2545 
2546 	// get the current string table size
2547 	size_t stringTableSize = 1;
2548 	if (image->num_debug_symbols > 0) {
2549 		for (int32 i = image->num_debug_symbols - 1; i >= 0; i--) {
2550 			int32 nameIndex = image->debug_symbols[i].st_name;
2551 			if (nameIndex != 0) {
2552 				stringTableSize = nameIndex
2553 					+ strlen(image->debug_string_table + nameIndex) + 1;
2554 				break;
2555 			}
2556 		}
2557 	}
2558 
2559 	// enter the name in the string table
2560 	char* stringTable = (char*)image->debug_string_table;
2561 	size_t stringIndex = 0;
2562 	if (name != NULL) {
2563 		size_t nameSize = strlen(name) + 1;
2564 		stringIndex = stringTableSize;
2565 		stringTableSize += nameSize;
2566 		stringTable = (char*)realloc((char*)image->debug_string_table,
2567 			stringTableSize);
2568 		if (stringTable == NULL)
2569 			return B_NO_MEMORY;
2570 		image->debug_string_table = stringTable;
2571 		memcpy(stringTable + stringIndex, name, nameSize);
2572 	}
2573 
2574 	// resize the symbol table
2575 	int32 symbolCount = image->num_debug_symbols + 1;
2576 	elf_sym* symbolTable = (elf_sym*)realloc(
2577 		(elf_sym*)image->debug_symbols, sizeof(elf_sym) * symbolCount);
2578 	if (symbolTable == NULL)
2579 		return B_NO_MEMORY;
2580 	image->debug_symbols = symbolTable;
2581 
2582 	// enter the symbol
2583 	elf_sym& symbol = symbolTable[symbolCount - 1];
2584 	symbol.SetInfo(STB_GLOBAL,
2585 		type == B_SYMBOL_TYPE_DATA ? STT_OBJECT : STT_FUNC);
2586 	symbol.st_name = stringIndex;
2587 	symbol.st_value = address;
2588 	symbol.st_size = size;
2589 	symbol.st_other = 0;
2590 	symbol.st_shndx = 0;
2591 	image->num_debug_symbols++;
2592 
2593 	return B_OK;
2594 }
2595 
2596 
2597 /*!	Reads the symbol and string table for the kernel image with the given ID.
2598 	\a _symbolCount and \a _stringTableSize are both in- and output parameters.
2599 	When called they call the size of the buffers given by \a symbolTable and
2600 	\a stringTable respectively. When the function returns successfully, they
2601 	will contain the actual sizes (which can be greater than the original ones).
2602 	The function will copy as much as possible into the buffers. For only
2603 	getting the required buffer sizes, it can be invoked with \c NULL buffers.
2604 	On success \a _imageDelta will contain the offset to be added to the symbol
2605 	values in the table to get the actual symbol addresses.
2606 */
2607 status_t
2608 elf_read_kernel_image_symbols(image_id id, elf_sym* symbolTable,
2609 	int32* _symbolCount, char* stringTable, size_t* _stringTableSize,
2610 	addr_t* _imageDelta, bool kernel)
2611 {
2612 	// check params
2613 	if (_symbolCount == NULL || _stringTableSize == NULL)
2614 		return B_BAD_VALUE;
2615 	if (!kernel) {
2616 		if (!IS_USER_ADDRESS(_symbolCount) || !IS_USER_ADDRESS(_stringTableSize)
2617 			|| (_imageDelta != NULL && !IS_USER_ADDRESS(_imageDelta))
2618 			|| (symbolTable != NULL && !IS_USER_ADDRESS(symbolTable))
2619 			|| (stringTable != NULL && !IS_USER_ADDRESS(stringTable))) {
2620 			return B_BAD_ADDRESS;
2621 		}
2622 	}
2623 
2624 	// get buffer sizes
2625 	int32 maxSymbolCount;
2626 	size_t maxStringTableSize;
2627 	if (kernel) {
2628 		maxSymbolCount = *_symbolCount;
2629 		maxStringTableSize = *_stringTableSize;
2630 	} else {
2631 		if (user_memcpy(&maxSymbolCount, _symbolCount, sizeof(maxSymbolCount))
2632 				!= B_OK
2633 			|| user_memcpy(&maxStringTableSize, _stringTableSize,
2634 				sizeof(maxStringTableSize)) != B_OK) {
2635 			return B_BAD_ADDRESS;
2636 		}
2637 	}
2638 
2639 	// find the image
2640 	MutexLocker _(sImageMutex);
2641 	struct elf_image_info* image = find_image(id);
2642 	if (image == NULL)
2643 		return B_ENTRY_NOT_FOUND;
2644 
2645 	// get the tables and infos
2646 	addr_t imageDelta = image->text_region.delta;
2647 	const elf_sym* symbols;
2648 	int32 symbolCount;
2649 	const char* strings;
2650 
2651 	if (image->debug_symbols != NULL) {
2652 		symbols = image->debug_symbols;
2653 		symbolCount = image->num_debug_symbols;
2654 		strings = image->debug_string_table;
2655 	} else {
2656 		symbols = image->syms;
2657 		symbolCount = image->symhash[1];
2658 		strings = image->strtab;
2659 	}
2660 
2661 	// The string table size isn't stored in the elf_image_info structure. Find
2662 	// out by iterating through all symbols.
2663 	size_t stringTableSize = 0;
2664 	for (int32 i = 0; i < symbolCount; i++) {
2665 		size_t index = symbols[i].st_name;
2666 		if (index > stringTableSize)
2667 			stringTableSize = index;
2668 	}
2669 	stringTableSize += strlen(strings + stringTableSize) + 1;
2670 		// add size of the last string
2671 
2672 	// copy symbol table
2673 	int32 symbolsToCopy = min_c(symbolCount, maxSymbolCount);
2674 	if (symbolTable != NULL && symbolsToCopy > 0) {
2675 		if (kernel) {
2676 			memcpy(symbolTable, symbols, sizeof(elf_sym) * symbolsToCopy);
2677 		} else if (user_memcpy(symbolTable, symbols,
2678 				sizeof(elf_sym) * symbolsToCopy) != B_OK) {
2679 			return B_BAD_ADDRESS;
2680 		}
2681 	}
2682 
2683 	// copy string table
2684 	size_t stringsToCopy = min_c(stringTableSize, maxStringTableSize);
2685 	if (stringTable != NULL && stringsToCopy > 0) {
2686 		if (kernel) {
2687 			memcpy(stringTable, strings, stringsToCopy);
2688 		} else {
2689 			if (user_memcpy(stringTable, strings, stringsToCopy)
2690 					!= B_OK) {
2691 				return B_BAD_ADDRESS;
2692 			}
2693 		}
2694 	}
2695 
2696 	// copy sizes
2697 	if (kernel) {
2698 		*_symbolCount = symbolCount;
2699 		*_stringTableSize = stringTableSize;
2700 		if (_imageDelta != NULL)
2701 			*_imageDelta = imageDelta;
2702 	} else {
2703 		if (user_memcpy(_symbolCount, &symbolCount, sizeof(symbolCount)) != B_OK
2704 			|| user_memcpy(_stringTableSize, &stringTableSize,
2705 					sizeof(stringTableSize)) != B_OK
2706 			|| (_imageDelta != NULL && user_memcpy(_imageDelta, &imageDelta,
2707 					sizeof(imageDelta)) != B_OK)) {
2708 			return B_BAD_ADDRESS;
2709 		}
2710 	}
2711 
2712 	return B_OK;
2713 }
2714 
2715 
2716 status_t
2717 elf_init(kernel_args* args)
2718 {
2719 	struct preloaded_image* image;
2720 
2721 	image_init();
2722 
2723 	if (void* handle = load_driver_settings("kernel")) {
2724 		sLoadElfSymbols = get_driver_boolean_parameter(handle, "load_symbols",
2725 			false, false);
2726 
2727 		unload_driver_settings(handle);
2728 	}
2729 
2730 	sImagesHash = new(std::nothrow) ImageHash();
2731 	if (sImagesHash == NULL)
2732 		return B_NO_MEMORY;
2733 	status_t init = sImagesHash->Init(IMAGE_HASH_SIZE);
2734 	if (init != B_OK)
2735 		return init;
2736 
2737 	// Build a image structure for the kernel, which has already been loaded.
2738 	// The preloaded_images were already prepared by the VM.
2739 	image = args->kernel_image;
2740 	if (insert_preloaded_image(static_cast<preloaded_elf_image *>(image),
2741 			true) < B_OK)
2742 		panic("could not create kernel image.\n");
2743 
2744 	// Build image structures for all preloaded images.
2745 	for (image = args->preloaded_images; image != NULL; image = image->next)
2746 		insert_preloaded_image(static_cast<preloaded_elf_image *>(image),
2747 			false);
2748 
2749 	add_debugger_command("ls", &dump_address_info,
2750 		"lookup symbol for a particular address");
2751 	add_debugger_command("symbols", &dump_symbols, "dump symbols for image");
2752 	add_debugger_command("symbol", &dump_symbol, "search symbol in images");
2753 	add_debugger_command_etc("image", &dump_image, "dump image info",
2754 		"Prints info about the specified image.\n"
2755 		"  <image>  - pointer to the semaphore structure, or ID\n"
2756 		"           of the image to print info for.\n", 0);
2757 
2758 	sInitialized = true;
2759 	return B_OK;
2760 }
2761 
2762 
2763 // #pragma mark -
2764 
2765 
2766 /*!	Reads the symbol and string table for the kernel image with the given ID.
2767 	\a _symbolCount and \a _stringTableSize are both in- and output parameters.
2768 	When called they call the size of the buffers given by \a symbolTable and
2769 	\a stringTable respectively. When the function returns successfully, they
2770 	will contain the actual sizes (which can be greater than the original ones).
2771 	The function will copy as much as possible into the buffers. For only
2772 	getting the required buffer sizes, it can be invoked with \c NULL buffers.
2773 	On success \a _imageDelta will contain the offset to be added to the symbol
2774 	values in the table to get the actual symbol addresses.
2775 */
2776 status_t
2777 _user_read_kernel_image_symbols(image_id id, elf_sym* symbolTable,
2778 	int32* _symbolCount, char* stringTable, size_t* _stringTableSize,
2779 	addr_t* _imageDelta)
2780 {
2781 	return elf_read_kernel_image_symbols(id, symbolTable, _symbolCount,
2782 		stringTable, _stringTableSize, _imageDelta, false);
2783 }
2784 
2785 #endif // ELF32_COMPAT
2786 
2787