mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 11:38:21 +02:00
913 lines
22 KiB
C++
913 lines
22 KiB
C++
#include "BlCvTypeSource.h"
|
|
#include "BlContext.h"
|
|
#include "codeview/cvinfo.h"
|
|
#include "BlCvParser.h"
|
|
#include "BlPdbParser.h"
|
|
#include "BlCodeView.h"
|
|
|
|
#define GET(T) *((T*)(data += sizeof(T)) - 1)
|
|
#define GET_INTO(T, name) T name = GET(T)
|
|
#define PTR_ALIGN(ptr, origPtr, alignSize) ptr = ( (origPtr)+( ((ptr - origPtr) + (alignSize - 1)) & ~(alignSize - 1) ) )
|
|
|
|
USING_NS_BF;
|
|
|
|
static int sIdx = 0;
|
|
|
|
BlCvTypeContainer::BlCvTypeContainer()
|
|
{
|
|
mSectionData = NULL;
|
|
mSectionSize = 0;
|
|
mCvMinTag = -1;
|
|
mCvMaxTag = -1;
|
|
mCodeView = NULL;
|
|
mOutTypeInfo = NULL;
|
|
mIdx = sIdx++;
|
|
}
|
|
|
|
BlCvTypeContainer::~BlCvTypeContainer()
|
|
{
|
|
|
|
}
|
|
|
|
void BlCvTypeContainer::Fail(const StringImpl& err)
|
|
{
|
|
BF_FATAL("Err");
|
|
}
|
|
|
|
const char* BlCvTypeContainer::CvParseAndDupString(uint8*& data, bool hasUniqueName)
|
|
{
|
|
const char* strStart = (const char*)data;
|
|
int strLen = (int)strlen((const char*)data);
|
|
if (strLen == 0)
|
|
return NULL;
|
|
data += strLen + 1;
|
|
if (hasUniqueName)
|
|
{
|
|
strLen = (int)strlen((const char*)data);
|
|
data += strLen + 1;
|
|
}
|
|
char* retVal = (char*)mCodeView->mAlloc.AllocBytes((int)(data - (uint8*)strStart));
|
|
memcpy(retVal, strStart, data - (uint8*)strStart);
|
|
return retVal;
|
|
}
|
|
|
|
int BlCvTypeContainer::CreateMasterTag(int tagId, BlTypeInfo* outTypeInfo)
|
|
{
|
|
#define DECL_LEAF(leafType, leafName) \
|
|
leafType& leafName = *(leafType*)&outBuffer[2];
|
|
#define FIXTPI(varName) \
|
|
varName = GetMasterTPITag(varName);
|
|
#define FIXIPI(varName) \
|
|
varName = GetMasterIPITag(varName);
|
|
|
|
uint8* sectionData = mSectionData; //mCvTypeSectionData;
|
|
|
|
uint8* srcDataStart = sectionData + mCvTagStartMap[tagId - mCvMinTag];
|
|
int16 tagLen = *(int16*)(srcDataStart - 2);
|
|
uint8* srcDataEnd = srcDataStart + tagLen;
|
|
|
|
int outSize = (int)(srcDataEnd - srcDataStart) + 2;
|
|
uint8 outBuffer[0x10000];
|
|
memcpy(outBuffer, srcDataStart - 2, outSize);
|
|
uint8* data = (uint8*)outBuffer + 2;
|
|
uint8* dataEnd = data + tagLen;
|
|
|
|
int16 trLeafType = GET(uint16);
|
|
|
|
BF_ASSERT(((intptr)data) % 4 == 0);
|
|
|
|
switch (trLeafType)
|
|
{
|
|
case LF_VTSHAPE:
|
|
break;
|
|
case LF_LABEL:
|
|
break;
|
|
case LF_STRUCTURE:
|
|
case LF_CLASS:
|
|
{
|
|
DECL_LEAF(lfClass, classInfo);
|
|
FIXTPI(classInfo.derived);
|
|
FIXTPI(classInfo.field);
|
|
FIXTPI(classInfo.vshape);
|
|
}
|
|
break;
|
|
case LF_ENUM:
|
|
{
|
|
DECL_LEAF(lfEnum, enumInfo);
|
|
FIXTPI(enumInfo.field);
|
|
}
|
|
break;
|
|
case LF_UNION:
|
|
{
|
|
DECL_LEAF(lfUnion, unionInfo);
|
|
FIXTPI(unionInfo.field);
|
|
}
|
|
break;
|
|
case LF_ARRAY:
|
|
{
|
|
DECL_LEAF(lfArray, arrayInfo);
|
|
FIXTPI(arrayInfo.elemtype);
|
|
FIXTPI(arrayInfo.idxtype);
|
|
}
|
|
break;
|
|
case LF_POINTER:
|
|
{
|
|
DECL_LEAF(lfPointer, pointerInfo);
|
|
FIXTPI(pointerInfo.utype);
|
|
if ((pointerInfo.attr.ptrmode == CV_PTR_MODE_PMEM) || (pointerInfo.attr.ptrmode == CV_PTR_MODE_PMFUNC))
|
|
{
|
|
FIXTPI(pointerInfo.pbase.pm.pmclass);
|
|
}
|
|
else if (pointerInfo.attr.ptrmode == CV_PTR_BASE_TYPE)
|
|
{
|
|
FIXTPI(pointerInfo.pbase.btype.index);
|
|
}
|
|
}
|
|
break;
|
|
case LF_MODIFIER:
|
|
{
|
|
DECL_LEAF(lfModifier, modifierInfo);
|
|
FIXTPI(modifierInfo.type);
|
|
}
|
|
break;
|
|
case LF_MFUNCTION:
|
|
{
|
|
DECL_LEAF(lfMFunc, func);
|
|
FIXTPI(func.rvtype);
|
|
FIXTPI(func.classtype);
|
|
FIXTPI(func.thistype);
|
|
FIXTPI(func.arglist);
|
|
}
|
|
break;
|
|
case LF_PROCEDURE:
|
|
{
|
|
DECL_LEAF(lfProc, proc);
|
|
FIXTPI(proc.rvtype);
|
|
FIXTPI(proc.arglist);
|
|
}
|
|
break;
|
|
case LF_FIELDLIST:
|
|
{
|
|
while (data < dataEnd)
|
|
{
|
|
static int itrIdx = 0;
|
|
itrIdx++;
|
|
|
|
uint8* leafDataStart = data;
|
|
int leafType = (int)GET(uint16);
|
|
switch (leafType)
|
|
{
|
|
case LF_VFUNCTAB:
|
|
{
|
|
lfVFuncTab& vfuncTab = *(lfVFuncTab*)leafDataStart;
|
|
FIXTPI(vfuncTab.type);
|
|
data = (uint8*)(&vfuncTab + 1);
|
|
}
|
|
break;
|
|
case LF_BCLASS:
|
|
{
|
|
lfBClass& baseClassInfo = *(lfBClass*)leafDataStart;
|
|
data = (uint8*)&baseClassInfo.offset;
|
|
int thisOffset = (int)BlCvParser::CvParseConstant(data);
|
|
FIXTPI(baseClassInfo.index);
|
|
}
|
|
break;
|
|
case LF_VBCLASS:
|
|
case LF_IVBCLASS:
|
|
{
|
|
lfVBClass& baseClassInfo = *(lfVBClass*)leafDataStart;
|
|
data = (uint8*)&baseClassInfo.vbpoff;
|
|
int thisOffset = (int)BlCvParser::CvParseConstant(data);
|
|
int vTableOffset = (int)BlCvParser::CvParseConstant(data);
|
|
FIXTPI(baseClassInfo.index);
|
|
FIXTPI(baseClassInfo.vbptr);
|
|
}
|
|
break;
|
|
case LF_ENUMERATE:
|
|
{
|
|
CV_fldattr_t fieldAttr = GET(CV_fldattr_t);
|
|
int64 fieldVal = BlCvParser::CvParseConstant(data);
|
|
const char* fieldName = BlCvParser::CvParseString(data);
|
|
}
|
|
break;
|
|
case LF_NESTTYPE:
|
|
{
|
|
lfNestType& nestType = *(lfNestType*)leafDataStart;
|
|
FIXTPI(nestType.index);
|
|
data = (uint8*)&nestType.Name;
|
|
const char* typeName = BlCvParser::CvParseString(data);
|
|
}
|
|
break;
|
|
case LF_ONEMETHOD:
|
|
{
|
|
lfOneMethod& oneMethod = *(lfOneMethod*)leafDataStart;
|
|
FIXTPI(oneMethod.index);
|
|
data = (uint8*)&oneMethod.vbaseoff;
|
|
int virtOffset = -1;
|
|
if ((oneMethod.attr.mprop == CV_MTintro) || (oneMethod.attr.mprop == CV_MTpureintro))
|
|
{
|
|
virtOffset = GET(int32);
|
|
}
|
|
const char* methodName = BlCvParser::CvParseString(data);
|
|
}
|
|
break;
|
|
case LF_METHOD:
|
|
{
|
|
lfMethod& method = *(lfMethod*)leafDataStart;
|
|
FIXTPI(method.mList);
|
|
data = (uint8*)&method.Name;
|
|
const char* methodName = BlCvParser::CvParseString(data);
|
|
}
|
|
break;
|
|
case LF_MEMBER:
|
|
case LF_STMEMBER:
|
|
{
|
|
lfMember& member = *(lfMember*)leafDataStart;
|
|
FIXTPI(member.index);
|
|
bool isStatic = leafType == LF_STMEMBER;
|
|
data = (uint8*)&member.offset;
|
|
int memberOffset = -1;
|
|
if (!isStatic)
|
|
{
|
|
memberOffset = (int)BlCvParser::CvParseConstant(data);
|
|
//
|
|
}
|
|
char* fieldName = (char*)BlCvParser::CvParseString(data);
|
|
}
|
|
break;
|
|
default:
|
|
BF_FATAL("Unhandled");
|
|
}
|
|
|
|
PTR_ALIGN(data, outBuffer, 4);
|
|
//BF_ASSERT(((intptr)data) % 4 == 0);
|
|
}
|
|
}
|
|
break;
|
|
case LF_ARGLIST:
|
|
{
|
|
int argCount = GET(int32);
|
|
for (int argIdx = 0; argIdx < argCount; argIdx++)
|
|
{
|
|
CV_typ_t& argTypeId = GET(CV_typ_t);
|
|
FIXTPI(argTypeId);
|
|
}
|
|
}
|
|
break;
|
|
case LF_METHODLIST:
|
|
{
|
|
while (data < dataEnd)
|
|
{
|
|
mlMethod& method = *(mlMethod*)data;
|
|
FIXTPI(method.index);
|
|
data = (uint8*)method.vbaseoff;
|
|
if ((method.attr.mprop == CV_MTintro) || (method.attr.mprop == CV_MTpureintro))
|
|
{
|
|
int virtOffset = GET(int32);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case LF_STRING_ID:
|
|
break;
|
|
case LF_SUBSTR_LIST:
|
|
{
|
|
DECL_LEAF(lfArgList, argList);
|
|
data = (uint8*)&argList.arg;
|
|
for (int idx = 0; idx < (int)argList.count; idx++)
|
|
{
|
|
CV_ItemId& itemId = GET(CV_ItemId);
|
|
FIXIPI(itemId);
|
|
}
|
|
}
|
|
break;
|
|
case LF_UDT_SRC_LINE:
|
|
{
|
|
DECL_LEAF(lfUdtSrcLine, udtSrcLine);
|
|
udtSrcLine.leaf = LF_UDT_MOD_SRC_LINE;
|
|
FIXTPI(udtSrcLine.type);
|
|
FIXIPI(udtSrcLine.src);
|
|
|
|
lfUdtModSrcLine& udtModSrcLine = *(lfUdtModSrcLine*)&udtSrcLine;
|
|
udtModSrcLine.imod = 1;
|
|
outSize += 4;
|
|
*(int16*)(outBuffer) += 4;
|
|
}
|
|
break;
|
|
case LF_FUNC_ID:
|
|
{
|
|
DECL_LEAF(lfFuncId, funcId);
|
|
FIXIPI(funcId.scopeId);
|
|
FIXTPI(funcId.type);
|
|
}
|
|
break;
|
|
case LF_MFUNC_ID:
|
|
{
|
|
DECL_LEAF(lfMFuncId, mfuncId);
|
|
FIXTPI(mfuncId.parentType);
|
|
FIXTPI(mfuncId.type);
|
|
}
|
|
break;
|
|
case LF_BUILDINFO:
|
|
{
|
|
DECL_LEAF(lfBuildInfo, buildInfo);
|
|
data = (uint8*)&buildInfo.arg;
|
|
for (int idx = 0; idx < buildInfo.count; idx++)
|
|
{
|
|
CV_ItemId& itemId = GET(CV_ItemId);
|
|
FIXIPI(itemId);
|
|
}
|
|
}
|
|
break;
|
|
case LF_BITFIELD:
|
|
{
|
|
DECL_LEAF(lfBitfield, bitfield);
|
|
FIXTPI(bitfield.type);
|
|
}
|
|
break;
|
|
case LF_VFTABLE:
|
|
{
|
|
DECL_LEAF(lfVftable, vtTable);
|
|
FIXTPI(vtTable.type);
|
|
FIXTPI(vtTable.baseVftable);
|
|
}
|
|
break;
|
|
default:
|
|
NotImpl();
|
|
break;
|
|
}
|
|
|
|
BF_ASSERT(*(int16*)(outBuffer) == outSize - 2);
|
|
outTypeInfo->mData.Write(outBuffer, outSize);
|
|
return outTypeInfo->mCurTagId++;
|
|
}
|
|
|
|
void BlCvTypeContainer::HashName(const char* namePtr, bool hasMangledName, HashContext& hashContext)
|
|
{
|
|
int hashSize = (int)strlen(namePtr);
|
|
if (hasMangledName)
|
|
hashSize += 1 + (int)strlen(namePtr + hashSize + 1);
|
|
hashContext.Mixin(namePtr, hashSize);
|
|
}
|
|
|
|
int BlCvTypeContainer::GetMasterTPITag(int tagId)
|
|
{
|
|
if (tagId == 0)
|
|
return 0;
|
|
if (tagId < mCvMinTag)
|
|
return tagId;
|
|
int masterTag = (*mTPIMap)[tagId - mCvMinTag];
|
|
if (masterTag == -1)
|
|
{
|
|
// Ensure we're TPI
|
|
BF_ASSERT(&mTagMap == mTPIMap);
|
|
ParseTag(tagId);
|
|
masterTag = (*mTPIMap)[tagId - mCvMinTag];
|
|
BF_ASSERT(masterTag != -1);
|
|
return masterTag;
|
|
}
|
|
|
|
BF_ASSERT(masterTag != -1);
|
|
return masterTag;
|
|
}
|
|
|
|
int BlCvTypeContainer::GetMasterIPITag(int tagId)
|
|
{
|
|
if (tagId == 0)
|
|
return 0;
|
|
// Ensure we're IPI
|
|
BF_ASSERT(&mTagMap == mIPIMap);
|
|
if (tagId < mCvMinTag)
|
|
return tagId;
|
|
int typeIdx = mTagMap[tagId - mCvMinTag];
|
|
BF_ASSERT(typeIdx != -1);
|
|
return typeIdx;
|
|
}
|
|
|
|
void BlCvTypeContainer::NotImpl()
|
|
{
|
|
BF_FATAL("NotImpl");
|
|
}
|
|
|
|
void BlCvTypeContainer::ScanTypeData()
|
|
{
|
|
uint8* sectionData = mSectionData;
|
|
int sectionSize = mSectionSize;
|
|
|
|
uint8* data = (uint8*)sectionData;
|
|
uint8* dataEnd = data + sectionSize;
|
|
|
|
if (mCvMinTag == -1)
|
|
{
|
|
mCvMinTag = 0x1000;
|
|
|
|
int tagCountGuess = sectionSize / 128;
|
|
mCvTagStartMap.reserve(tagCountGuess);
|
|
|
|
int tagIdx = mCvMinTag;
|
|
while (data < dataEnd)
|
|
{
|
|
int tagLen = GET(uint16);
|
|
uint8* dataStart = data;
|
|
uint8* dataTagEnd = data + tagLen;
|
|
|
|
mCvTagStartMap.push_back((int)(data - sectionData));
|
|
|
|
data = dataTagEnd;
|
|
tagIdx++;
|
|
}
|
|
mCvMaxTag = tagIdx;
|
|
}
|
|
else
|
|
{
|
|
int tagIdx = mCvMinTag;
|
|
while (data < dataEnd)
|
|
{
|
|
int tagLen = GET(uint16);
|
|
uint8* dataStart = data;
|
|
uint8* dataTagEnd = data + tagLen;
|
|
|
|
mCvTagStartMap[tagIdx - mCvMinTag] = (int)(data - sectionData);
|
|
|
|
data = dataTagEnd;
|
|
tagIdx++;
|
|
}
|
|
}
|
|
}
|
|
|
|
void BlCvTypeContainer::HashTPITag(int tagId, HashContext& hashContext)
|
|
{
|
|
int masterTagId = GetMasterTPITag(tagId);
|
|
hashContext.Mixin(masterTagId);
|
|
}
|
|
|
|
void BlCvTypeContainer::HashIPITag(int tagId, HashContext& hashContext)
|
|
{
|
|
int masterTagId = GetMasterIPITag(tagId);
|
|
hashContext.Mixin(masterTagId);
|
|
}
|
|
|
|
void BlCvTypeContainer::HashTagContent(int tagId, HashContext& hashContext, bool& isIPI)
|
|
{
|
|
uint8* sectionData = mSectionData; //mCvTypeSectionData;
|
|
|
|
uint8* data = sectionData + mCvTagStartMap[tagId - mCvMinTag];
|
|
uint8* dataStart = data;
|
|
int16 tagLen = *(int16*)(data - 2);
|
|
uint8* dataEnd = data + tagLen;
|
|
int16 trLeafType = GET(uint16);
|
|
|
|
hashContext.Mixin(trLeafType);
|
|
|
|
switch (trLeafType)
|
|
{
|
|
case LF_VTSHAPE:
|
|
{
|
|
lfVTShape& vtShape = *(lfVTShape*)dataStart;
|
|
data = (uint8*)&vtShape.desc;
|
|
int shapeBytes = (vtShape.count + 1) / 2;
|
|
hashContext.Mixin(data, shapeBytes);
|
|
}
|
|
break;
|
|
case LF_LABEL:
|
|
{
|
|
lfLabel& label = *(lfLabel*)dataStart;
|
|
hashContext.Mixin(label.mode);
|
|
}
|
|
break;
|
|
case LF_ARGLIST:
|
|
{
|
|
int argCount = (int)GET(int32);
|
|
hashContext.Mixin(argCount);
|
|
for (int argIdx = 0; argIdx < (int)argCount; argIdx++)
|
|
{
|
|
HashTPITag(GET(CV_typ_t), hashContext);
|
|
}
|
|
}
|
|
break;
|
|
case LF_FIELDLIST:
|
|
{
|
|
while (data < dataEnd)
|
|
{
|
|
uint8* leafDataStart = data;
|
|
int leafType = (int)GET(uint16);
|
|
hashContext.Mixin(leafType);
|
|
switch (leafType)
|
|
{
|
|
case LF_VFUNCTAB:
|
|
{
|
|
lfVFuncTab& vfuncTab = *(lfVFuncTab*)leafDataStart;
|
|
HashTPITag(vfuncTab.type, hashContext);
|
|
data = (uint8*)(&vfuncTab + 1);
|
|
}
|
|
break;
|
|
case LF_BCLASS:
|
|
{
|
|
lfBClass& baseClassInfo = *(lfBClass*)leafDataStart;
|
|
data = (uint8*)&baseClassInfo.offset;
|
|
int thisOffset = (int)BlCvParser::CvParseConstant(data);
|
|
hashContext.Mixin(thisOffset);
|
|
HashTPITag(baseClassInfo.index, hashContext);
|
|
}
|
|
break;
|
|
case LF_VBCLASS:
|
|
case LF_IVBCLASS:
|
|
{
|
|
lfVBClass& baseClassInfo = *(lfVBClass*)leafDataStart;
|
|
data = (uint8*)&baseClassInfo.vbpoff;
|
|
int thisOffset = (int)BlCvParser::CvParseConstant(data);
|
|
int vTableOffset = (int)BlCvParser::CvParseConstant(data);
|
|
hashContext.Mixin(baseClassInfo.attr);
|
|
HashTPITag(baseClassInfo.index, hashContext);
|
|
HashTPITag(baseClassInfo.vbptr, hashContext);
|
|
HashTPITag(thisOffset, hashContext);
|
|
HashTPITag(vTableOffset, hashContext);
|
|
}
|
|
break;
|
|
case LF_ENUMERATE:
|
|
{
|
|
CV_fldattr_t fieldAttr = GET(CV_fldattr_t);
|
|
int64 fieldVal = BlCvParser::CvParseConstant(data);
|
|
const char* fieldName = BlCvParser::CvParseString(data);
|
|
hashContext.Mixin(fieldAttr);
|
|
hashContext.Mixin(fieldVal);
|
|
hashContext.MixinStr(fieldName);
|
|
}
|
|
break;
|
|
case LF_NESTTYPE:
|
|
{
|
|
int16 pad = GET(int16);
|
|
int32 nestedTypeId = GET(int32);
|
|
//int64 nestedSize = BlCvParser::CvParseConstant(data);
|
|
const char* typeName = BlCvParser::CvParseString(data);
|
|
HashTPITag(nestedTypeId, hashContext);
|
|
}
|
|
break;
|
|
case LF_ONEMETHOD:
|
|
{
|
|
CV_fldattr_t attr = GET(CV_fldattr_t);
|
|
CV_typ_t methodTypeId = GET(CV_typ_t);
|
|
hashContext.Mixin(attr);
|
|
HashTPITag(methodTypeId, hashContext);
|
|
|
|
int virtOffset = -1;
|
|
if ((attr.mprop == CV_MTintro) || (attr.mprop == CV_MTpureintro))
|
|
{
|
|
virtOffset = GET(int32);
|
|
hashContext.Mixin(virtOffset);
|
|
}
|
|
const char* name = BlCvParser::CvParseString(data);
|
|
hashContext.MixinStr(name);
|
|
}
|
|
break;
|
|
case LF_METHOD:
|
|
{
|
|
int count = (int)GET(uint16);
|
|
int32 methodList = GET(int32);
|
|
const char* name = BlCvParser::CvParseString(data);
|
|
hashContext.MixinStr(name);
|
|
}
|
|
break;
|
|
case LF_MEMBER:
|
|
case LF_STMEMBER:
|
|
{
|
|
bool isStatic = leafType == LF_STMEMBER;
|
|
bool isConst = false;
|
|
CV_fldattr_t attr = GET(CV_fldattr_t);
|
|
CV_typ_t fieldTypeId = GET(CV_typ_t);
|
|
hashContext.Mixin(attr);
|
|
|
|
int memberOffset = -1;
|
|
if (!isStatic)
|
|
{
|
|
memberOffset = (int)BlCvParser::CvParseConstant(data);
|
|
hashContext.Mixin(memberOffset);
|
|
}
|
|
const char* name = BlCvParser::CvParseString(data);
|
|
hashContext.MixinStr(name);
|
|
HashTPITag(fieldTypeId, hashContext);
|
|
}
|
|
break;
|
|
default:
|
|
BF_FATAL("Unhandled");
|
|
}
|
|
|
|
PTR_ALIGN(data, sectionData, 4);
|
|
}
|
|
}
|
|
break;
|
|
case LF_METHODLIST:
|
|
{
|
|
while (data < dataEnd)
|
|
{
|
|
mlMethod& method = *(mlMethod*)data;
|
|
bool tempBool = false;
|
|
HashTagContent(method.index, hashContext, tempBool);
|
|
data = (uint8*)method.vbaseoff;
|
|
if ((method.attr.mprop == CV_MTintro) || (method.attr.mprop == CV_MTpureintro))
|
|
{
|
|
int virtOffset = GET(int32);
|
|
hashContext.Mixin(virtOffset);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case LF_STRUCTURE:
|
|
case LF_CLASS:
|
|
{
|
|
lfClass& classInfo = *(lfClass*)dataStart;
|
|
data = (uint8*)&classInfo.data;
|
|
int dataSize = (int)BlCvParser::CvParseConstant(data);
|
|
HashName((char*)data, classInfo.property.hasuniquename, hashContext);
|
|
hashContext.Mixin(dataSize);
|
|
hashContext.Mixin(classInfo.property);
|
|
HashTPITag(classInfo.field, hashContext);
|
|
HashTPITag(classInfo.derived, hashContext);
|
|
HashTPITag(classInfo.vshape, hashContext);
|
|
}
|
|
break;
|
|
case LF_ENUM:
|
|
{
|
|
lfEnum& enumInfo = *(lfEnum*)dataStart;
|
|
data = (uint8*)enumInfo.Name;
|
|
HashName((char*)data, enumInfo.property.hasuniquename, hashContext);
|
|
hashContext.Mixin(enumInfo.property);
|
|
HashTPITag(enumInfo.utype, hashContext);
|
|
HashTPITag(enumInfo.field, hashContext);
|
|
}
|
|
break;
|
|
case LF_UNION:
|
|
{
|
|
lfUnion& unionInfo = *(lfUnion*)dataStart;
|
|
data = (uint8*)unionInfo.data;
|
|
int dataSize = (int)BlCvParser::CvParseConstant(data);
|
|
HashName((char*)data, unionInfo.property.hasuniquename, hashContext);
|
|
hashContext.Mixin(dataSize);
|
|
hashContext.Mixin(unionInfo.property);
|
|
HashTPITag(unionInfo.field, hashContext);
|
|
}
|
|
break;
|
|
case LF_ARRAY:
|
|
{
|
|
lfArray& arrayInfo = *(lfArray*)dataStart;
|
|
data = (uint8*)arrayInfo.data;
|
|
int dataSize = (int)BlCvParser::CvParseConstant(data);
|
|
HashName((char*)data, false, hashContext);
|
|
HashTPITag(arrayInfo.elemtype, hashContext);
|
|
HashTPITag(arrayInfo.idxtype, hashContext);
|
|
}
|
|
break;
|
|
case LF_MFUNCTION:
|
|
{
|
|
lfMFunc& func = *(lfMFunc*)dataStart;
|
|
HashTPITag(func.thistype, hashContext);
|
|
HashTPITag(func.classtype, hashContext);
|
|
HashTPITag(func.rvtype, hashContext);
|
|
HashTPITag(func.arglist, hashContext);
|
|
hashContext.Mixin(func.funcattr);
|
|
hashContext.Mixin(func.calltype);
|
|
hashContext.Mixin(func.parmcount);
|
|
hashContext.Mixin(func.thisadjust);
|
|
}
|
|
break;
|
|
case LF_PROCEDURE:
|
|
{
|
|
lfProc& proc = *(lfProc*)dataStart;
|
|
HashTPITag(proc.rvtype, hashContext);
|
|
HashTPITag(proc.arglist, hashContext);
|
|
hashContext.Mixin(proc.funcattr);
|
|
hashContext.Mixin(proc.calltype);
|
|
hashContext.Mixin(proc.parmcount);
|
|
}
|
|
break;
|
|
case LF_POINTER:
|
|
{
|
|
lfPointer& pointerInfo = *(lfPointer*)dataStart;
|
|
HashTPITag(pointerInfo.utype, hashContext);
|
|
hashContext.Mixin(pointerInfo.attr);
|
|
}
|
|
break;
|
|
case LF_MODIFIER:
|
|
{
|
|
lfModifier& modifierInfo = *(lfModifier*)dataStart;
|
|
HashTPITag(modifierInfo.type, hashContext);
|
|
hashContext.Mixin(modifierInfo.attr);
|
|
}
|
|
break;
|
|
case LF_STRING_ID:
|
|
{
|
|
isIPI = true;
|
|
lfStringId& stringId = *(lfStringId*)dataStart;
|
|
HashIPITag(stringId.id, hashContext);
|
|
HashName((char*)stringId.name, false, hashContext);
|
|
}
|
|
break;
|
|
case LF_SUBSTR_LIST:
|
|
{
|
|
lfArgList& argList = *(lfArgList*)dataStart;
|
|
data = (uint8*)&argList.arg;
|
|
for (int idx = 0; idx < (int)argList.count; idx++)
|
|
{
|
|
CV_ItemId& itemId = GET(CV_ItemId);
|
|
HashIPITag(itemId, hashContext);
|
|
}
|
|
}
|
|
break;
|
|
case LF_UDT_SRC_LINE:
|
|
{
|
|
lfUdtSrcLine& srcLine = *(lfUdtSrcLine*)dataStart;
|
|
HashTPITag(srcLine.type, hashContext);
|
|
HashIPITag(srcLine.src, hashContext);
|
|
}
|
|
break;
|
|
case LF_FUNC_ID:
|
|
{
|
|
isIPI = true;
|
|
lfFuncId& funcId = *(lfFuncId*)dataStart;
|
|
HashIPITag(funcId.scopeId, hashContext);
|
|
HashTPITag(funcId.type, hashContext);
|
|
HashName((char*)funcId.name, false, hashContext);
|
|
}
|
|
break;
|
|
case LF_MFUNC_ID:
|
|
{
|
|
isIPI = true;
|
|
lfMFuncId& mfuncId = *(lfMFuncId*)dataStart;
|
|
HashTPITag(mfuncId.parentType, hashContext);
|
|
HashTPITag(mfuncId.type, hashContext);
|
|
HashName((char*)mfuncId.name, false, hashContext);
|
|
}
|
|
break;
|
|
case LF_BUILDINFO:
|
|
{
|
|
lfBuildInfo& buildInfo = *(lfBuildInfo*)dataStart;
|
|
data = (uint8*)&buildInfo.arg;
|
|
for (int idx = 0; idx < (int)buildInfo.count; idx++)
|
|
{
|
|
CV_ItemId& itemId = GET(CV_ItemId);
|
|
HashIPITag(itemId, hashContext);
|
|
}
|
|
}
|
|
break;
|
|
case LF_BITFIELD:
|
|
{
|
|
lfBitfield& bitfield = *(lfBitfield*)dataStart;
|
|
HashTPITag(bitfield.type, hashContext);
|
|
hashContext.Mixin(bitfield.length);
|
|
hashContext.Mixin(bitfield.position);
|
|
}
|
|
break;
|
|
case LF_VFTABLE:
|
|
{
|
|
lfVftable& vtTable = *(lfVftable*)dataStart;
|
|
HashTPITag(vtTable.type, hashContext);
|
|
HashTPITag(vtTable.baseVftable, hashContext);
|
|
hashContext.Mixin(vtTable.offsetInObjectLayout);
|
|
data = (uint8*)&vtTable.Names;
|
|
hashContext.Mixin(data, vtTable.len);
|
|
}
|
|
break;
|
|
default:
|
|
NotImpl();
|
|
break;
|
|
}
|
|
}
|
|
|
|
void BlCvTypeContainer::ParseTag(int tagId, bool forceFull)
|
|
{
|
|
uint8* data = mSectionData + mCvTagStartMap[tagId - mCvMinTag];
|
|
uint8* dataStart = data;
|
|
int16 tagLen = *(int16*)(data - 2);
|
|
uint8* dataEnd = data + tagLen;
|
|
int16 trLeafType = GET(uint16);
|
|
|
|
//TODO: Bad? Good?
|
|
//forceFull = true;
|
|
|
|
bool wantsExt = false;
|
|
int memberMasterTag = 0;
|
|
switch (trLeafType)
|
|
{
|
|
case LF_FUNC_ID:
|
|
{
|
|
mCodeView->mStat_ParseTagFuncs++;
|
|
|
|
wantsExt = true;
|
|
lfFuncId& funcId = *(lfFuncId*)dataStart;
|
|
int memberTagId = GetMasterTPITag(funcId.type);
|
|
mElementMap[tagId - mCvMinTag] = memberTagId;
|
|
|
|
/*if (!forceFull)
|
|
{
|
|
mTagMap[tagId - mCvMinTag] = memberMasterTag | BlTypeMapFlag_InfoExt_ProcId_TypeOnly;
|
|
return;
|
|
}*/
|
|
|
|
//return;
|
|
}
|
|
break;
|
|
case LF_MFUNC_ID:
|
|
{
|
|
mCodeView->mStat_ParseTagFuncs++;
|
|
|
|
wantsExt = true;
|
|
lfMFuncId& funcId = *(lfMFuncId*)dataStart;
|
|
|
|
int memberTagId = GetMasterTPITag(funcId.type);
|
|
mElementMap[tagId - mCvMinTag] = memberTagId;
|
|
/*if (!forceFull)
|
|
{
|
|
mTagMap[tagId - mCvMinTag] = memberMasterTag | BlTypeMapFlag_InfoExt_ProcId_TypeOnly;
|
|
return;
|
|
}*/
|
|
|
|
//return;
|
|
|
|
}
|
|
break;
|
|
}
|
|
|
|
HashContext hashContext;
|
|
bool isIPI = false;
|
|
HashTagContent(tagId, hashContext, isIPI);
|
|
auto outTypeInfo = mOutTypeInfo;
|
|
if (isIPI)
|
|
outTypeInfo = &mCodeView->mIPI;
|
|
|
|
mCodeView->mStat_TypeMapInserts++;
|
|
|
|
Val128 hashVal = hashContext.Finish128();
|
|
|
|
int masterTagId;
|
|
auto insertPair = outTypeInfo->mTypeMap.insert(std::make_pair(hashVal, -1));
|
|
if (insertPair.second)
|
|
{
|
|
masterTagId = CreateMasterTag(tagId, outTypeInfo);
|
|
insertPair.first->second = masterTagId;
|
|
}
|
|
else
|
|
{
|
|
masterTagId = insertPair.first->second;
|
|
}
|
|
|
|
/*if (wantsExt)
|
|
{
|
|
mTagMap[tagId - mCvMinTag] = (int)mInfoExts.size() | BlTypeMapFlag_InfoExt_ProcId_Resolved;
|
|
|
|
BlCvTypeInfoExt infoExt;
|
|
infoExt.mMasterTag = masterTagId;
|
|
infoExt.mMemberMasterTag = memberMasterTag;
|
|
mInfoExts.push_back(infoExt);
|
|
}
|
|
else*/
|
|
mTagMap[tagId - mCvMinTag] = masterTagId;
|
|
}
|
|
|
|
void BlCvTypeContainer::ParseTypeData()
|
|
{
|
|
mTagMap.insert(mTagMap.begin(), mCvTagStartMap.size(), -1);
|
|
mElementMap.insert(mElementMap.begin(), mCvTagStartMap.size(), -1);
|
|
for (int tagId = mCvMinTag; tagId < mCvMaxTag; tagId++)
|
|
{
|
|
if (mTagMap[tagId - mCvMinTag] == -1)
|
|
ParseTag(tagId);
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
BlCvTypeSource::BlCvTypeSource()
|
|
{
|
|
mTypeServerLib = NULL;
|
|
mIPI = NULL;
|
|
mIsDone = false;
|
|
mObjectData = NULL;
|
|
}
|
|
|
|
BlCvTypeSource::~BlCvTypeSource()
|
|
{
|
|
delete mTypeServerLib;
|
|
if (mIPI != &mTPI)
|
|
delete mIPI;
|
|
}
|
|
|
|
void BlCvTypeSource::CreateIPI()
|
|
{
|
|
auto codeView = mTPI.mCodeView;
|
|
|
|
BF_ASSERT(mIPI == &mTPI);
|
|
mIPI = new BlCvTypeContainer();
|
|
mIPI->mCodeView = codeView;
|
|
mIPI->mOutTypeInfo = &codeView->mIPI;
|
|
mIPI->mTPIMap = &mTPI.mTagMap;
|
|
mIPI->mIPIMap = &mIPI->mTagMap;
|
|
}
|
|
|
|
void BlCvTypeSource::Init(BlCodeView* codeView)
|
|
{
|
|
mTPI.mCodeView = codeView;
|
|
mTPI.mOutTypeInfo = &codeView->mTPI;
|
|
mTPI.mTPIMap = &mTPI.mTagMap;
|
|
mTPI.mIPIMap = &mTPI.mTagMap;
|
|
mIPI = &mTPI;
|
|
}
|