1/*
2 * Copyright 2009-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5#ifndef ELF_SYMBOL_LOOKUP_H
6#define ELF_SYMBOL_LOOKUP_H
7
8
9#include <stdlib.h>
10#include <string.h>
11
12#include <runtime_loader.h>
13
14
15// values for SymbolLookupInfo::flags
16#define LOOKUP_FLAG_DEFAULT_VERSION	0x01
17
18
19uint32 elf_hash(const char* name);
20
21
22struct SymbolLookupInfo {
23	const char*				name;
24	int32					type;
25	uint32					hash;
26	uint32					flags;
27	const elf_version_info*	version;
28	elf_sym*				requestingSymbol;
29
30	SymbolLookupInfo(const char* name, int32 type, uint32 hash,
31		const elf_version_info* version = NULL, uint32 flags = 0,
32		elf_sym* requestingSymbol = NULL)
33		:
34		name(name),
35		type(type),
36		hash(hash),
37		flags(flags),
38		version(version),
39		requestingSymbol(requestingSymbol)
40	{
41	}
42
43	SymbolLookupInfo(const char* name, int32 type,
44		const elf_version_info* version = NULL, uint32 flags = 0,
45		elf_sym* requestingSymbol = NULL)
46		:
47		name(name),
48		type(type),
49		hash(elf_hash(name)),
50		flags(flags),
51		version(version),
52		requestingSymbol(requestingSymbol)
53	{
54	}
55};
56
57
58struct SymbolLookupCache {
59	SymbolLookupCache(image_t* image)
60		:
61		fTableSize(image->symhash != NULL ? image->symhash[1] : 0),
62		fValues(NULL),
63		fDSOs(NULL),
64		fValuesResolved(NULL)
65	{
66		if (fTableSize > 0) {
67			fValues = (addr_t*)malloc(sizeof(addr_t) * fTableSize);
68			fDSOs = (image_t**)malloc(sizeof(image_t*) * fTableSize);
69
70			size_t elementCount = (fTableSize + 31) / 32;
71			fValuesResolved = (uint32*)malloc(4 * elementCount);
72
73			if (fValues == NULL || fDSOs == NULL || fValuesResolved == NULL) {
74				free(fValuesResolved);
75				fValuesResolved = NULL;
76				free(fValues);
77				fValues = NULL;
78				free(fDSOs);
79				fDSOs = NULL;
80				fTableSize = 0;
81			} else {
82				memset(fValuesResolved, 0, 4 * elementCount);
83			}
84		}
85	}
86
87	~SymbolLookupCache()
88	{
89		free(fValuesResolved);
90		free(fValues);
91		free(fDSOs);
92	}
93
94	bool IsSymbolValueCached(size_t index) const
95	{
96		return index < fTableSize
97			&& (fValuesResolved[index / 32] & (1 << (index % 32))) != 0;
98	}
99
100	addr_t SymbolValueAt(size_t index) const
101	{
102		return fValues[index];
103	}
104
105	addr_t SymbolValueAt(size_t index, image_t** image) const
106	{
107		if (image)
108			*image = fDSOs[index];
109		return fValues[index];
110	}
111
112	void SetSymbolValueAt(size_t index, addr_t value, image_t* image)
113	{
114		if (index < fTableSize) {
115			fValues[index] = value;
116			fDSOs[index] = image;
117			fValuesResolved[index / 32] |= 1 << (index % 32);
118		}
119	}
120
121private:
122	size_t		fTableSize;
123	addr_t*		fValues;
124	image_t**	fDSOs;
125	uint32*		fValuesResolved;
126};
127
128
129void		patch_defined_symbol(image_t* image, const char* name,
130				void** symbol, int32* type);
131void		patch_undefined_symbol(image_t* rootImage, image_t* image,
132				const char* name, image_t** foundInImage, void** symbol,
133				int32* type);
134
135elf_sym*	find_symbol(image_t* image, const SymbolLookupInfo& lookupInfo,
136				bool allowLocal = false);
137status_t	find_symbol(image_t* image, const SymbolLookupInfo& lookupInfo,
138				void** _location);
139status_t	find_symbol_breadth_first(image_t* image,
140				const SymbolLookupInfo& lookupInfo, image_t** _foundInImage,
141				void** _location);
142elf_sym*	find_undefined_symbol_beos(image_t* rootImage, image_t* image,
143				const SymbolLookupInfo& lookupInfo, image_t** foundInImage);
144elf_sym*	find_undefined_symbol_global(image_t* rootImage, image_t* image,
145				const SymbolLookupInfo& lookupInfo, image_t** foundInImage);
146elf_sym*	find_undefined_symbol_add_on(image_t* rootImage, image_t* image,
147				const SymbolLookupInfo& lookupInfo, image_t** foundInImage);
148
149
150#endif	// ELF_SYMBOL_LOOKUP_H
151