All pastes #368732 Raw Edit

kxMemoryChunk.cpp I

public cpp v1 · immutable
#368732 ·published 2007-02-23 08:39 UTC
rendered paste body
#include "stdafx.h"#include "kxMemoryChunk.h"#include <iostream>#include <DbgHelp.h>// Inicializace statickych clenskych promennychunsigned long int kxMemoryChunk::m_Count = 0;HMODULE kxMemoryChunk::m_hImagehlpDll = 0;DWORD kxMemoryChunk::m_ImageType = 0;HANDLE kxMemoryChunk::m_hProcess = 0;HANDLE kxMemoryChunk::m_hThread = 0;kxMemoryChunk* kxMemoryChunk::m_Begin = NULL;kxMemoryChunk* kxMemoryChunk::m_End = NULL;tSC   kxMemoryChunk::pSC = NULL;tSFTA kxMemoryChunk::pSFTA = NULL;tSGLFA kxMemoryChunk::pSGLFA = NULL;tSGMB kxMemoryChunk::pSGMB = NULL;tSGMI kxMemoryChunk::pSGMI = NULL;tSGO kxMemoryChunk::pSGO = NULL;tSGSFA kxMemoryChunk::pSGSFA = NULL;tSI kxMemoryChunk::pSI = NULL;tSLM kxMemoryChunk::pSLM = NULL;tSSO kxMemoryChunk::pSSO = NULL;tSW kxMemoryChunk::pSW = NULL;tUDSN kxMemoryChunk::pUDSN = NULL;kxMemoryChunk::kxMemoryChunk(size_t size){			if(m_Count > 0 && size > 0)	{		ZeroMemory(&m_StackFrame,sizeof(m_StackFrame));		ZeroMemory(&m_Context,sizeof(m_Context));		m_Data = malloc(size);		m_Size = size;		}}// *******************************************************************************************kxMemoryChunk::~kxMemoryChunk(){}// Pretizeni lokalniho new void* kxMemoryChunk::operator new(size_t size){		if(m_Count == 0) // Musime inicializovat begin a end	{		LazyInit();	}	//kxMemoryChunk* ptr = (kxMemoryChunk*)malloc(sizeof(kxMemoryChunk));	kxMemoryChunk* ptr = (kxMemoryChunk*)malloc(size);	if(ptr)	{					ptr->m_Prev = m_End->m_Prev;        // Linknuti		ptr->m_Next = m_End;		m_End->m_Prev->m_Next = ptr;		m_End->m_Prev = ptr;		Dump(ptr); // Dumpnuti dat		}	m_Count++;	return ptr;}// Pretizeni lokalniho deletevoid kxMemoryChunk::operator delete(void* ptr)  {	kxMemoryChunk* chunk = (kxMemoryChunk*)ptr;	// Unlinknuti	chunk->m_Prev->m_Next = chunk->m_Next;	chunk->m_Next->m_Prev = chunk->m_Prev;	if(m_Count == 1)	{		LazyCleanup();	}	free(ptr);	m_Count--;}kxMemoryChunk* kxMemoryChunk::GetBegin(){	return m_Begin;}kxMemoryChunk* kxMemoryChunk::GetEnd(){	return m_End;}unsigned long int kxMemoryChunk::GetCount(){	return m_Count;}void kxMemoryChunk::Delete(void* data_ptr){	// Pre-conditions	if(m_Begin == NULL || m_End == NULL)	{		return;	}		// Vykonne telo	kxMemoryChunk* tmp = m_Begin->m_Next;	while(tmp != m_End)	{		if(tmp->m_Data == data_ptr)		{			delete tmp;			return;		}		tmp = tmp->m_Next;	}}void kxMemoryChunk::Check(){	if(m_Count > 0)	{		std::cout << "Error: " << m_Count << " neuvolnenych chunku bude uvolneno!" << std::endl;		size_t total = 0;		while(m_Count > 0)		{			total += m_Begin->m_Next->m_Size;			std::cout << "Address: 0x" << (void*)m_Begin->m_Next->m_Data << ", Length = " << m_Begin->m_Next->m_Size << std::endl;			delete m_Begin->m_Next;		}		std::cout << "Totaly " << total << " has been freed!" << std::endl;	}}void kxMemoryChunk::Dump(kxMemoryChunk* chunk){	/*	StackWalk( \		m_ImageType, \		m_hProcess, \		m_hThread, \		(LPSTACKFRAME)&chunk->m_StackFrame, \		&chunk->m_Context, \		NULL, \		(PFUNCTION_TABLE_ACCESS_ROUTINE) GetProcAddress( m_hImagehlpDll, "SymFunctionTableAccess" ), \		(PGET_MODULE_BASE_ROUTINE) GetProcAddress( m_hImagehlpDll, "SymGetModuleBase" ), \		NULL \	);	*/		#define gle (GetLastError())	#define lenof(a) (sizeof(a) / sizeof((a)[0]))	#define MAXNAMELEN 1024 // max name length for found symbols	#define IMGSYMLEN ( sizeof IMAGEHLP_SYMBOL )	#define TTBUFLEN 65536 // for a temp buffer		DWORD symOptions; // symbol handler settings	IMAGEHLP_SYMBOL *pSym = (IMAGEHLP_SYMBOL *) malloc( IMGSYMLEN + MAXNAMELEN );	DWORD offsetFromSymbol;	char undName[MAXNAMELEN]; // undecorated name	char undFullName[MAXNAMELEN]; // undecorated name with all shenanigans	IMAGEHLP_MODULE Module;	IMAGEHLP_LINE Line;	std::string symSearchPath;		char *tt = 0, *p;	tt = (char*)malloc(TTBUFLEN); // this is a _sample_. you can do the error checking yourself.	// build symbol search path from:	symSearchPath = "";	// current directory	if ( GetCurrentDirectoryA( TTBUFLEN, tt ) )		symSearchPath += tt + std::string( ";" );	// dir with executable	if ( GetModuleFileNameA( 0, tt, TTBUFLEN ) )	{		for ( p = tt + strlen( tt ) - 1; p >= tt; -- p )		{			// locate the rightmost path separator			if ( *p == '\\' || *p == '/' || *p == ':' )				break;		}		// if we found one, p is pointing at it; if not, tt only contains		// an exe name (no path), and p points before its first byte		if ( p != tt ) // path sep found?		{			if ( *p == ':' ) // we leave colons in place				++ p;			*p = '\0'; // eliminate the exe name and last path sep			symSearchPath += tt + std::string( ";" );		}	}	// environment variable _NT_SYMBOL_PATH	if ( GetEnvironmentVariableA( "_NT_SYMBOL_PATH", tt, TTBUFLEN ) )		symSearchPath += tt + std::string( ";" );	// environment variable _NT_ALTERNATE_SYMBOL_PATH	if ( GetEnvironmentVariableA( "_NT_ALTERNATE_SYMBOL_PATH", tt, TTBUFLEN ) )		symSearchPath += tt + std::string( ";" );	// environment variable SYSTEMROOT	if ( GetEnvironmentVariableA( "SYSTEMROOT", tt, TTBUFLEN ) )		symSearchPath += tt + std::string( ";" );	if ( symSearchPath.size() > 0 ) // if we added anything, we have a trailing semicolon		symSearchPath = symSearchPath.substr( 0, symSearchPath.size() - 1 );	printf( "symbols path: %s\n", symSearchPath.c_str() );	// why oh why does SymInitialize() want a writeable string?	strncpy( tt, symSearchPath.c_str(), TTBUFLEN );	tt[TTBUFLEN - 1] = '\0'; // if strncpy() overruns, it doesn't add the null terminator	// init symbol handler stuff (SymInitialize())	if ( ! pSI( m_hProcess, tt, false ) )	{		printf( "SymInitialize(): gle = %lu\n", gle );		goto cleanup;	}	// SymGetOptions()	symOptions = pSGO();	symOptions |= SYMOPT_LOAD_LINES;	symOptions &= ~SYMOPT_UNDNAME;	pSSO( symOptions ); // SymSetOptions()	// Enumerate modules and tell imagehlp.dll about them.	// On NT, this is not necessary, but it won't hurt.	EnumumAndLoadModuleSymbols( chunk->m_hProcess, GetCurrentProcessId() );	// init STACKFRAME for first call	// Notes: AddrModeFlat is just an assumption. I hate VDM debugging.	// Notes: will have to be #ifdef-ed for Alphas; MIPSes are dead anyway,	// and good riddance.	chunk->m_StackFrame.AddrPC.Offset = chunk->m_Context.Eip;	chunk->m_StackFrame.AddrPC.Mode = AddrModeFlat;	chunk->m_StackFrame.AddrFrame.Offset = chunk->m_Context.Ebp;	chunk->m_StackFrame.AddrFrame.Mode = AddrModeFlat;		chunk->m_hProcess = GetCurrentProcess();	chunk->m_hThread = GetCurrentThread();	chunk->m_Context.ContextFlags = CONTEXT_FULL;	GetThreadContext(chunk->m_hThread,&chunk->m_Context);	memset( pSym, '\0', IMGSYMLEN + MAXNAMELEN );	pSym->SizeOfStruct = IMGSYMLEN;	pSym->MaxNameLength = MAXNAMELEN;	memset( &Line, '\0', sizeof Line );	Line.SizeOfStruct = sizeof Line;	memset( &Module, '\0', sizeof Module );	Module.SizeOfStruct = sizeof Module;	offsetFromSymbol = 0;	for ( int frameNum = 0; ; ++ frameNum )	{		// get next stack frame (StackWalk(), SymFunctionTableAccess(), SymGetModuleBase())		// if this returns ERROR_INVALID_ADDRESS (487) or ERROR_NOACCESS (998), you can		// assume that either you are done, or that the stack is so hosed that the next		// deeper frame could not be found.		if ( ! StackWalk(IMAGE_FILE_MACHINE_I386, chunk->m_hProcess, chunk->m_hThread,(LPSTACKFRAME)&chunk->m_StackFrame, &chunk->m_Context, NULL,	(PFUNCTION_TABLE_ACCESS_ROUTINE) GetProcAddress( m_hImagehlpDll, "SymFunctionTableAccess" ), (PGET_MODULE_BASE_ROUTINE) GetProcAddress( m_hImagehlpDll, "SymGetModuleBase" ), NULL ) )			break;		// display its contents		printf( "\n%3d %c%c %08lx %08lx %08lx %08lx ",	frameNum, chunk->m_StackFrame.Far? 'F': '.', chunk->m_StackFrame.Virtual? 'V': '.',	chunk->m_StackFrame.AddrPC.Offset, chunk->m_StackFrame.AddrReturn.Offset, chunk->m_StackFrame.AddrFrame.Offset, chunk->m_StackFrame.AddrStack.Offset );		if ( chunk->m_StackFrame.AddrPC.Offset == 0 )		{			printf( "(-nosymbols- PC == 0)\n" );		}		else		{ // we seem to have a valid PC			// show procedure info (SymGetSymFromAddr())			if ( ! pSGSFA( chunk->m_hProcess, chunk->m_StackFrame.AddrPC.Offset, &offsetFromSymbol, pSym ) )			{				if ( gle != 487 )					printf( "SymGetSymFromAddr(): gle = %lu\n", gle );			}			else			{				// UnDecorateSymbolName()				pUDSN( pSym->Name, undName, MAXNAMELEN, UNDNAME_NAME_ONLY );				pUDSN( pSym->Name, undFullName, MAXNAMELEN, UNDNAME_COMPLETE );				printf( "%s", undName );				if ( offsetFromSymbol != 0 )					printf( " %+ld bytes", (long) offsetFromSymbol );				putchar( '\n' );				printf( "    Sig:  %s\n", pSym->Name );				printf( "    Decl: %s\n", undFullName );			}			// show line number info, NT5.0-method (SymGetLineFromAddr())			if ( pSGLFA != NULL )			{ // yes, we have SymGetLineFromAddr()				if ( ! pSGLFA(chunk->m_hProcess, chunk->m_StackFrame.AddrPC.Offset, &offsetFromSymbol, &Line ) )				{					if ( gle != 487 )						printf( "SymGetLineFromAddr(): gle = %lu\n", gle );				}				else				{					printf( "    Line: %s(%lu) %+ld bytes\n",						Line.FileName, Line.LineNumber, offsetFromSymbol );				}			} // yes, we have SymGetLineFromAddr()			// show module info (SymGetModuleInfo())			if ( ! pSGMI( chunk->m_hProcess, chunk->m_StackFrame.AddrPC.Offset, &Module ) )			{				printf( "SymGetModuleInfo): gle = %lu\n", gle );			}			else			{ // got module info OK				char ty[80];				switch ( Module.SymType )				{				case SymNone:					strcpy( ty, "-nosymbols-" );					break;				case SymCoff:					strcpy( ty, "COFF" );					break;				case SymCv:					strcpy( ty, "CV" );					break;				case SymPdb:					strcpy( ty, "PDB" );					break;				case SymExport:					strcpy( ty, "-exported-" );					break;				case SymDeferred:					strcpy( ty, "-deferred-" );					break;				case SymSym:					strcpy( ty, "SYM" );					break;				default:					_snprintf( ty, sizeof ty, "symtype=%ld", (long) Module.SymType );					break;				}				printf( "    Mod:  %s[%s], base: %08lxh\n",					Module.ModuleName, Module.ImageName, Module.BaseOfImage );				printf( "    Sym:  type: %s, file: %s\n",					ty, Module.LoadedImageName );			} // got module info OK		} // we seem to have a valid PC		// no return address means no deeper stackframe		if ( chunk->m_StackFrame.AddrReturn.Offset == 0 )		{			// avoid misunderstandings in the printf() following the loop			SetLastError( 0 );			break;		}	} // for ( frameNum )cleanup:	pSC( m_hProcess );	free( pSym );	free(tt);}bool kxMemoryChunk::FillModuleList( ModuleList& modules, DWORD pid, HANDLE hProcess ){	// try toolhelp32 first	if ( FillModuleListTH32( modules, pid ) )		return true;	// nope? try psapi, then	return FillModuleListPSAPI( modules, pid, hProcess );}bool kxMemoryChunk::FillModuleListTH32( ModuleList& modules, DWORD pid ){	// CreateToolhelp32Snapshot()	typedef HANDLE (__stdcall *tCT32S)( DWORD dwFlags, DWORD th32ProcessID );	// Module32First()	typedef BOOL (__stdcall *tM32F)( HANDLE hSnapshot, LPMODULEENTRY32 lpme );	// Module32Next()	typedef BOOL (__stdcall *tM32N)( HANDLE hSnapshot, LPMODULEENTRY32 lpme );	// I think the DLL is called tlhelp32.dll on Win9X, so we try both	const char *dllname[] = { "kernel32.dll", "tlhelp32.dll" };	HINSTANCE hToolhelp;	tCT32S pCT32S;	tM32F pM32F;	tM32N pM32N;	HANDLE hSnap;	MODULEENTRY32 me = { sizeof me };	bool keepGoing;	ModuleEntry e;	int i;	for ( i = 0; i < lenof( dllname ); ++ i )	{		hToolhelp = LoadLibraryA( dllname[i] );		if ( hToolhelp == 0 )			continue;		pCT32S = (tCT32S) GetProcAddress( hToolhelp, "CreateToolhelp32Snapshot" );		pM32F = (tM32F) GetProcAddress( hToolhelp, "Module32First" );		pM32N = (tM32N) GetProcAddress( hToolhelp, "Module32Next" );		if ( pCT32S != 0 && pM32F != 0 && pM32N != 0 )			break; // found the functions!		FreeLibrary( hToolhelp );		hToolhelp = 0;	}	if ( hToolhelp == 0 ) // nothing found?		return false;	hSnap = pCT32S( TH32CS_SNAPMODULE, pid );	if ( hSnap == (HANDLE) -1 )		return false;	keepGoing = !!pM32F( hSnap, &me );	while ( keepGoing )	{		// here, we have a filled-in MODULEENTRY32		printf( "%08lXh %6lu %-15.15s %s\n", me.modBaseAddr, me.modBaseSize, me.szModule, me.szExePath );		e.imageName = me.szExePath;		e.moduleName = me.szModule;		e.baseAddress = (DWORD) me.modBaseAddr;		e.size = me.modBaseSize;		modules.push_back( e );		keepGoing = !!pM32N( hSnap, &me );	}	CloseHandle( hSnap );	FreeLibrary( hToolhelp );	return modules.size() != 0;}// miscellaneous psapi declarations; we cannot #include the header// because not all systems may have ittypedef struct _MODULEINFO {	LPVOID lpBaseOfDll;	DWORD SizeOfImage;	LPVOID EntryPoint;} MODULEINFO, *LPMODULEINFO;bool kxMemoryChunk::FillModuleListPSAPI( ModuleList& modules, DWORD pid, HANDLE hProcess ){	// EnumProcessModules()	typedef BOOL (__stdcall *tEPM)( HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded );	// GetModuleFileNameEx()	typedef DWORD (__stdcall *tGMFNE)( HANDLE hProcess, HMODULE hModule, LPSTR lpFilename, DWORD nSize );	// GetModuleBaseName() -- redundant, as GMFNE() has the same prototype, but who cares?	typedef DWORD (__stdcall *tGMBN)( HANDLE hProcess, HMODULE hModule, LPSTR lpFilename, DWORD nSize );	// GetModuleInformation()	typedef BOOL (__stdcall *tGMI)( HANDLE hProcess, HMODULE hModule, LPMODULEINFO pmi, DWORD nSize );	HINSTANCE hPsapi;	tEPM pEPM;	tGMFNE pGMFNE;	tGMBN pGMBN;	tGMI pGMI;	int i;	ModuleEntry e;	DWORD cbNeeded;	MODULEINFO mi;	HMODULE *hMods = 0;	char *tt = 0;	hPsapi = LoadLibraryA( "psapi.dll" );	if ( hPsapi == 0 )		return false;	modules.clear();	pEPM = (tEPM) GetProcAddress( hPsapi, "EnumProcessModules" );	pGMFNE = (tGMFNE) GetProcAddress( hPsapi, "GetModuleFileNameExA" );	pGMBN = (tGMFNE) GetProcAddress( hPsapi, "GetModuleBaseNameA" );	pGMI = (tGMI) GetProcAddress( hPsapi, "GetModuleInformation" );	if ( pEPM == 0 || pGMFNE == 0 || pGMBN == 0 || pGMI == 0 )	{		// yuck. Some API is missing.		FreeLibrary( hPsapi );		return false;	}	hMods = new HMODULE[TTBUFLEN / sizeof HMODULE];	tt = new char[TTBUFLEN];	// not that this is a sample. Which means I can get away with	// not checking for errors, but you cannot. :)	if ( ! pEPM( hProcess, hMods, TTBUFLEN, &cbNeeded ) )	{		printf( "EPM failed, gle = %lu\n", gle );		goto cleanup;	}	if ( cbNeeded > TTBUFLEN )	{		printf( "More than %lu module handles. Huh?\n", lenof( hMods ) );		goto cleanup;	}	for ( i = 0; i < cbNeeded / sizeof hMods[0]; ++ i )	{		// for each module, get:		// base address, size		pGMI( hProcess, hMods[i], &mi, sizeof mi );		e.baseAddress = (DWORD) mi.lpBaseOfDll;		e.size = mi.SizeOfImage;		// image file name		tt[0] = '\0';		pGMFNE( hProcess, hMods[i], tt, TTBUFLEN );		e.imageName = tt;		// module name		tt[0] = '\0';		pGMBN( hProcess, hMods[i], tt, TTBUFLEN );		e.moduleName = tt;		printf( "%08lXh %6lu %-15.15s %s\n", e.baseAddress,			e.size, e.moduleName.c_str(), e.imageName.c_str() );		modules.push_back( e );	}cleanup:	if ( hPsapi )		FreeLibrary( hPsapi );	delete [] tt;	delete [] hMods;	return modules.size() != 0;}void kxMemoryChunk::EnumumAndLoadModuleSymbols( HANDLE hProcess, DWORD pid ){	ModuleList modules;	ModuleListIter it;	char *img, *mod;	// fill in module list	FillModuleList( modules, pid, hProcess );	for ( it = modules.begin(); it != modules.end(); ++ it )	{		// unfortunately, SymLoadModule() wants writeable strings		img = (char*)malloc((*it).imageName.size() + 1);		strcpy( img, (*it).imageName.c_str() );		mod = (char*)malloc((*it).moduleName.size() + 1);		strcpy( mod, (*it).moduleName.c_str() );		if ( pSLM( hProcess, 0, img, mod, (*it).baseAddress, (*it).size ) == 0 )			printf( "Error %lu loading symbols for \"%s\"\n",			gle, (*it).moduleName.c_str() );		else			printf( "Symbols loaded: \"%s\"\n", (*it).moduleName.c_str() );		free(img);		free(mod);	}}void kxMemoryChunk::LazyInit(){	m_Begin = (kxMemoryChunk*)malloc(sizeof(kxMemoryChunk));	m_End = (kxMemoryChunk*)malloc(sizeof(kxMemoryChunk));	m_Begin->m_Prev = NULL;	m_Begin->m_Next = m_End;	m_End->m_Prev = m_Begin;	m_End->m_Next = NULL;	m_hImagehlpDll = LoadLibrary( _T("imagehlp.dll") );	pSC = (tSC) GetProcAddress( m_hImagehlpDll, "SymCleanup" );	pSFTA = (tSFTA) GetProcAddress( m_hImagehlpDll, "SymFunctionTableAccess" );	pSGLFA = (tSGLFA) GetProcAddress( m_hImagehlpDll, "SymGetLineFromAddr" );	pSGMB = (tSGMB) GetProcAddress( m_hImagehlpDll, "SymGetModuleBase" );	pSGMI = (tSGMI) GetProcAddress( m_hImagehlpDll, "SymGetModuleInfo" );	pSGO = (tSGO) GetProcAddress( m_hImagehlpDll, "SymGetOptions" );	pSGSFA = (tSGSFA) GetProcAddress( m_hImagehlpDll, "SymGetSymFromAddr" );	pSI = (tSI) GetProcAddress( m_hImagehlpDll, "SymInitialize" );	pSSO = (tSSO) GetProcAddress( m_hImagehlpDll, "SymSetOptions" );	pSW = (tSW) GetProcAddress( m_hImagehlpDll, "StackWalk" );	pUDSN = (tUDSN) GetProcAddress( m_hImagehlpDll, "UnDecorateSymbolName" );	pSLM = (tSLM) GetProcAddress( m_hImagehlpDll, "SymLoadModule" );}void kxMemoryChunk::LazyCleanup(){	free(m_Begin);	free(m_End);	pSC = (tSC) NULL;	pSFTA = (tSFTA) NULL;	pSGLFA = (tSGLFA) NULL;	pSGMB = (tSGMB) NULL;	pSGMI = (tSGMI) NULL;	pSGO = (tSGO) NULL;	pSGSFA = (tSGSFA) NULL;	pSI = (tSI) NULL;	pSSO = (tSSO) NULL;	pSW = (tSW) NULL;	pUDSN = (tUDSN) NULL;	pSLM = (tSLM) NULL;	m_Begin = m_End = NULL;}void* operator new(size_t size){	kxMemoryChunk* tmp = new kxMemoryChunk(size);	if(tmp->m_Data == NULL) // Pokud se nam nepodarilo alokovat data	{		delete tmp;		return NULL;	}	return tmp->m_Data;}void operator delete(void* ptr){	kxMemoryChunk::Delete(ptr);}