123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322 |
- #include "BlPdbParser.h"
- #include "BlContext.h"
- #include "codeview/cvinfo.h"
- #include "BlCvParser.h"
- #include "BlCvTypeSource.h"
- USING_NS_BF;
- #define MSF_SIGNATURE_700 "Microsoft C/C++ MSF 7.00\r\n\032DS\0\0"
- #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) ) )
- void BlPdbParser::Fail(const StringImpl& err)
- {
- BF_FATAL("Err");
- }
- void BlPdbParser::NotImpl()
- {
- BF_FATAL("NotImpl");
- }
- BlPdbParser::BlPdbParser()
- {
- mCvHeaderData = NULL;
- mCvTypeSectionData = NULL;
- mCvIPIData = NULL;
- mMappedFile = NULL;
- }
- BlPdbParser::~BlPdbParser()
- {
- delete mCvHeaderData;
- delete mCvTypeSectionData;
- delete mCvIPIData;
- delete mMappedFile;
- }
- bool BlPdbParser::Load(const StringImpl& fileName)
- {
- mMappedFile = new MappedFile();
- if (!mMappedFile->Open(fileName))
- return false;
- mData = (uint8*)mMappedFile->mData;
- uint8* data = (uint8*)mMappedFile->mData;
- if (memcmp(data, MSF_SIGNATURE_700, 32) != 0)
- {
- Fail("PDB signature error");
- return false;
- }
- data += 32;
- int pageSize = GET(int32);
- int fpmPageNum = GET(int32);
- int totalPageCount = GET(int32);
- int rootDirSize = GET(int32);
- int unknown = GET(int32);
- int rootDirPtr = GET(int32);
- bool failed = false;
- mCvPageSize = pageSize;
- int rootPageCount = (rootDirSize + pageSize - 1) / pageSize;
- int rootPointersPages = (rootPageCount * sizeof(int32) + pageSize - 1) / pageSize;
- int rootPageIdx = 0;
- std::vector<uint8> rootDirData;
- rootDirData.resize(rootPageCount * pageSize);
- data = mData + (rootDirPtr * pageSize);
- int32* rootPages = (int32*)data;
- for (int subRootPageIdx = 0; subRootPageIdx < pageSize / 4; subRootPageIdx++, rootPageIdx++)
- {
- if (rootPageIdx >= rootPageCount)
- break;
- int rootPagePtr = rootPages[subRootPageIdx];
- if (rootPagePtr == 0)
- break;
- data = mData + (rootPagePtr * pageSize);
- memcpy(&rootDirData[rootPageIdx * pageSize], data, pageSize);
- data += pageSize;
- }
- if (!ParseCv(&rootDirData[0]))
- {
- Fail("Failed to parse PDB");
- return false;
- }
- return true;
- }
- bool BlPdbParser::CvParseHeader()
- {
- uint8* data = CvReadStream(1);
- mCvHeaderData = data;
- int32 pdbVersion = GET(int32);
- int32 timestamp = GET(int32);
- int32 pdbAge = GET(int32);
- int8 pdbGuid[16];
- for (int i = 0; i < 16; i++)
- pdbGuid[i] = GET(int8);
- /*if ((wantAge != -1) &&
- ((pdbAge != wantAge) || (memcmp(pdbGuid, wantGuid, 16) != 0)))
- {
- String msg = "PDB version did not match requested version\n";
- msg += StrFormat(" Age: %d Module GUID: ", wantAge);
- for (int i = 0; i < 16; i++)
- msg += StrFormat("%02X", (uint8)wantGuid[i]);
- msg += "\n";
- msg += StrFormat(" Age: %d PDB GUID : ", pdbAge);
- for (int i = 0; i < 16; i++)
- msg += StrFormat("%02X", (uint8)pdbGuid[i]);
- msg += "\n";
- mDebugger->OutputMessage(msg);
- return false;
- }*/
- int nameTableIdx = -1;
- GET_INTO(int32, strTabLen);
- const char* strTab = (const char*)data;
- data += strTabLen;
- GET_INTO(int32, numStrItems);
- GET_INTO(int32, strItemMax);
- GET_INTO(int32, usedLen);
- data += usedLen * sizeof(int32);
- GET_INTO(int32, deletedLen);
- data += deletedLen * sizeof(int32);
- for (int tableIdx = 0; tableIdx < numStrItems; tableIdx++)
- {
- GET_INTO(int32, strOfs);
- GET_INTO(int32, streamNum);
- const char* tableName = strTab + strOfs;
- if (strcmp(tableName, "/names") == 0)
- mStringTable.mStream = streamNum;
- }
- return true;
- }
- uint8* BlPdbParser::CvReadStream(int streamIdx, int* outSize)
- {
- int streamSize = mCvStreamSizes[streamIdx];
- if (outSize != NULL)
- *outSize = streamSize;
- if (streamSize <= 0)
- return NULL;
- int streamPageCount = (streamSize + mCvPageSize - 1) / mCvPageSize;
- uint8* sectionData = new uint8[streamSize];
- bool deferDeleteSectionData = false;
- int streamPtrIdx = mCvStreamPtrStartIdxs[streamIdx];
- for (int streamPageIdx = 0; streamPageIdx < streamPageCount; streamPageIdx++)
- {
- uint8* data = mData + (mCvStreamPtrs[streamPtrIdx] * mCvPageSize);
- memcpy(sectionData + streamPageIdx * mCvPageSize, data, std::min(streamSize - (streamPageIdx * mCvPageSize), mCvPageSize));
- streamPtrIdx++;
- }
- return sectionData;
- }
- bool BlPdbParser::ParseCv(uint8* rootDirData)
- {
- uint8* data = rootDirData;
- bool failed = false;
- int numStreams = GET(int32);
- if (numStreams == 0)
- return true;
- mCvStreamSizes.resize(numStreams);
- mCvStreamPtrStartIdxs.resize(numStreams);
- int streamPages = 0;
- for (int i = 0; i < (int)mCvStreamSizes.size(); i++)
- mCvStreamSizes[i] = GET(int32);
- for (int streamIdx = 0; streamIdx < numStreams; streamIdx++)
- {
- mCvStreamPtrStartIdxs[streamIdx] = streamPages;
- if (mCvStreamSizes[streamIdx] > 0)
- streamPages += (mCvStreamSizes[streamIdx] + mCvPageSize - 1) / mCvPageSize;
- }
- mCvStreamPtrs.resize(streamPages);
- for (int i = 0; i < (int)mCvStreamPtrs.size(); i++)
- mCvStreamPtrs[i] = GET(int32);
- //////////////////////////////////////////////////////////////////////////
- if (!CvParseHeader())
- return false;
- ParseTypeData();
- ParseIPIData();
- return true;
- }
- void BlPdbParser::ParseTypeData()
- {
- int sectionSize = 0;
- mCvTypeSectionData = CvReadStream(2, §ionSize);
- uint8* data = mCvTypeSectionData;
- uint8* sectionData = mCvTypeSectionData;
-
- int32 ver = GET(int32);
- int32 headerSize = GET(int32);
- int32 minVal = GET(int32);
- int32 maxVal = GET(int32);
- int32 followSize = GET(int32);
- int16 hashStream = GET(int16);
- int16 hashStreamPadding = GET(int16);
- int32 hashKey = GET(int32);
- int32 hashBucketsSize = GET(int32);
- int32 hashValsOffset = GET(int32);
- int32 hashValsSize = GET(int32);
- int32 hashTypeInfoOffset = GET(int32);
- int32 hashTypeInfoSize = GET(int32);
- int32 hashAdjOffset = GET(int32);
- int32 hashAdjSize = GET(int32);
- mTypeSource->mTPI.mCvMinTag = minVal;
- mTypeSource->mTPI.mCvMaxTag = maxVal;
- //mCvTypeMap.clear();
- //mTypeSource->mTPI.mCvTagStartMap.clear();
- //mCvTypeMap.resize(maxVal - minVal);
- mTypeSource->mTPI.mCvTagStartMap.resize(maxVal - minVal);
- //DbgDataMap dataMap(minVal, maxVal);
- mTypeSource->mTPI.mSectionData = data;
- mTypeSource->mTPI.mSectionSize = sectionSize - (int)(data - sectionData);
- mTypeSource->mTPI.ScanTypeData();
- mTypeSource->mTPI.ParseTypeData();
- if (hashAdjSize > 0)
- {
- int sectionSize = 0;
- uint8* data = CvReadStream(hashStream, §ionSize);
- uint8* sectionData = data;
- data = sectionData + hashAdjOffset;
- GET_INTO(int32, adjustCount);
- GET_INTO(int32, unk0);
- GET_INTO(int32, unkCount);
- for (int i = 0; i < unkCount; i++)
- {
- GET_INTO(int32, unk2);
- }
- GET_INTO(int32, unkCount2);
- for (int i = 0; i < unkCount2; i++)
- {
- GET_INTO(int32, unk3);
- }
- // Types listed in the adjustment table are always primary types,
- // they should override any "old types" with the same name
- for (int adjIdx = 0; adjIdx < adjustCount; adjIdx++)
- {
- GET_INTO(int32, adjVal);
- GET_INTO(CV_typ_t, typeId);
- }
- delete[] sectionData;
- }
- }
- void BlPdbParser::ParseIPIData()
- {
- int sectionSize = 0;
- mCvIPIData = CvReadStream(4, §ionSize);
- uint8* data = mCvIPIData;
- uint8* sectionData = data;
- int32 ver = GET(int32);
- int32 headerSize = GET(int32);
- int32 minVal = GET(int32);
- int32 maxVal = GET(int32);
- int32 followSize = GET(int32);
- int16 hashStream = GET(int16);
- int16 hashStreamPadding = GET(int16);
- int32 hashKey = GET(int32);
- int32 hashBucketsSize = GET(int32);
- int32 hashValsOffset = GET(int32);
- int32 hashValsSize = GET(int32);
- int32 hashTypeInfoOffset = GET(int32);
- int32 hashTypeInfoSize = GET(int32);
- int32 hashAdjOffset = GET(int32);
- int32 hashAdjSize = GET(int32);
- mTypeSource->CreateIPI();
- mTypeSource->mIPI->mCvMinTag = minVal;
- mTypeSource->mIPI->mCvMaxTag = maxVal;
- int recordCount = maxVal - minVal;
- mTypeSource->mIPI->mCvTagStartMap.resize(recordCount);
- int typeDataSize = sectionSize - (int)(data - sectionData);
- mTypeSource->mIPI->mSectionData = data;
- mTypeSource->mIPI->mSectionSize = typeDataSize;
- mTypeSource->mIPI->ScanTypeData();
- mTypeSource->mIPI->ParseTypeData();
- }
|