BlPdbParser.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. #include "BlPdbParser.h"
  2. #include "BlContext.h"
  3. #include "codeview/cvinfo.h"
  4. #include "BlCvParser.h"
  5. #include "BlCvTypeSource.h"
  6. USING_NS_BF;
  7. #define MSF_SIGNATURE_700 "Microsoft C/C++ MSF 7.00\r\n\032DS\0\0"
  8. #define GET(T) *((T*)(data += sizeof(T)) - 1)
  9. #define GET_INTO(T, name) T name = GET(T)
  10. #define PTR_ALIGN(ptr, origPtr, alignSize) ptr = ( (origPtr)+( ((ptr - origPtr) + (alignSize - 1)) & ~(alignSize - 1) ) )
  11. void BlPdbParser::Fail(const StringImpl& err)
  12. {
  13. BF_FATAL("Err");
  14. }
  15. void BlPdbParser::NotImpl()
  16. {
  17. BF_FATAL("NotImpl");
  18. }
  19. BlPdbParser::BlPdbParser()
  20. {
  21. mCvHeaderData = NULL;
  22. mCvTypeSectionData = NULL;
  23. mCvIPIData = NULL;
  24. mMappedFile = NULL;
  25. }
  26. BlPdbParser::~BlPdbParser()
  27. {
  28. delete mCvHeaderData;
  29. delete mCvTypeSectionData;
  30. delete mCvIPIData;
  31. delete mMappedFile;
  32. }
  33. bool BlPdbParser::Load(const StringImpl& fileName)
  34. {
  35. mMappedFile = new MappedFile();
  36. if (!mMappedFile->Open(fileName))
  37. return false;
  38. mData = (uint8*)mMappedFile->mData;
  39. uint8* data = (uint8*)mMappedFile->mData;
  40. if (memcmp(data, MSF_SIGNATURE_700, 32) != 0)
  41. {
  42. Fail("PDB signature error");
  43. return false;
  44. }
  45. data += 32;
  46. int pageSize = GET(int32);
  47. int fpmPageNum = GET(int32);
  48. int totalPageCount = GET(int32);
  49. int rootDirSize = GET(int32);
  50. int unknown = GET(int32);
  51. int rootDirPtr = GET(int32);
  52. bool failed = false;
  53. mCvPageSize = pageSize;
  54. int rootPageCount = (rootDirSize + pageSize - 1) / pageSize;
  55. int rootPointersPages = (rootPageCount * sizeof(int32) + pageSize - 1) / pageSize;
  56. int rootPageIdx = 0;
  57. std::vector<uint8> rootDirData;
  58. rootDirData.resize(rootPageCount * pageSize);
  59. data = mData + (rootDirPtr * pageSize);
  60. int32* rootPages = (int32*)data;
  61. for (int subRootPageIdx = 0; subRootPageIdx < pageSize / 4; subRootPageIdx++, rootPageIdx++)
  62. {
  63. if (rootPageIdx >= rootPageCount)
  64. break;
  65. int rootPagePtr = rootPages[subRootPageIdx];
  66. if (rootPagePtr == 0)
  67. break;
  68. data = mData + (rootPagePtr * pageSize);
  69. memcpy(&rootDirData[rootPageIdx * pageSize], data, pageSize);
  70. data += pageSize;
  71. }
  72. if (!ParseCv(&rootDirData[0]))
  73. {
  74. Fail("Failed to parse PDB");
  75. return false;
  76. }
  77. return true;
  78. }
  79. bool BlPdbParser::CvParseHeader()
  80. {
  81. uint8* data = CvReadStream(1);
  82. mCvHeaderData = data;
  83. int32 pdbVersion = GET(int32);
  84. int32 timestamp = GET(int32);
  85. int32 pdbAge = GET(int32);
  86. int8 pdbGuid[16];
  87. for (int i = 0; i < 16; i++)
  88. pdbGuid[i] = GET(int8);
  89. /*if ((wantAge != -1) &&
  90. ((pdbAge != wantAge) || (memcmp(pdbGuid, wantGuid, 16) != 0)))
  91. {
  92. String msg = "PDB version did not match requested version\n";
  93. msg += StrFormat(" Age: %d Module GUID: ", wantAge);
  94. for (int i = 0; i < 16; i++)
  95. msg += StrFormat("%02X", (uint8)wantGuid[i]);
  96. msg += "\n";
  97. msg += StrFormat(" Age: %d PDB GUID : ", pdbAge);
  98. for (int i = 0; i < 16; i++)
  99. msg += StrFormat("%02X", (uint8)pdbGuid[i]);
  100. msg += "\n";
  101. mDebugger->OutputMessage(msg);
  102. return false;
  103. }*/
  104. int nameTableIdx = -1;
  105. GET_INTO(int32, strTabLen);
  106. const char* strTab = (const char*)data;
  107. data += strTabLen;
  108. GET_INTO(int32, numStrItems);
  109. GET_INTO(int32, strItemMax);
  110. GET_INTO(int32, usedLen);
  111. data += usedLen * sizeof(int32);
  112. GET_INTO(int32, deletedLen);
  113. data += deletedLen * sizeof(int32);
  114. for (int tableIdx = 0; tableIdx < numStrItems; tableIdx++)
  115. {
  116. GET_INTO(int32, strOfs);
  117. GET_INTO(int32, streamNum);
  118. const char* tableName = strTab + strOfs;
  119. if (strcmp(tableName, "/names") == 0)
  120. mStringTable.mStream = streamNum;
  121. }
  122. return true;
  123. }
  124. uint8* BlPdbParser::CvReadStream(int streamIdx, int* outSize)
  125. {
  126. int streamSize = mCvStreamSizes[streamIdx];
  127. if (outSize != NULL)
  128. *outSize = streamSize;
  129. if (streamSize <= 0)
  130. return NULL;
  131. int streamPageCount = (streamSize + mCvPageSize - 1) / mCvPageSize;
  132. uint8* sectionData = new uint8[streamSize];
  133. bool deferDeleteSectionData = false;
  134. int streamPtrIdx = mCvStreamPtrStartIdxs[streamIdx];
  135. for (int streamPageIdx = 0; streamPageIdx < streamPageCount; streamPageIdx++)
  136. {
  137. uint8* data = mData + (mCvStreamPtrs[streamPtrIdx] * mCvPageSize);
  138. memcpy(sectionData + streamPageIdx * mCvPageSize, data, std::min(streamSize - (streamPageIdx * mCvPageSize), mCvPageSize));
  139. streamPtrIdx++;
  140. }
  141. return sectionData;
  142. }
  143. bool BlPdbParser::ParseCv(uint8* rootDirData)
  144. {
  145. uint8* data = rootDirData;
  146. bool failed = false;
  147. int numStreams = GET(int32);
  148. if (numStreams == 0)
  149. return true;
  150. mCvStreamSizes.resize(numStreams);
  151. mCvStreamPtrStartIdxs.resize(numStreams);
  152. int streamPages = 0;
  153. for (int i = 0; i < (int)mCvStreamSizes.size(); i++)
  154. mCvStreamSizes[i] = GET(int32);
  155. for (int streamIdx = 0; streamIdx < numStreams; streamIdx++)
  156. {
  157. mCvStreamPtrStartIdxs[streamIdx] = streamPages;
  158. if (mCvStreamSizes[streamIdx] > 0)
  159. streamPages += (mCvStreamSizes[streamIdx] + mCvPageSize - 1) / mCvPageSize;
  160. }
  161. mCvStreamPtrs.resize(streamPages);
  162. for (int i = 0; i < (int)mCvStreamPtrs.size(); i++)
  163. mCvStreamPtrs[i] = GET(int32);
  164. //////////////////////////////////////////////////////////////////////////
  165. if (!CvParseHeader())
  166. return false;
  167. ParseTypeData();
  168. ParseIPIData();
  169. return true;
  170. }
  171. void BlPdbParser::ParseTypeData()
  172. {
  173. int sectionSize = 0;
  174. mCvTypeSectionData = CvReadStream(2, &sectionSize);
  175. uint8* data = mCvTypeSectionData;
  176. uint8* sectionData = mCvTypeSectionData;
  177. int32 ver = GET(int32);
  178. int32 headerSize = GET(int32);
  179. int32 minVal = GET(int32);
  180. int32 maxVal = GET(int32);
  181. int32 followSize = GET(int32);
  182. int16 hashStream = GET(int16);
  183. int16 hashStreamPadding = GET(int16);
  184. int32 hashKey = GET(int32);
  185. int32 hashBucketsSize = GET(int32);
  186. int32 hashValsOffset = GET(int32);
  187. int32 hashValsSize = GET(int32);
  188. int32 hashTypeInfoOffset = GET(int32);
  189. int32 hashTypeInfoSize = GET(int32);
  190. int32 hashAdjOffset = GET(int32);
  191. int32 hashAdjSize = GET(int32);
  192. mTypeSource->mTPI.mCvMinTag = minVal;
  193. mTypeSource->mTPI.mCvMaxTag = maxVal;
  194. //mCvTypeMap.clear();
  195. //mTypeSource->mTPI.mCvTagStartMap.clear();
  196. //mCvTypeMap.resize(maxVal - minVal);
  197. mTypeSource->mTPI.mCvTagStartMap.resize(maxVal - minVal);
  198. //DbgDataMap dataMap(minVal, maxVal);
  199. mTypeSource->mTPI.mSectionData = data;
  200. mTypeSource->mTPI.mSectionSize = sectionSize - (int)(data - sectionData);
  201. mTypeSource->mTPI.ScanTypeData();
  202. mTypeSource->mTPI.ParseTypeData();
  203. if (hashAdjSize > 0)
  204. {
  205. int sectionSize = 0;
  206. uint8* data = CvReadStream(hashStream, &sectionSize);
  207. uint8* sectionData = data;
  208. data = sectionData + hashAdjOffset;
  209. GET_INTO(int32, adjustCount);
  210. GET_INTO(int32, unk0);
  211. GET_INTO(int32, unkCount);
  212. for (int i = 0; i < unkCount; i++)
  213. {
  214. GET_INTO(int32, unk2);
  215. }
  216. GET_INTO(int32, unkCount2);
  217. for (int i = 0; i < unkCount2; i++)
  218. {
  219. GET_INTO(int32, unk3);
  220. }
  221. // Types listed in the adjustment table are always primary types,
  222. // they should override any "old types" with the same name
  223. for (int adjIdx = 0; adjIdx < adjustCount; adjIdx++)
  224. {
  225. GET_INTO(int32, adjVal);
  226. GET_INTO(CV_typ_t, typeId);
  227. }
  228. delete[] sectionData;
  229. }
  230. }
  231. void BlPdbParser::ParseIPIData()
  232. {
  233. int sectionSize = 0;
  234. mCvIPIData = CvReadStream(4, &sectionSize);
  235. uint8* data = mCvIPIData;
  236. uint8* sectionData = data;
  237. int32 ver = GET(int32);
  238. int32 headerSize = GET(int32);
  239. int32 minVal = GET(int32);
  240. int32 maxVal = GET(int32);
  241. int32 followSize = GET(int32);
  242. int16 hashStream = GET(int16);
  243. int16 hashStreamPadding = GET(int16);
  244. int32 hashKey = GET(int32);
  245. int32 hashBucketsSize = GET(int32);
  246. int32 hashValsOffset = GET(int32);
  247. int32 hashValsSize = GET(int32);
  248. int32 hashTypeInfoOffset = GET(int32);
  249. int32 hashTypeInfoSize = GET(int32);
  250. int32 hashAdjOffset = GET(int32);
  251. int32 hashAdjSize = GET(int32);
  252. mTypeSource->CreateIPI();
  253. mTypeSource->mIPI->mCvMinTag = minVal;
  254. mTypeSource->mIPI->mCvMaxTag = maxVal;
  255. int recordCount = maxVal - minVal;
  256. mTypeSource->mIPI->mCvTagStartMap.resize(recordCount);
  257. int typeDataSize = sectionSize - (int)(data - sectionData);
  258. mTypeSource->mIPI->mSectionData = data;
  259. mTypeSource->mIPI->mSectionSize = typeDataSize;
  260. mTypeSource->mIPI->ScanTypeData();
  261. mTypeSource->mIPI->ParseTypeData();
  262. }