libroot_debug: Merge guarded heap into libroot_debug.
[haiku.git] / src / system / kernel / elf.cpp
blob66764f71abe26e79746c5b7014f0237289692df7
1 /*
2 * Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de.
4 * Distributed under the terms of the MIT License.
6 * Copyright 2001, Travis Geiselbrecht. All rights reserved.
7 * Distributed under the terms of the NewOS License.
8 */
10 /*! Contains the ELF loader */
13 #include <elf.h>
15 #include <OS.h>
17 #include <unistd.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <stdio.h>
21 #include <ctype.h>
23 #include <algorithm>
25 #include <AutoDeleter.h>
26 #include <commpage.h>
27 #include <boot/kernel_args.h>
28 #include <debug.h>
29 #include <image_defs.h>
30 #include <kernel.h>
31 #include <kimage.h>
32 #include <syscalls.h>
33 #include <team.h>
34 #include <thread.h>
35 #include <runtime_loader.h>
36 #include <util/AutoLock.h>
37 #include <vfs.h>
38 #include <vm/vm.h>
39 #include <vm/vm_types.h>
40 #include <vm/VMAddressSpace.h>
41 #include <vm/VMArea.h>
43 #include <arch/cpu.h>
44 #include <arch/elf.h>
45 #include <elf_priv.h>
46 #include <boot/elf.h>
48 //#define TRACE_ELF
49 #ifdef TRACE_ELF
50 # define TRACE(x) dprintf x
51 #else
52 # define TRACE(x) ;
53 #endif
56 #define IMAGE_HASH_SIZE 16
58 struct ImageHashDefinition {
59 typedef struct elf_image_info ValueType;
60 typedef image_id KeyType;
62 size_t Hash(ValueType* entry) const
63 { return HashKey(entry->id); }
64 ValueType*& GetLink(ValueType* entry) const
65 { return entry->next; }
67 size_t HashKey(KeyType key) const
69 return (size_t)key;
72 bool Compare(KeyType key, ValueType* entry) const
74 return key == entry->id;
78 typedef BOpenHashTable<ImageHashDefinition> ImageHash;
80 static ImageHash *sImagesHash;
82 static struct elf_image_info *sKernelImage = NULL;
83 static mutex sImageMutex = MUTEX_INITIALIZER("kimages_lock");
84 // guards sImagesHash
85 static mutex sImageLoadMutex = MUTEX_INITIALIZER("kimages_load_lock");
86 // serializes loading/unloading add-ons locking order
87 // sImageLoadMutex -> sImageMutex
88 static bool sInitialized = false;
91 static elf_sym *elf_find_symbol(struct elf_image_info *image, const char *name,
92 const elf_version_info *version, bool lookupDefault);
95 static void
96 unregister_elf_image(struct elf_image_info *image)
98 unregister_image(team_get_kernel_team(), image->id);
99 sImagesHash->Remove(image);
103 static void
104 register_elf_image(struct elf_image_info *image)
106 image_info imageInfo;
108 memset(&imageInfo, 0, sizeof(image_info));
109 imageInfo.id = image->id;
110 imageInfo.type = B_SYSTEM_IMAGE;
111 strlcpy(imageInfo.name, image->name, sizeof(imageInfo.name));
113 imageInfo.text = (void *)image->text_region.start;
114 imageInfo.text_size = image->text_region.size;
115 imageInfo.data = (void *)image->data_region.start;
116 imageInfo.data_size = image->data_region.size;
118 if (image->text_region.id >= 0) {
119 // evaluate the API/ABI version symbols
121 // Haiku API version
122 imageInfo.api_version = 0;
123 elf_sym* symbol = elf_find_symbol(image,
124 B_SHARED_OBJECT_HAIKU_VERSION_VARIABLE_NAME, NULL, true);
125 if (symbol != NULL && symbol->st_shndx != SHN_UNDEF
126 && symbol->st_value > 0
127 && symbol->Type() == STT_OBJECT
128 && symbol->st_size >= sizeof(uint32)) {
129 addr_t symbolAddress = symbol->st_value + image->text_region.delta;
130 if (symbolAddress >= image->text_region.start
131 && symbolAddress - image->text_region.start + sizeof(uint32)
132 <= image->text_region.size) {
133 imageInfo.api_version = *(uint32*)symbolAddress;
137 // Haiku ABI
138 imageInfo.abi = 0;
139 symbol = elf_find_symbol(image,
140 B_SHARED_OBJECT_HAIKU_ABI_VARIABLE_NAME, NULL, true);
141 if (symbol != NULL && symbol->st_shndx != SHN_UNDEF
142 && symbol->st_value > 0
143 && symbol->Type() == STT_OBJECT
144 && symbol->st_size >= sizeof(uint32)) {
145 addr_t symbolAddress = symbol->st_value + image->text_region.delta;
146 if (symbolAddress >= image->text_region.start
147 && symbolAddress - image->text_region.start + sizeof(uint32)
148 <= image->text_region.size) {
149 imageInfo.api_version = *(uint32*)symbolAddress;
152 } else {
153 // in-memory image -- use the current values
154 imageInfo.api_version = B_HAIKU_VERSION;
155 imageInfo.abi = B_HAIKU_ABI;
158 image->id = register_image(team_get_kernel_team(), &imageInfo,
159 sizeof(image_info));
160 sImagesHash->Insert(image);
164 /*! Note, you must lock the image mutex when you call this function. */
165 static struct elf_image_info *
166 find_image_at_address(addr_t address)
168 #if KDEBUG
169 if (!debug_debugger_running())
170 ASSERT_LOCKED_MUTEX(&sImageMutex);
171 #endif
173 ImageHash::Iterator iterator(sImagesHash);
175 // get image that may contain the address
177 while (iterator.HasNext()) {
178 struct elf_image_info* image = iterator.Next();
179 if ((address >= image->text_region.start && address
180 <= (image->text_region.start + image->text_region.size))
181 || (address >= image->data_region.start
182 && address
183 <= (image->data_region.start + image->data_region.size)))
184 return image;
187 return NULL;
191 static int
192 dump_address_info(int argc, char **argv)
194 const char *symbol, *imageName;
195 bool exactMatch;
196 addr_t address, baseAddress;
198 if (argc < 2) {
199 kprintf("usage: ls <address>\n");
200 return 0;
203 address = strtoul(argv[1], NULL, 16);
205 status_t error;
207 if (IS_KERNEL_ADDRESS(address)) {
208 error = elf_debug_lookup_symbol_address(address, &baseAddress, &symbol,
209 &imageName, &exactMatch);
210 } else {
211 error = elf_debug_lookup_user_symbol_address(
212 debug_get_debugged_thread()->team, address, &baseAddress, &symbol,
213 &imageName, &exactMatch);
216 if (error == B_OK) {
217 kprintf("%p = %s + 0x%lx (%s)%s\n", (void*)address, symbol,
218 address - baseAddress, imageName, exactMatch ? "" : " (nearest)");
219 } else
220 kprintf("There is no image loaded at this address!\n");
222 return 0;
226 static struct elf_image_info *
227 find_image(image_id id)
229 return sImagesHash->Lookup(id);
233 static struct elf_image_info *
234 find_image_by_vnode(void *vnode)
236 MutexLocker locker(sImageMutex);
238 ImageHash::Iterator iterator(sImagesHash);
239 while (iterator.HasNext()) {
240 struct elf_image_info* image = iterator.Next();
241 if (image->vnode == vnode)
242 return image;
245 return NULL;
249 static struct elf_image_info *
250 create_image_struct()
252 struct elf_image_info *image
253 = (struct elf_image_info *)malloc(sizeof(struct elf_image_info));
254 if (image == NULL)
255 return NULL;
257 memset(image, 0, sizeof(struct elf_image_info));
259 image->text_region.id = -1;
260 image->data_region.id = -1;
261 image->ref_count = 1;
263 return image;
267 static void
268 delete_elf_image(struct elf_image_info *image)
270 if (image->text_region.id >= 0)
271 delete_area(image->text_region.id);
273 if (image->data_region.id >= 0)
274 delete_area(image->data_region.id);
276 if (image->vnode)
277 vfs_put_vnode(image->vnode);
279 free(image->versions);
280 free(image->debug_symbols);
281 free((void*)image->debug_string_table);
282 free(image->elf_header);
283 free(image->name);
284 free(image);
288 static uint32
289 elf_hash(const char *name)
291 uint32 hash = 0;
292 uint32 temp;
294 while (*name) {
295 hash = (hash << 4) + (uint8)*name++;
296 if ((temp = hash & 0xf0000000) != 0)
297 hash ^= temp >> 24;
298 hash &= ~temp;
300 return hash;
304 static const char *
305 get_symbol_type_string(elf_sym *symbol)
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 "----";
320 static const char *
321 get_symbol_bind_string(elf_sym *symbol)
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 "----";
336 /*! Searches a symbol (pattern) in all kernel images */
337 static int
338 dump_symbol(int argc, char **argv)
340 if (argc != 2 || !strcmp(argv[1], "--help")) {
341 kprintf("usage: %s <symbol-name>\n", argv[0]);
342 return 0;
345 struct elf_image_info *image = NULL;
346 const char *pattern = argv[1];
348 void* symbolAddress = NULL;
350 ImageHash::Iterator iterator(sImagesHash);
351 while (iterator.HasNext()) {
352 image = iterator.Next();
353 if (image->num_debug_symbols > 0) {
354 // search extended debug symbol table (contains static symbols)
355 for (uint32 i = 0; i < image->num_debug_symbols; i++) {
356 elf_sym *symbol = &image->debug_symbols[i];
357 const char *name = image->debug_string_table + symbol->st_name;
359 if (symbol->st_value > 0 && strstr(name, pattern) != 0) {
360 symbolAddress
361 = (void*)(symbol->st_value + image->text_region.delta);
362 kprintf("%p %5lu %s:%s\n", symbolAddress, symbol->st_size,
363 image->name, name);
366 } else {
367 // search standard symbol lookup table
368 for (uint32 i = 0; i < HASHTABSIZE(image); i++) {
369 for (uint32 j = HASHBUCKETS(image)[i]; j != STN_UNDEF;
370 j = HASHCHAINS(image)[j]) {
371 elf_sym *symbol = &image->syms[j];
372 const char *name = SYMNAME(image, symbol);
374 if (symbol->st_value > 0 && strstr(name, pattern) != 0) {
375 symbolAddress = (void*)(symbol->st_value
376 + image->text_region.delta);
377 kprintf("%p %5lu %s:%s\n", symbolAddress,
378 symbol->st_size, image->name, name);
385 if (symbolAddress != NULL)
386 set_debug_variable("_", (addr_t)symbolAddress);
388 return 0;
392 static int
393 dump_symbols(int argc, char **argv)
395 struct elf_image_info *image = NULL;
396 uint32 i;
398 // if the argument looks like a hex number, treat it as such
399 if (argc > 1) {
400 if (isdigit(argv[1][0])) {
401 addr_t num = strtoul(argv[1], NULL, 0);
403 if (IS_KERNEL_ADDRESS(num)) {
404 // find image at address
406 ImageHash::Iterator iterator(sImagesHash);
407 while (iterator.HasNext()) {
408 elf_image_info* current = iterator.Next();
409 if (current->text_region.start <= num
410 && current->text_region.start
411 + current->text_region.size >= num) {
412 image = current;
413 break;
417 if (image == NULL) {
418 kprintf("No image covers %#" B_PRIxADDR " in the kernel!\n",
419 num);
421 } else {
422 image = sImagesHash->Lookup(num);
423 if (image == NULL) {
424 kprintf("image %#" B_PRIxADDR " doesn't exist in the "
425 "kernel!\n", num);
428 } else {
429 // look for image by name
430 ImageHash::Iterator iterator(sImagesHash);
431 while (iterator.HasNext()) {
432 elf_image_info* current = iterator.Next();
433 if (!strcmp(current->name, argv[1])) {
434 image = current;
435 break;
439 if (image == NULL)
440 kprintf("No image \"%s\" found in kernel!\n", argv[1]);
442 } else {
443 kprintf("usage: %s image_name/image_id/address_in_image\n", argv[0]);
444 return 0;
447 if (image == NULL)
448 return -1;
450 // dump symbols
452 kprintf("Symbols of image %" B_PRId32 " \"%s\":\n", image->id, image->name);
453 kprintf("%-*s Type Size Name\n", B_PRINTF_POINTER_WIDTH, "Address");
455 if (image->num_debug_symbols > 0) {
456 // search extended debug symbol table (contains static symbols)
457 for (i = 0; i < image->num_debug_symbols; i++) {
458 elf_sym *symbol = &image->debug_symbols[i];
460 if (symbol->st_value == 0 || symbol->st_size
461 >= image->text_region.size + image->data_region.size)
462 continue;
464 kprintf("%0*lx %s/%s %5ld %s\n", B_PRINTF_POINTER_WIDTH,
465 symbol->st_value + image->text_region.delta,
466 get_symbol_type_string(symbol), get_symbol_bind_string(symbol),
467 symbol->st_size, image->debug_string_table + symbol->st_name);
469 } else {
470 int32 j;
472 // search standard symbol lookup table
473 for (i = 0; i < HASHTABSIZE(image); i++) {
474 for (j = HASHBUCKETS(image)[i]; j != STN_UNDEF;
475 j = HASHCHAINS(image)[j]) {
476 elf_sym *symbol = &image->syms[j];
478 if (symbol->st_value == 0 || symbol->st_size
479 >= image->text_region.size + image->data_region.size)
480 continue;
482 kprintf("%08lx %s/%s %5ld %s\n",
483 symbol->st_value + image->text_region.delta,
484 get_symbol_type_string(symbol),
485 get_symbol_bind_string(symbol),
486 symbol->st_size, SYMNAME(image, symbol));
491 return 0;
495 static void
496 dump_elf_region(struct elf_region *region, const char *name)
498 kprintf(" %s.id %" B_PRId32 "\n", name, region->id);
499 kprintf(" %s.start %#" B_PRIxADDR "\n", name, region->start);
500 kprintf(" %s.size %#" B_PRIxSIZE "\n", name, region->size);
501 kprintf(" %s.delta %ld\n", name, region->delta);
505 static void
506 dump_image_info(struct elf_image_info *image)
508 kprintf("elf_image_info at %p:\n", image);
509 kprintf(" next %p\n", image->next);
510 kprintf(" id %" B_PRId32 "\n", image->id);
511 dump_elf_region(&image->text_region, "text");
512 dump_elf_region(&image->data_region, "data");
513 kprintf(" dynamic_section %#" B_PRIxADDR "\n", image->dynamic_section);
514 kprintf(" needed %p\n", image->needed);
515 kprintf(" symhash %p\n", image->symhash);
516 kprintf(" syms %p\n", image->syms);
517 kprintf(" strtab %p\n", image->strtab);
518 kprintf(" rel %p\n", image->rel);
519 kprintf(" rel_len %#x\n", image->rel_len);
520 kprintf(" rela %p\n", image->rela);
521 kprintf(" rela_len %#x\n", image->rela_len);
522 kprintf(" pltrel %p\n", image->pltrel);
523 kprintf(" pltrel_len %#x\n", image->pltrel_len);
525 kprintf(" debug_symbols %p (%" B_PRIu32 ")\n",
526 image->debug_symbols, image->num_debug_symbols);
530 static int
531 dump_image(int argc, char **argv)
533 struct elf_image_info *image;
535 // if the argument looks like a hex number, treat it as such
536 if (argc > 1) {
537 addr_t num = strtoul(argv[1], NULL, 0);
539 if (IS_KERNEL_ADDRESS(num)) {
540 // semi-hack
541 dump_image_info((struct elf_image_info *)num);
542 } else {
543 image = sImagesHash->Lookup(num);
544 if (image == NULL) {
545 kprintf("image %#" B_PRIxADDR " doesn't exist in the kernel!\n",
546 num);
547 } else
548 dump_image_info(image);
550 return 0;
553 kprintf("loaded kernel images:\n");
555 ImageHash::Iterator iterator(sImagesHash);
557 while (iterator.HasNext()) {
558 image = iterator.Next();
559 kprintf("%p (%" B_PRId32 ") %s\n", image, image->id, image->name);
562 return 0;
566 // Currently unused
567 #if 0
568 static
569 void dump_symbol(struct elf_image_info *image, elf_sym *sym)
572 kprintf("symbol at %p, in image %p\n", sym, image);
574 kprintf(" name index %d, '%s'\n", sym->st_name, SYMNAME(image, sym));
575 kprintf(" st_value 0x%x\n", sym->st_value);
576 kprintf(" st_size %d\n", sym->st_size);
577 kprintf(" st_info 0x%x\n", sym->st_info);
578 kprintf(" st_other 0x%x\n", sym->st_other);
579 kprintf(" st_shndx %d\n", sym->st_shndx);
581 #endif
584 static elf_sym *
585 elf_find_symbol(struct elf_image_info *image, const char *name,
586 const elf_version_info *lookupVersion, bool lookupDefault)
588 if (image->dynamic_section == 0 || HASHTABSIZE(image) == 0)
589 return NULL;
591 elf_sym* versionedSymbol = NULL;
592 uint32 versionedSymbolCount = 0;
594 uint32 hash = elf_hash(name) % HASHTABSIZE(image);
595 for (uint32 i = HASHBUCKETS(image)[hash]; i != STN_UNDEF;
596 i = HASHCHAINS(image)[i]) {
597 elf_sym* symbol = &image->syms[i];
599 // consider only symbols with the right name and binding
600 if (symbol->st_shndx == SHN_UNDEF
601 || ((symbol->Bind() != STB_GLOBAL) && (symbol->Bind() != STB_WEAK))
602 || strcmp(SYMNAME(image, symbol), name) != 0) {
603 continue;
606 // check the version
608 // Handle the simple cases -- the image doesn't have version
609 // information -- first.
610 if (image->symbol_versions == NULL) {
611 if (lookupVersion == NULL) {
612 // No specific symbol version was requested either, so the
613 // symbol is just fine.
614 return symbol;
617 // A specific version is requested. Since the only possible
618 // dependency is the kernel itself, the add-on was obviously linked
619 // against a newer kernel.
620 dprintf("Kernel add-on requires version support, but the kernel "
621 "is too old.\n");
622 return NULL;
625 // The image has version information. Let's see what we've got.
626 uint32 versionID = image->symbol_versions[i];
627 uint32 versionIndex = VER_NDX(versionID);
628 elf_version_info& version = image->versions[versionIndex];
630 // skip local versions
631 if (versionIndex == VER_NDX_LOCAL)
632 continue;
634 if (lookupVersion != NULL) {
635 // a specific version is requested
637 // compare the versions
638 if (version.hash == lookupVersion->hash
639 && strcmp(version.name, lookupVersion->name) == 0) {
640 // versions match
641 return symbol;
644 // The versions don't match. We're still fine with the
645 // base version, if it is public and we're not looking for
646 // the default version.
647 if ((versionID & VER_NDX_FLAG_HIDDEN) == 0
648 && versionIndex == VER_NDX_GLOBAL
649 && !lookupDefault) {
650 // TODO: Revise the default version case! That's how
651 // FreeBSD implements it, but glibc doesn't handle it
652 // specially.
653 return symbol;
655 } else {
656 // No specific version requested, but the image has version
657 // information. This can happen in either of these cases:
659 // * The dependent object was linked against an older version
660 // of the now versioned dependency.
661 // * The symbol is looked up via find_image_symbol() or dlsym().
663 // In the first case we return the base version of the symbol
664 // (VER_NDX_GLOBAL or VER_NDX_INITIAL), or, if that doesn't
665 // exist, the unique, non-hidden versioned symbol.
667 // In the second case we want to return the public default
668 // version of the symbol. The handling is pretty similar to the
669 // first case, with the exception that we treat VER_NDX_INITIAL
670 // as regular version.
672 // VER_NDX_GLOBAL is always good, VER_NDX_INITIAL is fine, if
673 // we don't look for the default version.
674 if (versionIndex == VER_NDX_GLOBAL
675 || (!lookupDefault && versionIndex == VER_NDX_INITIAL)) {
676 return symbol;
679 // If not hidden, remember the version -- we'll return it, if
680 // it is the only one.
681 if ((versionID & VER_NDX_FLAG_HIDDEN) == 0) {
682 versionedSymbolCount++;
683 versionedSymbol = symbol;
688 return versionedSymbolCount == 1 ? versionedSymbol : NULL;
692 static status_t
693 elf_parse_dynamic_section(struct elf_image_info *image)
695 elf_dyn *d;
696 ssize_t neededOffset = -1;
698 TRACE(("top of elf_parse_dynamic_section\n"));
700 image->symhash = 0;
701 image->syms = 0;
702 image->strtab = 0;
704 d = (elf_dyn *)image->dynamic_section;
705 if (!d)
706 return B_ERROR;
708 for (int32 i = 0; d[i].d_tag != DT_NULL; i++) {
709 switch (d[i].d_tag) {
710 case DT_NEEDED:
711 neededOffset = d[i].d_un.d_ptr + image->text_region.delta;
712 break;
713 case DT_HASH:
714 image->symhash = (uint32 *)(d[i].d_un.d_ptr
715 + image->text_region.delta);
716 break;
717 case DT_STRTAB:
718 image->strtab = (char *)(d[i].d_un.d_ptr
719 + image->text_region.delta);
720 break;
721 case DT_SYMTAB:
722 image->syms = (elf_sym *)(d[i].d_un.d_ptr
723 + image->text_region.delta);
724 break;
725 case DT_REL:
726 image->rel = (elf_rel *)(d[i].d_un.d_ptr
727 + image->text_region.delta);
728 break;
729 case DT_RELSZ:
730 image->rel_len = d[i].d_un.d_val;
731 break;
732 case DT_RELA:
733 image->rela = (elf_rela *)(d[i].d_un.d_ptr
734 + image->text_region.delta);
735 break;
736 case DT_RELASZ:
737 image->rela_len = d[i].d_un.d_val;
738 break;
739 case DT_JMPREL:
740 image->pltrel = (elf_rel *)(d[i].d_un.d_ptr
741 + image->text_region.delta);
742 break;
743 case DT_PLTRELSZ:
744 image->pltrel_len = d[i].d_un.d_val;
745 break;
746 case DT_PLTREL:
747 image->pltrel_type = d[i].d_un.d_val;
748 break;
749 case DT_VERSYM:
750 image->symbol_versions = (elf_versym*)
751 (d[i].d_un.d_ptr + image->text_region.delta);
752 break;
753 case DT_VERDEF:
754 image->version_definitions = (elf_verdef*)
755 (d[i].d_un.d_ptr + image->text_region.delta);
756 break;
757 case DT_VERDEFNUM:
758 image->num_version_definitions = d[i].d_un.d_val;
759 break;
760 case DT_VERNEED:
761 image->needed_versions = (elf_verneed*)
762 (d[i].d_un.d_ptr + image->text_region.delta);
763 break;
764 case DT_VERNEEDNUM:
765 image->num_needed_versions = d[i].d_un.d_val;
766 break;
767 case DT_SYMBOLIC:
768 image->symbolic = true;
769 break;
770 case DT_FLAGS:
772 uint32 flags = d[i].d_un.d_val;
773 if ((flags & DF_SYMBOLIC) != 0)
774 image->symbolic = true;
775 break;
778 default:
779 continue;
783 // lets make sure we found all the required sections
784 if (!image->symhash || !image->syms || !image->strtab)
785 return B_ERROR;
787 TRACE(("needed_offset = %ld\n", neededOffset));
789 if (neededOffset >= 0)
790 image->needed = STRING(image, neededOffset);
792 return B_OK;
796 static status_t
797 assert_defined_image_version(elf_image_info* dependentImage,
798 elf_image_info* image, const elf_version_info& neededVersion, bool weak)
800 // If the image doesn't have version definitions, we print a warning and
801 // succeed. Weird, but that's how glibc does it. Not unlikely we'll fail
802 // later when resolving versioned symbols.
803 if (image->version_definitions == NULL) {
804 dprintf("%s: No version information available (required by %s)\n",
805 image->name, dependentImage->name);
806 return B_OK;
809 // iterate through the defined versions to find the given one
810 elf_verdef* definition = image->version_definitions;
811 for (uint32 i = 0; i < image->num_version_definitions; i++) {
812 uint32 versionIndex = VER_NDX(definition->vd_ndx);
813 elf_version_info& info = image->versions[versionIndex];
815 if (neededVersion.hash == info.hash
816 && strcmp(neededVersion.name, info.name) == 0) {
817 return B_OK;
820 definition = (elf_verdef*)
821 ((uint8*)definition + definition->vd_next);
824 // version not found -- fail, if not weak
825 if (!weak) {
826 dprintf("%s: version \"%s\" not found (required by %s)\n", image->name,
827 neededVersion.name, dependentImage->name);
828 return B_MISSING_SYMBOL;
831 return B_OK;
835 static status_t
836 init_image_version_infos(elf_image_info* image)
838 // First find out how many version infos we need -- i.e. get the greatest
839 // version index from the defined and needed versions (they use the same
840 // index namespace).
841 uint32 maxIndex = 0;
843 if (image->version_definitions != NULL) {
844 elf_verdef* definition = image->version_definitions;
845 for (uint32 i = 0; i < image->num_version_definitions; i++) {
846 if (definition->vd_version != 1) {
847 dprintf("Unsupported version definition revision: %u\n",
848 definition->vd_version);
849 return B_BAD_VALUE;
852 uint32 versionIndex = VER_NDX(definition->vd_ndx);
853 if (versionIndex > maxIndex)
854 maxIndex = versionIndex;
856 definition = (elf_verdef*)
857 ((uint8*)definition + definition->vd_next);
861 if (image->needed_versions != NULL) {
862 elf_verneed* needed = image->needed_versions;
863 for (uint32 i = 0; i < image->num_needed_versions; i++) {
864 if (needed->vn_version != 1) {
865 dprintf("Unsupported version needed revision: %u\n",
866 needed->vn_version);
867 return B_BAD_VALUE;
870 elf_vernaux* vernaux
871 = (elf_vernaux*)((uint8*)needed + needed->vn_aux);
872 for (uint32 k = 0; k < needed->vn_cnt; k++) {
873 uint32 versionIndex = VER_NDX(vernaux->vna_other);
874 if (versionIndex > maxIndex)
875 maxIndex = versionIndex;
877 vernaux = (elf_vernaux*)((uint8*)vernaux + vernaux->vna_next);
880 needed = (elf_verneed*)((uint8*)needed + needed->vn_next);
884 if (maxIndex == 0)
885 return B_OK;
887 // allocate the version infos
888 image->versions
889 = (elf_version_info*)malloc(sizeof(elf_version_info) * (maxIndex + 1));
890 if (image->versions == NULL) {
891 dprintf("Memory shortage in init_image_version_infos()\n");
892 return B_NO_MEMORY;
894 image->num_versions = maxIndex + 1;
896 // init the version infos
898 // version definitions
899 if (image->version_definitions != NULL) {
900 elf_verdef* definition = image->version_definitions;
901 for (uint32 i = 0; i < image->num_version_definitions; i++) {
902 if (definition->vd_cnt > 0
903 && (definition->vd_flags & VER_FLG_BASE) == 0) {
904 elf_verdaux* verdaux
905 = (elf_verdaux*)((uint8*)definition + definition->vd_aux);
907 uint32 versionIndex = VER_NDX(definition->vd_ndx);
908 elf_version_info& info = image->versions[versionIndex];
909 info.hash = definition->vd_hash;
910 info.name = STRING(image, verdaux->vda_name);
911 info.file_name = NULL;
914 definition = (elf_verdef*)
915 ((uint8*)definition + definition->vd_next);
919 // needed versions
920 if (image->needed_versions != NULL) {
921 elf_verneed* needed = image->needed_versions;
922 for (uint32 i = 0; i < image->num_needed_versions; i++) {
923 const char* fileName = STRING(image, needed->vn_file);
925 elf_vernaux* vernaux
926 = (elf_vernaux*)((uint8*)needed + needed->vn_aux);
927 for (uint32 k = 0; k < needed->vn_cnt; k++) {
928 uint32 versionIndex = VER_NDX(vernaux->vna_other);
929 elf_version_info& info = image->versions[versionIndex];
930 info.hash = vernaux->vna_hash;
931 info.name = STRING(image, vernaux->vna_name);
932 info.file_name = fileName;
934 vernaux = (elf_vernaux*)((uint8*)vernaux + vernaux->vna_next);
937 needed = (elf_verneed*)((uint8*)needed + needed->vn_next);
941 return B_OK;
945 static status_t
946 check_needed_image_versions(elf_image_info* image)
948 if (image->needed_versions == NULL)
949 return B_OK;
951 elf_verneed* needed = image->needed_versions;
952 for (uint32 i = 0; i < image->num_needed_versions; i++) {
953 elf_image_info* dependency = sKernelImage;
955 elf_vernaux* vernaux
956 = (elf_vernaux*)((uint8*)needed + needed->vn_aux);
957 for (uint32 k = 0; k < needed->vn_cnt; k++) {
958 uint32 versionIndex = VER_NDX(vernaux->vna_other);
959 elf_version_info& info = image->versions[versionIndex];
961 status_t error = assert_defined_image_version(image, dependency,
962 info, (vernaux->vna_flags & VER_FLG_WEAK) != 0);
963 if (error != B_OK)
964 return error;
966 vernaux = (elf_vernaux*)((uint8*)vernaux + vernaux->vna_next);
969 needed = (elf_verneed*)((uint8*)needed + needed->vn_next);
972 return B_OK;
976 /*! Resolves the \a symbol by linking against \a sharedImage if necessary.
977 Returns the resolved symbol's address in \a _symbolAddress.
979 status_t
980 elf_resolve_symbol(struct elf_image_info *image, elf_sym *symbol,
981 struct elf_image_info *sharedImage, addr_t *_symbolAddress)
983 // Local symbols references are always resolved to the given symbol.
984 if (symbol->Bind() == STB_LOCAL) {
985 *_symbolAddress = symbol->st_value + image->text_region.delta;
986 return B_OK;
989 // Non-local symbols we try to resolve to the kernel image first. Unless
990 // the image is linked symbolically, then vice versa.
991 elf_image_info* firstImage = sharedImage;
992 elf_image_info* secondImage = image;
993 if (image->symbolic)
994 std::swap(firstImage, secondImage);
996 const char *symbolName = SYMNAME(image, symbol);
998 // get the version info
999 const elf_version_info* versionInfo = NULL;
1000 if (image->symbol_versions != NULL) {
1001 uint32 index = symbol - image->syms;
1002 uint32 versionIndex = VER_NDX(image->symbol_versions[index]);
1003 if (versionIndex >= VER_NDX_INITIAL)
1004 versionInfo = image->versions + versionIndex;
1007 // find the symbol
1008 elf_image_info* foundImage = firstImage;
1009 elf_sym* foundSymbol = elf_find_symbol(firstImage, symbolName, versionInfo,
1010 false);
1011 if (foundSymbol == NULL
1012 || foundSymbol->Bind() == STB_WEAK) {
1013 // Not found or found a weak definition -- try to resolve in the other
1014 // image.
1015 elf_sym* secondSymbol = elf_find_symbol(secondImage, symbolName,
1016 versionInfo, false);
1017 // If we found a symbol -- take it in case we didn't have a symbol
1018 // before or the new symbol is not weak.
1019 if (secondSymbol != NULL
1020 && (foundSymbol == NULL
1021 || secondSymbol->Bind() != STB_WEAK)) {
1022 foundImage = secondImage;
1023 foundSymbol = secondSymbol;
1027 if (foundSymbol == NULL) {
1028 // Weak undefined symbols get a value of 0, if unresolved.
1029 if (symbol->Bind() == STB_WEAK) {
1030 *_symbolAddress = 0;
1031 return B_OK;
1034 dprintf("\"%s\": could not resolve symbol '%s'\n", image->name,
1035 symbolName);
1036 return B_MISSING_SYMBOL;
1039 // make sure they're the same type
1040 if (symbol->Type() != foundSymbol->Type()) {
1041 dprintf("elf_resolve_symbol: found symbol '%s' in image '%s' "
1042 "(requested by image '%s') but wrong type (%d vs. %d)\n",
1043 symbolName, foundImage->name, image->name,
1044 foundSymbol->Type(), symbol->Type());
1045 return B_MISSING_SYMBOL;
1048 *_symbolAddress = foundSymbol->st_value + foundImage->text_region.delta;
1049 return B_OK;
1053 /*! Until we have shared library support, just this links against the kernel */
1054 static int
1055 elf_relocate(struct elf_image_info* image, struct elf_image_info* resolveImage)
1057 int status = B_NO_ERROR;
1059 TRACE(("elf_relocate(%p (\"%s\"))\n", image, image->name));
1061 // deal with the rels first
1062 if (image->rel) {
1063 TRACE(("total %i rel relocs\n", image->rel_len / (int)sizeof(elf_rel)));
1065 status = arch_elf_relocate_rel(image, resolveImage, image->rel,
1066 image->rel_len);
1067 if (status < B_OK)
1068 return status;
1071 if (image->pltrel) {
1072 if (image->pltrel_type == DT_REL) {
1073 TRACE(("total %i plt-relocs\n",
1074 image->pltrel_len / (int)sizeof(elf_rel)));
1075 status = arch_elf_relocate_rel(image, resolveImage, image->pltrel,
1076 image->pltrel_len);
1077 } else {
1078 TRACE(("total %i plt-relocs\n",
1079 image->pltrel_len / (int)sizeof(elf_rela)));
1080 status = arch_elf_relocate_rela(image, resolveImage,
1081 (elf_rela *)image->pltrel, image->pltrel_len);
1083 if (status < B_OK)
1084 return status;
1087 if (image->rela) {
1088 TRACE(("total %i rel relocs\n",
1089 image->rela_len / (int)sizeof(elf_rela)));
1091 status = arch_elf_relocate_rela(image, resolveImage, image->rela,
1092 image->rela_len);
1093 if (status < B_OK)
1094 return status;
1097 return status;
1101 static int
1102 verify_eheader(elf_ehdr *elfHeader)
1104 if (memcmp(elfHeader->e_ident, ELF_MAGIC, 4) != 0)
1105 return B_NOT_AN_EXECUTABLE;
1107 if (elfHeader->e_ident[4] != ELF_CLASS)
1108 return B_NOT_AN_EXECUTABLE;
1110 if (elfHeader->e_phoff == 0)
1111 return B_NOT_AN_EXECUTABLE;
1113 if (elfHeader->e_phentsize < sizeof(elf_phdr))
1114 return B_NOT_AN_EXECUTABLE;
1116 return 0;
1120 static void
1121 unload_elf_image(struct elf_image_info *image)
1123 if (atomic_add(&image->ref_count, -1) > 1)
1124 return;
1126 TRACE(("unload image %" B_PRId32 ", %s\n", image->id, image->name));
1128 unregister_elf_image(image);
1129 delete_elf_image(image);
1133 static status_t
1134 load_elf_symbol_table(int fd, struct elf_image_info *image)
1136 elf_ehdr *elfHeader = image->elf_header;
1137 elf_sym *symbolTable = NULL;
1138 elf_shdr *stringHeader = NULL;
1139 uint32 numSymbols = 0;
1140 char *stringTable;
1141 status_t status;
1142 ssize_t length;
1143 int32 i;
1145 // get section headers
1147 ssize_t size = elfHeader->e_shnum * elfHeader->e_shentsize;
1148 elf_shdr *sectionHeaders = (elf_shdr *)malloc(size);
1149 if (sectionHeaders == NULL) {
1150 dprintf("error allocating space for section headers\n");
1151 return B_NO_MEMORY;
1154 length = read_pos(fd, elfHeader->e_shoff, sectionHeaders, size);
1155 if (length < size) {
1156 TRACE(("error reading in program headers\n"));
1157 status = B_ERROR;
1158 goto error1;
1161 // find symbol table in section headers
1163 for (i = 0; i < elfHeader->e_shnum; i++) {
1164 if (sectionHeaders[i].sh_type == SHT_SYMTAB) {
1165 stringHeader = &sectionHeaders[sectionHeaders[i].sh_link];
1167 if (stringHeader->sh_type != SHT_STRTAB) {
1168 TRACE(("doesn't link to string table\n"));
1169 status = B_BAD_DATA;
1170 goto error1;
1173 // read in symbol table
1174 size = sectionHeaders[i].sh_size;
1175 symbolTable = (elf_sym *)malloc(size);
1176 if (symbolTable == NULL) {
1177 status = B_NO_MEMORY;
1178 goto error1;
1181 length
1182 = read_pos(fd, sectionHeaders[i].sh_offset, symbolTable, size);
1183 if (length < size) {
1184 TRACE(("error reading in symbol table\n"));
1185 status = B_ERROR;
1186 goto error2;
1189 numSymbols = size / sizeof(elf_sym);
1190 break;
1194 if (symbolTable == NULL) {
1195 TRACE(("no symbol table\n"));
1196 status = B_BAD_VALUE;
1197 goto error1;
1200 // read in string table
1202 stringTable = (char *)malloc(size = stringHeader->sh_size);
1203 if (stringTable == NULL) {
1204 status = B_NO_MEMORY;
1205 goto error2;
1208 length = read_pos(fd, stringHeader->sh_offset, stringTable, size);
1209 if (length < size) {
1210 TRACE(("error reading in string table\n"));
1211 status = B_ERROR;
1212 goto error3;
1215 TRACE(("loaded %" B_PRId32 " debug symbols\n", numSymbols));
1217 // insert tables into image
1218 image->debug_symbols = symbolTable;
1219 image->num_debug_symbols = numSymbols;
1220 image->debug_string_table = stringTable;
1222 free(sectionHeaders);
1223 return B_OK;
1225 error3:
1226 free(stringTable);
1227 error2:
1228 free(symbolTable);
1229 error1:
1230 free(sectionHeaders);
1232 return status;
1236 static status_t
1237 insert_preloaded_image(preloaded_elf_image *preloadedImage, bool kernel)
1239 status_t status;
1241 status = verify_eheader(&preloadedImage->elf_header);
1242 if (status != B_OK)
1243 return status;
1245 elf_image_info *image = create_image_struct();
1246 if (image == NULL)
1247 return B_NO_MEMORY;
1249 image->name = strdup(preloadedImage->name);
1250 image->dynamic_section = preloadedImage->dynamic_section.start;
1252 image->text_region.id = preloadedImage->text_region.id;
1253 image->text_region.start = preloadedImage->text_region.start;
1254 image->text_region.size = preloadedImage->text_region.size;
1255 image->text_region.delta = preloadedImage->text_region.delta;
1256 image->data_region.id = preloadedImage->data_region.id;
1257 image->data_region.start = preloadedImage->data_region.start;
1258 image->data_region.size = preloadedImage->data_region.size;
1259 image->data_region.delta = preloadedImage->data_region.delta;
1261 status = elf_parse_dynamic_section(image);
1262 if (status != B_OK)
1263 goto error1;
1265 status = init_image_version_infos(image);
1266 if (status != B_OK)
1267 goto error1;
1269 if (!kernel) {
1270 status = check_needed_image_versions(image);
1271 if (status != B_OK)
1272 goto error1;
1274 status = elf_relocate(image, sKernelImage);
1275 if (status != B_OK)
1276 goto error1;
1277 } else
1278 sKernelImage = image;
1280 // copy debug symbols to the kernel heap
1281 if (preloadedImage->debug_symbols != NULL) {
1282 int32 debugSymbolsSize = sizeof(elf_sym)
1283 * preloadedImage->num_debug_symbols;
1284 image->debug_symbols = (elf_sym*)malloc(debugSymbolsSize);
1285 if (image->debug_symbols != NULL) {
1286 memcpy(image->debug_symbols, preloadedImage->debug_symbols,
1287 debugSymbolsSize);
1290 image->num_debug_symbols = preloadedImage->num_debug_symbols;
1292 // copy debug string table to the kernel heap
1293 if (preloadedImage->debug_string_table != NULL) {
1294 image->debug_string_table = (char*)malloc(
1295 preloadedImage->debug_string_table_size);
1296 if (image->debug_string_table != NULL) {
1297 memcpy((void*)image->debug_string_table,
1298 preloadedImage->debug_string_table,
1299 preloadedImage->debug_string_table_size);
1303 register_elf_image(image);
1304 preloadedImage->id = image->id;
1305 // modules_init() uses this information to get the preloaded images
1307 // we now no longer need to write to the text area anymore
1308 set_area_protection(image->text_region.id,
1309 B_KERNEL_READ_AREA | B_KERNEL_EXECUTE_AREA);
1311 return B_OK;
1313 error1:
1314 delete_elf_image(image);
1316 preloadedImage->id = -1;
1318 return status;
1322 // #pragma mark - userland symbol lookup
1325 class UserSymbolLookup {
1326 public:
1327 static UserSymbolLookup& Default()
1329 return sLookup;
1332 status_t Init(Team* team)
1334 // find the runtime loader debug area
1335 VMArea* area;
1336 for (VMAddressSpace::AreaIterator it
1337 = team->address_space->GetAreaIterator();
1338 (area = it.Next()) != NULL;) {
1339 if (strcmp(area->name, RUNTIME_LOADER_DEBUG_AREA_NAME) == 0)
1340 break;
1343 if (area == NULL)
1344 return B_ERROR;
1346 // copy the runtime loader data structure
1347 if (!_Read((runtime_loader_debug_area*)area->Base(), fDebugArea))
1348 return B_BAD_ADDRESS;
1350 fTeam = team;
1351 return B_OK;
1354 status_t LookupSymbolAddress(addr_t address, addr_t *_baseAddress,
1355 const char **_symbolName, const char **_imageName, bool *_exactMatch)
1357 // Note, that this function doesn't find all symbols that we would like
1358 // to find. E.g. static functions do not appear in the symbol table
1359 // as function symbols, but as sections without name and size. The
1360 // .symtab section together with the .strtab section, which apparently
1361 // differ from the tables referred to by the .dynamic section, also
1362 // contain proper names and sizes for those symbols. Therefore, to get
1363 // completely satisfying results, we would need to read those tables
1364 // from the shared object.
1366 // get the image for the address
1367 image_t image;
1368 status_t error = _FindImageAtAddress(address, image);
1369 if (error != B_OK) {
1370 // commpage requires special treatment since kernel stores symbol
1371 // information
1372 addr_t commPageAddress = (addr_t)fTeam->commpage_address;
1373 if (address >= commPageAddress
1374 && address < commPageAddress + COMMPAGE_SIZE) {
1375 if (*_imageName)
1376 *_imageName = "commpage";
1377 address -= (addr_t)commPageAddress;
1378 error = elf_debug_lookup_symbol_address(address, _baseAddress,
1379 _symbolName, NULL, _exactMatch);
1380 if (_baseAddress)
1381 *_baseAddress += (addr_t)fTeam->commpage_address;
1383 return error;
1386 strlcpy(fImageName, image.name, sizeof(fImageName));
1388 // symbol hash table size
1389 uint32 hashTabSize;
1390 if (!_Read(image.symhash, hashTabSize))
1391 return B_BAD_ADDRESS;
1393 // remote pointers to hash buckets and chains
1394 const uint32* hashBuckets = image.symhash + 2;
1395 const uint32* hashChains = image.symhash + 2 + hashTabSize;
1397 const elf_region_t& textRegion = image.regions[0];
1399 // search the image for the symbol
1400 elf_sym symbolFound;
1401 addr_t deltaFound = INT_MAX;
1402 bool exactMatch = false;
1404 // to get rid of the erroneous "uninitialized" warnings
1405 symbolFound.st_name = 0;
1406 symbolFound.st_value = 0;
1408 for (uint32 i = 0; i < hashTabSize; i++) {
1409 uint32 bucket;
1410 if (!_Read(&hashBuckets[i], bucket))
1411 return B_BAD_ADDRESS;
1413 for (uint32 j = bucket; j != STN_UNDEF;
1414 _Read(&hashChains[j], j) ? 0 : j = STN_UNDEF) {
1416 elf_sym symbol;
1417 if (!_Read(image.syms + j, symbol))
1418 continue;
1420 // The symbol table contains not only symbols referring to
1421 // functions and data symbols within the shared object, but also
1422 // referenced symbols of other shared objects, as well as
1423 // section and file references. We ignore everything but
1424 // function and data symbols that have an st_value != 0 (0
1425 // seems to be an indication for a symbol defined elsewhere
1426 // -- couldn't verify that in the specs though).
1427 if ((symbol.Type() != STT_FUNC && symbol.Type() != STT_OBJECT)
1428 || symbol.st_value == 0
1429 || symbol.st_value + symbol.st_size + textRegion.delta
1430 > textRegion.vmstart + textRegion.size) {
1431 continue;
1434 // skip symbols starting after the given address
1435 addr_t symbolAddress = symbol.st_value + textRegion.delta;
1436 if (symbolAddress > address)
1437 continue;
1438 addr_t symbolDelta = address - symbolAddress;
1440 if (symbolDelta < deltaFound) {
1441 deltaFound = symbolDelta;
1442 symbolFound = symbol;
1444 if (symbolDelta >= 0 && symbolDelta < symbol.st_size) {
1445 // exact match
1446 exactMatch = true;
1447 break;
1453 if (_imageName)
1454 *_imageName = fImageName;
1456 if (_symbolName) {
1457 *_symbolName = NULL;
1459 if (deltaFound < INT_MAX) {
1460 if (_ReadString(image, symbolFound.st_name, fSymbolName,
1461 sizeof(fSymbolName))) {
1462 *_symbolName = fSymbolName;
1463 } else {
1464 // we can't get its name, so forget the symbol
1465 deltaFound = INT_MAX;
1470 if (_baseAddress) {
1471 if (deltaFound < INT_MAX)
1472 *_baseAddress = symbolFound.st_value + textRegion.delta;
1473 else
1474 *_baseAddress = textRegion.vmstart;
1477 if (_exactMatch)
1478 *_exactMatch = exactMatch;
1480 return B_OK;
1483 status_t _FindImageAtAddress(addr_t address, image_t& image)
1485 image_queue_t imageQueue;
1486 if (!_Read(fDebugArea.loaded_images, imageQueue))
1487 return B_BAD_ADDRESS;
1489 image_t* imageAddress = imageQueue.head;
1490 while (imageAddress != NULL) {
1491 if (!_Read(imageAddress, image))
1492 return B_BAD_ADDRESS;
1494 if (image.regions[0].vmstart <= address
1495 && address < image.regions[0].vmstart + image.regions[0].size) {
1496 return B_OK;
1499 imageAddress = image.next;
1502 return B_ENTRY_NOT_FOUND;
1505 bool _ReadString(const image_t& image, uint32 offset, char* buffer,
1506 size_t bufferSize)
1508 const char* address = image.strtab + offset;
1510 if (!IS_USER_ADDRESS(address))
1511 return false;
1513 if (debug_debugger_running()) {
1514 return debug_strlcpy(B_CURRENT_TEAM, buffer, address, bufferSize)
1515 >= 0;
1517 return user_strlcpy(buffer, address, bufferSize) >= 0;
1520 template<typename T> bool _Read(const T* address, T& data);
1521 // gcc 2.95.3 doesn't like it defined in-place
1523 private:
1524 Team* fTeam;
1525 runtime_loader_debug_area fDebugArea;
1526 char fImageName[B_OS_NAME_LENGTH];
1527 char fSymbolName[256];
1528 static UserSymbolLookup sLookup;
1532 template<typename T>
1533 bool
1534 UserSymbolLookup::_Read(const T* address, T& data)
1536 if (!IS_USER_ADDRESS(address))
1537 return false;
1539 if (debug_debugger_running())
1540 return debug_memcpy(B_CURRENT_TEAM, &data, address, sizeof(T)) == B_OK;
1541 return user_memcpy(&data, address, sizeof(T)) == B_OK;
1545 UserSymbolLookup UserSymbolLookup::sLookup;
1546 // doesn't need construction, but has an Init() method
1549 // #pragma mark - public kernel API
1552 status_t
1553 get_image_symbol(image_id id, const char *name, int32 symbolClass,
1554 void **_symbol)
1556 struct elf_image_info *image;
1557 elf_sym *symbol;
1558 status_t status = B_OK;
1560 TRACE(("get_image_symbol(%s)\n", name));
1562 mutex_lock(&sImageMutex);
1564 image = find_image(id);
1565 if (image == NULL) {
1566 status = B_BAD_IMAGE_ID;
1567 goto done;
1570 symbol = elf_find_symbol(image, name, NULL, true);
1571 if (symbol == NULL || symbol->st_shndx == SHN_UNDEF) {
1572 status = B_ENTRY_NOT_FOUND;
1573 goto done;
1576 // TODO: support the "symbolClass" parameter!
1578 TRACE(("found: %lx (%lx + %lx)\n",
1579 symbol->st_value + image->text_region.delta,
1580 symbol->st_value, image->text_region.delta));
1582 *_symbol = (void *)(symbol->st_value + image->text_region.delta);
1584 done:
1585 mutex_unlock(&sImageMutex);
1586 return status;
1590 // #pragma mark - kernel private API
1593 /*! Looks up a symbol by address in all images loaded in kernel space.
1594 Note, if you need to call this function outside a debugger, make
1595 sure you fix locking and the way it returns its information, first!
1597 status_t
1598 elf_debug_lookup_symbol_address(addr_t address, addr_t *_baseAddress,
1599 const char **_symbolName, const char **_imageName, bool *_exactMatch)
1601 struct elf_image_info *image;
1602 elf_sym *symbolFound = NULL;
1603 const char *symbolName = NULL;
1604 addr_t deltaFound = INT_MAX;
1605 bool exactMatch = false;
1606 status_t status;
1608 TRACE(("looking up %p\n", (void *)address));
1610 if (!sInitialized)
1611 return B_ERROR;
1613 //mutex_lock(&sImageMutex);
1615 image = find_image_at_address(address);
1616 // get image that may contain the address
1618 if (image != NULL) {
1619 addr_t symbolDelta;
1620 uint32 i;
1621 int32 j;
1623 TRACE((" image %p, base = %p, size = %p\n", image,
1624 (void *)image->text_region.start, (void *)image->text_region.size));
1626 if (image->debug_symbols != NULL) {
1627 // search extended debug symbol table (contains static symbols)
1629 TRACE((" searching debug symbols...\n"));
1631 for (i = 0; i < image->num_debug_symbols; i++) {
1632 elf_sym *symbol = &image->debug_symbols[i];
1634 if (symbol->st_value == 0 || symbol->st_size
1635 >= image->text_region.size + image->data_region.size)
1636 continue;
1638 symbolDelta
1639 = address - (symbol->st_value + image->text_region.delta);
1640 if (symbolDelta >= 0 && symbolDelta < symbol->st_size)
1641 exactMatch = true;
1643 if (exactMatch || symbolDelta < deltaFound) {
1644 deltaFound = symbolDelta;
1645 symbolFound = symbol;
1646 symbolName = image->debug_string_table + symbol->st_name;
1648 if (exactMatch)
1649 break;
1652 } else {
1653 // search standard symbol lookup table
1655 TRACE((" searching standard symbols...\n"));
1657 for (i = 0; i < HASHTABSIZE(image); i++) {
1658 for (j = HASHBUCKETS(image)[i]; j != STN_UNDEF;
1659 j = HASHCHAINS(image)[j]) {
1660 elf_sym *symbol = &image->syms[j];
1662 if (symbol->st_value == 0
1663 || symbol->st_size >= image->text_region.size
1664 + image->data_region.size)
1665 continue;
1667 symbolDelta = address - (long)(symbol->st_value
1668 + image->text_region.delta);
1669 if (symbolDelta >= 0 && symbolDelta < symbol->st_size)
1670 exactMatch = true;
1672 if (exactMatch || symbolDelta < deltaFound) {
1673 deltaFound = symbolDelta;
1674 symbolFound = symbol;
1675 symbolName = SYMNAME(image, symbol);
1677 if (exactMatch)
1678 goto symbol_found;
1684 symbol_found:
1686 if (symbolFound != NULL) {
1687 if (_symbolName)
1688 *_symbolName = symbolName;
1689 if (_imageName)
1690 *_imageName = image->name;
1691 if (_baseAddress)
1692 *_baseAddress = symbolFound->st_value + image->text_region.delta;
1693 if (_exactMatch)
1694 *_exactMatch = exactMatch;
1696 status = B_OK;
1697 } else if (image != NULL) {
1698 TRACE(("symbol not found!\n"));
1700 if (_symbolName)
1701 *_symbolName = NULL;
1702 if (_imageName)
1703 *_imageName = image->name;
1704 if (_baseAddress)
1705 *_baseAddress = image->text_region.start;
1706 if (_exactMatch)
1707 *_exactMatch = false;
1709 status = B_OK;
1710 } else {
1711 TRACE(("image not found!\n"));
1712 status = B_ENTRY_NOT_FOUND;
1715 // Note, theoretically, all information we return back to our caller
1716 // would have to be locked - but since this function is only called
1717 // from the debugger, it's safe to do it this way
1719 //mutex_unlock(&sImageMutex);
1721 return status;
1725 /*! Tries to find a matching user symbol for the given address.
1726 Note that the given team's address space must already be in effect.
1728 status_t
1729 elf_debug_lookup_user_symbol_address(Team* team, addr_t address,
1730 addr_t *_baseAddress, const char **_symbolName, const char **_imageName,
1731 bool *_exactMatch)
1733 if (team == NULL || team == team_get_kernel_team())
1734 return B_BAD_VALUE;
1736 UserSymbolLookup& lookup = UserSymbolLookup::Default();
1737 status_t error = lookup.Init(team);
1738 if (error != B_OK)
1739 return error;
1741 return lookup.LookupSymbolAddress(address, _baseAddress, _symbolName,
1742 _imageName, _exactMatch);
1746 /*! Looks up a symbol in all kernel images. Note, this function is thought to
1747 be used in the kernel debugger, and therefore doesn't perform any locking.
1749 addr_t
1750 elf_debug_lookup_symbol(const char* searchName)
1752 struct elf_image_info *image = NULL;
1754 ImageHash::Iterator iterator(sImagesHash);
1755 while (iterator.HasNext()) {
1756 image = iterator.Next();
1757 if (image->num_debug_symbols > 0) {
1758 // search extended debug symbol table (contains static symbols)
1759 for (uint32 i = 0; i < image->num_debug_symbols; i++) {
1760 elf_sym *symbol = &image->debug_symbols[i];
1761 const char *name = image->debug_string_table + symbol->st_name;
1763 if (symbol->st_value > 0 && !strcmp(name, searchName))
1764 return symbol->st_value + image->text_region.delta;
1766 } else {
1767 // search standard symbol lookup table
1768 for (uint32 i = 0; i < HASHTABSIZE(image); i++) {
1769 for (uint32 j = HASHBUCKETS(image)[i]; j != STN_UNDEF;
1770 j = HASHCHAINS(image)[j]) {
1771 elf_sym *symbol = &image->syms[j];
1772 const char *name = SYMNAME(image, symbol);
1774 if (symbol->st_value > 0 && !strcmp(name, searchName))
1775 return symbol->st_value + image->text_region.delta;
1781 return 0;
1785 status_t
1786 elf_lookup_kernel_symbol(const char* name, elf_symbol_info* info)
1788 // find the symbol
1789 elf_sym* foundSymbol = elf_find_symbol(sKernelImage, name, NULL, false);
1790 if (foundSymbol == NULL)
1791 return B_MISSING_SYMBOL;
1793 info->address = foundSymbol->st_value + sKernelImage->text_region.delta;
1794 info->size = foundSymbol->st_size;
1795 return B_OK;
1799 status_t
1800 elf_load_user_image(const char *path, Team *team, int flags, addr_t *entry)
1802 elf_ehdr elfHeader;
1803 elf_phdr *programHeaders = NULL;
1804 char baseName[B_OS_NAME_LENGTH];
1805 status_t status;
1806 ssize_t length;
1807 int fd;
1808 int i;
1809 addr_t delta = 0;
1810 uint32 addressSpec = B_RANDOMIZED_BASE_ADDRESS;
1811 area_id* mappedAreas = NULL;
1813 TRACE(("elf_load: entry path '%s', team %p\n", path, team));
1815 fd = _kern_open(-1, path, O_RDONLY, 0);
1816 if (fd < 0)
1817 return fd;
1819 struct stat st;
1820 status = _kern_read_stat(fd, NULL, false, &st, sizeof(st));
1821 if (status != B_OK)
1822 return status;
1824 // read and verify the ELF header
1826 length = _kern_read(fd, 0, &elfHeader, sizeof(elfHeader));
1827 if (length < B_OK) {
1828 status = length;
1829 goto error;
1832 if (length != sizeof(elfHeader)) {
1833 // short read
1834 status = B_NOT_AN_EXECUTABLE;
1835 goto error;
1837 status = verify_eheader(&elfHeader);
1838 if (status < B_OK)
1839 goto error;
1841 struct elf_image_info* image;
1842 image = create_image_struct();
1843 if (image == NULL) {
1844 status = B_NO_MEMORY;
1845 goto error;
1847 image->elf_header = &elfHeader;
1849 // read program header
1851 programHeaders = (elf_phdr *)malloc(
1852 elfHeader.e_phnum * elfHeader.e_phentsize);
1853 if (programHeaders == NULL) {
1854 dprintf("error allocating space for program headers\n");
1855 status = B_NO_MEMORY;
1856 goto error2;
1859 TRACE(("reading in program headers at 0x%lx, length 0x%x\n",
1860 elfHeader.e_phoff, elfHeader.e_phnum * elfHeader.e_phentsize));
1861 length = _kern_read(fd, elfHeader.e_phoff, programHeaders,
1862 elfHeader.e_phnum * elfHeader.e_phentsize);
1863 if (length < B_OK) {
1864 status = length;
1865 dprintf("error reading in program headers\n");
1866 goto error2;
1868 if (length != elfHeader.e_phnum * elfHeader.e_phentsize) {
1869 dprintf("short read while reading in program headers\n");
1870 status = -1;
1871 goto error2;
1874 // construct a nice name for the region we have to create below
1876 int32 length;
1878 const char *leaf = strrchr(path, '/');
1879 if (leaf == NULL)
1880 leaf = path;
1881 else
1882 leaf++;
1884 length = strlen(leaf);
1885 if (length > B_OS_NAME_LENGTH - 8)
1886 sprintf(baseName, "...%s", leaf + length + 8 - B_OS_NAME_LENGTH);
1887 else
1888 strcpy(baseName, leaf);
1891 // map the program's segments into memory, initially with rw access
1892 // correct area protection will be set after relocation
1894 mappedAreas = (area_id*)malloc(sizeof(area_id) * elfHeader.e_phnum);
1895 if (mappedAreas == NULL) {
1896 status = B_NO_MEMORY;
1897 goto error2;
1900 image_info imageInfo;
1901 memset(&imageInfo, 0, sizeof(image_info));
1903 for (i = 0; i < elfHeader.e_phnum; i++) {
1904 char regionName[B_OS_NAME_LENGTH];
1905 char *regionAddress;
1906 char *originalRegionAddress;
1907 area_id id;
1909 mappedAreas[i] = -1;
1911 if (programHeaders[i].p_type == PT_DYNAMIC) {
1912 image->dynamic_section = programHeaders[i].p_vaddr;
1913 continue;
1916 if (programHeaders[i].p_type != PT_LOAD)
1917 continue;
1919 regionAddress = (char *)(ROUNDDOWN(programHeaders[i].p_vaddr,
1920 B_PAGE_SIZE) + delta);
1921 originalRegionAddress = regionAddress;
1923 if (programHeaders[i].p_flags & PF_WRITE) {
1924 // rw/data segment
1925 size_t memUpperBound = (programHeaders[i].p_vaddr % B_PAGE_SIZE)
1926 + programHeaders[i].p_memsz;
1927 size_t fileUpperBound = (programHeaders[i].p_vaddr % B_PAGE_SIZE)
1928 + programHeaders[i].p_filesz;
1930 memUpperBound = ROUNDUP(memUpperBound, B_PAGE_SIZE);
1931 fileUpperBound = ROUNDUP(fileUpperBound, B_PAGE_SIZE);
1933 sprintf(regionName, "%s_seg%drw", baseName, i);
1935 id = vm_map_file(team->id, regionName, (void **)&regionAddress,
1936 addressSpec, fileUpperBound,
1937 B_READ_AREA | B_WRITE_AREA, REGION_PRIVATE_MAP, false,
1938 fd, ROUNDDOWN(programHeaders[i].p_offset, B_PAGE_SIZE));
1939 if (id < B_OK) {
1940 dprintf("error mapping file data: %s!\n", strerror(id));
1941 status = B_NOT_AN_EXECUTABLE;
1942 goto error2;
1944 mappedAreas[i] = id;
1946 imageInfo.data = regionAddress;
1947 imageInfo.data_size = memUpperBound;
1949 image->data_region.start = (addr_t)regionAddress;
1950 image->data_region.size = memUpperBound;
1952 // clean garbage brought by mmap (the region behind the file,
1953 // at least parts of it are the bss and have to be zeroed)
1954 addr_t start = (addr_t)regionAddress
1955 + (programHeaders[i].p_vaddr % B_PAGE_SIZE)
1956 + programHeaders[i].p_filesz;
1957 size_t amount = fileUpperBound
1958 - (programHeaders[i].p_vaddr % B_PAGE_SIZE)
1959 - (programHeaders[i].p_filesz);
1960 memset((void *)start, 0, amount);
1962 // Check if we need extra storage for the bss - we have to do this if
1963 // the above region doesn't already comprise the memory size, too.
1965 if (memUpperBound != fileUpperBound) {
1966 size_t bssSize = memUpperBound - fileUpperBound;
1968 snprintf(regionName, B_OS_NAME_LENGTH, "%s_bss%d", baseName, i);
1970 regionAddress += fileUpperBound;
1971 virtual_address_restrictions virtualRestrictions = {};
1972 virtualRestrictions.address = regionAddress;
1973 virtualRestrictions.address_specification = B_EXACT_ADDRESS;
1974 physical_address_restrictions physicalRestrictions = {};
1975 id = create_area_etc(team->id, regionName, bssSize, B_NO_LOCK,
1976 B_READ_AREA | B_WRITE_AREA, 0, 0, &virtualRestrictions,
1977 &physicalRestrictions, (void**)&regionAddress);
1978 if (id < B_OK) {
1979 dprintf("error allocating bss area: %s!\n", strerror(id));
1980 status = B_NOT_AN_EXECUTABLE;
1981 goto error2;
1984 } else {
1985 // assume ro/text segment
1986 snprintf(regionName, B_OS_NAME_LENGTH, "%s_seg%dro", baseName, i);
1988 size_t segmentSize = ROUNDUP(programHeaders[i].p_memsz
1989 + (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE);
1991 id = vm_map_file(team->id, regionName, (void **)&regionAddress,
1992 addressSpec, segmentSize,
1993 B_READ_AREA | B_WRITE_AREA, REGION_PRIVATE_MAP, false, fd,
1994 ROUNDDOWN(programHeaders[i].p_offset, B_PAGE_SIZE));
1995 if (id < B_OK) {
1996 dprintf("error mapping file text: %s!\n", strerror(id));
1997 status = B_NOT_AN_EXECUTABLE;
1998 goto error2;
2001 mappedAreas[i] = id;
2003 imageInfo.text = regionAddress;
2004 imageInfo.text_size = segmentSize;
2006 image->text_region.start = (addr_t)regionAddress;
2007 image->text_region.size = segmentSize;
2010 if (addressSpec != B_EXACT_ADDRESS) {
2011 addressSpec = B_EXACT_ADDRESS;
2012 delta = regionAddress - originalRegionAddress;
2016 image->data_region.delta = delta;
2017 image->text_region.delta = delta;
2019 // modify the dynamic ptr by the delta of the regions
2020 image->dynamic_section += image->text_region.delta;
2022 status = elf_parse_dynamic_section(image);
2023 if (status != B_OK)
2024 goto error2;
2026 status = elf_relocate(image, image);
2027 if (status != B_OK)
2028 goto error2;
2030 // set correct area protection
2031 for (i = 0; i < elfHeader.e_phnum; i++) {
2032 if (mappedAreas[i] == -1)
2033 continue;
2035 uint32 protection = 0;
2037 if (programHeaders[i].p_flags & PF_EXECUTE)
2038 protection |= B_EXECUTE_AREA;
2039 if (programHeaders[i].p_flags & PF_WRITE)
2040 protection |= B_WRITE_AREA;
2041 if (programHeaders[i].p_flags & PF_READ)
2042 protection |= B_READ_AREA;
2044 status = vm_set_area_protection(team->id, mappedAreas[i], protection,
2045 true);
2046 if (status != B_OK)
2047 goto error2;
2050 // register the loaded image
2051 imageInfo.type = B_LIBRARY_IMAGE;
2052 imageInfo.device = st.st_dev;
2053 imageInfo.node = st.st_ino;
2054 strlcpy(imageInfo.name, path, sizeof(imageInfo.name));
2056 imageInfo.api_version = B_HAIKU_VERSION;
2057 imageInfo.abi = B_HAIKU_ABI;
2058 // TODO: Get the actual values for the shared object. Currently only
2059 // the runtime loader is loaded, so this is good enough for the time
2060 // being.
2062 imageInfo.id = register_image(team, &imageInfo, sizeof(image_info));
2063 if (imageInfo.id >= 0 && team_get_current_team_id() == team->id)
2064 user_debug_image_created(&imageInfo);
2065 // Don't care, if registering fails. It's not crucial.
2067 TRACE(("elf_load: done!\n"));
2069 *entry = elfHeader.e_entry + delta;
2070 status = B_OK;
2072 error2:
2073 free(mappedAreas);
2075 image->elf_header = NULL;
2076 delete_elf_image(image);
2078 error:
2079 free(programHeaders);
2080 _kern_close(fd);
2082 return status;
2086 image_id
2087 load_kernel_add_on(const char *path)
2089 elf_phdr *programHeaders;
2090 elf_ehdr *elfHeader;
2091 struct elf_image_info *image;
2092 const char *fileName;
2093 void *reservedAddress;
2094 size_t reservedSize;
2095 status_t status;
2096 ssize_t length;
2097 bool textSectionWritable = false;
2098 int executableHeaderCount = 0;
2100 TRACE(("elf_load_kspace: entry path '%s'\n", path));
2102 int fd = _kern_open(-1, path, O_RDONLY, 0);
2103 if (fd < 0)
2104 return fd;
2106 struct vnode *vnode;
2107 status = vfs_get_vnode_from_fd(fd, true, &vnode);
2108 if (status < B_OK)
2109 goto error0;
2111 // get the file name
2112 fileName = strrchr(path, '/');
2113 if (fileName == NULL)
2114 fileName = path;
2115 else
2116 fileName++;
2118 // Prevent someone else from trying to load this image
2119 mutex_lock(&sImageLoadMutex);
2121 // make sure it's not loaded already. Search by vnode
2122 image = find_image_by_vnode(vnode);
2123 if (image) {
2124 atomic_add(&image->ref_count, 1);
2125 goto done;
2128 elfHeader = (elf_ehdr *)malloc(sizeof(*elfHeader));
2129 if (!elfHeader) {
2130 status = B_NO_MEMORY;
2131 goto error;
2134 length = _kern_read(fd, 0, elfHeader, sizeof(*elfHeader));
2135 if (length < B_OK) {
2136 status = length;
2137 goto error1;
2139 if (length != sizeof(*elfHeader)) {
2140 // short read
2141 status = B_NOT_AN_EXECUTABLE;
2142 goto error1;
2144 status = verify_eheader(elfHeader);
2145 if (status < B_OK)
2146 goto error1;
2148 image = create_image_struct();
2149 if (!image) {
2150 status = B_NO_MEMORY;
2151 goto error1;
2153 image->vnode = vnode;
2154 image->elf_header = elfHeader;
2155 image->name = strdup(path);
2156 vnode = NULL;
2158 programHeaders = (elf_phdr *)malloc(elfHeader->e_phnum
2159 * elfHeader->e_phentsize);
2160 if (programHeaders == NULL) {
2161 dprintf("%s: error allocating space for program headers\n", fileName);
2162 status = B_NO_MEMORY;
2163 goto error2;
2166 TRACE(("reading in program headers at 0x%lx, length 0x%x\n",
2167 elfHeader->e_phoff, elfHeader->e_phnum * elfHeader->e_phentsize));
2169 length = _kern_read(fd, elfHeader->e_phoff, programHeaders,
2170 elfHeader->e_phnum * elfHeader->e_phentsize);
2171 if (length < B_OK) {
2172 status = length;
2173 TRACE(("%s: error reading in program headers\n", fileName));
2174 goto error3;
2176 if (length != elfHeader->e_phnum * elfHeader->e_phentsize) {
2177 TRACE(("%s: short read while reading in program headers\n", fileName));
2178 status = B_ERROR;
2179 goto error3;
2182 // determine how much space we need for all loaded segments
2184 reservedSize = 0;
2185 length = 0;
2187 for (int32 i = 0; i < elfHeader->e_phnum; i++) {
2188 size_t end;
2190 if (programHeaders[i].p_type != PT_LOAD)
2191 continue;
2193 length += ROUNDUP(programHeaders[i].p_memsz
2194 + (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE);
2196 end = ROUNDUP(programHeaders[i].p_memsz + programHeaders[i].p_vaddr,
2197 B_PAGE_SIZE);
2198 if (end > reservedSize)
2199 reservedSize = end;
2201 if (programHeaders[i].IsExecutable())
2202 executableHeaderCount++;
2205 // Check whether the segments have an unreasonable amount of unused space
2206 // inbetween.
2207 if ((ssize_t)reservedSize > length + 8 * 1024) {
2208 status = B_BAD_DATA;
2209 goto error1;
2212 // reserve that space and allocate the areas from that one
2213 if (vm_reserve_address_range(VMAddressSpace::KernelID(), &reservedAddress,
2214 B_ANY_KERNEL_ADDRESS, reservedSize, 0) < B_OK) {
2215 status = B_NO_MEMORY;
2216 goto error3;
2219 image->data_region.size = 0;
2220 image->text_region.size = 0;
2222 for (int32 i = 0; i < elfHeader->e_phnum; i++) {
2223 char regionName[B_OS_NAME_LENGTH];
2224 elf_region *region;
2226 TRACE(("looking at program header %" B_PRId32 "\n", i));
2228 switch (programHeaders[i].p_type) {
2229 case PT_LOAD:
2230 break;
2231 case PT_DYNAMIC:
2232 image->dynamic_section = programHeaders[i].p_vaddr;
2233 continue;
2234 default:
2235 dprintf("%s: unhandled pheader type %#" B_PRIx32 "\n", fileName,
2236 programHeaders[i].p_type);
2237 continue;
2240 // we're here, so it must be a PT_LOAD segment
2242 // Usually add-ons have two PT_LOAD headers: one for .data one or .text.
2243 // x86 and PPC may differ in permission bits for .data's PT_LOAD header
2244 // x86 is usually RW, PPC is RWE
2246 // Some add-ons may have .text and .data concatenated in a single
2247 // PT_LOAD RWE header and we must map that to .text.
2248 if (programHeaders[i].IsReadWrite()
2249 && (!programHeaders[i].IsExecutable()
2250 || executableHeaderCount > 1)) {
2251 // this is the writable segment
2252 if (image->data_region.size != 0) {
2253 // we've already created this segment
2254 continue;
2256 region = &image->data_region;
2258 snprintf(regionName, B_OS_NAME_LENGTH, "%s_data", fileName);
2259 } else if (programHeaders[i].IsExecutable()) {
2260 // this is the non-writable segment
2261 if (image->text_region.size != 0) {
2262 // we've already created this segment
2263 continue;
2265 region = &image->text_region;
2267 // some programs may have .text and .data concatenated in a
2268 // single PT_LOAD section which is readable/writable/executable
2269 textSectionWritable = programHeaders[i].IsReadWrite();
2270 snprintf(regionName, B_OS_NAME_LENGTH, "%s_text", fileName);
2271 } else {
2272 dprintf("%s: weird program header flags %#" B_PRIx32 "\n", fileName,
2273 programHeaders[i].p_flags);
2274 continue;
2277 region->start = (addr_t)reservedAddress + ROUNDDOWN(
2278 programHeaders[i].p_vaddr, B_PAGE_SIZE);
2279 region->size = ROUNDUP(programHeaders[i].p_memsz
2280 + (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE);
2281 region->id = create_area(regionName, (void **)&region->start,
2282 B_EXACT_ADDRESS, region->size, B_FULL_LOCK,
2283 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
2284 if (region->id < B_OK) {
2285 dprintf("%s: error allocating area: %s\n", fileName,
2286 strerror(region->id));
2287 status = B_NOT_AN_EXECUTABLE;
2288 goto error4;
2290 region->delta = -ROUNDDOWN(programHeaders[i].p_vaddr, B_PAGE_SIZE);
2292 TRACE(("elf_load_kspace: created area \"%s\" at %p\n",
2293 regionName, (void *)region->start));
2295 length = _kern_read(fd, programHeaders[i].p_offset,
2296 (void *)(region->start + (programHeaders[i].p_vaddr % B_PAGE_SIZE)),
2297 programHeaders[i].p_filesz);
2298 if (length < B_OK) {
2299 status = length;
2300 dprintf("%s: error reading in segment %" B_PRId32 "\n", fileName,
2302 goto error5;
2306 image->data_region.delta += image->data_region.start;
2307 image->text_region.delta += image->text_region.start;
2309 // modify the dynamic ptr by the delta of the regions
2310 image->dynamic_section += image->text_region.delta;
2312 status = elf_parse_dynamic_section(image);
2313 if (status < B_OK)
2314 goto error5;
2316 status = init_image_version_infos(image);
2317 if (status != B_OK)
2318 goto error5;
2320 status = check_needed_image_versions(image);
2321 if (status != B_OK)
2322 goto error5;
2324 status = elf_relocate(image, sKernelImage);
2325 if (status < B_OK)
2326 goto error5;
2328 // We needed to read in the contents of the "text" area, but
2329 // now we can protect it read-only/execute, unless this is a
2330 // special image with concatenated .text and .data, when it
2331 // will also need write access.
2332 set_area_protection(image->text_region.id,
2333 B_KERNEL_READ_AREA | B_KERNEL_EXECUTE_AREA
2334 | (textSectionWritable ? B_KERNEL_WRITE_AREA : 0));
2336 // There might be a hole between the two segments, and we don't need to
2337 // reserve this any longer
2338 vm_unreserve_address_range(VMAddressSpace::KernelID(), reservedAddress,
2339 reservedSize);
2341 // ToDo: this should be enabled by kernel settings!
2342 if (1)
2343 load_elf_symbol_table(fd, image);
2345 free(programHeaders);
2346 mutex_lock(&sImageMutex);
2347 register_elf_image(image);
2348 mutex_unlock(&sImageMutex);
2350 done:
2351 _kern_close(fd);
2352 mutex_unlock(&sImageLoadMutex);
2354 return image->id;
2356 error5:
2357 error4:
2358 vm_unreserve_address_range(VMAddressSpace::KernelID(), reservedAddress,
2359 reservedSize);
2360 error3:
2361 free(programHeaders);
2362 error2:
2363 delete_elf_image(image);
2364 elfHeader = NULL;
2365 error1:
2366 free(elfHeader);
2367 error:
2368 mutex_unlock(&sImageLoadMutex);
2369 error0:
2370 dprintf("Could not load kernel add-on \"%s\": %s\n", path,
2371 strerror(status));
2373 if (vnode)
2374 vfs_put_vnode(vnode);
2375 _kern_close(fd);
2377 return status;
2381 status_t
2382 unload_kernel_add_on(image_id id)
2384 MutexLocker _(sImageLoadMutex);
2385 MutexLocker _2(sImageMutex);
2387 elf_image_info *image = find_image(id);
2388 if (image == NULL)
2389 return B_BAD_IMAGE_ID;
2391 unload_elf_image(image);
2392 return B_OK;
2396 struct elf_image_info*
2397 elf_get_kernel_image()
2399 return sKernelImage;
2403 status_t
2404 elf_get_image_info_for_address(addr_t address, image_info* info)
2406 MutexLocker _(sImageMutex);
2407 struct elf_image_info* elfInfo = find_image_at_address(address);
2408 if (elfInfo == NULL)
2409 return B_ENTRY_NOT_FOUND;
2411 info->id = elfInfo->id;
2412 info->type = B_SYSTEM_IMAGE;
2413 info->sequence = 0;
2414 info->init_order = 0;
2415 info->init_routine = NULL;
2416 info->term_routine = NULL;
2417 info->device = -1;
2418 info->node = -1;
2419 // TODO: We could actually fill device/node in.
2420 strlcpy(info->name, elfInfo->name, sizeof(info->name));
2421 info->text = (void*)elfInfo->text_region.start;
2422 info->data = (void*)elfInfo->data_region.start;
2423 info->text_size = elfInfo->text_region.size;
2424 info->data_size = elfInfo->data_region.size;
2426 return B_OK;
2430 image_id
2431 elf_create_memory_image(const char* imageName, addr_t text, size_t textSize,
2432 addr_t data, size_t dataSize)
2434 // allocate the image
2435 elf_image_info* image = create_image_struct();
2436 if (image == NULL)
2437 return B_NO_MEMORY;
2438 MemoryDeleter imageDeleter(image);
2440 // allocate symbol and string tables -- we allocate an empty symbol table,
2441 // so that elf_debug_lookup_symbol_address() won't try the dynamic symbol
2442 // table, which we don't have.
2443 elf_sym* symbolTable = (elf_sym*)malloc(0);
2444 char* stringTable = (char*)malloc(1);
2445 MemoryDeleter symbolTableDeleter(symbolTable);
2446 MemoryDeleter stringTableDeleter(stringTable);
2447 if (symbolTable == NULL || stringTable == NULL)
2448 return B_NO_MEMORY;
2450 // the string table always contains the empty string
2451 stringTable[0] = '\0';
2453 image->debug_symbols = symbolTable;
2454 image->num_debug_symbols = 0;
2455 image->debug_string_table = stringTable;
2457 // dup image name
2458 image->name = strdup(imageName);
2459 if (image->name == NULL)
2460 return B_NO_MEMORY;
2462 // data and text region
2463 image->text_region.id = -1;
2464 image->text_region.start = text;
2465 image->text_region.size = textSize;
2466 image->text_region.delta = 0;
2468 image->data_region.id = -1;
2469 image->data_region.start = data;
2470 image->data_region.size = dataSize;
2471 image->data_region.delta = 0;
2473 mutex_lock(&sImageMutex);
2474 register_elf_image(image);
2475 image_id imageID = image->id;
2476 mutex_unlock(&sImageMutex);
2478 // keep the allocated memory
2479 imageDeleter.Detach();
2480 symbolTableDeleter.Detach();
2481 stringTableDeleter.Detach();
2483 return imageID;
2487 status_t
2488 elf_add_memory_image_symbol(image_id id, const char* name, addr_t address,
2489 size_t size, int32 type)
2491 MutexLocker _(sImageMutex);
2493 // get the image
2494 struct elf_image_info* image = find_image(id);
2495 if (image == NULL)
2496 return B_ENTRY_NOT_FOUND;
2498 // get the current string table size
2499 size_t stringTableSize = 1;
2500 if (image->num_debug_symbols > 0) {
2501 for (int32 i = image->num_debug_symbols - 1; i >= 0; i--) {
2502 int32 nameIndex = image->debug_symbols[i].st_name;
2503 if (nameIndex != 0) {
2504 stringTableSize = nameIndex
2505 + strlen(image->debug_string_table + nameIndex) + 1;
2506 break;
2511 // enter the name in the string table
2512 char* stringTable = (char*)image->debug_string_table;
2513 size_t stringIndex = 0;
2514 if (name != NULL) {
2515 size_t nameSize = strlen(name) + 1;
2516 stringIndex = stringTableSize;
2517 stringTableSize += nameSize;
2518 stringTable = (char*)realloc((char*)image->debug_string_table,
2519 stringTableSize);
2520 if (stringTable == NULL)
2521 return B_NO_MEMORY;
2522 image->debug_string_table = stringTable;
2523 memcpy(stringTable + stringIndex, name, nameSize);
2526 // resize the symbol table
2527 int32 symbolCount = image->num_debug_symbols + 1;
2528 elf_sym* symbolTable = (elf_sym*)realloc(
2529 (elf_sym*)image->debug_symbols, sizeof(elf_sym) * symbolCount);
2530 if (symbolTable == NULL)
2531 return B_NO_MEMORY;
2532 image->debug_symbols = symbolTable;
2534 // enter the symbol
2535 elf_sym& symbol = symbolTable[symbolCount - 1];
2536 symbol.SetInfo(STB_GLOBAL,
2537 type == B_SYMBOL_TYPE_DATA ? STT_OBJECT : STT_FUNC);
2538 symbol.st_name = stringIndex;
2539 symbol.st_value = address;
2540 symbol.st_size = size;
2541 symbol.st_other = 0;
2542 symbol.st_shndx = 0;
2543 image->num_debug_symbols++;
2545 return B_OK;
2549 status_t
2550 elf_init(kernel_args *args)
2552 struct preloaded_image *image;
2554 image_init();
2556 sImagesHash = new(std::nothrow) ImageHash();
2557 if (sImagesHash == NULL)
2558 return B_NO_MEMORY;
2559 status_t init = sImagesHash->Init(IMAGE_HASH_SIZE);
2560 if (init != B_OK)
2561 return init;
2563 // Build a image structure for the kernel, which has already been loaded.
2564 // The preloaded_images were already prepared by the VM.
2565 image = args->kernel_image;
2566 if (insert_preloaded_image(static_cast<preloaded_elf_image *>(image),
2567 true) < B_OK)
2568 panic("could not create kernel image.\n");
2570 // Build image structures for all preloaded images.
2571 for (image = args->preloaded_images; image != NULL; image = image->next)
2572 insert_preloaded_image(static_cast<preloaded_elf_image *>(image),
2573 false);
2575 add_debugger_command("ls", &dump_address_info,
2576 "lookup symbol for a particular address");
2577 add_debugger_command("symbols", &dump_symbols, "dump symbols for image");
2578 add_debugger_command("symbol", &dump_symbol, "search symbol in images");
2579 add_debugger_command_etc("image", &dump_image, "dump image info",
2580 "Prints info about the specified image.\n"
2581 " <image> - pointer to the semaphore structure, or ID\n"
2582 " of the image to print info for.\n", 0);
2584 sInitialized = true;
2585 return B_OK;
2589 // #pragma mark -
2592 /*! Reads the symbol and string table for the kernel image with the given ID.
2593 \a _symbolCount and \a _stringTableSize are both in- and output parameters.
2594 When called they call the size of the buffers given by \a symbolTable and
2595 \a stringTable respectively. When the function returns successfully, they
2596 will contain the actual sizes (which can be greater than the original ones).
2597 The function will copy as much as possible into the buffers. For only
2598 getting the required buffer sizes, it can be invoked with \c NULL buffers.
2599 On success \a _imageDelta will contain the offset to be added to the symbol
2600 values in the table to get the actual symbol addresses.
2602 status_t
2603 _user_read_kernel_image_symbols(image_id id, elf_sym* symbolTable,
2604 int32* _symbolCount, char* stringTable, size_t* _stringTableSize,
2605 addr_t* _imageDelta)
2607 // check params
2608 if (_symbolCount == NULL || _stringTableSize == NULL)
2609 return B_BAD_VALUE;
2610 if (!IS_USER_ADDRESS(_symbolCount) || !IS_USER_ADDRESS(_stringTableSize)
2611 || (_imageDelta != NULL && !IS_USER_ADDRESS(_imageDelta))
2612 || (symbolTable != NULL && !IS_USER_ADDRESS(symbolTable))
2613 || (stringTable != NULL && !IS_USER_ADDRESS(stringTable))) {
2614 return B_BAD_ADDRESS;
2617 // get buffer sizes
2618 int32 maxSymbolCount;
2619 size_t maxStringTableSize;
2620 if (user_memcpy(&maxSymbolCount, _symbolCount, sizeof(maxSymbolCount))
2621 != B_OK
2622 || user_memcpy(&maxStringTableSize, _stringTableSize,
2623 sizeof(maxStringTableSize)) != B_OK) {
2624 return B_BAD_ADDRESS;
2627 // find the image
2628 MutexLocker _(sImageMutex);
2629 struct elf_image_info* image = find_image(id);
2630 if (image == NULL)
2631 return B_ENTRY_NOT_FOUND;
2633 // get the tables and infos
2634 addr_t imageDelta = image->text_region.delta;
2635 const elf_sym* symbols;
2636 int32 symbolCount;
2637 const char* strings;
2639 if (image->debug_symbols != NULL) {
2640 symbols = image->debug_symbols;
2641 symbolCount = image->num_debug_symbols;
2642 strings = image->debug_string_table;
2643 } else {
2644 symbols = image->syms;
2645 symbolCount = image->symhash[1];
2646 strings = image->strtab;
2649 // The string table size isn't stored in the elf_image_info structure. Find
2650 // out by iterating through all symbols.
2651 size_t stringTableSize = 0;
2652 for (int32 i = 0; i < symbolCount; i++) {
2653 size_t index = symbols[i].st_name;
2654 if (index > stringTableSize)
2655 stringTableSize = index;
2657 stringTableSize += strlen(strings + stringTableSize) + 1;
2658 // add size of the last string
2660 // copy symbol table
2661 int32 symbolsToCopy = min_c(symbolCount, maxSymbolCount);
2662 if (symbolTable != NULL && symbolsToCopy > 0) {
2663 if (user_memcpy(symbolTable, symbols, sizeof(elf_sym) * symbolsToCopy)
2664 != B_OK) {
2665 return B_BAD_ADDRESS;
2669 // copy string table
2670 size_t stringsToCopy = min_c(stringTableSize, maxStringTableSize);
2671 if (stringTable != NULL && stringsToCopy > 0) {
2672 if (user_memcpy(stringTable, strings, stringsToCopy)
2673 != B_OK) {
2674 return B_BAD_ADDRESS;
2678 // copy sizes
2679 if (user_memcpy(_symbolCount, &symbolCount, sizeof(symbolCount)) != B_OK
2680 || user_memcpy(_stringTableSize, &stringTableSize,
2681 sizeof(stringTableSize)) != B_OK
2682 || (_imageDelta != NULL && user_memcpy(_imageDelta, &imageDelta,
2683 sizeof(imageDelta)) != B_OK)) {
2684 return B_BAD_ADDRESS;
2687 return B_OK;