* 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:
Ingo Weinhold
2010-11-26 13:32:24 +00:00
parent 003b80f0bb
commit c07db2ec3f
2 changed files with 49 additions and 17 deletions
+2
View File
@@ -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
View File
@@ -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;
} }