From ca7aa99f983390f2997f478c86819a4dc69487be Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Wed, 12 Jan 2011 12:43:13 +0000 Subject: [PATCH] * Added SymbolLookupInfo::requestingSymbol which is passed in by resolve_symbol(). * find_undefined_symbol_beos(): Does now check whether SymbolLookupInfo::requestingSymbol is defined, and, if so, returns it directly. This saves the time for the hash table lookup and also works around broken files like SoundPlay. Fixes the runtime loader part of #7094. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@40211 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../runtime_loader/elf_symbol_lookup.cpp | 18 +++++++++++++++--- src/system/runtime_loader/elf_symbol_lookup.h | 13 +++++++++---- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/system/runtime_loader/elf_symbol_lookup.cpp b/src/system/runtime_loader/elf_symbol_lookup.cpp index 9d4788e87d..8716db1d41 100644 --- a/src/system/runtime_loader/elf_symbol_lookup.cpp +++ b/src/system/runtime_loader/elf_symbol_lookup.cpp @@ -109,7 +109,7 @@ find_symbol(image_t* image, const SymbolLookupInfo& lookupInfo) Elf32_Sym* symbol = &image->syms[i]; if (symbol->st_shndx != SHN_UNDEF - && ((ELF32_ST_BIND(symbol->st_info)== STB_GLOBAL) + && ((ELF32_ST_BIND(symbol->st_info) == STB_GLOBAL) || (ELF32_ST_BIND(symbol->st_info) == STB_WEAK)) && !strcmp(SYMNAME(image, symbol), lookupInfo.name)) { @@ -300,13 +300,25 @@ find_undefined_symbol_beos(image_t* rootImage, image_t* image, { // BeOS style symbol resolution: It is sufficient to check the image itself // and its direct dependencies. The linker would have complained, if the - // symbol wasn't there. + // symbol wasn't there. First we check whether the requesting symbol is + // defined already -- then we can simply return it, since, due to symbolic + // linking, that's the one we'd find anyway. + if (Elf32_Sym* symbol = lookupInfo.requestingSymbol) { + if (symbol->st_shndx != SHN_UNDEF + && ((ELF32_ST_BIND(symbol->st_info) == STB_GLOBAL) + || (ELF32_ST_BIND(symbol->st_info) == STB_WEAK))) { + return symbol; + } + } + + // lookup in image Elf32_Sym* symbol = find_symbol(image, lookupInfo); if (symbol != NULL) { *foundInImage = image; return symbol; } + // lookup in dependencies for (uint32 i = 0; i < image->num_needed; i++) { if (image->needed[i]->dynamic_ptr) { symbol = find_symbol(image->needed[i], lookupInfo); @@ -479,7 +491,7 @@ resolve_symbol(image_t* rootImage, image_t* image, struct Elf32_Sym* sym, // search the symbol sharedSym = rootImage->find_undefined_symbol(rootImage, image, - SymbolLookupInfo(symName, type, versionInfo), &sharedImage); + SymbolLookupInfo(symName, type, versionInfo, 0, sym), &sharedImage); } enum { diff --git a/src/system/runtime_loader/elf_symbol_lookup.h b/src/system/runtime_loader/elf_symbol_lookup.h index e9117d4740..3f2791317f 100644 --- a/src/system/runtime_loader/elf_symbol_lookup.h +++ b/src/system/runtime_loader/elf_symbol_lookup.h @@ -25,26 +25,31 @@ struct SymbolLookupInfo { uint32 hash; uint32 flags; const elf_version_info* version; + Elf32_Sym* requestingSymbol; SymbolLookupInfo(const char* name, int32 type, uint32 hash, - const elf_version_info* version = NULL, uint32 flags = 0) + const elf_version_info* version = NULL, uint32 flags = 0, + Elf32_Sym* requestingSymbol = NULL) : name(name), type(type), hash(hash), flags(flags), - version(version) + version(version), + requestingSymbol(requestingSymbol) { } SymbolLookupInfo(const char* name, int32 type, - const elf_version_info* version = NULL, uint32 flags = 0) + const elf_version_info* version = NULL, uint32 flags = 0, + Elf32_Sym* requestingSymbol = NULL) : name(name), type(type), hash(elf_hash(name)), flags(flags), - version(version) + version(version), + requestingSymbol(requestingSymbol) { } };