📄 fastmm4bcb.cpp.svn-base
字号:
if (FindCodeDataRangeByDataAddr((unsigned)AVTablePtr
- (sizeof(unsigned) * 4), NULL, &ADataRange))
{
//maybe vtableptr
unsigned * vftPtr = (unsigned *)AVTablePtr;
unsigned VMFuncAddr = *vftPtr;
if (((VMFuncAddr >= ADataRange->CodeSecStart)
&& (VMFuncAddr < ADataRange->DataSecStart))
|| (FindCodeDataRangeByCodeAddr(VMFuncAddr, NULL, &ACodeRange)))
{
//address of virtual member function is valid
unsigned varOffset = vftPtr[-2];
unsigned rttiPtrOffset = vftPtr[-1];
if (varOffset <= AVTablePtrOffset)
{
unsigned rttiPtr = (unsigned)((char *)vftPtr - rttiPtrOffset);
if ((rttiPtr >= ADataRange->DataSecStart)
&& (((unsigned *)rttiPtr)[-1] == 0))
{ //rtti Ptr is valid
TypeDescriptorPtr mdtpidPtr = *((TypeDescriptorPtr *)((unsigned *)rttiPtr - 2) - 1);
if (((unsigned)mdtpidPtr > ADataRange->CodeSecStart)
&& (((unsigned)mdtpidPtr + (sizeof(TypeDescriptor) - sizeof(GUID)))
< ADataRange->DataSecStart))
{ //tpid data in code section
if ((mdtpidPtr->Size >= (AVTablePtrOffset + sizeof(void *)))
&& (mdtpidPtr->Class.VTablePtrOffset == AVTablePtrOffset)
&& (mdtpidPtr->Mask & (TYPE_MASK_IS_STRUCT | TYPE_MASK_IS_CLASS))
&& (mdtpidPtr->Class.Flags & (CLASS_FLAG_HAS_VTABPTR | CLASS_FLAG_HAS_RTTI)))
{ //tpid data valid ?
unsigned char * TypeName = (unsigned char *)mdtpidPtr
+ mdtpidPtr->Name;
if ((((unsigned)TypeName + sizeof(unsigned char) * 2)
< ADataRange->DataSecStart) && (*TypeName <= 'z'))
{
return mdtpidPtr;
}
}
}
}
}
}
}
}
}
}
return NULL;
}
//#define CheckVirtualRootBaseFirst //Returned may not be the most derived type
TypeDescriptorPtr __fastcall GetCppVirtualObjectTypeIdPtr(void * APointer, unsigned ASize)
{
if ((APointer) && (ASize >= sizeof(void *)))
{
if (!((unsigned)APointer & (sizeof(void *) - 1)))
{
if (!gpModuleCodeDataRanges)
{
if (!FillModuleCodeDataRanges())
{
return NULL;
}
}
#ifdef CheckVirtualRootBaseFirst
TypeDescriptorPtr ret = GetCppVirtualObjectTypeIdPtrByVTablePtr(*((void **)APointer), 0);
if (ret)
{
return ret;
}
#endif
PModuleCodeDataRanges ADataRange, ACodeRange;
unsigned ObjectSize = ASize;
ASize = ASize - (ASize & (sizeof(void *) - 1)) - sizeof(void *);
unsigned * DataPtr = (unsigned *)((char *)APointer + ASize);
#ifdef CheckVirtualRootBaseFirst
while (DataPtr > (unsigned *)APointer)
#else
while (DataPtr >= (unsigned *)APointer)
#endif
{
unsigned Data = *DataPtr;
if ((Data >= LowestDataAddr) && (Data <= HighestDataAddr))
{
if (FindCodeDataRangeByDataAddr(Data - (sizeof(unsigned) * 4),
NULL, &ADataRange))
{
//maybe vtableptr
unsigned * vftPtr = (unsigned *)Data;
unsigned VMFuncAddr = *vftPtr;
if (((VMFuncAddr >= ADataRange->CodeSecStart)
&& (VMFuncAddr < ADataRange->DataSecStart))
|| (FindCodeDataRangeByCodeAddr(VMFuncAddr, NULL, &ACodeRange)))
{
//address of virtual member function is valid
unsigned varOffset = vftPtr[-2];
unsigned rttiPtrOffset = vftPtr[-1];
unsigned vftPtrOffset = (char *)DataPtr - (char *)APointer;
if (varOffset <= vftPtrOffset)
{
unsigned rttiPtr = (unsigned)((char *)vftPtr - rttiPtrOffset);
if ((rttiPtr >= ADataRange->DataSecStart)
&& (((unsigned *)rttiPtr)[-1] == 0))
{ //rtti Ptr is valid
TypeDescriptorPtr mdtpidPtr = *((TypeDescriptorPtr *)((unsigned *)rttiPtr - 2) - 1);
if (((unsigned)mdtpidPtr > ADataRange->CodeSecStart)
&& (((unsigned)mdtpidPtr + (sizeof(TypeDescriptor) - sizeof(GUID)))
< ADataRange->DataSecStart))
{ //tpid data in code section
if ((mdtpidPtr->Size <= ObjectSize)
&& (mdtpidPtr->Class.VTablePtrOffset == vftPtrOffset)
&& (mdtpidPtr->Mask & (TYPE_MASK_IS_STRUCT | TYPE_MASK_IS_CLASS))
&& (mdtpidPtr->Class.Flags & (CLASS_FLAG_HAS_VTABPTR | CLASS_FLAG_HAS_RTTI)))
{ //tpid data valid ?
unsigned char * TypeName = (unsigned char *)mdtpidPtr
+ mdtpidPtr->Name;
if ((((unsigned)TypeName + sizeof(unsigned char) * 2)
< ADataRange->DataSecStart) && (*TypeName <= 'z'))
{
return mdtpidPtr;
}
}
}
}
}
}
}
}
DataPtr--;
}
}
}
return NULL;
}
char * __fastcall GetCppVirtualObjectTypeName(void * APointer, unsigned ASize)
{
TypeDescriptorPtr AtpidPtr = GetCppVirtualObjectTypeIdPtr(APointer, ASize);
if (AtpidPtr)
{
return (char *)AtpidPtr + AtpidPtr->Name;
}
else {
return NULL;
}
}
char * __fastcall GetCppVirtualObjectTypeNameByVTablePtr(void * AVTablePtr,
unsigned AVTablePtrOffset)
{
TypeDescriptorPtr AtpidPtr = GetCppVirtualObjectTypeIdPtrByVTablePtr(AVTablePtr,
AVTablePtrOffset);
if (AtpidPtr)
{
return (char *)AtpidPtr + AtpidPtr->Name;
}
else {
return NULL;
}
}
unsigned __fastcall GetCppVirtualObjectSizeByTypeIdPtr(TypeDescriptorPtr AtpidPtr)
{
if ((AtpidPtr)
&& (AtpidPtr->Mask & (TYPE_MASK_IS_STRUCT | TYPE_MASK_IS_CLASS))
&& (AtpidPtr->Class.Flags & (CLASS_FLAG_HAS_VTABPTR | CLASS_FLAG_HAS_RTTI)))
{
return AtpidPtr->Size;
}
else {
return 0;
}
}
char * __fastcall GetCppVirtualObjectTypeNameByTypeIdPtr(TypeDescriptorPtr AtpidPtr)
{
if (AtpidPtr)
{
return (char *)AtpidPtr + AtpidPtr->Name;
}
else {
return NULL;
}
}
#endif //CheckCppObjectTypeEnabled
#define BORLANDMM "borlndmm"
#define CRTL_MEM_SIGNATURE_EXPORT "___CRTL_MEM_GetBorMemPtrs"
#define CRTL_GET_HEAP_REDIRECTOR_INFO "__get_heap_redirector_info"
bool __fastcall TryHookRTLHeapRedirector(HMODULE AModule, void *AParam)
{
if ((FindResource(AModule, DVCLALResName, RT_RCDATA))
/*&& (GetProcAddress(AModule, CPPdebugHookExport))*/
&& (GetProcAddress(AModule, CRTL_MEM_SIGNATURE_EXPORT)))
{
rtl_get_heap_redirector_info_func rtl_get_heap_redirector_info;
rtl_get_heap_redirector_info
= (rtl_get_heap_redirector_info_func)GetProcAddress(AModule, CRTL_GET_HEAP_REDIRECTOR_INFO);
if (rtl_get_heap_redirector_info)
{
HeapRedirector * pHRDir = (*rtl_get_heap_redirector_info)();
if (pHRDir)
{
if ((pHRDir->flags < hrfBorlndmm) || (pHRDir->flags == hrfVCLSystem))
{
void * PatchAddr;
HeapRedirectorStorePtr node = (HeapRedirectorStorePtr)FinalGetMem(sizeof(HeapRedirectorStore));
node->Data = *pHRDir;
node->Module = AModule;
//insert node into store list
node->Next = HeapRedirectorStoreListHeader;
HeapRedirectorStoreListHeader = node;
pHRDir->malloc = &Cpp_malloc_Stub;
pHRDir->free = &Cpp_free_Stub;
pHRDir->realloc = &Cpp_realloc_Stub;
pHRDir->terminate = &Cpp_terminate_Stub;
pHRDir->flags = hrfOther;
pHRDir->allocated = 1;
//patch RTL _terminate of this module
PatchAddr = GetProcAddress(AModule, _terminateExport);
if ((PatchAddr) && (((PRelativeJmp32)PatchAddr)->JmpInst != RelativeJmp32Inst)
&& (!PatchProc(PatchAddr, &New_terminate, &node->PatchBackup)))
{
node->PatchAddress = PatchAddr;
}
else
{
node->PatchAddress = NULL;
}
}
}
}
}
return true;
}
bool __fastcall TryUnhookRTLHeapRedirector(HMODULE AModule, void *AParam)
{
if ((FindResource(AModule, DVCLALResName, RT_RCDATA))
/*&& (GetProcAddress(AModule, CPPdebugHookExport))*/
&& (GetProcAddress(AModule, CRTL_MEM_SIGNATURE_EXPORT)))
{
rtl_get_heap_redirector_info_func rtl_get_heap_redirector_info;
rtl_get_heap_redirector_info
= (rtl_get_heap_redirector_info_func)GetProcAddress(AModule, CRTL_GET_HEAP_REDIRECTOR_INFO);
if (rtl_get_heap_redirector_info)
{
HeapRedirector * pHRDir = (*rtl_get_heap_redirector_info)();
if (pHRDir)
{
//restore and remove store node
{
HeapRedirectorStorePtr prev, node;
prev = NULL;
node = HeapRedirectorStoreListHeader;
while (node)
{
if (node->Module == AModule)
{
//restore original heap redirector
if ((pHRDir->flags == hrfOther)
&& (pHRDir->malloc == &Cpp_malloc_Stub)
&& (pHRDir->free == &Cpp_free_Stub)
&& (pHRDir->realloc == &Cpp_realloc_Stub)
&& (pHRDir->terminate == &Cpp_terminate_Stub)
)
{
#ifdef DetectMMOperationsAfterUninstall
if ((bool)AParam)
{
pHRDir->malloc = &Cpp_Invalid_malloc_Stub;
pHRDir->free = &Cpp_Invalid_free_Stub;
pHRDir->realloc = &Cpp_Invalid_realloc_Stub;
}
else
#endif
*pHRDir = node->Data;
}
//restore RTL _terminate of this module
if (node->PatchAddress)
{
UnPatchProc(node->PatchAddress, &New_terminate, &node->PatchBackup);
}
//remove node from store list
if (prev)
{
prev->Next = node->Next;
}
else
{
HeapRedirectorStoreListHeader = node->Next;
}
FinalFreeMem(node);
break;
}
else
{
prev = node;
node = node->Next;
}
}
}
}
}
}
return true;
}
#endif //PatchBCBTerminate
void BCBInstallFastMM()
{
//#ifdef __DLL__ //not defined even with -tWD ?
//#endif
//#if ((!defined(_NO_VCL)) && defined(__DLL__) && defined(_RTLDLL))
//borlndmm.dll will linked in
//#else
InitializeMemoryManager();
#if __BORLANDC__ >= 0x582
//>= BDS2006 ?
//CheckCanInstallMemoryManager will finally call System.GetHeapStatus which is the
//internal shipped copy of FastGetHeapStatus routine, but the InitializeMemoryManager
//routine of that copy is not called yet at this point, and thus System.GetHeapStatus
//will generate an access violation exception.
//Currently avoid this exception by skip the check
#ifndef _NO_VCL
if (CheckCanInstallMemoryManager())
#endif //!_NO_VCL
#else
if (CheckCanInstallMemoryManager())
#endif //< BDS2006
{
#ifdef PatchBCBTerminate
#if defined(__DLL__) && defined(FullDebugMode) && defined(LoadDebugDLLDynamically)
//if FastMM_FullDebugMode.dll receive DLL_PROCESS_DETACH before
//calling FinalizeMemoryManager, exception will occur when calling
//LogStackTrace in FastMM_FullDebugMode.dll, the following call
//will delay the processing of DLL_PROCESS_DETACH in DllMain of
//FastMM_FullDebugMode.dll
if (!TryHookFullDebugModeDllEntry())
{
return;
}
#endif
#endif
#ifdef FullDebugMode
#ifdef ClearLogFileOnStartup
DeleteEventLog();
#endif //ClearLogFileOnStartup
#endif //FullDebugMode
#ifdef PatchBCBTerminate
#if __BORLANDC__ >= 0x582
//>= BDS2006 ?
System::TMemoryManagerEx AMemoryManager;
#else
System::TMemoryManager AMemoryManager;
#endif
System::GetMemoryManager(AMemoryManager);
StockGetMemPtr = AMemoryManager.GetMem;
#endif
InstallMemoryManager();
#ifdef PatchBCBTerminate
IsMMInstalled = true;
#endif
#ifdef PatchBCBTerminate
HMODULE ThisModule = (HMODULE)System::FindHInstance(&BCBInstallFastMM);
HMODULE MainModule = GetModuleHandle(0);
//#ifndef _RTLDLL
HMODULE BorlandMM_Module = GetModuleHandle(BORLANDMM);
if (!BorlandMM_Module)
{
pHRDir = _get_heap_redirector_info();
if (pHRDir)
{
if ((pHRDir->flags < hrfBorlndmm) || (pHRDir->flags == hrfVCLSystem))
{
Old_heap_redirector = *pHRDir;
pHRDir->malloc = &Cpp_malloc_Stub;
pHRDir->free = &Cpp_free_Stub;
pHRDir->realloc = &Cpp_realloc_Stub;
pHRDir->terminate = &Cpp_terminate_Stub;
pHRDir->flags = hrfOther;
pHRDir->allocated = 1;
}
else {
pHRDir = NULL;
}
}
}
else
{
if (BorlandMM_Module == ThisModule)
{
IsBorlandMMDLL = true;
//Try hook heap redirector of RTL modules
EnumModules(TryHookRTLHeapRedirector, NULL);
}
}
//#endif //!_RTLDLL
pCppDebugHook = PInteger(GetProcAddress(MainModule, CPPdebugHookExport));
if (!pCppDebugHook)
{
pCppDebugHook = &__CPPdebugHook;
}
#ifdef CheckCppObjectTypeEnabled
GetCppVirtObjSizeByTypeIdPtrFunc =
(TGetCppVirtObjSizeByTypeIdPtrFunc)&GetCppVirtualObjectSizeByTypeIdPtr;
GetCppVirtObjTypeIdPtrFunc =
(TGetCppVirtObjTypeIdPtrFunc)&GetCppVirtualObjectTypeIdPtr;
GetCppVirtObjTypeNameFunc =
(TGetCppVirtObjTypeNameFunc)&GetCppVirtualObjectTypeName;
GetCppVirtObjTypeNameByTypeIdPtrFunc =
(TGetCppVirtObjTypeNameByTypeIdPtrFunc)&GetCppVirtualObjectTypeNameByTypeIdPtr;
GetCppVirtObjTypeNameByVTablePtrFunc =
(TGetCppVirtObjTypeNameByVTablePtrFunc)&GetCppVirtualObjectTypeNameByVTablePtr;
#endif
IsInDLL = (MainModule != ThisModule);
if (!IsInDLL)
{
if (Patch_terminate())
{
terminatePatched = true;
#ifdef EnableMemoryLeakReporting
#if __BORLANDC__ >= 0x582
//>= BDS2006 ?
//"ios.cpp", line 136, ios_base::_Init(), "locale" leaks
RegisterExpectedMemoryLeak(20, 8);
//"locale0.cpp", line 167, locale::_Init(), "_Locimp" leak due to above leaks
RegisterExpectedMemoryLeak(68, 1);
#endif
#endif
}
}
#ifndef _RTLDLL
else
{
#ifdef EnableMemoryLeakReporting
#if __BORLANDC__ >= 0x582
//>= BDS2006 ?
//"ios.cpp", line 136, ios_base::_Init(), "locale" leaks
RegisterExpectedMemoryLeak(20, 8);
//"locale0.cpp", line 167, locale::_Init(), "_Locimp" leak due to above leaks
RegisterExpectedMemoryLeak(68, 1);
RegisterExpectedMemoryLeak(228, 1);
#endif
#endif
}
#endif //_RTLDLL
#endif //PatchBCBTerminate
}
//#endif
}
#pragma startup BCBInstallFastMM 0
#ifdef PatchBCBTerminate
void BCBUninstallFastMM()
{
//Sadly we cannot uninstall here since there are still live pointers.
//#if ((!defined(_NO_VCL)) && defined(__DLL__) && defined(_RTLDLL))
//#else
if (IsMMInstalled && (!terminatePatched))
{
//Delphi MemoryManager already installed here
FinalizeMemoryManager();
#if __BORLANDC__ >= 0x582
//>= BDS2006 ?
System::TMemoryManagerEx AMemoryManager;
#else
System::TMemoryManager AMemoryManager;
#endif
System::GetMemoryManager(AMemoryManager);
//MemoryManager uninstalled ?
bool DelphiMMUninstalled = (AMemoryManager.GetMem != InternalGetMem);
#ifdef DetectMMOperationsAfterUninstall
//InvalidMemoryManager get set as Delphi MemoryManager ?
bool InvalidMMSet = (AMemoryManager.GetMem != StockGetMemPtr);
#endif
#ifdef CheckCppObjectTypeEnabled
GetCppVirtObjSizeByTypeIdPtrFunc = NULL;
GetCppVirtObjTypeIdPtrFunc = NULL;
GetCppVirtObjTypeNameFunc = NULL;
GetCppVirtObjTypeNameByTypeIdPtrFunc = NULL;
GetCppVirtObjTypeNameByVTablePtrFunc = NULL;
FinalizeModuleCodeDataRanges();
#endif
if (DelphiMMUninstalled)
{
if (pHRDir)
{
#ifdef DetectMMOperationsAfterUninstall
if (InvalidMMSet)
{
InvalidGetMemPtr = AMemoryManager.GetMem;
InvalidFreeMemPtr = AMemoryManager.FreeMem;
InvalidReallocMemPtr = AMemoryManager.ReallocMem;
pHRDir->malloc = Cpp_Invalid_malloc_Stub;
pHRDir->free = Cpp_Invalid_free_Stub;
pHRDir->realloc = Cpp_Invalid_realloc_Stub;
}
else
#endif
*pHRDir = Old_heap_redirector;
pHRDir = NULL;
}
else
{
if (IsBorlandMMDLL)
{
//Try unhook heap redirector of RTL modules
#ifdef DetectMMOperationsAfterUninstall
EnumModules(TryUnhookRTLHeapRedirector, (void *)InvalidMMSet);
#else
EnumModules(TryUnhookRTLHeapRedirector, NULL);
#endif
FinalizeHeapRedirectorStoreList();
}
}
}
#if defined(__DLL__) && defined(FullDebugMode) && defined(LoadDebugDLLDynamically)
CallOldFullDebugModeDllEntry();
#endif
}
//#endif
}
#pragma exit BCBUninstallFastMM 0
#endif //PatchBCBTerminate
#ifdef __cplusplus
} // extern "C"
#endif
#pragma option pop
//#endif //!_NO_VCL
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -