Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3599 lines
105 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1999 - 2000
  6. //
  7. // File: moduleinfo.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. // ModuleInfo.cpp: implementation of the CModuleInfo class.
  11. //
  12. //////////////////////////////////////////////////////////////////////
  13. #ifndef NO_STRICT
  14. #ifndef STRICT
  15. #define STRICT 1
  16. #endif
  17. #endif /* NO_STRICT */
  18. #include <WINDOWS.H>
  19. #include <STDIO.H>
  20. #include <TCHAR.H>
  21. #include <time.h>
  22. #include "ModuleInfo.h"
  23. #include "Globals.h"
  24. #include "ProgramOptions.h"
  25. #include "SymbolVerification.h"
  26. #include "FileData.h"
  27. #include "UtilityFunctions.h"
  28. #include "DmpFile.h"
  29. //////////////////////////////////////////////////////////////////////
  30. // Construction/Destruction
  31. //////////////////////////////////////////////////////////////////////
  32. CModuleInfo::CModuleInfo()
  33. {
  34. m_dwRefCount = 1;
  35. m_dwCurrentReadPosition = 0;
  36. m_lpInputFile = NULL;
  37. m_lpOutputFile = NULL;
  38. m_lpDmpFile = NULL;
  39. // File version information
  40. m_fPEImageFileVersionInfo = false;
  41. m_tszPEImageFileVersionDescription = NULL;
  42. m_tszPEImageFileVersionCompanyName = NULL;
  43. m_tszPEImageFileVersionString = NULL;
  44. m_dwPEImageFileVersionMS = 0;
  45. m_dwPEImageFileVersionLS = 0;
  46. m_tszPEImageProductVersionString = NULL;
  47. m_dwPEImageProductVersionMS = 0;
  48. m_dwPEImageProductVersionLS = 0;
  49. // PE Image Properties
  50. m_tszPEImageModuleName = NULL; // Module name (eg. notepad.exe)
  51. m_tszPEImageModuleFileSystemPath = NULL; // Full path to module (eg. C:\winnt\system32\notepad.exe)
  52. m_dwPEImageFileSize = 0;
  53. m_ftPEImageFileTimeDateStamp.dwLowDateTime = 0;
  54. m_ftPEImageFileTimeDateStamp.dwHighDateTime = 0;
  55. m_dwPEImageCheckSum = 0;
  56. m_dwPEImageTimeDateStamp = 0;
  57. m_dwPEImageSizeOfImage = 0;
  58. m_enumPEImageType = PEImageTypeUnknown; // We need to track what ImageType we have (PE32/PE64/???)
  59. m_dw64BaseAddress = 0;
  60. m_wPEImageMachineArchitecture = 0;
  61. m_wCharacteristics = 0; // These are the PE image characteristics
  62. // PE Image has a reference to DBG file
  63. m_enumPEImageSymbolStatus = SYMBOLS_NO; // Assume there are no symbols for this module
  64. m_tszPEImageDebugDirectoryDBGPath = NULL; // Path to DBG (found in PE Image)
  65. // PE Image has internal symbols
  66. m_dwPEImageDebugDirectoryCoffSize = 0;
  67. m_dwPEImageDebugDirectoryFPOSize = 0;
  68. m_dwPEImageDebugDirectoryCVSize = 0;
  69. m_dwPEImageDebugDirectoryOMAPtoSRCSize = 0;
  70. m_dwPEImageDebugDirectoryOMAPfromSRCSize = 0;
  71. // PE Image has a reference to PDB file...
  72. m_tszPEImageDebugDirectoryPDBPath = NULL;
  73. m_dwPEImageDebugDirectoryPDBFormatSpecifier = 0;
  74. m_dwPEImageDebugDirectoryPDBSignature = 0; // PDB Signature (unique (across PDB instances) signature)
  75. m_dwPEImageDebugDirectoryPDBAge = 0; // PDB Age (Number of times this instance has been updated)
  76. m_tszPEImageDebugDirectoryPDBGuid = NULL;
  77. // DBG Symbol information
  78. m_enumDBGModuleStatus = SYMBOL_NOT_FOUND; // Status of the DBG file
  79. m_tszDBGModuleFileSystemPath = NULL; // Path to the DBG file (after searching)
  80. m_dwDBGTimeDateStamp = 0;
  81. m_dwDBGCheckSum = 0;
  82. m_dwDBGSizeOfImage = 0;
  83. m_dwDBGImageDebugDirectoryCoffSize = 0;
  84. m_dwDBGImageDebugDirectoryFPOSize = 0;
  85. m_dwDBGImageDebugDirectoryCVSize = 0;
  86. m_dwDBGImageDebugDirectoryOMAPtoSRCSize = 0;
  87. m_dwDBGImageDebugDirectoryOMAPfromSRCSize = 0;
  88. // DBG File has a reference to a PDB file...
  89. m_tszDBGDebugDirectoryPDBPath = NULL;
  90. m_dwDBGDebugDirectoryPDBFormatSpecifier = 0; // NB10, RSDS, etc...
  91. m_dwDBGDebugDirectoryPDBAge = 0;
  92. m_dwDBGDebugDirectoryPDBSignature = 0;
  93. m_tszDBGDebugDirectoryPDBGuid = NULL;
  94. // PDB File Information
  95. m_enumPDBModuleStatus = SYMBOL_NOT_FOUND; // Status of the PDB file
  96. m_tszPDBModuleFileSystemPath = NULL; // Path to the PDB file (after searching)
  97. m_dwPDBFormatSpecifier = 0;
  98. m_dwPDBSignature = 0;
  99. m_dwPDBAge = 0;
  100. m_tszPDBGuid = NULL;
  101. m_dwPDBTotalBytesOfLineInformation = 0;
  102. m_dwPDBTotalBytesOfSymbolInformation = 0;
  103. m_dwPDBTotalSymbolTypesRange = 0;
  104. }
  105. CModuleInfo::~CModuleInfo()
  106. {
  107. // Let's cleanup a bit...
  108. if (m_tszPEImageFileVersionDescription)
  109. delete [] m_tszPEImageFileVersionDescription;
  110. if (m_tszPEImageFileVersionCompanyName)
  111. delete [] m_tszPEImageFileVersionCompanyName;
  112. if (m_tszPEImageFileVersionString)
  113. delete [] m_tszPEImageFileVersionString;
  114. if (m_tszPEImageProductVersionString)
  115. delete [] m_tszPEImageProductVersionString;
  116. if (m_tszPEImageModuleName)
  117. delete [] m_tszPEImageModuleName;
  118. if (m_tszPEImageModuleFileSystemPath)
  119. delete [] m_tszPEImageModuleFileSystemPath;
  120. if (m_tszPEImageDebugDirectoryDBGPath)
  121. delete [] m_tszPEImageDebugDirectoryDBGPath;
  122. if (m_tszPEImageDebugDirectoryPDBPath)
  123. delete [] m_tszPEImageDebugDirectoryPDBPath;
  124. if (m_tszPEImageDebugDirectoryPDBGuid)
  125. delete [] m_tszPEImageDebugDirectoryPDBGuid;
  126. if (m_tszDBGModuleFileSystemPath)
  127. delete [] m_tszDBGModuleFileSystemPath;
  128. if (m_tszDBGDebugDirectoryPDBPath)
  129. delete [] m_tszDBGDebugDirectoryPDBPath;
  130. if (m_tszDBGDebugDirectoryPDBGuid)
  131. delete [] m_tszDBGDebugDirectoryPDBGuid;
  132. if (m_tszPDBModuleFileSystemPath)
  133. delete [] m_tszPDBModuleFileSystemPath;
  134. if (m_tszPDBGuid)
  135. delete [] m_tszPDBGuid;
  136. }
  137. //bool CModuleInfo::Initialize(CProgramOptions * lpProgramOptions, CFileData * lpInputFile, CFileData * lpOutputFile)
  138. bool CModuleInfo::Initialize(CFileData * lpInputFile, CFileData * lpOutputFile, CDmpFile * lpDmpFile)
  139. {
  140. // Let's save off the Program Options so we don't have to pass it to every method...
  141. m_lpInputFile = lpInputFile;
  142. m_lpOutputFile = lpOutputFile;
  143. m_lpDmpFile = lpDmpFile;
  144. return true;
  145. }
  146. bool CModuleInfo::GetModuleInfo(LPTSTR tszModulePath, bool fDmpFile, DWORD64 dw64ModAddress, bool fGetDataFromCSVFile)
  147. {
  148. bool fReturn = true;
  149. if (fGetDataFromCSVFile)
  150. {
  151. fReturn = GetModuleInfoFromCSVFile(tszModulePath);
  152. } else
  153. {
  154. fReturn = GetModuleInfoFromPEImage(tszModulePath, fDmpFile, dw64ModAddress);
  155. }
  156. return fReturn;
  157. }
  158. LPTSTR CModuleInfo::GetModulePath()
  159. {
  160. return m_tszPEImageModuleFileSystemPath;
  161. }
  162. bool CModuleInfo::OutputData(LPTSTR tszProcessName, DWORD iProcessID, unsigned int dwModuleNumber)
  163. {
  164. // Output to STDOUT?
  165. if (!g_lpProgramOptions->GetMode(CProgramOptions::QuietMode))
  166. {
  167. if (!OutputDataToStdout(dwModuleNumber))
  168. return false;
  169. }
  170. // Output to file?
  171. if (g_lpProgramOptions->GetMode(CProgramOptions::OutputCSVFileMode))
  172. {
  173. // Try and output to file...
  174. if (!OutputDataToFile(tszProcessName, iProcessID))
  175. return false;
  176. }
  177. return true;
  178. }
  179. bool CModuleInfo::fCheckPDBSignature(bool fDmpFile, HANDLE hModuleHandle, OMFSignature *pSig, PDB_INFO *ppdb)
  180. {
  181. if (!DoRead(fDmpFile, hModuleHandle, pSig, sizeof(*pSig)))
  182. return false;
  183. if ( (pSig->Signature[0] != 'N') ||
  184. (pSig->Signature[1] != 'B') ||
  185. (!isdigit(pSig->Signature[2])) ||
  186. (!isdigit(pSig->Signature[3])))
  187. {
  188. //
  189. // If this is a DMP file (fDmpFile), odds are good that this was not compiled with
  190. // a linker 6.20 or higher (which marks the PDB path in the PE image such
  191. // that it gets mapped into the virtual address space (and will be in the user.dmp
  192. // file).
  193. //
  194. return false;
  195. }
  196. // This switch statement is reminiscent of some windbg code...don't shoot me
  197. // (I modified it slightly since the NB signature isn't super important to me)...
  198. switch (*(LONG UNALIGNED *)(pSig->Signature))
  199. {
  200. case sigNB10: // OMF Signature, and hopefully some PDB INFO
  201. {
  202. if (!DoRead(fDmpFile, hModuleHandle, ppdb, sizeof(PDB_INFO)))
  203. break;
  204. }
  205. default:
  206. break;
  207. }
  208. // Before returning true (since we have some form of NB## symbols), we'll save this...
  209. /*
  210. #ifdef _UNICODE
  211. // Source is in ANSI, dest is in _UNICODE... need to convert...
  212. MultiByteToWideChar(CP_ACP,
  213. MB_PRECOMPOSED,
  214. pSig->Signature,
  215. 4,
  216. m_tszPEImageDebugDirectoryNBInfo,
  217. 4);
  218. #else
  219. // Copy the ANSI string over...
  220. strncpy(m_tszPEImageDebugDirectoryNBInfo, pSig->Signature, 4);
  221. #endif
  222. m_tszPEImageDebugDirectoryNBInfo[4] = '\0';
  223. */
  224. return true;
  225. }
  226. bool CModuleInfo::VerifySymbols(CSymbolVerification * lpSymbolVerification)
  227. {
  228. bool fReturn = false;
  229. if (!m_tszPEImageModuleName)
  230. goto cleanup;
  231. // Find/Verify a DBG file...
  232. if (m_enumPEImageSymbolStatus == SYMBOLS_DBG)
  233. {
  234. if ( g_lpProgramOptions->GetMode(CProgramOptions::VerifySymbolsModeWithSymbolPath) )
  235. {
  236. fReturn = GetDBGModuleFileUsingSymbolPath(g_lpProgramOptions->GetSymbolPath());
  237. }
  238. // Do we want to try an alternate method to find symbols?
  239. if ( m_enumDBGModuleStatus != SYMBOL_MATCH )
  240. {
  241. // Try SQL server next...
  242. if ( g_lpProgramOptions->GetMode(CProgramOptions::VerifySymbolsModeWithSQLServer) )
  243. {
  244. fReturn = GetDBGModuleFileUsingSQLServer(lpSymbolVerification);
  245. }
  246. // Try SQL2 server next ... mjl 12/14/99
  247. if ( g_lpProgramOptions->GetMode(CProgramOptions::VerifySymbolsModeWithSQLServer2) )
  248. {
  249. fReturn = GetDBGModuleFileUsingSQLServer2(lpSymbolVerification);
  250. }
  251. }
  252. }
  253. // Note, it is possible that the m_enumPEImageSymbolStatus will have changed from SYMBOLS_DBG
  254. // to SYMBOLS_DBG_AND_PDB after the DBG file is found above...
  255. if ( (m_enumPEImageSymbolStatus == SYMBOLS_DBG_AND_PDB) ||
  256. (m_enumPEImageSymbolStatus == SYMBOLS_PDB) )
  257. {
  258. // This gets populated with the PDB filename (obtained from the DBG or PE Image)
  259. // if (m_tszDebugDirectoryPDBPath)
  260. if (GetDebugDirectoryPDBPath())
  261. {
  262. if (!lpSymbolVerification)
  263. {
  264. m_enumPDBModuleStatus = SYMBOL_NO_HELPER_DLL;
  265. goto cleanup;
  266. }
  267. fReturn = GetPDBModuleFileUsingSymbolPath();
  268. // Do we want to try an alternate method to find symbols?
  269. if ( m_enumPDBModuleStatus != SYMBOL_MATCH )
  270. {
  271. // Search for PDB in SQL2 if enabled - mjl 12/14/99
  272. if ( g_lpProgramOptions->GetMode(CProgramOptions::VerifySymbolsModeWithSQLServer2) )
  273. {
  274. fReturn = GetPDBModuleFileUsingSQLServer2(lpSymbolVerification);
  275. }
  276. }
  277. }
  278. }
  279. cleanup:
  280. return fReturn;
  281. }
  282. bool CModuleInfo::GetDBGModuleFileUsingSymbolPath(LPTSTR tszSymbolPath)
  283. {
  284. HANDLE hModuleHandle = INVALID_HANDLE_VALUE;
  285. TCHAR tszDebugModulePath[_MAX_PATH+1];
  286. TCHAR tszDrive[_MAX_DRIVE];
  287. TCHAR tszDir[_MAX_DIR];
  288. TCHAR tszExtModuleName[_MAX_EXT];
  289. TCHAR tszDBGModuleName[_MAX_FNAME];
  290. TCHAR tszSymbolPathWithModulePathPrepended[_MAX_PATH+_MAX_PATH+1];
  291. TCHAR tszPEImageModuleName[_MAX_FNAME+_MAX_EXT+1];
  292. bool fDebugSearchPaths = g_lpProgramOptions->fDebugSearchPaths();
  293. // We have two options on the name of the DBG file...
  294. //
  295. // We compose the name of the DBG file we're searching for and pass that as the
  296. // first parameter (we could grab that which is in the MISC section but the
  297. // debuggers do not tend to do that...
  298. //
  299. // or
  300. //
  301. // We actually grab the MISC section and pull the name from there...
  302. if (!g_lpProgramOptions->GetMode(CProgramOptions::VerifySymbolsModeUsingDBGInMISCSection))
  303. {
  304. // We search for this PE Image by it's actual name...
  305. _tcscpy(tszPEImageModuleName, m_tszPEImageModuleName);
  306. // Compose the DBG filename from the PE Image Name
  307. _tsplitpath(m_tszPEImageModuleName, NULL, NULL, tszDBGModuleName, NULL);
  308. _tcscat(tszDBGModuleName, TEXT(".DBG"));
  309. } else
  310. {
  311. // If we're told to grab the DBG name from the MISC section... and there isn't one...
  312. // bail!
  313. if (!m_tszPEImageDebugDirectoryDBGPath)
  314. goto cleanup;
  315. // Okay, the user wants us to look in the MISC section of the Debug Directories
  316. // to figure out the DBG file location... though the FindDebugInfoFileEx() takes
  317. // as an argument the name of the DBG file... if you provide the PE Image name
  318. // instead, it performs a search that is more "broad"...
  319. // Split the DBG file info found in the MISC section into components...
  320. _tsplitpath(m_tszPEImageDebugDirectoryDBGPath, NULL, NULL, tszDBGModuleName, tszExtModuleName);
  321. // Save the module name found here...
  322. _tcscpy(tszPEImageModuleName, tszDBGModuleName);
  323. // Append the DBG extension back on...
  324. _tcscat(tszDBGModuleName, tszExtModuleName);
  325. // Grab the extension of the PE Image and add it to end of our DBG module name..
  326. _tsplitpath(m_tszPEImageModuleName, NULL, NULL, NULL, tszExtModuleName);
  327. _tcscat(tszPEImageModuleName, tszExtModuleName);
  328. }
  329. // _tcsupr(tszDBGModuleName);
  330. tszSymbolPathWithModulePathPrepended[0] = '\0'; // Fast way to empty this string ;)
  331. if (fDebugSearchPaths)
  332. {
  333. _tprintf(TEXT("DBG Search - Looking for [%s] Using Symbol Path...\n"), tszDBGModuleName);
  334. };
  335. if (g_lpProgramOptions->GetMode(CProgramOptions::BuildSymbolTreeMode) )
  336. {
  337. if (fDebugSearchPaths)
  338. {
  339. _tprintf(TEXT("DBG Search - SEARCH in Symbol Tree We're Building!\n"));
  340. };
  341. // When we are constructing a build symbol tree... we should first
  342. // search there to see if our symbol is already present...
  343. hModuleHandle = CUtilityFunctions::FindDebugInfoFileEx(tszPEImageModuleName, g_lpProgramOptions->GetSymbolTreeToBuild(), tszDebugModulePath, VerifyDBGFile, this);
  344. // Close handle if one is returned...
  345. if (hModuleHandle != NULL)
  346. {
  347. CloseHandle(hModuleHandle);
  348. }
  349. // Hey, if we found it, we're done...
  350. if (GetDBGSymbolModuleStatus() == SYMBOL_MATCH)
  351. {
  352. goto cleanup;
  353. }
  354. }
  355. // Okay, we're not building a symbol tree... or we didn't find our symbol match in
  356. // the symbol tree... keep looking...
  357. // Well... let's search the SymbolPath provided for the DBG file...
  358. if (g_lpProgramOptions->GetMode(CProgramOptions::VerifySymbolsModeWithSymbolPathRecursion))
  359. {
  360. // Do we use recursion???
  361. if (fDebugSearchPaths)
  362. {
  363. _tprintf(TEXT("DBG Search - SEARCH Symbol path with recursion!\n"));
  364. // ISSUE-2000/07/24-GREGWI: Does FindDebugInfoFileEx2 support SYMSRV?
  365. };
  366. hModuleHandle = CUtilityFunctions::FindDebugInfoFileEx2(tszDBGModuleName, tszSymbolPath, VerifyDBGFile, this);
  367. } else
  368. {
  369. // Only do this if we're doing the standard file search mechanism...
  370. if (!g_lpProgramOptions->GetMode(CProgramOptions::VerifySymbolsModeWithSymbolPathOnly))
  371. {
  372. // Don't do this block here if VerifySymbolsModeWithSymbolPathOnly option has been set...
  373. // Hmm... Windbg changed behavior and now prepends the module path to the
  374. // front of the symbolpath before called FindDebugInfoFileEx()...
  375. _tsplitpath(m_tszPEImageModuleFileSystemPath, tszDrive, tszDir, NULL, NULL);
  376. _tcscat(tszSymbolPathWithModulePathPrepended, tszDrive);
  377. _tcscat(tszSymbolPathWithModulePathPrepended, tszDir);
  378. _tcscat(tszSymbolPathWithModulePathPrepended, TEXT(";"));
  379. }
  380. _tcscat(tszSymbolPathWithModulePathPrepended, tszSymbolPath);
  381. if (fDebugSearchPaths)
  382. {
  383. _tprintf(TEXT("DBG Search - SEARCH Symbol path!\n"));
  384. };
  385. // Do we do the standard thing?
  386. hModuleHandle = CUtilityFunctions::FindDebugInfoFileEx(tszPEImageModuleName, tszSymbolPathWithModulePathPrepended, tszDebugModulePath, VerifyDBGFile, this);
  387. }
  388. cleanup:
  389. // If we have a hModuleHandle... free it now..
  390. if (hModuleHandle != NULL)
  391. {
  392. CloseHandle(hModuleHandle);
  393. }
  394. // We found the following path
  395. if (m_tszDBGModuleFileSystemPath)
  396. {
  397. // Okay, let's clean up any "strangeness" added by FindDebugInfoFileEx()
  398. // If a symbol is found in the same directory as the module, it will be
  399. // returned with an extra \.\ combination (which is superfluous normally)...
  400. LPTSTR tszLocationOfExtraJunk = _tcsstr(m_tszDBGModuleFileSystemPath, TEXT("\\.\\"));
  401. if ( tszLocationOfExtraJunk )
  402. {
  403. // Remember where we were...
  404. LPTSTR tszPreviousLocation = tszLocationOfExtraJunk;
  405. // Skip the junk...
  406. tszLocationOfExtraJunk = CharNext(tszLocationOfExtraJunk); // '\\'
  407. tszLocationOfExtraJunk = CharNext(tszLocationOfExtraJunk); // '.'
  408. // While we have data... copy to the old location...
  409. while (*tszLocationOfExtraJunk)
  410. {
  411. *tszPreviousLocation = *tszLocationOfExtraJunk;
  412. tszLocationOfExtraJunk = CharNext(tszLocationOfExtraJunk);
  413. tszPreviousLocation = CharNext(tszPreviousLocation);
  414. }
  415. // Null terminate the module path...
  416. *tszPreviousLocation = '\0';
  417. }
  418. }
  419. if (fDebugSearchPaths)
  420. {
  421. if (GetDBGSymbolModuleStatus() == SYMBOL_MATCH)
  422. {
  423. _tprintf(TEXT("DBG Search - Debug Module Found at [%s]\n\n"), m_tszDBGModuleFileSystemPath);
  424. } else
  425. {
  426. _tprintf(TEXT("DBG Search - Debug Module Not Found.\n\n"));
  427. }
  428. }
  429. return true;
  430. }
  431. bool CModuleInfo::GetDBGModuleFileUsingSQLServer(CSymbolVerification * lpSymbolVerification)
  432. {
  433. // Do we need to initialize the SQL Server Connection?
  434. if (!lpSymbolVerification->SQLServerConnectionInitialized() &&
  435. !lpSymbolVerification->SQLServerConnectionAttempted())
  436. {
  437. if (!lpSymbolVerification->InitializeSQLServerConnection( g_lpProgramOptions->GetSQLServerName() ) )
  438. return false;
  439. }
  440. // Let's only use the SQL Server if it was initialized properly...
  441. if ( lpSymbolVerification->SQLServerConnectionInitialized() )
  442. {
  443. if (!lpSymbolVerification->SearchForDBGFileUsingSQLServer(m_tszPEImageModuleName, m_dwPEImageTimeDateStamp, this))
  444. return false;
  445. }
  446. return true;
  447. }
  448. // begin SQL2 - mjl 12/14/99
  449. bool CModuleInfo::GetDBGModuleFileUsingSQLServer2(CSymbolVerification * lpSymbolVerification)
  450. {
  451. // Do we need to initialize the SQL Server Connection?
  452. if (!lpSymbolVerification->SQLServerConnectionInitialized2() &&
  453. !lpSymbolVerification->SQLServerConnectionAttempted2())
  454. {
  455. if (!lpSymbolVerification->InitializeSQLServerConnection2( g_lpProgramOptions->GetSQLServerName2() ) )
  456. return false;
  457. }
  458. // Let's only use the SQL Server if it was initialized properly...
  459. if ( lpSymbolVerification->SQLServerConnectionInitialized2() )
  460. {
  461. if (!lpSymbolVerification->SearchForDBGFileUsingSQLServer2(m_tszPEImageModuleName, m_dwPEImageTimeDateStamp, this))
  462. return false;
  463. }
  464. return true;
  465. }
  466. bool CModuleInfo::GetPDBModuleFileUsingSQLServer2(CSymbolVerification * lpSymbolVerification)
  467. {
  468. // Do we need to initialize the SQL Server Connection?
  469. if (!lpSymbolVerification->SQLServerConnectionInitialized2() &&
  470. !lpSymbolVerification->SQLServerConnectionAttempted2())
  471. {
  472. if (!lpSymbolVerification->InitializeSQLServerConnection2( g_lpProgramOptions->GetSQLServerName2() ) )
  473. return false;
  474. }
  475. // Let's only use the SQL Server if it was initialized properly...
  476. if ( lpSymbolVerification->SQLServerConnectionInitialized2() )
  477. {
  478. if (!lpSymbolVerification->SearchForPDBFileUsingSQLServer2(m_tszPEImageModuleName, m_dwPEImageDebugDirectoryPDBSignature, this))
  479. return false;
  480. }
  481. return true;
  482. }
  483. // end SQL2 - mjl 12/14/99
  484. bool CModuleInfo::fValidDBGCheckSum()
  485. {
  486. if (m_enumDBGModuleStatus == SYMBOL_MATCH)
  487. return true;
  488. if ((g_lpProgramOptions->GetVerificationLevel() == 1) && fValidDBGTimeDateStamp())
  489. return true;
  490. if (m_enumDBGModuleStatus == SYMBOL_POSSIBLE_MISMATCH)
  491. return (m_dwPEImageCheckSum == m_dwDBGCheckSum);
  492. return false;
  493. }
  494. bool CModuleInfo::fValidDBGTimeDateStamp()
  495. {
  496. return ( (m_enumDBGModuleStatus == SYMBOL_POSSIBLE_MISMATCH) ||
  497. (m_enumDBGModuleStatus == SYMBOL_MATCH) )
  498. ? (m_dwPEImageTimeDateStamp == m_dwDBGTimeDateStamp ) : false;
  499. }
  500. bool CModuleInfo::GetPDBModuleFileUsingSymbolPath()
  501. {
  502. enum {
  503. niNil = 0,
  504. PDB_MAX_PATH = 260,
  505. cbErrMax = 1024,
  506. };
  507. HANDLE hModuleHandle = NULL;
  508. TCHAR tszSymbolPathWithModulePathPrepended[_MAX_PATH+_MAX_PATH+1];
  509. bool fSuccess = false;
  510. TCHAR tszRefPath[_MAX_PATH];
  511. TCHAR tszImageExt[_MAX_EXT] = {0}; // In case there is no extension we need to null terminate now...
  512. char szPDBOut[cbErrMax];
  513. TCHAR tszPDBModuleName[_MAX_FNAME];
  514. LPTSTR pcEndOfPath = NULL;
  515. tszPDBModuleName[0] = '\0';
  516. tszSymbolPathWithModulePathPrepended[0] = '\0';
  517. bool fDebugSearchPaths = g_lpProgramOptions->fDebugSearchPaths();
  518. _tsplitpath(m_tszPEImageModuleFileSystemPath, NULL, NULL, NULL, tszImageExt);
  519. // Copy the symbol name we're searching for from the Debug Directories
  520. //LPTSTR lptszPointerToPDBName = _tcsrchr(m_tszDebugDirectoryPDBPath, '\\');
  521. LPTSTR lptszPointerToPDBName = _tcsrchr(GetDebugDirectoryPDBPath(), '\\');
  522. // If we don't find a \ char, then go ahead and copy the PDBPath directly...
  523. if (lptszPointerToPDBName == NULL)
  524. {
  525. //_tcscpy(tszPDBModuleName, m_tszDebugDirectoryPDBPath);
  526. _tcscpy(tszPDBModuleName, GetDebugDirectoryPDBPath());
  527. } else
  528. {
  529. // Advance past the \ char...
  530. lptszPointerToPDBName = CharNext(lptszPointerToPDBName);
  531. _tcscpy(tszPDBModuleName, lptszPointerToPDBName);
  532. }
  533. if (fDebugSearchPaths)
  534. {
  535. //_tprintf(TEXT("PDB Search - Looking for [%s] Using Symbol Path...\n"), g_lpProgramOptions->GetMode(CProgramOptions::VerifySymbolsModeWithSymbolPathOnly) ? tszPDBModuleName : m_tszDebugDirectoryPDBPath);
  536. _tprintf(TEXT("PDB Search - Looking for [%s] Using Symbol Path...\n"), g_lpProgramOptions->GetMode(CProgramOptions::VerifySymbolsModeWithSymbolPathOnly) ? tszPDBModuleName : GetDebugDirectoryPDBPath());
  537. };
  538. if (g_lpProgramOptions->GetMode(CProgramOptions::BuildSymbolTreeMode) )
  539. {
  540. // When we are constructing a build symbol tree... we should first
  541. // search there to see if our symbol is already present...
  542. // Do we do the standard thing?
  543. if (fDebugSearchPaths)
  544. {
  545. _tprintf(TEXT("PDB Search - SEARCH in Symbol Tree We're Building!\n"));
  546. };
  547. //fSuccess = LocatePdb(g_lpProgramOptions->GetMode(CProgramOptions::VerifySymbolsModeWithSymbolPathOnly) ? tszPDBModuleName : m_tszDebugDirectoryPDBPath,
  548. fSuccess = LocatePdb(g_lpProgramOptions->GetMode(CProgramOptions::VerifySymbolsModeWithSymbolPathOnly) ? tszPDBModuleName : GetDebugDirectoryPDBPath(),
  549. m_dwPEImageDebugDirectoryPDBAge,
  550. m_dwPEImageDebugDirectoryPDBSignature,
  551. g_lpProgramOptions->GetSymbolTreeToBuild(),
  552. &tszImageExt[1],
  553. false);
  554. // Hey, if we found it, we're done...
  555. if (fSuccess)
  556. {
  557. goto cleanup;
  558. }
  559. }
  560. if (!g_lpProgramOptions->GetMode(CProgramOptions::VerifySymbolsModeWithSymbolPathOnly))
  561. {
  562. // Hey, we better have one or the other...
  563. if (!m_tszDBGModuleFileSystemPath && !m_tszPEImageModuleFileSystemPath)
  564. goto cleanup;
  565. // figure out the home directory of the EXE/DLL or DBG file - pass that along to
  566. // OpenValidate this will direct to dbi to search for it in that directory.
  567. _tfullpath(tszRefPath, m_tszDBGModuleFileSystemPath ? m_tszDBGModuleFileSystemPath : m_tszPEImageModuleFileSystemPath, sizeof(tszRefPath)/sizeof(TCHAR));
  568. pcEndOfPath = _tcsrchr(tszRefPath, '\\');
  569. *pcEndOfPath = '\0'; // null terminate it
  570. *szPDBOut = '\0';
  571. if (_MAX_PATH+_MAX_PATH+1 < (_tcsclen(tszRefPath) + _tcsclen(g_lpProgramOptions->GetSymbolPath())+2))
  572. goto cleanup; // Buffer isn't big enough... sigh...
  573. _tcscat(tszSymbolPathWithModulePathPrepended, tszRefPath);
  574. _tcscat(tszSymbolPathWithModulePathPrepended, TEXT(";"));
  575. }
  576. _tcscat(tszSymbolPathWithModulePathPrepended, g_lpProgramOptions->GetSymbolPath());
  577. // Well... let's search the SymbolPath provided for the PDB file...
  578. if (g_lpProgramOptions->GetMode(CProgramOptions::VerifySymbolsModeWithSymbolPathRecursion))
  579. {
  580. if (fDebugSearchPaths)
  581. {
  582. _tprintf(TEXT("PDB Search - SEARCH Symbol path with recursion!\n"));
  583. // ISSUE-2000/07/24-GREGWI: Does FindDebugInfoFileEx2 support SYMSRV?
  584. };
  585. // Do we use recursion???
  586. // ISSUE-2000/07/24-GREGWI - Are we passing the right first arg? Is this supported?
  587. hModuleHandle = CUtilityFunctions::FindDebugInfoFileEx2(tszPDBModuleName, tszSymbolPathWithModulePathPrepended, VerifyPDBFile, this);
  588. if (hModuleHandle != NULL)
  589. {
  590. CloseHandle(hModuleHandle);
  591. }
  592. fSuccess = false;
  593. } else
  594. {
  595. if (fDebugSearchPaths)
  596. {
  597. _tprintf(TEXT("PDB Search - SEARCH Symbol path!\n"));
  598. };
  599. // Search for the PDB file the old fashioned way...
  600. // fSuccess = LocatePdb(g_lpProgramOptions->GetMode(CProgramOptions::VerifySymbolsModeWithSymbolPathOnly) ? tszPDBModuleName : m_tszDebugDirectoryPDBPath,
  601. if (m_enumPEImageSymbolStatus == SYMBOLS_PDB)
  602. {
  603. fSuccess = LocatePdb(g_lpProgramOptions->GetMode(CProgramOptions::VerifySymbolsModeWithSymbolPathOnly) ? tszPDBModuleName : GetDebugDirectoryPDBPath(),
  604. m_dwPEImageDebugDirectoryPDBAge,
  605. m_dwPEImageDebugDirectoryPDBSignature,
  606. tszSymbolPathWithModulePathPrepended,
  607. &tszImageExt[1],
  608. false);
  609. } else
  610. {
  611. fSuccess = LocatePdb(g_lpProgramOptions->GetMode(CProgramOptions::VerifySymbolsModeWithSymbolPathOnly) ? tszPDBModuleName : GetDebugDirectoryPDBPath(),
  612. m_dwDBGDebugDirectoryPDBAge,
  613. m_dwDBGDebugDirectoryPDBSignature,
  614. tszSymbolPathWithModulePathPrepended,
  615. &tszImageExt[1],
  616. false);
  617. }
  618. }
  619. cleanup:
  620. if (fDebugSearchPaths)
  621. {
  622. if (GetPDBSymbolModuleStatus() == SYMBOL_MATCH)
  623. {
  624. _tprintf(TEXT("PDB Search - Debug Module Found at [%s]\n\n"), m_tszPDBModuleFileSystemPath);
  625. } else
  626. {
  627. _tprintf(TEXT("PDB Search - Debug Module Not Found.\n\n"));
  628. }
  629. }
  630. return fSuccess;
  631. }
  632. BOOL CModuleInfo::VerifyPDBFile(HANDLE hFileHandle, LPTSTR tszFileName, PVOID CallerData)
  633. {
  634. PDB * lpPdb = NULL;
  635. EC ec = 0;
  636. char szError[cbErrMax] = "";
  637. bool fPdbModuleFound = false;
  638. char szFileName[_MAX_FNAME+1];
  639. hFileHandle = INVALID_HANDLE_VALUE;
  640. // Let's grab the data passed to us...
  641. CModuleInfo * lpModuleInfo = (CModuleInfo *) CallerData; // mjl
  642. CUtilityFunctions::CopyTSTRStringToAnsi(tszFileName, szFileName, _MAX_FNAME+1);
  643. PDBOpenValidate(szFileName, NULL, pdbRead, lpModuleInfo->m_dwPEImageDebugDirectoryPDBSignature, lpModuleInfo->m_dwPEImageDebugDirectoryPDBAge, &ec, szError, &lpPdb);
  644. // Based on the return code, the path may be saved, and the PDB Module Status
  645. // updated...
  646. fPdbModuleFound = lpModuleInfo->HandlePDBOpenValidateReturn(lpPdb, tszFileName, ec);
  647. if (lpPdb)
  648. {
  649. PDBClose(lpPdb);
  650. lpPdb = NULL;
  651. }
  652. return fPdbModuleFound ? (ec == EC_OK) : FALSE;
  653. }
  654. bool
  655. CModuleInfo::LocatePdb(
  656. LPTSTR tszPDB,
  657. ULONG PdbAge,
  658. ULONG PdbSignature,
  659. LPTSTR tszSymbolPath,
  660. LPTSTR tszImageExt,
  661. bool fImagePathPassed
  662. )
  663. {
  664. PDB *lpPdb = NULL;
  665. EC ec = 0;
  666. char szError[cbErrMax] = "";
  667. TCHAR tszPDBSansPath[_MAX_FNAME];
  668. TCHAR tszPDBExt[_MAX_EXT];
  669. TCHAR tszPDBLocal[_MAX_PATH];
  670. char szPDBLocal[_MAX_PATH];
  671. LPTSTR ptszSemiColon;
  672. DWORD pass;
  673. BOOL symsrv = TRUE;
  674. TCHAR tszPDBName[_MAX_PATH];
  675. bool fDebugSearchPaths = g_lpProgramOptions->fDebugSearchPaths();
  676. // We're pessimistic initially...
  677. m_enumPDBModuleStatus = SYMBOL_NOT_FOUND;
  678. bool fPdbModuleFound = false;
  679. // szSymbolPath is a semicolon delimited path (reference path first)
  680. _tcscpy(tszPDBLocal, tszPDB);
  681. _tsplitpath(tszPDBLocal, NULL, NULL, tszPDBSansPath, tszPDBExt);
  682. do {
  683. ptszSemiColon = _tcschr(tszSymbolPath, ';');
  684. if (ptszSemiColon) {
  685. *ptszSemiColon = '\0';
  686. }
  687. if (fImagePathPassed) {
  688. pass = 2;
  689. fImagePathPassed = 0;
  690. } else {
  691. pass = 0;
  692. }
  693. if (tszSymbolPath) {
  694. do_again:
  695. if (!_tcsnicmp(tszSymbolPath, TEXT("SYMSRV*"), 7)) {
  696. *tszPDBLocal = 0;
  697. _stprintf(tszPDBName, TEXT("%s%s"), tszPDBSansPath, TEXT(".pdb"));
  698. if (symsrv) {
  699. if (fDebugSearchPaths)
  700. {
  701. _tprintf(TEXT("PDB Search - SYMSRV [%s,0x%x,0x%x]\n"),
  702. tszSymbolPath,
  703. PdbSignature,
  704. PdbAge);
  705. }
  706. CUtilityFunctions::GetSymbolFileFromServer(tszSymbolPath,
  707. tszPDBName,
  708. PdbSignature,
  709. PdbAge,
  710. 0,
  711. tszPDBLocal);
  712. symsrv = FALSE;
  713. }
  714. } else {
  715. _tcscpy(tszPDBLocal, tszSymbolPath);
  716. CUtilityFunctions::EnsureTrailingBackslash(tszPDBLocal);
  717. // search order is ...
  718. //
  719. // %dir%\symbols\%ext%\%file%
  720. // %dir%\%ext%\%file%
  721. // %dir%\%file%
  722. switch (pass)
  723. {
  724. case 0:
  725. _tcscat(tszPDBLocal, TEXT("symbols"));
  726. CUtilityFunctions::EnsureTrailingBackslash(tszPDBLocal);
  727. // pass through
  728. case 1:
  729. _tcscat(tszPDBLocal, tszImageExt);
  730. // pass through
  731. default:
  732. CUtilityFunctions::EnsureTrailingBackslash(tszPDBLocal);
  733. break;
  734. }
  735. _tcscat(tszPDBLocal, tszPDBSansPath);
  736. _tcscat(tszPDBLocal, tszPDBExt);
  737. }
  738. // Okay... at this point we may have a path to a PDB file to examine...
  739. // If so, then issue the PDBOpenValidate() and attempt to verify it...
  740. if (*tszPDBLocal)
  741. {
  742. CUtilityFunctions::CopyTSTRStringToAnsi(tszPDBLocal, szPDBLocal, _MAX_PATH);
  743. if (fDebugSearchPaths)
  744. {
  745. _tprintf(TEXT("PDB Search - Search here [%s]\n"), tszPDBLocal);
  746. }
  747. PDBOpenValidate(szPDBLocal, NULL, "r", PdbSignature, PdbAge, &ec, szError, &lpPdb);
  748. if (lpPdb)
  749. {
  750. fPdbModuleFound = true;
  751. }
  752. // Based on the return code, the path may be saved, and the PDB Module Status
  753. // updated...
  754. if ( !HandlePDBOpenValidateReturn(lpPdb, tszPDBLocal, ec) )
  755. goto cleanup;
  756. if (fPdbModuleFound)
  757. {
  758. PDBClose(lpPdb);
  759. lpPdb = NULL;
  760. break;
  761. } else
  762. {
  763. if (pass < 2)
  764. {
  765. pass++;
  766. goto do_again;
  767. }
  768. }
  769. }
  770. }
  771. // If we found a semicolon before... then restore the semi... and move just beyond it...
  772. // Enable our symsrv searching again...
  773. if (ptszSemiColon) {
  774. *ptszSemiColon = ';';
  775. ptszSemiColon++;
  776. symsrv = TRUE;
  777. }
  778. // Reset the tszSymbolPath to the new location...
  779. tszSymbolPath = ptszSemiColon;
  780. } while (ptszSemiColon);
  781. // Only try this last check if we're not bound to our Symbol Path Only
  782. if (!g_lpProgramOptions->GetMode(CProgramOptions::VerifySymbolsModeWithSymbolPathOnly))
  783. {
  784. // Okay... if pdb is still not found... then try the tszPDB location...
  785. if (!lpPdb)
  786. {
  787. // ISSUE-2000/07/24-GREGWI: Is it required to copy the tszPDB string here?
  788. _tcscpy(tszPDBLocal, tszPDB);
  789. CUtilityFunctions::CopyTSTRStringToAnsi(tszPDBLocal, szPDBLocal, _MAX_PATH);
  790. if (fDebugSearchPaths)
  791. {
  792. _tprintf(TEXT("PDB Search - Search here [%s]\n"), tszPDBLocal);
  793. }
  794. PDBOpenValidate(szPDBLocal, NULL, "r", PdbSignature, PdbAge, &ec, szError, &lpPdb);
  795. if ( !HandlePDBOpenValidateReturn(lpPdb, tszPDBLocal, ec) )
  796. goto cleanup;
  797. if (lpPdb)
  798. {
  799. fPdbModuleFound = true;
  800. PDBClose(lpPdb);
  801. lpPdb = NULL;
  802. }
  803. }
  804. }
  805. cleanup:
  806. return fPdbModuleFound;
  807. }
  808. BOOL CModuleInfo::VerifyDBGFile(HANDLE hFileHandle, LPTSTR tszFileName, PVOID CallerData)
  809. {
  810. CModuleInfo * lpModuleInfo = (CModuleInfo * )CallerData;
  811. WORD wMagic; // Read to identify a DBG file...
  812. bool fPerfectMatch = false; // Assume we don't have a good DBG match...
  813. // DBG Image Locals
  814. IMAGE_SEPARATE_DEBUG_HEADER ImageSeparateDebugHeader;
  815. // Start at the top of the image...
  816. lpModuleInfo->SetReadPointer(false, hFileHandle, 0, FILE_BEGIN);
  817. // Read in a signature word... is this a DBG file?
  818. if ( !lpModuleInfo->DoRead(false, hFileHandle, &wMagic, sizeof(wMagic) ) )
  819. goto cleanup;
  820. // No sense in going further since we're expecting a DBG image file...
  821. if (wMagic != IMAGE_SEPARATE_DEBUG_SIGNATURE)
  822. goto cleanup;
  823. // Start at the top of the image...
  824. lpModuleInfo->SetReadPointer(false, hFileHandle, 0, FILE_BEGIN);
  825. // Read in the full Separate Debug Header
  826. if ( !lpModuleInfo->DoRead(false, hFileHandle, &ImageSeparateDebugHeader, sizeof(ImageSeparateDebugHeader) ) )
  827. goto cleanup;
  828. //
  829. // We have a more stringent requirement for matching the checksum if the verification level is set...
  830. //
  831. if ( (lpModuleInfo->m_dwPEImageTimeDateStamp == ImageSeparateDebugHeader.TimeDateStamp ) &&
  832. (lpModuleInfo->m_dwPEImageSizeOfImage == ImageSeparateDebugHeader.SizeOfImage ) )
  833. {
  834. if (g_lpProgramOptions->GetVerificationLevel() == 2)
  835. {
  836. if (lpModuleInfo->m_dwPEImageCheckSum == ImageSeparateDebugHeader.CheckSum)
  837. fPerfectMatch = true;
  838. } else
  839. {
  840. fPerfectMatch = true;
  841. }
  842. }
  843. //
  844. // We're going to perform some action below unless this is not a perfect match
  845. // and we've already picked up a "bad" DBG file reference...
  846. //
  847. if (!fPerfectMatch && lpModuleInfo->m_tszDBGModuleFileSystemPath)
  848. goto cleanup;
  849. //
  850. // Take action based on our results...
  851. // 1. If we have a perfect match... save our stuff!
  852. // 2. If we don't already have a DBG, go ahead and save (even if wrong)
  853. //
  854. // Save off the checksum/linker information...
  855. lpModuleInfo->m_dwDBGTimeDateStamp = ImageSeparateDebugHeader.TimeDateStamp;
  856. lpModuleInfo->m_dwDBGCheckSum = ImageSeparateDebugHeader.CheckSum;
  857. lpModuleInfo->m_dwDBGSizeOfImage = ImageSeparateDebugHeader.SizeOfImage;
  858. // If we already had a path to a wrong DBG file, delete it...
  859. if (lpModuleInfo->m_tszDBGModuleFileSystemPath)
  860. {
  861. delete [] lpModuleInfo->m_tszDBGModuleFileSystemPath;
  862. lpModuleInfo->m_tszDBGModuleFileSystemPath = NULL;
  863. }
  864. // Save the Module Path now that we know we have a match...
  865. // Okay, let's save off the path to the DBG file...
  866. lpModuleInfo->m_tszDBGModuleFileSystemPath = (LPTSTR)CUtilityFunctions::CopyString(tszFileName);
  867. // Delete any PDB reference we may have found in our last DBG file (if any)...
  868. if (lpModuleInfo->m_tszDBGDebugDirectoryPDBPath)
  869. {
  870. delete [] lpModuleInfo->m_tszDBGDebugDirectoryPDBPath;
  871. lpModuleInfo->m_tszDBGDebugDirectoryPDBPath = NULL;
  872. }
  873. //
  874. // At this point, we only continue on if we've made a perfect "hit"
  875. //
  876. if (!fPerfectMatch)
  877. {
  878. // Not a perfect symbol.. record the status and exit...
  879. lpModuleInfo->m_enumDBGModuleStatus = SYMBOL_POSSIBLE_MISMATCH;
  880. goto cleanup;
  881. }
  882. // Good symbol.. record this...
  883. lpModuleInfo->m_enumDBGModuleStatus = SYMBOL_MATCH;
  884. // Now that we're done verifying the module... do we save the symbol in
  885. // our tree?
  886. if ( g_lpProgramOptions->GetMode(CProgramOptions::BuildSymbolTreeMode) )
  887. {
  888. // Yup...
  889. CUtilityFunctions::CopySymbolFileToSymbolTree(lpModuleInfo->m_tszPEImageModuleName, &lpModuleInfo->m_tszDBGModuleFileSystemPath, g_lpProgramOptions->GetSymbolTreeToBuild());
  890. }
  891. //
  892. // Okay, now with a good symbol let's extract the goods...
  893. //
  894. // If there's no debug info, we can't continue further.
  895. if (ImageSeparateDebugHeader.DebugDirectorySize == 0)
  896. {
  897. goto cleanup;
  898. }
  899. // Okay, we need to advance by the IMAGE_SECTION_HEADER...
  900. lpModuleInfo->SetReadPointer(false, hFileHandle, (ImageSeparateDebugHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER)), FILE_CURRENT);
  901. // Skip over the exported names.
  902. if (ImageSeparateDebugHeader.ExportedNamesSize)
  903. {
  904. lpModuleInfo->SetReadPointer(false, hFileHandle, ImageSeparateDebugHeader.ExportedNamesSize, FILE_CURRENT);
  905. }
  906. if (!lpModuleInfo->ProcessDebugDirectory(false, false, hFileHandle, ImageSeparateDebugHeader.DebugDirectorySize, lpModuleInfo->GetReadPointer()))
  907. goto cleanup;
  908. cleanup:
  909. return (fPerfectMatch ? TRUE : FALSE);
  910. }
  911. bool CModuleInfo::OutputDataToFile(LPTSTR tszProcessName, DWORD iProcessID)
  912. {
  913. LPTSTR tszString = NULL;
  914. bool fReturn = false;
  915. // We remove the first three columns if -E was specified...
  916. if (!g_lpProgramOptions->GetMode(CProgramOptions::ExceptionMonitorMode))
  917. {
  918. // Let's skip the first column to make room for the tag in the first column...
  919. if (!m_lpOutputFile->WriteString(TEXT(",")))
  920. goto cleanup;
  921. //
  922. // Process Name
  923. //
  924. if (tszProcessName)
  925. {
  926. if (!m_lpOutputFile->WriteString(tszProcessName, true))
  927. goto cleanup;
  928. }
  929. if (!m_lpOutputFile->WriteString(TEXT(",")))
  930. goto cleanup;
  931. //
  932. // BUG 524 - GREGWI - CheckSym - Unable to read CSV file generated on Windows 2000 Machine
  933. // (I changed the code to emit the PID no matter what it's value, I was special casing 0)
  934. //
  935. // Process ID
  936. //
  937. // ISSUE-2000/07/24-GREGWI: Put conditional write back in (only emit if this is PROCESSES collection
  938. // ISSUE-2000/07/24-GREGWI: we don't want to see 0 as the PID for any other collection....
  939. if (tszProcessName)
  940. {
  941. // Let's only emit the PID if there is a process name...
  942. if (!m_lpOutputFile->WriteDWORD(iProcessID))
  943. goto cleanup;
  944. }
  945. if (!m_lpOutputFile->WriteString(TEXT(",")))
  946. goto cleanup;
  947. }
  948. // if -E is specified, we only spit out if the module has a problem
  949. if ( g_lpProgramOptions->GetMode(CProgramOptions::ExceptionMonitorMode) )
  950. {
  951. switch (m_enumPEImageSymbolStatus)
  952. {
  953. case SYMBOLS_DBG:
  954. if ( m_enumDBGModuleStatus == SYMBOL_MATCH)
  955. {
  956. // Don't print this out.. it matches...
  957. fReturn = true;
  958. goto cleanup;
  959. }
  960. break;
  961. case SYMBOLS_DBG_AND_PDB:
  962. if ( m_enumDBGModuleStatus == SYMBOL_MATCH &&
  963. m_enumPDBModuleStatus == SYMBOL_MATCH )
  964. {
  965. // Don't print this out.. it matches...
  966. fReturn = true;
  967. goto cleanup;
  968. }
  969. break;
  970. case SYMBOLS_PDB:
  971. if ( m_enumPDBModuleStatus == SYMBOL_MATCH)
  972. {
  973. // Don't print this out.. it matches...
  974. fReturn = true;
  975. goto cleanup;
  976. }
  977. break;
  978. }
  979. }
  980. //
  981. // Module Path
  982. //
  983. if (m_tszPEImageModuleFileSystemPath)
  984. {
  985. if (!m_lpOutputFile->WriteString(m_tszPEImageModuleFileSystemPath, true))
  986. goto cleanup;
  987. }
  988. if (!m_lpOutputFile->WriteString(TEXT(",")))
  989. goto cleanup;
  990. //
  991. // Symbol Status
  992. //
  993. if (m_enumPEImageSymbolStatus != SYMBOL_INFORMATION_UNKNOWN)
  994. {
  995. tszString = SymbolInformationString(m_enumPEImageSymbolStatus);
  996. if (tszString)
  997. {
  998. if (!m_lpOutputFile->WriteString(tszString))
  999. goto cleanup;
  1000. }
  1001. }
  1002. if (!m_lpOutputFile->WriteString(TEXT(",")))
  1003. goto cleanup;
  1004. // We remove this column if -E is specified
  1005. if (!g_lpProgramOptions->GetMode(CProgramOptions::ExceptionMonitorMode))
  1006. {
  1007. //
  1008. // Checksum
  1009. //
  1010. if ( m_enumPEImageSymbolStatus != SYMBOL_INFORMATION_UNKNOWN )
  1011. {
  1012. if (!m_lpOutputFile->WriteDWORD(m_dwPEImageCheckSum))
  1013. goto cleanup;
  1014. }
  1015. if (!m_lpOutputFile->WriteString(TEXT(",")))
  1016. goto cleanup;
  1017. //
  1018. // Time/Date Stamp
  1019. //
  1020. if ( m_enumPEImageSymbolStatus != SYMBOL_INFORMATION_UNKNOWN )
  1021. {
  1022. if (!m_lpOutputFile->WriteDWORD(m_dwPEImageTimeDateStamp))
  1023. goto cleanup;
  1024. }
  1025. if (!m_lpOutputFile->WriteString(TEXT(",")))
  1026. goto cleanup;
  1027. }
  1028. //
  1029. // Time/Date String
  1030. //
  1031. // If -E is specified we'll use version2 of the output format...
  1032. if (!g_lpProgramOptions->GetMode(CProgramOptions::ExceptionMonitorMode))
  1033. {
  1034. if ( m_enumPEImageSymbolStatus != SYMBOL_INFORMATION_UNKNOWN )
  1035. {
  1036. if (!m_lpOutputFile->WriteTimeDateString(m_dwPEImageTimeDateStamp))
  1037. goto cleanup;
  1038. }
  1039. } else
  1040. {
  1041. if (!m_lpOutputFile->WriteTimeDateString2(m_dwPEImageTimeDateStamp))
  1042. goto cleanup;
  1043. }
  1044. if (!m_lpOutputFile->WriteString(TEXT(",")))
  1045. goto cleanup;
  1046. // We remove these columns if -E is specified
  1047. if (!g_lpProgramOptions->GetMode(CProgramOptions::ExceptionMonitorMode))
  1048. {
  1049. //
  1050. // Size Of Image (internal PE value) - used for SYMSRV support
  1051. //
  1052. if (!m_lpOutputFile->WriteDWORD(m_dwPEImageSizeOfImage))
  1053. goto cleanup;
  1054. if (!m_lpOutputFile->WriteString(TEXT(",")))
  1055. goto cleanup;
  1056. //
  1057. // DBG Pointer
  1058. //
  1059. if ( m_enumPEImageSymbolStatus == SYMBOLS_DBG ||
  1060. m_enumPEImageSymbolStatus == SYMBOLS_DBG_AND_PDB )
  1061. {
  1062. // Output the Path
  1063. if (m_tszPEImageDebugDirectoryDBGPath)
  1064. {
  1065. if (!m_lpOutputFile->WriteString(m_tszPEImageDebugDirectoryDBGPath, true))
  1066. goto cleanup;
  1067. }
  1068. }
  1069. if (!m_lpOutputFile->WriteString(TEXT(",")))
  1070. goto cleanup;
  1071. //
  1072. // PDB Pointer
  1073. //
  1074. if ( m_enumPEImageSymbolStatus == SYMBOLS_PDB )
  1075. {
  1076. // Output the Path
  1077. if (GetDebugDirectoryPDBPath())
  1078. {
  1079. if (!m_lpOutputFile->WriteString(GetDebugDirectoryPDBPath(), true))
  1080. goto cleanup;
  1081. }
  1082. }
  1083. if (!m_lpOutputFile->WriteString(TEXT(",")))
  1084. goto cleanup;
  1085. //
  1086. // PDB Signature
  1087. //
  1088. if ( m_enumPEImageSymbolStatus == SYMBOLS_PDB )
  1089. {
  1090. if (!m_lpOutputFile->WriteDWORD(m_dwPEImageDebugDirectoryPDBSignature))
  1091. goto cleanup;
  1092. }
  1093. if (!m_lpOutputFile->WriteString(TEXT(",")))
  1094. goto cleanup;
  1095. //
  1096. // PDB Age
  1097. //
  1098. if ( m_enumPEImageSymbolStatus == SYMBOLS_PDB )
  1099. {
  1100. if (!m_lpOutputFile->WriteDWORD(m_dwPEImageDebugDirectoryPDBAge))
  1101. goto cleanup;
  1102. }
  1103. if (!m_lpOutputFile->WriteString(TEXT(",")))
  1104. goto cleanup;
  1105. }
  1106. //
  1107. // Product Version
  1108. //
  1109. // We remove these columns if -E is specified
  1110. if (!g_lpProgramOptions->GetMode(CProgramOptions::ExceptionMonitorMode))
  1111. {
  1112. if (m_fPEImageFileVersionInfo && m_tszPEImageProductVersionString)
  1113. {
  1114. if (!m_lpOutputFile->WriteString(m_tszPEImageProductVersionString))
  1115. goto cleanup;
  1116. }
  1117. if (!m_lpOutputFile->WriteString(TEXT(",")))
  1118. goto cleanup;
  1119. }
  1120. //
  1121. // File Version
  1122. //
  1123. if (m_fPEImageFileVersionInfo && m_tszPEImageFileVersionString)
  1124. {
  1125. if (!m_lpOutputFile->WriteString(m_tszPEImageFileVersionString))
  1126. goto cleanup;
  1127. }
  1128. if (!m_lpOutputFile->WriteString(TEXT(",")))
  1129. goto cleanup;
  1130. //
  1131. // Company Name
  1132. //
  1133. if (m_fPEImageFileVersionInfo && m_tszPEImageFileVersionCompanyName)
  1134. {
  1135. if (!m_lpOutputFile->WriteString(m_tszPEImageFileVersionCompanyName, true))
  1136. goto cleanup;
  1137. }
  1138. if (!m_lpOutputFile->WriteString(TEXT(",")))
  1139. goto cleanup;
  1140. //
  1141. // File Description
  1142. //
  1143. if (m_fPEImageFileVersionInfo && m_tszPEImageFileVersionDescription)
  1144. {
  1145. if (!m_lpOutputFile->WriteString(m_tszPEImageFileVersionDescription, true))
  1146. goto cleanup;
  1147. }
  1148. if (!m_lpOutputFile->WriteString(TEXT(",")))
  1149. goto cleanup;
  1150. // We remove these columns if -E is specified
  1151. if (!g_lpProgramOptions->GetMode(CProgramOptions::ExceptionMonitorMode))
  1152. {
  1153. //
  1154. // File Size (in bytes)
  1155. //
  1156. if ( m_dwPEImageFileSize )
  1157. {
  1158. if (!m_lpOutputFile->WriteDWORD(m_dwPEImageFileSize))
  1159. goto cleanup;
  1160. }
  1161. if (!m_lpOutputFile->WriteString(TEXT(",")))
  1162. goto cleanup;
  1163. // File Date High Word
  1164. if ( m_ftPEImageFileTimeDateStamp.dwLowDateTime ||
  1165. m_ftPEImageFileTimeDateStamp.dwHighDateTime )
  1166. {
  1167. if (!m_lpOutputFile->WriteDWORD(m_ftPEImageFileTimeDateStamp.dwHighDateTime))
  1168. goto cleanup;
  1169. }
  1170. if (!m_lpOutputFile->WriteString(TEXT(",")))
  1171. goto cleanup;
  1172. // File Date Low Word
  1173. if ( m_ftPEImageFileTimeDateStamp.dwLowDateTime ||
  1174. m_ftPEImageFileTimeDateStamp.dwHighDateTime )
  1175. {
  1176. if (!m_lpOutputFile->WriteDWORD(m_ftPEImageFileTimeDateStamp.dwLowDateTime))
  1177. goto cleanup;
  1178. }
  1179. if (!m_lpOutputFile->WriteString(TEXT(",")))
  1180. goto cleanup;
  1181. }
  1182. // File Date String
  1183. if ( m_ftPEImageFileTimeDateStamp.dwLowDateTime ||
  1184. m_ftPEImageFileTimeDateStamp.dwHighDateTime )
  1185. {
  1186. // If -E is specified we'll use version2 of the output format...
  1187. if (!g_lpProgramOptions->GetMode(CProgramOptions::ExceptionMonitorMode))
  1188. {
  1189. if (!m_lpOutputFile->WriteFileTimeString(m_ftPEImageFileTimeDateStamp))
  1190. goto cleanup;
  1191. } else
  1192. {
  1193. if (!m_lpOutputFile->WriteFileTimeString2(m_ftPEImageFileTimeDateStamp))
  1194. goto cleanup;
  1195. }
  1196. }
  1197. if (!m_lpOutputFile->WriteString(TEXT(",")))
  1198. goto cleanup;
  1199. if (g_lpProgramOptions->GetMode(CProgramOptions::VerifySymbolsMode))
  1200. {
  1201. //
  1202. // Local DBG Status
  1203. //
  1204. if ( (m_enumPEImageSymbolStatus == SYMBOLS_DBG) || (m_enumPEImageSymbolStatus == SYMBOLS_DBG_AND_PDB) )
  1205. {
  1206. tszString = SymbolModuleStatusString(m_enumDBGModuleStatus);
  1207. if (tszString)
  1208. {
  1209. if (!m_lpOutputFile->WriteString(tszString))
  1210. goto cleanup;
  1211. }
  1212. }
  1213. if (!m_lpOutputFile->WriteString(TEXT(",")))
  1214. goto cleanup;
  1215. //
  1216. // Local DBG
  1217. //
  1218. if ( (m_enumPEImageSymbolStatus == SYMBOLS_DBG) || (m_enumPEImageSymbolStatus == SYMBOLS_DBG_AND_PDB) )
  1219. {
  1220. if (m_tszDBGModuleFileSystemPath)
  1221. {
  1222. if (!m_lpOutputFile->WriteString(m_tszDBGModuleFileSystemPath, true))
  1223. goto cleanup;
  1224. }
  1225. }
  1226. if (!m_lpOutputFile->WriteString(TEXT(",")))
  1227. goto cleanup;
  1228. //
  1229. // Local PDB Status
  1230. //
  1231. if ( (m_enumPEImageSymbolStatus == SYMBOLS_DBG_AND_PDB) || (m_enumPEImageSymbolStatus == SYMBOLS_PDB) )
  1232. {
  1233. tszString = SymbolModuleStatusString(m_enumPDBModuleStatus);
  1234. if (tszString)
  1235. {
  1236. if (!m_lpOutputFile->WriteString(tszString))
  1237. goto cleanup;
  1238. }
  1239. }
  1240. if (!m_lpOutputFile->WriteString(TEXT(",")))
  1241. goto cleanup;
  1242. //
  1243. // Local PDB
  1244. //
  1245. if ( (m_enumPEImageSymbolStatus == SYMBOLS_DBG_AND_PDB) || (m_enumPEImageSymbolStatus == SYMBOLS_PDB) )
  1246. {
  1247. if (m_tszPDBModuleFileSystemPath)
  1248. {
  1249. if (!m_lpOutputFile->WriteString(m_tszPDBModuleFileSystemPath, true))
  1250. goto cleanup;
  1251. }
  1252. }
  1253. }
  1254. // Write the carriage-return line-feed at the end of the line...
  1255. if (!m_lpOutputFile->WriteString(TEXT("\r\n")))
  1256. goto cleanup;
  1257. fReturn = true; // Success
  1258. cleanup:
  1259. if (!fReturn)
  1260. {
  1261. _tprintf(TEXT("Error: Failure writing module data!\n"));
  1262. m_lpOutputFile->PrintLastError();
  1263. }
  1264. return fReturn;
  1265. }
  1266. bool CModuleInfo::OutputDataToStdout(DWORD dwModuleNumber)
  1267. {
  1268. //
  1269. // Do we output this module?
  1270. //
  1271. if (!OutputDataToStdoutThisModule())
  1272. return false;
  1273. //
  1274. // First, Output Module Info
  1275. //
  1276. OutputDataToStdoutModuleInfo(dwModuleNumber);
  1277. bool fPrintCarriageReturn = false;
  1278. //
  1279. // Second, if we were to collect symbol info, but NOT verify... dump out what we
  1280. // discovered about the symbol info...
  1281. //
  1282. if (g_lpProgramOptions->GetMode(CProgramOptions::OutputSymbolInformationMode) &&
  1283. !g_lpProgramOptions->GetMode(CProgramOptions::VerifySymbolsMode))
  1284. {
  1285. fPrintCarriageReturn = true;
  1286. switch (m_enumPEImageSymbolStatus)
  1287. {
  1288. case SYMBOL_INFORMATION_UNKNOWN:
  1289. _tprintf(TEXT(" Module symbol information was not collected!\n"));
  1290. break;
  1291. case SYMBOLS_NO:
  1292. _tprintf(TEXT(" Module has NO symbols!\n"));
  1293. break;
  1294. case SYMBOLS_LOCAL:
  1295. //
  1296. // This module has ONLY local symbols...
  1297. //
  1298. _tprintf(TEXT(" Module has internal symbols only! %s\n"), SourceEnabledPEImage());
  1299. OutputDataToStdoutInternalSymbolInfo(m_dwPEImageDebugDirectoryCoffSize, m_dwPEImageDebugDirectoryFPOSize, m_dwPEImageDebugDirectoryCVSize, m_dwPEImageDebugDirectoryOMAPtoSRCSize, m_dwPEImageDebugDirectoryOMAPfromSRCSize);
  1300. break;
  1301. case SYMBOLS_DBG:
  1302. //
  1303. // This module may have Internal Symbols but has a DBG file...
  1304. //
  1305. OutputDataToStdoutInternalSymbolInfo(m_dwPEImageDebugDirectoryCoffSize, m_dwPEImageDebugDirectoryFPOSize, m_dwPEImageDebugDirectoryCVSize, m_dwPEImageDebugDirectoryOMAPtoSRCSize, m_dwPEImageDebugDirectoryOMAPfromSRCSize);
  1306. //
  1307. // Output the DBG Symbol Information
  1308. //
  1309. OutputDataToStdoutDbgSymbolInfo(m_tszPEImageDebugDirectoryDBGPath, m_dwPEImageTimeDateStamp, m_dwPEImageCheckSum, m_dwPEImageSizeOfImage);
  1310. //
  1311. // Output the DBG Internal Symbol Information
  1312. //
  1313. OutputDataToStdoutInternalSymbolInfo(m_dwDBGImageDebugDirectoryCoffSize, m_dwDBGImageDebugDirectoryFPOSize, m_dwDBGImageDebugDirectoryCVSize, m_dwDBGImageDebugDirectoryOMAPtoSRCSize, m_dwDBGImageDebugDirectoryOMAPfromSRCSize);
  1314. break;
  1315. case SYMBOLS_PDB:
  1316. //
  1317. // Output any internal symbols (that should be "splitsym'ed out")
  1318. //
  1319. OutputDataToStdoutInternalSymbolInfo(m_dwPEImageDebugDirectoryCoffSize, m_dwPEImageDebugDirectoryFPOSize, m_dwPEImageDebugDirectoryCVSize, m_dwPEImageDebugDirectoryOMAPtoSRCSize, m_dwPEImageDebugDirectoryOMAPfromSRCSize);
  1320. //
  1321. // In this case, we have a PE Image with a PDB file...
  1322. //
  1323. OutputDataToStdoutPdbSymbolInfo(m_dwPEImageDebugDirectoryPDBFormatSpecifier, m_tszPEImageDebugDirectoryPDBPath, m_dwPEImageDebugDirectoryPDBSignature, m_tszPEImageDebugDirectoryPDBGuid, m_dwPEImageDebugDirectoryPDBAge);
  1324. break;
  1325. }
  1326. }
  1327. //
  1328. // Third, if we were to verify symbol info, display the results...
  1329. //
  1330. if (g_lpProgramOptions->GetMode(CProgramOptions::VerifySymbolsMode))
  1331. {
  1332. fPrintCarriageReturn = true;
  1333. switch (m_enumPEImageSymbolStatus)
  1334. {
  1335. case SYMBOL_INFORMATION_UNKNOWN:
  1336. _tprintf(TEXT(" Module symbol information was not collected!\n"));
  1337. break;
  1338. case SYMBOLS_NO:
  1339. _tprintf(TEXT(" Module has NO symbols\n"));
  1340. break;
  1341. case SYMBOLS_LOCAL:
  1342. _tprintf(TEXT(" Module has internal symbols only! %s\n"), SourceEnabledPEImage());
  1343. OutputDataToStdoutInternalSymbolInfo(m_dwPEImageDebugDirectoryCoffSize, m_dwPEImageDebugDirectoryFPOSize, m_dwPEImageDebugDirectoryCVSize, m_dwPEImageDebugDirectoryOMAPtoSRCSize, m_dwPEImageDebugDirectoryOMAPfromSRCSize);
  1344. break;
  1345. case SYMBOLS_DBG:
  1346. case SYMBOLS_DBG_AND_PDB:
  1347. switch (m_enumDBGModuleStatus)
  1348. {
  1349. case SYMBOL_MATCH:
  1350. // Did they want the debug/symbol info for the PE image itself?
  1351. if(g_lpProgramOptions->GetMode(CProgramOptions::OutputSymbolInformationMode))
  1352. {
  1353. OutputDataToStdoutInternalSymbolInfo(m_dwPEImageDebugDirectoryCoffSize, m_dwPEImageDebugDirectoryFPOSize, m_dwPEImageDebugDirectoryCVSize, m_dwPEImageDebugDirectoryOMAPtoSRCSize, m_dwPEImageDebugDirectoryOMAPfromSRCSize);
  1354. }
  1355. if(m_tszDBGModuleFileSystemPath )
  1356. {
  1357. _tprintf(TEXT(" DBG File = %s [VERIFIED] %s\n"), m_tszDBGModuleFileSystemPath, SourceEnabledDBGImage());
  1358. }
  1359. if(g_lpProgramOptions->GetMode(CProgramOptions::OutputSymbolInformationMode))
  1360. {
  1361. OutputDataToStdoutInternalSymbolInfo(m_dwDBGImageDebugDirectoryCoffSize, m_dwDBGImageDebugDirectoryFPOSize, m_dwDBGImageDebugDirectoryCVSize, m_dwDBGImageDebugDirectoryOMAPtoSRCSize, m_dwDBGImageDebugDirectoryOMAPfromSRCSize);
  1362. }
  1363. break;
  1364. case SYMBOL_NOT_FOUND:
  1365. OutputDataToStdoutInternalSymbolInfo(m_dwPEImageDebugDirectoryCoffSize, m_dwPEImageDebugDirectoryFPOSize, m_dwPEImageDebugDirectoryCVSize, m_dwPEImageDebugDirectoryOMAPtoSRCSize, m_dwPEImageDebugDirectoryOMAPfromSRCSize);
  1366. OutputDataToStdoutDbgSymbolInfo(m_tszPEImageDebugDirectoryDBGPath, m_dwPEImageTimeDateStamp, m_dwPEImageCheckSum, m_dwPEImageSizeOfImage);
  1367. _tprintf(TEXT(" DBG File NOT FOUND!\n"));
  1368. break; // If we didn't find the DBG file... we don't bother with the PDB...
  1369. case SYMBOL_POSSIBLE_MISMATCH:
  1370. OutputDataToStdoutInternalSymbolInfo(m_dwPEImageDebugDirectoryCoffSize, m_dwPEImageDebugDirectoryFPOSize, m_dwPEImageDebugDirectoryCVSize, m_dwPEImageDebugDirectoryOMAPtoSRCSize, m_dwPEImageDebugDirectoryOMAPfromSRCSize);
  1371. OutputDataToStdoutDbgSymbolInfo(m_tszPEImageDebugDirectoryDBGPath, m_dwPEImageTimeDateStamp, m_dwPEImageCheckSum, m_dwPEImageSizeOfImage);
  1372. OutputDataToStdoutDbgSymbolInfo(m_tszDBGModuleFileSystemPath, m_dwDBGTimeDateStamp, m_dwDBGCheckSum, m_dwDBGSizeOfImage, TEXT("DISCREPANCY"), m_dwPEImageTimeDateStamp, m_dwPEImageCheckSum, m_dwPEImageSizeOfImage);
  1373. OutputDataToStdoutInternalSymbolInfo(m_dwDBGImageDebugDirectoryCoffSize, m_dwDBGImageDebugDirectoryFPOSize, m_dwDBGImageDebugDirectoryCVSize, m_dwDBGImageDebugDirectoryOMAPtoSRCSize, m_dwDBGImageDebugDirectoryOMAPfromSRCSize);
  1374. break;
  1375. };
  1376. //
  1377. // Intentional fall through to SYMBOLS_PDB (we might have one)
  1378. //
  1379. case SYMBOLS_PDB:
  1380. // These two cases should have a PDB file... if we can find it...
  1381. //
  1382. if ( (m_enumPEImageSymbolStatus == SYMBOLS_DBG_AND_PDB) ||
  1383. (m_enumPEImageSymbolStatus == SYMBOLS_PDB) )
  1384. {
  1385. //
  1386. // If we have a DebugDirectoryPDBPath... then display the goods...
  1387. //
  1388. if (GetDebugDirectoryPDBPath())
  1389. {
  1390. switch(m_enumPDBModuleStatus)
  1391. {
  1392. case SYMBOL_NOT_FOUND:
  1393. OutputDataToStdoutInternalSymbolInfo(m_dwPEImageDebugDirectoryCoffSize, m_dwPEImageDebugDirectoryFPOSize, m_dwPEImageDebugDirectoryCVSize, m_dwPEImageDebugDirectoryOMAPtoSRCSize, m_dwPEImageDebugDirectoryOMAPfromSRCSize);
  1394. // Output PDB info as appropriate
  1395. if (m_enumPEImageSymbolStatus == SYMBOLS_PDB)
  1396. {
  1397. OutputDataToStdoutPdbSymbolInfo(m_dwPEImageDebugDirectoryPDBFormatSpecifier, m_tszPEImageDebugDirectoryPDBPath, m_dwPEImageDebugDirectoryPDBSignature, m_tszPEImageDebugDirectoryPDBGuid, m_dwPEImageDebugDirectoryPDBAge);
  1398. }
  1399. else
  1400. {
  1401. OutputDataToStdoutPdbSymbolInfo(m_dwDBGDebugDirectoryPDBFormatSpecifier, m_tszDBGDebugDirectoryPDBPath, m_dwDBGDebugDirectoryPDBSignature, m_tszDBGDebugDirectoryPDBGuid, m_dwDBGDebugDirectoryPDBAge);
  1402. }
  1403. _tprintf(TEXT(" NO PDB FILE FOUND!!\n"));
  1404. break;
  1405. case SYMBOL_MATCH:
  1406. // Did they want the debug/symbol info for the PE image itself?
  1407. if(m_tszPDBModuleFileSystemPath )
  1408. _tprintf(TEXT(" PDB File = %s [VERIFIED] %s\n"), m_tszPDBModuleFileSystemPath, SourceEnabledPDB());
  1409. // BUGBUG: Testing...
  1410. if (g_lpProgramOptions->GetMode(CProgramOptions::OutputSymbolInformationMode))
  1411. {
  1412. if (m_dwPDBTotalBytesOfLineInformation)
  1413. _tprintf(TEXT(" Module PDB Bytes of Lines = 0x%x\n"), m_dwPDBTotalBytesOfLineInformation);
  1414. if (m_dwPDBTotalBytesOfSymbolInformation)
  1415. _tprintf(TEXT(" Module PDB Bytes of Symbols = 0x%x\n"), m_dwPDBTotalBytesOfSymbolInformation);
  1416. if (m_dwPDBTotalSymbolTypesRange)
  1417. _tprintf(TEXT(" Module PDB Symbol Types Range = 0x%x\n"), m_dwPDBTotalSymbolTypesRange);
  1418. }
  1419. break;
  1420. case SYMBOL_POSSIBLE_MISMATCH:
  1421. if(m_tszPDBModuleFileSystemPath )
  1422. {
  1423. // Output PDB info as appropriate
  1424. if (m_enumPEImageSymbolStatus == SYMBOLS_PDB)
  1425. {
  1426. OutputDataToStdoutPdbSymbolInfo(m_dwPEImageDebugDirectoryPDBFormatSpecifier, m_tszPEImageDebugDirectoryPDBPath, m_dwPEImageDebugDirectoryPDBSignature, m_tszPEImageDebugDirectoryPDBGuid, m_dwPEImageDebugDirectoryPDBAge);
  1427. }
  1428. else
  1429. {
  1430. OutputDataToStdoutPdbSymbolInfo(m_dwDBGDebugDirectoryPDBFormatSpecifier, m_tszDBGDebugDirectoryPDBPath, m_dwDBGDebugDirectoryPDBSignature, m_tszDBGDebugDirectoryPDBGuid, m_dwDBGDebugDirectoryPDBAge);
  1431. }
  1432. //
  1433. // Output the PDB data itself...
  1434. //
  1435. OutputDataToStdoutPdbSymbolInfo(m_dwPDBFormatSpecifier, m_tszPDBModuleFileSystemPath, m_dwPDBSignature, m_tszPDBGuid, m_dwPDBAge, TEXT("DISCREPANCY"));
  1436. }
  1437. break;
  1438. case SYMBOL_INVALID_FORMAT:
  1439. if(m_tszPDBModuleFileSystemPath )
  1440. {
  1441. // Output PDB info as appropriate
  1442. if (m_enumPEImageSymbolStatus == SYMBOLS_PDB)
  1443. {
  1444. OutputDataToStdoutPdbSymbolInfo(m_dwPEImageDebugDirectoryPDBFormatSpecifier, m_tszPEImageDebugDirectoryPDBPath, m_dwPEImageDebugDirectoryPDBSignature, m_tszPEImageDebugDirectoryPDBGuid, m_dwPEImageDebugDirectoryPDBAge);
  1445. }
  1446. else
  1447. {
  1448. OutputDataToStdoutPdbSymbolInfo(m_dwDBGDebugDirectoryPDBFormatSpecifier, m_tszDBGDebugDirectoryPDBPath, m_dwDBGDebugDirectoryPDBSignature, m_tszDBGDebugDirectoryPDBGuid, m_dwDBGDebugDirectoryPDBAge);
  1449. }
  1450. _tprintf(TEXT(" PDB File = %s [INVALID_FORMAT]\n"), m_tszPDBModuleFileSystemPath );
  1451. }
  1452. break;
  1453. case SYMBOL_NO_HELPER_DLL:
  1454. if(m_tszPDBModuleFileSystemPath )
  1455. {
  1456. // Output PDB info as appropriate
  1457. if (m_enumPEImageSymbolStatus == SYMBOLS_PDB)
  1458. {
  1459. OutputDataToStdoutPdbSymbolInfo(m_dwPEImageDebugDirectoryPDBFormatSpecifier, m_tszPEImageDebugDirectoryPDBPath, m_dwPEImageDebugDirectoryPDBSignature, m_tszPEImageDebugDirectoryPDBGuid, m_dwPEImageDebugDirectoryPDBAge);
  1460. }
  1461. else
  1462. {
  1463. OutputDataToStdoutPdbSymbolInfo(m_dwDBGDebugDirectoryPDBFormatSpecifier, m_tszDBGDebugDirectoryPDBPath, m_dwDBGDebugDirectoryPDBSignature, m_tszDBGDebugDirectoryPDBGuid, m_dwDBGDebugDirectoryPDBAge);
  1464. }
  1465. _tprintf(TEXT(" PDB File = %s [Unable to Validate]\n"), m_tszPDBModuleFileSystemPath );
  1466. }
  1467. break;
  1468. }
  1469. } else
  1470. {
  1471. OutputDataToStdoutInternalSymbolInfo(m_dwPEImageDebugDirectoryCoffSize, m_dwPEImageDebugDirectoryFPOSize, m_dwPEImageDebugDirectoryCVSize, m_dwPEImageDebugDirectoryOMAPtoSRCSize, m_dwPEImageDebugDirectoryOMAPfromSRCSize);
  1472. OutputDataToStdoutDbgSymbolInfo(m_tszPEImageDebugDirectoryDBGPath, m_dwPEImageTimeDateStamp, m_dwPEImageCheckSum, m_dwPEImageSizeOfImage);
  1473. _tprintf(TEXT(" Module has PDB File\n"));
  1474. _tprintf(TEXT(" Module Pointer to PDB = [UNKNOWN] (Could not find in PE Image)\n"));
  1475. };
  1476. };
  1477. }
  1478. }
  1479. // Should we tack an extra carriage-return?
  1480. if ( fPrintCarriageReturn )
  1481. _tprintf(TEXT("\n"));
  1482. return true;
  1483. }
  1484. LPTSTR CModuleInfo::SymbolModuleStatusString(enum SymbolModuleStatus enumModuleStatus)
  1485. {
  1486. LPTSTR tszStringPointer = NULL;
  1487. // Output the Symbol Information for the PE module
  1488. switch (enumModuleStatus)
  1489. {
  1490. case SYMBOL_NOT_FOUND:
  1491. tszStringPointer = TEXT("SYMBOL_NOT_FOUND");
  1492. break;
  1493. case SYMBOL_MATCH:
  1494. tszStringPointer = TEXT("SYMBOL_MATCH");
  1495. break;
  1496. case SYMBOL_POSSIBLE_MISMATCH:
  1497. tszStringPointer = TEXT("SYMBOL_POSSIBLE_MISMATCH");
  1498. break;
  1499. case SYMBOL_INVALID_FORMAT:
  1500. tszStringPointer = TEXT("SYMBOL_INVALID_FORMAT");
  1501. break;
  1502. case SYMBOL_NO_HELPER_DLL:
  1503. tszStringPointer = TEXT("SYMBOL_NO_HELPER_DLL");
  1504. break;
  1505. default:
  1506. tszStringPointer = NULL;
  1507. }
  1508. return tszStringPointer;
  1509. }
  1510. LPTSTR CModuleInfo::SymbolInformationString(enum SymbolInformationForPEImage enumSymbolInformationForPEImage)
  1511. {
  1512. LPTSTR tszStringPointer = NULL;
  1513. // Ouput the Symbol Information for the PE module
  1514. switch (enumSymbolInformationForPEImage)
  1515. {
  1516. case SYMBOL_INFORMATION_UNKNOWN:
  1517. tszStringPointer = TEXT("SYMBOL_INFORMATION_UNKNOWN");
  1518. break;
  1519. case SYMBOLS_NO:
  1520. tszStringPointer = TEXT("SYMBOLS_NO");
  1521. break;
  1522. case SYMBOLS_LOCAL:
  1523. tszStringPointer = TEXT("SYMBOLS_LOCAL");
  1524. break;
  1525. case SYMBOLS_DBG:
  1526. tszStringPointer = TEXT("SYMBOLS_DBG");
  1527. break;
  1528. case SYMBOLS_DBG_AND_PDB:
  1529. tszStringPointer = TEXT("SYMBOLS_DBG_AND_PDB");
  1530. break;
  1531. case SYMBOLS_PDB:
  1532. tszStringPointer = TEXT("SYMBOLS_PDB");
  1533. break;
  1534. default:
  1535. tszStringPointer = NULL;
  1536. }
  1537. return tszStringPointer;
  1538. }
  1539. bool CModuleInfo::GetModuleInfoFromPEImage(LPTSTR tszModulePath, const bool fDmpFile, const DWORD64 dw64ModAddress)
  1540. {
  1541. HANDLE hModuleHandle = INVALID_HANDLE_VALUE;
  1542. bool fReturn = false;
  1543. // PE File Version
  1544. TCHAR tszFileName[_MAX_FNAME];
  1545. TCHAR tszFileExtension[_MAX_EXT];
  1546. DWORD dwVersionInfoSize = 0;
  1547. DWORD dwHandle = 0;
  1548. LPBYTE lpBuffer = NULL;
  1549. VS_FIXEDFILEINFO * lpFixedFileInfo = NULL;
  1550. DWORD * pdwLang = NULL;
  1551. unsigned int cbLang = 0;
  1552. unsigned int uint = 0;
  1553. TCHAR achName[256];
  1554. LPTSTR psz = NULL;
  1555. // PE Image Locals
  1556. IMAGE_DOS_HEADER ImageDosHeader;
  1557. DWORD dwMagic;
  1558. IMAGE_FILE_HEADER ImageFileHeader;
  1559. IMAGE_DATA_DIRECTORY DebugImageDataDirectory;
  1560. IMAGE_OPTIONAL_HEADER64 ImageOptionalHeader64;
  1561. PIMAGE_OPTIONAL_HEADER32 lpImageOptionalHeader32 = NULL;
  1562. PIMAGE_SECTION_HEADER lpImageSectionHeader = NULL;
  1563. ULONG OffsetImageDebugDirectory;
  1564. unsigned long ul;
  1565. // bool fDBGSymbolStrippedFromImage = false;
  1566. bool fCodeViewSectionFound = false;
  1567. // unsigned long NumDebugDirs;
  1568. // Save the base address so that all DmpFile reads become relative to this...
  1569. m_dw64BaseAddress = dw64ModAddress;
  1570. // We don't know anything about symbols yet... (we may not when we exit if the user
  1571. // didn't ask us to look...)
  1572. m_enumPEImageSymbolStatus = SYMBOL_INFORMATION_UNKNOWN;
  1573. if (!fDmpFile)
  1574. {
  1575. // Copy the Module Name to the ModuleInfo Object...
  1576. _tsplitpath(m_tszPEImageModuleFileSystemPath, NULL, NULL, tszFileName, tszFileExtension);
  1577. if (tszFileName && tszFileExtension)
  1578. {
  1579. // Compose the module name...
  1580. m_tszPEImageModuleName = new TCHAR[_tcsclen(tszFileName)+_tcsclen(tszFileExtension)+1];
  1581. if (!m_tszPEImageModuleName)
  1582. goto cleanup;
  1583. _tcscpy(m_tszPEImageModuleName, tszFileName);
  1584. _tcscat(m_tszPEImageModuleName, tszFileExtension);
  1585. }
  1586. // Let's open the file... we use this for both Version Info and Symbol Info
  1587. // gathering...
  1588. hModuleHandle = CreateFile( tszModulePath,
  1589. GENERIC_READ ,
  1590. FILE_SHARE_READ,
  1591. NULL,
  1592. OPEN_EXISTING,
  1593. 0,
  1594. 0);
  1595. if (hModuleHandle == INVALID_HANDLE_VALUE)
  1596. {
  1597. goto cleanup;
  1598. }
  1599. }
  1600. // Did the user request version information?
  1601. if (g_lpProgramOptions->GetMode(CProgramOptions::CollectVersionInfoMode) && !fDmpFile)
  1602. {
  1603. // Now, get CheckSum, TimeDateStamp, and other Image properties...
  1604. BY_HANDLE_FILE_INFORMATION lpFileInformation;
  1605. if ( GetFileInformationByHandle(hModuleHandle, &lpFileInformation) )
  1606. {
  1607. // Get the file size...
  1608. m_dwPEImageFileSize = lpFileInformation.nFileSizeLow;
  1609. m_ftPEImageFileTimeDateStamp = lpFileInformation.ftLastWriteTime;
  1610. }
  1611. // First, is there any FileVersionInfo at all?
  1612. dwVersionInfoSize = GetFileVersionInfoSize(m_tszPEImageModuleFileSystemPath, &dwHandle);
  1613. if (dwVersionInfoSize != 0)
  1614. {
  1615. // Allocate a buffer to read into...
  1616. lpBuffer = new BYTE[dwVersionInfoSize];
  1617. if (lpBuffer)
  1618. {
  1619. // Okay... query to get this version info...
  1620. if (GetFileVersionInfo(m_tszPEImageModuleFileSystemPath, dwHandle, dwVersionInfoSize, lpBuffer))
  1621. {
  1622. // Well, we returned the buffer...
  1623. m_fPEImageFileVersionInfo = true;
  1624. // Get the VS_FIXEDFILEINFO structure which carries version info...
  1625. if (VerQueryValue(lpBuffer, TEXT("\\"), (LPVOID *)&lpFixedFileInfo, &uint))
  1626. {
  1627. m_dwPEImageFileVersionMS = lpFixedFileInfo->dwFileVersionMS;
  1628. m_dwPEImageFileVersionLS = lpFixedFileInfo->dwFileVersionLS;
  1629. m_dwPEImageProductVersionMS = lpFixedFileInfo->dwProductVersionMS;
  1630. m_dwPEImageProductVersionLS = lpFixedFileInfo->dwProductVersionLS;
  1631. // Okay, before we go allocating a version string... let's ensure
  1632. // we actually have a version number worth reporting...
  1633. if ( m_dwPEImageFileVersionMS || m_dwPEImageFileVersionLS )
  1634. {
  1635. m_tszPEImageFileVersionString = new TCHAR[1+5+1+5+1+5+1+5+1+1]; // Format will be (#.#:#.#) where each # is a word
  1636. if (m_tszPEImageFileVersionString) // Okay, blitz the data into place...
  1637. _stprintf( m_tszPEImageFileVersionString, TEXT("(%d.%d:%d.%d)"), HIWORD(m_dwPEImageFileVersionMS), LOWORD(m_dwPEImageFileVersionMS), HIWORD(m_dwPEImageFileVersionLS), LOWORD(m_dwPEImageFileVersionLS) );
  1638. }
  1639. // Okay, before we go allocating a version string... let's ensure
  1640. // we actually have a version number worth reporting...
  1641. if ( m_dwPEImageProductVersionMS || m_dwPEImageProductVersionLS )
  1642. {
  1643. m_tszPEImageProductVersionString = new TCHAR[1+5+1+5+1+5+1+5+1+1]; // Format will be (#.#:#.#) where each # is a word
  1644. if (m_tszPEImageProductVersionString) // Okay, blitz the data into place...
  1645. _stprintf( m_tszPEImageProductVersionString, TEXT("(%d.%d:%d.%d)"), HIWORD(m_dwPEImageFileVersionMS), LOWORD(m_dwPEImageFileVersionMS), HIWORD(m_dwPEImageProductVersionLS), LOWORD(m_dwPEImageProductVersionLS) );
  1646. }
  1647. }
  1648. // Get the language and codepage information for the CompanyName and
  1649. // FileDescription string table resources...
  1650. if (VerQueryValue(lpBuffer, TEXT("\\VarFileInfo\\Translation"), (LPVOID *)&pdwLang, &cbLang))
  1651. {
  1652. _stprintf(achName,TEXT("\\StringFileInfo\\%04x%04x\\CompanyName"),
  1653. LOWORD(*pdwLang),
  1654. HIWORD(*pdwLang));
  1655. if (VerQueryValue(lpBuffer, achName, (LPVOID *)&psz, &uint))
  1656. {
  1657. // Cool, we have a Company Name...
  1658. if (psz && *psz)
  1659. {
  1660. m_tszPEImageFileVersionCompanyName = new TCHAR[_tcslen(psz)+1];
  1661. if (m_tszPEImageFileVersionCompanyName)
  1662. _tcscpy(m_tszPEImageFileVersionCompanyName, psz);
  1663. }
  1664. }
  1665. _stprintf(achName,TEXT("\\StringFileInfo\\%04x%04x\\FileDescription"),
  1666. LOWORD(*pdwLang),
  1667. HIWORD(*pdwLang));
  1668. if (VerQueryValue(lpBuffer, achName, (LPVOID *)&psz, &uint))
  1669. {
  1670. // Cool, we have a Company Name...
  1671. if (psz && *psz)
  1672. {
  1673. m_tszPEImageFileVersionDescription = new TCHAR[_tcslen(psz)+1];
  1674. if (m_tszPEImageFileVersionDescription)
  1675. _tcscpy(m_tszPEImageFileVersionDescription, psz);
  1676. }
  1677. }
  1678. // If we still don't have a proper file version... just try
  1679. // and grab the FileVersion string and hope it's good...
  1680. if ( !m_dwPEImageFileVersionMS && !m_dwPEImageFileVersionLS )
  1681. {
  1682. _stprintf(achName,TEXT("\\StringFileInfo\\%04x%04x\\FileVersion"),
  1683. LOWORD(*pdwLang),
  1684. HIWORD(*pdwLang));
  1685. if (VerQueryValue(lpBuffer, achName, (LPVOID *)&psz, &uint))
  1686. {
  1687. // Cool, we have a FileVersion String...
  1688. if (psz && *psz)
  1689. {
  1690. m_tszPEImageFileVersionString = new TCHAR[_tcslen(psz)+1];
  1691. if (m_tszPEImageFileVersionString)
  1692. _tcscpy(m_tszPEImageFileVersionString, psz);
  1693. }
  1694. }
  1695. }
  1696. // If we still don't have a proper file version... just try
  1697. // and grab the ProductVersion string and hope it's good...
  1698. if ( !m_dwPEImageProductVersionMS && !m_dwPEImageProductVersionLS )
  1699. {
  1700. _stprintf(achName,TEXT("\\StringFileInfo\\%04x%04x\\ProductVersion"),
  1701. LOWORD(*pdwLang),
  1702. HIWORD(*pdwLang));
  1703. if (VerQueryValue(lpBuffer, achName, (LPVOID *)&psz, &uint))
  1704. {
  1705. // Cool, we have a FileVersion String...
  1706. if (psz && *psz)
  1707. {
  1708. m_tszPEImageProductVersionString = new TCHAR[_tcslen(psz)+1];
  1709. if (m_tszPEImageProductVersionString)
  1710. _tcscpy(m_tszPEImageProductVersionString, psz);
  1711. }
  1712. }
  1713. }
  1714. }
  1715. }
  1716. }
  1717. }
  1718. }
  1719. // If the user chose not to collect or verify symbol information, then bail out of here...
  1720. if (!g_lpProgramOptions->GetMode(CProgramOptions::OutputSymbolInformationMode) &&
  1721. !g_lpProgramOptions->GetMode(CProgramOptions::VerifySymbolsMode))
  1722. {
  1723. fReturn = true;
  1724. goto cleanup;
  1725. }
  1726. // Start at the top of the image...
  1727. SetReadPointer(fDmpFile, hModuleHandle, 0, FILE_BEGIN);
  1728. // Read in a dos exe header
  1729. if ( !DoRead(fDmpFile, hModuleHandle, &ImageDosHeader, sizeof(ImageDosHeader) ) )
  1730. goto cleanup;
  1731. if (ImageDosHeader.e_magic != IMAGE_DOS_SIGNATURE)
  1732. { // No sense in going further since we're expecting a PE image file...
  1733. goto cleanup;
  1734. }
  1735. if (ImageDosHeader.e_lfanew == 0)
  1736. { // This is a DOS program... very odd...
  1737. goto cleanup;
  1738. }
  1739. // Great, we have a valid DOS_SIGNATURE... now read in the NT_SIGNATURE?!
  1740. SetReadPointer(fDmpFile, hModuleHandle, ImageDosHeader.e_lfanew, FILE_BEGIN);
  1741. // Read in a DWORD to see if this is an image worth looking at...
  1742. if ( !DoRead(fDmpFile, hModuleHandle, &dwMagic, sizeof(DWORD)) )
  1743. goto cleanup;
  1744. // Probe to see if this is a valid image... we only handle NT images (PE/PE64)
  1745. if (dwMagic != IMAGE_NT_SIGNATURE)
  1746. goto cleanup;
  1747. // Now read the ImageFileHeader...
  1748. if ( !DoRead(fDmpFile, hModuleHandle, &ImageFileHeader, sizeof(IMAGE_FILE_HEADER)) )
  1749. goto cleanup;
  1750. // Okay, we have a PE Image!!!!
  1751. // Save the Time Date Stamp
  1752. m_dwPEImageTimeDateStamp = ImageFileHeader.TimeDateStamp;
  1753. // Save the Machine Architecture
  1754. m_wPEImageMachineArchitecture = ImageFileHeader.Machine;
  1755. // Save the PE Image Characteristics
  1756. m_wCharacteristics = ImageFileHeader.Characteristics;
  1757. // The OptionalHeader is necessary to get the SizeOfImage and to find the DebugDirectoryInfo.
  1758. if (ImageFileHeader.SizeOfOptionalHeader == 0)
  1759. goto cleanup;
  1760. // Now... the size of the Optional Header is DIFFERENT between PE32 and PE64...
  1761. // The only items we need from the option header are:
  1762. //
  1763. // ULONG CheckSum
  1764. // ULONG SizeOfImage
  1765. // IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG]
  1766. //
  1767. // We'll read as a PE64 (since it's larger) and cast to PE32 if required...
  1768. if ( !DoRead(fDmpFile, hModuleHandle, &ImageOptionalHeader64, sizeof(IMAGE_OPTIONAL_HEADER64)) )
  1769. goto cleanup;
  1770. switch (ImageOptionalHeader64.Magic)
  1771. {
  1772. case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
  1773. m_enumPEImageType = PE32;
  1774. lpImageOptionalHeader32 = (PIMAGE_OPTIONAL_HEADER32)&ImageOptionalHeader64;
  1775. // Save the Checksum info (though it's not very relavent to identifying symbols)
  1776. m_dwPEImageCheckSum = lpImageOptionalHeader32->CheckSum;
  1777. // Save the SizeOfImage info...
  1778. m_dwPEImageSizeOfImage = lpImageOptionalHeader32->SizeOfImage;
  1779. // Get the preferred load address (but only if we don't already have one)
  1780. if (m_dw64BaseAddress != 0)
  1781. {
  1782. m_dw64BaseAddress = lpImageOptionalHeader32->ImageBase;
  1783. }
  1784. DebugImageDataDirectory.Size = lpImageOptionalHeader32->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
  1785. DebugImageDataDirectory.VirtualAddress = lpImageOptionalHeader32->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
  1786. break;
  1787. case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
  1788. m_enumPEImageType = PE64;
  1789. // Save the Checksum info (though it's not very relavent to identifying symbols)
  1790. m_dwPEImageCheckSum = ImageOptionalHeader64.CheckSum;
  1791. // Save the SizeOfImage info...
  1792. m_dwPEImageSizeOfImage = ImageOptionalHeader64.SizeOfImage;
  1793. // Get the preferred load address (but only if we don't already have one)
  1794. if (m_dw64BaseAddress != 0)
  1795. {
  1796. m_dw64BaseAddress = ImageOptionalHeader64.ImageBase;
  1797. }
  1798. DebugImageDataDirectory.Size = ImageOptionalHeader64.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
  1799. DebugImageDataDirectory.VirtualAddress = ImageOptionalHeader64.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
  1800. break;
  1801. default:
  1802. goto cleanup;
  1803. }
  1804. // Let's quickly look to see if there is even a Debug Directory in the PE image!
  1805. if (DebugImageDataDirectory.Size == 0)
  1806. {
  1807. m_enumPEImageSymbolStatus = SYMBOLS_NO;
  1808. fReturn = true;
  1809. goto cleanup; // No Debug Directory found...
  1810. }
  1811. // Now, go ahead and allocate the storage...
  1812. lpImageSectionHeader = (PIMAGE_SECTION_HEADER) new IMAGE_SECTION_HEADER[ImageFileHeader.NumberOfSections];
  1813. if (lpImageSectionHeader == NULL)
  1814. goto cleanup;
  1815. // Set the pointer to the start of the Section Headers... (we may need to back up if we read
  1816. // PE64 Optional Headers and this is a PE32 image...
  1817. if (m_enumPEImageType == PE32)
  1818. {
  1819. SetReadPointer(fDmpFile, hModuleHandle, (LONG)(sizeof(IMAGE_OPTIONAL_HEADER32)-sizeof(IMAGE_OPTIONAL_HEADER64)), FILE_CURRENT);
  1820. }
  1821. // Read in the Section Headers...
  1822. if (!DoRead(fDmpFile, hModuleHandle, lpImageSectionHeader, (ImageFileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER))))
  1823. goto cleanup;
  1824. // Let's walk through these Section Headers...
  1825. // For PE images, walk the section headers looking for the
  1826. // one that's got the debug directory.
  1827. for (ul=0; ul < ImageFileHeader.NumberOfSections; ul++) {
  1828. // If the virtual address for the Debug Entry falls into this section header, then we've found it!
  1829. if ( DebugImageDataDirectory.VirtualAddress >= lpImageSectionHeader[ul].VirtualAddress &&
  1830. DebugImageDataDirectory.VirtualAddress < lpImageSectionHeader[ul].VirtualAddress + lpImageSectionHeader[ul].SizeOfRawData )
  1831. {
  1832. break;
  1833. }
  1834. }
  1835. // Assuming we haven't exhausted the list of section headers, we should have the debug directory now.
  1836. if (ul >= ImageFileHeader.NumberOfSections)
  1837. {
  1838. m_enumPEImageSymbolStatus = SYMBOLS_NO;
  1839. fReturn = true;
  1840. goto cleanup; // No Debug Directory found...
  1841. }
  1842. // For a DmpFile, the address is based on the Section Header's Virtual Address, not PointerToRawData
  1843. if (fDmpFile)
  1844. {
  1845. OffsetImageDebugDirectory = ((DebugImageDataDirectory.VirtualAddress - lpImageSectionHeader[ul].VirtualAddress) + lpImageSectionHeader[ul].VirtualAddress);
  1846. } else
  1847. {
  1848. OffsetImageDebugDirectory = ((DebugImageDataDirectory.VirtualAddress - lpImageSectionHeader[ul].VirtualAddress) + lpImageSectionHeader[ul].PointerToRawData);
  1849. }
  1850. // NumDebugDirs = DebugImageDataDirectory.Size / sizeof(IMAGE_DEBUG_DIRECTORY);
  1851. if (!ProcessDebugDirectory(true, fDmpFile, hModuleHandle, DebugImageDataDirectory.Size, OffsetImageDebugDirectory))
  1852. goto cleanup;
  1853. fReturn = true;
  1854. // fDBGSymbolStrippedFromImage = (ImageFileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED) == IMAGE_FILE_DEBUG_STRIPPED;
  1855. // fIMAGE_FILE_LOCAL_SYMS_STRIPPED = (ImageFileHeader.Characteristics & IMAGE_FILE_LOCAL_SYMS_STRIPPED) == IMAGE_FILE_LOCAL_SYMS_STRIPPED;
  1856. /**
  1857. **
  1858. ** What type of symbols were found to be present...
  1859. **
  1860. ** NO SYMBOLS
  1861. ** =============
  1862. ** No Debug Directory
  1863. ** NO Debug information stripped
  1864. ** Symbols stripped
  1865. **
  1866. ** LOCAL SYMBOLS
  1867. ** =============
  1868. ** Debug Directory
  1869. ** NO Debug information stripped
  1870. ** NO Symbols stripped
  1871. **
  1872. ** PDB SYMBOL
  1873. ** =============
  1874. ** Debug Directory
  1875. ** NO Debug information stripped
  1876. ** Symbols stripped
  1877. **
  1878. ** DBG SYMBOL
  1879. ** =============
  1880. ** Debug Directory (assumed)
  1881. ** BOTH - YES/NO Debug information stripped
  1882. ** NO Symbols stripped
  1883. **
  1884. **/
  1885. if ((ImageFileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED) == IMAGE_FILE_DEBUG_STRIPPED)
  1886. { // Debug Information Stripped! (A DBG file is assumed)
  1887. m_enumPEImageSymbolStatus = SYMBOLS_DBG;
  1888. } else
  1889. {
  1890. // Debug Information NOT stripped! (Either a PDB exists, or symbols are local, or both...)
  1891. if ( ( m_tszPEImageDebugDirectoryPDBPath) || (fDmpFile && fCodeViewSectionFound) )
  1892. { // If we find PDB data, a PDB file is assumed...
  1893. // Starting with LINK.EXE 6.2 and higher, we'll find PDB data in USER.DMP files....
  1894. m_enumPEImageSymbolStatus = SYMBOLS_PDB;
  1895. } else
  1896. { // Symbols NOT stripped (Symbols appear to be local to the PE Image)
  1897. m_enumPEImageSymbolStatus = SYMBOLS_LOCAL;
  1898. }
  1899. }
  1900. cleanup:
  1901. if (hModuleHandle != INVALID_HANDLE_VALUE)
  1902. CloseHandle(hModuleHandle);
  1903. if (lpImageSectionHeader)
  1904. delete [] lpImageSectionHeader;
  1905. return fReturn;
  1906. }
  1907. bool CModuleInfo::GetModuleInfoFromCSVFile(LPTSTR tszModulePath)
  1908. {
  1909. TCHAR tszFileName[_MAX_FNAME];
  1910. TCHAR tszFileExtension[_MAX_EXT];
  1911. // Copy the Module Name to the ModuleInfo Object...
  1912. _tsplitpath(tszModulePath, NULL, NULL, tszFileName, tszFileExtension);
  1913. if (tszFileName && tszFileExtension)
  1914. {
  1915. // Compose the module name...
  1916. m_tszPEImageModuleName = new TCHAR[_tcsclen(tszFileName)+_tcsclen(tszFileExtension)+1];
  1917. if (!m_tszPEImageModuleName)
  1918. return false;
  1919. _tcscpy(m_tszPEImageModuleName, tszFileName);
  1920. _tcscat(m_tszPEImageModuleName, tszFileExtension);
  1921. }
  1922. // Get the symbol status
  1923. enum {BUFFER_SIZE = 32};
  1924. char szSymbolStatus[BUFFER_SIZE];
  1925. m_lpInputFile->ReadString(szSymbolStatus, BUFFER_SIZE);
  1926. // Get the enum value for this string...
  1927. m_enumPEImageSymbolStatus = SymbolInformation(szSymbolStatus);
  1928. // Reset the symbol status if it is DBG/PDB (that may have
  1929. // applied on the other machine where the data was captured,
  1930. // but on this machine we'll have to find the DBG file
  1931. // first, then see if a PDB file exists...
  1932. if (m_enumPEImageSymbolStatus == SYMBOLS_DBG_AND_PDB)
  1933. m_enumPEImageSymbolStatus = SYMBOLS_DBG;
  1934. m_lpInputFile->ReadDWORD(&m_dwPEImageCheckSum);
  1935. m_lpInputFile->ReadDWORD((LPDWORD)&m_dwPEImageTimeDateStamp);
  1936. // Skip the time/date string...
  1937. m_lpInputFile->ReadString();
  1938. m_lpInputFile->ReadDWORD(&m_dwPEImageSizeOfImage);
  1939. char szBuffer[_MAX_PATH+1];
  1940. DWORD dwStringLength;
  1941. // Read in the DBG Module Path
  1942. dwStringLength = m_lpInputFile->ReadString(szBuffer, _MAX_PATH+1);
  1943. if (dwStringLength)
  1944. {
  1945. // Okay, if we found a good path... allocate space for it...
  1946. m_tszPEImageDebugDirectoryDBGPath = CUtilityFunctions::CopyAnsiStringToTSTR(szBuffer);
  1947. if (!m_tszPEImageDebugDirectoryDBGPath)
  1948. return false;
  1949. }
  1950. // Read in the PDB Module Path
  1951. dwStringLength = m_lpInputFile->ReadString(szBuffer, _MAX_PATH+1);
  1952. if (dwStringLength)
  1953. {
  1954. // Okay, if we found a good path... allocate space for it...
  1955. m_tszPEImageDebugDirectoryPDBPath = CUtilityFunctions::CopyAnsiStringToTSTR(szBuffer);
  1956. if (!m_tszPEImageDebugDirectoryPDBPath)
  1957. return false; // Failure allocating...
  1958. }
  1959. m_lpInputFile->ReadDWORD(&m_dwPEImageDebugDirectoryPDBSignature);
  1960. m_lpInputFile->ReadDWORD(&m_dwPEImageDebugDirectoryPDBAge);
  1961. // Read in the Product Version String
  1962. dwStringLength = m_lpInputFile->ReadString(szBuffer, _MAX_PATH+1);
  1963. if (dwStringLength)
  1964. {
  1965. // Okay, if we found a good version... allocate space for it...
  1966. m_tszPEImageProductVersionString = CUtilityFunctions::CopyAnsiStringToTSTR(szBuffer);
  1967. if (!m_tszPEImageProductVersionString )
  1968. return false; // Failure allocating...
  1969. }
  1970. // Read in the File Version String
  1971. dwStringLength = m_lpInputFile->ReadString(szBuffer, _MAX_PATH+1);
  1972. if (dwStringLength)
  1973. {
  1974. // Okay, if we found a good version... allocate space for it...
  1975. m_tszPEImageFileVersionString = CUtilityFunctions::CopyAnsiStringToTSTR(szBuffer);
  1976. if (!m_tszPEImageFileVersionString )
  1977. return false; // Failure allocating...
  1978. }
  1979. // Read in the File Version Company String
  1980. dwStringLength = m_lpInputFile->ReadString(szBuffer, _MAX_PATH+1);
  1981. if (dwStringLength)
  1982. {
  1983. // Okay, if we found a good version... allocate space for it...
  1984. m_tszPEImageFileVersionCompanyName = CUtilityFunctions::CopyAnsiStringToTSTR(szBuffer);
  1985. if ( !m_tszPEImageFileVersionCompanyName )
  1986. return false; // Failure allocating...
  1987. }
  1988. // Read in the File Version Description String
  1989. dwStringLength = m_lpInputFile->ReadString(szBuffer, _MAX_PATH+1);
  1990. if (dwStringLength)
  1991. {
  1992. // Okay, if we found a good version... allocate space for it...
  1993. m_tszPEImageFileVersionDescription = CUtilityFunctions::CopyAnsiStringToTSTR(szBuffer);
  1994. if ( !m_tszPEImageFileVersionDescription )
  1995. return false; // Failure allocating...
  1996. }
  1997. m_lpInputFile->ReadDWORD(&m_dwPEImageFileSize);
  1998. m_lpInputFile->ReadDWORD(&m_ftPEImageFileTimeDateStamp.dwHighDateTime);
  1999. m_lpInputFile->ReadDWORD(&m_ftPEImageFileTimeDateStamp.dwLowDateTime);
  2000. // Okay... read to the start of the next line...
  2001. m_lpInputFile->ReadFileLine();
  2002. return true;
  2003. }
  2004. // This function is for ANSI strings explicitly because we only need to map these from
  2005. // ANSI strings read from a file, to an enum...
  2006. CModuleInfo::SymbolInformationForPEImage CModuleInfo::SymbolInformation(LPSTR szSymbolInformationString)
  2007. {
  2008. if (0 == _stricmp(szSymbolInformationString, "SYMBOLS_DBG"))
  2009. return SYMBOLS_DBG;
  2010. if (0 == _stricmp(szSymbolInformationString, "SYMBOLS_PDB"))
  2011. return SYMBOLS_PDB;
  2012. if (0 == _stricmp(szSymbolInformationString, "SYMBOLS_DBG_AND_PDB"))
  2013. return SYMBOLS_DBG_AND_PDB;
  2014. if (0 == _stricmp(szSymbolInformationString, "SYMBOLS_NO"))
  2015. return SYMBOLS_NO;
  2016. if (0 == _stricmp(szSymbolInformationString, "SYMBOLS_LOCAL"))
  2017. return SYMBOLS_LOCAL;
  2018. if (0 == _stricmp(szSymbolInformationString, "SYMBOL_INFORMATION_UNKNOWN"))
  2019. return SYMBOL_INFORMATION_UNKNOWN;
  2020. return SYMBOL_INFORMATION_UNKNOWN;
  2021. }
  2022. bool CModuleInfo::OutputFileTime(FILETIME ftFileTime, LPTSTR tszFileTime, int iFileTimeBufferSize)
  2023. {
  2024. // Thu Oct 08 15:37:22 1998
  2025. FILETIME ftLocalFileTime;
  2026. SYSTEMTIME lpSystemTime;
  2027. int cch = 0, cch2 = 0;
  2028. // Let's convert this to a local file time first...
  2029. if (!FileTimeToLocalFileTime(&ftFileTime, &ftLocalFileTime))
  2030. return false;
  2031. FileTimeToSystemTime( &ftLocalFileTime, &lpSystemTime );
  2032. cch = GetDateFormat( LOCALE_USER_DEFAULT,
  2033. 0,
  2034. &lpSystemTime,
  2035. TEXT("ddd MMM dd"),
  2036. tszFileTime,
  2037. iFileTimeBufferSize );
  2038. if (!cch)
  2039. return false;
  2040. // Let's keep going...
  2041. tszFileTime[cch-1] = TEXT(' ');
  2042. //
  2043. // Get time and format to characters
  2044. //
  2045. cch2 = GetTimeFormat( LOCALE_USER_DEFAULT,
  2046. NULL,
  2047. &lpSystemTime,
  2048. TEXT("HH':'mm':'ss"),
  2049. tszFileTime + cch,
  2050. iFileTimeBufferSize - cch );
  2051. // Let's keep going... we have to tack on the year...
  2052. tszFileTime[cch + cch2 - 1] = TEXT(' ');
  2053. GetDateFormat( LOCALE_USER_DEFAULT,
  2054. 0,
  2055. &lpSystemTime,
  2056. TEXT("yyyy"),
  2057. tszFileTime + cch + cch2,
  2058. iFileTimeBufferSize - cch - cch2);
  2059. return true;
  2060. }
  2061. bool CModuleInfo::SetModulePath(LPTSTR tszModulePath)
  2062. {
  2063. // Copy the Module Path to the ModuleInfo Object...
  2064. if (!tszModulePath) {
  2065. return false;
  2066. }
  2067. if (m_tszPEImageModuleFileSystemPath)
  2068. delete [] m_tszPEImageModuleFileSystemPath;
  2069. m_tszPEImageModuleFileSystemPath = new TCHAR[(_tcsclen(tszModulePath)+1)];
  2070. if (!m_tszPEImageModuleFileSystemPath)
  2071. return false;
  2072. _tcscpy(m_tszPEImageModuleFileSystemPath, tszModulePath);
  2073. return true;
  2074. }
  2075. bool CModuleInfo::HandlePDBOpenValidateReturn(PDB * lpPdb, LPTSTR tszPDBLocal, EC ec)
  2076. {
  2077. char szPDBLocal[_MAX_PATH+1];
  2078. // What we do now is based on the return from PDBOpenValidate()
  2079. switch (ec)
  2080. {
  2081. case EC_NOT_FOUND:
  2082. break; // Not here, go back for more...
  2083. case EC_OK:
  2084. // Yee haa... save the data for sure...
  2085. m_enumPDBModuleStatus = SYMBOL_MATCH;
  2086. // On a perfect match, these must be equal...
  2087. m_dwPDBSignature = m_dwPEImageDebugDirectoryPDBSignature;
  2088. m_dwPDBAge = m_dwPEImageDebugDirectoryPDBAge;
  2089. // We're saving this... delete an existing one if found...
  2090. if (m_tszPDBModuleFileSystemPath)
  2091. {
  2092. delete [] m_tszPDBModuleFileSystemPath;
  2093. m_tszPDBModuleFileSystemPath = NULL;
  2094. }
  2095. m_tszPDBModuleFileSystemPath = CUtilityFunctions::CopyString(tszPDBLocal);
  2096. _tcscpy(m_tszPDBModuleFileSystemPath, tszPDBLocal);
  2097. if (!m_tszPDBModuleFileSystemPath)
  2098. return false;
  2099. // Now that we're done verifying the module... do we save the symbol in
  2100. // our tree?
  2101. if ( g_lpProgramOptions->GetMode(CProgramOptions::BuildSymbolTreeMode) )
  2102. {
  2103. // Yup...
  2104. CUtilityFunctions::CopySymbolFileToSymbolTree(m_tszPEImageModuleName, &m_tszPDBModuleFileSystemPath, g_lpProgramOptions->GetSymbolTreeToBuild());
  2105. }
  2106. //
  2107. // Is there any Private Information (Source Enabled?)
  2108. //
  2109. if (!ProcessPDBSourceInfo(lpPdb))
  2110. return false;
  2111. break;
  2112. case EC_FORMAT:
  2113. // This deserves an error of its own...
  2114. m_enumPDBModuleStatus = SYMBOL_INVALID_FORMAT;
  2115. // We'll only save this if we don't already have one...
  2116. if (m_tszPDBModuleFileSystemPath == NULL)
  2117. {
  2118. m_tszPDBModuleFileSystemPath = CUtilityFunctions::CopyString(tszPDBLocal);
  2119. if (!m_tszPDBModuleFileSystemPath)
  2120. return false;
  2121. }
  2122. break;
  2123. case EC_INVALID_SIG:
  2124. case EC_INVALID_AGE:
  2125. // We'll save the location only for interests sake (and only if we
  2126. // don't have a PDB path already...
  2127. // Maybe we need to be more granular?
  2128. m_enumPDBModuleStatus = SYMBOL_POSSIBLE_MISMATCH;
  2129. // We'll only save this if we don't already have one...
  2130. if (m_tszPDBModuleFileSystemPath == NULL)
  2131. {
  2132. m_tszPDBModuleFileSystemPath = CUtilityFunctions::CopyString(tszPDBLocal);
  2133. if (!m_tszPDBModuleFileSystemPath)
  2134. return false;
  2135. }
  2136. // Okay, we know that we had a bad match, but we don't know why... let's
  2137. // go ahead and figure it out...
  2138. EC ec;
  2139. char szError[cbErrMax];
  2140. PDB *pPdb;
  2141. CUtilityFunctions::CopyTSTRStringToAnsi(tszPDBLocal, szPDBLocal, _MAX_PATH+1);
  2142. if ( PDBOpen(szPDBLocal,
  2143. pdbRead,
  2144. m_dwPEImageDebugDirectoryPDBSignature,
  2145. &ec,
  2146. szError,
  2147. &pPdb) )
  2148. {
  2149. // We opened it...
  2150. // Get the goods...
  2151. m_dwPDBFormatSpecifier = sigNB10; // TEMPORARY ASSUMPTION!!!
  2152. m_dwPDBSignature = PDBQuerySignature(pPdb);
  2153. m_dwPDBAge = PDBQueryAge(pPdb);
  2154. PDBClose(pPdb);
  2155. }
  2156. break;
  2157. case EC_USAGE:
  2158. m_enumPDBModuleStatus = SYMBOL_NO_HELPER_DLL;
  2159. // We'll only save this if we don't already have one...
  2160. if (m_tszPDBModuleFileSystemPath == NULL)
  2161. {
  2162. m_tszPDBModuleFileSystemPath = CUtilityFunctions::CopyString(tszPDBLocal);
  2163. if (!m_tszPDBModuleFileSystemPath)
  2164. return false;
  2165. }
  2166. break;
  2167. default:
  2168. break;
  2169. }
  2170. return true;
  2171. }
  2172. ULONG CModuleInfo::SetReadPointer(bool fDmpFile, HANDLE hModuleHandle, LONG cbOffset, int iFrom)
  2173. {
  2174. if (fDmpFile)
  2175. {
  2176. switch( iFrom )
  2177. {
  2178. case FILE_BEGIN:
  2179. m_dwCurrentReadPosition = cbOffset;
  2180. break;
  2181. case FILE_CURRENT:
  2182. m_dwCurrentReadPosition += cbOffset;
  2183. break;
  2184. default:
  2185. break;
  2186. }
  2187. } else
  2188. {
  2189. m_dwCurrentReadPosition = SetFilePointer(hModuleHandle, cbOffset, NULL, iFrom);
  2190. }
  2191. return m_dwCurrentReadPosition;
  2192. }
  2193. bool CModuleInfo::DoRead(bool fDmpFile, HANDLE hModuleHandle, LPVOID lpBuffer, DWORD cbNumberOfBytesToRead)
  2194. {
  2195. DWORD cbActuallyRead;
  2196. bool fReturn = false;
  2197. if (fDmpFile)
  2198. {
  2199. if (m_lpDmpFile)
  2200. {
  2201. HRESULT Hr;
  2202. if (FAILED(Hr = m_lpDmpFile->m_pIDebugDataSpaces->ReadVirtual(m_dw64BaseAddress+(DWORD64)m_dwCurrentReadPosition,
  2203. lpBuffer,
  2204. cbNumberOfBytesToRead,
  2205. &cbActuallyRead)))
  2206. {
  2207. goto exit;
  2208. }
  2209. if (cbActuallyRead != cbNumberOfBytesToRead)
  2210. {
  2211. goto exit;
  2212. }
  2213. } else
  2214. {
  2215. goto exit;
  2216. }
  2217. m_dwCurrentReadPosition += cbActuallyRead;
  2218. } else if ( (ReadFile(hModuleHandle, lpBuffer, cbNumberOfBytesToRead, &cbActuallyRead, NULL) == 0) ||
  2219. (cbNumberOfBytesToRead != cbActuallyRead) )
  2220. {
  2221. goto exit;
  2222. }
  2223. fReturn = true;
  2224. exit:
  2225. return fReturn;
  2226. }
  2227. bool CModuleInfo::SetDebugDirectoryDBGPath(LPTSTR tszNewDebugDirectoryDBGPath)
  2228. {
  2229. if (m_tszPEImageDebugDirectoryDBGPath)
  2230. delete [] m_tszPEImageDebugDirectoryDBGPath;
  2231. m_tszPEImageDebugDirectoryDBGPath = CUtilityFunctions::CopyString(tszNewDebugDirectoryDBGPath);
  2232. return true;
  2233. }
  2234. bool CModuleInfo::SetPEDebugDirectoryPDBPath(LPTSTR tszNewDebugDirectoryPDBPath)
  2235. {
  2236. if (m_tszPEImageDebugDirectoryPDBPath)
  2237. delete [] m_tszPEImageDebugDirectoryPDBPath;
  2238. m_tszPEImageDebugDirectoryPDBPath = CUtilityFunctions::CopyString(tszNewDebugDirectoryPDBPath);
  2239. return true;
  2240. }
  2241. bool CModuleInfo::SetPEImageModulePath(LPTSTR tszNewPEImageModulePath)
  2242. {
  2243. if (m_tszPEImageModuleFileSystemPath)
  2244. delete [] m_tszPEImageModuleFileSystemPath;
  2245. m_tszPEImageModuleFileSystemPath = CUtilityFunctions::CopyString(tszNewPEImageModulePath);
  2246. _tcsupr(m_tszPEImageModuleFileSystemPath);
  2247. return true;
  2248. }
  2249. bool CModuleInfo::SetPEImageModuleName(LPTSTR tszNewModuleName)
  2250. {
  2251. if (m_tszPEImageModuleName)
  2252. delete [] m_tszPEImageModuleName;
  2253. m_tszPEImageModuleName = CUtilityFunctions::CopyString(tszNewModuleName);
  2254. _tcsupr(m_tszPEImageModuleName);
  2255. return true;
  2256. }
  2257. // Evaluate whether we've found the symbolic information for this module
  2258. // that the user is looking for.
  2259. bool CModuleInfo::GoodSymbolNotFound()
  2260. {
  2261. bool fBadSymbol = true;
  2262. // Well, we evaluate success based on the type of symbol we're looking for
  2263. // and whether it was successfully found.
  2264. switch (GetPESymbolInformation())
  2265. {
  2266. // This is bad... consider this fatal...
  2267. case SYMBOL_INFORMATION_UNKNOWN:
  2268. break;
  2269. // Is this bad? I think so... but if you inherit a module as an import should you
  2270. // be punished for the ills of another? Hmm.... For now we'll say it's okay...
  2271. case SYMBOLS_NO:
  2272. fBadSymbol = false;
  2273. break;
  2274. // While this is wasteful, we have symbolic info... so that's cool
  2275. case SYMBOLS_LOCAL:
  2276. fBadSymbol = false;
  2277. break;
  2278. case SYMBOLS_DBG:
  2279. fBadSymbol = SYMBOL_MATCH == GetDBGSymbolModuleStatus();
  2280. break;
  2281. case SYMBOLS_DBG_AND_PDB:
  2282. fBadSymbol = (SYMBOL_MATCH == GetDBGSymbolModuleStatus()) &&
  2283. (SYMBOL_MATCH == GetPDBSymbolModuleStatus());
  2284. break;
  2285. case SYMBOLS_PDB:
  2286. fBadSymbol = SYMBOL_MATCH == GetPDBSymbolModuleStatus();
  2287. break;
  2288. default:
  2289. break;
  2290. }
  2291. return fBadSymbol;
  2292. }
  2293. //
  2294. // Process the DebugDirectory data for a PE image (or a DBG file)
  2295. //
  2296. bool CModuleInfo::ProcessDebugDirectory(const bool fPEImage, const bool fDmpFile, const HANDLE hModuleHandle, unsigned int iDebugDirectorySize, ULONG OffsetImageDebugDirectory)
  2297. {
  2298. unsigned int iNumberOfDebugDirectoryEntries = iDebugDirectorySize / sizeof(IMAGE_DEBUG_DIRECTORY);
  2299. //
  2300. // Let's loop through the debug directories and collect the relavent info...
  2301. //
  2302. while (iNumberOfDebugDirectoryEntries--)
  2303. {
  2304. IMAGE_DEBUG_DIRECTORY ImageDebugDirectory;
  2305. // Set the pointer to the DebugDirectories entry
  2306. SetReadPointer(fDmpFile, hModuleHandle, OffsetImageDebugDirectory, FILE_BEGIN);
  2307. // Read the DebugDirectoryImage
  2308. if (!DoRead(fDmpFile, hModuleHandle, &ImageDebugDirectory, sizeof(IMAGE_DEBUG_DIRECTORY)))
  2309. goto cleanup;
  2310. //
  2311. // Processing of the Debug Directory is dependent on the type
  2312. //
  2313. switch (ImageDebugDirectory.Type)
  2314. {
  2315. //
  2316. // This is our preferred debug format as it offers full source level debugging (typically)
  2317. //
  2318. case IMAGE_DEBUG_TYPE_CODEVIEW:
  2319. ProcessDebugTypeCVDirectoryEntry(fPEImage, fDmpFile, hModuleHandle, &ImageDebugDirectory);
  2320. break;
  2321. //
  2322. // COFF symbols are okay... CV is better :)
  2323. //
  2324. case IMAGE_DEBUG_TYPE_COFF:
  2325. ProcessDebugTypeCoffDirectoryEntry(fPEImage, &ImageDebugDirectory);
  2326. break;
  2327. //
  2328. // MISC implies that a DBG file is created...
  2329. //
  2330. case IMAGE_DEBUG_TYPE_MISC:
  2331. ProcessDebugTypeMiscDirectoryEntry(fPEImage, fDmpFile, hModuleHandle, &ImageDebugDirectory);
  2332. break;
  2333. //
  2334. // FPO info is important for working with functions with FPO
  2335. //
  2336. case IMAGE_DEBUG_TYPE_FPO:
  2337. ProcessDebugTypeFPODirectoryEntry(fPEImage, &ImageDebugDirectory);
  2338. break;
  2339. case IMAGE_DEBUG_TYPE_OMAP_TO_SRC:
  2340. case IMAGE_DEBUG_TYPE_OMAP_FROM_SRC:
  2341. ProcessDebugTypeOMAPDirectoryEntry(fPEImage, &ImageDebugDirectory);
  2342. break;
  2343. case IMAGE_DEBUG_TYPE_UNKNOWN:
  2344. case IMAGE_DEBUG_TYPE_EXCEPTION:
  2345. case IMAGE_DEBUG_TYPE_FIXUP:
  2346. case IMAGE_DEBUG_TYPE_BORLAND:
  2347. case IMAGE_DEBUG_TYPE_RESERVED10:
  2348. case IMAGE_DEBUG_TYPE_CLSID:
  2349. break;
  2350. default:
  2351. break;
  2352. }
  2353. OffsetImageDebugDirectory += sizeof(IMAGE_DEBUG_DIRECTORY);
  2354. }
  2355. cleanup:
  2356. return true;
  2357. }
  2358. bool CModuleInfo::ProcessDebugTypeMiscDirectoryEntry(const bool fPEImage, const bool fDmpFile, const HANDLE hModuleHandle, const PIMAGE_DEBUG_DIRECTORY lpImageDebugDirectory)
  2359. {
  2360. bool fReturnValue = false;
  2361. PIMAGE_DEBUG_MISC lpImageDebugMisc = NULL, lpCurrentImageDebugMiscPointer = NULL;
  2362. ULONG OffsetImageDebugDirectory = NULL;
  2363. unsigned long ulSizeOfMiscDirectoryEntry = lpImageDebugDirectory->SizeOfData;
  2364. //
  2365. // DBG files tend to store the EXE name here... not too useful for now...
  2366. //
  2367. if (!fPEImage)
  2368. {
  2369. fReturnValue = true;
  2370. goto cleanup;
  2371. }
  2372. //
  2373. // Allocate storage for the MISC data...
  2374. //
  2375. lpImageDebugMisc = (PIMAGE_DEBUG_MISC) new BYTE[ulSizeOfMiscDirectoryEntry];
  2376. if (lpImageDebugMisc == NULL)
  2377. goto cleanup;
  2378. // Calculate the location/size so we can load it.
  2379. if (fDmpFile)
  2380. {
  2381. OffsetImageDebugDirectory = lpImageDebugDirectory->AddressOfRawData;
  2382. } else
  2383. {
  2384. OffsetImageDebugDirectory = lpImageDebugDirectory->PointerToRawData;
  2385. }
  2386. // Advance to the location of the Debug Info
  2387. SetReadPointer(fDmpFile, hModuleHandle, OffsetImageDebugDirectory, FILE_BEGIN);
  2388. // Read the data...
  2389. if (!DoRead(fDmpFile, hModuleHandle, lpImageDebugMisc, ulSizeOfMiscDirectoryEntry))
  2390. goto cleanup;
  2391. // Set our pointer to the start of our data...
  2392. lpCurrentImageDebugMiscPointer = lpImageDebugMisc;
  2393. //
  2394. // The logic of this routine will skip past bad sections of the MISC datastream...
  2395. //
  2396. while(ulSizeOfMiscDirectoryEntry > 0)
  2397. {
  2398. //
  2399. // Hopefully we have a string here...
  2400. //
  2401. if (lpCurrentImageDebugMiscPointer->DataType == IMAGE_DEBUG_MISC_EXENAME)
  2402. {
  2403. LPSTR lpszExeName;
  2404. lpszExeName = (LPSTR)&lpCurrentImageDebugMiscPointer->Data[ 0 ];
  2405. // Save off the DBG Path...
  2406. if (m_tszPEImageDebugDirectoryDBGPath)
  2407. delete [] m_tszPEImageDebugDirectoryDBGPath;
  2408. if (lpCurrentImageDebugMiscPointer->Unicode)
  2409. {
  2410. // Is this a Unicode string?
  2411. m_tszPEImageDebugDirectoryDBGPath = CUtilityFunctions::CopyUnicodeStringToTSTR((LPWSTR)lpszExeName);
  2412. } else
  2413. {
  2414. // Is this an ANSI string?
  2415. m_tszPEImageDebugDirectoryDBGPath = CUtilityFunctions::CopyAnsiStringToTSTR(lpszExeName);
  2416. }
  2417. if (!m_tszPEImageDebugDirectoryDBGPath)
  2418. goto cleanup;
  2419. break;
  2420. } else
  2421. {
  2422. // Beware of corrupt images
  2423. if (lpCurrentImageDebugMiscPointer->Length == 0)
  2424. {
  2425. break;
  2426. }
  2427. // Decrement the ulSizeOfMiscDirectoryEntry by the length of this "stuff"
  2428. ulSizeOfMiscDirectoryEntry -= lpCurrentImageDebugMiscPointer->Length;
  2429. // If our new value exceeds the SizeOfData we need to bail...
  2430. if (ulSizeOfMiscDirectoryEntry > lpImageDebugDirectory->SizeOfData)
  2431. {
  2432. ulSizeOfMiscDirectoryEntry = 0; // Avoid AV on bad exe
  2433. break;
  2434. }
  2435. lpCurrentImageDebugMiscPointer = (PIMAGE_DEBUG_MISC) (lpCurrentImageDebugMiscPointer + lpCurrentImageDebugMiscPointer->Length);
  2436. }
  2437. }
  2438. fReturnValue = true;
  2439. cleanup:
  2440. if (lpImageDebugMisc)
  2441. {
  2442. delete [] lpImageDebugMisc;
  2443. lpImageDebugMisc = NULL;
  2444. }
  2445. return fReturnValue;
  2446. }
  2447. bool CModuleInfo::ProcessDebugTypeCoffDirectoryEntry(const bool fPEImage, const PIMAGE_DEBUG_DIRECTORY lpImageDebugDirectory)
  2448. {
  2449. //
  2450. // The only thing we really care about is the size right now...
  2451. //
  2452. if (fPEImage)
  2453. {
  2454. m_dwPEImageDebugDirectoryCoffSize = lpImageDebugDirectory->SizeOfData;
  2455. } else
  2456. {
  2457. m_dwDBGImageDebugDirectoryCoffSize = lpImageDebugDirectory->SizeOfData;
  2458. }
  2459. return true;
  2460. }
  2461. bool CModuleInfo::ProcessDebugTypeFPODirectoryEntry(const bool fPEImage, const PIMAGE_DEBUG_DIRECTORY lpImageDebugDirectory)
  2462. {
  2463. //
  2464. // The only thing we really care about is the size right now...
  2465. //
  2466. if (fPEImage)
  2467. {
  2468. m_dwPEImageDebugDirectoryFPOSize = lpImageDebugDirectory->SizeOfData;
  2469. } else
  2470. {
  2471. m_dwDBGImageDebugDirectoryFPOSize = lpImageDebugDirectory->SizeOfData;
  2472. }
  2473. return true;
  2474. }
  2475. bool CModuleInfo::ProcessDebugTypeCVDirectoryEntry(const bool fPEImage, const bool fDmpFile, const HANDLE hModuleHandle, const PIMAGE_DEBUG_DIRECTORY lpImageDebugDirectory)
  2476. {
  2477. bool fReturnValue = false;
  2478. ULONG OffsetImageDebugDirectory;
  2479. DWORD dwCVFormatSpecifier;
  2480. char szPdb[_MAX_PATH * 3]; // Must this be so large?
  2481. // Calculate the location/size so we can load it.
  2482. if (fDmpFile)
  2483. {
  2484. OffsetImageDebugDirectory = lpImageDebugDirectory->AddressOfRawData;
  2485. } else
  2486. {
  2487. OffsetImageDebugDirectory = lpImageDebugDirectory->PointerToRawData;
  2488. }
  2489. // Advance to the location of the Debug Info
  2490. SetReadPointer(fDmpFile, hModuleHandle, OffsetImageDebugDirectory, FILE_BEGIN);
  2491. // Read the data...
  2492. if (!DoRead(fDmpFile, hModuleHandle, &dwCVFormatSpecifier, sizeof(DWORD)))
  2493. goto cleanup;
  2494. if (fPEImage)
  2495. {
  2496. m_dwPEImageDebugDirectoryPDBFormatSpecifier = dwCVFormatSpecifier;
  2497. } else
  2498. {
  2499. m_dwDBGDebugDirectoryPDBFormatSpecifier = dwCVFormatSpecifier;
  2500. }
  2501. switch (dwCVFormatSpecifier)
  2502. {
  2503. case sigNB09:
  2504. case sigNB11:
  2505. //
  2506. // The only thing we really care about is the size right now...
  2507. //
  2508. if (fPEImage)
  2509. {
  2510. m_dwPEImageDebugDirectoryCVSize = lpImageDebugDirectory->SizeOfData;
  2511. } else
  2512. {
  2513. m_dwDBGImageDebugDirectoryCVSize = lpImageDebugDirectory->SizeOfData;
  2514. }
  2515. break;
  2516. case sigNB10:
  2517. NB10I nb10i;
  2518. // Read the data...
  2519. if (!DoRead(fDmpFile, hModuleHandle, &nb10i.off, sizeof(NB10I) - sizeof(DWORD)))
  2520. goto cleanup;
  2521. if (fPEImage)
  2522. {
  2523. // Save away the PDB Signature...
  2524. m_dwPEImageDebugDirectoryPDBSignature = nb10i.sig;
  2525. // Save away the PDB Age...
  2526. m_dwPEImageDebugDirectoryPDBAge = nb10i.age;
  2527. } else
  2528. {
  2529. // Save away the PDB Signature...
  2530. m_dwDBGDebugDirectoryPDBSignature = nb10i.sig;
  2531. // Save away the PDB Age...
  2532. m_dwDBGDebugDirectoryPDBAge = nb10i.age;
  2533. }
  2534. // Read the data...
  2535. if (!DoRead(fDmpFile, hModuleHandle, szPdb, (lpImageDebugDirectory->SizeOfData) - sizeof(NB10I)))
  2536. goto cleanup;
  2537. if (szPdb[0] != '\0')
  2538. {
  2539. // Save the data (as appropriate)
  2540. if (fPEImage)
  2541. {
  2542. // Copy the PDB path away...
  2543. m_tszPEImageDebugDirectoryPDBPath = CUtilityFunctions::CopyAnsiStringToTSTR(szPdb);
  2544. if (!m_tszPEImageDebugDirectoryPDBPath)
  2545. goto cleanup;
  2546. } else
  2547. {
  2548. // Copy the PDB path away...
  2549. m_tszDBGDebugDirectoryPDBPath = CUtilityFunctions::CopyAnsiStringToTSTR(szPdb);
  2550. if (!m_tszDBGDebugDirectoryPDBPath)
  2551. goto cleanup;
  2552. // We now know that we have a DBG/PDB combination...
  2553. m_enumPEImageSymbolStatus = SYMBOLS_DBG_AND_PDB;
  2554. }
  2555. }
  2556. break;
  2557. case sigRSDS:
  2558. RSDSI rsdsi;
  2559. // Read the RSDSI structure (except for the rsds DWORD at the beginning).
  2560. if (!DoRead(fDmpFile, hModuleHandle, &rsdsi.guidSig, sizeof(RSDSI) - sizeof(DWORD)))
  2561. goto cleanup;
  2562. wchar_t wszGuid[39];
  2563. StringFromGUID2(rsdsi.guidSig, wszGuid, sizeof(wszGuid)/sizeof(wchar_t));
  2564. if (fPEImage)
  2565. {
  2566. // Save away the PDB Age...
  2567. m_dwPEImageDebugDirectoryPDBAge = rsdsi.age;
  2568. // Copy the GUID...
  2569. m_tszPEImageDebugDirectoryPDBGuid = CUtilityFunctions::CopyUnicodeStringToTSTR(wszGuid);
  2570. } else
  2571. {
  2572. // Save away the PDB Age...
  2573. m_dwDBGDebugDirectoryPDBAge = rsdsi.age;
  2574. // Copy the GUID...
  2575. m_tszDBGDebugDirectoryPDBGuid = CUtilityFunctions::CopyUnicodeStringToTSTR(wszGuid);
  2576. }
  2577. // Now, read in the PDB path... apparently it's in UTF8 format...
  2578. if (!DoRead(fDmpFile, hModuleHandle, szPdb, (lpImageDebugDirectory->SizeOfData) - sizeof(RSDSI)))
  2579. goto cleanup;
  2580. if (szPdb[0] != '\0')
  2581. {
  2582. // Save the data (as appropriate)
  2583. if (fPEImage)
  2584. {
  2585. wchar_t wszPdb[_MAX_PATH];
  2586. CUtilityFunctions::UTF8ToUnicode(szPdb, wszPdb, sizeof(wszPdb));
  2587. // Copy the PDB path away...
  2588. m_tszPEImageDebugDirectoryPDBPath = CUtilityFunctions::CopyUnicodeStringToTSTR(wszPdb);
  2589. if (!m_tszPEImageDebugDirectoryPDBPath)
  2590. goto cleanup;
  2591. } else
  2592. {
  2593. wchar_t wszPdb[_MAX_PATH];
  2594. CUtilityFunctions::UTF8ToUnicode(szPdb, wszPdb, sizeof(wszPdb));
  2595. // Copy the PDB path away...
  2596. m_tszDBGDebugDirectoryPDBPath = CUtilityFunctions::CopyUnicodeStringToTSTR(wszPdb);
  2597. if (!m_tszDBGDebugDirectoryPDBPath)
  2598. goto cleanup;
  2599. }
  2600. }
  2601. break;
  2602. // Unknown CV format...
  2603. default:
  2604. break;
  2605. }
  2606. fReturnValue = true;
  2607. cleanup:
  2608. return fReturnValue;
  2609. }
  2610. bool CModuleInfo::ProcessDebugTypeOMAPDirectoryEntry(const bool fPEImage, const PIMAGE_DEBUG_DIRECTORY lpImageDebugDirectory)
  2611. {
  2612. DWORD dwSize = lpImageDebugDirectory->SizeOfData;
  2613. //
  2614. // The only thing we really care about is the size right now...
  2615. //
  2616. switch (lpImageDebugDirectory->Type)
  2617. {
  2618. case IMAGE_DEBUG_TYPE_OMAP_TO_SRC:
  2619. if (fPEImage)
  2620. {
  2621. m_dwPEImageDebugDirectoryOMAPtoSRCSize = dwSize;
  2622. } else
  2623. {
  2624. m_dwDBGImageDebugDirectoryOMAPtoSRCSize = dwSize;
  2625. }
  2626. break;
  2627. case IMAGE_DEBUG_TYPE_OMAP_FROM_SRC:
  2628. if (fPEImage)
  2629. {
  2630. m_dwPEImageDebugDirectoryOMAPfromSRCSize = dwSize;
  2631. } else
  2632. {
  2633. m_dwDBGImageDebugDirectoryOMAPfromSRCSize = dwSize;
  2634. }
  2635. break;
  2636. }
  2637. return true;
  2638. }
  2639. bool CModuleInfo::OutputDataToStdoutInternalSymbolInfo(DWORD dwCoffSize, DWORD dwFPOSize, DWORD dwCVSize, DWORD dwOMAPtoSRC, DWORD dwOMAPfromSRC)
  2640. {
  2641. // _tprintf(TEXT(" Module has internal symbols.\n"));
  2642. if (dwCoffSize)
  2643. {
  2644. _tprintf(TEXT(" Internal COFF Symbols - Size 0x%08x bytes\n"), dwCoffSize);
  2645. }
  2646. if (dwFPOSize)
  2647. {
  2648. _tprintf(TEXT(" Internal FPO Symbols - Size 0x%08x bytes\n"), dwFPOSize);
  2649. }
  2650. if (dwCVSize)
  2651. {
  2652. _tprintf(TEXT(" Internal CV Symbols - Size 0x%08x bytes\n"), dwCVSize);
  2653. }
  2654. if (dwOMAPtoSRC)
  2655. {
  2656. _tprintf(TEXT(" Internal -> SRC Symbols - Size 0x%08x bytes\n"), dwOMAPtoSRC);
  2657. }
  2658. if (dwOMAPfromSRC)
  2659. {
  2660. _tprintf(TEXT(" Internal SRC -> Symbols - Size 0x%08x bytes\n"), dwOMAPfromSRC);
  2661. }
  2662. return true;
  2663. }
  2664. //
  2665. // Dump DBG information
  2666. //
  2667. bool CModuleInfo::OutputDataToStdoutDbgSymbolInfo(LPCTSTR tszModulePointerToDbg, DWORD dwTimeDateStamp, DWORD dwChecksum, DWORD dwSizeOfImage, LPCTSTR tszDbgComment, DWORD dwExpectedTimeDateStamp, DWORD dwExpectedChecksum, DWORD dwExpectedSizeOfImage)
  2668. {
  2669. if (!tszDbgComment)
  2670. {
  2671. // Dump out the pointer to the DBG file from the PE Image
  2672. if (tszModulePointerToDbg)
  2673. {
  2674. _tprintf(TEXT(" Module Pointer to DBG = [%s]\n"), tszModulePointerToDbg);
  2675. } else
  2676. {
  2677. _tprintf(TEXT(" Module had DBG File stripped from it.\n"));
  2678. }
  2679. time_t time = dwTimeDateStamp;
  2680. _tprintf(TEXT(" Module TimeDateStamp = 0x%08x - %s"), dwTimeDateStamp, _tctime(&time));
  2681. _tprintf(TEXT(" Module Checksum = 0x%08x\n"), dwChecksum);
  2682. _tprintf(TEXT(" Module SizeOfImage = 0x%08x\n"), dwSizeOfImage);
  2683. } else
  2684. {
  2685. TCHAR tszBuffer[2*_MAX_PATH]; // This should be large enough ;)
  2686. size_t tszStringLength;
  2687. // Is this discrepancy stuff...
  2688. if (tszModulePointerToDbg)
  2689. {
  2690. _tprintf(TEXT(" DBG File = [%s] [%s]\n"), tszModulePointerToDbg, tszDbgComment);
  2691. }
  2692. time_t time = dwTimeDateStamp;
  2693. _stprintf(tszBuffer, TEXT(" DBG TimeDateStamp = 0x%08x - %s"), dwTimeDateStamp, _tctime(&time));
  2694. // If our TimeDateStamps don't match... we have some fixup to do...
  2695. if (dwTimeDateStamp != dwExpectedTimeDateStamp)
  2696. {
  2697. tszStringLength = _tcslen(tszBuffer);
  2698. if (tszBuffer[tszStringLength-1] == '\n')
  2699. tszBuffer[tszStringLength-1] = '\0';
  2700. }
  2701. _tprintf(tszBuffer);
  2702. // If our TimeDateStamps don't match... we have some fixup to do...
  2703. if (dwTimeDateStamp != dwExpectedTimeDateStamp)
  2704. {
  2705. _tprintf(TEXT(" [%s]!\n"), (dwTimeDateStamp > dwExpectedTimeDateStamp) ? TEXT("NEWER") : TEXT("OLDER"));
  2706. }
  2707. _tprintf(TEXT(" DBG Checksum = 0x%08x [%s]\n"), dwChecksum, ( (dwChecksum == dwExpectedChecksum) ? TEXT("MATCHED"):TEXT("UNMATCHED")) );
  2708. _tprintf(TEXT(" DBG SizeOfImage = 0x%08x [%s]\n"), dwSizeOfImage, ( ( dwSizeOfImage == dwExpectedSizeOfImage) ? TEXT("MATCHED"):TEXT("UNMATCHED")) );
  2709. }
  2710. return true;
  2711. }
  2712. bool CModuleInfo::OutputDataToStdoutPdbSymbolInfo(DWORD dwPDBFormatSpecifier, LPTSTR tszModulePointerToPDB, DWORD dwPDBSignature, LPTSTR tszPDBGuid, DWORD dwPDBAge, LPCTSTR tszPdbComment)
  2713. {
  2714. if (tszModulePointerToPDB)
  2715. {
  2716. if (!tszPdbComment)
  2717. {
  2718. _tprintf(TEXT(" Module Pointer to PDB = [%s]\n"), tszModulePointerToPDB);
  2719. } else
  2720. {
  2721. _tprintf(TEXT(" PDB File = [%s] [%s]\n"), tszModulePointerToPDB, tszPdbComment);
  2722. }
  2723. switch (dwPDBFormatSpecifier)
  2724. {
  2725. case sigNB10:
  2726. _tprintf(TEXT(" Module PDB Signature = 0x%x\n"), dwPDBSignature);
  2727. break;
  2728. case sigRSDS:
  2729. _tprintf(TEXT(" Module PDB Guid = %s\n"), tszPDBGuid);
  2730. break;
  2731. default:
  2732. _tprintf(TEXT(" UNKNOWN PDB Format!\n"));
  2733. break;
  2734. }
  2735. _tprintf(TEXT(" Module PDB Age = 0x%x\n"), dwPDBAge);
  2736. } else
  2737. {
  2738. _tprintf(TEXT(" Module has PDB File\n"));
  2739. _tprintf(TEXT(" Module Pointer to PDB = [UNKNOWN] (Could not find in PE Image)\n"));
  2740. }
  2741. return true;
  2742. }
  2743. bool CModuleInfo::OutputDataToStdoutModuleInfo(DWORD dwModuleNumber)
  2744. {
  2745. _tprintf(TEXT("Module[%3d] [%s] %s\n"), dwModuleNumber, m_tszPEImageModuleFileSystemPath, (m_dwPEImageDebugDirectoryCVSize ? TEXT("(Source Enabled)") : TEXT("")));
  2746. // LPTSTR lpMachineArchitecture;
  2747. //
  2748. // switch(m_wPEImageMachineArchitecture)
  2749. // {
  2750. // case IMAGE_FILE_MACHINE_I386:
  2751. // lpMachineArchitecture = TEXT("Binary Image for Intel Machines");
  2752. // break;
  2753. //
  2754. // case IMAGE_FILE_MACHINE_ALPHA64:
  2755. // lpMachineArchitecture = TEXT("Binary Image for Alpha Machines");
  2756. // break;
  2757. //
  2758. // default:
  2759. // lpMachineArchitecture = TEXT("Binary Image for Unknown Machine Architecture");
  2760. // }
  2761. //
  2762. // if (m_wPEImageMachineArchitecture) _tprintf(TEXT(" %s\n"), lpMachineArchitecture);
  2763. //
  2764. // First, let's output version information if requested
  2765. //
  2766. if (g_lpProgramOptions->GetMode(CProgramOptions::CollectVersionInfoMode) )
  2767. {
  2768. // Version Information
  2769. if (m_tszPEImageFileVersionCompanyName) _tprintf(TEXT(" Company Name: %s\n"), m_tszPEImageFileVersionCompanyName);
  2770. if (m_tszPEImageFileVersionDescription) _tprintf(TEXT(" File Description: %s\n"), m_tszPEImageFileVersionDescription);
  2771. if (m_tszPEImageProductVersionString) _tprintf(TEXT(" Product Version: %s\n"), m_tszPEImageProductVersionString);
  2772. if (m_tszPEImageFileVersionString) _tprintf(TEXT(" File Version: %s\n"), m_tszPEImageFileVersionString);
  2773. if (m_dwPEImageFileSize) _tprintf(TEXT(" File Size (bytes): %d\n"), m_dwPEImageFileSize);
  2774. if ( m_ftPEImageFileTimeDateStamp.dwHighDateTime || m_ftPEImageFileTimeDateStamp.dwLowDateTime)
  2775. {
  2776. enum { FILETIME_BUFFERSIZE = 128 };
  2777. TCHAR tszFileTime[FILETIME_BUFFERSIZE];
  2778. if (OutputFileTime(m_ftPEImageFileTimeDateStamp, tszFileTime, FILETIME_BUFFERSIZE))
  2779. _tprintf(TEXT(" File Date: %s\n"), tszFileTime);
  2780. }
  2781. }
  2782. return true;
  2783. }
  2784. bool CModuleInfo::OutputDataToStdoutThisModule()
  2785. {
  2786. //
  2787. // If we're not doing "Discrepancies Only" then we output this module unconditionally...
  2788. //
  2789. if (!g_lpProgramOptions->GetMode(CProgramOptions::OutputDiscrepanciesOnly))
  2790. return true;
  2791. //
  2792. // If we're not in verification mode, then we output everything...
  2793. //
  2794. if (!g_lpProgramOptions->GetMode(CProgramOptions::VerifySymbolsMode))
  2795. return true;
  2796. //
  2797. // This is "Discrepancy Only" mode, so check for discrepancies...
  2798. //
  2799. bool fAnyDiscrepancies = false;
  2800. // Hey, if they only want to dump out modules with discrepancies... check to see
  2801. // if this qualifies...
  2802. switch (m_enumPEImageSymbolStatus)
  2803. {
  2804. // Consider these normal status codes...
  2805. case SYMBOLS_DBG:
  2806. case SYMBOLS_DBG_AND_PDB:
  2807. case SYMBOLS_PDB:
  2808. case SYMBOLS_LOCAL:
  2809. break;
  2810. // Anything else is worth reporting...
  2811. default:
  2812. fAnyDiscrepancies = true;
  2813. }
  2814. // If we don't have a discrepancy yet... let's look further...
  2815. if (!fAnyDiscrepancies)
  2816. {
  2817. // Is there a DBG file?
  2818. if ( (m_enumPEImageSymbolStatus == SYMBOLS_DBG) ||
  2819. (m_enumPEImageSymbolStatus == SYMBOLS_DBG_AND_PDB) )
  2820. {
  2821. // Does it match?
  2822. if ( m_enumDBGModuleStatus != SYMBOL_MATCH )
  2823. fAnyDiscrepancies = true;
  2824. }
  2825. // Is there a PDB file?
  2826. if ( GetDebugDirectoryPDBPath() )
  2827. {
  2828. if (m_enumPDBModuleStatus != SYMBOL_MATCH )
  2829. fAnyDiscrepancies = true;
  2830. }
  2831. }
  2832. return fAnyDiscrepancies;
  2833. }
  2834. bool CModuleInfo::ProcessPDBSourceInfo(PDB *lpPdb)
  2835. {
  2836. bool fReturnValue = false;
  2837. DBI* lpDbi = NULL;
  2838. // Module variables...
  2839. Mod * lpMod = NULL;
  2840. Mod * lpPrevMod = NULL;
  2841. long cb;
  2842. // Type variables...
  2843. TPI * lpTpi = NULL;
  2844. TI tiMin;
  2845. TI tiMac;
  2846. // Summary variables
  2847. m_dwPDBTotalBytesOfLineInformation = 0;
  2848. m_dwPDBTotalBytesOfSymbolInformation = 0;
  2849. m_dwPDBTotalSymbolTypesRange = 0;
  2850. if (!PDBOpenDBI(lpPdb, pdbRead, NULL, &lpDbi))
  2851. goto cleanup;
  2852. //
  2853. // Enumerate through the modules in the Dbi interface we opened...
  2854. //
  2855. while (DBIQueryNextMod(lpDbi, lpMod, &lpMod) && lpMod)
  2856. {
  2857. // If we had a Module Previously... close it...
  2858. if (lpPrevMod)
  2859. {
  2860. ModClose(lpPrevMod);
  2861. lpPrevMod = NULL;
  2862. }
  2863. // Check that Source line info is removed
  2864. ModQueryLines(lpMod, NULL, &cb);
  2865. // If we have lines... add these to our total...
  2866. m_dwPDBTotalBytesOfLineInformation+= cb;
  2867. // Check that local symbols are removed
  2868. ModQuerySymbols(lpMod, NULL, &cb);
  2869. // If we have symbols for this module... add these to our total...
  2870. m_dwPDBTotalBytesOfSymbolInformation+= cb;
  2871. // Save the current module (so we can close it if needed)...
  2872. lpPrevMod = lpMod;
  2873. }
  2874. //
  2875. // Attempt to open the Tpi Interface
  2876. //
  2877. PDBOpenTpi(lpPdb, pdbRead, &lpTpi);
  2878. // If we
  2879. if(lpTpi)
  2880. {
  2881. // Find the Min and Max Index...
  2882. tiMin = TypesQueryTiMinEx(lpTpi);
  2883. tiMac = TypesQueryTiMacEx(lpTpi);
  2884. if (tiMin < tiMac)
  2885. {
  2886. m_dwPDBTotalSymbolTypesRange = tiMac - tiMin;
  2887. }
  2888. }
  2889. fReturnValue = true;
  2890. cleanup:
  2891. if (lpTpi)
  2892. {
  2893. TypesClose(lpTpi);
  2894. lpTpi = NULL;
  2895. }
  2896. if (lpMod)
  2897. {
  2898. ModClose(lpMod);
  2899. lpMod = NULL;
  2900. }
  2901. if (lpPrevMod)
  2902. {
  2903. ModClose(lpPrevMod);
  2904. lpPrevMod = NULL;
  2905. }
  2906. if (lpDbi)
  2907. {
  2908. DBIClose(lpDbi);
  2909. }
  2910. return fReturnValue;
  2911. }