windows-nt/Source/XPSP1/NT/sdktools/debuggers/imagehlp/fecache.hpp
2020-09-26 16:20:57 +08:00

296 lines
9.3 KiB
C++

//----------------------------------------------------------------------------
//
// Function entry cache.
//
// Copyright (C) Microsoft Corporation, 2000.
//
//----------------------------------------------------------------------------
#ifndef __FECACHE_HPP__
#define __FECACHE_HPP__
union FeCacheData
{
// 32-bit Alpha entry is only temporary storage;
// cache entries are always converted to 64-bit
// to allow common code.
IMAGE_ALPHA_RUNTIME_FUNCTION_ENTRY Axp32;
IMAGE_ALPHA64_RUNTIME_FUNCTION_ENTRY Axp64;
IMAGE_IA64_RUNTIME_FUNCTION_ENTRY Ia64;
_IMAGE_RUNTIME_FUNCTION_ENTRY Amd64;
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_ShowRuntimeFunctionAxp64(x) ShowRuntimeFunctionAxp64##x
#define FE_SET_DESC(Ent, Desc) ((Ent)->Description = (Desc))
void
ShowRuntimeFunctionEntryIa64(
FeCacheEntry* FunctionEntry,
PSTR Label
);
void
ShowRuntimeFunctionAxp64(
FeCacheEntry* FunctionEntry,
PSTR Label
);
#else
#define FE_DEBUG(x)
#define FE_ShowRuntimeFunctionIa64(x)
#define FE_ShowRuntimeFunctionAxp64(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
);
};
//----------------------------------------------------------------------------
//
// Axp32FunctionEntryCache.
//
//----------------------------------------------------------------------------
class Axp32FunctionEntryCache : public AlphaFunctionEntryCache
{
public:
Axp32FunctionEntryCache(void) :
AlphaFunctionEntryCache(sizeof(IMAGE_ALPHA_RUNTIME_FUNCTION_ENTRY),
sizeof(IMAGE_ALPHA64_RUNTIME_FUNCTION_ENTRY),
IMAGE_FILE_MACHINE_ALPHA)
{
}
protected:
virtual void TranslateRawData(FeCacheEntry* Entry);
};
//----------------------------------------------------------------------------
//
// Axp64FunctionEntryCache.
//
//----------------------------------------------------------------------------
class Axp64FunctionEntryCache : public AlphaFunctionEntryCache
{
public:
Axp64FunctionEntryCache(void) :
AlphaFunctionEntryCache(sizeof(IMAGE_ALPHA64_RUNTIME_FUNCTION_ENTRY),
sizeof(IMAGE_ALPHA64_RUNTIME_FUNCTION_ENTRY),
IMAGE_FILE_MACHINE_ALPHA64)
{
}
protected:
virtual void TranslateRawData(FeCacheEntry* Entry);
};
//----------------------------------------------------------------------------
//
// Functions.
//
//----------------------------------------------------------------------------
FunctionEntryCache* GetFeCache(ULONG Machine, BOOL Create);
void ClearFeCaches(void);
#endif // #ifndef __FECACHE_HPP__