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.
10 /*! Contains the ELF loader */
25 #include <AutoDeleter.h>
27 #include <boot/kernel_args.h>
29 #include <image_defs.h>
35 #include <runtime_loader.h>
36 #include <util/AutoLock.h>
39 #include <vm/vm_types.h>
40 #include <vm/VMAddressSpace.h>
41 #include <vm/VMArea.h>
50 # define TRACE(x) dprintf x
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
74 bool Compare(KeyType key
, ValueType
* entry
) const
76 return key
== entry
->id
;
80 typedef BOpenHashTable
<ImageHashDefinition
> ImageHash
;
85 static ImageHash
*sImagesHash
;
87 static struct elf_image_info
*sKernelImage
= NULL
;
88 static mutex sImageMutex
= MUTEX_INITIALIZER("kimages_lock");
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
);
101 unregister_elf_image(struct elf_image_info
*image
)
103 unregister_image(team_get_kernel_team(), image
->id
);
104 sImagesHash
->Remove(image
);
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
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
;
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
;
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
,
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
)
175 if (!debug_debugger_running())
176 ASSERT_LOCKED_MUTEX(&sImageMutex
);
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
189 <= (image
->data_region
.start
+ image
->data_region
.size
)))
198 dump_address_info(int argc
, char **argv
)
200 const char *symbol
, *imageName
;
202 addr_t address
, baseAddress
;
205 kprintf("usage: ls <address>\n");
209 address
= strtoul(argv
[1], NULL
, 16);
213 if (IS_KERNEL_ADDRESS(address
)) {
214 error
= elf_debug_lookup_symbol_address(address
, &baseAddress
, &symbol
,
215 &imageName
, &exactMatch
);
217 error
= elf_debug_lookup_user_symbol_address(
218 debug_get_debugged_thread()->team
, address
, &baseAddress
, &symbol
,
219 &imageName
, &exactMatch
);
223 kprintf("%p = %s + 0x%lx (%s)%s\n", (void*)address
, symbol
,
224 address
- baseAddress
, imageName
, exactMatch
? "" : " (nearest)");
226 kprintf("There is no image loaded at this address!\n");
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
)
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
));
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;
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
);
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
);
295 elf_hash(const char *name
)
301 hash
= (hash
<< 4) + (uint8
)*name
++;
302 if ((temp
= hash
& 0xf0000000) != 0)
311 get_symbol_type_string(elf_sym
*symbol
)
313 switch (symbol
->Type()) {
327 get_symbol_bind_string(elf_sym
*symbol
)
329 switch (symbol
->Bind()) {
342 /*! Searches a symbol (pattern) in all kernel images */
344 dump_symbol(int argc
, char **argv
)
346 if (argc
!= 2 || !strcmp(argv
[1], "--help")) {
347 kprintf("usage: %s <symbol-name>\n", argv
[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) {
367 = (void*)(symbol
->st_value
+ image
->text_region
.delta
);
368 kprintf("%p %5lu %s:%s\n", symbolAddress
, symbol
->st_size
,
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
);
399 dump_symbols(int argc
, char **argv
)
401 struct elf_image_info
*image
= NULL
;
404 // if the argument looks like a hex number, treat it as such
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
) {
424 kprintf("No image covers %#" B_PRIxADDR
" in the kernel!\n",
428 image
= sImagesHash
->Lookup(num
);
430 kprintf("image %#" B_PRIxADDR
" doesn't exist in the "
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])) {
446 kprintf("No image \"%s\" found in kernel!\n", argv
[1]);
449 kprintf("usage: %s image_name/image_id/address_in_image\n", argv
[0]);
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
)
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
);
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
)
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
));
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
);
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
);
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
543 addr_t num
= strtoul(argv
[1], NULL
, 0);
545 if (IS_KERNEL_ADDRESS(num
)) {
547 dump_image_info((struct elf_image_info
*)num
);
549 image
= sImagesHash
->Lookup(num
);
551 kprintf("image %#" B_PRIxADDR
" doesn't exist in the kernel!\n",
554 dump_image_info(image
);
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
);
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
);
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)
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) {
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.
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 "
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
)
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) {
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
656 // TODO: Revise the default version case! That's how
657 // FreeBSD implements it, but glibc doesn't handle it
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
)) {
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
;
699 elf_parse_dynamic_section(struct elf_image_info
*image
)
702 ssize_t neededOffset
= -1;
704 TRACE(("top of elf_parse_dynamic_section\n"));
710 d
= (elf_dyn
*)image
->dynamic_section
;
714 for (int32 i
= 0; d
[i
].d_tag
!= DT_NULL
; i
++) {
715 switch (d
[i
].d_tag
) {
717 neededOffset
= d
[i
].d_un
.d_ptr
+ image
->text_region
.delta
;
720 image
->symhash
= (uint32
*)(d
[i
].d_un
.d_ptr
721 + image
->text_region
.delta
);
724 image
->strtab
= (char *)(d
[i
].d_un
.d_ptr
725 + image
->text_region
.delta
);
728 image
->syms
= (elf_sym
*)(d
[i
].d_un
.d_ptr
729 + image
->text_region
.delta
);
732 image
->rel
= (elf_rel
*)(d
[i
].d_un
.d_ptr
733 + image
->text_region
.delta
);
736 image
->rel_len
= d
[i
].d_un
.d_val
;
739 image
->rela
= (elf_rela
*)(d
[i
].d_un
.d_ptr
740 + image
->text_region
.delta
);
743 image
->rela_len
= d
[i
].d_un
.d_val
;
746 image
->pltrel
= (elf_rel
*)(d
[i
].d_un
.d_ptr
747 + image
->text_region
.delta
);
750 image
->pltrel_len
= d
[i
].d_un
.d_val
;
753 image
->pltrel_type
= d
[i
].d_un
.d_val
;
756 image
->symbol_versions
= (elf_versym
*)
757 (d
[i
].d_un
.d_ptr
+ image
->text_region
.delta
);
760 image
->version_definitions
= (elf_verdef
*)
761 (d
[i
].d_un
.d_ptr
+ image
->text_region
.delta
);
764 image
->num_version_definitions
= d
[i
].d_un
.d_val
;
767 image
->needed_versions
= (elf_verneed
*)
768 (d
[i
].d_un
.d_ptr
+ image
->text_region
.delta
);
771 image
->num_needed_versions
= d
[i
].d_un
.d_val
;
774 image
->symbolic
= true;
778 uint32 flags
= d
[i
].d_un
.d_val
;
779 if ((flags
& DF_SYMBOLIC
) != 0)
780 image
->symbolic
= true;
789 // lets make sure we found all the required sections
790 if (!image
->symhash
|| !image
->syms
|| !image
->strtab
)
793 TRACE(("needed_offset = %ld\n", neededOffset
));
795 if (neededOffset
>= 0)
796 image
->needed
= STRING(image
, neededOffset
);
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
);
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) {
826 definition
= (elf_verdef
*)
827 ((uint8
*)definition
+ definition
->vd_next
);
830 // version not found -- fail, if not weak
832 dprintf("%s: version \"%s\" not found (required by %s)\n", image
->name
,
833 neededVersion
.name
, dependentImage
->name
);
834 return B_MISSING_SYMBOL
;
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
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
);
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",
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
);
893 // allocate the version infos
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");
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) {
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
);
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
);
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
);
952 check_needed_image_versions(elf_image_info
* image
)
954 if (image
->needed_versions
== NULL
)
957 elf_verneed
* needed
= image
->needed_versions
;
958 for (uint32 i
= 0; i
< image
->num_needed_versions
; i
++) {
959 elf_image_info
* dependency
= sKernelImage
;
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);
972 vernaux
= (elf_vernaux
*)((uint8
*)vernaux
+ vernaux
->vna_next
);
975 needed
= (elf_verneed
*)((uint8
*)needed
+ needed
->vn_next
);
982 /*! Resolves the \a symbol by linking against \a sharedImage if necessary.
983 Returns the resolved symbol's address in \a _symbolAddress.
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
;
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
;
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
;
1014 elf_image_info
* foundImage
= firstImage
;
1015 elf_sym
* foundSymbol
= elf_find_symbol(firstImage
, symbolName
, versionInfo
,
1017 if (foundSymbol
== NULL
1018 || foundSymbol
->Bind() == STB_WEAK
) {
1019 // Not found or found a weak definition -- try to resolve in the other
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;
1040 dprintf("\"%s\": could not resolve symbol '%s'\n", image
->name
,
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
;
1059 /*! Until we have shared library support, just this links against the kernel */
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
1069 TRACE(("total %i rel relocs\n", image
->rel_len
/ (int)sizeof(elf_rel
)));
1071 status
= arch_elf_relocate_rel(image
, resolveImage
, image
->rel
,
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
,
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
);
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
,
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
;
1127 unload_elf_image(struct elf_image_info
*image
)
1129 if (atomic_add(&image
->ref_count
, -1) > 1)
1132 TRACE(("unload image %" B_PRId32
", %s\n", image
->id
, image
->name
));
1134 unregister_elf_image(image
);
1135 delete_elf_image(image
);
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;
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");
1160 length
= read_pos(fd
, elfHeader
->e_shoff
, sectionHeaders
, size
);
1161 if (length
< size
) {
1162 TRACE(("error reading in program headers\n"));
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
= §ionHeaders
[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
;
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
;
1188 = read_pos(fd
, sectionHeaders
[i
].sh_offset
, symbolTable
, size
);
1189 if (length
< size
) {
1190 TRACE(("error reading in symbol table\n"));
1195 numSymbols
= size
/ sizeof(elf_sym
);
1200 if (symbolTable
== NULL
) {
1201 TRACE(("no symbol table\n"));
1202 status
= B_BAD_VALUE
;
1206 // read in string table
1208 stringTable
= (char *)malloc(size
= stringHeader
->sh_size
);
1209 if (stringTable
== NULL
) {
1210 status
= B_NO_MEMORY
;
1214 length
= read_pos(fd
, stringHeader
->sh_offset
, stringTable
, size
);
1215 if (length
< size
) {
1216 TRACE(("error reading in string table\n"));
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
);
1236 free(sectionHeaders
);
1243 insert_preloaded_image(preloaded_elf_image
*preloadedImage
, bool kernel
)
1247 status
= verify_eheader(&preloadedImage
->elf_header
);
1251 elf_image_info
*image
= create_image_struct();
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
);
1271 status
= init_image_version_infos(image
);
1276 status
= check_needed_image_versions(image
);
1280 status
= elf_relocate(image
, sKernelImage
);
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
,
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
);
1320 delete_elf_image(image
);
1322 preloadedImage
->id
= -1;
1328 // #pragma mark - userland symbol lookup
1331 class UserSymbolLookup
{
1333 static UserSymbolLookup
& Default()
1338 status_t
Init(Team
* team
)
1340 // find the runtime loader debug 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)
1352 // copy the runtime loader data structure
1353 if (!_Read((runtime_loader_debug_area
*)area
->Base(), fDebugArea
))
1354 return B_BAD_ADDRESS
;
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
1374 status_t error
= _FindImageAtAddress(address
, image
);
1375 if (error
!= B_OK
) {
1376 // commpage requires special treatment since kernel stores symbol
1378 addr_t commPageAddress
= (addr_t
)fTeam
->commpage_address
;
1379 if (address
>= commPageAddress
1380 && address
< commPageAddress
+ COMMPAGE_SIZE
) {
1382 *_imageName
= "commpage";
1383 address
-= (addr_t
)commPageAddress
;
1384 error
= elf_debug_lookup_symbol_address(address
, _baseAddress
,
1385 _symbolName
, NULL
, _exactMatch
);
1387 *_baseAddress
+= (addr_t
)fTeam
->commpage_address
;
1392 strlcpy(fImageName
, image
.name
, sizeof(fImageName
));
1394 // symbol hash table size
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
++) {
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
) {
1423 if (!_Read(image
.syms
+ j
, symbol
))
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
) {
1440 // skip symbols starting after the given address
1441 addr_t symbolAddress
= symbol
.st_value
+ textRegion
.delta
;
1442 if (symbolAddress
> address
)
1444 addr_t symbolDelta
= address
- symbolAddress
;
1446 if (symbolDelta
< deltaFound
) {
1447 deltaFound
= symbolDelta
;
1448 symbolFound
= symbol
;
1450 if (symbolDelta
>= 0 && symbolDelta
< symbol
.st_size
) {
1460 *_imageName
= fImageName
;
1463 *_symbolName
= NULL
;
1465 if (deltaFound
< INT_MAX
) {
1466 if (_ReadString(image
, symbolFound
.st_name
, fSymbolName
,
1467 sizeof(fSymbolName
))) {
1468 *_symbolName
= fSymbolName
;
1470 // we can't get its name, so forget the symbol
1471 deltaFound
= INT_MAX
;
1477 if (deltaFound
< INT_MAX
)
1478 *_baseAddress
= symbolFound
.st_value
+ textRegion
.delta
;
1480 *_baseAddress
= textRegion
.vmstart
;
1484 *_exactMatch
= exactMatch
;
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
) {
1505 imageAddress
= image
.next
;
1508 return B_ENTRY_NOT_FOUND
;
1511 bool _ReadString(const image_t
& image
, uint32 offset
, char* buffer
,
1514 const char* address
= image
.strtab
+ offset
;
1516 if (!IS_USER_ADDRESS(address
))
1519 if (debug_debugger_running()) {
1520 return debug_strlcpy(B_CURRENT_TEAM
, buffer
, address
, bufferSize
)
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
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
>
1540 UserSymbolLookup::_Read(const T
* address
, T
& data
)
1542 if (!IS_USER_ADDRESS(address
))
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
1559 get_image_symbol(image_id id
, const char *name
, int32 symbolClass
,
1562 struct elf_image_info
*image
;
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
;
1576 symbol
= elf_find_symbol(image
, name
, NULL
, true);
1577 if (symbol
== NULL
|| symbol
->st_shndx
== SHN_UNDEF
) {
1578 status
= B_ENTRY_NOT_FOUND
;
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
);
1591 mutex_unlock(&sImageMutex
);
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!
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;
1614 TRACE(("looking up %p\n", (void *)address
));
1619 //mutex_lock(&sImageMutex);
1621 image
= find_image_at_address(address
);
1622 // get image that may contain the address
1624 if (image
!= NULL
) {
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
)
1645 = address
- (symbol
->st_value
+ image
->text_region
.delta
);
1646 if (symbolDelta
>= 0 && symbolDelta
< symbol
->st_size
)
1649 if (exactMatch
|| symbolDelta
< deltaFound
) {
1650 deltaFound
= symbolDelta
;
1651 symbolFound
= symbol
;
1652 symbolName
= image
->debug_string_table
+ symbol
->st_name
;
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
)
1673 symbolDelta
= address
- (long)(symbol
->st_value
1674 + image
->text_region
.delta
);
1675 if (symbolDelta
>= 0 && symbolDelta
< symbol
->st_size
)
1678 if (exactMatch
|| symbolDelta
< deltaFound
) {
1679 deltaFound
= symbolDelta
;
1680 symbolFound
= symbol
;
1681 symbolName
= SYMNAME(image
, symbol
);
1692 if (symbolFound
!= NULL
) {
1694 *_symbolName
= symbolName
;
1696 *_imageName
= image
->name
;
1698 *_baseAddress
= symbolFound
->st_value
+ image
->text_region
.delta
;
1700 *_exactMatch
= exactMatch
;
1703 } else if (image
!= NULL
) {
1704 TRACE(("symbol not found!\n"));
1707 *_symbolName
= NULL
;
1709 *_imageName
= image
->name
;
1711 *_baseAddress
= image
->text_region
.start
;
1713 *_exactMatch
= false;
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);
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.
1735 elf_debug_lookup_user_symbol_address(Team
* team
, addr_t address
,
1736 addr_t
*_baseAddress
, const char **_symbolName
, const char **_imageName
,
1739 if (team
== NULL
|| team
== team_get_kernel_team())
1742 UserSymbolLookup
& lookup
= UserSymbolLookup::Default();
1743 status_t error
= lookup
.Init(team
);
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.
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
;
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
;
1792 elf_lookup_kernel_symbol(const char* name
, elf_symbol_info
* info
)
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
;
1806 elf_load_user_image(const char *path
, Team
*team
, int flags
, addr_t
*entry
)
1809 elf_phdr
*programHeaders
= NULL
;
1810 char baseName
[B_OS_NAME_LENGTH
];
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);
1826 status
= _kern_read_stat(fd
, NULL
, false, &st
, sizeof(st
));
1830 // read and verify the ELF header
1832 length
= _kern_read(fd
, 0, &elfHeader
, sizeof(elfHeader
));
1833 if (length
< B_OK
) {
1838 if (length
!= sizeof(elfHeader
)) {
1840 status
= B_NOT_AN_EXECUTABLE
;
1843 status
= verify_eheader(&elfHeader
);
1847 struct elf_image_info
* image
;
1848 image
= create_image_struct();
1849 if (image
== NULL
) {
1850 status
= B_NO_MEMORY
;
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
;
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
) {
1871 dprintf("error reading in program headers\n");
1874 if (length
!= elfHeader
.e_phnum
* elfHeader
.e_phentsize
) {
1875 dprintf("short read while reading in program headers\n");
1880 // construct a nice name for the region we have to create below
1884 const char *leaf
= strrchr(path
, '/');
1890 length
= strlen(leaf
);
1891 if (length
> B_OS_NAME_LENGTH
- 8)
1892 sprintf(baseName
, "...%s", leaf
+ length
+ 8 - B_OS_NAME_LENGTH
);
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
;
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
;
1915 mappedAreas
[i
] = -1;
1917 if (programHeaders
[i
].p_type
== PT_DYNAMIC
) {
1918 image
->dynamic_section
= programHeaders
[i
].p_vaddr
;
1922 if (programHeaders
[i
].p_type
!= PT_LOAD
)
1925 regionAddress
= (char *)(ROUNDDOWN(programHeaders
[i
].p_vaddr
,
1926 B_PAGE_SIZE
) + delta
);
1927 originalRegionAddress
= regionAddress
;
1929 if (programHeaders
[i
].p_flags
& PF_WRITE
) {
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 **)®ionAddress
,
1942 addressSpec
, fileUpperBound
,
1943 B_READ_AREA
| B_WRITE_AREA
, REGION_PRIVATE_MAP
, false,
1944 fd
, ROUNDDOWN(programHeaders
[i
].p_offset
, B_PAGE_SIZE
));
1946 dprintf("error mapping file data: %s!\n", strerror(id
));
1947 status
= B_NOT_AN_EXECUTABLE
;
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**)®ionAddress
);
1985 dprintf("error allocating bss area: %s!\n", strerror(id
));
1986 status
= B_NOT_AN_EXECUTABLE
;
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 **)®ionAddress
,
1998 addressSpec
, segmentSize
,
1999 B_READ_AREA
| B_WRITE_AREA
, REGION_PRIVATE_MAP
, false, fd
,
2000 ROUNDDOWN(programHeaders
[i
].p_offset
, B_PAGE_SIZE
));
2002 dprintf("error mapping file text: %s!\n", strerror(id
));
2003 status
= B_NOT_AN_EXECUTABLE
;
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
);
2032 status
= elf_relocate(image
, image
);
2036 // set correct area protection
2037 for (i
= 0; i
< elfHeader
.e_phnum
; i
++) {
2038 if (mappedAreas
[i
] == -1)
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
,
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
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
,
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
;
2087 image
->elf_header
= NULL
;
2088 delete_elf_image(image
);
2091 free(programHeaders
);
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
;
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);
2118 struct vnode
*vnode
;
2119 status
= vfs_get_vnode_from_fd(fd
, true, &vnode
);
2123 // get the file name
2124 fileName
= strrchr(path
, '/');
2125 if (fileName
== NULL
)
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
);
2136 atomic_add(&image
->ref_count
, 1);
2140 elfHeader
= (elf_ehdr
*)malloc(sizeof(*elfHeader
));
2142 status
= B_NO_MEMORY
;
2146 length
= _kern_read(fd
, 0, elfHeader
, sizeof(*elfHeader
));
2147 if (length
< B_OK
) {
2151 if (length
!= sizeof(*elfHeader
)) {
2153 status
= B_NOT_AN_EXECUTABLE
;
2156 status
= verify_eheader(elfHeader
);
2160 image
= create_image_struct();
2162 status
= B_NO_MEMORY
;
2165 image
->vnode
= vnode
;
2166 image
->elf_header
= elfHeader
;
2167 image
->name
= strdup(path
);
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
;
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
) {
2185 TRACE(("%s: error reading in program headers\n", fileName
));
2188 if (length
!= elfHeader
->e_phnum
* elfHeader
->e_phentsize
) {
2189 TRACE(("%s: short read while reading in program headers\n", fileName
));
2194 // determine how much space we need for all loaded segments
2199 for (int32 i
= 0; i
< elfHeader
->e_phnum
; i
++) {
2202 if (programHeaders
[i
].p_type
!= PT_LOAD
)
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
,
2210 if (end
> reservedSize
)
2213 if (programHeaders
[i
].IsExecutable())
2214 executableHeaderCount
++;
2217 // Check whether the segments have an unreasonable amount of unused space
2219 if ((ssize_t
)reservedSize
> length
+ 8 * 1024) {
2220 status
= B_BAD_DATA
;
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
;
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
];
2238 TRACE(("looking at program header %" B_PRId32
"\n", i
));
2240 switch (programHeaders
[i
].p_type
) {
2244 image
->dynamic_section
= programHeaders
[i
].p_vaddr
;
2247 // should check here for appropriate interpreter
2253 dprintf("%s: unhandled pheader type %#" B_PRIx32
"\n", fileName
,
2254 programHeaders
[i
].p_type
);
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
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
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
);
2290 dprintf("%s: weird program header flags %#" B_PRIx32
"\n", fileName
,
2291 programHeaders
[i
].p_flags
);
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 **)®ion
->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
;
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
) {
2318 dprintf("%s: error reading in segment %" B_PRId32
"\n", fileName
,
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
);
2334 status
= init_image_version_infos(image
);
2338 status
= check_needed_image_versions(image
);
2342 status
= elf_relocate(image
, sKernelImage
);
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
,
2359 // ToDo: this should be enabled by kernel settings!
2361 load_elf_symbol_table(fd
, image
);
2363 free(programHeaders
);
2364 mutex_lock(&sImageMutex
);
2365 register_elf_image(image
);
2366 mutex_unlock(&sImageMutex
);
2370 mutex_unlock(&sImageLoadMutex
);
2376 vm_unreserve_address_range(VMAddressSpace::KernelID(), reservedAddress
,
2379 free(programHeaders
);
2381 delete_elf_image(image
);
2386 mutex_unlock(&sImageLoadMutex
);
2388 dprintf("Could not load kernel add-on \"%s\": %s\n", path
,
2392 vfs_put_vnode(vnode
);
2400 unload_kernel_add_on(image_id id
)
2402 MutexLocker
_(sImageLoadMutex
);
2403 MutexLocker
_2(sImageMutex
);
2405 elf_image_info
*image
= find_image(id
);
2407 return B_BAD_IMAGE_ID
;
2409 unload_elf_image(image
);
2414 struct elf_image_info
*
2415 elf_get_kernel_image()
2417 return sKernelImage
;
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
;
2432 info
->init_order
= 0;
2433 info
->init_routine
= NULL
;
2434 info
->term_routine
= NULL
;
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
;
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();
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
)
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
;
2476 image
->name
= strdup(imageName
);
2477 if (image
->name
== NULL
)
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();
2506 elf_add_memory_image_symbol(image_id id
, const char* name
, addr_t address
,
2507 size_t size
, int32 type
)
2509 MutexLocker
_(sImageMutex
);
2512 struct elf_image_info
* image
= find_image(id
);
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;
2529 // enter the name in the string table
2530 char* stringTable
= (char*)image
->debug_string_table
;
2531 size_t stringIndex
= 0;
2533 size_t nameSize
= strlen(name
) + 1;
2534 stringIndex
= stringTableSize
;
2535 stringTableSize
+= nameSize
;
2536 stringTable
= (char*)realloc((char*)image
->debug_string_table
,
2538 if (stringTable
== NULL
)
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
)
2550 image
->debug_symbols
= symbolTable
;
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
++;
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.
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
)
2583 if (_symbolCount
== NULL
|| _stringTableSize
== NULL
)
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
;
2595 int32 maxSymbolCount
;
2596 size_t maxStringTableSize
;
2598 maxSymbolCount
= *_symbolCount
;
2599 maxStringTableSize
= *_stringTableSize
;
2601 if (user_memcpy(&maxSymbolCount
, _symbolCount
, sizeof(maxSymbolCount
))
2603 || user_memcpy(&maxStringTableSize
, _stringTableSize
,
2604 sizeof(maxStringTableSize
)) != B_OK
) {
2605 return B_BAD_ADDRESS
;
2610 MutexLocker
_(sImageMutex
);
2611 struct elf_image_info
* image
= find_image(id
);
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
;
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
;
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) {
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) {
2657 memcpy(stringTable
, strings
, stringsToCopy
);
2659 if (user_memcpy(stringTable
, strings
, stringsToCopy
)
2661 return B_BAD_ADDRESS
;
2668 *_symbolCount
= symbolCount
;
2669 *_stringTableSize
= stringTableSize
;
2670 if (_imageDelta
!= NULL
)
2671 *_imageDelta
= imageDelta
;
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
;
2687 elf_init(kernel_args
*args
)
2689 struct preloaded_image
*image
;
2693 sImagesHash
= new(std::nothrow
) ImageHash();
2694 if (sImagesHash
== NULL
)
2696 status_t init
= sImagesHash
->Init(IMAGE_HASH_SIZE
);
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
),
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
),
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;
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.
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);