Author: bonefish Date: 2010-11-15 22:12:15 +0100 (Mon, 15 Nov 2010) New Revision: 39439 Changeset: http://dev.haiku-os.org/changeset/39439 Modified: haiku/branches/developer/bonefish/weak-symbols/src/system/runtime_loader/arch/m68k/arch_relocate.cpp haiku/branches/developer/bonefish/weak-symbols/src/system/runtime_loader/arch/ppc/arch_relocate.cpp haiku/branches/developer/bonefish/weak-symbols/src/system/runtime_loader/arch/x86/arch_relocate.cpp haiku/branches/developer/bonefish/weak-symbols/src/system/runtime_loader/elf.cpp haiku/branches/developer/bonefish/weak-symbols/src/system/runtime_loader/elf_symbol_lookup.cpp haiku/branches/developer/bonefish/weak-symbols/src/system/runtime_loader/elf_symbol_lookup.h haiku/branches/developer/bonefish/weak-symbols/src/system/runtime_loader/runtime_loader_private.h Log: Implemented a simple caching mechanism for symbol resolutions during the image relocation. The cache consists of an array the same size as the image's symbol table. After looking up a referenced symbol we store its value in the cache so that we don't have to look it up again. Idea blantantly stolen from FreeBSD. Modified: haiku/branches/developer/bonefish/weak-symbols/src/system/runtime_loader/arch/m68k/arch_relocate.cpp =================================================================== --- haiku/branches/developer/bonefish/weak-symbols/src/system/runtime_loader/arch/m68k/arch_relocate.cpp 2010-11-15 19:35:43 UTC (rev 39438) +++ haiku/branches/developer/bonefish/weak-symbols/src/system/runtime_loader/arch/m68k/arch_relocate.cpp 2010-11-15 21:12:15 UTC (rev 39439) @@ -73,7 +73,7 @@ static int relocate_rela(image_t *rootImage, image_t *image, struct Elf32_Rela *rel, - int rel_len) + int rel_len, SymbolLookupCache* cache) { int i; addr_t S; @@ -101,7 +101,7 @@ status_t status; sym = SYMBOL(image, ELF32_R_SYM(rel[i].r_info)); - status = resolve_symbol(rootImage, image, sym, &S); + status = resolve_symbol(rootImage, image, sym, cache, &S); if (status < B_OK) { TRACE(("resolve symbol \"%s\" returned: %ld\n", SYMNAME(image, sym), status)); @@ -195,14 +195,14 @@ break; TRACE(("R_68K_PLT16 overflow\n")); return B_BAD_DATA; - + case R_68K_PLT8: REQUIRE_PLT; if (write_8_check(P, (L + A - P))) break; TRACE(("R_68K_PLT8 overflow\n")); return B_BAD_DATA; - + case R_68K_PLT32O: REQUIRE_PLT; write_32(P, (L + A)); @@ -272,7 +272,8 @@ status_t -arch_relocate_image(image_t *rootImage, image_t *image) +arch_relocate_image(image_t *rootImage, image_t *image, + SymbolLookupCache* cache) { status_t status; @@ -294,7 +295,8 @@ } if (image->rela) { - status = relocate_rela(rootImage, image, image->rela, image->rela_len); + status = relocate_rela(rootImage, image, image->rela, image->rela_len, + cache); //int i; if (status < B_OK) return status; Modified: haiku/branches/developer/bonefish/weak-symbols/src/system/runtime_loader/arch/ppc/arch_relocate.cpp =================================================================== --- haiku/branches/developer/bonefish/weak-symbols/src/system/runtime_loader/arch/ppc/arch_relocate.cpp 2010-11-15 19:35:43 UTC (rev 39438) +++ haiku/branches/developer/bonefish/weak-symbols/src/system/runtime_loader/arch/ppc/arch_relocate.cpp 2010-11-15 21:12:15 UTC (rev 39439) @@ -22,7 +22,7 @@ static int relocate_rel(image_t *rootImage, image_t *image, struct Elf32_Rel *rel, - int rel_len) + int rel_len, SymbolLookupCache* cache) { // ToDo: implement me! @@ -31,20 +31,22 @@ status_t -arch_relocate_image(image_t *rootImage, image_t *image) +arch_relocate_image(image_t *rootImage, image_t *image, + SymbolLookupCache* cache) { status_t status = B_NO_ERROR; // deal with the rels first if (image->rel) { - status = relocate_rel(rootImage, image, image->rel, image->rel_len); + status = relocate_rel(rootImage, image, image->rel, image->rel_len, + cache); if (status < B_OK) return status; } if (image->pltrel) { status = relocate_rel(rootImage, image, image->pltrel, - image->pltrel_len); + image->pltrel_len, cache); if (status < B_OK) return status; } Modified: haiku/branches/developer/bonefish/weak-symbols/src/system/runtime_loader/arch/x86/arch_relocate.cpp =================================================================== --- haiku/branches/developer/bonefish/weak-symbols/src/system/runtime_loader/arch/x86/arch_relocate.cpp 2010-11-15 19:35:43 UTC (rev 39438) +++ haiku/branches/developer/bonefish/weak-symbols/src/system/runtime_loader/arch/x86/arch_relocate.cpp 2010-11-15 21:12:15 UTC (rev 39439) @@ -19,7 +19,7 @@ static int relocate_rel(image_t *rootImage, image_t *image, struct Elf32_Rel *rel, - int rel_len) + int rel_len, SymbolLookupCache* cache) { int i; addr_t S; @@ -43,7 +43,7 @@ status_t status; sym = SYMBOL(image, ELF32_R_SYM(rel[i].r_info)); - status = resolve_symbol(rootImage, image, sym, &S); + status = resolve_symbol(rootImage, image, sym, cache, &S); if (status < B_OK) { TRACE(("resolve symbol \"%s\" returned: %ld\n", SYMNAME(image, sym), status)); @@ -107,20 +107,22 @@ status_t -arch_relocate_image(image_t *rootImage, image_t *image) +arch_relocate_image(image_t* rootImage, image_t* image, + SymbolLookupCache* cache) { status_t status; // deal with the rels first if (image->rel) { - status = relocate_rel(rootImage, image, image->rel, image->rel_len); + status = relocate_rel(rootImage, image, image->rel, image->rel_len, + cache); if (status < B_OK) return status; } if (image->pltrel) { status = relocate_rel(rootImage, image, image->pltrel, - image->pltrel_len); + image->pltrel_len, cache); if (status < B_OK) return status; } Modified: haiku/branches/developer/bonefish/weak-symbols/src/system/runtime_loader/elf.cpp =================================================================== --- haiku/branches/developer/bonefish/weak-symbols/src/system/runtime_loader/elf.cpp 2010-11-15 19:35:43 UTC (rev 39438) +++ haiku/branches/developer/bonefish/weak-symbols/src/system/runtime_loader/elf.cpp 2010-11-15 21:12:15 UTC (rev 39439) @@ -198,7 +198,9 @@ static status_t relocate_image(image_t *rootImage, image_t *image) { - status_t status = arch_relocate_image(rootImage, image); + SymbolLookupCache cache(image); + + status_t status = arch_relocate_image(rootImage, image, &cache); if (status < B_OK) { FATAL("%s: Troubles relocating: %s\n", image->path, strerror(status)); return status; Modified: haiku/branches/developer/bonefish/weak-symbols/src/system/runtime_loader/elf_symbol_lookup.cpp =================================================================== --- haiku/branches/developer/bonefish/weak-symbols/src/system/runtime_loader/elf_symbol_lookup.cpp 2010-11-15 19:35:43 UTC (rev 39438) +++ haiku/branches/developer/bonefish/weak-symbols/src/system/runtime_loader/elf_symbol_lookup.cpp 2010-11-15 21:12:15 UTC (rev 39439) @@ -438,8 +438,16 @@ int resolve_symbol(image_t* rootImage, image_t* image, struct Elf32_Sym* sym, - addr_t* symAddress) + SymbolLookupCache* cache, addr_t* symAddress) { + uint32 index = sym - image->syms; + + // check the cache first + if (cache->IsSymbolValueCached(index)) { + *symAddress = cache->SymbolValueAt(index); + return B_OK; + } + struct Elf32_Sym* sharedSym; image_t* sharedImage; const char* symName = SYMNAME(image, sym); @@ -459,7 +467,6 @@ // get the version info const elf_version_info* versionInfo = NULL; if (image->symbol_versions != NULL) { - uint32 index = sym - image->syms; uint32 versionIndex = VER_NDX(image->symbol_versions[index]); if (versionIndex >= VER_NDX_INITIAL) versionInfo = image->versions + versionIndex; @@ -529,6 +536,8 @@ return B_MISSING_SYMBOL; } + cache->SetSymbolValueAt(index, (addr_t)location); + *symAddress = (addr_t)location; return B_OK; } Modified: haiku/branches/developer/bonefish/weak-symbols/src/system/runtime_loader/elf_symbol_lookup.h =================================================================== --- haiku/branches/developer/bonefish/weak-symbols/src/system/runtime_loader/elf_symbol_lookup.h 2010-11-15 19:35:43 UTC (rev 39438) +++ haiku/branches/developer/bonefish/weak-symbols/src/system/runtime_loader/elf_symbol_lookup.h 2010-11-15 21:12:15 UTC (rev 39439) @@ -1,10 +1,14 @@ /* - * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxxx + * Copyright 2009-2010, Ingo Weinhold, ingo_weinhold@xxxxxxx * Distributed under the terms of the MIT License. */ #ifndef ELF_SYMBOL_LOOKUP_H #define ELF_SYMBOL_LOOKUP_H + +#include <stdlib.h> +#include <string.h> + #include <runtime_loader.h> @@ -46,6 +50,60 @@ }; +struct SymbolLookupCache { + SymbolLookupCache(image_t* image) + : + fTableSize(image->symhash[1]), + fValues(NULL), + fValuesResolved(NULL) + { + if (fTableSize > 0) { + fValues = (addr_t*)malloc(sizeof(addr_t) * fTableSize); + + size_t elementCount = (fTableSize + 31) / 32; + fValuesResolved = (uint32*)malloc(4 * elementCount); + memset(fValuesResolved, 0, 4 * elementCount); + + if (fValues == NULL || fValuesResolved == NULL) { + free(fValuesResolved); + free(fValues); + fTableSize = 0; + } + } + } + + ~SymbolLookupCache() + { + free(fValuesResolved); + free(fValues); + } + + bool IsSymbolValueCached(size_t index) const + { + return index < fTableSize + && (fValuesResolved[index / 32] & (1 << (index % 32))) != 0; + } + + addr_t SymbolValueAt(size_t index) const + { + return fValues[index]; + } + + void SetSymbolValueAt(size_t index, addr_t value) + { + if (index < fTableSize) { + fValues[index] = value; + fValuesResolved[index / 32] |= 1 << (index % 32); + } + } + +private: + size_t fTableSize; + addr_t* fValues; + uint32* fValuesResolved; +}; + + void patch_defined_symbol(image_t* image, const char* name, void** symbol, int32* type); void patch_undefined_symbol(image_t* rootImage, image_t* image, Modified: haiku/branches/developer/bonefish/weak-symbols/src/system/runtime_loader/runtime_loader_private.h =================================================================== --- haiku/branches/developer/bonefish/weak-symbols/src/system/runtime_loader/runtime_loader_private.h 2010-11-15 19:35:43 UTC (rev 39438) +++ haiku/branches/developer/bonefish/weak-symbols/src/system/runtime_loader/runtime_loader_private.h 2010-11-15 21:12:15 UTC (rev 39439) @@ -39,6 +39,9 @@ } while (false) +struct SymbolLookupCache; + + extern struct user_space_program_args* gProgramArgs; extern struct rld_export gRuntimeLoader; extern char* (*gGetEnv)(const char* name); @@ -69,7 +72,7 @@ status_t get_next_image_dependency(image_id id, uint32* cookie, const char** _name); int resolve_symbol(image_t* rootImage, image_t* image, struct Elf32_Sym* sym, - addr_t* sym_addr); + SymbolLookupCache* cache, addr_t* sym_addr); status_t elf_verify_header(void* header, int32 length); @@ -80,7 +83,8 @@ status_t heap_init(void); // arch dependent prototypes -status_t arch_relocate_image(image_t* rootImage, image_t* image); +status_t arch_relocate_image(image_t* rootImage, image_t* image, + SymbolLookupCache* cache); #ifdef __cplusplus }