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