|
|
//----------------------------------------------------------------------------
//
// Function entry cache.
//
// Copyright (C) Microsoft Corporation, 2000-2001.
//
//----------------------------------------------------------------------------
#ifndef __FECACHE_HPP__
#define __FECACHE_HPP__
typedef IMAGE_ALPHA_RUNTIME_FUNCTION_ENTRY IMAGE_ARM_RUNTIME_FUNCTION_ENTRY; typedef IMAGE_ARM_RUNTIME_FUNCTION_ENTRY *PIMAGE_ARM_RUNTIME_FUNCTION_ENTRY;
union FeCacheData { // 32-bit Alpha entry is only temporary storage;
// cache entries are always converted to 64-bit
// to allow common code.
IMAGE_IA64_RUNTIME_FUNCTION_ENTRY Ia64; _IMAGE_RUNTIME_FUNCTION_ENTRY Amd64; IMAGE_ARM_RUNTIME_FUNCTION_ENTRY Arm; UCHAR Data[1]; };
struct FeCacheEntry { FeCacheData Data; // Generic values translated from the raw data.
ULONG RelBegin; ULONG RelEnd; ULONG64 Address; HANDLE Process; ULONG64 ModuleBase; #if DBG
PSTR Description; #endif
};
#if DBG
#define FE_DEBUG(x) if (tlsvar(DebugFunctionEntries)) dbPrint##x
#define FE_ShowRuntimeFunctionIa64(x) ShowRuntimeFunctionIa64##x
#define FE_SET_DESC(Ent, Desc) ((Ent)->Description = (Desc))
void ShowRuntimeFunctionEntryIa64( FeCacheEntry* FunctionEntry, PSTR Label ); #else
#define FE_DEBUG(x)
#define FE_ShowRuntimeFunctionIa64(x)
#define FE_SET_DESC(Ent, Desc)
#endif // #if DBG
//----------------------------------------------------------------------------
//
// FunctionEntryCache.
//
//----------------------------------------------------------------------------
class FunctionEntryCache { public: FunctionEntryCache(ULONG ImageDataSize, ULONG CacheDataSize, ULONG Machine); ~FunctionEntryCache(void);
BOOL Initialize(ULONG MaxEntries, ULONG ReplaceAt); FeCacheEntry* Find( HANDLE Process, ULONG64 CodeOffset, PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemory, PGET_MODULE_BASE_ROUTINE64 GetModuleBase, PFUNCTION_TABLE_ACCESS_ROUTINE64 GetFunctionEntry ); FeCacheEntry* FindDirect( HANDLE Process, ULONG64 CodeOffset, PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemory, PGET_MODULE_BASE_ROUTINE64 GetModuleBase, PFUNCTION_TABLE_ACCESS_ROUTINE64 GetFunctionEntry ); FeCacheEntry* ReadImage( HANDLE Process, ULONG64 Address, PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemory, PGET_MODULE_BASE_ROUTINE64 GetModuleBase );
void InvalidateProcessOrModule(HANDLE Process, ULONG64 Base); protected: // Total number of entries to store.
ULONG m_MaxEntries; // When the cache is full entries are overwritten starting
// at the replacement point. Cache hits are moved up
// prior to the replacement point so frequently used
// entries stay unmodified in the front of the cache
// and other entries are stored temporarily at the end.
ULONG m_ReplaceAt; // Size of raw function entry data in the image.
ULONG m_ImageDataSize; // Size of raw function entry data in the cache.
// This may be different from the image data size if
// the image data is translated into a different form,
// such as Axp32 keeping cache entries in Axp64 form.
ULONG m_CacheDataSize; // Machine type.
ULONG m_Machine;
FeCacheEntry* m_Entries; // Number of entries currently used.
ULONG m_Used; // Index of next slot to fill.
ULONG m_Next; // Temporary data area for callback-filled data.
FeCacheEntry m_Temporary;
FeCacheEntry* FillTemporary(HANDLE Process, PVOID RawEntry) { // No need to translate as this entry is not part of
// the cache that will be searched.
ZeroMemory(&m_Temporary, sizeof(m_Temporary)); memcpy(&m_Temporary.Data, RawEntry, m_CacheDataSize); m_Temporary.Process = Process; return &m_Temporary; } virtual void TranslateRawData(FeCacheEntry* Entry) = 0; virtual void TranslateRvaDataToRawData(PIMGHLP_RVA_FUNCTION_DATA RvaData, ULONG64 ModuleBase, FeCacheData* Data) = 0; // Base implementation just returns the given entry.
virtual FeCacheEntry* SearchForPrimaryEntry( FeCacheEntry* CacheEntry, HANDLE Process, PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemory, PGET_MODULE_BASE_ROUTINE64 GetModuleBase, PFUNCTION_TABLE_ACCESS_ROUTINE64 GetFunctionEntry ); FeCacheEntry* FindStatic( HANDLE Process, ULONG64 CodeOffset, PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemory, PGET_MODULE_BASE_ROUTINE64 GetModuleBase, PFUNCTION_TABLE_ACCESS_ROUTINE64 GetFunctionEntry, PULONG64 ModuleBase ); FeCacheEntry* Promote(FeCacheEntry* Entry); ULONG64 FunctionTableBase( HANDLE Process, PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemory, ULONG64 Base, PULONG Size ); };
//----------------------------------------------------------------------------
//
// Ia64FunctionEntryCache.
//
//----------------------------------------------------------------------------
class Ia64FunctionEntryCache : public FunctionEntryCache { public: Ia64FunctionEntryCache(void) : FunctionEntryCache(sizeof(IMAGE_IA64_RUNTIME_FUNCTION_ENTRY), sizeof(IMAGE_IA64_RUNTIME_FUNCTION_ENTRY), IMAGE_FILE_MACHINE_IA64) { }
protected: virtual void TranslateRawData(FeCacheEntry* Entry); virtual void TranslateRvaDataToRawData(PIMGHLP_RVA_FUNCTION_DATA RvaData, ULONG64 ModuleBase, FeCacheData* Data); };
//----------------------------------------------------------------------------
//
// Amd64FunctionEntryCache.
//
//----------------------------------------------------------------------------
class Amd64FunctionEntryCache : public FunctionEntryCache { public: Amd64FunctionEntryCache(void) : FunctionEntryCache(sizeof(_IMAGE_RUNTIME_FUNCTION_ENTRY), sizeof(_IMAGE_RUNTIME_FUNCTION_ENTRY), IMAGE_FILE_MACHINE_AMD64) { }
protected: virtual void TranslateRawData(FeCacheEntry* Entry); virtual void TranslateRvaDataToRawData(PIMGHLP_RVA_FUNCTION_DATA RvaData, ULONG64 ModuleBase, FeCacheData* Data); };
//----------------------------------------------------------------------------
//
// AlphaFunctionEntryCache.
//
//----------------------------------------------------------------------------
class AlphaFunctionEntryCache : public FunctionEntryCache { public: AlphaFunctionEntryCache(ULONG ImageDataSize, ULONG CacheDataSize, ULONG Machine) : FunctionEntryCache(ImageDataSize, CacheDataSize, Machine) { }
protected: virtual void TranslateRvaDataToRawData(PIMGHLP_RVA_FUNCTION_DATA RvaData, ULONG64 ModuleBase, FeCacheData* Data); virtual FeCacheEntry* SearchForPrimaryEntry( FeCacheEntry* CacheEntry, HANDLE Process, PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemory, PGET_MODULE_BASE_ROUTINE64 GetModuleBase, PFUNCTION_TABLE_ACCESS_ROUTINE64 GetFunctionEntry ); };
//----------------------------------------------------------------------------
//
// ArmFunctionEntryCache.
//
//----------------------------------------------------------------------------
class ArmFunctionEntryCache : public FunctionEntryCache { public: ArmFunctionEntryCache(void) : FunctionEntryCache(sizeof(IMAGE_ARM_RUNTIME_FUNCTION_ENTRY), sizeof(IMAGE_ARM_RUNTIME_FUNCTION_ENTRY), IMAGE_FILE_MACHINE_ARM) { }
protected: virtual void TranslateRawData(FeCacheEntry* Entry); virtual void TranslateRvaDataToRawData(PIMGHLP_RVA_FUNCTION_DATA RvaData, ULONG64 ModuleBase, FeCacheData* Data); };
//----------------------------------------------------------------------------
//
// Functions.
//
//----------------------------------------------------------------------------
FunctionEntryCache* GetFeCache(ULONG Machine, BOOL Create); void ClearFeCaches(void);
#endif // #ifndef __FECACHE_HPP__
|