l2-unlegits/L2C_Server/utils/Debugging.cpp
2012-02-01 05:25:08 +00:00

305 lines
8.2 KiB
C++

#include "pch.h"
#include "Log.h"
#include "Debugging.h"
#define MAX_SYM_NAME_LEN 256
Debug *Debug::s_instance = NULL;
Debug *Debug::getInstance()
{
if( !s_instance )
s_instance = new Debug();
return s_instance;
}
void Debug::freeInstance()
{
if( s_instance )
{
delete s_instance;
s_instance = NULL;
}
}
/*BOOL CALLBACK Debug_EnumerateModulesProc64( PCSTR ModuleName, DWORD64 BaseOfDll, PVOID UserContext )
{
//LogDebug( L" EnumerateModulesProc [%S] 0x%08X", ModuleName, (DWORD)BaseOfDll );
wchar_t w[1024];
wsprintfW( w, L" EnumerateModulesProc [%S] 0x%08X", ModuleName, (DWORD)BaseOfDll );
MessageBox( NULL, w, L"Enum mod", 0 );
return TRUE;
}*/
Debug::Debug()
{
InitializeCriticalSectionAndSpinCount( &m_lock, 10 );
EnterCriticalSection( &m_lock );
m_initOK = false;
m_symHandle = GetCurrentProcess();
// set symbol handler options
SymSetOptions( SYMOPT_UNDNAME | /*SYMOPT_DEFERRED_LOADS |*/ SYMOPT_LOAD_LINES );
// create symbol search path
WCHAR windir[256] = {0};
WCHAR szSearchPath[256] = {0};
GetWindowsDirectoryW( windir, 255 );
wsprintfW( szSearchPath, L".;.\\Symbols;%s\\Symbols;%s\\Symbols\\dll", windir, windir );
//MessageBoxW( NULL, szSearchPath, NULL, 0 );
// initialize symbol handler
BOOL ok = SymInitializeW( m_symHandle, szSearchPath/*NULL*/, TRUE );
if( !ok )
{
DWORD le = GetLastError();
wchar_t msg[512];
wsprintfW( msg, L"SymInitialize() failed: %u", le );
MessageBox( NULL, msg, L"Error", MB_ICONSTOP );
}
else
{
m_initOK = true;
//
// load PDBs for all modules possible
//SymEnumerateModules64( m_symHandle, Debug_EnumerateModulesProc64, NULL );
//
}
LeaveCriticalSection( &m_lock );
}
Debug::~Debug()
{
EnterCriticalSection( &m_lock );
if( m_initOK )
{
SymCleanup( m_symHandle );
m_initOK = false;
}
LeaveCriticalSection( &m_lock );
DeleteCriticalSection( &m_lock );
}
void Debug::createStackTrace( DebugStackTrace& traceObject )
{
traceObject.clear();
EnterCriticalSection( &m_lock );
//
// fill stackframe struct
STACKFRAME64 stackFrame;
memset( &stackFrame, 0, sizeof(stackFrame) );
stackFrame.AddrPC.Mode = AddrModeFlat;
stackFrame.AddrFrame.Mode = AddrModeFlat;
stackFrame.AddrStack.Mode = AddrModeFlat;
unsigned int i;
__asm mov i, esp
stackFrame.AddrStack.Offset = i;
__asm mov i, ebp
stackFrame.AddrFrame.Offset = i;
//stackFrame.AddrPC.Offset = (DWORD64)(void *)(Debug::createStackTrace);
stackFrame.AddrPC.Offset = (DWORD64)(void *)&stackFrame;
BOOL bRet = TRUE;
//
bRet = StackWalk64( IMAGE_FILE_MACHINE_I386, this->m_symHandle, GetCurrentThread(), &stackFrame,
NULL, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL );
while( bRet )
{
DebugOneStackFrameInfo frameInfo;
DWORD64 addr_offset = 0; // address offset
SYMBOL_INFO *psymInfo = (SYMBOL_INFO *)malloc( sizeof(SYMBOL_INFO) + MAX_SYM_NAME_LEN + 1 );
memset( psymInfo, 0, sizeof(SYMBOL_INFO) + MAX_SYM_NAME_LEN + 1 );
psymInfo->SizeOfStruct = sizeof(SYMBOL_INFO);
psymInfo->MaxNameLen = MAX_SYM_NAME_LEN;
if( stackFrame.AddrReturn.Offset > 0 )
{
bRet = SymFromAddr( this->m_symHandle, stackFrame.AddrReturn.Offset, &addr_offset, psymInfo );
if( bRet )
{
// get module info
char *moduleName = NULL;
IMAGEHLP_MODULE64 moduleInfo;
memset( &moduleInfo, 0, sizeof(moduleInfo) );
moduleInfo.SizeOfStruct = sizeof(IMAGEHLP_MODULE64); // 584?
if( !SymGetModuleInfo64( this->m_symHandle, psymInfo->Address, &moduleInfo ) )
{
Log_Win32Error( L"SymGetModuleInfo64() failed", GetLastError() );
LogError( L"For addr 0x%08X name %S", (DWORD)psymInfo->Address, psymInfo->Name );
}
else moduleName = moduleInfo.ModuleName;
//
// get file name and line number
IMAGEHLP_LINE64 lineinfo;
memset( &lineinfo, 0, sizeof(lineinfo) );
lineinfo.SizeOfStruct = sizeof(lineinfo);
DWORD disp = 0;
if( SymGetLineFromAddr64( GetCurrentProcess(), psymInfo->Address, &disp, &lineinfo ) )
{
frameInfo.set( psymInfo->Name, psymInfo->Address, addr_offset,
lineinfo.FileName, lineinfo.LineNumber,
moduleName );
}
else
{
DWORD le = GetLastError();
if( le != ERROR_INVALID_ADDRESS ) // Attempt to access invalid address.
{
Log_Win32Error( L"dbghelp!SymGetLineFromAddr64() failed", le );
LogError( L"For name: [%S]", psymInfo->Name );
}
frameInfo.set( psymInfo->Name, psymInfo->Address, addr_offset, NULL, 0, moduleName );
}
}
else
{
DWORD le = GetLastError();
Log_Win32Error( L"dbghelp!SymFromAddr() failed", le );
LogError( L"For addr: 0x%08X", (DWORD)stackFrame.AddrReturn.Offset );
}
// add frame info
traceObject.addStackFrame( frameInfo );
}
free( psymInfo );
//
bRet = StackWalk64( IMAGE_FILE_MACHINE_I386, GetCurrentProcess(), GetCurrentThread(), &stackFrame, NULL,
NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL );
}
DWORD le = GetLastError();
if( le != ERROR_INVALID_ADDRESS && le != NO_ERROR )
Log_Win32Error( L"StackWalk64() ended", le );
//
// unlock
LeaveCriticalSection( &m_lock );
}
DebugOneStackFrameInfo::~DebugOneStackFrameInfo()
{
if( m_name ) free( m_name );
m_name = NULL;
if( m_fileName ) free( m_fileName );
m_fileName = NULL;
if( m_moduleName ) free( m_moduleName );
m_moduleName = NULL;
m_addr = 0;
m_addr_offset = 0;
m_line = 0;
}
DebugOneStackFrameInfo::DebugOneStackFrameInfo( const DebugOneStackFrameInfo& other )
{
m_name = NULL;
m_fileName = NULL;
m_addr = 0;
m_addr_offset = 0;
m_line = 0;
m_moduleName = NULL;
this->operator=( other );
}
const DebugOneStackFrameInfo& DebugOneStackFrameInfo::operator=( const DebugOneStackFrameInfo& other )
{
if( this == &other ) return (*this);
set( other.m_name, other.m_addr, other.m_addr_offset, other.m_fileName, other.m_line, other.m_moduleName );
return (*this);
}
// compares only address & addr offset
bool DebugOneStackFrameInfo::operator==( const DebugOneStackFrameInfo& other )
{
if( this->m_addr != other.m_addr ) return false; // different addr
if( this->m_addr_offset != other.m_addr_offset ) return false; // different offset
return true; // addresses equal
}
void DebugOneStackFrameInfo::set(
const char *name,
unsigned long long addr,
unsigned long long addr_offset,
const char *fileName,
unsigned int line,
const char *moduleName )
{
m_addr = addr;
m_addr_offset = addr_offset;
m_line = line;
if( m_name ) free( m_name );
m_name = NULL;
if( name ) m_name = _strdup( name );
if( m_fileName ) free( m_fileName );
m_fileName = NULL;
if( fileName ) m_fileName = _strdup( fileName );
if( m_moduleName ) free( m_moduleName );
m_moduleName = NULL;
if( moduleName ) m_moduleName = _strdup( moduleName );
}
DebugStackTrace::DebugStackTrace()
{
m_list.clear();
}
DebugStackTrace::~DebugStackTrace()
{
m_list.clear();
}
void DebugStackTrace::clear()
{
m_list.clear();
}
void DebugStackTrace::addStackFrame( DebugOneStackFrameInfo& ref )
{
m_list.push_back( ref );
}
void DebugStackTrace::logStackTrace()
{
std::list<DebugOneStackFrameInfo>::const_iterator iter = m_list.begin();
int nFrame = 0;
while( iter != m_list.end() )
{
DebugOneStackFrameInfo frm = (*iter);
if( frm.getModuleName() == NULL )
{
if( frm.getFileName() )
{
Log( L" %2d: %S() (0x%08X + %I64u) [%S line %u]", nFrame,
frm.getName(), (unsigned int)frm.getAddr(), frm.getAddrOffset(),
frm.getFileName(), frm.getLine() );
}
else
{
Log( L" %2d: %S() (0x%08X + %I64u)", nFrame,
frm.getName(), (unsigned int)frm.getAddr(), frm.getAddrOffset() );
}
}
else
{
if( frm.getFileName() )
{
Log( L" %2d: %S!%S() (0x%08X + %I64u) [%S line %u]", nFrame,
frm.getModuleName(), frm.getName(), (unsigned int)frm.getAddr(), frm.getAddrOffset(),
frm.getFileName(), frm.getLine() );
}
else
{
Log( L" %2d: %S!%S() (0x%08X + %I64u)", nFrame,
frm.getModuleName(), frm.getName(), (unsigned int)frm.getAddr(), frm.getAddrOffset() );
}
}
nFrame++;
iter++;
}
}