194830eb2SIngo Weinhold/*
225dc253dSIngo Weinhold * Copyright 2009-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
394830eb2SIngo Weinhold * Distributed under the terms of the MIT License.
494830eb2SIngo Weinhold */
594830eb2SIngo Weinhold#ifndef ELF_SYMBOL_LOOKUP_H
694830eb2SIngo Weinhold#define ELF_SYMBOL_LOOKUP_H
794830eb2SIngo Weinhold
825dc253dSIngo Weinhold
925dc253dSIngo Weinhold#include <stdlib.h>
1025dc253dSIngo Weinhold#include <string.h>
1125dc253dSIngo Weinhold
1294830eb2SIngo Weinhold#include <runtime_loader.h>
1394830eb2SIngo Weinhold
1494830eb2SIngo Weinhold
1594830eb2SIngo Weinhold// values for SymbolLookupInfo::flags
1694830eb2SIngo Weinhold#define LOOKUP_FLAG_DEFAULT_VERSION	0x01
1794830eb2SIngo Weinhold
1894830eb2SIngo Weinhold
1994830eb2SIngo Weinholduint32 elf_hash(const char* name);
2094830eb2SIngo Weinhold
2194830eb2SIngo Weinhold
2294830eb2SIngo Weinholdstruct SymbolLookupInfo {
2394830eb2SIngo Weinhold	const char*				name;
2494830eb2SIngo Weinhold	int32					type;
2594830eb2SIngo Weinhold	uint32					hash;
2694830eb2SIngo Weinhold	uint32					flags;
2794830eb2SIngo Weinhold	const elf_version_info*	version;
28e3ac2588SAlex Smith	elf_sym*				requestingSymbol;
2994830eb2SIngo Weinhold
3094830eb2SIngo Weinhold	SymbolLookupInfo(const char* name, int32 type, uint32 hash,
31ca7aa99fSIngo Weinhold		const elf_version_info* version = NULL, uint32 flags = 0,
32e3ac2588SAlex Smith		elf_sym* requestingSymbol = NULL)
3394830eb2SIngo Weinhold		:
3494830eb2SIngo Weinhold		name(name),
3594830eb2SIngo Weinhold		type(type),
3694830eb2SIngo Weinhold		hash(hash),
3794830eb2SIngo Weinhold		flags(flags),
38ca7aa99fSIngo Weinhold		version(version),
39ca7aa99fSIngo Weinhold		requestingSymbol(requestingSymbol)
4094830eb2SIngo Weinhold	{
4194830eb2SIngo Weinhold	}
4294830eb2SIngo Weinhold
4394830eb2SIngo Weinhold	SymbolLookupInfo(const char* name, int32 type,
44ca7aa99fSIngo Weinhold		const elf_version_info* version = NULL, uint32 flags = 0,
45e3ac2588SAlex Smith		elf_sym* requestingSymbol = NULL)
4694830eb2SIngo Weinhold		:
4794830eb2SIngo Weinhold		name(name),
4894830eb2SIngo Weinhold		type(type),
4994830eb2SIngo Weinhold		hash(elf_hash(name)),
5094830eb2SIngo Weinhold		flags(flags),
51ca7aa99fSIngo Weinhold		version(version),
52ca7aa99fSIngo Weinhold		requestingSymbol(requestingSymbol)
5394830eb2SIngo Weinhold	{
5494830eb2SIngo Weinhold	}
5594830eb2SIngo Weinhold};
5694830eb2SIngo Weinhold
5794830eb2SIngo Weinhold
5825dc253dSIngo Weinholdstruct SymbolLookupCache {
5925dc253dSIngo Weinhold	SymbolLookupCache(image_t* image)
6025dc253dSIngo Weinhold		:
61d5447eb9SSimon South		fTableSize(image->symhash != NULL ? image->symhash[1] : 0),
6225dc253dSIngo Weinhold		fValues(NULL),
63fad7246fSPawel Dziepak		fDSOs(NULL),
6425dc253dSIngo Weinhold		fValuesResolved(NULL)
6525dc253dSIngo Weinhold	{
6625dc253dSIngo Weinhold		if (fTableSize > 0) {
6725dc253dSIngo Weinhold			fValues = (addr_t*)malloc(sizeof(addr_t) * fTableSize);
680e45e3ebSPawel Dziepak			fDSOs = (image_t**)malloc(sizeof(image_t*) * fTableSize);
6925dc253dSIngo Weinhold
7025dc253dSIngo Weinhold			size_t elementCount = (fTableSize + 31) / 32;
7125dc253dSIngo Weinhold			fValuesResolved = (uint32*)malloc(4 * elementCount);
7225dc253dSIngo Weinhold			memset(fValuesResolved, 0, 4 * elementCount);
7325dc253dSIngo Weinhold
74fad7246fSPawel Dziepak			if (fValues == NULL || fDSOs == NULL || fValuesResolved == NULL) {
7525dc253dSIngo Weinhold				free(fValuesResolved);
7625dc253dSIngo Weinhold				free(fValues);
77fad7246fSPawel Dziepak				free(fDSOs);
7825dc253dSIngo Weinhold				fTableSize = 0;
7925dc253dSIngo Weinhold			}
8025dc253dSIngo Weinhold		}
8125dc253dSIngo Weinhold	}
8225dc253dSIngo Weinhold
8325dc253dSIngo Weinhold	~SymbolLookupCache()
8425dc253dSIngo Weinhold	{
8525dc253dSIngo Weinhold		free(fValuesResolved);
8625dc253dSIngo Weinhold		free(fValues);
870e45e3ebSPawel Dziepak		free(fDSOs);
8825dc253dSIngo Weinhold	}
8925dc253dSIngo Weinhold
9025dc253dSIngo Weinhold	bool IsSymbolValueCached(size_t index) const
9125dc253dSIngo Weinhold	{
9225dc253dSIngo Weinhold		return index < fTableSize
9325dc253dSIngo Weinhold			&& (fValuesResolved[index / 32] & (1 << (index % 32))) != 0;
9425dc253dSIngo Weinhold	}
9525dc253dSIngo Weinhold
9625dc253dSIngo Weinhold	addr_t SymbolValueAt(size_t index) const
9725dc253dSIngo Weinhold	{
9825dc253dSIngo Weinhold		return fValues[index];
9925dc253dSIngo Weinhold	}
10025dc253dSIngo Weinhold
1010e45e3ebSPawel Dziepak	addr_t SymbolValueAt(size_t index, image_t** image) const
1020e45e3ebSPawel Dziepak	{
1030e45e3ebSPawel Dziepak		if (image)
1040e45e3ebSPawel Dziepak			*image = fDSOs[index];
1050e45e3ebSPawel Dziepak		return fValues[index];
1060e45e3ebSPawel Dziepak	}
1070e45e3ebSPawel Dziepak
1080e45e3ebSPawel Dziepak	void SetSymbolValueAt(size_t index, addr_t value, image_t* image)
10925dc253dSIngo Weinhold	{
11025dc253dSIngo Weinhold		if (index < fTableSize) {
11125dc253dSIngo Weinhold			fValues[index] = value;
1120e45e3ebSPawel Dziepak			fDSOs[index] = image;
11325dc253dSIngo Weinhold			fValuesResolved[index / 32] |= 1 << (index % 32);
11425dc253dSIngo Weinhold		}
11525dc253dSIngo Weinhold	}
11625dc253dSIngo Weinhold
11725dc253dSIngo Weinholdprivate:
1180e45e3ebSPawel Dziepak	size_t		fTableSize;
1190e45e3ebSPawel Dziepak	addr_t*		fValues;
1200e45e3ebSPawel Dziepak	image_t**	fDSOs;
1210e45e3ebSPawel Dziepak	uint32*		fValuesResolved;
12225dc253dSIngo Weinhold};
12325dc253dSIngo Weinhold
12425dc253dSIngo Weinhold
12594830eb2SIngo Weinholdvoid		patch_defined_symbol(image_t* image, const char* name,
12694830eb2SIngo Weinhold				void** symbol, int32* type);
12794830eb2SIngo Weinholdvoid		patch_undefined_symbol(image_t* rootImage, image_t* image,
12894830eb2SIngo Weinhold				const char* name, image_t** foundInImage, void** symbol,
12994830eb2SIngo Weinhold				int32* type);
13094830eb2SIngo Weinhold
13161987fe7SAdrien Destugueself_sym*	find_symbol(image_t* image, const SymbolLookupInfo& lookupInfo,
13261987fe7SAdrien Destugues				bool allowLocal = false);
13394830eb2SIngo Weinholdstatus_t	find_symbol(image_t* image, const SymbolLookupInfo& lookupInfo,
13494830eb2SIngo Weinhold				void** _location);
13594830eb2SIngo Weinholdstatus_t	find_symbol_breadth_first(image_t* image,
13694830eb2SIngo Weinhold				const SymbolLookupInfo& lookupInfo, image_t** _foundInImage,
13794830eb2SIngo Weinhold				void** _location);
138e3ac2588SAlex Smithelf_sym*	find_undefined_symbol_beos(image_t* rootImage, image_t* image,
13994830eb2SIngo Weinhold				const SymbolLookupInfo& lookupInfo, image_t** foundInImage);
140e3ac2588SAlex Smithelf_sym*	find_undefined_symbol_global(image_t* rootImage, image_t* image,
14194830eb2SIngo Weinhold				const SymbolLookupInfo& lookupInfo, image_t** foundInImage);
142e3ac2588SAlex Smithelf_sym*	find_undefined_symbol_add_on(image_t* rootImage, image_t* image,
14394830eb2SIngo Weinhold				const SymbolLookupInfo& lookupInfo, image_t** foundInImage);
14494830eb2SIngo Weinhold
14594830eb2SIngo Weinhold
14694830eb2SIngo Weinhold#endif	// ELF_SYMBOL_LOOKUP_H
147