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
56 #define IMAGE_HASH_SIZE 16
58 struct ImageHashDefinition
{
59 typedef struct elf_image_info ValueType
;
60 typedef image_id KeyType
;
62 size_t Hash(ValueType
* entry
) const
63 { return HashKey(entry
->id
); }
64 ValueType
*& GetLink(ValueType
* entry
) const
65 { return entry
->next
; }
67 size_t HashKey(KeyType key
) const
72 bool Compare(KeyType key
, ValueType
* entry
) const
74 return key
== entry
->id
;
78 typedef BOpenHashTable
<ImageHashDefinition
> ImageHash
;
80 static ImageHash
*sImagesHash
;
82 static struct elf_image_info
*sKernelImage
= NULL
;
83 static mutex sImageMutex
= MUTEX_INITIALIZER("kimages_lock");
85 static mutex sImageLoadMutex
= MUTEX_INITIALIZER("kimages_load_lock");
86 // serializes loading/unloading add-ons locking order
87 // sImageLoadMutex -> sImageMutex
88 static bool sInitialized
= false;
91 static elf_sym
*elf_find_symbol(struct elf_image_info
*image
, const char *name
,
92 const elf_version_info
*version
, bool lookupDefault
);
96 unregister_elf_image(struct elf_image_info
*image
)
98 unregister_image(team_get_kernel_team(), image
->id
);
99 sImagesHash
->Remove(image
);
104 register_elf_image(struct elf_image_info
*image
)
106 image_info imageInfo
;
108 memset(&imageInfo
, 0, sizeof(image_info
));
109 imageInfo
.id
= image
->id
;
110 imageInfo
.type
= B_SYSTEM_IMAGE
;
111 strlcpy(imageInfo
.name
, image
->name
, sizeof(imageInfo
.name
));
113 imageInfo
.text
= (void *)image
->text_region
.start
;
114 imageInfo
.text_size
= image
->text_region
.size
;
115 imageInfo
.data
= (void *)image
->data_region
.start
;
116 imageInfo
.data_size
= image
->data_region
.size
;
118 if (image
->text_region
.id
>= 0) {
119 // evaluate the API/ABI version symbols
122 imageInfo
.api_version
= 0;
123 elf_sym
* symbol
= elf_find_symbol(image
,
124 B_SHARED_OBJECT_HAIKU_VERSION_VARIABLE_NAME
, NULL
, true);
125 if (symbol
!= NULL
&& symbol
->st_shndx
!= SHN_UNDEF
126 && symbol
->st_value
> 0
127 && symbol
->Type() == STT_OBJECT
128 && symbol
->st_size
>= sizeof(uint32
)) {
129 addr_t symbolAddress
= symbol
->st_value
+ image
->text_region
.delta
;
130 if (symbolAddress
>= image
->text_region
.start
131 && symbolAddress
- image
->text_region
.start
+ sizeof(uint32
)
132 <= image
->text_region
.size
) {
133 imageInfo
.api_version
= *(uint32
*)symbolAddress
;
139 symbol
= elf_find_symbol(image
,
140 B_SHARED_OBJECT_HAIKU_ABI_VARIABLE_NAME
, NULL
, true);
141 if (symbol
!= NULL
&& symbol
->st_shndx
!= SHN_UNDEF
142 && symbol
->st_value
> 0
143 && symbol
->Type() == STT_OBJECT
144 && symbol
->st_size
>= sizeof(uint32
)) {
145 addr_t symbolAddress
= symbol
->st_value
+ image
->text_region
.delta
;
146 if (symbolAddress
>= image
->text_region
.start
147 && symbolAddress
- image
->text_region
.start
+ sizeof(uint32
)
148 <= image
->text_region
.size
) {
149 imageInfo
.api_version
= *(uint32
*)symbolAddress
;
153 // in-memory image -- use the current values
154 imageInfo
.api_version
= B_HAIKU_VERSION
;
155 imageInfo
.abi
= B_HAIKU_ABI
;
158 image
->id
= register_image(team_get_kernel_team(), &imageInfo
,
160 sImagesHash
->Insert(image
);
164 /*! Note, you must lock the image mutex when you call this function. */
165 static struct elf_image_info
*
166 find_image_at_address(addr_t address
)
169 if (!debug_debugger_running())
170 ASSERT_LOCKED_MUTEX(&sImageMutex
);
173 ImageHash::Iterator
iterator(sImagesHash
);
175 // get image that may contain the address
177 while (iterator
.HasNext()) {
178 struct elf_image_info
* image
= iterator
.Next();
179 if ((address
>= image
->text_region
.start
&& address
180 <= (image
->text_region
.start
+ image
->text_region
.size
))
181 || (address
>= image
->data_region
.start
183 <= (image
->data_region
.start
+ image
->data_region
.size
)))
192 dump_address_info(int argc
, char **argv
)
194 const char *symbol
, *imageName
;
196 addr_t address
, baseAddress
;
199 kprintf("usage: ls <address>\n");
203 address
= strtoul(argv
[1], NULL
, 16);
207 if (IS_KERNEL_ADDRESS(address
)) {
208 error
= elf_debug_lookup_symbol_address(address
, &baseAddress
, &symbol
,
209 &imageName
, &exactMatch
);
211 error
= elf_debug_lookup_user_symbol_address(
212 debug_get_debugged_thread()->team
, address
, &baseAddress
, &symbol
,
213 &imageName
, &exactMatch
);
217 kprintf("%p = %s + 0x%lx (%s)%s\n", (void*)address
, symbol
,
218 address
- baseAddress
, imageName
, exactMatch
? "" : " (nearest)");
220 kprintf("There is no image loaded at this address!\n");
226 static struct elf_image_info
*
227 find_image(image_id id
)
229 return sImagesHash
->Lookup(id
);
233 static struct elf_image_info
*
234 find_image_by_vnode(void *vnode
)
236 MutexLocker
locker(sImageMutex
);
238 ImageHash::Iterator
iterator(sImagesHash
);
239 while (iterator
.HasNext()) {
240 struct elf_image_info
* image
= iterator
.Next();
241 if (image
->vnode
== vnode
)
249 static struct elf_image_info
*
250 create_image_struct()
252 struct elf_image_info
*image
253 = (struct elf_image_info
*)malloc(sizeof(struct elf_image_info
));
257 memset(image
, 0, sizeof(struct elf_image_info
));
259 image
->text_region
.id
= -1;
260 image
->data_region
.id
= -1;
261 image
->ref_count
= 1;
268 delete_elf_image(struct elf_image_info
*image
)
270 if (image
->text_region
.id
>= 0)
271 delete_area(image
->text_region
.id
);
273 if (image
->data_region
.id
>= 0)
274 delete_area(image
->data_region
.id
);
277 vfs_put_vnode(image
->vnode
);
279 free(image
->versions
);
280 free(image
->debug_symbols
);
281 free((void*)image
->debug_string_table
);
282 free(image
->elf_header
);
289 elf_hash(const char *name
)
295 hash
= (hash
<< 4) + (uint8
)*name
++;
296 if ((temp
= hash
& 0xf0000000) != 0)
305 get_symbol_type_string(elf_sym
*symbol
)
307 switch (symbol
->Type()) {
321 get_symbol_bind_string(elf_sym
*symbol
)
323 switch (symbol
->Bind()) {
336 /*! Searches a symbol (pattern) in all kernel images */
338 dump_symbol(int argc
, char **argv
)
340 if (argc
!= 2 || !strcmp(argv
[1], "--help")) {
341 kprintf("usage: %s <symbol-name>\n", argv
[0]);
345 struct elf_image_info
*image
= NULL
;
346 const char *pattern
= argv
[1];
348 void* symbolAddress
= NULL
;
350 ImageHash::Iterator
iterator(sImagesHash
);
351 while (iterator
.HasNext()) {
352 image
= iterator
.Next();
353 if (image
->num_debug_symbols
> 0) {
354 // search extended debug symbol table (contains static symbols)
355 for (uint32 i
= 0; i
< image
->num_debug_symbols
; i
++) {
356 elf_sym
*symbol
= &image
->debug_symbols
[i
];
357 const char *name
= image
->debug_string_table
+ symbol
->st_name
;
359 if (symbol
->st_value
> 0 && strstr(name
, pattern
) != 0) {
361 = (void*)(symbol
->st_value
+ image
->text_region
.delta
);
362 kprintf("%p %5lu %s:%s\n", symbolAddress
, symbol
->st_size
,
367 // search standard symbol lookup table
368 for (uint32 i
= 0; i
< HASHTABSIZE(image
); i
++) {
369 for (uint32 j
= HASHBUCKETS(image
)[i
]; j
!= STN_UNDEF
;
370 j
= HASHCHAINS(image
)[j
]) {
371 elf_sym
*symbol
= &image
->syms
[j
];
372 const char *name
= SYMNAME(image
, symbol
);
374 if (symbol
->st_value
> 0 && strstr(name
, pattern
) != 0) {
375 symbolAddress
= (void*)(symbol
->st_value
376 + image
->text_region
.delta
);
377 kprintf("%p %5lu %s:%s\n", symbolAddress
,
378 symbol
->st_size
, image
->name
, name
);
385 if (symbolAddress
!= NULL
)
386 set_debug_variable("_", (addr_t
)symbolAddress
);
393 dump_symbols(int argc
, char **argv
)
395 struct elf_image_info
*image
= NULL
;
398 // if the argument looks like a hex number, treat it as such
400 if (isdigit(argv
[1][0])) {
401 addr_t num
= strtoul(argv
[1], NULL
, 0);
403 if (IS_KERNEL_ADDRESS(num
)) {
404 // find image at address
406 ImageHash::Iterator
iterator(sImagesHash
);
407 while (iterator
.HasNext()) {
408 elf_image_info
* current
= iterator
.Next();
409 if (current
->text_region
.start
<= num
410 && current
->text_region
.start
411 + current
->text_region
.size
>= num
) {
418 kprintf("No image covers %#" B_PRIxADDR
" in the kernel!\n",
422 image
= sImagesHash
->Lookup(num
);
424 kprintf("image %#" B_PRIxADDR
" doesn't exist in the "
429 // look for image by name
430 ImageHash::Iterator
iterator(sImagesHash
);
431 while (iterator
.HasNext()) {
432 elf_image_info
* current
= iterator
.Next();
433 if (!strcmp(current
->name
, argv
[1])) {
440 kprintf("No image \"%s\" found in kernel!\n", argv
[1]);
443 kprintf("usage: %s image_name/image_id/address_in_image\n", argv
[0]);
452 kprintf("Symbols of image %" B_PRId32
" \"%s\":\n", image
->id
, image
->name
);
453 kprintf("%-*s Type Size Name\n", B_PRINTF_POINTER_WIDTH
, "Address");
455 if (image
->num_debug_symbols
> 0) {
456 // search extended debug symbol table (contains static symbols)
457 for (i
= 0; i
< image
->num_debug_symbols
; i
++) {
458 elf_sym
*symbol
= &image
->debug_symbols
[i
];
460 if (symbol
->st_value
== 0 || symbol
->st_size
461 >= image
->text_region
.size
+ image
->data_region
.size
)
464 kprintf("%0*lx %s/%s %5ld %s\n", B_PRINTF_POINTER_WIDTH
,
465 symbol
->st_value
+ image
->text_region
.delta
,
466 get_symbol_type_string(symbol
), get_symbol_bind_string(symbol
),
467 symbol
->st_size
, image
->debug_string_table
+ symbol
->st_name
);
472 // search standard symbol lookup table
473 for (i
= 0; i
< HASHTABSIZE(image
); i
++) {
474 for (j
= HASHBUCKETS(image
)[i
]; j
!= STN_UNDEF
;
475 j
= HASHCHAINS(image
)[j
]) {
476 elf_sym
*symbol
= &image
->syms
[j
];
478 if (symbol
->st_value
== 0 || symbol
->st_size
479 >= image
->text_region
.size
+ image
->data_region
.size
)
482 kprintf("%08lx %s/%s %5ld %s\n",
483 symbol
->st_value
+ image
->text_region
.delta
,
484 get_symbol_type_string(symbol
),
485 get_symbol_bind_string(symbol
),
486 symbol
->st_size
, SYMNAME(image
, symbol
));
496 dump_elf_region(struct elf_region
*region
, const char *name
)
498 kprintf(" %s.id %" B_PRId32
"\n", name
, region
->id
);
499 kprintf(" %s.start %#" B_PRIxADDR
"\n", name
, region
->start
);
500 kprintf(" %s.size %#" B_PRIxSIZE
"\n", name
, region
->size
);
501 kprintf(" %s.delta %ld\n", name
, region
->delta
);
506 dump_image_info(struct elf_image_info
*image
)
508 kprintf("elf_image_info at %p:\n", image
);
509 kprintf(" next %p\n", image
->next
);
510 kprintf(" id %" B_PRId32
"\n", image
->id
);
511 dump_elf_region(&image
->text_region
, "text");
512 dump_elf_region(&image
->data_region
, "data");
513 kprintf(" dynamic_section %#" B_PRIxADDR
"\n", image
->dynamic_section
);
514 kprintf(" needed %p\n", image
->needed
);
515 kprintf(" symhash %p\n", image
->symhash
);
516 kprintf(" syms %p\n", image
->syms
);
517 kprintf(" strtab %p\n", image
->strtab
);
518 kprintf(" rel %p\n", image
->rel
);
519 kprintf(" rel_len %#x\n", image
->rel_len
);
520 kprintf(" rela %p\n", image
->rela
);
521 kprintf(" rela_len %#x\n", image
->rela_len
);
522 kprintf(" pltrel %p\n", image
->pltrel
);
523 kprintf(" pltrel_len %#x\n", image
->pltrel_len
);
525 kprintf(" debug_symbols %p (%" B_PRIu32
")\n",
526 image
->debug_symbols
, image
->num_debug_symbols
);
531 dump_image(int argc
, char **argv
)
533 struct elf_image_info
*image
;
535 // if the argument looks like a hex number, treat it as such
537 addr_t num
= strtoul(argv
[1], NULL
, 0);
539 if (IS_KERNEL_ADDRESS(num
)) {
541 dump_image_info((struct elf_image_info
*)num
);
543 image
= sImagesHash
->Lookup(num
);
545 kprintf("image %#" B_PRIxADDR
" doesn't exist in the kernel!\n",
548 dump_image_info(image
);
553 kprintf("loaded kernel images:\n");
555 ImageHash::Iterator
iterator(sImagesHash
);
557 while (iterator
.HasNext()) {
558 image
= iterator
.Next();
559 kprintf("%p (%" B_PRId32
") %s\n", image
, image
->id
, image
->name
);
569 void dump_symbol(struct elf_image_info
*image
, elf_sym
*sym
)
572 kprintf("symbol at %p, in image %p\n", sym
, image
);
574 kprintf(" name index %d, '%s'\n", sym
->st_name
, SYMNAME(image
, sym
));
575 kprintf(" st_value 0x%x\n", sym
->st_value
);
576 kprintf(" st_size %d\n", sym
->st_size
);
577 kprintf(" st_info 0x%x\n", sym
->st_info
);
578 kprintf(" st_other 0x%x\n", sym
->st_other
);
579 kprintf(" st_shndx %d\n", sym
->st_shndx
);
585 elf_find_symbol(struct elf_image_info
*image
, const char *name
,
586 const elf_version_info
*lookupVersion
, bool lookupDefault
)
588 if (image
->dynamic_section
== 0 || HASHTABSIZE(image
) == 0)
591 elf_sym
* versionedSymbol
= NULL
;
592 uint32 versionedSymbolCount
= 0;
594 uint32 hash
= elf_hash(name
) % HASHTABSIZE(image
);
595 for (uint32 i
= HASHBUCKETS(image
)[hash
]; i
!= STN_UNDEF
;
596 i
= HASHCHAINS(image
)[i
]) {
597 elf_sym
* symbol
= &image
->syms
[i
];
599 // consider only symbols with the right name and binding
600 if (symbol
->st_shndx
== SHN_UNDEF
601 || ((symbol
->Bind() != STB_GLOBAL
) && (symbol
->Bind() != STB_WEAK
))
602 || strcmp(SYMNAME(image
, symbol
), name
) != 0) {
608 // Handle the simple cases -- the image doesn't have version
609 // information -- first.
610 if (image
->symbol_versions
== NULL
) {
611 if (lookupVersion
== NULL
) {
612 // No specific symbol version was requested either, so the
613 // symbol is just fine.
617 // A specific version is requested. Since the only possible
618 // dependency is the kernel itself, the add-on was obviously linked
619 // against a newer kernel.
620 dprintf("Kernel add-on requires version support, but the kernel "
625 // The image has version information. Let's see what we've got.
626 uint32 versionID
= image
->symbol_versions
[i
];
627 uint32 versionIndex
= VER_NDX(versionID
);
628 elf_version_info
& version
= image
->versions
[versionIndex
];
630 // skip local versions
631 if (versionIndex
== VER_NDX_LOCAL
)
634 if (lookupVersion
!= NULL
) {
635 // a specific version is requested
637 // compare the versions
638 if (version
.hash
== lookupVersion
->hash
639 && strcmp(version
.name
, lookupVersion
->name
) == 0) {
644 // The versions don't match. We're still fine with the
645 // base version, if it is public and we're not looking for
646 // the default version.
647 if ((versionID
& VER_NDX_FLAG_HIDDEN
) == 0
648 && versionIndex
== VER_NDX_GLOBAL
650 // TODO: Revise the default version case! That's how
651 // FreeBSD implements it, but glibc doesn't handle it
656 // No specific version requested, but the image has version
657 // information. This can happen in either of these cases:
659 // * The dependent object was linked against an older version
660 // of the now versioned dependency.
661 // * The symbol is looked up via find_image_symbol() or dlsym().
663 // In the first case we return the base version of the symbol
664 // (VER_NDX_GLOBAL or VER_NDX_INITIAL), or, if that doesn't
665 // exist, the unique, non-hidden versioned symbol.
667 // In the second case we want to return the public default
668 // version of the symbol. The handling is pretty similar to the
669 // first case, with the exception that we treat VER_NDX_INITIAL
670 // as regular version.
672 // VER_NDX_GLOBAL is always good, VER_NDX_INITIAL is fine, if
673 // we don't look for the default version.
674 if (versionIndex
== VER_NDX_GLOBAL
675 || (!lookupDefault
&& versionIndex
== VER_NDX_INITIAL
)) {
679 // If not hidden, remember the version -- we'll return it, if
680 // it is the only one.
681 if ((versionID
& VER_NDX_FLAG_HIDDEN
) == 0) {
682 versionedSymbolCount
++;
683 versionedSymbol
= symbol
;
688 return versionedSymbolCount
== 1 ? versionedSymbol
: NULL
;
693 elf_parse_dynamic_section(struct elf_image_info
*image
)
696 ssize_t neededOffset
= -1;
698 TRACE(("top of elf_parse_dynamic_section\n"));
704 d
= (elf_dyn
*)image
->dynamic_section
;
708 for (int32 i
= 0; d
[i
].d_tag
!= DT_NULL
; i
++) {
709 switch (d
[i
].d_tag
) {
711 neededOffset
= d
[i
].d_un
.d_ptr
+ image
->text_region
.delta
;
714 image
->symhash
= (uint32
*)(d
[i
].d_un
.d_ptr
715 + image
->text_region
.delta
);
718 image
->strtab
= (char *)(d
[i
].d_un
.d_ptr
719 + image
->text_region
.delta
);
722 image
->syms
= (elf_sym
*)(d
[i
].d_un
.d_ptr
723 + image
->text_region
.delta
);
726 image
->rel
= (elf_rel
*)(d
[i
].d_un
.d_ptr
727 + image
->text_region
.delta
);
730 image
->rel_len
= d
[i
].d_un
.d_val
;
733 image
->rela
= (elf_rela
*)(d
[i
].d_un
.d_ptr
734 + image
->text_region
.delta
);
737 image
->rela_len
= d
[i
].d_un
.d_val
;
740 image
->pltrel
= (elf_rel
*)(d
[i
].d_un
.d_ptr
741 + image
->text_region
.delta
);
744 image
->pltrel_len
= d
[i
].d_un
.d_val
;
747 image
->pltrel_type
= d
[i
].d_un
.d_val
;
750 image
->symbol_versions
= (elf_versym
*)
751 (d
[i
].d_un
.d_ptr
+ image
->text_region
.delta
);
754 image
->version_definitions
= (elf_verdef
*)
755 (d
[i
].d_un
.d_ptr
+ image
->text_region
.delta
);
758 image
->num_version_definitions
= d
[i
].d_un
.d_val
;
761 image
->needed_versions
= (elf_verneed
*)
762 (d
[i
].d_un
.d_ptr
+ image
->text_region
.delta
);
765 image
->num_needed_versions
= d
[i
].d_un
.d_val
;
768 image
->symbolic
= true;
772 uint32 flags
= d
[i
].d_un
.d_val
;
773 if ((flags
& DF_SYMBOLIC
) != 0)
774 image
->symbolic
= true;
783 // lets make sure we found all the required sections
784 if (!image
->symhash
|| !image
->syms
|| !image
->strtab
)
787 TRACE(("needed_offset = %ld\n", neededOffset
));
789 if (neededOffset
>= 0)
790 image
->needed
= STRING(image
, neededOffset
);
797 assert_defined_image_version(elf_image_info
* dependentImage
,
798 elf_image_info
* image
, const elf_version_info
& neededVersion
, bool weak
)
800 // If the image doesn't have version definitions, we print a warning and
801 // succeed. Weird, but that's how glibc does it. Not unlikely we'll fail
802 // later when resolving versioned symbols.
803 if (image
->version_definitions
== NULL
) {
804 dprintf("%s: No version information available (required by %s)\n",
805 image
->name
, dependentImage
->name
);
809 // iterate through the defined versions to find the given one
810 elf_verdef
* definition
= image
->version_definitions
;
811 for (uint32 i
= 0; i
< image
->num_version_definitions
; i
++) {
812 uint32 versionIndex
= VER_NDX(definition
->vd_ndx
);
813 elf_version_info
& info
= image
->versions
[versionIndex
];
815 if (neededVersion
.hash
== info
.hash
816 && strcmp(neededVersion
.name
, info
.name
) == 0) {
820 definition
= (elf_verdef
*)
821 ((uint8
*)definition
+ definition
->vd_next
);
824 // version not found -- fail, if not weak
826 dprintf("%s: version \"%s\" not found (required by %s)\n", image
->name
,
827 neededVersion
.name
, dependentImage
->name
);
828 return B_MISSING_SYMBOL
;
836 init_image_version_infos(elf_image_info
* image
)
838 // First find out how many version infos we need -- i.e. get the greatest
839 // version index from the defined and needed versions (they use the same
843 if (image
->version_definitions
!= NULL
) {
844 elf_verdef
* definition
= image
->version_definitions
;
845 for (uint32 i
= 0; i
< image
->num_version_definitions
; i
++) {
846 if (definition
->vd_version
!= 1) {
847 dprintf("Unsupported version definition revision: %u\n",
848 definition
->vd_version
);
852 uint32 versionIndex
= VER_NDX(definition
->vd_ndx
);
853 if (versionIndex
> maxIndex
)
854 maxIndex
= versionIndex
;
856 definition
= (elf_verdef
*)
857 ((uint8
*)definition
+ definition
->vd_next
);
861 if (image
->needed_versions
!= NULL
) {
862 elf_verneed
* needed
= image
->needed_versions
;
863 for (uint32 i
= 0; i
< image
->num_needed_versions
; i
++) {
864 if (needed
->vn_version
!= 1) {
865 dprintf("Unsupported version needed revision: %u\n",
871 = (elf_vernaux
*)((uint8
*)needed
+ needed
->vn_aux
);
872 for (uint32 k
= 0; k
< needed
->vn_cnt
; k
++) {
873 uint32 versionIndex
= VER_NDX(vernaux
->vna_other
);
874 if (versionIndex
> maxIndex
)
875 maxIndex
= versionIndex
;
877 vernaux
= (elf_vernaux
*)((uint8
*)vernaux
+ vernaux
->vna_next
);
880 needed
= (elf_verneed
*)((uint8
*)needed
+ needed
->vn_next
);
887 // allocate the version infos
889 = (elf_version_info
*)malloc(sizeof(elf_version_info
) * (maxIndex
+ 1));
890 if (image
->versions
== NULL
) {
891 dprintf("Memory shortage in init_image_version_infos()\n");
894 image
->num_versions
= maxIndex
+ 1;
896 // init the version infos
898 // version definitions
899 if (image
->version_definitions
!= NULL
) {
900 elf_verdef
* definition
= image
->version_definitions
;
901 for (uint32 i
= 0; i
< image
->num_version_definitions
; i
++) {
902 if (definition
->vd_cnt
> 0
903 && (definition
->vd_flags
& VER_FLG_BASE
) == 0) {
905 = (elf_verdaux
*)((uint8
*)definition
+ definition
->vd_aux
);
907 uint32 versionIndex
= VER_NDX(definition
->vd_ndx
);
908 elf_version_info
& info
= image
->versions
[versionIndex
];
909 info
.hash
= definition
->vd_hash
;
910 info
.name
= STRING(image
, verdaux
->vda_name
);
911 info
.file_name
= NULL
;
914 definition
= (elf_verdef
*)
915 ((uint8
*)definition
+ definition
->vd_next
);
920 if (image
->needed_versions
!= NULL
) {
921 elf_verneed
* needed
= image
->needed_versions
;
922 for (uint32 i
= 0; i
< image
->num_needed_versions
; i
++) {
923 const char* fileName
= STRING(image
, needed
->vn_file
);
926 = (elf_vernaux
*)((uint8
*)needed
+ needed
->vn_aux
);
927 for (uint32 k
= 0; k
< needed
->vn_cnt
; k
++) {
928 uint32 versionIndex
= VER_NDX(vernaux
->vna_other
);
929 elf_version_info
& info
= image
->versions
[versionIndex
];
930 info
.hash
= vernaux
->vna_hash
;
931 info
.name
= STRING(image
, vernaux
->vna_name
);
932 info
.file_name
= fileName
;
934 vernaux
= (elf_vernaux
*)((uint8
*)vernaux
+ vernaux
->vna_next
);
937 needed
= (elf_verneed
*)((uint8
*)needed
+ needed
->vn_next
);
946 check_needed_image_versions(elf_image_info
* image
)
948 if (image
->needed_versions
== NULL
)
951 elf_verneed
* needed
= image
->needed_versions
;
952 for (uint32 i
= 0; i
< image
->num_needed_versions
; i
++) {
953 elf_image_info
* dependency
= sKernelImage
;
956 = (elf_vernaux
*)((uint8
*)needed
+ needed
->vn_aux
);
957 for (uint32 k
= 0; k
< needed
->vn_cnt
; k
++) {
958 uint32 versionIndex
= VER_NDX(vernaux
->vna_other
);
959 elf_version_info
& info
= image
->versions
[versionIndex
];
961 status_t error
= assert_defined_image_version(image
, dependency
,
962 info
, (vernaux
->vna_flags
& VER_FLG_WEAK
) != 0);
966 vernaux
= (elf_vernaux
*)((uint8
*)vernaux
+ vernaux
->vna_next
);
969 needed
= (elf_verneed
*)((uint8
*)needed
+ needed
->vn_next
);
976 /*! Resolves the \a symbol by linking against \a sharedImage if necessary.
977 Returns the resolved symbol's address in \a _symbolAddress.
980 elf_resolve_symbol(struct elf_image_info
*image
, elf_sym
*symbol
,
981 struct elf_image_info
*sharedImage
, addr_t
*_symbolAddress
)
983 // Local symbols references are always resolved to the given symbol.
984 if (symbol
->Bind() == STB_LOCAL
) {
985 *_symbolAddress
= symbol
->st_value
+ image
->text_region
.delta
;
989 // Non-local symbols we try to resolve to the kernel image first. Unless
990 // the image is linked symbolically, then vice versa.
991 elf_image_info
* firstImage
= sharedImage
;
992 elf_image_info
* secondImage
= image
;
994 std::swap(firstImage
, secondImage
);
996 const char *symbolName
= SYMNAME(image
, symbol
);
998 // get the version info
999 const elf_version_info
* versionInfo
= NULL
;
1000 if (image
->symbol_versions
!= NULL
) {
1001 uint32 index
= symbol
- image
->syms
;
1002 uint32 versionIndex
= VER_NDX(image
->symbol_versions
[index
]);
1003 if (versionIndex
>= VER_NDX_INITIAL
)
1004 versionInfo
= image
->versions
+ versionIndex
;
1008 elf_image_info
* foundImage
= firstImage
;
1009 elf_sym
* foundSymbol
= elf_find_symbol(firstImage
, symbolName
, versionInfo
,
1011 if (foundSymbol
== NULL
1012 || foundSymbol
->Bind() == STB_WEAK
) {
1013 // Not found or found a weak definition -- try to resolve in the other
1015 elf_sym
* secondSymbol
= elf_find_symbol(secondImage
, symbolName
,
1016 versionInfo
, false);
1017 // If we found a symbol -- take it in case we didn't have a symbol
1018 // before or the new symbol is not weak.
1019 if (secondSymbol
!= NULL
1020 && (foundSymbol
== NULL
1021 || secondSymbol
->Bind() != STB_WEAK
)) {
1022 foundImage
= secondImage
;
1023 foundSymbol
= secondSymbol
;
1027 if (foundSymbol
== NULL
) {
1028 // Weak undefined symbols get a value of 0, if unresolved.
1029 if (symbol
->Bind() == STB_WEAK
) {
1030 *_symbolAddress
= 0;
1034 dprintf("\"%s\": could not resolve symbol '%s'\n", image
->name
,
1036 return B_MISSING_SYMBOL
;
1039 // make sure they're the same type
1040 if (symbol
->Type() != foundSymbol
->Type()) {
1041 dprintf("elf_resolve_symbol: found symbol '%s' in image '%s' "
1042 "(requested by image '%s') but wrong type (%d vs. %d)\n",
1043 symbolName
, foundImage
->name
, image
->name
,
1044 foundSymbol
->Type(), symbol
->Type());
1045 return B_MISSING_SYMBOL
;
1048 *_symbolAddress
= foundSymbol
->st_value
+ foundImage
->text_region
.delta
;
1053 /*! Until we have shared library support, just this links against the kernel */
1055 elf_relocate(struct elf_image_info
* image
, struct elf_image_info
* resolveImage
)
1057 int status
= B_NO_ERROR
;
1059 TRACE(("elf_relocate(%p (\"%s\"))\n", image
, image
->name
));
1061 // deal with the rels first
1063 TRACE(("total %i rel relocs\n", image
->rel_len
/ (int)sizeof(elf_rel
)));
1065 status
= arch_elf_relocate_rel(image
, resolveImage
, image
->rel
,
1071 if (image
->pltrel
) {
1072 if (image
->pltrel_type
== DT_REL
) {
1073 TRACE(("total %i plt-relocs\n",
1074 image
->pltrel_len
/ (int)sizeof(elf_rel
)));
1075 status
= arch_elf_relocate_rel(image
, resolveImage
, image
->pltrel
,
1078 TRACE(("total %i plt-relocs\n",
1079 image
->pltrel_len
/ (int)sizeof(elf_rela
)));
1080 status
= arch_elf_relocate_rela(image
, resolveImage
,
1081 (elf_rela
*)image
->pltrel
, image
->pltrel_len
);
1088 TRACE(("total %i rel relocs\n",
1089 image
->rela_len
/ (int)sizeof(elf_rela
)));
1091 status
= arch_elf_relocate_rela(image
, resolveImage
, image
->rela
,
1102 verify_eheader(elf_ehdr
*elfHeader
)
1104 if (memcmp(elfHeader
->e_ident
, ELF_MAGIC
, 4) != 0)
1105 return B_NOT_AN_EXECUTABLE
;
1107 if (elfHeader
->e_ident
[4] != ELF_CLASS
)
1108 return B_NOT_AN_EXECUTABLE
;
1110 if (elfHeader
->e_phoff
== 0)
1111 return B_NOT_AN_EXECUTABLE
;
1113 if (elfHeader
->e_phentsize
< sizeof(elf_phdr
))
1114 return B_NOT_AN_EXECUTABLE
;
1121 unload_elf_image(struct elf_image_info
*image
)
1123 if (atomic_add(&image
->ref_count
, -1) > 1)
1126 TRACE(("unload image %" B_PRId32
", %s\n", image
->id
, image
->name
));
1128 unregister_elf_image(image
);
1129 delete_elf_image(image
);
1134 load_elf_symbol_table(int fd
, struct elf_image_info
*image
)
1136 elf_ehdr
*elfHeader
= image
->elf_header
;
1137 elf_sym
*symbolTable
= NULL
;
1138 elf_shdr
*stringHeader
= NULL
;
1139 uint32 numSymbols
= 0;
1145 // get section headers
1147 ssize_t size
= elfHeader
->e_shnum
* elfHeader
->e_shentsize
;
1148 elf_shdr
*sectionHeaders
= (elf_shdr
*)malloc(size
);
1149 if (sectionHeaders
== NULL
) {
1150 dprintf("error allocating space for section headers\n");
1154 length
= read_pos(fd
, elfHeader
->e_shoff
, sectionHeaders
, size
);
1155 if (length
< size
) {
1156 TRACE(("error reading in program headers\n"));
1161 // find symbol table in section headers
1163 for (i
= 0; i
< elfHeader
->e_shnum
; i
++) {
1164 if (sectionHeaders
[i
].sh_type
== SHT_SYMTAB
) {
1165 stringHeader
= §ionHeaders
[sectionHeaders
[i
].sh_link
];
1167 if (stringHeader
->sh_type
!= SHT_STRTAB
) {
1168 TRACE(("doesn't link to string table\n"));
1169 status
= B_BAD_DATA
;
1173 // read in symbol table
1174 size
= sectionHeaders
[i
].sh_size
;
1175 symbolTable
= (elf_sym
*)malloc(size
);
1176 if (symbolTable
== NULL
) {
1177 status
= B_NO_MEMORY
;
1182 = read_pos(fd
, sectionHeaders
[i
].sh_offset
, symbolTable
, size
);
1183 if (length
< size
) {
1184 TRACE(("error reading in symbol table\n"));
1189 numSymbols
= size
/ sizeof(elf_sym
);
1194 if (symbolTable
== NULL
) {
1195 TRACE(("no symbol table\n"));
1196 status
= B_BAD_VALUE
;
1200 // read in string table
1202 stringTable
= (char *)malloc(size
= stringHeader
->sh_size
);
1203 if (stringTable
== NULL
) {
1204 status
= B_NO_MEMORY
;
1208 length
= read_pos(fd
, stringHeader
->sh_offset
, stringTable
, size
);
1209 if (length
< size
) {
1210 TRACE(("error reading in string table\n"));
1215 TRACE(("loaded %" B_PRId32
" debug symbols\n", numSymbols
));
1217 // insert tables into image
1218 image
->debug_symbols
= symbolTable
;
1219 image
->num_debug_symbols
= numSymbols
;
1220 image
->debug_string_table
= stringTable
;
1222 free(sectionHeaders
);
1230 free(sectionHeaders
);
1237 insert_preloaded_image(preloaded_elf_image
*preloadedImage
, bool kernel
)
1241 status
= verify_eheader(&preloadedImage
->elf_header
);
1245 elf_image_info
*image
= create_image_struct();
1249 image
->name
= strdup(preloadedImage
->name
);
1250 image
->dynamic_section
= preloadedImage
->dynamic_section
.start
;
1252 image
->text_region
.id
= preloadedImage
->text_region
.id
;
1253 image
->text_region
.start
= preloadedImage
->text_region
.start
;
1254 image
->text_region
.size
= preloadedImage
->text_region
.size
;
1255 image
->text_region
.delta
= preloadedImage
->text_region
.delta
;
1256 image
->data_region
.id
= preloadedImage
->data_region
.id
;
1257 image
->data_region
.start
= preloadedImage
->data_region
.start
;
1258 image
->data_region
.size
= preloadedImage
->data_region
.size
;
1259 image
->data_region
.delta
= preloadedImage
->data_region
.delta
;
1261 status
= elf_parse_dynamic_section(image
);
1265 status
= init_image_version_infos(image
);
1270 status
= check_needed_image_versions(image
);
1274 status
= elf_relocate(image
, sKernelImage
);
1278 sKernelImage
= image
;
1280 // copy debug symbols to the kernel heap
1281 if (preloadedImage
->debug_symbols
!= NULL
) {
1282 int32 debugSymbolsSize
= sizeof(elf_sym
)
1283 * preloadedImage
->num_debug_symbols
;
1284 image
->debug_symbols
= (elf_sym
*)malloc(debugSymbolsSize
);
1285 if (image
->debug_symbols
!= NULL
) {
1286 memcpy(image
->debug_symbols
, preloadedImage
->debug_symbols
,
1290 image
->num_debug_symbols
= preloadedImage
->num_debug_symbols
;
1292 // copy debug string table to the kernel heap
1293 if (preloadedImage
->debug_string_table
!= NULL
) {
1294 image
->debug_string_table
= (char*)malloc(
1295 preloadedImage
->debug_string_table_size
);
1296 if (image
->debug_string_table
!= NULL
) {
1297 memcpy((void*)image
->debug_string_table
,
1298 preloadedImage
->debug_string_table
,
1299 preloadedImage
->debug_string_table_size
);
1303 register_elf_image(image
);
1304 preloadedImage
->id
= image
->id
;
1305 // modules_init() uses this information to get the preloaded images
1307 // we now no longer need to write to the text area anymore
1308 set_area_protection(image
->text_region
.id
,
1309 B_KERNEL_READ_AREA
| B_KERNEL_EXECUTE_AREA
);
1314 delete_elf_image(image
);
1316 preloadedImage
->id
= -1;
1322 // #pragma mark - userland symbol lookup
1325 class UserSymbolLookup
{
1327 static UserSymbolLookup
& Default()
1332 status_t
Init(Team
* team
)
1334 // find the runtime loader debug area
1336 for (VMAddressSpace::AreaIterator it
1337 = team
->address_space
->GetAreaIterator();
1338 (area
= it
.Next()) != NULL
;) {
1339 if (strcmp(area
->name
, RUNTIME_LOADER_DEBUG_AREA_NAME
) == 0)
1346 // copy the runtime loader data structure
1347 if (!_Read((runtime_loader_debug_area
*)area
->Base(), fDebugArea
))
1348 return B_BAD_ADDRESS
;
1354 status_t
LookupSymbolAddress(addr_t address
, addr_t
*_baseAddress
,
1355 const char **_symbolName
, const char **_imageName
, bool *_exactMatch
)
1357 // Note, that this function doesn't find all symbols that we would like
1358 // to find. E.g. static functions do not appear in the symbol table
1359 // as function symbols, but as sections without name and size. The
1360 // .symtab section together with the .strtab section, which apparently
1361 // differ from the tables referred to by the .dynamic section, also
1362 // contain proper names and sizes for those symbols. Therefore, to get
1363 // completely satisfying results, we would need to read those tables
1364 // from the shared object.
1366 // get the image for the address
1368 status_t error
= _FindImageAtAddress(address
, image
);
1369 if (error
!= B_OK
) {
1370 // commpage requires special treatment since kernel stores symbol
1372 addr_t commPageAddress
= (addr_t
)fTeam
->commpage_address
;
1373 if (address
>= commPageAddress
1374 && address
< commPageAddress
+ COMMPAGE_SIZE
) {
1376 *_imageName
= "commpage";
1377 address
-= (addr_t
)commPageAddress
;
1378 error
= elf_debug_lookup_symbol_address(address
, _baseAddress
,
1379 _symbolName
, NULL
, _exactMatch
);
1381 *_baseAddress
+= (addr_t
)fTeam
->commpage_address
;
1386 strlcpy(fImageName
, image
.name
, sizeof(fImageName
));
1388 // symbol hash table size
1390 if (!_Read(image
.symhash
, hashTabSize
))
1391 return B_BAD_ADDRESS
;
1393 // remote pointers to hash buckets and chains
1394 const uint32
* hashBuckets
= image
.symhash
+ 2;
1395 const uint32
* hashChains
= image
.symhash
+ 2 + hashTabSize
;
1397 const elf_region_t
& textRegion
= image
.regions
[0];
1399 // search the image for the symbol
1400 elf_sym symbolFound
;
1401 addr_t deltaFound
= INT_MAX
;
1402 bool exactMatch
= false;
1404 // to get rid of the erroneous "uninitialized" warnings
1405 symbolFound
.st_name
= 0;
1406 symbolFound
.st_value
= 0;
1408 for (uint32 i
= 0; i
< hashTabSize
; i
++) {
1410 if (!_Read(&hashBuckets
[i
], bucket
))
1411 return B_BAD_ADDRESS
;
1413 for (uint32 j
= bucket
; j
!= STN_UNDEF
;
1414 _Read(&hashChains
[j
], j
) ? 0 : j
= STN_UNDEF
) {
1417 if (!_Read(image
.syms
+ j
, symbol
))
1420 // The symbol table contains not only symbols referring to
1421 // functions and data symbols within the shared object, but also
1422 // referenced symbols of other shared objects, as well as
1423 // section and file references. We ignore everything but
1424 // function and data symbols that have an st_value != 0 (0
1425 // seems to be an indication for a symbol defined elsewhere
1426 // -- couldn't verify that in the specs though).
1427 if ((symbol
.Type() != STT_FUNC
&& symbol
.Type() != STT_OBJECT
)
1428 || symbol
.st_value
== 0
1429 || symbol
.st_value
+ symbol
.st_size
+ textRegion
.delta
1430 > textRegion
.vmstart
+ textRegion
.size
) {
1434 // skip symbols starting after the given address
1435 addr_t symbolAddress
= symbol
.st_value
+ textRegion
.delta
;
1436 if (symbolAddress
> address
)
1438 addr_t symbolDelta
= address
- symbolAddress
;
1440 if (symbolDelta
< deltaFound
) {
1441 deltaFound
= symbolDelta
;
1442 symbolFound
= symbol
;
1444 if (symbolDelta
>= 0 && symbolDelta
< symbol
.st_size
) {
1454 *_imageName
= fImageName
;
1457 *_symbolName
= NULL
;
1459 if (deltaFound
< INT_MAX
) {
1460 if (_ReadString(image
, symbolFound
.st_name
, fSymbolName
,
1461 sizeof(fSymbolName
))) {
1462 *_symbolName
= fSymbolName
;
1464 // we can't get its name, so forget the symbol
1465 deltaFound
= INT_MAX
;
1471 if (deltaFound
< INT_MAX
)
1472 *_baseAddress
= symbolFound
.st_value
+ textRegion
.delta
;
1474 *_baseAddress
= textRegion
.vmstart
;
1478 *_exactMatch
= exactMatch
;
1483 status_t
_FindImageAtAddress(addr_t address
, image_t
& image
)
1485 image_queue_t imageQueue
;
1486 if (!_Read(fDebugArea
.loaded_images
, imageQueue
))
1487 return B_BAD_ADDRESS
;
1489 image_t
* imageAddress
= imageQueue
.head
;
1490 while (imageAddress
!= NULL
) {
1491 if (!_Read(imageAddress
, image
))
1492 return B_BAD_ADDRESS
;
1494 if (image
.regions
[0].vmstart
<= address
1495 && address
< image
.regions
[0].vmstart
+ image
.regions
[0].size
) {
1499 imageAddress
= image
.next
;
1502 return B_ENTRY_NOT_FOUND
;
1505 bool _ReadString(const image_t
& image
, uint32 offset
, char* buffer
,
1508 const char* address
= image
.strtab
+ offset
;
1510 if (!IS_USER_ADDRESS(address
))
1513 if (debug_debugger_running()) {
1514 return debug_strlcpy(B_CURRENT_TEAM
, buffer
, address
, bufferSize
)
1517 return user_strlcpy(buffer
, address
, bufferSize
) >= 0;
1520 template<typename T
> bool _Read(const T
* address
, T
& data
);
1521 // gcc 2.95.3 doesn't like it defined in-place
1525 runtime_loader_debug_area fDebugArea
;
1526 char fImageName
[B_OS_NAME_LENGTH
];
1527 char fSymbolName
[256];
1528 static UserSymbolLookup sLookup
;
1532 template<typename T
>
1534 UserSymbolLookup::_Read(const T
* address
, T
& data
)
1536 if (!IS_USER_ADDRESS(address
))
1539 if (debug_debugger_running())
1540 return debug_memcpy(B_CURRENT_TEAM
, &data
, address
, sizeof(T
)) == B_OK
;
1541 return user_memcpy(&data
, address
, sizeof(T
)) == B_OK
;
1545 UserSymbolLookup
UserSymbolLookup::sLookup
;
1546 // doesn't need construction, but has an Init() method
1549 // #pragma mark - public kernel API
1553 get_image_symbol(image_id id
, const char *name
, int32 symbolClass
,
1556 struct elf_image_info
*image
;
1558 status_t status
= B_OK
;
1560 TRACE(("get_image_symbol(%s)\n", name
));
1562 mutex_lock(&sImageMutex
);
1564 image
= find_image(id
);
1565 if (image
== NULL
) {
1566 status
= B_BAD_IMAGE_ID
;
1570 symbol
= elf_find_symbol(image
, name
, NULL
, true);
1571 if (symbol
== NULL
|| symbol
->st_shndx
== SHN_UNDEF
) {
1572 status
= B_ENTRY_NOT_FOUND
;
1576 // TODO: support the "symbolClass" parameter!
1578 TRACE(("found: %lx (%lx + %lx)\n",
1579 symbol
->st_value
+ image
->text_region
.delta
,
1580 symbol
->st_value
, image
->text_region
.delta
));
1582 *_symbol
= (void *)(symbol
->st_value
+ image
->text_region
.delta
);
1585 mutex_unlock(&sImageMutex
);
1590 // #pragma mark - kernel private API
1593 /*! Looks up a symbol by address in all images loaded in kernel space.
1594 Note, if you need to call this function outside a debugger, make
1595 sure you fix locking and the way it returns its information, first!
1598 elf_debug_lookup_symbol_address(addr_t address
, addr_t
*_baseAddress
,
1599 const char **_symbolName
, const char **_imageName
, bool *_exactMatch
)
1601 struct elf_image_info
*image
;
1602 elf_sym
*symbolFound
= NULL
;
1603 const char *symbolName
= NULL
;
1604 addr_t deltaFound
= INT_MAX
;
1605 bool exactMatch
= false;
1608 TRACE(("looking up %p\n", (void *)address
));
1613 //mutex_lock(&sImageMutex);
1615 image
= find_image_at_address(address
);
1616 // get image that may contain the address
1618 if (image
!= NULL
) {
1623 TRACE((" image %p, base = %p, size = %p\n", image
,
1624 (void *)image
->text_region
.start
, (void *)image
->text_region
.size
));
1626 if (image
->debug_symbols
!= NULL
) {
1627 // search extended debug symbol table (contains static symbols)
1629 TRACE((" searching debug symbols...\n"));
1631 for (i
= 0; i
< image
->num_debug_symbols
; i
++) {
1632 elf_sym
*symbol
= &image
->debug_symbols
[i
];
1634 if (symbol
->st_value
== 0 || symbol
->st_size
1635 >= image
->text_region
.size
+ image
->data_region
.size
)
1639 = address
- (symbol
->st_value
+ image
->text_region
.delta
);
1640 if (symbolDelta
>= 0 && symbolDelta
< symbol
->st_size
)
1643 if (exactMatch
|| symbolDelta
< deltaFound
) {
1644 deltaFound
= symbolDelta
;
1645 symbolFound
= symbol
;
1646 symbolName
= image
->debug_string_table
+ symbol
->st_name
;
1653 // search standard symbol lookup table
1655 TRACE((" searching standard symbols...\n"));
1657 for (i
= 0; i
< HASHTABSIZE(image
); i
++) {
1658 for (j
= HASHBUCKETS(image
)[i
]; j
!= STN_UNDEF
;
1659 j
= HASHCHAINS(image
)[j
]) {
1660 elf_sym
*symbol
= &image
->syms
[j
];
1662 if (symbol
->st_value
== 0
1663 || symbol
->st_size
>= image
->text_region
.size
1664 + image
->data_region
.size
)
1667 symbolDelta
= address
- (long)(symbol
->st_value
1668 + image
->text_region
.delta
);
1669 if (symbolDelta
>= 0 && symbolDelta
< symbol
->st_size
)
1672 if (exactMatch
|| symbolDelta
< deltaFound
) {
1673 deltaFound
= symbolDelta
;
1674 symbolFound
= symbol
;
1675 symbolName
= SYMNAME(image
, symbol
);
1686 if (symbolFound
!= NULL
) {
1688 *_symbolName
= symbolName
;
1690 *_imageName
= image
->name
;
1692 *_baseAddress
= symbolFound
->st_value
+ image
->text_region
.delta
;
1694 *_exactMatch
= exactMatch
;
1697 } else if (image
!= NULL
) {
1698 TRACE(("symbol not found!\n"));
1701 *_symbolName
= NULL
;
1703 *_imageName
= image
->name
;
1705 *_baseAddress
= image
->text_region
.start
;
1707 *_exactMatch
= false;
1711 TRACE(("image not found!\n"));
1712 status
= B_ENTRY_NOT_FOUND
;
1715 // Note, theoretically, all information we return back to our caller
1716 // would have to be locked - but since this function is only called
1717 // from the debugger, it's safe to do it this way
1719 //mutex_unlock(&sImageMutex);
1725 /*! Tries to find a matching user symbol for the given address.
1726 Note that the given team's address space must already be in effect.
1729 elf_debug_lookup_user_symbol_address(Team
* team
, addr_t address
,
1730 addr_t
*_baseAddress
, const char **_symbolName
, const char **_imageName
,
1733 if (team
== NULL
|| team
== team_get_kernel_team())
1736 UserSymbolLookup
& lookup
= UserSymbolLookup::Default();
1737 status_t error
= lookup
.Init(team
);
1741 return lookup
.LookupSymbolAddress(address
, _baseAddress
, _symbolName
,
1742 _imageName
, _exactMatch
);
1746 /*! Looks up a symbol in all kernel images. Note, this function is thought to
1747 be used in the kernel debugger, and therefore doesn't perform any locking.
1750 elf_debug_lookup_symbol(const char* searchName
)
1752 struct elf_image_info
*image
= NULL
;
1754 ImageHash::Iterator
iterator(sImagesHash
);
1755 while (iterator
.HasNext()) {
1756 image
= iterator
.Next();
1757 if (image
->num_debug_symbols
> 0) {
1758 // search extended debug symbol table (contains static symbols)
1759 for (uint32 i
= 0; i
< image
->num_debug_symbols
; i
++) {
1760 elf_sym
*symbol
= &image
->debug_symbols
[i
];
1761 const char *name
= image
->debug_string_table
+ symbol
->st_name
;
1763 if (symbol
->st_value
> 0 && !strcmp(name
, searchName
))
1764 return symbol
->st_value
+ image
->text_region
.delta
;
1767 // search standard symbol lookup table
1768 for (uint32 i
= 0; i
< HASHTABSIZE(image
); i
++) {
1769 for (uint32 j
= HASHBUCKETS(image
)[i
]; j
!= STN_UNDEF
;
1770 j
= HASHCHAINS(image
)[j
]) {
1771 elf_sym
*symbol
= &image
->syms
[j
];
1772 const char *name
= SYMNAME(image
, symbol
);
1774 if (symbol
->st_value
> 0 && !strcmp(name
, searchName
))
1775 return symbol
->st_value
+ image
->text_region
.delta
;
1786 elf_lookup_kernel_symbol(const char* name
, elf_symbol_info
* info
)
1789 elf_sym
* foundSymbol
= elf_find_symbol(sKernelImage
, name
, NULL
, false);
1790 if (foundSymbol
== NULL
)
1791 return B_MISSING_SYMBOL
;
1793 info
->address
= foundSymbol
->st_value
+ sKernelImage
->text_region
.delta
;
1794 info
->size
= foundSymbol
->st_size
;
1800 elf_load_user_image(const char *path
, Team
*team
, int flags
, addr_t
*entry
)
1803 elf_phdr
*programHeaders
= NULL
;
1804 char baseName
[B_OS_NAME_LENGTH
];
1810 uint32 addressSpec
= B_RANDOMIZED_BASE_ADDRESS
;
1811 area_id
* mappedAreas
= NULL
;
1813 TRACE(("elf_load: entry path '%s', team %p\n", path
, team
));
1815 fd
= _kern_open(-1, path
, O_RDONLY
, 0);
1820 status
= _kern_read_stat(fd
, NULL
, false, &st
, sizeof(st
));
1824 // read and verify the ELF header
1826 length
= _kern_read(fd
, 0, &elfHeader
, sizeof(elfHeader
));
1827 if (length
< B_OK
) {
1832 if (length
!= sizeof(elfHeader
)) {
1834 status
= B_NOT_AN_EXECUTABLE
;
1837 status
= verify_eheader(&elfHeader
);
1841 struct elf_image_info
* image
;
1842 image
= create_image_struct();
1843 if (image
== NULL
) {
1844 status
= B_NO_MEMORY
;
1847 image
->elf_header
= &elfHeader
;
1849 // read program header
1851 programHeaders
= (elf_phdr
*)malloc(
1852 elfHeader
.e_phnum
* elfHeader
.e_phentsize
);
1853 if (programHeaders
== NULL
) {
1854 dprintf("error allocating space for program headers\n");
1855 status
= B_NO_MEMORY
;
1859 TRACE(("reading in program headers at 0x%lx, length 0x%x\n",
1860 elfHeader
.e_phoff
, elfHeader
.e_phnum
* elfHeader
.e_phentsize
));
1861 length
= _kern_read(fd
, elfHeader
.e_phoff
, programHeaders
,
1862 elfHeader
.e_phnum
* elfHeader
.e_phentsize
);
1863 if (length
< B_OK
) {
1865 dprintf("error reading in program headers\n");
1868 if (length
!= elfHeader
.e_phnum
* elfHeader
.e_phentsize
) {
1869 dprintf("short read while reading in program headers\n");
1874 // construct a nice name for the region we have to create below
1878 const char *leaf
= strrchr(path
, '/');
1884 length
= strlen(leaf
);
1885 if (length
> B_OS_NAME_LENGTH
- 8)
1886 sprintf(baseName
, "...%s", leaf
+ length
+ 8 - B_OS_NAME_LENGTH
);
1888 strcpy(baseName
, leaf
);
1891 // map the program's segments into memory, initially with rw access
1892 // correct area protection will be set after relocation
1894 mappedAreas
= (area_id
*)malloc(sizeof(area_id
) * elfHeader
.e_phnum
);
1895 if (mappedAreas
== NULL
) {
1896 status
= B_NO_MEMORY
;
1900 image_info imageInfo
;
1901 memset(&imageInfo
, 0, sizeof(image_info
));
1903 for (i
= 0; i
< elfHeader
.e_phnum
; i
++) {
1904 char regionName
[B_OS_NAME_LENGTH
];
1905 char *regionAddress
;
1906 char *originalRegionAddress
;
1909 mappedAreas
[i
] = -1;
1911 if (programHeaders
[i
].p_type
== PT_DYNAMIC
) {
1912 image
->dynamic_section
= programHeaders
[i
].p_vaddr
;
1916 if (programHeaders
[i
].p_type
!= PT_LOAD
)
1919 regionAddress
= (char *)(ROUNDDOWN(programHeaders
[i
].p_vaddr
,
1920 B_PAGE_SIZE
) + delta
);
1921 originalRegionAddress
= regionAddress
;
1923 if (programHeaders
[i
].p_flags
& PF_WRITE
) {
1925 size_t memUpperBound
= (programHeaders
[i
].p_vaddr
% B_PAGE_SIZE
)
1926 + programHeaders
[i
].p_memsz
;
1927 size_t fileUpperBound
= (programHeaders
[i
].p_vaddr
% B_PAGE_SIZE
)
1928 + programHeaders
[i
].p_filesz
;
1930 memUpperBound
= ROUNDUP(memUpperBound
, B_PAGE_SIZE
);
1931 fileUpperBound
= ROUNDUP(fileUpperBound
, B_PAGE_SIZE
);
1933 sprintf(regionName
, "%s_seg%drw", baseName
, i
);
1935 id
= vm_map_file(team
->id
, regionName
, (void **)®ionAddress
,
1936 addressSpec
, fileUpperBound
,
1937 B_READ_AREA
| B_WRITE_AREA
, REGION_PRIVATE_MAP
, false,
1938 fd
, ROUNDDOWN(programHeaders
[i
].p_offset
, B_PAGE_SIZE
));
1940 dprintf("error mapping file data: %s!\n", strerror(id
));
1941 status
= B_NOT_AN_EXECUTABLE
;
1944 mappedAreas
[i
] = id
;
1946 imageInfo
.data
= regionAddress
;
1947 imageInfo
.data_size
= memUpperBound
;
1949 image
->data_region
.start
= (addr_t
)regionAddress
;
1950 image
->data_region
.size
= memUpperBound
;
1952 // clean garbage brought by mmap (the region behind the file,
1953 // at least parts of it are the bss and have to be zeroed)
1954 addr_t start
= (addr_t
)regionAddress
1955 + (programHeaders
[i
].p_vaddr
% B_PAGE_SIZE
)
1956 + programHeaders
[i
].p_filesz
;
1957 size_t amount
= fileUpperBound
1958 - (programHeaders
[i
].p_vaddr
% B_PAGE_SIZE
)
1959 - (programHeaders
[i
].p_filesz
);
1960 memset((void *)start
, 0, amount
);
1962 // Check if we need extra storage for the bss - we have to do this if
1963 // the above region doesn't already comprise the memory size, too.
1965 if (memUpperBound
!= fileUpperBound
) {
1966 size_t bssSize
= memUpperBound
- fileUpperBound
;
1968 snprintf(regionName
, B_OS_NAME_LENGTH
, "%s_bss%d", baseName
, i
);
1970 regionAddress
+= fileUpperBound
;
1971 virtual_address_restrictions virtualRestrictions
= {};
1972 virtualRestrictions
.address
= regionAddress
;
1973 virtualRestrictions
.address_specification
= B_EXACT_ADDRESS
;
1974 physical_address_restrictions physicalRestrictions
= {};
1975 id
= create_area_etc(team
->id
, regionName
, bssSize
, B_NO_LOCK
,
1976 B_READ_AREA
| B_WRITE_AREA
, 0, 0, &virtualRestrictions
,
1977 &physicalRestrictions
, (void**)®ionAddress
);
1979 dprintf("error allocating bss area: %s!\n", strerror(id
));
1980 status
= B_NOT_AN_EXECUTABLE
;
1985 // assume ro/text segment
1986 snprintf(regionName
, B_OS_NAME_LENGTH
, "%s_seg%dro", baseName
, i
);
1988 size_t segmentSize
= ROUNDUP(programHeaders
[i
].p_memsz
1989 + (programHeaders
[i
].p_vaddr
% B_PAGE_SIZE
), B_PAGE_SIZE
);
1991 id
= vm_map_file(team
->id
, regionName
, (void **)®ionAddress
,
1992 addressSpec
, segmentSize
,
1993 B_READ_AREA
| B_WRITE_AREA
, REGION_PRIVATE_MAP
, false, fd
,
1994 ROUNDDOWN(programHeaders
[i
].p_offset
, B_PAGE_SIZE
));
1996 dprintf("error mapping file text: %s!\n", strerror(id
));
1997 status
= B_NOT_AN_EXECUTABLE
;
2001 mappedAreas
[i
] = id
;
2003 imageInfo
.text
= regionAddress
;
2004 imageInfo
.text_size
= segmentSize
;
2006 image
->text_region
.start
= (addr_t
)regionAddress
;
2007 image
->text_region
.size
= segmentSize
;
2010 if (addressSpec
!= B_EXACT_ADDRESS
) {
2011 addressSpec
= B_EXACT_ADDRESS
;
2012 delta
= regionAddress
- originalRegionAddress
;
2016 image
->data_region
.delta
= delta
;
2017 image
->text_region
.delta
= delta
;
2019 // modify the dynamic ptr by the delta of the regions
2020 image
->dynamic_section
+= image
->text_region
.delta
;
2022 status
= elf_parse_dynamic_section(image
);
2026 status
= elf_relocate(image
, image
);
2030 // set correct area protection
2031 for (i
= 0; i
< elfHeader
.e_phnum
; i
++) {
2032 if (mappedAreas
[i
] == -1)
2035 uint32 protection
= 0;
2037 if (programHeaders
[i
].p_flags
& PF_EXECUTE
)
2038 protection
|= B_EXECUTE_AREA
;
2039 if (programHeaders
[i
].p_flags
& PF_WRITE
)
2040 protection
|= B_WRITE_AREA
;
2041 if (programHeaders
[i
].p_flags
& PF_READ
)
2042 protection
|= B_READ_AREA
;
2044 status
= vm_set_area_protection(team
->id
, mappedAreas
[i
], protection
,
2050 // register the loaded image
2051 imageInfo
.type
= B_LIBRARY_IMAGE
;
2052 imageInfo
.device
= st
.st_dev
;
2053 imageInfo
.node
= st
.st_ino
;
2054 strlcpy(imageInfo
.name
, path
, sizeof(imageInfo
.name
));
2056 imageInfo
.api_version
= B_HAIKU_VERSION
;
2057 imageInfo
.abi
= B_HAIKU_ABI
;
2058 // TODO: Get the actual values for the shared object. Currently only
2059 // the runtime loader is loaded, so this is good enough for the time
2062 imageInfo
.id
= register_image(team
, &imageInfo
, sizeof(image_info
));
2063 if (imageInfo
.id
>= 0 && team_get_current_team_id() == team
->id
)
2064 user_debug_image_created(&imageInfo
);
2065 // Don't care, if registering fails. It's not crucial.
2067 TRACE(("elf_load: done!\n"));
2069 *entry
= elfHeader
.e_entry
+ delta
;
2075 image
->elf_header
= NULL
;
2076 delete_elf_image(image
);
2079 free(programHeaders
);
2087 load_kernel_add_on(const char *path
)
2089 elf_phdr
*programHeaders
;
2090 elf_ehdr
*elfHeader
;
2091 struct elf_image_info
*image
;
2092 const char *fileName
;
2093 void *reservedAddress
;
2094 size_t reservedSize
;
2097 bool textSectionWritable
= false;
2098 int executableHeaderCount
= 0;
2100 TRACE(("elf_load_kspace: entry path '%s'\n", path
));
2102 int fd
= _kern_open(-1, path
, O_RDONLY
, 0);
2106 struct vnode
*vnode
;
2107 status
= vfs_get_vnode_from_fd(fd
, true, &vnode
);
2111 // get the file name
2112 fileName
= strrchr(path
, '/');
2113 if (fileName
== NULL
)
2118 // Prevent someone else from trying to load this image
2119 mutex_lock(&sImageLoadMutex
);
2121 // make sure it's not loaded already. Search by vnode
2122 image
= find_image_by_vnode(vnode
);
2124 atomic_add(&image
->ref_count
, 1);
2128 elfHeader
= (elf_ehdr
*)malloc(sizeof(*elfHeader
));
2130 status
= B_NO_MEMORY
;
2134 length
= _kern_read(fd
, 0, elfHeader
, sizeof(*elfHeader
));
2135 if (length
< B_OK
) {
2139 if (length
!= sizeof(*elfHeader
)) {
2141 status
= B_NOT_AN_EXECUTABLE
;
2144 status
= verify_eheader(elfHeader
);
2148 image
= create_image_struct();
2150 status
= B_NO_MEMORY
;
2153 image
->vnode
= vnode
;
2154 image
->elf_header
= elfHeader
;
2155 image
->name
= strdup(path
);
2158 programHeaders
= (elf_phdr
*)malloc(elfHeader
->e_phnum
2159 * elfHeader
->e_phentsize
);
2160 if (programHeaders
== NULL
) {
2161 dprintf("%s: error allocating space for program headers\n", fileName
);
2162 status
= B_NO_MEMORY
;
2166 TRACE(("reading in program headers at 0x%lx, length 0x%x\n",
2167 elfHeader
->e_phoff
, elfHeader
->e_phnum
* elfHeader
->e_phentsize
));
2169 length
= _kern_read(fd
, elfHeader
->e_phoff
, programHeaders
,
2170 elfHeader
->e_phnum
* elfHeader
->e_phentsize
);
2171 if (length
< B_OK
) {
2173 TRACE(("%s: error reading in program headers\n", fileName
));
2176 if (length
!= elfHeader
->e_phnum
* elfHeader
->e_phentsize
) {
2177 TRACE(("%s: short read while reading in program headers\n", fileName
));
2182 // determine how much space we need for all loaded segments
2187 for (int32 i
= 0; i
< elfHeader
->e_phnum
; i
++) {
2190 if (programHeaders
[i
].p_type
!= PT_LOAD
)
2193 length
+= ROUNDUP(programHeaders
[i
].p_memsz
2194 + (programHeaders
[i
].p_vaddr
% B_PAGE_SIZE
), B_PAGE_SIZE
);
2196 end
= ROUNDUP(programHeaders
[i
].p_memsz
+ programHeaders
[i
].p_vaddr
,
2198 if (end
> reservedSize
)
2201 if (programHeaders
[i
].IsExecutable())
2202 executableHeaderCount
++;
2205 // Check whether the segments have an unreasonable amount of unused space
2207 if ((ssize_t
)reservedSize
> length
+ 8 * 1024) {
2208 status
= B_BAD_DATA
;
2212 // reserve that space and allocate the areas from that one
2213 if (vm_reserve_address_range(VMAddressSpace::KernelID(), &reservedAddress
,
2214 B_ANY_KERNEL_ADDRESS
, reservedSize
, 0) < B_OK
) {
2215 status
= B_NO_MEMORY
;
2219 image
->data_region
.size
= 0;
2220 image
->text_region
.size
= 0;
2222 for (int32 i
= 0; i
< elfHeader
->e_phnum
; i
++) {
2223 char regionName
[B_OS_NAME_LENGTH
];
2226 TRACE(("looking at program header %" B_PRId32
"\n", i
));
2228 switch (programHeaders
[i
].p_type
) {
2232 image
->dynamic_section
= programHeaders
[i
].p_vaddr
;
2235 dprintf("%s: unhandled pheader type %#" B_PRIx32
"\n", fileName
,
2236 programHeaders
[i
].p_type
);
2240 // we're here, so it must be a PT_LOAD segment
2242 // Usually add-ons have two PT_LOAD headers: one for .data one or .text.
2243 // x86 and PPC may differ in permission bits for .data's PT_LOAD header
2244 // x86 is usually RW, PPC is RWE
2246 // Some add-ons may have .text and .data concatenated in a single
2247 // PT_LOAD RWE header and we must map that to .text.
2248 if (programHeaders
[i
].IsReadWrite()
2249 && (!programHeaders
[i
].IsExecutable()
2250 || executableHeaderCount
> 1)) {
2251 // this is the writable segment
2252 if (image
->data_region
.size
!= 0) {
2253 // we've already created this segment
2256 region
= &image
->data_region
;
2258 snprintf(regionName
, B_OS_NAME_LENGTH
, "%s_data", fileName
);
2259 } else if (programHeaders
[i
].IsExecutable()) {
2260 // this is the non-writable segment
2261 if (image
->text_region
.size
!= 0) {
2262 // we've already created this segment
2265 region
= &image
->text_region
;
2267 // some programs may have .text and .data concatenated in a
2268 // single PT_LOAD section which is readable/writable/executable
2269 textSectionWritable
= programHeaders
[i
].IsReadWrite();
2270 snprintf(regionName
, B_OS_NAME_LENGTH
, "%s_text", fileName
);
2272 dprintf("%s: weird program header flags %#" B_PRIx32
"\n", fileName
,
2273 programHeaders
[i
].p_flags
);
2277 region
->start
= (addr_t
)reservedAddress
+ ROUNDDOWN(
2278 programHeaders
[i
].p_vaddr
, B_PAGE_SIZE
);
2279 region
->size
= ROUNDUP(programHeaders
[i
].p_memsz
2280 + (programHeaders
[i
].p_vaddr
% B_PAGE_SIZE
), B_PAGE_SIZE
);
2281 region
->id
= create_area(regionName
, (void **)®ion
->start
,
2282 B_EXACT_ADDRESS
, region
->size
, B_FULL_LOCK
,
2283 B_KERNEL_READ_AREA
| B_KERNEL_WRITE_AREA
);
2284 if (region
->id
< B_OK
) {
2285 dprintf("%s: error allocating area: %s\n", fileName
,
2286 strerror(region
->id
));
2287 status
= B_NOT_AN_EXECUTABLE
;
2290 region
->delta
= -ROUNDDOWN(programHeaders
[i
].p_vaddr
, B_PAGE_SIZE
);
2292 TRACE(("elf_load_kspace: created area \"%s\" at %p\n",
2293 regionName
, (void *)region
->start
));
2295 length
= _kern_read(fd
, programHeaders
[i
].p_offset
,
2296 (void *)(region
->start
+ (programHeaders
[i
].p_vaddr
% B_PAGE_SIZE
)),
2297 programHeaders
[i
].p_filesz
);
2298 if (length
< B_OK
) {
2300 dprintf("%s: error reading in segment %" B_PRId32
"\n", fileName
,
2306 image
->data_region
.delta
+= image
->data_region
.start
;
2307 image
->text_region
.delta
+= image
->text_region
.start
;
2309 // modify the dynamic ptr by the delta of the regions
2310 image
->dynamic_section
+= image
->text_region
.delta
;
2312 status
= elf_parse_dynamic_section(image
);
2316 status
= init_image_version_infos(image
);
2320 status
= check_needed_image_versions(image
);
2324 status
= elf_relocate(image
, sKernelImage
);
2328 // We needed to read in the contents of the "text" area, but
2329 // now we can protect it read-only/execute, unless this is a
2330 // special image with concatenated .text and .data, when it
2331 // will also need write access.
2332 set_area_protection(image
->text_region
.id
,
2333 B_KERNEL_READ_AREA
| B_KERNEL_EXECUTE_AREA
2334 | (textSectionWritable
? B_KERNEL_WRITE_AREA
: 0));
2336 // There might be a hole between the two segments, and we don't need to
2337 // reserve this any longer
2338 vm_unreserve_address_range(VMAddressSpace::KernelID(), reservedAddress
,
2341 // ToDo: this should be enabled by kernel settings!
2343 load_elf_symbol_table(fd
, image
);
2345 free(programHeaders
);
2346 mutex_lock(&sImageMutex
);
2347 register_elf_image(image
);
2348 mutex_unlock(&sImageMutex
);
2352 mutex_unlock(&sImageLoadMutex
);
2358 vm_unreserve_address_range(VMAddressSpace::KernelID(), reservedAddress
,
2361 free(programHeaders
);
2363 delete_elf_image(image
);
2368 mutex_unlock(&sImageLoadMutex
);
2370 dprintf("Could not load kernel add-on \"%s\": %s\n", path
,
2374 vfs_put_vnode(vnode
);
2382 unload_kernel_add_on(image_id id
)
2384 MutexLocker
_(sImageLoadMutex
);
2385 MutexLocker
_2(sImageMutex
);
2387 elf_image_info
*image
= find_image(id
);
2389 return B_BAD_IMAGE_ID
;
2391 unload_elf_image(image
);
2396 struct elf_image_info
*
2397 elf_get_kernel_image()
2399 return sKernelImage
;
2404 elf_get_image_info_for_address(addr_t address
, image_info
* info
)
2406 MutexLocker
_(sImageMutex
);
2407 struct elf_image_info
* elfInfo
= find_image_at_address(address
);
2408 if (elfInfo
== NULL
)
2409 return B_ENTRY_NOT_FOUND
;
2411 info
->id
= elfInfo
->id
;
2412 info
->type
= B_SYSTEM_IMAGE
;
2414 info
->init_order
= 0;
2415 info
->init_routine
= NULL
;
2416 info
->term_routine
= NULL
;
2419 // TODO: We could actually fill device/node in.
2420 strlcpy(info
->name
, elfInfo
->name
, sizeof(info
->name
));
2421 info
->text
= (void*)elfInfo
->text_region
.start
;
2422 info
->data
= (void*)elfInfo
->data_region
.start
;
2423 info
->text_size
= elfInfo
->text_region
.size
;
2424 info
->data_size
= elfInfo
->data_region
.size
;
2431 elf_create_memory_image(const char* imageName
, addr_t text
, size_t textSize
,
2432 addr_t data
, size_t dataSize
)
2434 // allocate the image
2435 elf_image_info
* image
= create_image_struct();
2438 MemoryDeleter
imageDeleter(image
);
2440 // allocate symbol and string tables -- we allocate an empty symbol table,
2441 // so that elf_debug_lookup_symbol_address() won't try the dynamic symbol
2442 // table, which we don't have.
2443 elf_sym
* symbolTable
= (elf_sym
*)malloc(0);
2444 char* stringTable
= (char*)malloc(1);
2445 MemoryDeleter
symbolTableDeleter(symbolTable
);
2446 MemoryDeleter
stringTableDeleter(stringTable
);
2447 if (symbolTable
== NULL
|| stringTable
== NULL
)
2450 // the string table always contains the empty string
2451 stringTable
[0] = '\0';
2453 image
->debug_symbols
= symbolTable
;
2454 image
->num_debug_symbols
= 0;
2455 image
->debug_string_table
= stringTable
;
2458 image
->name
= strdup(imageName
);
2459 if (image
->name
== NULL
)
2462 // data and text region
2463 image
->text_region
.id
= -1;
2464 image
->text_region
.start
= text
;
2465 image
->text_region
.size
= textSize
;
2466 image
->text_region
.delta
= 0;
2468 image
->data_region
.id
= -1;
2469 image
->data_region
.start
= data
;
2470 image
->data_region
.size
= dataSize
;
2471 image
->data_region
.delta
= 0;
2473 mutex_lock(&sImageMutex
);
2474 register_elf_image(image
);
2475 image_id imageID
= image
->id
;
2476 mutex_unlock(&sImageMutex
);
2478 // keep the allocated memory
2479 imageDeleter
.Detach();
2480 symbolTableDeleter
.Detach();
2481 stringTableDeleter
.Detach();
2488 elf_add_memory_image_symbol(image_id id
, const char* name
, addr_t address
,
2489 size_t size
, int32 type
)
2491 MutexLocker
_(sImageMutex
);
2494 struct elf_image_info
* image
= find_image(id
);
2496 return B_ENTRY_NOT_FOUND
;
2498 // get the current string table size
2499 size_t stringTableSize
= 1;
2500 if (image
->num_debug_symbols
> 0) {
2501 for (int32 i
= image
->num_debug_symbols
- 1; i
>= 0; i
--) {
2502 int32 nameIndex
= image
->debug_symbols
[i
].st_name
;
2503 if (nameIndex
!= 0) {
2504 stringTableSize
= nameIndex
2505 + strlen(image
->debug_string_table
+ nameIndex
) + 1;
2511 // enter the name in the string table
2512 char* stringTable
= (char*)image
->debug_string_table
;
2513 size_t stringIndex
= 0;
2515 size_t nameSize
= strlen(name
) + 1;
2516 stringIndex
= stringTableSize
;
2517 stringTableSize
+= nameSize
;
2518 stringTable
= (char*)realloc((char*)image
->debug_string_table
,
2520 if (stringTable
== NULL
)
2522 image
->debug_string_table
= stringTable
;
2523 memcpy(stringTable
+ stringIndex
, name
, nameSize
);
2526 // resize the symbol table
2527 int32 symbolCount
= image
->num_debug_symbols
+ 1;
2528 elf_sym
* symbolTable
= (elf_sym
*)realloc(
2529 (elf_sym
*)image
->debug_symbols
, sizeof(elf_sym
) * symbolCount
);
2530 if (symbolTable
== NULL
)
2532 image
->debug_symbols
= symbolTable
;
2535 elf_sym
& symbol
= symbolTable
[symbolCount
- 1];
2536 symbol
.SetInfo(STB_GLOBAL
,
2537 type
== B_SYMBOL_TYPE_DATA
? STT_OBJECT
: STT_FUNC
);
2538 symbol
.st_name
= stringIndex
;
2539 symbol
.st_value
= address
;
2540 symbol
.st_size
= size
;
2541 symbol
.st_other
= 0;
2542 symbol
.st_shndx
= 0;
2543 image
->num_debug_symbols
++;
2550 elf_init(kernel_args
*args
)
2552 struct preloaded_image
*image
;
2556 sImagesHash
= new(std::nothrow
) ImageHash();
2557 if (sImagesHash
== NULL
)
2559 status_t init
= sImagesHash
->Init(IMAGE_HASH_SIZE
);
2563 // Build a image structure for the kernel, which has already been loaded.
2564 // The preloaded_images were already prepared by the VM.
2565 image
= args
->kernel_image
;
2566 if (insert_preloaded_image(static_cast<preloaded_elf_image
*>(image
),
2568 panic("could not create kernel image.\n");
2570 // Build image structures for all preloaded images.
2571 for (image
= args
->preloaded_images
; image
!= NULL
; image
= image
->next
)
2572 insert_preloaded_image(static_cast<preloaded_elf_image
*>(image
),
2575 add_debugger_command("ls", &dump_address_info
,
2576 "lookup symbol for a particular address");
2577 add_debugger_command("symbols", &dump_symbols
, "dump symbols for image");
2578 add_debugger_command("symbol", &dump_symbol
, "search symbol in images");
2579 add_debugger_command_etc("image", &dump_image
, "dump image info",
2580 "Prints info about the specified image.\n"
2581 " <image> - pointer to the semaphore structure, or ID\n"
2582 " of the image to print info for.\n", 0);
2584 sInitialized
= true;
2592 /*! Reads the symbol and string table for the kernel image with the given ID.
2593 \a _symbolCount and \a _stringTableSize are both in- and output parameters.
2594 When called they call the size of the buffers given by \a symbolTable and
2595 \a stringTable respectively. When the function returns successfully, they
2596 will contain the actual sizes (which can be greater than the original ones).
2597 The function will copy as much as possible into the buffers. For only
2598 getting the required buffer sizes, it can be invoked with \c NULL buffers.
2599 On success \a _imageDelta will contain the offset to be added to the symbol
2600 values in the table to get the actual symbol addresses.
2603 _user_read_kernel_image_symbols(image_id id
, elf_sym
* symbolTable
,
2604 int32
* _symbolCount
, char* stringTable
, size_t* _stringTableSize
,
2605 addr_t
* _imageDelta
)
2608 if (_symbolCount
== NULL
|| _stringTableSize
== NULL
)
2610 if (!IS_USER_ADDRESS(_symbolCount
) || !IS_USER_ADDRESS(_stringTableSize
)
2611 || (_imageDelta
!= NULL
&& !IS_USER_ADDRESS(_imageDelta
))
2612 || (symbolTable
!= NULL
&& !IS_USER_ADDRESS(symbolTable
))
2613 || (stringTable
!= NULL
&& !IS_USER_ADDRESS(stringTable
))) {
2614 return B_BAD_ADDRESS
;
2618 int32 maxSymbolCount
;
2619 size_t maxStringTableSize
;
2620 if (user_memcpy(&maxSymbolCount
, _symbolCount
, sizeof(maxSymbolCount
))
2622 || user_memcpy(&maxStringTableSize
, _stringTableSize
,
2623 sizeof(maxStringTableSize
)) != B_OK
) {
2624 return B_BAD_ADDRESS
;
2628 MutexLocker
_(sImageMutex
);
2629 struct elf_image_info
* image
= find_image(id
);
2631 return B_ENTRY_NOT_FOUND
;
2633 // get the tables and infos
2634 addr_t imageDelta
= image
->text_region
.delta
;
2635 const elf_sym
* symbols
;
2637 const char* strings
;
2639 if (image
->debug_symbols
!= NULL
) {
2640 symbols
= image
->debug_symbols
;
2641 symbolCount
= image
->num_debug_symbols
;
2642 strings
= image
->debug_string_table
;
2644 symbols
= image
->syms
;
2645 symbolCount
= image
->symhash
[1];
2646 strings
= image
->strtab
;
2649 // The string table size isn't stored in the elf_image_info structure. Find
2650 // out by iterating through all symbols.
2651 size_t stringTableSize
= 0;
2652 for (int32 i
= 0; i
< symbolCount
; i
++) {
2653 size_t index
= symbols
[i
].st_name
;
2654 if (index
> stringTableSize
)
2655 stringTableSize
= index
;
2657 stringTableSize
+= strlen(strings
+ stringTableSize
) + 1;
2658 // add size of the last string
2660 // copy symbol table
2661 int32 symbolsToCopy
= min_c(symbolCount
, maxSymbolCount
);
2662 if (symbolTable
!= NULL
&& symbolsToCopy
> 0) {
2663 if (user_memcpy(symbolTable
, symbols
, sizeof(elf_sym
) * symbolsToCopy
)
2665 return B_BAD_ADDRESS
;
2669 // copy string table
2670 size_t stringsToCopy
= min_c(stringTableSize
, maxStringTableSize
);
2671 if (stringTable
!= NULL
&& stringsToCopy
> 0) {
2672 if (user_memcpy(stringTable
, strings
, stringsToCopy
)
2674 return B_BAD_ADDRESS
;
2679 if (user_memcpy(_symbolCount
, &symbolCount
, sizeof(symbolCount
)) != B_OK
2680 || user_memcpy(_stringTableSize
, &stringTableSize
,
2681 sizeof(stringTableSize
)) != B_OK
2682 || (_imageDelta
!= NULL
&& user_memcpy(_imageDelta
, &imageDelta
,
2683 sizeof(imageDelta
)) != B_OK
)) {
2684 return B_BAD_ADDRESS
;