Files
2022-10-26 12:25:11 +08:00

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()
{
}