From 61987fe7a257b47c4e7be4dc4f941c3105adf38d Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Sat, 29 Oct 2016 10:16:29 +0200 Subject: [PATCH] runtime_loader: allow the ABI version symbol to be local. Some libraries buildsystems (eg. zlib) somehow prevent the symbol from being exported. We should fix that, but binaries with missing symbols are already out there, so we need to handle them in any case. --- src/system/runtime_loader/elf_haiku_version.cpp | 3 +-- src/system/runtime_loader/elf_symbol_lookup.cpp | 15 ++++++++++++--- src/system/runtime_loader/elf_symbol_lookup.h | 3 ++- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/system/runtime_loader/elf_haiku_version.cpp b/src/system/runtime_loader/elf_haiku_version.cpp index 1a7149b898..7e61df133c 100644 --- a/src/system/runtime_loader/elf_haiku_version.cpp +++ b/src/system/runtime_loader/elf_haiku_version.cpp @@ -211,10 +211,9 @@ analyze_image_haiku_version_and_abi(int fd, image_t* image, elf_ehdr& eheader, // Haiku API version elf_sym* symbol = find_symbol(image, SymbolLookupInfo(B_SHARED_OBJECT_HAIKU_VERSION_VARIABLE_NAME, - B_SYMBOL_TYPE_DATA)); + B_SYMBOL_TYPE_DATA, true)); if (symbol != NULL && symbol->st_shndx != SHN_UNDEF && symbol->st_value > 0 - && symbol->Type() == STT_OBJECT && symbol->st_size >= sizeof(uint32)) { image->api_version = *(uint32*)(symbol->st_value + image->regions[0].delta); diff --git a/src/system/runtime_loader/elf_symbol_lookup.cpp b/src/system/runtime_loader/elf_symbol_lookup.cpp index 593336e1ce..d3e68474e6 100644 --- a/src/system/runtime_loader/elf_symbol_lookup.cpp +++ b/src/system/runtime_loader/elf_symbol_lookup.cpp @@ -93,8 +93,18 @@ patch_undefined_symbol(image_t* rootImage, image_t* image, const char* name, } +static bool is_symbol_visible(elf_sym* symbol) +{ + if (symbol->Bind() == STB_GLOBAL) + return true; + if (symbol->Bind() == STB_WEAK) + return true; + return false; +} + + elf_sym* -find_symbol(image_t* image, const SymbolLookupInfo& lookupInfo) +find_symbol(image_t* image, const SymbolLookupInfo& lookupInfo, bool allowLocal) { if (image->dynamic_ptr == 0) return NULL; @@ -109,8 +119,7 @@ find_symbol(image_t* image, const SymbolLookupInfo& lookupInfo) elf_sym* symbol = &image->syms[i]; if (symbol->st_shndx != SHN_UNDEF - && ((symbol->Bind() == STB_GLOBAL) - || (symbol->Bind() == STB_WEAK)) + && (allowLocal || is_symbol_visible(symbol)) && !strcmp(SYMNAME(image, symbol), lookupInfo.name)) { // check if the type matches diff --git a/src/system/runtime_loader/elf_symbol_lookup.h b/src/system/runtime_loader/elf_symbol_lookup.h index 247c945b37..f3f031b40f 100644 --- a/src/system/runtime_loader/elf_symbol_lookup.h +++ b/src/system/runtime_loader/elf_symbol_lookup.h @@ -128,7 +128,8 @@ void patch_undefined_symbol(image_t* rootImage, image_t* image, const char* name, image_t** foundInImage, void** symbol, int32* type); -elf_sym* find_symbol(image_t* image, const SymbolLookupInfo& lookupInfo); +elf_sym* find_symbol(image_t* image, const SymbolLookupInfo& lookupInfo, + bool allowLocal = false); status_t find_symbol(image_t* image, const SymbolLookupInfo& lookupInfo, void** _location); status_t find_symbol_breadth_first(image_t* image,