headers/bsd: Add sys/queue.h.
[haiku.git] / src / system / kernel / elf.cpp
blob77300068fe902cb37c2cad2b10f975a7b0990032
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 namespace {
58 #define IMAGE_HASH_SIZE 16
60 struct ImageHashDefinition {
61 typedef struct elf_image_info ValueType;
62 typedef image_id KeyType;
64 size_t Hash(ValueType* entry) const
65 { return HashKey(entry->id); }
66 ValueType*& GetLink(ValueType* entry) const
67 { return entry->next; }
69 size_t HashKey(KeyType key) const
71 return (size_t)key;
74 bool Compare(KeyType key, ValueType* entry) const
76 return key == entry->id;
80 typedef BOpenHashTable<ImageHashDefinition> ImageHash;
82 } // namespace
85 static ImageHash *sImagesHash;
87 static struct elf_image_info *sKernelImage = NULL;
88 static mutex sImageMutex = MUTEX_INITIALIZER("kimages_lock");
89 // guards sImagesHash
90 static mutex sImageLoadMutex = MUTEX_INITIALIZER("kimages_load_lock");
91 // serializes loading/unloading add-ons locking order
92 // sImageLoadMutex -> sImageMutex
93 static bool sInitialized = false;
96 static elf_sym *elf_find_symbol(struct elf_image_info *image, const char *name,
97 const elf_version_info *version, bool lookupDefault);
100 static void
101 unregister_elf_image(struct elf_image_info *image)
103 unregister_image(team_get_kernel_team(), image->id);
104 sImagesHash->Remove(image);
108 static void
109 register_elf_image(struct elf_image_info *image)
111 extended_image_info imageInfo;
113 memset(&imageInfo, 0, sizeof(imageInfo));
114 imageInfo.basic_info.id = image->id;
115 imageInfo.basic_info.type = B_SYSTEM_IMAGE;
116 strlcpy(imageInfo.basic_info.name, image->name,
117 sizeof(imageInfo.basic_info.name));
119 imageInfo.basic_info.text = (void *)image->text_region.start;
120 imageInfo.basic_info.text_size = image->text_region.size;
121 imageInfo.basic_info.data = (void *)image->data_region.start;
122 imageInfo.basic_info.data_size = image->data_region.size;
124 if (image->text_region.id >= 0) {
125 // evaluate the API/ABI version symbols
127 // Haiku API version
128 imageInfo.basic_info.api_version = 0;
129 elf_sym* symbol = elf_find_symbol(image,
130 B_SHARED_OBJECT_HAIKU_VERSION_VARIABLE_NAME, NULL, true);
131 if (symbol != NULL && symbol->st_shndx != SHN_UNDEF
132 && symbol->st_value > 0
133 && symbol->Type() == STT_OBJECT
134 && symbol->st_size >= sizeof(uint32)) {
135 addr_t symbolAddress = symbol->st_value + image->text_region.delta;
136 if (symbolAddress >= image->text_region.start
137 && symbolAddress - image->text_region.start + sizeof(uint32)
138 <= image->text_region.size) {
139 imageInfo.basic_info.api_version = *(uint32*)symbolAddress;
143 // Haiku ABI
144 imageInfo.basic_info.abi = 0;
145 symbol = elf_find_symbol(image,
146 B_SHARED_OBJECT_HAIKU_ABI_VARIABLE_NAME, NULL, true);
147 if (symbol != NULL && symbol->st_shndx != SHN_UNDEF
148 && symbol->st_value > 0
149 && symbol->Type() == STT_OBJECT
150 && symbol->st_size >= sizeof(uint32)) {
151 addr_t symbolAddress = symbol->st_value + image->text_region.delta;
152 if (symbolAddress >= image->text_region.start
153 && symbolAddress - image->text_region.start + sizeof(uint32)
154 <= image->text_region.size) {
155 imageInfo.basic_info.api_version = *(uint32*)symbolAddress;
158 } else {
159 // in-memory image -- use the current values
160 imageInfo.basic_info.api_version = B_HAIKU_VERSION;
161 imageInfo.basic_info.abi = B_HAIKU_ABI;
164 image->id = register_image(team_get_kernel_team(), &imageInfo,
165 sizeof(imageInfo));
166 sImagesHash->Insert(image);
170 /*! Note, you must lock the image mutex when you call this function. */
171 static struct elf_image_info *
172 find_image_at_address(addr_t address)
174 #if KDEBUG
175 if (!debug_debugger_running())
176 ASSERT_LOCKED_MUTEX(&sImageMutex);
177 #endif
179 ImageHash::Iterator iterator(sImagesHash);
181 // get image that may contain the address
183 while (iterator.HasNext()) {
184 struct elf_image_info* image = iterator.Next();
185 if ((address >= image->text_region.start && address
186 <= (image->text_region.start + image->text_region.size))
187 || (address >= image->data_region.start
188 && address
189 <= (image->data_region.start + image->data_region.size)))
190 return image;
193 return NULL;
197 static int
198 dump_address_info(int argc, char **argv)
200 const char *symbol, *imageName;
201 bool exactMatch;
202 addr_t address, baseAddress;
204 if (argc < 2) {
205 kprintf("usage: ls <address>\n");
206 return 0;
209 address = strtoul(argv[1], NULL, 16);
211 status_t error;
213 if (IS_KERNEL_ADDRESS(address)) {
214 error = elf_debug_lookup_symbol_address(address, &baseAddress, &symbol,
215 &imageName, &exactMatch);
216 } else {
217 error = elf_debug_lookup_user_symbol_address(
218 debug_get_debugged_thread()->team, address, &baseAddress, &symbol,
219 &imageName, &exactMatch);
222 if (error == B_OK) {
223 kprintf("%p = %s + 0x%lx (%s)%s\n", (void*)address, symbol,
224 address - baseAddress, imageName, exactMatch ? "" : " (nearest)");
225 } else
226 kprintf("There is no image loaded at this address!\n");
228 return 0;
232 static struct elf_image_info *
233 find_image(image_id id)
235 return sImagesHash->Lookup(id);
239 static struct elf_image_info *
240 find_image_by_vnode(void *vnode)
242 MutexLocker locker(sImageMutex);
244 ImageHash::Iterator iterator(sImagesHash);
245 while (iterator.HasNext()) {
246 struct elf_image_info* image = iterator.Next();
247 if (image->vnode == vnode)
248 return image;
251 return NULL;
255 static struct elf_image_info *
256 create_image_struct()
258 struct elf_image_info *image
259 = (struct elf_image_info *)malloc(sizeof(struct elf_image_info));
260 if (image == NULL)
261 return NULL;
263 memset(image, 0, sizeof(struct elf_image_info));
265 image->text_region.id = -1;
266 image->data_region.id = -1;
267 image->ref_count = 1;
269 return image;
273 static void
274 delete_elf_image(struct elf_image_info *image)
276 if (image->text_region.id >= 0)
277 delete_area(image->text_region.id);
279 if (image->data_region.id >= 0)
280 delete_area(image->data_region.id);
282 if (image->vnode)
283 vfs_put_vnode(image->vnode);
285 free(image->versions);
286 free(image->debug_symbols);
287 free((void*)image->debug_string_table);
288 free(image->elf_header);
289 free(image->name);
290 free(image);
294 static uint32
295 elf_hash(const char *name)
297 uint32 hash = 0;
298 uint32 temp;
300 while (*name) {
301 hash = (hash << 4) + (uint8)*name++;
302 if ((temp = hash & 0xf0000000) != 0)
303 hash ^= temp >> 24;
304 hash &= ~temp;
306 return hash;
310 static const char *
311 get_symbol_type_string(elf_sym *symbol)
313 switch (symbol->Type()) {
314 case STT_FUNC:
315 return "func";
316 case STT_OBJECT:
317 return " obj";
318 case STT_FILE:
319 return "file";
320 default:
321 return "----";
326 static const char *
327 get_symbol_bind_string(elf_sym *symbol)
329 switch (symbol->Bind()) {
330 case STB_LOCAL:
331 return "loc ";
332 case STB_GLOBAL:
333 return "glob";
334 case STB_WEAK:
335 return "weak";
336 default:
337 return "----";
342 /*! Searches a symbol (pattern) in all kernel images */
343 static int
344 dump_symbol(int argc, char **argv)
346 if (argc != 2 || !strcmp(argv[1], "--help")) {
347 kprintf("usage: %s <symbol-name>\n", argv[0]);
348 return 0;
351 struct elf_image_info *image = NULL;
352 const char *pattern = argv[1];
354 void* symbolAddress = NULL;
356 ImageHash::Iterator iterator(sImagesHash);
357 while (iterator.HasNext()) {
358 image = iterator.Next();
359 if (image->num_debug_symbols > 0) {
360 // search extended debug symbol table (contains static symbols)
361 for (uint32 i = 0; i < image->num_debug_symbols; i++) {
362 elf_sym *symbol = &image->debug_symbols[i];
363 const char *name = image->debug_string_table + symbol->st_name;
365 if (symbol->st_value > 0 && strstr(name, pattern) != 0) {
366 symbolAddress
367 = (void*)(symbol->st_value + image->text_region.delta);
368 kprintf("%p %5lu %s:%s\n", symbolAddress, symbol->st_size,
369 image->name, name);
372 } else {
373 // search standard symbol lookup table
374 for (uint32 i = 0; i < HASHTABSIZE(image); i++) {
375 for (uint32 j = HASHBUCKETS(image)[i]; j != STN_UNDEF;
376 j = HASHCHAINS(image)[j]) {
377 elf_sym *symbol = &image->syms[j];
378 const char *name = SYMNAME(image, symbol);
380 if (symbol->st_value > 0 && strstr(name, pattern) != 0) {
381 symbolAddress = (void*)(symbol->st_value
382 + image->text_region.delta);
383 kprintf("%p %5lu %s:%s\n", symbolAddress,
384 symbol->st_size, image->name, name);
391 if (symbolAddress != NULL)
392 set_debug_variable("_", (addr_t)symbolAddress);
394 return 0;
398 static int
399 dump_symbols(int argc, char **argv)
401 struct elf_image_info *image = NULL;
402 uint32 i;
404 // if the argument looks like a hex number, treat it as such
405 if (argc > 1) {
406 if (isdigit(argv[1][0])) {
407 addr_t num = strtoul(argv[1], NULL, 0);
409 if (IS_KERNEL_ADDRESS(num)) {
410 // find image at address
412 ImageHash::Iterator iterator(sImagesHash);
413 while (iterator.HasNext()) {
414 elf_image_info* current = iterator.Next();
415 if (current->text_region.start <= num
416 && current->text_region.start
417 + current->text_region.size >= num) {
418 image = current;
419 break;
423 if (image == NULL) {
424 kprintf("No image covers %#" B_PRIxADDR " in the kernel!\n",
425 num);
427 } else {
428 image = sImagesHash->Lookup(num);
429 if (image == NULL) {
430 kprintf("image %#" B_PRIxADDR " doesn't exist in the "
431 "kernel!\n", num);
434 } else {
435 // look for image by name
436 ImageHash::Iterator iterator(sImagesHash);
437 while (iterator.HasNext()) {
438 elf_image_info* current = iterator.Next();
439 if (!strcmp(current->name, argv[1])) {
440 image = current;
441 break;
445 if (image == NULL)
446 kprintf("No image \"%s\" found in kernel!\n", argv[1]);
448 } else {
449 kprintf("usage: %s image_name/image_id/address_in_image\n", argv[0]);
450 return 0;
453 if (image == NULL)
454 return -1;
456 // dump symbols
458 kprintf("Symbols of image %" B_PRId32 " \"%s\":\n", image->id, image->name);
459 kprintf("%-*s Type Size Name\n", B_PRINTF_POINTER_WIDTH, "Address");
461 if (image->num_debug_symbols > 0) {
462 // search extended debug symbol table (contains static symbols)
463 for (i = 0; i < image->num_debug_symbols; i++) {
464 elf_sym *symbol = &image->debug_symbols[i];
466 if (symbol->st_value == 0 || symbol->st_size
467 >= image->text_region.size + image->data_region.size)
468 continue;
470 kprintf("%0*lx %s/%s %5ld %s\n", B_PRINTF_POINTER_WIDTH,
471 symbol->st_value + image->text_region.delta,
472 get_symbol_type_string(symbol), get_symbol_bind_string(symbol),
473 symbol->st_size, image->debug_string_table + symbol->st_name);
475 } else {
476 int32 j;
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];
484 if (symbol->st_value == 0 || symbol->st_size
485 >= image->text_region.size + image->data_region.size)
486 continue;
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 symbol->st_size, SYMNAME(image, symbol));
497 return 0;
501 static void
502 dump_elf_region(struct elf_region *region, const char *name)
504 kprintf(" %s.id %" B_PRId32 "\n", name, region->id);
505 kprintf(" %s.start %#" B_PRIxADDR "\n", name, region->start);
506 kprintf(" %s.size %#" B_PRIxSIZE "\n", name, region->size);
507 kprintf(" %s.delta %ld\n", name, region->delta);
511 static void
512 dump_image_info(struct elf_image_info *image)
514 kprintf("elf_image_info at %p:\n", image);
515 kprintf(" next %p\n", image->next);
516 kprintf(" id %" B_PRId32 "\n", image->id);
517 dump_elf_region(&image->text_region, "text");
518 dump_elf_region(&image->data_region, "data");
519 kprintf(" dynamic_section %#" B_PRIxADDR "\n", image->dynamic_section);
520 kprintf(" needed %p\n", image->needed);
521 kprintf(" symhash %p\n", image->symhash);
522 kprintf(" syms %p\n", image->syms);
523 kprintf(" strtab %p\n", image->strtab);
524 kprintf(" rel %p\n", image->rel);
525 kprintf(" rel_len %#x\n", image->rel_len);
526 kprintf(" rela %p\n", image->rela);
527 kprintf(" rela_len %#x\n", image->rela_len);
528 kprintf(" pltrel %p\n", image->pltrel);
529 kprintf(" pltrel_len %#x\n", image->pltrel_len);
531 kprintf(" debug_symbols %p (%" B_PRIu32 ")\n",
532 image->debug_symbols, image->num_debug_symbols);
536 static int
537 dump_image(int argc, char **argv)
539 struct elf_image_info *image;
541 // if the argument looks like a hex number, treat it as such
542 if (argc > 1) {
543 addr_t num = strtoul(argv[1], NULL, 0);
545 if (IS_KERNEL_ADDRESS(num)) {
546 // semi-hack
547 dump_image_info((struct elf_image_info *)num);
548 } else {
549 image = sImagesHash->Lookup(num);
550 if (image == NULL) {
551 kprintf("image %#" B_PRIxADDR " doesn't exist in the kernel!\n",
552 num);
553 } else
554 dump_image_info(image);
556 return 0;
559 kprintf("loaded kernel images:\n");
561 ImageHash::Iterator iterator(sImagesHash);
563 while (iterator.HasNext()) {
564 image = iterator.Next();
565 kprintf("%p (%" B_PRId32 ") %s\n", image, image->id, image->name);
568 return 0;
572 // Currently unused
573 #if 0
574 static
575 void dump_symbol(struct elf_image_info *image, elf_sym *sym)
578 kprintf("symbol at %p, in image %p\n", sym, image);
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);
587 #endif
590 static elf_sym *
591 elf_find_symbol(struct elf_image_info *image, const char *name,
592 const elf_version_info *lookupVersion, bool lookupDefault)
594 if (image->dynamic_section == 0 || HASHTABSIZE(image) == 0)
595 return NULL;
597 elf_sym* versionedSymbol = NULL;
598 uint32 versionedSymbolCount = 0;
600 uint32 hash = elf_hash(name) % HASHTABSIZE(image);
601 for (uint32 i = HASHBUCKETS(image)[hash]; i != STN_UNDEF;
602 i = HASHCHAINS(image)[i]) {
603 elf_sym* symbol = &image->syms[i];
605 // consider only symbols with the right name and binding
606 if (symbol->st_shndx == SHN_UNDEF
607 || ((symbol->Bind() != STB_GLOBAL) && (symbol->Bind() != STB_WEAK))
608 || strcmp(SYMNAME(image, symbol), name) != 0) {
609 continue;
612 // check the version
614 // Handle the simple cases -- the image doesn't have version
615 // information -- first.
616 if (image->symbol_versions == NULL) {
617 if (lookupVersion == NULL) {
618 // No specific symbol version was requested either, so the
619 // symbol is just fine.
620 return symbol;
623 // A specific version is requested. Since the only possible
624 // dependency is the kernel itself, the add-on was obviously linked
625 // against a newer kernel.
626 dprintf("Kernel add-on requires version support, but the kernel "
627 "is too old.\n");
628 return NULL;
631 // The image has version information. Let's see what we've got.
632 uint32 versionID = image->symbol_versions[i];
633 uint32 versionIndex = VER_NDX(versionID);
634 elf_version_info& version = image->versions[versionIndex];
636 // skip local versions
637 if (versionIndex == VER_NDX_LOCAL)
638 continue;
640 if (lookupVersion != NULL) {
641 // a specific version is requested
643 // compare the versions
644 if (version.hash == lookupVersion->hash
645 && strcmp(version.name, lookupVersion->name) == 0) {
646 // versions match
647 return symbol;
650 // The versions don't match. We're still fine with the
651 // base version, if it is public and we're not looking for
652 // the default version.
653 if ((versionID & VER_NDX_FLAG_HIDDEN) == 0
654 && versionIndex == VER_NDX_GLOBAL
655 && !lookupDefault) {
656 // TODO: Revise the default version case! That's how
657 // FreeBSD implements it, but glibc doesn't handle it
658 // specially.
659 return symbol;
661 } else {
662 // No specific version requested, but the image has version
663 // information. This can happen in either of these cases:
665 // * The dependent object was linked against an older version
666 // of the now versioned dependency.
667 // * The symbol is looked up via find_image_symbol() or dlsym().
669 // In the first case we return the base version of the symbol
670 // (VER_NDX_GLOBAL or VER_NDX_INITIAL), or, if that doesn't
671 // exist, the unique, non-hidden versioned symbol.
673 // In the second case we want to return the public default
674 // version of the symbol. The handling is pretty similar to the
675 // first case, with the exception that we treat VER_NDX_INITIAL
676 // as regular version.
678 // VER_NDX_GLOBAL is always good, VER_NDX_INITIAL is fine, if
679 // we don't look for the default version.
680 if (versionIndex == VER_NDX_GLOBAL
681 || (!lookupDefault && versionIndex == VER_NDX_INITIAL)) {
682 return symbol;
685 // If not hidden, remember the version -- we'll return it, if
686 // it is the only one.
687 if ((versionID & VER_NDX_FLAG_HIDDEN) == 0) {
688 versionedSymbolCount++;
689 versionedSymbol = symbol;
694 return versionedSymbolCount == 1 ? versionedSymbol : NULL;
698 static status_t
699 elf_parse_dynamic_section(struct elf_image_info *image)
701 elf_dyn *d;
702 ssize_t neededOffset = -1;
704 TRACE(("top of elf_parse_dynamic_section\n"));
706 image->symhash = 0;
707 image->syms = 0;
708 image->strtab = 0;
710 d = (elf_dyn *)image->dynamic_section;
711 if (!d)
712 return B_ERROR;
714 for (int32 i = 0; d[i].d_tag != DT_NULL; i++) {
715 switch (d[i].d_tag) {
716 case DT_NEEDED:
717 neededOffset = d[i].d_un.d_ptr + image->text_region.delta;
718 break;
719 case DT_HASH:
720 image->symhash = (uint32 *)(d[i].d_un.d_ptr
721 + image->text_region.delta);
722 break;
723 case DT_STRTAB:
724 image->strtab = (char *)(d[i].d_un.d_ptr
725 + image->text_region.delta);
726 break;
727 case DT_SYMTAB:
728 image->syms = (elf_sym *)(d[i].d_un.d_ptr
729 + image->text_region.delta);
730 break;
731 case DT_REL:
732 image->rel = (elf_rel *)(d[i].d_un.d_ptr
733 + image->text_region.delta);
734 break;
735 case DT_RELSZ:
736 image->rel_len = d[i].d_un.d_val;
737 break;
738 case DT_RELA:
739 image->rela = (elf_rela *)(d[i].d_un.d_ptr
740 + image->text_region.delta);
741 break;
742 case DT_RELASZ:
743 image->rela_len = d[i].d_un.d_val;
744 break;
745 case DT_JMPREL:
746 image->pltrel = (elf_rel *)(d[i].d_un.d_ptr
747 + image->text_region.delta);
748 break;
749 case DT_PLTRELSZ:
750 image->pltrel_len = d[i].d_un.d_val;
751 break;
752 case DT_PLTREL:
753 image->pltrel_type = d[i].d_un.d_val;
754 break;
755 case DT_VERSYM:
756 image->symbol_versions = (elf_versym*)
757 (d[i].d_un.d_ptr + image->text_region.delta);
758 break;
759 case DT_VERDEF:
760 image->version_definitions = (elf_verdef*)
761 (d[i].d_un.d_ptr + image->text_region.delta);
762 break;
763 case DT_VERDEFNUM:
764 image->num_version_definitions = d[i].d_un.d_val;
765 break;
766 case DT_VERNEED:
767 image->needed_versions = (elf_verneed*)
768 (d[i].d_un.d_ptr + image->text_region.delta);
769 break;
770 case DT_VERNEEDNUM:
771 image->num_needed_versions = d[i].d_un.d_val;
772 break;
773 case DT_SYMBOLIC:
774 image->symbolic = true;
775 break;
776 case DT_FLAGS:
778 uint32 flags = d[i].d_un.d_val;
779 if ((flags & DF_SYMBOLIC) != 0)
780 image->symbolic = true;
781 break;
784 default:
785 continue;
789 // lets make sure we found all the required sections
790 if (!image->symhash || !image->syms || !image->strtab)
791 return B_ERROR;
793 TRACE(("needed_offset = %ld\n", neededOffset));
795 if (neededOffset >= 0)
796 image->needed = STRING(image, neededOffset);
798 return B_OK;
802 static status_t
803 assert_defined_image_version(elf_image_info* dependentImage,
804 elf_image_info* image, const elf_version_info& neededVersion, bool weak)
806 // If the image doesn't have version definitions, we print a warning and
807 // succeed. Weird, but that's how glibc does it. Not unlikely we'll fail
808 // later when resolving versioned symbols.
809 if (image->version_definitions == NULL) {
810 dprintf("%s: No version information available (required by %s)\n",
811 image->name, dependentImage->name);
812 return B_OK;
815 // iterate through the defined versions to find the given one
816 elf_verdef* definition = image->version_definitions;
817 for (uint32 i = 0; i < image->num_version_definitions; i++) {
818 uint32 versionIndex = VER_NDX(definition->vd_ndx);
819 elf_version_info& info = image->versions[versionIndex];
821 if (neededVersion.hash == info.hash
822 && strcmp(neededVersion.name, info.name) == 0) {
823 return B_OK;
826 definition = (elf_verdef*)
827 ((uint8*)definition + definition->vd_next);
830 // version not found -- fail, if not weak
831 if (!weak) {
832 dprintf("%s: version \"%s\" not found (required by %s)\n", image->name,
833 neededVersion.name, dependentImage->name);
834 return B_MISSING_SYMBOL;
837 return B_OK;
841 static status_t
842 init_image_version_infos(elf_image_info* image)
844 // First find out how many version infos we need -- i.e. get the greatest
845 // version index from the defined and needed versions (they use the same
846 // index namespace).
847 uint32 maxIndex = 0;
849 if (image->version_definitions != NULL) {
850 elf_verdef* definition = image->version_definitions;
851 for (uint32 i = 0; i < image->num_version_definitions; i++) {
852 if (definition->vd_version != 1) {
853 dprintf("Unsupported version definition revision: %u\n",
854 definition->vd_version);
855 return B_BAD_VALUE;
858 uint32 versionIndex = VER_NDX(definition->vd_ndx);
859 if (versionIndex > maxIndex)
860 maxIndex = versionIndex;
862 definition = (elf_verdef*)
863 ((uint8*)definition + definition->vd_next);
867 if (image->needed_versions != NULL) {
868 elf_verneed* needed = image->needed_versions;
869 for (uint32 i = 0; i < image->num_needed_versions; i++) {
870 if (needed->vn_version != 1) {
871 dprintf("Unsupported version needed revision: %u\n",
872 needed->vn_version);
873 return B_BAD_VALUE;
876 elf_vernaux* vernaux
877 = (elf_vernaux*)((uint8*)needed + needed->vn_aux);
878 for (uint32 k = 0; k < needed->vn_cnt; k++) {
879 uint32 versionIndex = VER_NDX(vernaux->vna_other);
880 if (versionIndex > maxIndex)
881 maxIndex = versionIndex;
883 vernaux = (elf_vernaux*)((uint8*)vernaux + vernaux->vna_next);
886 needed = (elf_verneed*)((uint8*)needed + needed->vn_next);
890 if (maxIndex == 0)
891 return B_OK;
893 // allocate the version infos
894 image->versions
895 = (elf_version_info*)malloc(sizeof(elf_version_info) * (maxIndex + 1));
896 if (image->versions == NULL) {
897 dprintf("Memory shortage in init_image_version_infos()\n");
898 return B_NO_MEMORY;
900 image->num_versions = maxIndex + 1;
902 // init the version infos
904 // version definitions
905 if (image->version_definitions != NULL) {
906 elf_verdef* definition = image->version_definitions;
907 for (uint32 i = 0; i < image->num_version_definitions; i++) {
908 if (definition->vd_cnt > 0
909 && (definition->vd_flags & VER_FLG_BASE) == 0) {
910 elf_verdaux* verdaux
911 = (elf_verdaux*)((uint8*)definition + definition->vd_aux);
913 uint32 versionIndex = VER_NDX(definition->vd_ndx);
914 elf_version_info& info = image->versions[versionIndex];
915 info.hash = definition->vd_hash;
916 info.name = STRING(image, verdaux->vda_name);
917 info.file_name = NULL;
920 definition = (elf_verdef*)
921 ((uint8*)definition + definition->vd_next);
925 // needed versions
926 if (image->needed_versions != NULL) {
927 elf_verneed* needed = image->needed_versions;
928 for (uint32 i = 0; i < image->num_needed_versions; i++) {
929 const char* fileName = STRING(image, needed->vn_file);
931 elf_vernaux* vernaux
932 = (elf_vernaux*)((uint8*)needed + needed->vn_aux);
933 for (uint32 k = 0; k < needed->vn_cnt; k++) {
934 uint32 versionIndex = VER_NDX(vernaux->vna_other);
935 elf_version_info& info = image->versions[versionIndex];
936 info.hash = vernaux->vna_hash;
937 info.name = STRING(image, vernaux->vna_name);
938 info.file_name = fileName;
940 vernaux = (elf_vernaux*)((uint8*)vernaux + vernaux->vna_next);
943 needed = (elf_verneed*)((uint8*)needed + needed->vn_next);
947 return B_OK;
951 static status_t
952 check_needed_image_versions(elf_image_info* image)
954 if (image->needed_versions == NULL)
955 return B_OK;
957 elf_verneed* needed = image->needed_versions;
958 for (uint32 i = 0; i < image->num_needed_versions; i++) {
959 elf_image_info* dependency = sKernelImage;
961 elf_vernaux* vernaux
962 = (elf_vernaux*)((uint8*)needed + needed->vn_aux);
963 for (uint32 k = 0; k < needed->vn_cnt; k++) {
964 uint32 versionIndex = VER_NDX(vernaux->vna_other);
965 elf_version_info& info = image->versions[versionIndex];
967 status_t error = assert_defined_image_version(image, dependency,
968 info, (vernaux->vna_flags & VER_FLG_WEAK) != 0);
969 if (error != B_OK)
970 return error;
972 vernaux = (elf_vernaux*)((uint8*)vernaux + vernaux->vna_next);
975 needed = (elf_verneed*)((uint8*)needed + needed->vn_next);
978 return B_OK;
982 /*! Resolves the \a symbol by linking against \a sharedImage if necessary.
983 Returns the resolved symbol's address in \a _symbolAddress.
985 status_t
986 elf_resolve_symbol(struct elf_image_info *image, elf_sym *symbol,
987 struct elf_image_info *sharedImage, addr_t *_symbolAddress)
989 // Local symbols references are always resolved to the given symbol.
990 if (symbol->Bind() == STB_LOCAL) {
991 *_symbolAddress = symbol->st_value + image->text_region.delta;
992 return B_OK;
995 // Non-local symbols we try to resolve to the kernel image first. Unless
996 // the image is linked symbolically, then vice versa.
997 elf_image_info* firstImage = sharedImage;
998 elf_image_info* secondImage = image;
999 if (image->symbolic)
1000 std::swap(firstImage, secondImage);
1002 const char *symbolName = SYMNAME(image, symbol);
1004 // get the version info
1005 const elf_version_info* versionInfo = NULL;
1006 if (image->symbol_versions != NULL) {
1007 uint32 index = symbol - image->syms;
1008 uint32 versionIndex = VER_NDX(image->symbol_versions[index]);
1009 if (versionIndex >= VER_NDX_INITIAL)
1010 versionInfo = image->versions + versionIndex;
1013 // find the symbol
1014 elf_image_info* foundImage = firstImage;
1015 elf_sym* foundSymbol = elf_find_symbol(firstImage, symbolName, versionInfo,
1016 false);
1017 if (foundSymbol == NULL
1018 || foundSymbol->Bind() == STB_WEAK) {
1019 // Not found or found a weak definition -- try to resolve in the other
1020 // image.
1021 elf_sym* secondSymbol = elf_find_symbol(secondImage, symbolName,
1022 versionInfo, false);
1023 // If we found a symbol -- take it in case we didn't have a symbol
1024 // before or the new symbol is not weak.
1025 if (secondSymbol != NULL
1026 && (foundSymbol == NULL
1027 || secondSymbol->Bind() != STB_WEAK)) {
1028 foundImage = secondImage;
1029 foundSymbol = secondSymbol;
1033 if (foundSymbol == NULL) {
1034 // Weak undefined symbols get a value of 0, if unresolved.
1035 if (symbol->Bind() == STB_WEAK) {
1036 *_symbolAddress = 0;
1037 return B_OK;
1040 dprintf("\"%s\": could not resolve symbol '%s'\n", image->name,
1041 symbolName);
1042 return B_MISSING_SYMBOL;
1045 // make sure they're the same type
1046 if (symbol->Type() != foundSymbol->Type()) {
1047 dprintf("elf_resolve_symbol: found symbol '%s' in image '%s' "
1048 "(requested by image '%s') but wrong type (%d vs. %d)\n",
1049 symbolName, foundImage->name, image->name,
1050 foundSymbol->Type(), symbol->Type());
1051 return B_MISSING_SYMBOL;
1054 *_symbolAddress = foundSymbol->st_value + foundImage->text_region.delta;
1055 return B_OK;
1059 /*! Until we have shared library support, just this links against the kernel */
1060 static int
1061 elf_relocate(struct elf_image_info* image, struct elf_image_info* resolveImage)
1063 int status = B_NO_ERROR;
1065 TRACE(("elf_relocate(%p (\"%s\"))\n", image, image->name));
1067 // deal with the rels first
1068 if (image->rel) {
1069 TRACE(("total %i rel relocs\n", image->rel_len / (int)sizeof(elf_rel)));
1071 status = arch_elf_relocate_rel(image, resolveImage, image->rel,
1072 image->rel_len);
1073 if (status < B_OK)
1074 return status;
1077 if (image->pltrel) {
1078 if (image->pltrel_type == DT_REL) {
1079 TRACE(("total %i plt-relocs\n",
1080 image->pltrel_len / (int)sizeof(elf_rel)));
1081 status = arch_elf_relocate_rel(image, resolveImage, image->pltrel,
1082 image->pltrel_len);
1083 } else {
1084 TRACE(("total %i plt-relocs\n",
1085 image->pltrel_len / (int)sizeof(elf_rela)));
1086 status = arch_elf_relocate_rela(image, resolveImage,
1087 (elf_rela *)image->pltrel, image->pltrel_len);
1089 if (status < B_OK)
1090 return status;
1093 if (image->rela) {
1094 TRACE(("total %i rel relocs\n",
1095 image->rela_len / (int)sizeof(elf_rela)));
1097 status = arch_elf_relocate_rela(image, resolveImage, image->rela,
1098 image->rela_len);
1099 if (status < B_OK)
1100 return status;
1103 return status;
1107 static int
1108 verify_eheader(elf_ehdr *elfHeader)
1110 if (memcmp(elfHeader->e_ident, ELFMAG, 4) != 0)
1111 return B_NOT_AN_EXECUTABLE;
1113 if (elfHeader->e_ident[4] != ELF_CLASS)
1114 return B_NOT_AN_EXECUTABLE;
1116 if (elfHeader->e_phoff == 0)
1117 return B_NOT_AN_EXECUTABLE;
1119 if (elfHeader->e_phentsize < sizeof(elf_phdr))
1120 return B_NOT_AN_EXECUTABLE;
1122 return 0;
1126 static void
1127 unload_elf_image(struct elf_image_info *image)
1129 if (atomic_add(&image->ref_count, -1) > 1)
1130 return;
1132 TRACE(("unload image %" B_PRId32 ", %s\n", image->id, image->name));
1134 unregister_elf_image(image);
1135 delete_elf_image(image);
1139 static status_t
1140 load_elf_symbol_table(int fd, struct elf_image_info *image)
1142 elf_ehdr *elfHeader = image->elf_header;
1143 elf_sym *symbolTable = NULL;
1144 elf_shdr *stringHeader = NULL;
1145 uint32 numSymbols = 0;
1146 char *stringTable;
1147 status_t status;
1148 ssize_t length;
1149 int32 i;
1151 // get section headers
1153 ssize_t size = elfHeader->e_shnum * elfHeader->e_shentsize;
1154 elf_shdr *sectionHeaders = (elf_shdr *)malloc(size);
1155 if (sectionHeaders == NULL) {
1156 dprintf("error allocating space for section headers\n");
1157 return B_NO_MEMORY;
1160 length = read_pos(fd, elfHeader->e_shoff, sectionHeaders, size);
1161 if (length < size) {
1162 TRACE(("error reading in program headers\n"));
1163 status = B_ERROR;
1164 goto error1;
1167 // find symbol table in section headers
1169 for (i = 0; i < elfHeader->e_shnum; i++) {
1170 if (sectionHeaders[i].sh_type == SHT_SYMTAB) {
1171 stringHeader = &sectionHeaders[sectionHeaders[i].sh_link];
1173 if (stringHeader->sh_type != SHT_STRTAB) {
1174 TRACE(("doesn't link to string table\n"));
1175 status = B_BAD_DATA;
1176 goto error1;
1179 // read in symbol table
1180 size = sectionHeaders[i].sh_size;
1181 symbolTable = (elf_sym *)malloc(size);
1182 if (symbolTable == NULL) {
1183 status = B_NO_MEMORY;
1184 goto error1;
1187 length
1188 = read_pos(fd, sectionHeaders[i].sh_offset, symbolTable, size);
1189 if (length < size) {
1190 TRACE(("error reading in symbol table\n"));
1191 status = B_ERROR;
1192 goto error2;
1195 numSymbols = size / sizeof(elf_sym);
1196 break;
1200 if (symbolTable == NULL) {
1201 TRACE(("no symbol table\n"));
1202 status = B_BAD_VALUE;
1203 goto error1;
1206 // read in string table
1208 stringTable = (char *)malloc(size = stringHeader->sh_size);
1209 if (stringTable == NULL) {
1210 status = B_NO_MEMORY;
1211 goto error2;
1214 length = read_pos(fd, stringHeader->sh_offset, stringTable, size);
1215 if (length < size) {
1216 TRACE(("error reading in string table\n"));
1217 status = B_ERROR;
1218 goto error3;
1221 TRACE(("loaded %" B_PRId32 " debug symbols\n", numSymbols));
1223 // insert tables into image
1224 image->debug_symbols = symbolTable;
1225 image->num_debug_symbols = numSymbols;
1226 image->debug_string_table = stringTable;
1228 free(sectionHeaders);
1229 return B_OK;
1231 error3:
1232 free(stringTable);
1233 error2:
1234 free(symbolTable);
1235 error1:
1236 free(sectionHeaders);
1238 return status;
1242 static status_t
1243 insert_preloaded_image(preloaded_elf_image *preloadedImage, bool kernel)
1245 status_t status;
1247 status = verify_eheader(&preloadedImage->elf_header);
1248 if (status != B_OK)
1249 return status;
1251 elf_image_info *image = create_image_struct();
1252 if (image == NULL)
1253 return B_NO_MEMORY;
1255 image->name = strdup(preloadedImage->name);
1256 image->dynamic_section = preloadedImage->dynamic_section.start;
1258 image->text_region.id = preloadedImage->text_region.id;
1259 image->text_region.start = preloadedImage->text_region.start;
1260 image->text_region.size = preloadedImage->text_region.size;
1261 image->text_region.delta = preloadedImage->text_region.delta;
1262 image->data_region.id = preloadedImage->data_region.id;
1263 image->data_region.start = preloadedImage->data_region.start;
1264 image->data_region.size = preloadedImage->data_region.size;
1265 image->data_region.delta = preloadedImage->data_region.delta;
1267 status = elf_parse_dynamic_section(image);
1268 if (status != B_OK)
1269 goto error1;
1271 status = init_image_version_infos(image);
1272 if (status != B_OK)
1273 goto error1;
1275 if (!kernel) {
1276 status = check_needed_image_versions(image);
1277 if (status != B_OK)
1278 goto error1;
1280 status = elf_relocate(image, sKernelImage);
1281 if (status != B_OK)
1282 goto error1;
1283 } else
1284 sKernelImage = image;
1286 // copy debug symbols to the kernel heap
1287 if (preloadedImage->debug_symbols != NULL) {
1288 int32 debugSymbolsSize = sizeof(elf_sym)
1289 * preloadedImage->num_debug_symbols;
1290 image->debug_symbols = (elf_sym*)malloc(debugSymbolsSize);
1291 if (image->debug_symbols != NULL) {
1292 memcpy(image->debug_symbols, preloadedImage->debug_symbols,
1293 debugSymbolsSize);
1296 image->num_debug_symbols = preloadedImage->num_debug_symbols;
1298 // copy debug string table to the kernel heap
1299 if (preloadedImage->debug_string_table != NULL) {
1300 image->debug_string_table = (char*)malloc(
1301 preloadedImage->debug_string_table_size);
1302 if (image->debug_string_table != NULL) {
1303 memcpy((void*)image->debug_string_table,
1304 preloadedImage->debug_string_table,
1305 preloadedImage->debug_string_table_size);
1309 register_elf_image(image);
1310 preloadedImage->id = image->id;
1311 // modules_init() uses this information to get the preloaded images
1313 // we now no longer need to write to the text area anymore
1314 set_area_protection(image->text_region.id,
1315 B_KERNEL_READ_AREA | B_KERNEL_EXECUTE_AREA);
1317 return B_OK;
1319 error1:
1320 delete_elf_image(image);
1322 preloadedImage->id = -1;
1324 return status;
1328 // #pragma mark - userland symbol lookup
1331 class UserSymbolLookup {
1332 public:
1333 static UserSymbolLookup& Default()
1335 return sLookup;
1338 status_t Init(Team* team)
1340 // find the runtime loader debug area
1341 VMArea* area;
1342 for (VMAddressSpace::AreaIterator it
1343 = team->address_space->GetAreaIterator();
1344 (area = it.Next()) != NULL;) {
1345 if (strcmp(area->name, RUNTIME_LOADER_DEBUG_AREA_NAME) == 0)
1346 break;
1349 if (area == NULL)
1350 return B_ERROR;
1352 // copy the runtime loader data structure
1353 if (!_Read((runtime_loader_debug_area*)area->Base(), fDebugArea))
1354 return B_BAD_ADDRESS;
1356 fTeam = team;
1357 return B_OK;
1360 status_t LookupSymbolAddress(addr_t address, addr_t *_baseAddress,
1361 const char **_symbolName, const char **_imageName, bool *_exactMatch)
1363 // Note, that this function doesn't find all symbols that we would like
1364 // to find. E.g. static functions do not appear in the symbol table
1365 // as function symbols, but as sections without name and size. The
1366 // .symtab section together with the .strtab section, which apparently
1367 // differ from the tables referred to by the .dynamic section, also
1368 // contain proper names and sizes for those symbols. Therefore, to get
1369 // completely satisfying results, we would need to read those tables
1370 // from the shared object.
1372 // get the image for the address
1373 image_t image;
1374 status_t error = _FindImageAtAddress(address, image);
1375 if (error != B_OK) {
1376 // commpage requires special treatment since kernel stores symbol
1377 // information
1378 addr_t commPageAddress = (addr_t)fTeam->commpage_address;
1379 if (address >= commPageAddress
1380 && address < commPageAddress + COMMPAGE_SIZE) {
1381 if (*_imageName)
1382 *_imageName = "commpage";
1383 address -= (addr_t)commPageAddress;
1384 error = elf_debug_lookup_symbol_address(address, _baseAddress,
1385 _symbolName, NULL, _exactMatch);
1386 if (_baseAddress)
1387 *_baseAddress += (addr_t)fTeam->commpage_address;
1389 return error;
1392 strlcpy(fImageName, image.name, sizeof(fImageName));
1394 // symbol hash table size
1395 uint32 hashTabSize;
1396 if (!_Read(image.symhash, hashTabSize))
1397 return B_BAD_ADDRESS;
1399 // remote pointers to hash buckets and chains
1400 const uint32* hashBuckets = image.symhash + 2;
1401 const uint32* hashChains = image.symhash + 2 + hashTabSize;
1403 const elf_region_t& textRegion = image.regions[0];
1405 // search the image for the symbol
1406 elf_sym symbolFound;
1407 addr_t deltaFound = INT_MAX;
1408 bool exactMatch = false;
1410 // to get rid of the erroneous "uninitialized" warnings
1411 symbolFound.st_name = 0;
1412 symbolFound.st_value = 0;
1414 for (uint32 i = 0; i < hashTabSize; i++) {
1415 uint32 bucket;
1416 if (!_Read(&hashBuckets[i], bucket))
1417 return B_BAD_ADDRESS;
1419 for (uint32 j = bucket; j != STN_UNDEF;
1420 _Read(&hashChains[j], j) ? 0 : j = STN_UNDEF) {
1422 elf_sym symbol;
1423 if (!_Read(image.syms + j, symbol))
1424 continue;
1426 // The symbol table contains not only symbols referring to
1427 // functions and data symbols within the shared object, but also
1428 // referenced symbols of other shared objects, as well as
1429 // section and file references. We ignore everything but
1430 // function and data symbols that have an st_value != 0 (0
1431 // seems to be an indication for a symbol defined elsewhere
1432 // -- couldn't verify that in the specs though).
1433 if ((symbol.Type() != STT_FUNC && symbol.Type() != STT_OBJECT)
1434 || symbol.st_value == 0
1435 || symbol.st_value + symbol.st_size + textRegion.delta
1436 > textRegion.vmstart + textRegion.size) {
1437 continue;
1440 // skip symbols starting after the given address
1441 addr_t symbolAddress = symbol.st_value + textRegion.delta;
1442 if (symbolAddress > address)
1443 continue;
1444 addr_t symbolDelta = address - symbolAddress;
1446 if (symbolDelta < deltaFound) {
1447 deltaFound = symbolDelta;
1448 symbolFound = symbol;
1450 if (symbolDelta >= 0 && symbolDelta < symbol.st_size) {
1451 // exact match
1452 exactMatch = true;
1453 break;
1459 if (_imageName)
1460 *_imageName = fImageName;
1462 if (_symbolName) {
1463 *_symbolName = NULL;
1465 if (deltaFound < INT_MAX) {
1466 if (_ReadString(image, symbolFound.st_name, fSymbolName,
1467 sizeof(fSymbolName))) {
1468 *_symbolName = fSymbolName;
1469 } else {
1470 // we can't get its name, so forget the symbol
1471 deltaFound = INT_MAX;
1476 if (_baseAddress) {
1477 if (deltaFound < INT_MAX)
1478 *_baseAddress = symbolFound.st_value + textRegion.delta;
1479 else
1480 *_baseAddress = textRegion.vmstart;
1483 if (_exactMatch)
1484 *_exactMatch = exactMatch;
1486 return B_OK;
1489 status_t _FindImageAtAddress(addr_t address, image_t& image)
1491 image_queue_t imageQueue;
1492 if (!_Read(fDebugArea.loaded_images, imageQueue))
1493 return B_BAD_ADDRESS;
1495 image_t* imageAddress = imageQueue.head;
1496 while (imageAddress != NULL) {
1497 if (!_Read(imageAddress, image))
1498 return B_BAD_ADDRESS;
1500 if (image.regions[0].vmstart <= address
1501 && address < image.regions[0].vmstart + image.regions[0].size) {
1502 return B_OK;
1505 imageAddress = image.next;
1508 return B_ENTRY_NOT_FOUND;
1511 bool _ReadString(const image_t& image, uint32 offset, char* buffer,
1512 size_t bufferSize)
1514 const char* address = image.strtab + offset;
1516 if (!IS_USER_ADDRESS(address))
1517 return false;
1519 if (debug_debugger_running()) {
1520 return debug_strlcpy(B_CURRENT_TEAM, buffer, address, bufferSize)
1521 >= 0;
1523 return user_strlcpy(buffer, address, bufferSize) >= 0;
1526 template<typename T> bool _Read(const T* address, T& data);
1527 // gcc 2.95.3 doesn't like it defined in-place
1529 private:
1530 Team* fTeam;
1531 runtime_loader_debug_area fDebugArea;
1532 char fImageName[B_OS_NAME_LENGTH];
1533 char fSymbolName[256];
1534 static UserSymbolLookup sLookup;
1538 template<typename T>
1539 bool
1540 UserSymbolLookup::_Read(const T* address, T& data)
1542 if (!IS_USER_ADDRESS(address))
1543 return false;
1545 if (debug_debugger_running())
1546 return debug_memcpy(B_CURRENT_TEAM, &data, address, sizeof(T)) == B_OK;
1547 return user_memcpy(&data, address, sizeof(T)) == B_OK;
1551 UserSymbolLookup UserSymbolLookup::sLookup;
1552 // doesn't need construction, but has an Init() method
1555 // #pragma mark - public kernel API
1558 status_t
1559 get_image_symbol(image_id id, const char *name, int32 symbolClass,
1560 void **_symbol)
1562 struct elf_image_info *image;
1563 elf_sym *symbol;
1564 status_t status = B_OK;
1566 TRACE(("get_image_symbol(%s)\n", name));
1568 mutex_lock(&sImageMutex);
1570 image = find_image(id);
1571 if (image == NULL) {
1572 status = B_BAD_IMAGE_ID;
1573 goto done;
1576 symbol = elf_find_symbol(image, name, NULL, true);
1577 if (symbol == NULL || symbol->st_shndx == SHN_UNDEF) {
1578 status = B_ENTRY_NOT_FOUND;
1579 goto done;
1582 // TODO: support the "symbolClass" parameter!
1584 TRACE(("found: %lx (%lx + %lx)\n",
1585 symbol->st_value + image->text_region.delta,
1586 symbol->st_value, image->text_region.delta));
1588 *_symbol = (void *)(symbol->st_value + image->text_region.delta);
1590 done:
1591 mutex_unlock(&sImageMutex);
1592 return status;
1596 // #pragma mark - kernel private API
1599 /*! Looks up a symbol by address in all images loaded in kernel space.
1600 Note, if you need to call this function outside a debugger, make
1601 sure you fix locking and the way it returns its information, first!
1603 status_t
1604 elf_debug_lookup_symbol_address(addr_t address, addr_t *_baseAddress,
1605 const char **_symbolName, const char **_imageName, bool *_exactMatch)
1607 struct elf_image_info *image;
1608 elf_sym *symbolFound = NULL;
1609 const char *symbolName = NULL;
1610 addr_t deltaFound = INT_MAX;
1611 bool exactMatch = false;
1612 status_t status;
1614 TRACE(("looking up %p\n", (void *)address));
1616 if (!sInitialized)
1617 return B_ERROR;
1619 //mutex_lock(&sImageMutex);
1621 image = find_image_at_address(address);
1622 // get image that may contain the address
1624 if (image != NULL) {
1625 addr_t symbolDelta;
1626 uint32 i;
1627 int32 j;
1629 TRACE((" image %p, base = %p, size = %p\n", image,
1630 (void *)image->text_region.start, (void *)image->text_region.size));
1632 if (image->debug_symbols != NULL) {
1633 // search extended debug symbol table (contains static symbols)
1635 TRACE((" searching debug symbols...\n"));
1637 for (i = 0; i < image->num_debug_symbols; i++) {
1638 elf_sym *symbol = &image->debug_symbols[i];
1640 if (symbol->st_value == 0 || symbol->st_size
1641 >= image->text_region.size + image->data_region.size)
1642 continue;
1644 symbolDelta
1645 = address - (symbol->st_value + image->text_region.delta);
1646 if (symbolDelta >= 0 && symbolDelta < symbol->st_size)
1647 exactMatch = true;
1649 if (exactMatch || symbolDelta < deltaFound) {
1650 deltaFound = symbolDelta;
1651 symbolFound = symbol;
1652 symbolName = image->debug_string_table + symbol->st_name;
1654 if (exactMatch)
1655 break;
1658 } else {
1659 // search standard symbol lookup table
1661 TRACE((" searching standard symbols...\n"));
1663 for (i = 0; i < HASHTABSIZE(image); i++) {
1664 for (j = HASHBUCKETS(image)[i]; j != STN_UNDEF;
1665 j = HASHCHAINS(image)[j]) {
1666 elf_sym *symbol = &image->syms[j];
1668 if (symbol->st_value == 0
1669 || symbol->st_size >= image->text_region.size
1670 + image->data_region.size)
1671 continue;
1673 symbolDelta = address - (long)(symbol->st_value
1674 + image->text_region.delta);
1675 if (symbolDelta >= 0 && symbolDelta < symbol->st_size)
1676 exactMatch = true;
1678 if (exactMatch || symbolDelta < deltaFound) {
1679 deltaFound = symbolDelta;
1680 symbolFound = symbol;
1681 symbolName = SYMNAME(image, symbol);
1683 if (exactMatch)
1684 goto symbol_found;
1690 symbol_found:
1692 if (symbolFound != NULL) {
1693 if (_symbolName)
1694 *_symbolName = symbolName;
1695 if (_imageName)
1696 *_imageName = image->name;
1697 if (_baseAddress)
1698 *_baseAddress = symbolFound->st_value + image->text_region.delta;
1699 if (_exactMatch)
1700 *_exactMatch = exactMatch;
1702 status = B_OK;
1703 } else if (image != NULL) {
1704 TRACE(("symbol not found!\n"));
1706 if (_symbolName)
1707 *_symbolName = NULL;
1708 if (_imageName)
1709 *_imageName = image->name;
1710 if (_baseAddress)
1711 *_baseAddress = image->text_region.start;
1712 if (_exactMatch)
1713 *_exactMatch = false;
1715 status = B_OK;
1716 } else {
1717 TRACE(("image not found!\n"));
1718 status = B_ENTRY_NOT_FOUND;
1721 // Note, theoretically, all information we return back to our caller
1722 // would have to be locked - but since this function is only called
1723 // from the debugger, it's safe to do it this way
1725 //mutex_unlock(&sImageMutex);
1727 return status;
1731 /*! Tries to find a matching user symbol for the given address.
1732 Note that the given team's address space must already be in effect.
1734 status_t
1735 elf_debug_lookup_user_symbol_address(Team* team, addr_t address,
1736 addr_t *_baseAddress, const char **_symbolName, const char **_imageName,
1737 bool *_exactMatch)
1739 if (team == NULL || team == team_get_kernel_team())
1740 return B_BAD_VALUE;
1742 UserSymbolLookup& lookup = UserSymbolLookup::Default();
1743 status_t error = lookup.Init(team);
1744 if (error != B_OK)
1745 return error;
1747 return lookup.LookupSymbolAddress(address, _baseAddress, _symbolName,
1748 _imageName, _exactMatch);
1752 /*! Looks up a symbol in all kernel images. Note, this function is thought to
1753 be used in the kernel debugger, and therefore doesn't perform any locking.
1755 addr_t
1756 elf_debug_lookup_symbol(const char* searchName)
1758 struct elf_image_info *image = NULL;
1760 ImageHash::Iterator iterator(sImagesHash);
1761 while (iterator.HasNext()) {
1762 image = iterator.Next();
1763 if (image->num_debug_symbols > 0) {
1764 // search extended debug symbol table (contains static symbols)
1765 for (uint32 i = 0; i < image->num_debug_symbols; i++) {
1766 elf_sym *symbol = &image->debug_symbols[i];
1767 const char *name = image->debug_string_table + symbol->st_name;
1769 if (symbol->st_value > 0 && !strcmp(name, searchName))
1770 return symbol->st_value + image->text_region.delta;
1772 } else {
1773 // search standard symbol lookup table
1774 for (uint32 i = 0; i < HASHTABSIZE(image); i++) {
1775 for (uint32 j = HASHBUCKETS(image)[i]; j != STN_UNDEF;
1776 j = HASHCHAINS(image)[j]) {
1777 elf_sym *symbol = &image->syms[j];
1778 const char *name = SYMNAME(image, symbol);
1780 if (symbol->st_value > 0 && !strcmp(name, searchName))
1781 return symbol->st_value + image->text_region.delta;
1787 return 0;
1791 status_t
1792 elf_lookup_kernel_symbol(const char* name, elf_symbol_info* info)
1794 // find the symbol
1795 elf_sym* foundSymbol = elf_find_symbol(sKernelImage, name, NULL, false);
1796 if (foundSymbol == NULL)
1797 return B_MISSING_SYMBOL;
1799 info->address = foundSymbol->st_value + sKernelImage->text_region.delta;
1800 info->size = foundSymbol->st_size;
1801 return B_OK;
1805 status_t
1806 elf_load_user_image(const char *path, Team *team, int flags, addr_t *entry)
1808 elf_ehdr elfHeader;
1809 elf_phdr *programHeaders = NULL;
1810 char baseName[B_OS_NAME_LENGTH];
1811 status_t status;
1812 ssize_t length;
1813 int fd;
1814 int i;
1815 addr_t delta = 0;
1816 uint32 addressSpec = B_RANDOMIZED_BASE_ADDRESS;
1817 area_id* mappedAreas = NULL;
1819 TRACE(("elf_load: entry path '%s', team %p\n", path, team));
1821 fd = _kern_open(-1, path, O_RDONLY, 0);
1822 if (fd < 0)
1823 return fd;
1825 struct stat st;
1826 status = _kern_read_stat(fd, NULL, false, &st, sizeof(st));
1827 if (status != B_OK)
1828 return status;
1830 // read and verify the ELF header
1832 length = _kern_read(fd, 0, &elfHeader, sizeof(elfHeader));
1833 if (length < B_OK) {
1834 status = length;
1835 goto error;
1838 if (length != sizeof(elfHeader)) {
1839 // short read
1840 status = B_NOT_AN_EXECUTABLE;
1841 goto error;
1843 status = verify_eheader(&elfHeader);
1844 if (status < B_OK)
1845 goto error;
1847 struct elf_image_info* image;
1848 image = create_image_struct();
1849 if (image == NULL) {
1850 status = B_NO_MEMORY;
1851 goto error;
1853 image->elf_header = &elfHeader;
1855 // read program header
1857 programHeaders = (elf_phdr *)malloc(
1858 elfHeader.e_phnum * elfHeader.e_phentsize);
1859 if (programHeaders == NULL) {
1860 dprintf("error allocating space for program headers\n");
1861 status = B_NO_MEMORY;
1862 goto error2;
1865 TRACE(("reading in program headers at 0x%lx, length 0x%x\n",
1866 elfHeader.e_phoff, elfHeader.e_phnum * elfHeader.e_phentsize));
1867 length = _kern_read(fd, elfHeader.e_phoff, programHeaders,
1868 elfHeader.e_phnum * elfHeader.e_phentsize);
1869 if (length < B_OK) {
1870 status = length;
1871 dprintf("error reading in program headers\n");
1872 goto error2;
1874 if (length != elfHeader.e_phnum * elfHeader.e_phentsize) {
1875 dprintf("short read while reading in program headers\n");
1876 status = -1;
1877 goto error2;
1880 // construct a nice name for the region we have to create below
1882 int32 length;
1884 const char *leaf = strrchr(path, '/');
1885 if (leaf == NULL)
1886 leaf = path;
1887 else
1888 leaf++;
1890 length = strlen(leaf);
1891 if (length > B_OS_NAME_LENGTH - 8)
1892 sprintf(baseName, "...%s", leaf + length + 8 - B_OS_NAME_LENGTH);
1893 else
1894 strcpy(baseName, leaf);
1897 // map the program's segments into memory, initially with rw access
1898 // correct area protection will be set after relocation
1900 mappedAreas = (area_id*)malloc(sizeof(area_id) * elfHeader.e_phnum);
1901 if (mappedAreas == NULL) {
1902 status = B_NO_MEMORY;
1903 goto error2;
1906 extended_image_info imageInfo;
1907 memset(&imageInfo, 0, sizeof(imageInfo));
1909 for (i = 0; i < elfHeader.e_phnum; i++) {
1910 char regionName[B_OS_NAME_LENGTH];
1911 char *regionAddress;
1912 char *originalRegionAddress;
1913 area_id id;
1915 mappedAreas[i] = -1;
1917 if (programHeaders[i].p_type == PT_DYNAMIC) {
1918 image->dynamic_section = programHeaders[i].p_vaddr;
1919 continue;
1922 if (programHeaders[i].p_type != PT_LOAD)
1923 continue;
1925 regionAddress = (char *)(ROUNDDOWN(programHeaders[i].p_vaddr,
1926 B_PAGE_SIZE) + delta);
1927 originalRegionAddress = regionAddress;
1929 if (programHeaders[i].p_flags & PF_WRITE) {
1930 // rw/data segment
1931 size_t memUpperBound = (programHeaders[i].p_vaddr % B_PAGE_SIZE)
1932 + programHeaders[i].p_memsz;
1933 size_t fileUpperBound = (programHeaders[i].p_vaddr % B_PAGE_SIZE)
1934 + programHeaders[i].p_filesz;
1936 memUpperBound = ROUNDUP(memUpperBound, B_PAGE_SIZE);
1937 fileUpperBound = ROUNDUP(fileUpperBound, B_PAGE_SIZE);
1939 sprintf(regionName, "%s_seg%drw", baseName, i);
1941 id = vm_map_file(team->id, regionName, (void **)&regionAddress,
1942 addressSpec, fileUpperBound,
1943 B_READ_AREA | B_WRITE_AREA, REGION_PRIVATE_MAP, false,
1944 fd, ROUNDDOWN(programHeaders[i].p_offset, B_PAGE_SIZE));
1945 if (id < B_OK) {
1946 dprintf("error mapping file data: %s!\n", strerror(id));
1947 status = B_NOT_AN_EXECUTABLE;
1948 goto error2;
1950 mappedAreas[i] = id;
1952 imageInfo.basic_info.data = regionAddress;
1953 imageInfo.basic_info.data_size = memUpperBound;
1955 image->data_region.start = (addr_t)regionAddress;
1956 image->data_region.size = memUpperBound;
1958 // clean garbage brought by mmap (the region behind the file,
1959 // at least parts of it are the bss and have to be zeroed)
1960 addr_t start = (addr_t)regionAddress
1961 + (programHeaders[i].p_vaddr % B_PAGE_SIZE)
1962 + programHeaders[i].p_filesz;
1963 size_t amount = fileUpperBound
1964 - (programHeaders[i].p_vaddr % B_PAGE_SIZE)
1965 - (programHeaders[i].p_filesz);
1966 memset((void *)start, 0, amount);
1968 // Check if we need extra storage for the bss - we have to do this if
1969 // the above region doesn't already comprise the memory size, too.
1971 if (memUpperBound != fileUpperBound) {
1972 size_t bssSize = memUpperBound - fileUpperBound;
1974 snprintf(regionName, B_OS_NAME_LENGTH, "%s_bss%d", baseName, i);
1976 regionAddress += fileUpperBound;
1977 virtual_address_restrictions virtualRestrictions = {};
1978 virtualRestrictions.address = regionAddress;
1979 virtualRestrictions.address_specification = B_EXACT_ADDRESS;
1980 physical_address_restrictions physicalRestrictions = {};
1981 id = create_area_etc(team->id, regionName, bssSize, B_NO_LOCK,
1982 B_READ_AREA | B_WRITE_AREA, 0, 0, &virtualRestrictions,
1983 &physicalRestrictions, (void**)&regionAddress);
1984 if (id < B_OK) {
1985 dprintf("error allocating bss area: %s!\n", strerror(id));
1986 status = B_NOT_AN_EXECUTABLE;
1987 goto error2;
1990 } else {
1991 // assume ro/text segment
1992 snprintf(regionName, B_OS_NAME_LENGTH, "%s_seg%dro", baseName, i);
1994 size_t segmentSize = ROUNDUP(programHeaders[i].p_memsz
1995 + (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE);
1997 id = vm_map_file(team->id, regionName, (void **)&regionAddress,
1998 addressSpec, segmentSize,
1999 B_READ_AREA | B_WRITE_AREA, REGION_PRIVATE_MAP, false, fd,
2000 ROUNDDOWN(programHeaders[i].p_offset, B_PAGE_SIZE));
2001 if (id < B_OK) {
2002 dprintf("error mapping file text: %s!\n", strerror(id));
2003 status = B_NOT_AN_EXECUTABLE;
2004 goto error2;
2007 mappedAreas[i] = id;
2009 imageInfo.basic_info.text = regionAddress;
2010 imageInfo.basic_info.text_size = segmentSize;
2012 image->text_region.start = (addr_t)regionAddress;
2013 image->text_region.size = segmentSize;
2016 if (addressSpec != B_EXACT_ADDRESS) {
2017 addressSpec = B_EXACT_ADDRESS;
2018 delta = regionAddress - originalRegionAddress;
2022 image->data_region.delta = delta;
2023 image->text_region.delta = delta;
2025 // modify the dynamic ptr by the delta of the regions
2026 image->dynamic_section += image->text_region.delta;
2028 status = elf_parse_dynamic_section(image);
2029 if (status != B_OK)
2030 goto error2;
2032 status = elf_relocate(image, image);
2033 if (status != B_OK)
2034 goto error2;
2036 // set correct area protection
2037 for (i = 0; i < elfHeader.e_phnum; i++) {
2038 if (mappedAreas[i] == -1)
2039 continue;
2041 uint32 protection = 0;
2043 if (programHeaders[i].p_flags & PF_EXECUTE)
2044 protection |= B_EXECUTE_AREA;
2045 if (programHeaders[i].p_flags & PF_WRITE)
2046 protection |= B_WRITE_AREA;
2047 if (programHeaders[i].p_flags & PF_READ)
2048 protection |= B_READ_AREA;
2050 status = vm_set_area_protection(team->id, mappedAreas[i], protection,
2051 true);
2052 if (status != B_OK)
2053 goto error2;
2056 // register the loaded image
2057 imageInfo.basic_info.type = B_LIBRARY_IMAGE;
2058 imageInfo.basic_info.device = st.st_dev;
2059 imageInfo.basic_info.node = st.st_ino;
2060 strlcpy(imageInfo.basic_info.name, path, sizeof(imageInfo.basic_info.name));
2062 imageInfo.basic_info.api_version = B_HAIKU_VERSION;
2063 imageInfo.basic_info.abi = B_HAIKU_ABI;
2064 // TODO: Get the actual values for the shared object. Currently only
2065 // the runtime loader is loaded, so this is good enough for the time
2066 // being.
2068 imageInfo.text_delta = delta;
2069 imageInfo.symbol_table = image->syms;
2070 imageInfo.symbol_hash = image->symhash;
2071 imageInfo.string_table = image->strtab;
2073 imageInfo.basic_info.id = register_image(team, &imageInfo,
2074 sizeof(imageInfo));
2075 if (imageInfo.basic_info.id >= 0 && team_get_current_team_id() == team->id)
2076 user_debug_image_created(&imageInfo.basic_info);
2077 // Don't care, if registering fails. It's not crucial.
2079 TRACE(("elf_load: done!\n"));
2081 *entry = elfHeader.e_entry + delta;
2082 status = B_OK;
2084 error2:
2085 free(mappedAreas);
2087 image->elf_header = NULL;
2088 delete_elf_image(image);
2090 error:
2091 free(programHeaders);
2092 _kern_close(fd);
2094 return status;
2098 image_id
2099 load_kernel_add_on(const char *path)
2101 elf_phdr *programHeaders;
2102 elf_ehdr *elfHeader;
2103 struct elf_image_info *image;
2104 const char *fileName;
2105 void *reservedAddress;
2106 size_t reservedSize;
2107 status_t status;
2108 ssize_t length;
2109 bool textSectionWritable = false;
2110 int executableHeaderCount = 0;
2112 TRACE(("elf_load_kspace: entry path '%s'\n", path));
2114 int fd = _kern_open(-1, path, O_RDONLY, 0);
2115 if (fd < 0)
2116 return fd;
2118 struct vnode *vnode;
2119 status = vfs_get_vnode_from_fd(fd, true, &vnode);
2120 if (status < B_OK)
2121 goto error0;
2123 // get the file name
2124 fileName = strrchr(path, '/');
2125 if (fileName == NULL)
2126 fileName = path;
2127 else
2128 fileName++;
2130 // Prevent someone else from trying to load this image
2131 mutex_lock(&sImageLoadMutex);
2133 // make sure it's not loaded already. Search by vnode
2134 image = find_image_by_vnode(vnode);
2135 if (image) {
2136 atomic_add(&image->ref_count, 1);
2137 goto done;
2140 elfHeader = (elf_ehdr *)malloc(sizeof(*elfHeader));
2141 if (!elfHeader) {
2142 status = B_NO_MEMORY;
2143 goto error;
2146 length = _kern_read(fd, 0, elfHeader, sizeof(*elfHeader));
2147 if (length < B_OK) {
2148 status = length;
2149 goto error1;
2151 if (length != sizeof(*elfHeader)) {
2152 // short read
2153 status = B_NOT_AN_EXECUTABLE;
2154 goto error1;
2156 status = verify_eheader(elfHeader);
2157 if (status < B_OK)
2158 goto error1;
2160 image = create_image_struct();
2161 if (!image) {
2162 status = B_NO_MEMORY;
2163 goto error1;
2165 image->vnode = vnode;
2166 image->elf_header = elfHeader;
2167 image->name = strdup(path);
2168 vnode = NULL;
2170 programHeaders = (elf_phdr *)malloc(elfHeader->e_phnum
2171 * elfHeader->e_phentsize);
2172 if (programHeaders == NULL) {
2173 dprintf("%s: error allocating space for program headers\n", fileName);
2174 status = B_NO_MEMORY;
2175 goto error2;
2178 TRACE(("reading in program headers at 0x%lx, length 0x%x\n",
2179 elfHeader->e_phoff, elfHeader->e_phnum * elfHeader->e_phentsize));
2181 length = _kern_read(fd, elfHeader->e_phoff, programHeaders,
2182 elfHeader->e_phnum * elfHeader->e_phentsize);
2183 if (length < B_OK) {
2184 status = length;
2185 TRACE(("%s: error reading in program headers\n", fileName));
2186 goto error3;
2188 if (length != elfHeader->e_phnum * elfHeader->e_phentsize) {
2189 TRACE(("%s: short read while reading in program headers\n", fileName));
2190 status = B_ERROR;
2191 goto error3;
2194 // determine how much space we need for all loaded segments
2196 reservedSize = 0;
2197 length = 0;
2199 for (int32 i = 0; i < elfHeader->e_phnum; i++) {
2200 size_t end;
2202 if (programHeaders[i].p_type != PT_LOAD)
2203 continue;
2205 length += ROUNDUP(programHeaders[i].p_memsz
2206 + (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE);
2208 end = ROUNDUP(programHeaders[i].p_memsz + programHeaders[i].p_vaddr,
2209 B_PAGE_SIZE);
2210 if (end > reservedSize)
2211 reservedSize = end;
2213 if (programHeaders[i].IsExecutable())
2214 executableHeaderCount++;
2217 // Check whether the segments have an unreasonable amount of unused space
2218 // inbetween.
2219 if ((ssize_t)reservedSize > length + 8 * 1024) {
2220 status = B_BAD_DATA;
2221 goto error1;
2224 // reserve that space and allocate the areas from that one
2225 if (vm_reserve_address_range(VMAddressSpace::KernelID(), &reservedAddress,
2226 B_ANY_KERNEL_ADDRESS, reservedSize, 0) < B_OK) {
2227 status = B_NO_MEMORY;
2228 goto error3;
2231 image->data_region.size = 0;
2232 image->text_region.size = 0;
2234 for (int32 i = 0; i < elfHeader->e_phnum; i++) {
2235 char regionName[B_OS_NAME_LENGTH];
2236 elf_region *region;
2238 TRACE(("looking at program header %" B_PRId32 "\n", i));
2240 switch (programHeaders[i].p_type) {
2241 case PT_LOAD:
2242 break;
2243 case PT_DYNAMIC:
2244 image->dynamic_section = programHeaders[i].p_vaddr;
2245 continue;
2246 case PT_INTERP:
2247 // should check here for appropriate interpreter
2248 continue;
2249 case PT_PHDR:
2250 // we don't use it
2251 continue;
2252 default:
2253 dprintf("%s: unhandled pheader type %#" B_PRIx32 "\n", fileName,
2254 programHeaders[i].p_type);
2255 continue;
2258 // we're here, so it must be a PT_LOAD segment
2260 // Usually add-ons have two PT_LOAD headers: one for .data one or .text.
2261 // x86 and PPC may differ in permission bits for .data's PT_LOAD header
2262 // x86 is usually RW, PPC is RWE
2264 // Some add-ons may have .text and .data concatenated in a single
2265 // PT_LOAD RWE header and we must map that to .text.
2266 if (programHeaders[i].IsReadWrite()
2267 && (!programHeaders[i].IsExecutable()
2268 || executableHeaderCount > 1)) {
2269 // this is the writable segment
2270 if (image->data_region.size != 0) {
2271 // we've already created this segment
2272 continue;
2274 region = &image->data_region;
2276 snprintf(regionName, B_OS_NAME_LENGTH, "%s_data", fileName);
2277 } else if (programHeaders[i].IsExecutable()) {
2278 // this is the non-writable segment
2279 if (image->text_region.size != 0) {
2280 // we've already created this segment
2281 continue;
2283 region = &image->text_region;
2285 // some programs may have .text and .data concatenated in a
2286 // single PT_LOAD section which is readable/writable/executable
2287 textSectionWritable = programHeaders[i].IsReadWrite();
2288 snprintf(regionName, B_OS_NAME_LENGTH, "%s_text", fileName);
2289 } else {
2290 dprintf("%s: weird program header flags %#" B_PRIx32 "\n", fileName,
2291 programHeaders[i].p_flags);
2292 continue;
2295 region->start = (addr_t)reservedAddress + ROUNDDOWN(
2296 programHeaders[i].p_vaddr, B_PAGE_SIZE);
2297 region->size = ROUNDUP(programHeaders[i].p_memsz
2298 + (programHeaders[i].p_vaddr % B_PAGE_SIZE), B_PAGE_SIZE);
2299 region->id = create_area(regionName, (void **)&region->start,
2300 B_EXACT_ADDRESS, region->size, B_FULL_LOCK,
2301 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
2302 if (region->id < B_OK) {
2303 dprintf("%s: error allocating area: %s\n", fileName,
2304 strerror(region->id));
2305 status = B_NOT_AN_EXECUTABLE;
2306 goto error4;
2308 region->delta = -ROUNDDOWN(programHeaders[i].p_vaddr, B_PAGE_SIZE);
2310 TRACE(("elf_load_kspace: created area \"%s\" at %p\n",
2311 regionName, (void *)region->start));
2313 length = _kern_read(fd, programHeaders[i].p_offset,
2314 (void *)(region->start + (programHeaders[i].p_vaddr % B_PAGE_SIZE)),
2315 programHeaders[i].p_filesz);
2316 if (length < B_OK) {
2317 status = length;
2318 dprintf("%s: error reading in segment %" B_PRId32 "\n", fileName,
2320 goto error5;
2324 image->data_region.delta += image->data_region.start;
2325 image->text_region.delta += image->text_region.start;
2327 // modify the dynamic ptr by the delta of the regions
2328 image->dynamic_section += image->text_region.delta;
2330 status = elf_parse_dynamic_section(image);
2331 if (status < B_OK)
2332 goto error5;
2334 status = init_image_version_infos(image);
2335 if (status != B_OK)
2336 goto error5;
2338 status = check_needed_image_versions(image);
2339 if (status != B_OK)
2340 goto error5;
2342 status = elf_relocate(image, sKernelImage);
2343 if (status < B_OK)
2344 goto error5;
2346 // We needed to read in the contents of the "text" area, but
2347 // now we can protect it read-only/execute, unless this is a
2348 // special image with concatenated .text and .data, when it
2349 // will also need write access.
2350 set_area_protection(image->text_region.id,
2351 B_KERNEL_READ_AREA | B_KERNEL_EXECUTE_AREA
2352 | (textSectionWritable ? B_KERNEL_WRITE_AREA : 0));
2354 // There might be a hole between the two segments, and we don't need to
2355 // reserve this any longer
2356 vm_unreserve_address_range(VMAddressSpace::KernelID(), reservedAddress,
2357 reservedSize);
2359 // ToDo: this should be enabled by kernel settings!
2360 if (1)
2361 load_elf_symbol_table(fd, image);
2363 free(programHeaders);
2364 mutex_lock(&sImageMutex);
2365 register_elf_image(image);
2366 mutex_unlock(&sImageMutex);
2368 done:
2369 _kern_close(fd);
2370 mutex_unlock(&sImageLoadMutex);
2372 return image->id;
2374 error5:
2375 error4:
2376 vm_unreserve_address_range(VMAddressSpace::KernelID(), reservedAddress,
2377 reservedSize);
2378 error3:
2379 free(programHeaders);
2380 error2:
2381 delete_elf_image(image);
2382 elfHeader = NULL;
2383 error1:
2384 free(elfHeader);
2385 error:
2386 mutex_unlock(&sImageLoadMutex);
2387 error0:
2388 dprintf("Could not load kernel add-on \"%s\": %s\n", path,
2389 strerror(status));
2391 if (vnode)
2392 vfs_put_vnode(vnode);
2393 _kern_close(fd);
2395 return status;
2399 status_t
2400 unload_kernel_add_on(image_id id)
2402 MutexLocker _(sImageLoadMutex);
2403 MutexLocker _2(sImageMutex);
2405 elf_image_info *image = find_image(id);
2406 if (image == NULL)
2407 return B_BAD_IMAGE_ID;
2409 unload_elf_image(image);
2410 return B_OK;
2414 struct elf_image_info*
2415 elf_get_kernel_image()
2417 return sKernelImage;
2421 status_t
2422 elf_get_image_info_for_address(addr_t address, image_info* info)
2424 MutexLocker _(sImageMutex);
2425 struct elf_image_info* elfInfo = find_image_at_address(address);
2426 if (elfInfo == NULL)
2427 return B_ENTRY_NOT_FOUND;
2429 info->id = elfInfo->id;
2430 info->type = B_SYSTEM_IMAGE;
2431 info->sequence = 0;
2432 info->init_order = 0;
2433 info->init_routine = NULL;
2434 info->term_routine = NULL;
2435 info->device = -1;
2436 info->node = -1;
2437 // TODO: We could actually fill device/node in.
2438 strlcpy(info->name, elfInfo->name, sizeof(info->name));
2439 info->text = (void*)elfInfo->text_region.start;
2440 info->data = (void*)elfInfo->data_region.start;
2441 info->text_size = elfInfo->text_region.size;
2442 info->data_size = elfInfo->data_region.size;
2444 return B_OK;
2448 image_id
2449 elf_create_memory_image(const char* imageName, addr_t text, size_t textSize,
2450 addr_t data, size_t dataSize)
2452 // allocate the image
2453 elf_image_info* image = create_image_struct();
2454 if (image == NULL)
2455 return B_NO_MEMORY;
2456 MemoryDeleter imageDeleter(image);
2458 // allocate symbol and string tables -- we allocate an empty symbol table,
2459 // so that elf_debug_lookup_symbol_address() won't try the dynamic symbol
2460 // table, which we don't have.
2461 elf_sym* symbolTable = (elf_sym*)malloc(0);
2462 char* stringTable = (char*)malloc(1);
2463 MemoryDeleter symbolTableDeleter(symbolTable);
2464 MemoryDeleter stringTableDeleter(stringTable);
2465 if (symbolTable == NULL || stringTable == NULL)
2466 return B_NO_MEMORY;
2468 // the string table always contains the empty string
2469 stringTable[0] = '\0';
2471 image->debug_symbols = symbolTable;
2472 image->num_debug_symbols = 0;
2473 image->debug_string_table = stringTable;
2475 // dup image name
2476 image->name = strdup(imageName);
2477 if (image->name == NULL)
2478 return B_NO_MEMORY;
2480 // data and text region
2481 image->text_region.id = -1;
2482 image->text_region.start = text;
2483 image->text_region.size = textSize;
2484 image->text_region.delta = 0;
2486 image->data_region.id = -1;
2487 image->data_region.start = data;
2488 image->data_region.size = dataSize;
2489 image->data_region.delta = 0;
2491 mutex_lock(&sImageMutex);
2492 register_elf_image(image);
2493 image_id imageID = image->id;
2494 mutex_unlock(&sImageMutex);
2496 // keep the allocated memory
2497 imageDeleter.Detach();
2498 symbolTableDeleter.Detach();
2499 stringTableDeleter.Detach();
2501 return imageID;
2505 status_t
2506 elf_add_memory_image_symbol(image_id id, const char* name, addr_t address,
2507 size_t size, int32 type)
2509 MutexLocker _(sImageMutex);
2511 // get the image
2512 struct elf_image_info* image = find_image(id);
2513 if (image == NULL)
2514 return B_ENTRY_NOT_FOUND;
2516 // get the current string table size
2517 size_t stringTableSize = 1;
2518 if (image->num_debug_symbols > 0) {
2519 for (int32 i = image->num_debug_symbols - 1; i >= 0; i--) {
2520 int32 nameIndex = image->debug_symbols[i].st_name;
2521 if (nameIndex != 0) {
2522 stringTableSize = nameIndex
2523 + strlen(image->debug_string_table + nameIndex) + 1;
2524 break;
2529 // enter the name in the string table
2530 char* stringTable = (char*)image->debug_string_table;
2531 size_t stringIndex = 0;
2532 if (name != NULL) {
2533 size_t nameSize = strlen(name) + 1;
2534 stringIndex = stringTableSize;
2535 stringTableSize += nameSize;
2536 stringTable = (char*)realloc((char*)image->debug_string_table,
2537 stringTableSize);
2538 if (stringTable == NULL)
2539 return B_NO_MEMORY;
2540 image->debug_string_table = stringTable;
2541 memcpy(stringTable + stringIndex, name, nameSize);
2544 // resize the symbol table
2545 int32 symbolCount = image->num_debug_symbols + 1;
2546 elf_sym* symbolTable = (elf_sym*)realloc(
2547 (elf_sym*)image->debug_symbols, sizeof(elf_sym) * symbolCount);
2548 if (symbolTable == NULL)
2549 return B_NO_MEMORY;
2550 image->debug_symbols = symbolTable;
2552 // enter the symbol
2553 elf_sym& symbol = symbolTable[symbolCount - 1];
2554 symbol.SetInfo(STB_GLOBAL,
2555 type == B_SYMBOL_TYPE_DATA ? STT_OBJECT : STT_FUNC);
2556 symbol.st_name = stringIndex;
2557 symbol.st_value = address;
2558 symbol.st_size = size;
2559 symbol.st_other = 0;
2560 symbol.st_shndx = 0;
2561 image->num_debug_symbols++;
2563 return B_OK;
2567 /*! Reads the symbol and string table for the kernel image with the given ID.
2568 \a _symbolCount and \a _stringTableSize are both in- and output parameters.
2569 When called they call the size of the buffers given by \a symbolTable and
2570 \a stringTable respectively. When the function returns successfully, they
2571 will contain the actual sizes (which can be greater than the original ones).
2572 The function will copy as much as possible into the buffers. For only
2573 getting the required buffer sizes, it can be invoked with \c NULL buffers.
2574 On success \a _imageDelta will contain the offset to be added to the symbol
2575 values in the table to get the actual symbol addresses.
2577 status_t
2578 elf_read_kernel_image_symbols(image_id id, elf_sym* symbolTable,
2579 int32* _symbolCount, char* stringTable, size_t* _stringTableSize,
2580 addr_t* _imageDelta, bool kernel)
2582 // check params
2583 if (_symbolCount == NULL || _stringTableSize == NULL)
2584 return B_BAD_VALUE;
2585 if (!kernel) {
2586 if (!IS_USER_ADDRESS(_symbolCount) || !IS_USER_ADDRESS(_stringTableSize)
2587 || (_imageDelta != NULL && !IS_USER_ADDRESS(_imageDelta))
2588 || (symbolTable != NULL && !IS_USER_ADDRESS(symbolTable))
2589 || (stringTable != NULL && !IS_USER_ADDRESS(stringTable))) {
2590 return B_BAD_ADDRESS;
2594 // get buffer sizes
2595 int32 maxSymbolCount;
2596 size_t maxStringTableSize;
2597 if (kernel) {
2598 maxSymbolCount = *_symbolCount;
2599 maxStringTableSize = *_stringTableSize;
2600 } else {
2601 if (user_memcpy(&maxSymbolCount, _symbolCount, sizeof(maxSymbolCount))
2602 != B_OK
2603 || user_memcpy(&maxStringTableSize, _stringTableSize,
2604 sizeof(maxStringTableSize)) != B_OK) {
2605 return B_BAD_ADDRESS;
2609 // find the image
2610 MutexLocker _(sImageMutex);
2611 struct elf_image_info* image = find_image(id);
2612 if (image == NULL)
2613 return B_ENTRY_NOT_FOUND;
2615 // get the tables and infos
2616 addr_t imageDelta = image->text_region.delta;
2617 const elf_sym* symbols;
2618 int32 symbolCount;
2619 const char* strings;
2621 if (image->debug_symbols != NULL) {
2622 symbols = image->debug_symbols;
2623 symbolCount = image->num_debug_symbols;
2624 strings = image->debug_string_table;
2625 } else {
2626 symbols = image->syms;
2627 symbolCount = image->symhash[1];
2628 strings = image->strtab;
2631 // The string table size isn't stored in the elf_image_info structure. Find
2632 // out by iterating through all symbols.
2633 size_t stringTableSize = 0;
2634 for (int32 i = 0; i < symbolCount; i++) {
2635 size_t index = symbols[i].st_name;
2636 if (index > stringTableSize)
2637 stringTableSize = index;
2639 stringTableSize += strlen(strings + stringTableSize) + 1;
2640 // add size of the last string
2642 // copy symbol table
2643 int32 symbolsToCopy = min_c(symbolCount, maxSymbolCount);
2644 if (symbolTable != NULL && symbolsToCopy > 0) {
2645 if (kernel) {
2646 memcpy(symbolTable, symbols, sizeof(elf_sym) * symbolsToCopy);
2647 } else if (user_memcpy(symbolTable, symbols,
2648 sizeof(elf_sym) * symbolsToCopy) != B_OK) {
2649 return B_BAD_ADDRESS;
2653 // copy string table
2654 size_t stringsToCopy = min_c(stringTableSize, maxStringTableSize);
2655 if (stringTable != NULL && stringsToCopy > 0) {
2656 if (kernel) {
2657 memcpy(stringTable, strings, stringsToCopy);
2658 } else {
2659 if (user_memcpy(stringTable, strings, stringsToCopy)
2660 != B_OK) {
2661 return B_BAD_ADDRESS;
2666 // copy sizes
2667 if (kernel) {
2668 *_symbolCount = symbolCount;
2669 *_stringTableSize = stringTableSize;
2670 if (_imageDelta != NULL)
2671 *_imageDelta = imageDelta;
2672 } else {
2673 if (user_memcpy(_symbolCount, &symbolCount, sizeof(symbolCount)) != B_OK
2674 || user_memcpy(_stringTableSize, &stringTableSize,
2675 sizeof(stringTableSize)) != B_OK
2676 || (_imageDelta != NULL && user_memcpy(_imageDelta, &imageDelta,
2677 sizeof(imageDelta)) != B_OK)) {
2678 return B_BAD_ADDRESS;
2682 return B_OK;
2686 status_t
2687 elf_init(kernel_args *args)
2689 struct preloaded_image *image;
2691 image_init();
2693 sImagesHash = new(std::nothrow) ImageHash();
2694 if (sImagesHash == NULL)
2695 return B_NO_MEMORY;
2696 status_t init = sImagesHash->Init(IMAGE_HASH_SIZE);
2697 if (init != B_OK)
2698 return init;
2700 // Build a image structure for the kernel, which has already been loaded.
2701 // The preloaded_images were already prepared by the VM.
2702 image = args->kernel_image;
2703 if (insert_preloaded_image(static_cast<preloaded_elf_image *>(image),
2704 true) < B_OK)
2705 panic("could not create kernel image.\n");
2707 // Build image structures for all preloaded images.
2708 for (image = args->preloaded_images; image != NULL; image = image->next)
2709 insert_preloaded_image(static_cast<preloaded_elf_image *>(image),
2710 false);
2712 add_debugger_command("ls", &dump_address_info,
2713 "lookup symbol for a particular address");
2714 add_debugger_command("symbols", &dump_symbols, "dump symbols for image");
2715 add_debugger_command("symbol", &dump_symbol, "search symbol in images");
2716 add_debugger_command_etc("image", &dump_image, "dump image info",
2717 "Prints info about the specified image.\n"
2718 " <image> - pointer to the semaphore structure, or ID\n"
2719 " of the image to print info for.\n", 0);
2721 sInitialized = true;
2722 return B_OK;
2726 // #pragma mark -
2729 /*! Reads the symbol and string table for the kernel image with the given ID.
2730 \a _symbolCount and \a _stringTableSize are both in- and output parameters.
2731 When called they call the size of the buffers given by \a symbolTable and
2732 \a stringTable respectively. When the function returns successfully, they
2733 will contain the actual sizes (which can be greater than the original ones).
2734 The function will copy as much as possible into the buffers. For only
2735 getting the required buffer sizes, it can be invoked with \c NULL buffers.
2736 On success \a _imageDelta will contain the offset to be added to the symbol
2737 values in the table to get the actual symbol addresses.
2739 status_t
2740 _user_read_kernel_image_symbols(image_id id, elf_sym* symbolTable,
2741 int32* _symbolCount, char* stringTable, size_t* _stringTableSize,
2742 addr_t* _imageDelta)
2744 return elf_read_kernel_image_symbols(id, symbolTable, _symbolCount,
2745 stringTable, _stringTableSize, _imageDelta, false);