Files
Sun1602/Tools/CrashInfomationReport/CrashReport/DumpProcess.cpp
T
2022-10-26 12:25:11 +08:00

547 lines
18 KiB
C++

#include "StdAfx.h"
#include "DumpProcess.h"
//funtion정보를 알기위해서 사용됨
#include "ProcessManager.h"
bool CDumpProcess::LoadFile( const TCHAR* SymbolName )
{
//디코딩이 되지 않았다면 로드 되지 않음!
// if (!decodeDumpfile(SymbolName))
// {
// return false;
// }
if(!ReadDumpFile(SymbolName))
{
return false;
}
if(pMapping_)
{
UnmapViewOfFile(pMapping_);
}
if(handleMap_)
{
CloseHandle(handleMap_);
}
if(handleFile_ != INVALID_HANDLE_VALUE)
{
CloseHandle(handleFile_);
}
//로드 했으니깐 인코딩!
// if (!decodeDumpfile(SymbolName))
// {
// return false;
// }
return true;
}
void CDumpProcess::Clean()
{
}
bool CDumpProcess::ReadDumpFile( const TCHAR* FileName )
{
//파일 핸들 생성.
handleFile_ = CreateFile(FileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,
NULL,NULL);
if( handleFile_ == NULL || handleFile_ == INVALID_HANDLE_VALUE)
return false;
handleMap_ = CreateFileMapping(handleFile_,NULL,PAGE_READONLY,0,0,NULL);
if(handleMap_ == NULL)
return false;
pMapping_ = (byte*)MapViewOfFile(handleMap_,FILE_MAP_READ,0,0,0);
if (memcmp(pMapping_,"MDMP",4) != 0)
{
return false;
}
return OnReadDmpFile();
}
//사용하지 않는 메소드!!!!!!!!!!!!
bool CDumpProcess::OnSearch( DWORD ExceptionAddr , sExceptionInfomation& ExceptionInfo )
{
assert(0 && L"CDumpProcess::OnSearch Not Use CDumpProcess");
return false;
}
bool CDumpProcess::OnSearch( const char* ExceptionAddr,sExceptionInfomation& ExceptionInfo )
{
assert(0 && L"CDumpProcess::OnSearch Not Use CDumpProcess");
return false;
}
bool CDumpProcess::OnReadDmpFile()
{
if(!OnReadMiscInfo())
return false;
if(!OnReadMoudleInfo())
return false;
if(!OnReadSystemInfo())
return false;
if(!OnReadCrashInfo())
return false;
if(!OnReadMemoryInfo())
return false;
if(!OnReadThreadInfo())
return false;
return true;
}
bool CDumpProcess::OnReadMiscInfo()
{
MINIDUMP_MISC_INFO* pMiscInfo = (MINIDUMP_MISC_INFO*)GetDumpInfo(MiscInfoStream);
if(!pMiscInfo)
return false;
if (pMiscInfo->Flags1 & MINIDUMP_MISC1_PROCESS_TIMES)
{
ProcessTime_ = pMiscInfo->ProcessCreateTime;
UserTime_ = pMiscInfo->ProcessUserTime;
KerenlTime_ = pMiscInfo->ProcessKernelTime;
}
return true;
}
bool CDumpProcess::OnReadMoudleInfo()
{
MINIDUMP_MODULE_LIST* pModuleinfo = (MINIDUMP_MODULE_LIST*)GetDumpInfo(ModuleListStream);
MINIDUMP_MODULE* pModule = NULL;
MINIDUMP_STRING* pModuleString = NULL;
if(!pModuleinfo)
return false;
//모듈의 갯수는 0개보다 커야됨.
if(pModuleinfo->NumberOfModules > 0)
{
pModule = &pModuleinfo->Modules[0];
//이런경우가 있을지 모르겠지만... 모듈정보는 생성되었지만 모듈이 없을수 있나?
if(!pModule)
return false;
//처음 모듈 정보만!
pModuleString = (MINIDUMP_STRING*)((char*)pMapping_ + pModule->ModuleNameRva);
_tcsncpy(stringModuleName_,pModuleString->Buffer,sizeof(TCHAR)*256);
DumpModule_.reserve(pModuleinfo->NumberOfModules);
for (size_t index = 0 ; index < pModuleinfo->NumberOfModules ; ++index)
{
DumpModule_.push_back(pModuleinfo->Modules[index]);
}
return true;
}
return false;
}
bool CDumpProcess::OnReadCrashInfo()
{
MINIDUMP_EXCEPTION_STREAM* pExceptionStream =
(MINIDUMP_EXCEPTION_STREAM*)GetDumpInfo(ExceptionStream);
if(!pExceptionStream)
return false;
ExcpetionStreamPointer_ = pExceptionStream;
ExceptionCode_ = pExceptionStream->ExceptionRecord.ExceptionCode;
ExceptionAddr_ = pExceptionStream->ExceptionRecord.ExceptionAddress;
ExceptionInfo_ = pExceptionStream->ExceptionRecord;
//예외가 난 쓰레드 정보를 받기위해서!
ThreadContext_ = pExceptionStream->ThreadContext;
ThreadId_ = pExceptionStream->ThreadId;
FIndExceptionCode(ExceptionCode_);
return true;
}
bool CDumpProcess::OnReadSystemInfo()
{
MINIDUMP_SYSTEM_INFO* pSystemInfo = (MINIDUMP_SYSTEM_INFO*)GetDumpInfo(SystemInfoStream);
if(!pSystemInfo)
return false;
ProcessorArchitecture_ = pSystemInfo->ProcessorArchitecture;
ProcessorLevel_ = pSystemInfo->ProcessorLevel;
ProcessorRevision_ = pSystemInfo->ProcessorRevision;
MajorVersion_ = pSystemInfo->MajorVersion;
MinorVersion_ = pSystemInfo->MinorVersion;
BuildNumber_ = pSystemInfo->BuildNumber;
PlatformId_ = pSystemInfo->PlatformId;
return true;
}
//메모리 정렬에 사용
bool Compare(const MINIDUMP_MEMORY_DESCRIPTOR& a,const MINIDUMP_MEMORY_DESCRIPTOR& b )
{
return a.StartOfMemoryRange < b.StartOfMemoryRange;
}
bool CDumpProcess::OnReadMemoryInfo()
{
MINIDUMP_MEMORY_LIST* pMemList = (MINIDUMP_MEMORY_LIST*)GetDumpInfo(MemoryListStream);
if (!pMemList)
return false;
DumpMemory_.reserve(pMemList->NumberOfMemoryRanges);
for (size_t index = 0 ; index < pMemList->NumberOfMemoryRanges ; ++index)
{
const byte* ptrISRange = (byte*)pMapping_ + pMemList->MemoryRanges[index].Memory.Rva;
UINT sizeIsRange = pMemList->MemoryRanges[index].Memory.DataSize;
if(!IsBadReadPtr(ptrISRange,sizeIsRange) )
{
DumpMemory_.push_back(pMemList->MemoryRanges[index]);
}
}
MINIDUMP_MEMORY64_LIST* pMemList64 = (MINIDUMP_MEMORY64_LIST*)GetDumpInfo(Memory64ListStream);
if (pMemList64)
{
DumpMemory_.reserve(pMemList64->NumberOfMemoryRanges);
UINT rav = pMemList64->BaseRva;
for (size_t index = 0 ; index < pMemList64->NumberOfMemoryRanges ; ++index)
{
MINIDUMP_MEMORY_DESCRIPTOR memoryDescriptor;
memoryDescriptor.StartOfMemoryRange = pMemList64->MemoryRanges[index].StartOfMemoryRange;
memoryDescriptor.Memory.DataSize = pMemList64->MemoryRanges[index].DataSize;
memoryDescriptor.Memory.Rva = rav;
rav += memoryDescriptor.Memory.DataSize;
DumpMemory_.push_back(memoryDescriptor);
}
}
std::sort(DumpMemory_.begin(),DumpMemory_.end(),Compare);
return true;
}
bool CDumpProcess::OnReadThreadInfo()
{
MINIDUMP_THREAD_LIST* pThreadList = (MINIDUMP_THREAD_LIST*)GetDumpInfo(ThreadListStream);
MINIDUMP_THREAD* pThread = NULL;
if(!pThreadList)
return false;
if(pThreadList->NumberOfThreads > 0)
{
for (int threadID = 0 ; threadID < pThreadList->NumberOfThreads ; ++threadID )
{
pThread = &pThreadList->Threads[threadID];
//이 쓰레드가 예외가 난 스레드이다!
if(pThread->ThreadId == ThreadId_)
break;
}
//이런경우가 있을지 모르겠지만... 모듈정보는 생성되었지만 모듈이 없을수 있나?
if(!pThread)
return false;
//콜 스텍 메모리 재구성
//데이터를 읽을때는 4바이트로 정렬되도록 조정
UINT stackAddr = UINT(pThread->Stack.StartOfMemoryRange);
UINT stacksize = pThread->Stack.Memory.DataSize;
if ((stackAddr % 4) != 0)
{
int addr = 4 - (stackAddr % 4);
stackAddr += addr;
stacksize -= addr;
}
UINT LastFrameAddrSave = 0;
UINT LastFrameValueSave = 0;
bool LastFrameLinked = false;
//스텍을 읽으면서 확인 작업.
CONTEXT ThreadContext;
const CONTEXT* ctx = (const CONTEXT*)(pMapping_ + pThread->ThreadContext.Rva);
if(!IsBadReadPtr(ctx,sizeof(CONTEXT)))
{
ThreadContext = *ctx;
LastFrameValueSave = ThreadContext.Ebp;
}
UINT stackaddrEnd = stackAddr + stacksize;
for (UINT addr = stackAddr ; addr < stackaddrEnd ; addr += 4)
{
UINT value;
if (ReadMemoryValue(addr,&value) == false)
{
break;
}
if (value >= stackAddr && value < stackAddr)
{
LastFrameLinked = (LastFrameValueSave == addr);
LastFrameAddrSave = addr;
LastFrameValueSave = value;
}
}
}
return true;
}
PVOID CDumpProcess::GetDumpInfo( ULONG Type )
{
if(!pMapping_)
return NULL;
ULONG Size = 0;
void* pStream = NULL;
MINIDUMP_DIRECTORY* pDir = NULL;
if (!MiniDumpReadDumpStream((PVOID)pMapping_,Type,&pDir,&pStream,&Size))
{
return NULL;
}
return pStream;
}
void CDumpProcess::OnExceptionCause( DWORD exceptioncuase,TCHAR* String,size_t Size )
{
struct ExceptionNames
{
DWORD ExceptionCode;
TCHAR ExceptionName[256];
};
}
//메모리 정렬에 사용
bool Compare2(const MINIDUMP_MEMORY_DESCRIPTOR& a,const MINIDUMP_MEMORY_DESCRIPTOR& b )
{
if(a.StartOfMemoryRange < b.StartOfMemoryRange)
return true;
return false;
}
int CDumpProcess::ReadMemory( int addr, int size, byte* buffer )
{
UINT CurrentAddr = addr;
int LeftSize = size;
while (LeftSize > 0)
{
//메모리 중에서 현재 메모리를 가진 아이템을 찾는다.
MINIDUMP_MEMORY_DESCRIPTOR valueMemory;
valueMemory.StartOfMemoryRange = CurrentAddr;
std::vector<MINIDUMP_MEMORY_DESCRIPTOR>::iterator iterMem =
std::lower_bound(DumpMemory_.begin(),DumpMemory_.end(),valueMemory,Compare2);
if(iterMem == DumpMemory_.begin())
break;
iterMem--;
int posInRange = CurrentAddr - UINT(iterMem->StartOfMemoryRange);
int availableInRange = iterMem->Memory.DataSize - posInRange;
if (availableInRange <= 0)
break;
if (LeftSize <= availableInRange)
{
memcpy(buffer + (CurrentAddr - addr) ,
pMapping_ + (iterMem->Memory.Rva + posInRange),
LeftSize);
CurrentAddr += LeftSize;
LeftSize = 0;
}
else
{
memcpy(buffer + (CurrentAddr - addr) ,
pMapping_ + (iterMem->Memory.Rva + posInRange),
availableInRange);
CurrentAddr += availableInRange;
LeftSize -= availableInRange;
}
}
return size - LeftSize;
}
void CDumpProcess::OnInitation()
{
}
void CDumpProcess::FIndExceptionCode( DWORD ExceptionCode )
{
switch (ExceptionCode)
{
case STATUS_WAIT_0: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_WAIT_0")); break;
case STATUS_ABANDONED_WAIT_0: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_ABANDONED_WAIT_0")); break;
case STATUS_USER_APC: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_USER_APC")); break;
case STATUS_TIMEOUT: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_TIMEOUT")); break;
case STATUS_PENDING: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_PENDING")); break;
case DBG_EXCEPTION_HANDLED: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("DBG_EXCEPTION_HANDLED")); break;
case DBG_CONTINUE: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("DBG_CONTINUE")); break;
case STATUS_SEGMENT_NOTIFICATION: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_SEGMENT_NOTIFICATION")); break;
case DBG_TERMINATE_THREAD: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("DBG_TERMINATE_THREAD")); break;
case DBG_TERMINATE_PROCESS: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("DBG_TERMINATE_PROCESS")); break;
case DBG_CONTROL_C: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("DBG_CONTROL_C")); break;
case DBG_CONTROL_BREAK: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("DBG_CONTROL_BREAK")); break;
case DBG_COMMAND_EXCEPTION: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("DBG_COMMAND_EXCEPTION")); break;
case STATUS_GUARD_PAGE_VIOLATION: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_GUARD_PAGE_VIOLATION")); break;
case STATUS_DATATYPE_MISALIGNMENT: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_DATATYPE_MISALIGNMENT")); break;
case STATUS_BREAKPOINT: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_BREAKPOINT")); break;
case STATUS_SINGLE_STEP: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_SINGLE_STEP")); break;
case DBG_EXCEPTION_NOT_HANDLED: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("DBG_EXCEPTION_NOT_HANDLED")); break;
case STATUS_ACCESS_VIOLATION: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_ACCESS_VIOLATION")); break;
case STATUS_IN_PAGE_ERROR: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_IN_PAGE_ERROR")); break;
case STATUS_INVALID_HANDLE: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_INVALID_HANDLE")); break;
case STATUS_NO_MEMORY: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_NO_MEMORY")); break;
case STATUS_ILLEGAL_INSTRUCTION: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_ILLEGAL_INSTRUCTION")); break;
case STATUS_NONCONTINUABLE_EXCEPTION: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_NONCONTINUABLE_EXCEPTION")); break;
case STATUS_INVALID_DISPOSITION: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_INVALID_DISPOSITION")); break;
case STATUS_ARRAY_BOUNDS_EXCEEDED: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_ARRAY_BOUNDS_EXCEEDED")); break;
case STATUS_FLOAT_DENORMAL_OPERAND: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_FLOAT_DENORMAL_OPERAND")); break;
case STATUS_FLOAT_DIVIDE_BY_ZERO: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_FLOAT_DIVIDE_BY_ZERO")); break;
case STATUS_FLOAT_INEXACT_RESULT: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_FLOAT_INEXACT_RESULT")); break;
case STATUS_FLOAT_INVALID_OPERATION: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_FLOAT_INVALID_OPERATION")); break;
case STATUS_FLOAT_OVERFLOW: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_FLOAT_OVERFLOW")); break;
case STATUS_FLOAT_STACK_CHECK: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_FLOAT_STACK_CHECK")); break;
case STATUS_FLOAT_UNDERFLOW: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_FLOAT_UNDERFLOW")); break;
case STATUS_INTEGER_DIVIDE_BY_ZERO: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_INTEGER_DIVIDE_BY_ZERO")); break;
case STATUS_INTEGER_OVERFLOW: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_INTEGER_OVERFLOW")); break;
case STATUS_PRIVILEGED_INSTRUCTION: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_PRIVILEGED_INSTRUCTION")); break;
case STATUS_STACK_OVERFLOW: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_STACK_OVERFLOW")); break;
case STATUS_CONTROL_C_EXIT: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_CONTROL_C_EXIT")); break;
case STATUS_FLOAT_MULTIPLE_FAULTS: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_FLOAT_MULTIPLE_FAULTS")); break;
case STATUS_FLOAT_MULTIPLE_TRAPS: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_FLOAT_MULTIPLE_TRAPS")); break;
case STATUS_REG_NAT_CONSUMPTION: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_REG_NAT_CONSUMPTION")); break;
case STATUS_SXS_EARLY_DEACTIVATION: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_SXS_EARLY_DEACTIVATION")); break;
case STATUS_SXS_INVALID_DEACTIVATION: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_SXS_INVALID_DEACTIVATION")); break;
case 0xE06D7363: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("Microsoft C++ Exception")); break;
default: _stprintf_s(stringExceptionCause_, 256, _T("0x%08X"), ExceptionCode);
}
}
TCHAR* CDumpProcess::GetVersion(const _TCHAR* filename)
{
TCHAR* string_buffer;
const int kVersion_Depth = 15; //strlen("120104_0410.dmp")
string_buffer = _tcsstr(_tcslwr((_TCHAR*)filename), L"sungame_");
int string_length = 0;
if (string_buffer)
{
string_length = (int)_tcslen(string_buffer);
}
if (string_length - kVersion_Depth >= 0)
{
_TCHAR* string_pointer = string_buffer + (string_length - kVersion_Depth);
wsprintf(version_string, L"webzen@%d", _tstoi(string_pointer));
}
else
{
wsprintf(version_string, L"webzen@version");
}
return version_string;
}
bool CDumpProcess::decodeDumpfile( const TCHAR* DumpNmae )
{
AuMD5Encrypt Decoder;
std::fstream file;
file.open(DumpNmae, std::ios::in | std::ios::out | std::ios::binary);
if (!file)
{
MessageBox(NULL,L"파일을 열수 없습니다",L"오류",MB_OK);
return false;
}
file.seekg(0, std::ios::end);
size_t size = file.tellg();
char* buffer = new char[size];
file.seekg(0, std::ios::beg);
file.read(buffer, (unsigned int)size);
TCHAR* VersionString = GetVersion(DumpNmae);
char TempVersion[256];
WideCharToMultiByte ( CP_ACP, 0, VersionString, -1, TempVersion, 256, NULL, NULL );
if (!Decoder.DecryptString(TempVersion, buffer, (unsigned int)size))
{
TCHAR ErrorData[256];
wsprintf(ErrorData,L"DecryptString 에러(%s)",DumpNmae);
MessageBox(NULL,ErrorData,L"오류",MB_OK);
return false;
}
file.seekp(0, std::ios::beg);
file.write(buffer, (unsigned int)size);
file.close();
if (buffer)
{
delete[] buffer;
}
return true;
}