/*
 * 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;
	elf_sym*				requestingSymbol;
 
	SymbolLookupInfo(const char* name, int32 type, uint32 hash,
		const elf_version_info* version = NULL, uint32 flags = 0,
		elf_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,
		elf_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 != NULL ? image->symhash[1] : 0),
		fValues(NULL),
		fDSOs(NULL),
		fValuesResolved(NULL)
	{
		if (fTableSize > 0) {
			fValues = (addr_t*)malloc(sizeof(addr_t) * fTableSize);
			fDSOs = (image_t**)malloc(sizeof(image_t*) * fTableSize);
 
			size_t elementCount = (fTableSize + 31) / 32;
			fValuesResolved = (uint32*)malloc(4 * elementCount);
			memset(fValuesResolved, 0, 4 * elementCount);
 
			if (fValues == NULL || fDSOs == NULL || fValuesResolved == NULL) {
				free(fValuesResolved);
				free(fValues);
				free(fDSOs);
				fTableSize = 0;
			}
		}
	}
 
	~SymbolLookupCache()
	{
		free(fValuesResolved);
		free(fValues);
		free(fDSOs);
	}
 
	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];
	}
 
	addr_t SymbolValueAt(size_t index, image_t** image) const
	{
		if (image)
			*image = fDSOs[index];
		return fValues[index];
	}
 
	void SetSymbolValueAt(size_t index, addr_t value, image_t* image)
	{
		if (index < fTableSize) {
			fValues[index] = value;
			fDSOs[index] = image;
			fValuesResolved[index / 32] |= 1 << (index % 32);
		}
	}
 
private:
	size_t		fTableSize;
	addr_t*		fValues;
	image_t**	fDSOs;
	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);
 
elf_sym*	find_symbol(image_t* image, const SymbolLookupInfo& lookupInfo,
				bool allowLocal = false);
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);
elf_sym*	find_undefined_symbol_beos(image_t* rootImage, image_t* image,
				const SymbolLookupInfo& lookupInfo, image_t** foundInImage);
elf_sym*	find_undefined_symbol_global(image_t* rootImage, image_t* image,
				const SymbolLookupInfo& lookupInfo, image_t** foundInImage);
elf_sym*	find_undefined_symbol_add_on(image_t* rootImage, image_t* image,
				const SymbolLookupInfo& lookupInfo, image_t** foundInImage);
 
 
#endif	// ELF_SYMBOL_LOOKUP_H

V595 The 'fValuesResolved' pointer was utilized before it was verified against nullptr. Check lines: 72, 74.