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.

1877 lines
53 KiB

  1. #include <private.h>
  2. #include <symbols.h>
  3. #include "globals.h"
  4. // forward reference
  5. void
  6. RetrievePdbInfo(
  7. PIMGHLP_DEBUG_DATA pIDD,
  8. CHAR const *szReference
  9. );
  10. BOOL
  11. FindDebugInfoFileExCallback(
  12. HANDLE FileHandle,
  13. PSTR FileName,
  14. PVOID CallerData
  15. );
  16. BOOL
  17. FindExecutableImageExCallback(
  18. HANDLE FileHandle,
  19. PSTR FileName,
  20. PVOID CallerData
  21. );
  22. BOOL
  23. ProcessDebugInfo(
  24. PIMGHLP_DEBUG_DATA pIDD,
  25. DWORD datasrc
  26. );
  27. __inline
  28. BOOL
  29. ProcessImageDebugInfo(
  30. PIMGHLP_DEBUG_DATA pIDD
  31. )
  32. {
  33. return ProcessDebugInfo(pIDD, dsImage);
  34. }
  35. __inline
  36. BOOL
  37. ProcessInProcDebugInfo(
  38. PIMGHLP_DEBUG_DATA pIDD
  39. )
  40. {
  41. return ProcessDebugInfo(pIDD, dsInProc);
  42. }
  43. __inline
  44. BOOL
  45. ProcessDbgDebugInfo(
  46. PIMGHLP_DEBUG_DATA pIDD
  47. )
  48. {
  49. return ProcessDebugInfo(pIDD, dsDbg);
  50. }
  51. BOOL
  52. ProcessCallerDataDebugInfo(
  53. PIMGHLP_DEBUG_DATA pIDD
  54. )
  55. {
  56. PMODLOAD_DATA mld = pIDD->mld;
  57. PIMAGE_DEBUG_DIRECTORY dd;
  58. PCHAR pCV;
  59. DWORD cdd;
  60. DWORD i;
  61. if (!mld)
  62. return FALSE;
  63. if (!mld->ssize
  64. || !mld->size
  65. || !mld->data)
  66. return FALSE;
  67. if (mld->ssig != DBHHEADER_DEBUGDIRS)
  68. return FALSE;
  69. cdd = mld->size / sizeof(IMAGE_DEBUG_DIRECTORY);
  70. dd = (PIMAGE_DEBUG_DIRECTORY)mld->data;
  71. for (i = 0; i < cdd; i++, dd++) {
  72. if (dd->Type != IMAGE_DEBUG_TYPE_CODEVIEW)
  73. continue;
  74. pCV = (PCHAR)mld->data + dd->PointerToRawData;
  75. pIDD->fCvMapped = TRUE;
  76. pIDD->pMappedCv = (PCHAR)pCV;
  77. pIDD->cMappedCv = dd->SizeOfData;
  78. pIDD->dsCV = dsCallerData;
  79. pIDD->PdbSignature = 0;
  80. pIDD->PdbAge = 0;
  81. RetrievePdbInfo(pIDD, pIDD->ImageFilePath);
  82. mdSet(pIDD->md, dd->Type, dsNone, dsCallerData);
  83. break;
  84. }
  85. return TRUE;
  86. }
  87. // functions called by the MODULE_DATA array...
  88. BOOL
  89. mdfnOpenDbgFile(
  90. PIMGHLP_DEBUG_DATA pIDD
  91. )
  92. {
  93. dprint("mdfnOpenDbgFile()\n");
  94. if (pIDD->DbgFileHandle)
  95. return TRUE;
  96. if (*pIDD->OriginalDbgFileName) {
  97. pIDD->DbgFileHandle = fnFindDebugInfoFileEx(
  98. pIDD->OriginalDbgFileName,
  99. pIDD->SymbolPath,
  100. pIDD->DbgFilePath,
  101. FindDebugInfoFileExCallback,
  102. pIDD,
  103. fdifRECURSIVE);
  104. }
  105. if (!pIDD->DbgFileHandle) {
  106. pIDD->DbgFileHandle = fnFindDebugInfoFileEx(
  107. pIDD->ImageName,
  108. pIDD->SymbolPath,
  109. pIDD->DbgFilePath,
  110. FindDebugInfoFileExCallback,
  111. pIDD,
  112. fdifRECURSIVE);
  113. }
  114. if (!pIDD->DbgFileHandle)
  115. g.LastSymLoadError = SYMLOAD_DBGNOTFOUND;
  116. // if we have a .dbg file. See what we can get from it.
  117. if (pIDD->DbgFileHandle) {
  118. ProcessDbgDebugInfo(pIDD);
  119. }
  120. return TRUE;
  121. }
  122. BOOL
  123. mdfnGetExecutableImage(
  124. PIMGHLP_DEBUG_DATA pIDD
  125. )
  126. {
  127. dprint("mdfnGetExecutableImage()\n");
  128. if (!*pIDD->ImageName)
  129. return TRUE;
  130. if (!pIDD->ImageFileHandle)
  131. pIDD->ImageFileHandle = FindExecutableImageEx(pIDD->ImageName,
  132. pIDD->SymbolPath,
  133. pIDD->ImageFilePath,
  134. FindExecutableImageExCallback,
  135. pIDD);
  136. if (pIDD->ImageFileHandle)
  137. ProcessImageDebugInfo(pIDD);
  138. return TRUE;
  139. }
  140. // this struct is used to initilaize the module data array for a new module
  141. static MODULE_DATA gmd[NUM_MODULE_DATA_ENTRIES] =
  142. {
  143. {mdHeader, dsNone, dsNone, FALSE, NULL},
  144. {mdSecHdrs, dsNone, dsNone, FALSE, NULL},
  145. {IMAGE_DEBUG_TYPE_UNKNOWN, dsNone, dsNone, FALSE, NULL},
  146. {IMAGE_DEBUG_TYPE_COFF, dsNone, dsNone, FALSE, NULL},
  147. {IMAGE_DEBUG_TYPE_CODEVIEW, dsNone, dsNone, FALSE, NULL},
  148. {IMAGE_DEBUG_TYPE_FPO, dsNone, dsNone, TRUE, mdfnGetExecutableImage},
  149. {IMAGE_DEBUG_TYPE_MISC, dsNone, dsNone, FALSE, NULL},
  150. {IMAGE_DEBUG_TYPE_EXCEPTION, dsNone, dsNone, FALSE, NULL},
  151. {IMAGE_DEBUG_TYPE_FIXUP, dsNone, dsNone, FALSE, NULL},
  152. {IMAGE_DEBUG_TYPE_OMAP_TO_SRC, dsNone, dsNone, FALSE, NULL},
  153. {IMAGE_DEBUG_TYPE_OMAP_FROM_SRC, dsNone, dsNone, FALSE, NULL},
  154. {IMAGE_DEBUG_TYPE_BORLAND, dsNone, dsNone, FALSE, NULL},
  155. {IMAGE_DEBUG_TYPE_RESERVED10, dsNone, dsNone, FALSE, NULL},
  156. {IMAGE_DEBUG_TYPE_CLSID, dsNone, dsNone, FALSE, NULL}
  157. };
  158. DWORD
  159. mdSet(
  160. PMODULE_DATA md,
  161. DWORD id,
  162. DWORD hint,
  163. DWORD src
  164. )
  165. {
  166. DWORD i;
  167. for (i = 0; i < NUM_MODULE_DATA_ENTRIES; md++, i++) {
  168. if (md->id == id) {
  169. if (hint != dsNone)
  170. md->hint = hint;
  171. if (src != dsNone)
  172. md->src = src;
  173. return i;
  174. }
  175. }
  176. return 0;
  177. }
  178. void
  179. mdDump(
  180. PMODULE_DATA md,
  181. BOOL verbose
  182. )
  183. {
  184. DWORD i;
  185. static PCHAR idstr[] =
  186. {
  187. "mdHeader",
  188. "mdSecHdrs",
  189. "IMAGE_DEBUG_TYPE_UNKNOWN",
  190. "IMAGE_DEBUG_TYPE_COFF",
  191. "IMAGE_DEBUG_TYPE_CODEVIEW",
  192. "IMAGE_DEBUG_TYPE_FPO",
  193. "IMAGE_DEBUG_TYPE_MISC",
  194. "IMAGE_DEBUG_TYPE_EXCEPTION",
  195. "IMAGE_DEBUG_TYPE_FIXUP",
  196. "IMAGE_DEBUG_TYPE_OMAP_TO_SRC",
  197. "IMAGE_DEBUG_TYPE_OMAP_FROM_SRC",
  198. "IMAGE_DEBUG_TYPE_BORLAND",
  199. "IMAGE_DEBUG_TYPE_RESERVED10",
  200. "IMAGE_DEBUG_TYPE_CLSID"
  201. };
  202. static PCHAR dsstr[] =
  203. {
  204. "dsNone",
  205. "dsInProc",
  206. "dsImage",
  207. "dsDbg",
  208. "dsPdb",
  209. "dsDia"
  210. };
  211. for (i = 0; i < NUM_MODULE_DATA_ENTRIES; md++, i++) {
  212. if (verbose | md->hint | md->src) {
  213. dprint("MD:%30s hint=%s src=%s\n",
  214. idstr[i],
  215. dsstr[md->hint],
  216. dsstr[md->src]);
  217. }
  218. }
  219. dprint("\n");
  220. }
  221. BOOL
  222. GetUnfoundData(
  223. PIMGHLP_DEBUG_DATA pIDD
  224. )
  225. {
  226. DWORD i;
  227. PMODULE_DATA md;
  228. for (md = pIDD->md, i = 0; i < NUM_MODULE_DATA_ENTRIES; md++, i++) {
  229. if (!md->required)
  230. continue;
  231. if (md->hint == dsNone)
  232. continue;
  233. if (md->src != dsNone)
  234. continue;
  235. if (!md->fn)
  236. continue;
  237. if (!md->fn(pIDD))
  238. return FALSE;
  239. }
  240. return TRUE;
  241. }
  242. BOOL
  243. IsImageMachineType64(
  244. DWORD MachineType
  245. )
  246. {
  247. switch(MachineType) {
  248. case IMAGE_FILE_MACHINE_AXP64:
  249. case IMAGE_FILE_MACHINE_IA64:
  250. case IMAGE_FILE_MACHINE_AMD64:
  251. return TRUE;
  252. default:
  253. return FALSE;
  254. }
  255. }
  256. ULONG
  257. ReadImageData(
  258. IN HANDLE hprocess,
  259. IN ULONG64 ul,
  260. IN ULONG64 addr,
  261. OUT LPVOID buffer,
  262. IN ULONG size
  263. )
  264. {
  265. ULONG bytesread;
  266. if (hprocess) {
  267. ULONG64 base = ul;
  268. BOOL rc;
  269. rc = ReadInProcMemory(hprocess,
  270. base + addr,
  271. buffer,
  272. size,
  273. &bytesread);
  274. if (!rc || (bytesread < (ULONG)size))
  275. return 0;
  276. } else {
  277. PCHAR p = (PCHAR)ul + addr;
  278. memcpy(buffer, p, size);
  279. }
  280. return size;
  281. }
  282. PVOID
  283. MapItRO(
  284. HANDLE FileHandle
  285. )
  286. {
  287. PVOID MappedBase = NULL;
  288. if (FileHandle) {
  289. HANDLE MappingHandle = CreateFileMapping( FileHandle, NULL, PAGE_READONLY, 0, 0, NULL );
  290. if (MappingHandle) {
  291. MappedBase = MapViewOfFile( MappingHandle, FILE_MAP_READ, 0, 0, 0 );
  292. CloseHandle(MappingHandle);
  293. }
  294. }
  295. return MappedBase;
  296. }
  297. void
  298. CloseSymbolServer(
  299. VOID
  300. )
  301. {
  302. if (!g.hSrv)
  303. return;
  304. if (g.fnSymbolServerClose)
  305. g.fnSymbolServerClose();
  306. FreeLibrary(g.hSrv);
  307. g.hSrv = 0;
  308. *g.szSrvName = 0;
  309. g.szSrvParams = NULL;
  310. g.fnSymbolServer = NULL;
  311. g.fnSymbolServerClose = NULL;
  312. g.fnSymbolServerSetOptions = NULL;
  313. }
  314. DWORD
  315. ProcessSymbolServerError(
  316. BOOL success,
  317. LPCSTR params
  318. )
  319. {
  320. DWORD rc;
  321. if (success)
  322. return NO_ERROR;
  323. rc = GetLastError();
  324. switch(rc)
  325. {
  326. case ERROR_FILE_NOT_FOUND: // obvious
  327. case ERROR_MORE_DATA: // didn't pass any tokens
  328. break;
  329. case ERROR_INVALID_NAME:
  330. CloseSymbolServer();
  331. g.hSrv = (HINSTANCE)INVALID_HANDLE_VALUE;
  332. evtprint(NULL, sevProblem, ERROR_INVALID_NAME, NULL, "SYMSRV: %s needs a downstream store.\n", params);
  333. break;
  334. case ERROR_FILE_INVALID:
  335. evtprint(NULL, sevProblem, ERROR_FILE_INVALID, NULL, "SYMSRV: Compressed file needs a downstream store.\n");
  336. break;
  337. default:
  338. dprint("symsrv error 0x%x\n", rc);
  339. break;
  340. }
  341. return rc;
  342. }
  343. BOOL
  344. GetFileFromSymbolServer(
  345. IN LPCSTR ServerInfo,
  346. IN LPCSTR FileName,
  347. IN GUID *guid,
  348. IN DWORD two,
  349. IN DWORD three,
  350. OUT LPSTR FilePath
  351. )
  352. {
  353. BOOL rc;
  354. CHAR *params;
  355. LPCSTR fname;
  356. // strip any path information from the filename
  357. for (fname = FileName + strlen(FileName); fname > FileName; fname--) {
  358. if (*fname == '\\') {
  359. fname++;
  360. break;
  361. }
  362. }
  363. // initialize server, if needed
  364. if (g.hSrv == (HINSTANCE)INVALID_HANDLE_VALUE)
  365. return FALSE;
  366. if (!g.hSrv) {
  367. g.hSrv = (HINSTANCE)INVALID_HANDLE_VALUE;
  368. strcpy(g.szSrvName, &ServerInfo[7]);
  369. if (!*g.szSrvName)
  370. return FALSE;
  371. g.szSrvParams = strchr(g.szSrvName, '*');
  372. if (!g.szSrvParams )
  373. return FALSE;
  374. *g.szSrvParams++ = '\0';
  375. g.hSrv = LoadLibrary(g.szSrvName);
  376. if (g.hSrv) {
  377. g.fnSymbolServer = (PSYMBOLSERVERPROC)GetProcAddress(g.hSrv, "SymbolServer");
  378. if (!g.fnSymbolServer) {
  379. FreeLibrary(g.hSrv);
  380. g.hSrv = (HINSTANCE)INVALID_HANDLE_VALUE;
  381. }
  382. g.fnSymbolServerClose = (PSYMBOLSERVERCLOSEPROC)GetProcAddress(g.hSrv, "SymbolServerClose");
  383. g.fnSymbolServerSetOptions = (PSYMBOLSERVERSETOPTIONSPROC)GetProcAddress(g.hSrv, "SymbolServerSetOptions");
  384. SetSymbolServerOptions(SSRVOPT_RESET, 0);
  385. SetSymbolServerOptions(SSRVOPT_GUIDPTR, 1);
  386. } else {
  387. g.hSrv = (HINSTANCE)INVALID_HANDLE_VALUE;
  388. }
  389. }
  390. // bail, if we have no valid server
  391. if (g.hSrv == INVALID_HANDLE_VALUE) {
  392. dprint("SymSrv load failure: %s\n", g.szSrvName);
  393. return FALSE;
  394. }
  395. params = strchr(ServerInfo, '*');
  396. if (!params)
  397. return FALSE;
  398. params = strchr(params+1, '*');
  399. if (!params)
  400. return FALSE;
  401. SetCriticalErrorMode();
  402. rc = g.fnSymbolServer(params+1, fname, guid, two, three, FilePath);
  403. #ifdef GETRIDOFTHISASAP
  404. if (!rc) {
  405. SetSymbolServerOptions(SSRVOPT_RESET, 0);
  406. SetSymbolServerOptions(SSRVOPT_OLDGUIDPTR, 1);
  407. rc = g.fnSymbolServer(params+1, fname, guid, two, three, FilePath);
  408. SetSymbolServerOptions(SSRVOPT_RESET, 0);
  409. SetSymbolServerOptions(SSRVOPT_GUIDPTR, 1);
  410. }
  411. #endif
  412. ResetCriticalErrorMode();
  413. ProcessSymbolServerError(rc, params+1);
  414. return rc;
  415. }
  416. BOOL
  417. SymbolServerCallback(
  418. UINT_PTR action,
  419. ULONG64 data,
  420. ULONG64 context
  421. )
  422. {
  423. BOOL rc = TRUE;
  424. char *sz;
  425. switch (action) {
  426. case SSRVACTION_TRACE:
  427. sz = (char *)data;
  428. eprint((char *)data);
  429. break;
  430. default:
  431. // unsupported
  432. rc = FALSE;
  433. break;
  434. }
  435. return rc;
  436. }
  437. void
  438. SetSymbolServerOptions(
  439. ULONG_PTR options,
  440. ULONG64 data
  441. )
  442. {
  443. static ULONG_PTR ssopts = 0;
  444. static ULONG64 ssdata = 0;
  445. if (options != SSRVOPT_RESET) {
  446. ssopts = options;
  447. ssdata = data;
  448. }
  449. if (g.fnSymbolServerSetOptions)
  450. g.fnSymbolServerSetOptions(ssopts, ssdata);
  451. }
  452. void
  453. SetSymbolServerCallback(
  454. BOOL state
  455. )
  456. {
  457. if (state)
  458. SetSymbolServerOptions(SSRVOPT_CALLBACK, (ULONG64)SymbolServerCallback);
  459. else
  460. SetSymbolServerOptions(0, 0);
  461. }
  462. BOOL
  463. ProcessOldStyleCodeView(
  464. PIMGHLP_DEBUG_DATA pIDD
  465. )
  466. {
  467. OMFSignature *omfSig;
  468. OMFDirHeader *omfDirHdr;
  469. OMFDirEntry *omfDirEntry;
  470. OMFSegMap *omfSegMap;
  471. OMFSegMapDesc *omfSegMapDesc;
  472. DWORD i, j, k, SectionSize;
  473. DWORD SectionStart;
  474. PIMAGE_SECTION_HEADER Section;
  475. if (pIDD->cOmapFrom) {
  476. // If there's omap, we need to generate the original section map
  477. omfSig = (OMFSignature *)pIDD->pMappedCv;
  478. omfDirHdr = (OMFDirHeader*) ((PCHAR)pIDD->pMappedCv + (DWORD)omfSig->filepos);
  479. omfDirEntry = (OMFDirEntry*) ((PCHAR)omfDirHdr + sizeof(OMFDirHeader));
  480. if (!omfDirHdr->cDir) {
  481. pIDD->cOmapFrom = 0;
  482. pIDD->cOmapTo = 0;
  483. }
  484. for (i=0; i<omfDirHdr->cDir; i++,omfDirEntry++) {
  485. if (omfDirEntry->SubSection == sstSegMap) {
  486. omfSegMap = (OMFSegMap*) ((PCHAR)pIDD->pMappedCv + omfDirEntry->lfo);
  487. omfSegMapDesc = (OMFSegMapDesc*)&omfSegMap->rgDesc[0];
  488. SectionStart = *(DWORD *)pIDD->pOmapFrom;
  489. SectionSize = 0;
  490. Section = (PIMAGE_SECTION_HEADER) MemAlloc(omfSegMap->cSeg * sizeof(IMAGE_SECTION_HEADER));
  491. if (Section) {
  492. for (j=0, k=0; j < omfSegMap->cSeg; j++) {
  493. if (omfSegMapDesc[j].frame) {
  494. // The linker sets the frame field to the actual section header number. Zero is
  495. // used to track absolute symbols that don't exist in a real sections.
  496. Section[k].VirtualAddress =
  497. SectionStart =
  498. SectionStart + ((SectionSize + (pIDD->ImageAlign-1)) & ~(pIDD->ImageAlign-1));
  499. Section[k].Misc.VirtualSize =
  500. SectionSize = omfSegMapDesc[j].cbSeg;
  501. k++;
  502. }
  503. }
  504. pIDD->pOriginalSections = Section;
  505. pIDD->cOriginalSections = k;
  506. }
  507. }
  508. }
  509. }
  510. return TRUE;
  511. }
  512. __inline
  513. DWORD
  514. IsDataInSection (PIMAGE_SECTION_HEADER Section,
  515. PIMAGE_DATA_DIRECTORY Data
  516. )
  517. {
  518. DWORD RealDataOffset;
  519. if ((Data->VirtualAddress >= Section->VirtualAddress) &&
  520. ((Data->VirtualAddress + Data->Size) <= (Section->VirtualAddress + Section->SizeOfRawData))) {
  521. RealDataOffset = (DWORD)(Data->VirtualAddress -
  522. Section->VirtualAddress +
  523. Section->PointerToRawData);
  524. } else {
  525. RealDataOffset = 0;
  526. }
  527. return RealDataOffset;
  528. }
  529. __inline
  530. DWORD
  531. SectionContains (
  532. HANDLE hp,
  533. PIMAGE_SECTION_HEADER pSH,
  534. PIMAGE_DATA_DIRECTORY ddir
  535. )
  536. {
  537. DWORD rva = 0;
  538. if (!ddir->VirtualAddress)
  539. return 0;
  540. if (ddir->VirtualAddress >= pSH->VirtualAddress) {
  541. if ((ddir->VirtualAddress + ddir->Size) <= (pSH->VirtualAddress + pSH->SizeOfRawData)) {
  542. rva = ddir->VirtualAddress;
  543. if (!hp)
  544. rva = rva - pSH->VirtualAddress + pSH->PointerToRawData;
  545. }
  546. }
  547. return rva;
  548. }
  549. void
  550. RetrievePdbInfo(
  551. PIMGHLP_DEBUG_DATA pIDD,
  552. CHAR const *szReference
  553. )
  554. {
  555. CHAR szRefDrive[_MAX_DRIVE];
  556. CHAR szRefPath[_MAX_DIR];
  557. PCVDD pcv = (PCVDD)pIDD->pMappedCv;
  558. if (pIDD->PdbSignature)
  559. return;
  560. switch (pcv->dwSig)
  561. {
  562. case '01BN':
  563. pIDD->PdbAge = pcv->nb10i.age;
  564. pIDD->PdbSignature = pcv->nb10i.sig;
  565. strcpy(pIDD->PdbFileName, pcv->nb10i.szPdb);
  566. break;
  567. case 'SDSR':
  568. pIDD->PdbRSDS = TRUE;
  569. pIDD->PdbAge = pcv->rsdsi.age;
  570. memcpy(&pIDD->PdbGUID, &pcv->rsdsi.guidSig, sizeof(GUID));
  571. strcpy(pIDD->PdbFileName, pcv->rsdsi.szPdb);
  572. break;
  573. default:
  574. return;
  575. }
  576. // if there is a path in the CV record - use it
  577. if ((g.SymOptions & SYMOPT_IGNORE_CVREC) == 0) {
  578. _splitpath(szReference, szRefDrive, szRefPath, NULL, NULL);
  579. _makepath(pIDD->PdbReferencePath, szRefDrive, szRefPath, NULL, NULL);
  580. if (strlen(szRefPath) > 1) {
  581. pIDD->PdbReferencePath[strlen(pIDD->PdbReferencePath)-1] = '\0';
  582. return;
  583. }
  584. }
  585. // if we have full path info for the image - use it
  586. _splitpath(pIDD->ImageName, szRefDrive, szRefPath, NULL, NULL);
  587. _makepath(pIDD->PdbReferencePath, szRefDrive, szRefPath, NULL, NULL);
  588. if (strlen(szRefPath) > 1) {
  589. pIDD->PdbReferencePath[strlen(pIDD->PdbReferencePath)-1] = '\0';
  590. return;
  591. }
  592. // No path. Put on at least a dot "."
  593. strcpy(pIDD->PdbReferencePath, ".");
  594. }
  595. BOOL
  596. FakePdbName(
  597. PIMGHLP_DEBUG_DATA pIDD
  598. )
  599. {
  600. CHAR szName[_MAX_FNAME];
  601. if (pIDD->PdbSignature) {
  602. return FALSE;
  603. }
  604. if (!pIDD->ImageName)
  605. return FALSE;
  606. _splitpath(pIDD->ImageName, NULL, NULL, szName, NULL);
  607. if (!*szName)
  608. return FALSE;
  609. strcpy(pIDD->PdbFileName, szName);
  610. strcat(pIDD->PdbFileName, ".pdb");
  611. return TRUE;
  612. }
  613. BOOL
  614. FindDebugInfoFileExCallback(
  615. HANDLE FileHandle,
  616. PSTR FileName,
  617. PVOID CallerData
  618. )
  619. {
  620. PIMGHLP_DEBUG_DATA pIDD;
  621. PIMAGE_SEPARATE_DEBUG_HEADER DbgHeader;
  622. PVOID FileMap;
  623. BOOL rc;
  624. rc = TRUE;
  625. if (!CallerData)
  626. return TRUE;
  627. pIDD = (PIMGHLP_DEBUG_DATA)CallerData;
  628. FileMap = MapItRO(FileHandle);
  629. if (!FileMap) {
  630. return FALSE;
  631. }
  632. DbgHeader = (PIMAGE_SEPARATE_DEBUG_HEADER)FileMap;
  633. // Only support .dbg files for X86 and Alpha (32 bit).
  634. if ((DbgHeader->Signature != IMAGE_SEPARATE_DEBUG_SIGNATURE) ||
  635. ((DbgHeader->Machine != IMAGE_FILE_MACHINE_I386) &&
  636. (DbgHeader->Machine != IMAGE_FILE_MACHINE_ALPHA)))
  637. {
  638. rc = FALSE;
  639. goto cleanup;
  640. }
  641. // ignore checksums, they are bogus
  642. rc = (pIDD->TimeDateStamp == DbgHeader->TimeDateStamp) ? TRUE : FALSE;
  643. cleanup:
  644. if (FileMap)
  645. UnmapViewOfFile(FileMap);
  646. return rc;
  647. }
  648. BOOL
  649. ProcessDebugInfo(
  650. PIMGHLP_DEBUG_DATA pIDD,
  651. DWORD datasrc
  652. )
  653. {
  654. BOOL status;
  655. ULONG cb;
  656. IMAGE_DOS_HEADER dh;
  657. IMAGE_NT_HEADERS32 nh32;
  658. IMAGE_NT_HEADERS64 nh64;
  659. PIMAGE_ROM_OPTIONAL_HEADER rom = NULL;
  660. IMAGE_SEPARATE_DEBUG_HEADER sdh;
  661. PIMAGE_FILE_HEADER fh;
  662. PIMAGE_DEBUG_MISC md;
  663. ULONG ddva;
  664. ULONG shva;
  665. ULONG nSections;
  666. PIMAGE_SECTION_HEADER psh;
  667. IMAGE_DEBUG_DIRECTORY dd;
  668. PIMAGE_DATA_DIRECTORY datadir;
  669. PCHAR pCV;
  670. ULONG i;
  671. int nDebugDirs = 0;
  672. HANDLE hp;
  673. ULONG64 base;
  674. IMAGE_ROM_HEADERS ROMImage;
  675. DWORD rva;
  676. PCHAR filepath;
  677. IMAGE_EXPORT_DIRECTORY expdir;
  678. DWORD fsize;
  679. BOOL rc;
  680. USHORT filetype;
  681. // setup pointers for grabing data
  682. switch (datasrc) {
  683. case dsInProc:
  684. hp = pIDD->hProcess;
  685. base = pIDD->InProcImageBase;
  686. fsize = 0;
  687. filepath = pIDD->ImageFilePath;
  688. pIDD->PdbSrc = srcCVRec;
  689. break;
  690. case dsImage:
  691. hp = NULL;
  692. pIDD->ImageMap = MapItRO(pIDD->ImageFileHandle);
  693. base = (ULONG64)pIDD->ImageMap;
  694. fsize = GetFileSize(pIDD->ImageFileHandle, NULL);
  695. filepath = pIDD->ImageFilePath;
  696. pIDD->PdbSrc = srcImagePath;
  697. break;
  698. case dsDbg:
  699. hp = NULL;
  700. pIDD->DbgFileMap = MapItRO(pIDD->DbgFileHandle);
  701. base = (ULONG64)pIDD->DbgFileMap;
  702. fsize = GetFileSize(pIDD->DbgFileHandle, NULL);
  703. filepath = pIDD->DbgFilePath;
  704. pIDD->PdbSrc = srcDbgPath;
  705. break;
  706. default:
  707. return FALSE;
  708. }
  709. // some initialization
  710. pIDD->fNeedImage = FALSE;
  711. rc = FALSE;
  712. ddva = 0;
  713. __try {
  714. // test the file type
  715. status = ReadImageData(hp, base, 0, &filetype, sizeof(filetype));
  716. if (!status) {
  717. g.LastSymLoadError = SYMLOAD_HEADERPAGEDOUT;
  718. return FALSE;
  719. }
  720. pIDD->ImageType = datasrc;
  721. if (filetype == IMAGE_SEPARATE_DEBUG_SIGNATURE)
  722. goto dbg;
  723. if (filetype == IMAGE_DOS_SIGNATURE)
  724. {
  725. // grab the dos header
  726. status = ReadImageData(hp, base, 0, &dh, sizeof(dh));
  727. if (!status) {
  728. g.LastSymLoadError = SYMLOAD_HEADERPAGEDOUT;
  729. return FALSE;
  730. }
  731. // grab the pe header
  732. status = ReadImageData(hp, base, dh.e_lfanew, &nh32, sizeof(nh32));
  733. if (!status) {
  734. g.LastSymLoadError = SYMLOAD_HEADERPAGEDOUT;
  735. return FALSE;
  736. }
  737. // read header info
  738. if (nh32.Signature != IMAGE_NT_SIGNATURE) {
  739. // if header is not NT sig, this is a ROM image
  740. rom = (PIMAGE_ROM_OPTIONAL_HEADER)&nh32.OptionalHeader;
  741. fh = &nh32.FileHeader;
  742. shva = dh.e_lfanew + sizeof(DWORD) +
  743. sizeof(IMAGE_FILE_HEADER) + fh->SizeOfOptionalHeader;
  744. }
  745. } else if (filetype == IMAGE_FILE_MACHINE_I386) {
  746. // This is an X86 ROM image
  747. status = ReadImageData(hp, base, 0, &nh32.FileHeader, sizeof(nh32.FileHeader)+sizeof(nh32.OptionalHeader));
  748. if (!status)
  749. return FALSE;
  750. nh32.Signature = 'ROM ';
  751. } else {
  752. // This may be a ROM image
  753. status = ReadImageData(hp, base, 0, &ROMImage, sizeof(ROMImage));
  754. if (!status) {
  755. g.LastSymLoadError = SYMLOAD_HEADERPAGEDOUT;
  756. return FALSE;
  757. }
  758. if ((ROMImage.FileHeader.Machine == IMAGE_FILE_MACHINE_I386) ||
  759. (ROMImage.FileHeader.Machine == IMAGE_FILE_MACHINE_ALPHA) ||
  760. (ROMImage.FileHeader.Machine == IMAGE_FILE_MACHINE_ALPHA64))
  761. {
  762. rom = (PIMAGE_ROM_OPTIONAL_HEADER)&ROMImage.OptionalHeader;
  763. fh = &ROMImage.FileHeader;
  764. shva = sizeof(IMAGE_FILE_HEADER) + fh->SizeOfOptionalHeader;
  765. } else {
  766. return FALSE;
  767. }
  768. }
  769. if (rom) {
  770. if (rom->Magic == IMAGE_ROM_OPTIONAL_HDR_MAGIC) {
  771. pIDD->fROM = TRUE;
  772. pIDD->iohMagic = rom->Magic;
  773. pIDD->ImageBaseFromImage = rom->BaseOfCode;
  774. pIDD->SizeOfImage = rom->SizeOfCode;
  775. pIDD->CheckSum = 0;
  776. } else {
  777. return FALSE;
  778. }
  779. } else {
  780. // otherwise, get info from appropriate header type for 32 or 64 bit
  781. if (IsImageMachineType64(nh32.FileHeader.Machine)) {
  782. // Reread the header as a 64bit header.
  783. status = ReadImageData(hp, base, dh.e_lfanew, &nh64, sizeof(nh64));
  784. if (!status) {
  785. g.LastSymLoadError = SYMLOAD_HEADERPAGEDOUT;
  786. return FALSE;
  787. }
  788. fh = &nh64.FileHeader;
  789. datadir = nh64.OptionalHeader.DataDirectory;
  790. shva = dh.e_lfanew + sizeof(nh64);
  791. pIDD->iohMagic = nh64.OptionalHeader.Magic;
  792. pIDD->fPE64 = TRUE; // seems to be unused
  793. if (datasrc == dsImage || datasrc == dsInProc) {
  794. pIDD->ImageBaseFromImage = nh64.OptionalHeader.ImageBase;
  795. pIDD->ImageAlign = nh64.OptionalHeader.SectionAlignment;
  796. pIDD->CheckSum = nh64.OptionalHeader.CheckSum;
  797. }
  798. pIDD->SizeOfImage = nh64.OptionalHeader.SizeOfImage;
  799. }
  800. else {
  801. fh = &nh32.FileHeader;
  802. datadir = nh32.OptionalHeader.DataDirectory;
  803. pIDD->iohMagic = nh32.OptionalHeader.Magic;
  804. if (nh32.Signature == 'ROM ') {
  805. shva = sizeof(nh32.FileHeader)+sizeof(nh32.OptionalHeader);
  806. } else {
  807. shva = dh.e_lfanew + sizeof(nh32);
  808. }
  809. if (datasrc == dsImage || datasrc == dsInProc) {
  810. pIDD->ImageBaseFromImage = nh32.OptionalHeader.ImageBase;
  811. pIDD->ImageAlign = nh32.OptionalHeader.SectionAlignment;
  812. pIDD->CheckSum = nh32.OptionalHeader.CheckSum;
  813. }
  814. pIDD->SizeOfImage = nh32.OptionalHeader.SizeOfImage;
  815. }
  816. }
  817. mdSet(pIDD->md, mdHeader, datasrc, datasrc);
  818. // read the section headers
  819. nSections = fh->NumberOfSections;
  820. psh = (PIMAGE_SECTION_HEADER) MemAlloc(nSections * sizeof(IMAGE_SECTION_HEADER));
  821. if (!psh)
  822. goto debugdirs;
  823. status = ReadImageData(hp, base, shva, psh, nSections * sizeof(IMAGE_SECTION_HEADER));
  824. if (!status)
  825. goto debugdirs;
  826. // store off info to return struct
  827. pIDD->pCurrentSections = psh;
  828. pIDD->cCurrentSections = nSections;
  829. pIDD->pImageSections = psh;
  830. pIDD->cImageSections = nSections;
  831. pIDD->Machine = fh->Machine;
  832. pIDD->TimeDateStamp = fh->TimeDateStamp;
  833. pIDD->Characteristics = fh->Characteristics;
  834. mdSet(pIDD->md, mdSecHdrs, datasrc, datasrc);
  835. // get information from the sections
  836. for (i = 0; i < nSections; i++, psh++) {
  837. DWORD offset;
  838. if (pIDD->fROM &&
  839. ((fh->Characteristics & IMAGE_FILE_DEBUG_STRIPPED) == 0) &&
  840. (!strcmp((LPSTR)psh->Name, ".rdata")))
  841. {
  842. nDebugDirs = 1;
  843. ddva = psh->VirtualAddress;
  844. break;
  845. }
  846. if (offset = SectionContains(hp, psh, &datadir[IMAGE_DIRECTORY_ENTRY_EXPORT]))
  847. {
  848. pIDD->dsExports = datasrc;
  849. pIDD->cExports = datadir[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
  850. pIDD->oExports = offset;
  851. ReadImageData(hp, base, offset, &pIDD->expdir, sizeof(pIDD->expdir));
  852. }
  853. if (offset = SectionContains(hp, psh, &datadir[IMAGE_DIRECTORY_ENTRY_DEBUG]))
  854. {
  855. ddva = offset;
  856. nDebugDirs = datadir[IMAGE_DIRECTORY_ENTRY_DEBUG].Size / sizeof(IMAGE_DEBUG_DIRECTORY);
  857. }
  858. }
  859. goto debugdirs;
  860. dbg:
  861. // grab the dbg header
  862. status = ReadImageData(hp, base, 0, &sdh, sizeof(sdh));
  863. if (!status)
  864. return FALSE;
  865. // Only support .dbg files for X86 and Alpha (32 bit).
  866. if ((sdh.Machine != IMAGE_FILE_MACHINE_I386)
  867. && (sdh.Machine != IMAGE_FILE_MACHINE_ALPHA))
  868. {
  869. UnmapViewOfFile(pIDD->DbgFileMap);
  870. pIDD->DbgFileMap = 0;
  871. return FALSE;
  872. }
  873. pIDD->ImageAlign = sdh.SectionAlignment;
  874. pIDD->CheckSum = sdh.CheckSum;
  875. pIDD->Machine = sdh.Machine;
  876. pIDD->TimeDateStamp = sdh.TimeDateStamp;
  877. pIDD->Characteristics = sdh.Characteristics;
  878. if (!pIDD->ImageBaseFromImage) {
  879. pIDD->ImageBaseFromImage = sdh.ImageBase;
  880. }
  881. if (!pIDD->SizeOfImage) {
  882. pIDD->SizeOfImage = sdh.SizeOfImage;
  883. }
  884. nSections = sdh.NumberOfSections;
  885. psh = (PIMAGE_SECTION_HEADER) MemAlloc(nSections * sizeof(IMAGE_SECTION_HEADER));
  886. if (!psh)
  887. goto debugdirs;
  888. status = ReadImageData(hp,
  889. base,
  890. sizeof(IMAGE_SEPARATE_DEBUG_HEADER),
  891. psh,
  892. nSections * sizeof(IMAGE_SECTION_HEADER));
  893. if (!status)
  894. goto debugdirs;
  895. pIDD->pCurrentSections = psh;
  896. pIDD->cCurrentSections = nSections;
  897. pIDD->pDbgSections = psh;
  898. pIDD->cDbgSections = nSections;
  899. // pIDD->ExportedNamesSize = sdh.ExportedNamesSize;
  900. if (sdh.DebugDirectorySize) {
  901. nDebugDirs = (int)(sdh.DebugDirectorySize / sizeof(IMAGE_DEBUG_DIRECTORY));
  902. ddva = sizeof(IMAGE_SEPARATE_DEBUG_HEADER)
  903. + (sdh.NumberOfSections * sizeof(IMAGE_SECTION_HEADER))
  904. + sdh.ExportedNamesSize;
  905. }
  906. debugdirs:
  907. rc = TRUE;
  908. // copy the virtual addr of the debug directories over for MapDebugInformation
  909. if (datasrc == dsImage) {
  910. pIDD->ddva = ddva;
  911. pIDD->cdd = nDebugDirs;
  912. }
  913. // read the debug directories
  914. while (nDebugDirs) {
  915. status = ReadImageData(hp, base, (ULONG_PTR)ddva, &dd, sizeof(dd));
  916. if (!status)
  917. break;
  918. if (!dd.SizeOfData)
  919. goto nextdebugdir;
  920. // indicate that we found the debug directory
  921. mdSet(pIDD->md, dd.Type, datasrc, dsNone);
  922. // these debug directories are processed both in-proc and from file
  923. switch (dd.Type)
  924. {
  925. case IMAGE_DEBUG_TYPE_CODEVIEW:
  926. // get info on pdb file
  927. if (hp && dd.AddressOfRawData) {
  928. // in-proc image
  929. if (!(pCV = (PCHAR)MemAlloc(dd.SizeOfData)))
  930. break;
  931. status = ReadImageData(hp, base, dd.AddressOfRawData, pCV, dd.SizeOfData);
  932. if (!status) {
  933. MemFree(pCV);
  934. break;
  935. }
  936. } else {
  937. // file-base image
  938. if (dd.PointerToRawData >= fsize)
  939. break;
  940. pCV = (PCHAR)base + dd.PointerToRawData;
  941. pIDD->fCvMapped = TRUE;
  942. }
  943. pIDD->pMappedCv = (PCHAR)pCV;
  944. pIDD->cMappedCv = dd.SizeOfData;
  945. pIDD->dsCV = datasrc;
  946. RetrievePdbInfo(pIDD, filepath);
  947. mdSet(pIDD->md, dd.Type, dsNone, datasrc);
  948. break;
  949. case IMAGE_DEBUG_TYPE_MISC:
  950. // on stripped files, find the dbg file
  951. // on dbg file, find the original file name
  952. if (dd.PointerToRawData < fsize) {
  953. md = (PIMAGE_DEBUG_MISC)((PCHAR)base + dd.PointerToRawData);
  954. if (md->DataType != IMAGE_DEBUG_MISC_EXENAME)
  955. break;
  956. if (datasrc == dsDbg) {
  957. if (!*pIDD->OriginalImageFileName)
  958. strncpy(pIDD->OriginalImageFileName, (LPSTR)md->Data, sizeof(pIDD->OriginalImageFileName));
  959. break;
  960. }
  961. if (fh->Characteristics & IMAGE_FILE_DEBUG_STRIPPED) {
  962. strncpy(pIDD->OriginalDbgFileName, (LPSTR)md->Data, sizeof(pIDD->OriginalDbgFileName));
  963. } else {
  964. strncpy(pIDD->OriginalImageFileName, (LPSTR)md->Data, sizeof(pIDD->OriginalImageFileName));
  965. }
  966. }
  967. mdSet(pIDD->md, dd.Type, dsNone, datasrc);
  968. break;
  969. case IMAGE_DEBUG_TYPE_COFF:
  970. if (dd.PointerToRawData < fsize) {
  971. // pIDD->fNeedImage = TRUE;
  972. pIDD->pMappedCoff = (PCHAR)base + dd.PointerToRawData;
  973. pIDD->cMappedCoff = dd.SizeOfData;
  974. pIDD->fCoffMapped = TRUE;
  975. pIDD->dsCoff = datasrc;
  976. mdSet(pIDD->md, dd.Type, dsNone, datasrc);
  977. } else {
  978. pIDD->fNeedImage = TRUE;
  979. }
  980. break;
  981. #ifdef INPROC_SUPPORT
  982. case IMAGE_DEBUG_TYPE_FPO:
  983. if (dd.PointerToRawData < fsize) {
  984. pIDD->pFpo = (PCHAR)base + dd.PointerToRawData;
  985. pIDD->cFpo = dd.SizeOfData / SIZEOF_RFPO_DATA;
  986. pIDD->fFpoMapped = TRUE;
  987. pIDD->dsFPO = datasrc;
  988. mdSet(pIDD->md, dd.Type, dsNone, datasrc);
  989. } else {
  990. dprint("found fpo in-process\n");
  991. }
  992. break;
  993. case IMAGE_DEBUG_TYPE_OMAP_TO_SRC:
  994. if (dd.PointerToRawData < fsize) {
  995. pIDD->pOmapTo = (PCHAR)base + dd.PointerToRawData;
  996. pIDD->cOmapTo = dd.SizeOfData / sizeof(OMAP);
  997. pIDD->fOmapToMapped = TRUE;
  998. pIDD->dsOmapTo = datasrc;
  999. mdSet(pIDD->md, dd.Type, dsNone, datasrc);
  1000. } else {
  1001. dprint("found found omap-to in-process\n");
  1002. }
  1003. break;
  1004. case IMAGE_DEBUG_TYPE_OMAP_FROM_SRC:
  1005. if (dd.PointerToRawData < fsize) {
  1006. pIDD->pOmapFrom = (PCHAR)base + dd.PointerToRawData;
  1007. pIDD->cOmapFrom = dd.SizeOfData / sizeof(OMAP);
  1008. pIDD->fOmapFromMapped = TRUE;
  1009. pIDD->dsOmapFrom = datasrc;
  1010. mdSet(pIDD->md, dd.Type, dsNone, datasrc);
  1011. } else {
  1012. dprint("found omap-from in-process\n");
  1013. }
  1014. break;
  1015. #endif
  1016. }
  1017. // these debug directories are only processed for disk-based images
  1018. if (dd.PointerToRawData < fsize) {
  1019. switch (dd.Type)
  1020. {
  1021. case IMAGE_DEBUG_TYPE_FPO:
  1022. pIDD->pFpo = (PCHAR)base + dd.PointerToRawData;
  1023. pIDD->cFpo = dd.SizeOfData / SIZEOF_RFPO_DATA;
  1024. pIDD->fFpoMapped = TRUE;
  1025. pIDD->dsFPO = datasrc;
  1026. mdSet(pIDD->md, dd.Type, dsNone, datasrc);
  1027. break;
  1028. case IMAGE_DEBUG_TYPE_OMAP_TO_SRC:
  1029. pIDD->pOmapTo = (POMAP)((PCHAR)base + dd.PointerToRawData);
  1030. pIDD->cOmapTo = dd.SizeOfData / sizeof(OMAP);
  1031. pIDD->fOmapToMapped = TRUE;
  1032. pIDD->dsOmapTo = datasrc;
  1033. mdSet(pIDD->md, dd.Type, dsNone, datasrc);
  1034. break;
  1035. case IMAGE_DEBUG_TYPE_OMAP_FROM_SRC:
  1036. pIDD->pOmapFrom = (POMAP)((PCHAR)base + dd.PointerToRawData);
  1037. pIDD->cOmapFrom = dd.SizeOfData / sizeof(OMAP);
  1038. pIDD->fOmapFromMapped = TRUE;
  1039. pIDD->dsOmapFrom = datasrc;
  1040. mdSet(pIDD->md, dd.Type, dsNone, datasrc);
  1041. break;
  1042. case IMAGE_DEBUG_TYPE_EXCEPTION:
  1043. pIDD->dsExceptions = datasrc;
  1044. mdSet(pIDD->md, dd.Type, dsNone, datasrc);
  1045. break;
  1046. }
  1047. }
  1048. nextdebugdir:
  1049. ddva += sizeof(IMAGE_DEBUG_DIRECTORY);
  1050. nDebugDirs--;
  1051. }
  1052. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1053. // We might have gotten enough information
  1054. // to be okay. So don't indicate error.
  1055. }
  1056. return rc;
  1057. }
  1058. BOOL
  1059. FigureOutImageName(
  1060. PIMGHLP_DEBUG_DATA pIDD
  1061. )
  1062. /*
  1063. We got here because we didn't get the image name passed in from the original call
  1064. to GetDebugData AND we were unable to find the MISC data with the name
  1065. Have to figure it out.
  1066. A couple of options here. First, if the DLL bit is set, try looking for Export
  1067. table. If found, IMAGE_EXPORT_DIRECTORY->Name is a rva pointer to the dll name.
  1068. If it's not found, see if there's a OriginalDbgFileName.
  1069. If so see if the format is <ext>\<filename>.dbg.
  1070. If there's more than one backslash or no backslash, punt and label it with a .dll
  1071. extension.
  1072. Otherwise a splitpath will do the trick.
  1073. If there's no DbgFilePath, see if there's a PDB name. The same rules apply there as
  1074. for .dbg files. Worst case, you s/b able to get the base name and just stick on a
  1075. If this all fails, label it as mod<base address>.
  1076. If the DLL bit is not set, assume an exe and tag it with that extension. The base name
  1077. can be retrieved from DbgFilePath, PdbFilePath, or use just APP.
  1078. */
  1079. {
  1080. // Quick hack to get Dr. Watson going.
  1081. CHAR szName[_MAX_FNAME];
  1082. CHAR szExt[_MAX_FNAME];
  1083. if (pIDD->OriginalDbgFileName[0]) {
  1084. _splitpath(pIDD->OriginalDbgFileName, NULL, NULL, szName, NULL);
  1085. strcpy(pIDD->OriginalImageFileName, szName);
  1086. strcat(pIDD->OriginalImageFileName, pIDD->Characteristics & IMAGE_FILE_DLL ? ".dll" : ".exe");
  1087. } else if (pIDD->ImageName) {
  1088. _splitpath(pIDD->ImageName, NULL, NULL, szName, szExt);
  1089. strcpy(pIDD->OriginalImageFileName, szName);
  1090. if (*szExt) {
  1091. strcat(pIDD->OriginalImageFileName, szExt);
  1092. }
  1093. } else if (pIDD->PdbFileName[0]) {
  1094. _splitpath(pIDD->PdbFileName, NULL, NULL, szName, NULL);
  1095. strcpy(pIDD->OriginalImageFileName, szName);
  1096. strcat(pIDD->OriginalImageFileName, pIDD->Characteristics & IMAGE_FILE_DLL ? ".dll" : ".exe");
  1097. } else {
  1098. sprintf(pIDD->OriginalImageFileName, "MOD%p", pIDD->InProcImageBase);
  1099. }
  1100. return TRUE;
  1101. }
  1102. BOOL
  1103. FindExecutableImageExCallback(
  1104. HANDLE FileHandle,
  1105. PSTR FileName,
  1106. PVOID CallerData
  1107. )
  1108. {
  1109. PIMGHLP_DEBUG_DATA pIDD;
  1110. PIMAGE_FILE_HEADER FileHeader = NULL;
  1111. PVOID ImageMap = NULL;
  1112. BOOL rc;
  1113. if (!CallerData)
  1114. return TRUE;
  1115. pIDD = (PIMGHLP_DEBUG_DATA)CallerData;
  1116. if (!pIDD->TimeDateStamp)
  1117. return TRUE;
  1118. // Crack the image and let's see what we're working with
  1119. ImageMap = MapItRO(FileHandle);
  1120. if (!ImageMap)
  1121. return TRUE;
  1122. // Check the first word. We're either looking at a normal PE32/PE64 image, or it's
  1123. // a ROM image (no DOS stub) or it's a random file.
  1124. switch (*(PUSHORT)ImageMap) {
  1125. case IMAGE_FILE_MACHINE_I386:
  1126. // Must be an X86 ROM image (ie: ntldr)
  1127. FileHeader = &((PIMAGE_ROM_HEADERS)ImageMap)->FileHeader;
  1128. // Make sure
  1129. if (!(FileHeader->SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER32) &&
  1130. pIDD->iohMagic == IMAGE_NT_OPTIONAL_HDR32_MAGIC))
  1131. {
  1132. FileHeader = NULL;
  1133. }
  1134. break;
  1135. case IMAGE_FILE_MACHINE_ALPHA:
  1136. case IMAGE_FILE_MACHINE_ALPHA64:
  1137. case IMAGE_FILE_MACHINE_IA64:
  1138. case IMAGE_FILE_MACHINE_AMD64:
  1139. // Should be an Alpha/IA64 ROM image (ie: osloader.exe)
  1140. FileHeader = &((PIMAGE_ROM_HEADERS)ImageMap)->FileHeader;
  1141. // Make sure
  1142. if (!(FileHeader->SizeOfOptionalHeader == sizeof(IMAGE_ROM_OPTIONAL_HEADER) &&
  1143. pIDD->iohMagic == IMAGE_ROM_OPTIONAL_HDR_MAGIC))
  1144. {
  1145. FileHeader = NULL;
  1146. }
  1147. break;
  1148. case IMAGE_DOS_SIGNATURE:
  1149. {
  1150. PIMAGE_NT_HEADERS NtHeaders = ImageNtHeader(ImageMap);
  1151. if (NtHeaders) {
  1152. FileHeader = &NtHeaders->FileHeader;
  1153. }
  1154. }
  1155. break;
  1156. default:
  1157. break;
  1158. }
  1159. // default return is a match
  1160. rc = TRUE;
  1161. // compare timestamps
  1162. if (FileHeader && FileHeader->TimeDateStamp != pIDD->TimeDateStamp)
  1163. rc = FALSE;
  1164. pIDD->ImageSrc = srcSearchPath;
  1165. // cleanup
  1166. if (ImageMap)
  1167. UnmapViewOfFile(ImageMap);
  1168. return rc;
  1169. }
  1170. BOOL
  1171. SymbolInfoFound(
  1172. PIMGHLP_DEBUG_DATA pIDD
  1173. )
  1174. {
  1175. OMFSignature *omfSig;
  1176. if (pIDD->dia)
  1177. return TRUE;
  1178. // look for embedded codeview
  1179. if (pIDD->pMappedCv) {
  1180. omfSig = (OMFSignature*) pIDD->pMappedCv;
  1181. if (*(DWORD *)(omfSig->Signature) == '80BN')
  1182. return TRUE;
  1183. if (*(DWORD *)(omfSig->Signature) == '90BN')
  1184. return TRUE;
  1185. if (*(DWORD *)(omfSig->Signature) == '11BN')
  1186. return TRUE;
  1187. }
  1188. // look for coff symbols
  1189. if (pIDD->pMappedCoff)
  1190. return TRUE;
  1191. // must be no debug info
  1192. return FALSE;
  1193. }
  1194. BOOL FileNameIsPdb(
  1195. PIMGHLP_DEBUG_DATA pIDD,
  1196. LPSTR FileName
  1197. )
  1198. {
  1199. CHAR drive[_MAX_DRIVE];
  1200. CHAR path[_MAX_DIR];
  1201. char ext[20];
  1202. _splitpath(FileName, drive, path, NULL, ext);
  1203. if (_strcmpi(ext, ".pdb"))
  1204. return FALSE;
  1205. strcpy(pIDD->PdbFileName, FileName);
  1206. _makepath(pIDD->PdbReferencePath, drive, path, NULL, NULL);
  1207. if (strlen(path) > 1) {
  1208. // Chop off trailing backslash.
  1209. pIDD->PdbReferencePath[strlen(pIDD->PdbReferencePath)-1] = '\0';
  1210. } else {
  1211. // No path. Put on at least a dot "."
  1212. strcpy(pIDD->PdbReferencePath, ".");
  1213. }
  1214. return TRUE;
  1215. }
  1216. PIMGHLP_DEBUG_DATA
  1217. GetDebugData(
  1218. HANDLE hProcess,
  1219. HANDLE FileHandle,
  1220. LPSTR FileName,
  1221. LPSTR SymbolPath,
  1222. ULONG64 ImageBase,
  1223. PMODLOAD_DATA mld,
  1224. ULONG dwFlags
  1225. )
  1226. /*
  1227. Given:
  1228. ImageFileHandle - Map the thing. The only time FileHandle s/b non-null
  1229. is if we're given an image handle. If this is not
  1230. true, ignore the handle.
  1231. !ImageFileHandle - Use the filename and search for first the image name,
  1232. then the .dbg file, and finally a .pdb file.
  1233. dwFlags: NO_PE64_IMAGES - Return failure if only image is PE64.
  1234. Used to implement MapDebugInformation()
  1235. */
  1236. {
  1237. PIMGHLP_DEBUG_DATA pIDD;
  1238. // if (traceSubName(FileName)) // for setting debug breakpoints from DBGHELP_TOKEN
  1239. // dprint("debug(%s)\n", FileName);
  1240. // No File handle and no file name. Bail
  1241. if (!FileHandle && (!FileName || !*FileName)) {
  1242. return NULL;
  1243. }
  1244. SetLastError(NO_ERROR);
  1245. pIDD = InitDebugData();
  1246. if (!pIDD)
  1247. return NULL;
  1248. pIDD->flags = dwFlags;
  1249. __try {
  1250. // store off parameters
  1251. pIDD->InProcImageBase = ImageBase;
  1252. pIDD->hProcess = hProcess;
  1253. pIDD->mld = mld;
  1254. if (FileName && !FileNameIsPdb(pIDD, FileName))
  1255. lstrcpy(pIDD->ImageName, FileName);
  1256. if (SymbolPath) {
  1257. pIDD->SymbolPath = (PCHAR)MemAlloc(strlen(SymbolPath) + 1);
  1258. if (pIDD->SymbolPath) {
  1259. strcpy(pIDD->SymbolPath, SymbolPath);
  1260. }
  1261. }
  1262. // if we have a base pointer into process memory. See what we can get here.
  1263. if (pIDD->InProcImageBase) {
  1264. pIDD->fInProcHeader = ProcessInProcDebugInfo(pIDD);
  1265. if (pIDD->fInProcHeader)
  1266. pIDD->ImageSrc = srcMemory;
  1267. }
  1268. // find disk-based image
  1269. if (FileHandle) {
  1270. // if passed a handle, save it
  1271. if (!DuplicateHandle(
  1272. GetCurrentProcess(),
  1273. FileHandle,
  1274. GetCurrentProcess(),
  1275. &pIDD->ImageFileHandle,
  1276. GENERIC_READ,
  1277. FALSE,
  1278. DUPLICATE_SAME_ACCESS
  1279. ))
  1280. {
  1281. return NULL;
  1282. }
  1283. pIDD->ImageSrc = srcHandle;
  1284. if (FileName) {
  1285. strcpy(pIDD->ImageFilePath, FileName);
  1286. }
  1287. } else if (!pIDD->fInProcHeader)
  1288. {
  1289. // otherwise use the file name to open the disk image
  1290. // only if we didn't have access to in-proc headers
  1291. pIDD->ImageFileHandle = FindExecutableImageEx(pIDD->ImageName,
  1292. SymbolPath,
  1293. pIDD->ImageFilePath,
  1294. FindExecutableImageExCallback,
  1295. pIDD);
  1296. }
  1297. // if we have a file handle. See what we can get here.
  1298. if (pIDD->ImageFileHandle) {
  1299. if (!pIDD->DbgFileHandle && !*pIDD->PdbFileName) {
  1300. ProcessImageDebugInfo(pIDD);
  1301. }
  1302. }
  1303. // get info from the caller's data struct
  1304. ProcessCallerDataDebugInfo(pIDD);
  1305. // search for pdb, if indicated or if we have found no image info, so far
  1306. pIDD->DbgFileHandle = 0;
  1307. if (!pIDD->Characteristics || (pIDD->Characteristics & IMAGE_FILE_DEBUG_STRIPPED)) {
  1308. if (*pIDD->OriginalDbgFileName) {
  1309. pIDD->DbgFileHandle = fnFindDebugInfoFileEx(
  1310. pIDD->OriginalDbgFileName,
  1311. pIDD->SymbolPath,
  1312. pIDD->DbgFilePath,
  1313. FindDebugInfoFileExCallback,
  1314. pIDD,
  1315. fdifRECURSIVE);
  1316. }
  1317. if (!pIDD->DbgFileHandle) {
  1318. pIDD->DbgFileHandle = fnFindDebugInfoFileEx(
  1319. pIDD->ImageName,
  1320. pIDD->SymbolPath,
  1321. pIDD->DbgFilePath,
  1322. FindDebugInfoFileExCallback,
  1323. pIDD,
  1324. fdifRECURSIVE);
  1325. }
  1326. if (!pIDD->DbgFileHandle)
  1327. g.LastSymLoadError = SYMLOAD_DBGNOTFOUND;
  1328. }
  1329. // if we have a .dbg file. See what we can get from it.
  1330. if (pIDD->DbgFileHandle) {
  1331. ProcessDbgDebugInfo(pIDD);
  1332. }
  1333. // make sure we can process omaps
  1334. if (!pIDD->ImageAlign)
  1335. pIDD->fNeedImage = TRUE;
  1336. // check one more time to see if information we have acquired
  1337. // indicates we need the image from disk.
  1338. if (FileName && *FileName && pIDD->fNeedImage) {
  1339. pIDD->ImageFileHandle = FindExecutableImageEx(FileName,
  1340. SymbolPath,
  1341. pIDD->ImageFilePath,
  1342. FindExecutableImageExCallback,
  1343. pIDD);
  1344. if (pIDD->ImageFileHandle) {
  1345. ProcessImageDebugInfo(pIDD);
  1346. }
  1347. }
  1348. // if there's a pdb. Pull what we can from there.
  1349. if (*pIDD->PdbFileName) {
  1350. diaOpenPdb(pIDD);
  1351. // otherwise, if old codeview, pull from there
  1352. } else if (pIDD->pMappedCv) {
  1353. ProcessOldStyleCodeView(pIDD);
  1354. // otherwise if we couldn't read from the image info, look for PDB anyway
  1355. } else if (!pIDD->ImageFileHandle && !pIDD->DbgFileHandle) {
  1356. if (FakePdbName(pIDD)) {
  1357. diaOpenPdb(pIDD);
  1358. }
  1359. }
  1360. // if all else fails, one more try for a dbg
  1361. if (!(pIDD->Characteristics & IMAGE_FILE_DEBUG_STRIPPED)
  1362. && !pIDD->DbgFileHandle
  1363. && !SymbolInfoFound(pIDD)
  1364. )
  1365. {
  1366. pIDD->DbgFileHandle = fnFindDebugInfoFileEx(
  1367. (*pIDD->OriginalDbgFileName) ? pIDD->OriginalDbgFileName : pIDD->ImageName,
  1368. pIDD->SymbolPath,
  1369. pIDD->DbgFilePath,
  1370. FindDebugInfoFileExCallback,
  1371. pIDD,
  1372. fdifRECURSIVE);
  1373. // if we have a .dbg file. See what we can get from it.
  1374. if (pIDD->DbgFileHandle) {
  1375. ProcessDbgDebugInfo(pIDD);
  1376. }
  1377. }
  1378. if (!pIDD->OriginalImageFileName[0]) {
  1379. FigureOutImageName(pIDD);
  1380. }
  1381. GetUnfoundData(pIDD);
  1382. // mdDump(pIDD->md, FALSE);
  1383. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1384. if (pIDD) {
  1385. ReleaseDebugData(pIDD, IMGHLP_FREE_ALL);
  1386. pIDD = NULL;
  1387. }
  1388. }
  1389. return pIDD;
  1390. }
  1391. PIMGHLP_DEBUG_DATA
  1392. InitDebugData(
  1393. VOID
  1394. )
  1395. {
  1396. PIMGHLP_DEBUG_DATA pIDD;
  1397. pIDD = (PIMGHLP_DEBUG_DATA)MemAlloc(sizeof(IMGHLP_DEBUG_DATA));
  1398. if (!pIDD) {
  1399. SetLastError(ERROR_OUTOFMEMORY);
  1400. g.LastSymLoadError = SYMLOAD_OUTOFMEMORY;
  1401. return NULL;
  1402. }
  1403. ZeroMemory(pIDD, sizeof(IMGHLP_DEBUG_DATA));
  1404. pIDD->md = (PMODULE_DATA)MemAlloc(sizeof(gmd));
  1405. if (!pIDD->md) {
  1406. SetLastError(ERROR_OUTOFMEMORY);
  1407. g.LastSymLoadError = SYMLOAD_OUTOFMEMORY;
  1408. MemFree(pIDD);
  1409. return NULL;
  1410. }
  1411. memcpy(pIDD->md, gmd, sizeof(gmd));
  1412. return pIDD;
  1413. }
  1414. void
  1415. ReleaseDebugData(
  1416. PIMGHLP_DEBUG_DATA pIDD,
  1417. DWORD dwFlags
  1418. )
  1419. {
  1420. if (!pIDD)
  1421. return;
  1422. if (pIDD->ImageMap) {
  1423. UnmapViewOfFile(pIDD->ImageMap);
  1424. }
  1425. if (pIDD->ImageFileHandle) {
  1426. CloseHandle(pIDD->ImageFileHandle);
  1427. }
  1428. if (pIDD->DbgFileMap) {
  1429. UnmapViewOfFile(pIDD->DbgFileMap);
  1430. }
  1431. if (pIDD->DbgFileHandle) {
  1432. CloseHandle(pIDD->DbgFileHandle);
  1433. }
  1434. if ((dwFlags & IMGHLP_FREE_FPO) &&
  1435. pIDD->pFpo &&
  1436. !pIDD->fFpoMapped
  1437. )
  1438. {
  1439. MemFree(pIDD->pFpo);
  1440. }
  1441. if ((dwFlags & IMGHLP_FREE_PDATA) &&
  1442. pIDD->pPData &&
  1443. !pIDD->fPDataMapped
  1444. )
  1445. {
  1446. MemFree(pIDD->pPData);
  1447. }
  1448. if ((dwFlags & IMGHLP_FREE_XDATA) &&
  1449. pIDD->pXData &&
  1450. !pIDD->fXDataMapped
  1451. )
  1452. {
  1453. MemFree(pIDD->pXData);
  1454. }
  1455. if ((dwFlags & IMGHLP_FREE_PDATA) &&
  1456. pIDD->pMappedCoff &&
  1457. !pIDD->fCoffMapped
  1458. )
  1459. {
  1460. MemFree(pIDD->pMappedCoff);
  1461. }
  1462. if ((dwFlags & IMGHLP_FREE_PDATA) &&
  1463. pIDD->pMappedCv &&
  1464. !pIDD->fCvMapped
  1465. )
  1466. {
  1467. MemFree(pIDD->pMappedCv);
  1468. }
  1469. if ((dwFlags & IMGHLP_FREE_OMAPT) &&
  1470. pIDD->pOmapTo &&
  1471. !pIDD->fOmapToMapped
  1472. )
  1473. {
  1474. MemFree(pIDD->pOmapTo);
  1475. }
  1476. if ((dwFlags & IMGHLP_FREE_OMAPF) &&
  1477. pIDD->pOmapFrom &&
  1478. !pIDD->fOmapFromMapped
  1479. )
  1480. {
  1481. MemFree(pIDD->pOmapFrom);
  1482. }
  1483. if ((dwFlags & IMGHLP_FREE_OSECT) &&
  1484. pIDD->pOriginalSections
  1485. )
  1486. {
  1487. MemFree(pIDD->pOriginalSections);
  1488. }
  1489. if ((dwFlags & IMGHLP_FREE_CSECT) &&
  1490. pIDD->pCurrentSections &&
  1491. !pIDD->fCurrentSectionsMapped
  1492. )
  1493. {
  1494. MemFree(pIDD->pCurrentSections);
  1495. }
  1496. if (pIDD->SymbolPath) {
  1497. MemFree(pIDD->SymbolPath);
  1498. }
  1499. MemFree(pIDD->md);
  1500. MemFree(pIDD);
  1501. return;
  1502. }
  1503. #ifdef MAP_DEBUG_TEST
  1504. #if 0
  1505. void
  1506. __cdecl
  1507. main(
  1508. int argc,
  1509. char *argv[]
  1510. )
  1511. {
  1512. CHAR szSymPath[4096];
  1513. PIMGHLP_DEBUG_DATA pDebugInfo;
  1514. strcpy(szSymPath, "h:\\nt\\private\\sdktools\\imagehlp\\test\\test1");
  1515. pDebugInfo = GetDebugData(NULL, NULL, "h:\\nt\\private\\sdktools\\imagehlp\\test\\test1\\ntoskrnl.exe", szSymPath, 0x1000000, NULL, 0);
  1516. ReleaseDebugData(pDebugInfo, IMGHLP_FREE_ALL);
  1517. strcpy(szSymPath, "h:\\nt\\private\\sdktools\\imagehlp\\test\\test2");
  1518. pDebugInfo = GetDebugData(NULL, NULL, "h:\\nt\\private\\sdktools\\imagehlp\\test\\test2\\ntoskrnl.exe", szSymPath, 0x1000000, NULL, 0);
  1519. ReleaseDebugData(pDebugInfo, IMGHLP_FREE_ALL);
  1520. strcpy(szSymPath, "h:\\nt\\private\\sdktools\\imagehlp\\test\\test3");
  1521. pDebugInfo = GetDebugData(NULL, NULL, "h:\\nt\\private\\sdktools\\imagehlp\\test\\test3\\ntoskrnl.exe", szSymPath, 0x1000000, NULL, 0);
  1522. ReleaseDebugData(pDebugInfo, IMGHLP_FREE_ALL);
  1523. strcpy(szSymPath, "h:\\nt\\private\\sdktools\\imagehlp\\test\\test4");
  1524. pDebugInfo = GetDebugData(NULL, NULL, "h:\\nt\\private\\sdktools\\imagehlp\\test\\test4\\ntoskrnl.exe", szSymPath, 0x1000000, NULL, 0);
  1525. ReleaseDebugData(pDebugInfo, IMGHLP_FREE_ALL);
  1526. strcpy(szSymPath, "h:\\nt\\private\\sdktools\\imagehlp\\test\\test5");
  1527. pDebugInfo = GetDebugData(NULL, NULL, "h:\\nt\\private\\sdktools\\imagehlp\\test\\test5\\ntdll.dll", szSymPath, 0x1000000, NULL, 0);
  1528. ReleaseDebugData(pDebugInfo, IMGHLP_FREE_ALL);
  1529. strcpy(szSymPath, "h:\\nt\\private\\sdktools\\imagehlp\\test\\test6");
  1530. pDebugInfo = GetDebugData(NULL, NULL, "h:\\nt\\private\\sdktools\\imagehlp\\test\\test6\\ntdll.dll", szSymPath, 0x1000000, NULL, 0);
  1531. ReleaseDebugData(pDebugInfo, IMGHLP_FREE_ALL);
  1532. strcpy(szSymPath, "h:\\nt\\private\\sdktools\\imagehlp\\test\\test7");
  1533. pDebugInfo = GetDebugData(NULL, NULL, "h:\\nt\\private\\sdktools\\imagehlp\\test\\test7\\osloader.exe", szSymPath, 0x1000000, NULL, 0);
  1534. ReleaseDebugData(pDebugInfo, IMGHLP_FREE_ALL);
  1535. strcpy(szSymPath, "h:\\nt\\private\\sdktools\\imagehlp\\test\\test8");
  1536. pDebugInfo = GetDebugData(NULL, NULL, "h:\\nt\\private\\sdktools\\imagehlp\\test\\test8\\osloader.exe", szSymPath, 0x1000000, NULL, 0);
  1537. ReleaseDebugData(pDebugInfo, IMGHLP_FREE_ALL);
  1538. strcpy(szSymPath, "h:\\nt\\private\\sdktools\\imagehlp\\test\\test9");
  1539. pDebugInfo = GetDebugData(NULL, NULL, "h:\\nt\\private\\sdktools\\imagehlp\\test\\test9\\msvcrt.dll", szSymPath, 0x1000000, NULL, 0);
  1540. ReleaseDebugData(pDebugInfo, IMGHLP_FREE_ALL);
  1541. strcpy(szSymPath, "h:\\nt\\private\\sdktools\\imagehlp\\test\\test10");
  1542. pDebugInfo = GetDebugData(NULL, NULL, "h:\\nt\\private\\sdktools\\imagehlp\\test\\test10\\msvcrt.dll", szSymPath, 0x1000000, NULL, 0);
  1543. ReleaseDebugData(pDebugInfo, IMGHLP_FREE_ALL);
  1544. }
  1545. #endif
  1546. #endif