haiku/src/system/runtime_loader/elf_symbol_lookup.h
Ingo Weinhold ca7aa99f98 * 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
2011-01-12 12:43:13 +00:00

133 lines
3.1 KiB
C++

/*
* Copyright 2009-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
* 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>
// values for SymbolLookupInfo::flags
#define LOOKUP_FLAG_DEFAULT_VERSION 0x01
uint32 elf_hash(const char* name);
struct SymbolLookupInfo {
const char* name;
int32 type;
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,
Elf32_Sym* requestingSymbol = NULL)
:
name(name),
type(type),
hash(hash),
flags(flags),
version(version),
requestingSymbol(requestingSymbol)
{
}
SymbolLookupInfo(const char* name, int32 type,
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),
requestingSymbol(requestingSymbol)
{
}
};
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,
const char* name, image_t** foundInImage, void** symbol,
int32* type);
Elf32_Sym* find_symbol(image_t* image, const SymbolLookupInfo& lookupInfo);
status_t find_symbol(image_t* image, const SymbolLookupInfo& lookupInfo,
void** _location);
status_t find_symbol_breadth_first(image_t* image,
const SymbolLookupInfo& lookupInfo, image_t** _foundInImage,
void** _location);
Elf32_Sym* find_undefined_symbol_beos(image_t* rootImage, image_t* image,
const SymbolLookupInfo& lookupInfo, image_t** foundInImage);
Elf32_Sym* find_undefined_symbol_global(image_t* rootImage, image_t* image,
const SymbolLookupInfo& lookupInfo, image_t** foundInImage);
Elf32_Sym* find_undefined_symbol_add_on(image_t* rootImage, image_t* image,
const SymbolLookupInfo& lookupInfo, image_t** foundInImage);
#endif // ELF_SYMBOL_LOOKUP_H