434 lines
12 KiB
C++
434 lines
12 KiB
C++
#include "StdAfx.h"
|
|
#include "MapProcess.h"
|
|
|
|
CMapProcess::CMapProcess(void) : LoadBaseAddress_(0x0000000)
|
|
{
|
|
FuntionList_.clear();
|
|
LineinfoList_.clear();
|
|
}
|
|
|
|
CMapProcess::~CMapProcess(void)
|
|
{
|
|
Clean();
|
|
}
|
|
|
|
bool CMapProcess::LoadFile( const TCHAR* SymbolName )
|
|
{
|
|
|
|
FILE* fp = NULL;
|
|
fp = _tfopen(SymbolName,L"rt");
|
|
|
|
if(fp == NULL)
|
|
return false;
|
|
|
|
if(!GetLoadBaseAddress(fp))
|
|
return false;
|
|
|
|
if(!ReadAddress(fp))
|
|
return false;
|
|
|
|
if(!ReadSourceLine(fp))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
void CMapProcess::Clean()
|
|
{
|
|
FuntionList_.clear();
|
|
LineinfoList_.clear();
|
|
LoadBaseAddress_ = 0x000000;
|
|
}
|
|
|
|
bool CMapProcess::OnSearch( const char* ExceptionAddr,sExceptionInfomation& ExceptionInfo )
|
|
{
|
|
DWORD dwordExceptionAddr = GetHexValue(ExceptionAddr);
|
|
|
|
return OnSearch(dwordExceptionAddr,ExceptionInfo);
|
|
}
|
|
|
|
bool CMapProcess::OnSearch( DWORD ExceptionAddr , sExceptionInfomation& ExceptionInfo )
|
|
{
|
|
size_t funtioncount = FuntionList_.size();
|
|
|
|
for (size_t index = 0 ; index < funtioncount ; ++index)
|
|
{
|
|
if(ExceptionAddr < FuntionList_[index].FuntionAddress)
|
|
{
|
|
//첫 function주소는 핸들러임 처리 하지 않아도 상관 없음!
|
|
if(index == 0)
|
|
return false;;
|
|
|
|
sFuntionInfo* pFunctionSelect = &FuntionList_[index -1];
|
|
wsprintf(ExceptionInfo.ExceptionFuntionName,L"%s",pFunctionSelect->FuntionName);
|
|
ExceptionInfo.HeaderFile = pFunctionSelect->HeaderFile;
|
|
|
|
size_t LineCount = LineinfoList_.size();
|
|
for (size_t lineindex = 0 ; lineindex < LineCount ; ++lineindex)
|
|
{
|
|
if (wcsstr(LineinfoList_[lineindex].ObjectFileName ,
|
|
pFunctionSelect->ObjectFileName))
|
|
{
|
|
sLineInfo* pLineSelect = &LineinfoList_[lineindex];
|
|
wsprintf(ExceptionInfo.ExceptionFileName,L"%s",pLineSelect->SourceFileName);
|
|
|
|
size_t AddressCount = pLineSelect->vAddressLineEntityList.size();
|
|
for (size_t AddrIndex = 0 ; AddrIndex < AddressCount ; ++AddrIndex)
|
|
{
|
|
sLineAndAddressEntity* pEntity = &pLineSelect->vAddressLineEntityList[AddrIndex];
|
|
|
|
if(pLineSelect->vAddressLineEntityList[AddrIndex].LineAddress > ExceptionAddr)
|
|
{
|
|
//윗 주석과 동일
|
|
if(AddrIndex == 0)
|
|
return false;
|
|
|
|
sLineAndAddressEntity* lastSelect = &pLineSelect->vAddressLineEntityList[AddrIndex-1];
|
|
ExceptionInfo.FileSourceLine = lastSelect->SourceLine;
|
|
return true;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
bool CMapProcess::ReadAddress( FILE* fp )
|
|
{
|
|
//메모리 포함값이 1024를 넘었다! 2048이 안전함.
|
|
//만약 함수명이 길고 std::관련 function과 iterator 구분이 같이 들어 간다면.
|
|
// 이 이상의 사이즈도 생각해볼수 있음!
|
|
char LineString[2048];
|
|
|
|
while (!feof(fp))
|
|
{
|
|
fgets(LineString,2048,fp);
|
|
|
|
if(strstr(LineString,"Address Publics by Value Rva+Base Lib:Object"))
|
|
{
|
|
fgets(LineString,2048,fp);
|
|
|
|
while (!feof(fp))
|
|
{
|
|
fgets(LineString,2048,fp);
|
|
|
|
if(LineString[5] != ':')
|
|
return true;
|
|
|
|
//함수 이름 검색 21부터임!
|
|
UINT StringCntCount = 21;
|
|
sFuntionInfo FuntionNode;
|
|
memset(&FuntionNode,0,sizeof(sFuntionInfo));
|
|
|
|
char FuntionName[256];
|
|
memset(FuntionName,0,sizeof(char)*256);
|
|
|
|
//함수 이름 얻기
|
|
if(!GetCutFunctionString(LineString + StringCntCount,FuntionName,
|
|
sizeof(char)*256,StringCntCount))
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
//문자열 변환 multibyte -> unicode
|
|
MultiByteToWideChar(CP_ACP,MB_COMPOSITE,FuntionName,-1,FuntionNode.FuntionName
|
|
,256);
|
|
}
|
|
|
|
//함수 주소 얻기ch
|
|
if (!GetCutAddressString(LineString + StringCntCount , FuntionNode.FuntionAddress
|
|
,StringCntCount))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
StringCntCount++;
|
|
|
|
if (LineString[StringCntCount] != 'f')
|
|
{
|
|
continue;
|
|
}
|
|
|
|
StringCntCount += 2;
|
|
|
|
//i는 헤더 정보임.
|
|
FuntionNode.HeaderFile = (LineString[StringCntCount] == 'i');
|
|
StringCntCount += 2;
|
|
|
|
memset(FuntionName,0,sizeof(char)*256);
|
|
WideCharToMultiByte(CP_ACP,0,FuntionNode.FuntionName,-1,FuntionName,256,NULL,NULL);
|
|
|
|
char FileName[256];
|
|
memset(FileName,0,sizeof(char)*256);
|
|
|
|
//파일 이름 검색
|
|
strncpy(FileName,LineString + StringCntCount,sizeof(char)* 256);
|
|
size_t FileStringLen = strlen(FileName);
|
|
FileName[FileStringLen -1] = NULL;
|
|
|
|
MultiByteToWideChar(CP_ACP,MB_COMPOSITE,FileName,-1,FuntionNode.ObjectFileName
|
|
,256);
|
|
|
|
FuntionList_.push_back(FuntionNode);
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CMapProcess::ReadSourceLine( FILE* fp )
|
|
{
|
|
char LineString[2048];
|
|
|
|
while (!feof(fp))
|
|
{
|
|
fgets(LineString,2048,fp);
|
|
|
|
if(strstr(LineString,"Line numbers for"))
|
|
{
|
|
|
|
sLineInfo LineNode;
|
|
|
|
//오브젝트 이름의 검색은 17번째 부터 임.
|
|
UINT StringCntCount = 17;
|
|
|
|
char ObjectFileName[256];
|
|
memset(ObjectFileName,0,sizeof(char)*256);
|
|
if (!GetLineObjectFileName(LineString + StringCntCount,ObjectFileName,sizeof(char)*256
|
|
,StringCntCount))
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
//문자열 변환 multibyte -> unicode
|
|
MultiByteToWideChar(CP_ACP,MB_COMPOSITE,ObjectFileName,-1,LineNode.ObjectFileName
|
|
,256);
|
|
}
|
|
|
|
StringCntCount++;
|
|
|
|
char SourceFileName[256];
|
|
memset(SourceFileName,0,sizeof(char)*256);
|
|
if (!GetLineSourceName(LineString + StringCntCount,SourceFileName,sizeof(char)*256
|
|
,StringCntCount))
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
//문자열 변환 multibyte -> unicode
|
|
MultiByteToWideChar(CP_ACP,MB_COMPOSITE,SourceFileName,-1,LineNode.SourceFileName
|
|
,256);
|
|
}
|
|
|
|
//사이에 공백 라인 있음!
|
|
fgets(LineString,2048,fp);
|
|
|
|
//하나의 소스 라인 정보
|
|
while ( !feof(fp))
|
|
{
|
|
fgets(LineString,2048,fp);
|
|
if (strlen(LineString) < 2)
|
|
break;
|
|
|
|
//하나의 라인 간격 20자
|
|
size_t LineSpaceLen = strlen(LineString);
|
|
int stringcnt = static_cast<int>(LineSpaceLen) / 20;
|
|
|
|
//한줄에 소스 라인 정보는 4개가 넘지 않음!
|
|
for (int count = 0 ; count < 4 ; ++count)
|
|
{
|
|
sLineAndAddressEntity LineAddrEntity;
|
|
|
|
if(!GetLineAndAddress(LineString,count,LineAddrEntity))
|
|
return false;
|
|
|
|
LineNode.vAddressLineEntityList.push_back(LineAddrEntity);
|
|
}
|
|
}
|
|
|
|
LineinfoList_.push_back(LineNode);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CMapProcess::GetLoadBaseAddress( FILE* fp )
|
|
{
|
|
char szLine[1024];
|
|
while (!feof(fp))
|
|
{
|
|
fgets(szLine,1024,fp);
|
|
if(strstr(szLine," Preferred load address is "))
|
|
{
|
|
char Value[128];
|
|
size_t StringSize = strlen(" Preferred load address is ");
|
|
strcpy(Value,szLine + StringSize);
|
|
|
|
StringSize = strlen(Value);
|
|
Value[StringSize-1] = NULL;
|
|
LoadBaseAddress_ = GetHexValue(Value);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool CMapProcess::GetCutFunctionString( const char* pStringLine, char* pString, size_t stringLen,
|
|
UINT& CutStringCount )
|
|
{
|
|
int count = 0;
|
|
|
|
for (UINT index = 0 ; index < stringLen ; ++index)
|
|
{
|
|
if (pStringLine[index] == ' ' || pStringLine[index] == '@')
|
|
{
|
|
CutStringCount += index;
|
|
pString[index] = NULL;
|
|
return true;
|
|
}
|
|
else if (pStringLine[index] == '?' || pStringLine[index] == '$')
|
|
{
|
|
count = 0;
|
|
|
|
continue;
|
|
}
|
|
|
|
pString[count] = pStringLine[index];
|
|
count++;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool CMapProcess::GetCutAddressString( const char* pStringLine, DWORD& Address,
|
|
UINT& CutStringCount )
|
|
{
|
|
int count = 0;
|
|
bool EndSpace = false;
|
|
|
|
char AddressString[256];
|
|
|
|
UINT index = 0;
|
|
|
|
for (index = 0 ; index < strlen(pStringLine) ; ++index)
|
|
{
|
|
if (EndSpace)
|
|
{
|
|
if(pStringLine[index] == ' ')
|
|
break;
|
|
|
|
AddressString[count] = pStringLine[index];
|
|
count++;
|
|
}
|
|
else if ( pStringLine[index] == ' ' && pStringLine[index + 1] == '0')
|
|
{
|
|
EndSpace = true;
|
|
}
|
|
}
|
|
|
|
if(false == EndSpace)
|
|
return false;
|
|
|
|
CutStringCount += index;
|
|
AddressString[count] = NULL;
|
|
Address = GetHexValue(AddressString);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CMapProcess::GetLineObjectFileName( const char* pStringLine, char* pString, size_t stringLen, UINT& CutStringCount )
|
|
{
|
|
int count = 0;
|
|
|
|
for (UINT index = 0 ; index < stringLen ; ++index)
|
|
{
|
|
if(pStringLine[index] == '(')
|
|
{
|
|
CutStringCount += index;
|
|
pString[count] = NULL;
|
|
return true;
|
|
}
|
|
|
|
pString[count] = pStringLine[index];
|
|
count++;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CMapProcess::GetLineSourceName( const char* pStringLine, char* pString, size_t stringLen, UINT& CutStringCount )
|
|
{
|
|
int count = 0;
|
|
|
|
for (UINT index = 0 ; index < stringLen ; ++index)
|
|
{
|
|
if(pStringLine[index] == ')')
|
|
{
|
|
CutStringCount += index;
|
|
pString[count] = NULL;
|
|
return true;
|
|
}
|
|
|
|
pString[count] = pStringLine[index];
|
|
count++;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CMapProcess::GetLineAndAddress( const char* pStringLine, int numCount, sLineAndAddressEntity& LineEntity )
|
|
{
|
|
//하나의 정보임
|
|
char CutLineString[21];
|
|
int numStart = numCount * 20;
|
|
int CutCount = -1;
|
|
|
|
strncpy(CutLineString,pStringLine+numStart,sizeof(char)*21);
|
|
CutLineString[20] = NULL;
|
|
|
|
//라인 주소 얻기
|
|
for (int index = 0 ; index < 20 ; ++index)
|
|
{
|
|
if(CutLineString[index] == ':')
|
|
{
|
|
//어드레스 값
|
|
LineEntity.LineAddress = GetHexValue(CutLineString+index + 1);
|
|
LineEntity.LineAddress += LoadBaseAddress_;
|
|
LineEntity.LineAddress += 0x10000;
|
|
|
|
for (int sourceIndex = index ; sourceIndex >= 0 ; --sourceIndex)
|
|
{
|
|
if(CutLineString[sourceIndex] == ' ')
|
|
{
|
|
CutLineString[sourceIndex] = NULL;
|
|
LineEntity.SourceLine = atoi(CutLineString);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void CMapProcess::OnInitation()
|
|
{
|
|
|
|
} |