* elf_find_symbol(): Skip undefined symbols and symbols with the wrong binding.
* Implemented missing handling of symbolically linked images and of weak symbols. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@39646 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -34,6 +34,8 @@ struct elf_image_info {
|
|||||||
addr_t dynamic_section; // pointer to the dynamic section
|
addr_t dynamic_section; // pointer to the dynamic section
|
||||||
struct elf_linked_image *linked_images;
|
struct elf_linked_image *linked_images;
|
||||||
|
|
||||||
|
bool symbolic;
|
||||||
|
|
||||||
struct Elf32_Ehdr *elf_header;
|
struct Elf32_Ehdr *elf_header;
|
||||||
|
|
||||||
// pointer to symbol participation data structures
|
// pointer to symbol participation data structures
|
||||||
|
|||||||
+47
-17
@@ -19,6 +19,8 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include <AutoDeleter.h>
|
#include <AutoDeleter.h>
|
||||||
#include <boot/kernel_args.h>
|
#include <boot/kernel_args.h>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
@@ -603,8 +605,14 @@ elf_find_symbol(struct elf_image_info *image, const char *name,
|
|||||||
for (uint32 i = HASHBUCKETS(image)[hash]; i != STN_UNDEF;
|
for (uint32 i = HASHBUCKETS(image)[hash]; i != STN_UNDEF;
|
||||||
i = HASHCHAINS(image)[i]) {
|
i = HASHCHAINS(image)[i]) {
|
||||||
Elf32_Sym* symbol = &image->syms[i];
|
Elf32_Sym* symbol = &image->syms[i];
|
||||||
if (strcmp(SYMNAME(image, symbol), name) != 0)
|
|
||||||
|
// consider only symbols with the right name and binding
|
||||||
|
if (symbol->st_shndx == SHN_UNDEF
|
||||||
|
|| ((ELF32_ST_BIND(symbol->st_info) != STB_GLOBAL)
|
||||||
|
&& (ELF32_ST_BIND(symbol->st_info) != STB_WEAK))
|
||||||
|
|| strcmp(SYMNAME(image, symbol), name) != 0) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// check the version
|
// check the version
|
||||||
|
|
||||||
@@ -767,6 +775,16 @@ elf_parse_dynamic_section(struct elf_image_info *image)
|
|||||||
case DT_VERNEEDNUM:
|
case DT_VERNEEDNUM:
|
||||||
image->num_needed_versions = d[i].d_un.d_val;
|
image->num_needed_versions = d[i].d_un.d_val;
|
||||||
break;
|
break;
|
||||||
|
case DT_SYMBOLIC:
|
||||||
|
image->symbolic = true;
|
||||||
|
break;
|
||||||
|
case DT_FLAGS:
|
||||||
|
{
|
||||||
|
uint32 flags = d[i].d_un.d_val;
|
||||||
|
if ((flags & DF_SYMBOLIC) != 0)
|
||||||
|
image->symbolic = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
continue;
|
continue;
|
||||||
@@ -979,7 +997,13 @@ elf_resolve_symbol(struct elf_image_info *image, struct Elf32_Sym *symbol,
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Non-local symbols we try to resolve to the kernel image first.
|
// Non-local symbols we try to resolve to the kernel image first. Unless
|
||||||
|
// the image is linked symbolically, then vice versa.
|
||||||
|
elf_image_info* firstImage = sharedImage;
|
||||||
|
elf_image_info* secondImage = image;
|
||||||
|
if (image->symbolic)
|
||||||
|
std::swap(firstImage, secondImage);
|
||||||
|
|
||||||
const char *symbolName = SYMNAME(image, symbol);
|
const char *symbolName = SYMNAME(image, symbol);
|
||||||
|
|
||||||
// get the version info
|
// get the version info
|
||||||
@@ -992,13 +1016,23 @@ elf_resolve_symbol(struct elf_image_info *image, struct Elf32_Sym *symbol,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// find the symbol
|
// find the symbol
|
||||||
elf_image_info* foundImage = sharedImage;
|
elf_image_info* foundImage = firstImage;
|
||||||
struct Elf32_Sym* foundSymbol = elf_find_symbol(sharedImage, symbolName,
|
struct Elf32_Sym* foundSymbol = elf_find_symbol(firstImage, symbolName,
|
||||||
versionInfo, false);
|
versionInfo, false);
|
||||||
if (foundSymbol == NULL) {
|
if (foundSymbol == NULL
|
||||||
// not found yet, try to resolve in the requesting image
|
|| ELF32_ST_BIND(foundSymbol->st_info) == STB_WEAK) {
|
||||||
foundImage = image;
|
// Not found or found a weak definition -- try to resolve in the other
|
||||||
foundSymbol = elf_find_symbol(image, symbolName, versionInfo, false);
|
// image.
|
||||||
|
Elf32_Sym* secondSymbol = elf_find_symbol(secondImage, symbolName,
|
||||||
|
versionInfo, false);
|
||||||
|
// If we found a symbol -- take it in case we didn't have a symbol
|
||||||
|
// before or the new symbol is not weak.
|
||||||
|
if (secondSymbol != NULL
|
||||||
|
&& (foundSymbol == NULL
|
||||||
|
|| ELF32_ST_BIND(secondSymbol->st_info) != STB_WEAK)) {
|
||||||
|
foundImage = secondImage;
|
||||||
|
foundSymbol = secondSymbol;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (foundSymbol == NULL) {
|
if (foundSymbol == NULL) {
|
||||||
@@ -1015,15 +1049,11 @@ elf_resolve_symbol(struct elf_image_info *image, struct Elf32_Sym *symbol,
|
|||||||
|
|
||||||
// make sure they're the same type
|
// make sure they're the same type
|
||||||
if (ELF32_ST_TYPE(symbol->st_info) != ELF32_ST_TYPE(foundSymbol->st_info)) {
|
if (ELF32_ST_TYPE(symbol->st_info) != ELF32_ST_TYPE(foundSymbol->st_info)) {
|
||||||
dprintf("elf_resolve_symbol: found symbol '%s' in shared image "
|
dprintf("elf_resolve_symbol: found symbol '%s' in image '%s' "
|
||||||
"but wrong type\n", symbolName);
|
"(requested by image '%s') but wrong type (%d vs. %d)\n",
|
||||||
return B_MISSING_SYMBOL;
|
symbolName, foundImage->name, image->name,
|
||||||
}
|
ELF32_ST_TYPE(foundSymbol->st_info),
|
||||||
|
ELF32_ST_TYPE(symbol->st_info));
|
||||||
if (ELF32_ST_BIND(foundSymbol->st_info) != STB_GLOBAL
|
|
||||||
&& ELF32_ST_BIND(foundSymbol->st_info) != STB_WEAK) {
|
|
||||||
TRACE(("elf_resolve_symbol: found symbol '%s' but not exported\n",
|
|
||||||
symbolName));
|
|
||||||
return B_MISSING_SYMBOL;
|
return B_MISSING_SYMBOL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user