123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537 |
- #include "BlCvParser.h"
- #include "BlContext.h"
- #include "BlCodeView.h"
- #include "codeview/cvinfo.h"
- #include "../COFFData.h"
- #include "BeefySysLib/util/PerfTimer.h"
- USING_NS_BF;
- #define CV_BLOCK_SIZE 0x1000
- #define MSF_SIGNATURE_700 "Microsoft C/C++ MSF 7.00\r\n\032DS\0\0"
- #define GET(T) *((T*)(data += sizeof(T)) - 1)
- #define PTR_ALIGN(ptr, origPtr, alignSize) ptr = ( (origPtr)+( ((ptr - origPtr) + (alignSize - 1)) & ~(alignSize - 1) ) )
- BlCvParser::BlCvParser(BlContext* context)
- {
- mContext = context;
- mCodeView = context->mCodeView;
- mCurModule = NULL;
- mSyms = NULL;
- }
- void BlCvParser::NotImpl()
- {
- }
- void BlCvParser::Fail(const StringImpl& err)
- {
- mContext->Fail(StrFormat("%s in %s", err.c_str(), mContext->ObjectDataIdxToString(mCurModule->mObjectData->mIdx).c_str()));
- }
- int64 BlCvParser::CvParseConstant(uint16 constVal, uint8*& data)
- {
- if (constVal < LF_NUMERIC) // 0x8000
- return constVal;
- switch (constVal)
- {
- case LF_CHAR:
- return GET(int8);
- case LF_SHORT:
- return GET(int16);
- case LF_USHORT:
- return GET(uint16);
- case LF_LONG:
- return GET(int32);
- case LF_ULONG:
- return GET(uint32);
- case LF_QUADWORD:
- return GET(int64);
- case LF_UQUADWORD:
- return (int64)GET(uint64);
- default:
- BF_FATAL("Not handled");
- }
- return 0;
- }
- int64 BlCvParser::CvParseConstant(uint8*& data)
- {
- uint16 val = GET(uint16);
- return CvParseConstant(val, data);
- }
- const char* BlCvParser::CvParseString(uint8*& data)
- {
- const char* strStart = (const char*)data;
- int strLen = (int)strlen((const char*)data);
- data += strLen + 1;
- if (strLen == 0)
- return NULL;
- return strStart;
- }
- bool BlCvParser::MapAddress(void* symbolData, void* cvLoc, BlReloc& outReloc, COFFRelocation*& nextReloc)
- {
- int posOfs = (int)((uint8*)cvLoc - (uint8*)symbolData);
- int posSect = (int)((uint8*)cvLoc + 4 - (uint8*)symbolData);
- if (nextReloc->mVirtualAddress != posOfs)
- {
- outReloc.mFlags = (BeRelocFlags)0;
- outReloc.mSymName = NULL;
- return false;
- }
- auto sym = &(*mSyms)[nextReloc->mSymbolTableIndex];
- if (sym->mSym != NULL)
- {
- outReloc.mFlags = BeRelocFlags_Sym;
- outReloc.mSym = sym->mSym;
- }
- else
- {
- outReloc.mFlags = BeRelocFlags_Loc;
- outReloc.mSegmentIdx = sym->mSegmentIdx;
- outReloc.mSegmentOffset = sym->mSegmentOffset;
- }
- nextReloc++;
- if (nextReloc->mVirtualAddress != posSect)
- return false;
- // It MUST be the same sym
- nextReloc++;
- return true;
- }
- bool BlCvParser::TryReloc(void* symbolData, void* cvLoc, int32* outVal, COFFRelocation*& nextReloc)
- {
- int posOfs = (int)((uint8*)cvLoc - (uint8*)symbolData);
- if (nextReloc->mVirtualAddress != posOfs)
- return true;
- return false;
- }
- void BlCvParser::AddModule(BlObjectData* objectData, const char* strTab)
- {
- //const char* invalidStrs[] = { "delete_scalar", "new_scalar", "throw_bad_alloc", "std_type_info_static", "delete_scalar_size", "main2" };
- //const char* invalidStrs[] = { "delete_scalar", "new_scalar" };
- /*const char* invalidStrs[] = { "delete_scalar" };
- for (const char* invalidStr : invalidStrs)
- {
- //TODO:
- if (strstr(objectData->mName, invalidStr) != NULL)
- {
- return;
- }
- }
- if (strstr(objectData->mName, "new_scalar") != NULL)
- {
- mTEMP_Testing = true;
- }*/
-
- mCurModule = mCodeView->mModuleInfo.Alloc();
- mCurModule->mObjectData = objectData;
- mCurModule->mIdx = (int)mCodeView->mModuleInfo.size() - 1;
- mCurModule->mStrTab = strTab;
- }
- void BlCvParser::AddTypeData(PESectionHeader* sect)
- {
- mTypeSects.push_back(sect);
- }
- void BlCvParser::AddSymbolData(PESectionHeader* sect)
- {
- mSymSects.push_back(sect);
- }
- void BlCvParser::ParseTypeData(void* typeData, int size)
- {
- uint8* data = (uint8*)typeData;
- uint8* dataEnd = data + size;
- int sig = GET(int32);
- if (sig != CV_SIGNATURE_C13)
- {
- Fail("Invalid debug signature");
- return;
- }
- bool useWorkList = true;
- if (*(int16*)(data + 2) == LF_TYPESERVER2)
- {
- lfTypeServer2& typeServer = *(lfTypeServer2*)(data + 2);
- String filePath = (char*)typeServer.name;
- String fixedFilePath = FixPathAndCase(filePath);
- auto itr = mCodeView->mTypeServerFiles.find(fixedFilePath);
- if (itr == mCodeView->mTypeServerFiles.end())
- {
- auto itrPair = mCodeView->mTypeServerFiles.insert(std::make_pair(fixedFilePath, (BlCvTypeSource*)NULL));
- BlPdbParser* pdbParser = new BlPdbParser();
- pdbParser->mTypeSource = new BlCvTypeSource;
- itrPair.first->second = pdbParser->mTypeSource;
- pdbParser->mTypeSource->mTypeServerLib = pdbParser;
- pdbParser->mTypeSource->Init(mCodeView);
-
- if (FileExists(filePath))
- {
- pdbParser->mFileName = filePath;
- }
- else
- {
- String fileName = GetFileName(filePath);
- String checkFilePath;
- if (mCurModule->mObjectData->mLib != NULL)
- checkFilePath = GetFileDir(mCurModule->mObjectData->mLib->mFileName);
- else
- checkFilePath = GetFileDir(mCurModule->mObjectData->mName);
- checkFilePath += fileName;
- pdbParser->mFileName = checkFilePath;
- }
- if (useWorkList)
- {
- mCodeView->mTypeWorkThread.Add(pdbParser->mTypeSource);
- }
- else
- {
- pdbParser->Load(pdbParser->mFileName);
- }
-
- mCurModule->mTypeSource = pdbParser->mTypeSource;
- }
- else
- {
- mCurModule->mTypeSource = itr->second;
- }
- return;
- }
- auto typeSource = new BlCvTypeSource();
- typeSource->Init(mCodeView);
- mCurModule->mTypeSource = typeSource;
- typeSource->mTPI.mSectionData = data;
- typeSource->mTPI.mSectionSize = size - 4;
- typeSource->mObjectData = mCurModule->mObjectData;
-
- if (useWorkList)
- {
- mCodeView->mTypeWorkThread.Add(typeSource);
- }
- else
- {
- typeSource->mTPI.ScanTypeData();
- typeSource->mTPI.ParseTypeData();
- }
- }
- void BlCvParser::ParseSymbolData(void* symbolData, int size, void* relocData, int numRelocs)
- {
- // static int itrCount = 0;
- // itrCount++;
- //
- // if (itrCount == 0x32)
- // {
- // NOP;
- // }
- uint8* data = (uint8*)symbolData;
- uint8* symDataEnd = data + size;
- int sig = GET(int32);
- if (sig != CV_SIGNATURE_C13)
- {
- Fail("Invalid debug signature");
- return;
- }
- bool relocFailed = false;
- uint8* fileChecksumStart = NULL;
- uint8* fileChecksumEnd = NULL;
- COFFRelocation* nextReloc = (COFFRelocation*)relocData;
- COFFRelocation* relocEnd = nextReloc + numRelocs;
- const char* strTable = NULL;
- while (data < symDataEnd)
- {
- int sectionNum = GET(int32);
- int sectionLen = GET(int32);
- uint8* sectionStart = data;
- uint8* sectionEnd = data + sectionLen;
- if (sectionNum == DEBUG_S_STRINGTABLE)
- {
- //BF_ASSERT(mCurModule->mStrTab.size() == 0);
- //mCurModule->mStrTab.insert(mCurModule->mStrTab.begin(), (char*)sectionStart, (char*)sectionEnd);
- strTable = (char*)sectionStart;
- }
- else if (sectionNum == DEBUG_S_FILECHKSMS)
- {
- fileChecksumStart = sectionStart;
- fileChecksumEnd = sectionEnd;
- }
- data = sectionEnd;
- PTR_ALIGN(data, (uint8*)symbolData, 4);
- }
-
- //int bytesPerFile = 24;
-
- // Handle DEBUG_S_FILECHKSMS
- if (fileChecksumStart != NULL)
- {
- data = fileChecksumStart;
- uint8* sectionStart = data;
- uint8* sectionEnd = fileChecksumEnd;
- // Always at least 8 bytes per file info
- mChksumOfsToFileIdx.resize((sectionEnd - data) / 8);
- mCurModule->mFileInfos.reserve((sectionEnd - data) / 24);
- while (data < sectionEnd)
- {
- int dataOfs = (int)(data - sectionStart);
- uint32 fileTableOfs = GET(uint32);
- const char* fileName = strTable + fileTableOfs;
- uint8 hashLen = GET(uint8);
- uint8 hashType = GET(uint8);
- BlCvFileInfo fileInfo;
- fileInfo.mChksumOfs = dataOfs;
- fileInfo.mStrTableIdx = mCodeView->AddToStringTable(fileName);
- if (hashLen > 0)
- {
- BF_ASSERT(hashType == 1);
- fileInfo.mHashType = 1;
- memcpy(fileInfo.mHash, data, 16);
- data += hashLen;
- }
- else
- {
- fileInfo.mHashType = 0;
- }
-
- mChksumOfsToFileIdx[dataOfs / 8] = (int)mCurModule->mFileInfos.size();
- mCurModule->mFileInfos.push_back(fileInfo);
- PTR_ALIGN(data, sectionStart, 4);
- }
- }
-
- data = (uint8*)symbolData + 4;
- while (data < symDataEnd)
- {
- int sectionNum = GET(int32);
- int sectionLen = GET(int32);
- uint8* sectionStart = data;
- uint8* sectionEnd = data + sectionLen;
- if ((sectionNum == DEBUG_S_SYMBOLS) || (sectionNum == DEBUG_S_INLINEELINES))
- {
- //BL_AUTOPERF("DEBUG_S_SYMBOLS");
- BlCvSymDataBlock dataBlock;
- dataBlock.mSize = (int)(sectionEnd - sectionStart);
- dataBlock.mData = sectionStart;
- dataBlock.mSourceSectOffset = (int)((uint8*)sectionStart - (uint8*)symbolData);
- dataBlock.mRelocStart = nextReloc;
- dataBlock.mOutSize = -1;
- WIN32_MEMORY_RANGE_ENTRY vAddrs = { dataBlock.mData, (SIZE_T)dataBlock.mSize };
- //TODO: This was causing link errors on Win7
- #if 0
- PrefetchVirtualMemory(GetCurrentProcess(), 1, &vAddrs, 0);
- #endif
- data = sectionEnd;
- while ((nextReloc < relocEnd) && ((int)nextReloc->mVirtualAddress < (int)(sectionEnd - (uint8*)symbolData)))
- nextReloc++;
- dataBlock.mRelocEnd = nextReloc;
- if (sectionNum == DEBUG_S_SYMBOLS)
- mCurModule->mSymData.push_back(dataBlock);
- else
- mCurModule->mInlineData.push_back(dataBlock);
- PTR_ALIGN(data, (uint8*)symbolData, 4);
- continue;
- }
- if ((sectionNum & DEBUG_S_IGNORE) != 0)
- {
- data = sectionEnd;
- while ((nextReloc < relocEnd) && ((int)nextReloc->mVirtualAddress < (int)(sectionEnd - (uint8*)symbolData)))
- nextReloc++;
- PTR_ALIGN(data, (uint8*)symbolData, 4);
- continue;
- }
- switch (sectionNum)
- {
- case DEBUG_S_LINES:
- {
- //BL_AUTOPERF("DEBUG_S_LINES");
- CV_DebugSLinesHeader_t& lineSec = GET(CV_DebugSLinesHeader_t);
- BlReloc reloc;
- MapAddress(symbolData, &lineSec.offCon, reloc, nextReloc);
- auto lineInfo = mCurModule->mLineInfo.Alloc();
- /*if ((reloc.mFlags & BeRelocFlags_Sym) != 0)
- {
- auto sym = mContext->ProcessSymbol(reloc.mSym);
- if (sym->mSegmentIdx >= 0)
- {
- lineInfo->mStartSegmentIdx = sym->mSegmentIdx;
- lineInfo->mStartSegmentOffset = sym->mSegmentOffset;
- }
- else
- relocFailed = true;
- }
- else*/ if ((reloc.mFlags & BeRelocFlags_Loc) != 0)
- {
- lineInfo->mStartSegmentIdx = reloc.mSegmentIdx;
- lineInfo->mStartSegmentOffset = reloc.mSegmentOffset;
- }
- else
- {
- relocFailed = true;
- }
- lineInfo->mContribBytes = lineSec.cbCon;
-
- while (data < sectionEnd)
- {
- CV_DebugSLinesFileBlockHeader_t& linesFileHeader = GET(CV_DebugSLinesFileBlockHeader_t);
- lineInfo->mLineInfoBlocks.emplace_back(BlCvLineInfoBlock());
- auto& lineInfoBlock = lineInfo->mLineInfoBlocks.back();
- lineInfoBlock.mLines.reserve(linesFileHeader.nLines);
- if ((lineSec.flags & CV_LINES_HAVE_COLUMNS) != 0)
- lineInfoBlock.mColumns.reserve(linesFileHeader.nLines);
- //BF_ASSERT(linesFileHeader.offFile % bytesPerFile == 0);
- //lineInfoBlock.mFileInfoIdx = linesFileHeader.offFile / bytesPerFile;
- lineInfoBlock.mFileInfoIdx = mChksumOfsToFileIdx[linesFileHeader.offFile / 8];
- for (int lineIdx = 0; lineIdx < linesFileHeader.nLines; lineIdx++)
- {
- CV_Line_t& srcLineData = GET(CV_Line_t);
- BlCvLine cvLine;
- cvLine.mLineNumStart = srcLineData.linenumStart;
- cvLine.mOffset = srcLineData.offset;
- lineInfoBlock.mLines.push_back(cvLine);
- }
- if ((lineSec.flags & CV_LINES_HAVE_COLUMNS) != 0)
- {
- for (int lineIdx = 0; lineIdx < linesFileHeader.nLines; lineIdx++)
- {
- CV_Column_t& srcColumnData = GET(CV_Column_t);
- lineInfoBlock.mColumns.push_back(srcColumnData.offColumnStart);
- }
- }
- }
- }
- break;
- case DEBUG_S_INLINEELINES:
- {
- // Already handled
- }
- break;
- case DEBUG_S_STRINGTABLE:
- {
- // Already handled
- }
- break;
- case DEBUG_S_FILECHKSMS:
- {
- // Already handled
- }
- break;
- default:
- NotImpl();
- }
- data = sectionEnd;
- PTR_ALIGN(data, (uint8*)symbolData, 4);
- }
- if (nextReloc != (COFFRelocation*)relocData + numRelocs)
- relocFailed = true;
- if (relocFailed)
- Fail("Failed to apply relocations to debug symbol data");
- }
- void BlCvParser::AddContribution(int blSectionIdx, int blSectionOfs, int size, int characteristics)
- {
- if (mCurModule == NULL)
- return;
- if ((characteristics & IMAGE_SCN_MEM_EXECUTE) != 0)
- {
- if (mCurModule->mContrib.mCharacteristics == 0)
- {
- mCurModule->mContrib.mBlSectionIdx = blSectionIdx;
- mCurModule->mContrib.mBlSectionOfs = blSectionOfs;
- mCurModule->mContrib.mSize = size;
- mCurModule->mContrib.mCharacteristics = characteristics;
- }
- }
- BlCvContrib contrib;
- contrib.mModuleIdx = mCurModule->mIdx;
- contrib.mBlSectionOfs = blSectionOfs;
- contrib.mSize = size;
- contrib.mCharacteristics = characteristics;
- while (blSectionIdx >= (int)mCodeView->mContribMap.mSegments.size())
- mCodeView->mContribMap.mSegments.Alloc();
- auto contribMapSeg = mCodeView->mContribMap.mSegments[blSectionIdx];
- contribMapSeg->mContribs.push_back(contrib);
- }
- void BlCvParser::FinishModule(PESectionHeader* sectHeaderArr, const BfSizedVectorRef<BlObjectDataSectInfo>& sectInfos, PE_SymInfo* objSyms, const BfSizedVectorRef<BlObjectDataSymInfo>& syms)
- {
- if (mCurModule == NULL)
- return;
-
- mCurModule->mObjSyms = objSyms;
- if (!syms.empty())
- mCurModule->mSymInfo.insert(mCurModule->mSymInfo.begin(), syms.begin(), syms.end());
- for (auto sectInfo : sectInfos)
- mCurModule->mSectInfos.push_back(sectInfo);
- mSyms = &syms;
- //
- {
- BL_AUTOPERF("BlCvParser::FinishModule ParseTypeData");
- for (auto sect : mTypeSects)
- {
- ParseTypeData((uint8*)mCurModule->mObjectData->mData + sect->mPointerToRawData, sect->mSizeOfRawData);
- }
- }
-
- //
- {
- BL_AUTOPERF("BlCvParser::FinishModule ParseSymbolData");
- for (auto sect : mSymSects)
- {
- ParseSymbolData(
- (uint8*)mCurModule->mObjectData->mData + sect->mPointerToRawData, sect->mSizeOfRawData,
- (uint8*)mCurModule->mObjectData->mData + sect->mPointerToRelocations, sect->mNumberOfRelocations);
- }
- }
- mCodeView->mModuleWorkThread.Add(mCurModule);
- }
|