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.

3042 lines
72 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. dia.c
  5. Abstract:
  6. These routines call VC's new DIA symbol handler.
  7. Author:
  8. Pat Styles (patst) 26-May-2000
  9. Environment:
  10. User Mode
  11. --*/
  12. #define DIA_LIBRARY 1
  13. #include "private.h"
  14. #include "symbols.h"
  15. #include "globals.h"
  16. #include "dia2.h"
  17. #include "diacreate_int.h"
  18. #include <atlbase.h>
  19. typedef struct {
  20. CComPtr<IDiaDataSource> source;
  21. CComPtr<IDiaSession> session;
  22. CComPtr<IDiaSymbol> scope;
  23. CComPtr<IDiaSourceFile> srcfile;
  24. CComPtr<IDiaEnumFrameData> framedata;
  25. #ifdef BBTFIX
  26. CComPtr<IDiaAddressMap> addrmap;
  27. #endif
  28. } DIA, *PDIA;
  29. extern HRESULT STDMETHODCALLTYPE DiaCoCreate(
  30. REFCLSID rclsid,
  31. REFIID riid,
  32. void **ppv);
  33. extern HRESULT STDMETHODCALLTYPE NoOleCoCreate(REFCLSID rclsid,
  34. REFIID riid,
  35. void **ppv);
  36. #define freeString LocalFree
  37. // used by diaLocatePdb
  38. enum {
  39. ipNone = 0,
  40. ipFirst,
  41. ipLast
  42. };
  43. BOOL
  44. diaInit(
  45. VOID
  46. )
  47. {
  48. return TRUE;
  49. }
  50. BOOL
  51. ValidGUID(
  52. GUID *guid
  53. )
  54. {
  55. int i;
  56. if (!guid)
  57. return FALSE;
  58. if (guid->Data1)
  59. return TRUE;
  60. if (guid->Data2)
  61. return TRUE;
  62. if (guid->Data3)
  63. return TRUE;
  64. for (i = 0; i < 8; i++) {
  65. if (guid->Data4[i])
  66. return TRUE;
  67. }
  68. return FALSE;
  69. }
  70. __inline
  71. HRESULT
  72. SetDiaError(
  73. HRESULT ccode,
  74. HRESULT ncode
  75. )
  76. {
  77. if (ncode == EC_OK)
  78. return ncode;
  79. if (ccode != EC_NOT_FOUND)
  80. return ccode;
  81. return ncode;
  82. }
  83. __inline
  84. BOOL
  85. ValidSig(
  86. DWORD sig,
  87. GUID *guid
  88. )
  89. {
  90. if (ValidGUID(guid))
  91. return TRUE;
  92. if (sig)
  93. return TRUE;
  94. return FALSE;
  95. }
  96. typedef struct _DIAERROR {
  97. HRESULT hr;
  98. char *text;
  99. } DIAERROR, *PDIAERROR;
  100. char *
  101. diaErrorText(
  102. HRESULT hr
  103. )
  104. {
  105. #define ERROR_MAX 24
  106. static const DIAERROR error[ERROR_MAX] =
  107. {
  108. {E_PDB_OK, "OK"},
  109. {E_PDB_USAGE, "invalid parameters"},
  110. {E_PDB_OUT_OF_MEMORY, "out of memory"},
  111. {E_PDB_FILE_SYSTEM, "disk error"},
  112. {E_PDB_NOT_FOUND, "file not found"},
  113. {E_PDB_INVALID_SIG, "unmatched pdb"},
  114. {E_PDB_INVALID_AGE, "unmatched pdb"},
  115. {E_PDB_PRECOMP_REQUIRED, "E_PDB_PRECOMP_REQUIRED"},
  116. {E_PDB_OUT_OF_TI, "E_PDB_OUT_OF_TI"},
  117. {E_PDB_NOT_IMPLEMENTED, "E_PDB_NOT_IMPLEMENTED"},
  118. {E_PDB_V1_PDB, "E_PDB_V1_PDB"},
  119. {E_PDB_FORMAT, "file system or network error reading pdb"},
  120. {E_PDB_LIMIT, "E_PDB_LIMIT"},
  121. {E_PDB_CORRUPT, "E_PDB_CORRUPT"},
  122. {E_PDB_TI16, "E_PDB_TI16"},
  123. {E_PDB_ACCESS_DENIED, "E_PDB_ACCESS_DENIED"},
  124. {E_PDB_ILLEGAL_TYPE_EDIT, "E_PDB_ILLEGAL_TYPE_EDIT"},
  125. {E_PDB_INVALID_EXECUTABLE, "invalid executable image"},
  126. {E_PDB_DBG_NOT_FOUND, "dbg file not found"},
  127. {E_PDB_NO_DEBUG_INFO, "pdb is stripped of cv info"},
  128. {E_PDB_INVALID_EXE_TIMESTAMP, "image has invalid timestamp"},
  129. {E_PDB_RESERVED, "E_PDB_RESERVED"},
  130. {E_PDB_DEBUG_INFO_NOT_IN_PDB, "pdb has no symbols"},
  131. {E_PDB_MAX, "pdb error 0x%x"}
  132. };
  133. static char sz[50];
  134. DWORD i;
  135. for (i = 0; i < ERROR_MAX; i++) {
  136. if (hr == error[i].hr)
  137. return error[i].text;
  138. }
  139. sprintf(sz, "dia error 0x%x", hr);
  140. return sz;
  141. }
  142. extern DWORD DIA_VERSION;
  143. DWORD
  144. diaVersion(
  145. VOID
  146. )
  147. {
  148. return DIA_VERSION;
  149. }
  150. HRESULT
  151. diaLocatePdb(
  152. PIMGHLP_DEBUG_DATA pIDD,
  153. PSTR szPDB,
  154. GUID *PdbGUID,
  155. DWORD PdbSignature,
  156. DWORD PdbAge,
  157. char *SymbolPath,
  158. char *szImageExt,
  159. int ip
  160. )
  161. {
  162. char szError[cbErrMax] = "";
  163. char szPDBSansPath[_MAX_FNAME];
  164. char szPDBExt[_MAX_EXT];
  165. char szPDBLocal[_MAX_PATH];
  166. char szDbgPath[PDB_MAX_PATH];
  167. char *SemiColon;
  168. DWORD pass;
  169. EC hrcode = E_PDB_NOT_FOUND;
  170. BOOL symsrv = TRUE;
  171. char szPDBName[_MAX_PATH];
  172. char *SavedSymbolPath = SymbolPath;
  173. GUID guid;
  174. WCHAR wszPDB[_MAX_PATH + 1];
  175. WCHAR wszError[cbErrMax];
  176. WCHAR wszPDBLocal[_MAX_PATH + 1];
  177. PDIA pdia;
  178. HRESULT hr;
  179. BOOL ssfile;
  180. BOOL refpath;
  181. BOOL first;
  182. // if (traceSubName(szPDB)) // for setting debug breakpoints from DBGHELP_TOKEN
  183. // dprint("diaLocatePdb(%s)\n", szPDB);
  184. ZeroMemory(&guid, sizeof(GUID));
  185. if (!PdbSignature
  186. && !ValidGUID(PdbGUID)
  187. && (g.SymOptions & SYMOPT_EXACT_SYMBOLS))
  188. {
  189. g.LastSymLoadError = SYMLOAD_PDBUNMATCHED;
  190. return E_PDB_INVALID_SIG;
  191. }
  192. // SymbolPath is a semicolon delimited path (reference path first)
  193. strcpy (szPDBLocal, szPDB);
  194. _splitpath(szPDBLocal, NULL, NULL, szPDBSansPath, szPDBExt);
  195. pdia = (PDIA)pIDD->dia;
  196. if (!pdia)
  197. return !S_OK;
  198. first = TRUE;
  199. do {
  200. SemiColon = strchr(SymbolPath, ';');
  201. if (SemiColon) {
  202. *SemiColon = '\0';
  203. }
  204. if (first) {
  205. refpath = (ip == ipFirst);
  206. first = FALSE;
  207. } else if (!SemiColon) {
  208. refpath = (ip == ipLast);
  209. } else {
  210. refpath = FALSE;
  211. }
  212. if (refpath) {
  213. pass = 2;
  214. ip = ipNone;;
  215. } else {
  216. pass = 0;
  217. }
  218. if (SymbolPath) {
  219. do_again:
  220. ssfile = FALSE;
  221. if (!_strnicmp(SymbolPath, "SYMSRV*", 7)) {
  222. *szPDBLocal = 0;
  223. sprintf(szPDBName, "%s%s", szPDBSansPath, ".pdb");
  224. if (symsrv) {
  225. ssfile = TRUE;
  226. if (PdbSignature)
  227. guid.Data1 = PdbSignature;
  228. else if (PdbGUID)
  229. memcpy(&guid, PdbGUID, sizeof(GUID));
  230. GetFileFromSymbolServer(SymbolPath,
  231. szPDBName,
  232. &guid,
  233. PdbAge,
  234. 0,
  235. szPDBLocal);
  236. symsrv = FALSE;
  237. }
  238. } else {
  239. strcpy(szPDBLocal, SymbolPath);
  240. EnsureTrailingBackslash(szPDBLocal);
  241. // search order is ...
  242. //
  243. // %dir%\symbols\%ext%\%file%
  244. // %dir%\%ext%\%file%
  245. // %dir%\%file%
  246. switch (pass)
  247. {
  248. case 0:
  249. strcat(szPDBLocal, "symbols");
  250. EnsureTrailingBackslash(szPDBLocal);
  251. // pass through
  252. case 1:
  253. strcat(szPDBLocal, szImageExt);
  254. // pass through
  255. default:
  256. EnsureTrailingBackslash(szPDBLocal);
  257. break;
  258. }
  259. strcat(szPDBLocal, szPDBSansPath);
  260. strcat(szPDBLocal, szPDBExt);
  261. }
  262. if (*szPDBLocal) {
  263. ansi2wcs(szPDBLocal, wszPDBLocal, lengthof(wszPDBLocal));
  264. dprint("diaLocatePDB-> Looking for %s... ", szPDBLocal);
  265. if (!ValidSig(PdbSignature, PdbGUID)) {
  266. hr = pdia->source->loadDataFromPdb(wszPDBLocal);
  267. } else {
  268. hr = pdia->source->loadAndValidateDataFromPdb(wszPDBLocal,
  269. ValidGUID(PdbGUID) ? PdbGUID : NULL,
  270. PdbSignature,
  271. PdbAge);
  272. }
  273. hrcode = SetDiaError(hrcode, hr);
  274. if (hr == S_OK) {
  275. if (ssfile)
  276. pIDD->PdbSrc = srcSymSrv;
  277. else if (refpath)
  278. pIDD->PdbSrc = pIDD->PdbSrc;
  279. else
  280. pIDD->PdbSrc = srcSearchPath;
  281. if (!PdbSignature && !ValidGUID(PdbGUID))
  282. eprint("unknown pdb sig ");
  283. break;
  284. } else {
  285. if (hr == E_PDB_INVALID_SIG || hr == E_PDB_INVALID_AGE) {
  286. eprint("%s ", diaErrorText(hr));
  287. if (!ValidSig(PdbSignature, PdbGUID)) {
  288. hr = pdia->source->loadDataFromPdb(wszPDBLocal);
  289. if (hr == S_OK)
  290. break;
  291. }
  292. eprint("\n");
  293. } else if (hr == E_PDB_NOT_FOUND) {
  294. eprint("%s\n", diaErrorText(hr));
  295. if (!(g.LastSymLoadError & SYMLOAD_PDBERRORMASK)) {
  296. g.LastSymLoadError = SYMLOAD_PDBNOTFOUND;
  297. }
  298. } else {
  299. eprint("%s\n", diaErrorText(hr));
  300. g.LastSymLoadError = (hr << 8) & SYMLOAD_PDBERRORMASK;
  301. }
  302. if (pass < 2) {
  303. pass++;
  304. goto do_again;
  305. }
  306. }
  307. refpath = FALSE;
  308. }
  309. }
  310. if (SemiColon) {
  311. *SemiColon = ';';
  312. SemiColon++;
  313. symsrv = TRUE;
  314. }
  315. SymbolPath = SemiColon;
  316. } while (SemiColon);
  317. if (hr != S_OK) {
  318. strcpy(szPDBLocal, szPDB);
  319. ansi2wcs(szPDBLocal, wszPDBLocal, lengthof(wszPDB));
  320. dprint("diaLocatePDB-> Looking for %s... ", szPDBLocal);
  321. hr = pdia->source->loadAndValidateDataFromPdb(wszPDBLocal,
  322. ValidGUID(PdbGUID) ? PdbGUID : NULL,
  323. PdbSignature,
  324. PdbAge);
  325. if (hr != S_OK) {
  326. if (hr == E_PDB_INVALID_SIG || hr == E_PDB_INVALID_AGE) {
  327. eprint("%s ", diaErrorText(hr));
  328. if (!ValidSig(PdbSignature, PdbGUID)) {
  329. hr = pdia->source->loadDataFromPdb(wszPDBLocal);
  330. }
  331. if (hr != S_OK)
  332. eprint("\n");
  333. } else if (hr == E_PDB_NOT_FOUND) {
  334. eprint("%s\n", diaErrorText(hr));
  335. if (!(g.LastSymLoadError & SYMLOAD_PDBERRORMASK)) {
  336. g.LastSymLoadError = SYMLOAD_PDBNOTFOUND;
  337. }
  338. } else {
  339. eprint("%s\n", diaErrorText(hr));
  340. g.LastSymLoadError = (hr << 8) & SYMLOAD_PDBERRORMASK;
  341. }
  342. } else {
  343. pIDD->PdbSrc = srcCVRec;
  344. }
  345. }
  346. if (hr == S_OK) {
  347. eprint("OK\n");
  348. // Store the name of the PDB we actually opened for later reference.
  349. strcpy(szPDB, szPDBLocal);
  350. SetLastError(NO_ERROR);
  351. g.LastSymLoadError = SYMLOAD_OK;
  352. }
  353. if (hr != S_OK && (PdbSignature || ValidGUID(PdbGUID)) && (g.SymOptions & SYMOPT_LOAD_ANYTHING))
  354. return diaLocatePdb(pIDD, szPDB, NULL, 0, 0, SavedSymbolPath, szImageExt, ipNone);
  355. return hr;
  356. }
  357. BOOL
  358. diaGetFPOTable(
  359. PIMGHLP_DEBUG_DATA pIDD
  360. )
  361. {
  362. DWORD celt;
  363. LONG count;
  364. DWORD cb;
  365. PBYTE buf;
  366. HRESULT hr;
  367. PDIA pdia;
  368. VARIANT var;
  369. CComPtr< IDiaEnumDebugStreams > idiaStreams;
  370. CComPtr< IDiaEnumDebugStreamData > idiaStream;
  371. assert (pIDD && pIDD->dia);
  372. pdia = (PDIA)pIDD->dia;
  373. hr = pdia->session->getEnumDebugStreams(&idiaStreams);
  374. if (hr != S_OK)
  375. return FALSE;
  376. var.vt = VT_BSTR;
  377. var.bstrVal = L"FPO";
  378. hr = idiaStreams->Item(var, &idiaStream);
  379. if (hr != S_OK)
  380. return FALSE;
  381. hr = idiaStream->get_Count(&count);
  382. if (hr != S_OK)
  383. return FALSE;
  384. if (count < 1)
  385. return TRUE;
  386. hr = idiaStream->Next(count, 0, &cb, NULL, &celt);
  387. if (hr != S_OK)
  388. return FALSE;
  389. if (cb < 1)
  390. return TRUE;
  391. buf = (PBYTE)MemAlloc(cb);
  392. if (!buf)
  393. return FALSE;
  394. hr = idiaStream->Next(count, cb, &cb, buf, &celt);
  395. if (hr != S_OK) {
  396. MemFree(buf);
  397. return FALSE;
  398. }
  399. pIDD->cFpo = count;
  400. pIDD->pFpo = buf;
  401. return TRUE;
  402. }
  403. BOOL
  404. diaGetPData(
  405. PMODULE_ENTRY mi
  406. )
  407. {
  408. DWORD celt;
  409. LONG count;
  410. DWORD cb;
  411. PBYTE buf;
  412. HRESULT hr;
  413. PDIA pdia;
  414. VARIANT var;
  415. CComPtr< IDiaEnumDebugStreams > idiaStreams;
  416. CComPtr< IDiaEnumDebugStreamData > idiaStream;
  417. assert (mi && mi->dia);
  418. pdia = (PDIA)mi->dia;
  419. hr = pdia->session->getEnumDebugStreams(&idiaStreams);
  420. if (hr != S_OK)
  421. return FALSE;
  422. var.vt = VT_BSTR;
  423. var.bstrVal = L"PDATA";
  424. hr = idiaStreams->Item(var, &idiaStream);
  425. if (hr != S_OK)
  426. return FALSE;
  427. hr = idiaStream->get_Count(&count);
  428. if (hr != S_OK)
  429. return FALSE;
  430. if (count < 1)
  431. return TRUE;
  432. hr = idiaStream->Next(count, 0, &cb, NULL, &celt);
  433. if (hr != S_OK)
  434. return FALSE;
  435. if (cb < 1)
  436. return TRUE;
  437. buf = (PBYTE)MemAlloc(cb);
  438. if (!buf)
  439. return FALSE;
  440. hr = idiaStream->Next(count, cb, &cb, buf, &celt);
  441. if (hr != S_OK) {
  442. MemFree(buf);
  443. return FALSE;
  444. }
  445. mi->dsExceptions = dsDia;
  446. mi->cPData = count;
  447. mi->cbPData = cb;
  448. mi->pPData = buf;
  449. return TRUE;
  450. }
  451. BOOL
  452. diaGetXData(
  453. PMODULE_ENTRY mi
  454. )
  455. {
  456. DWORD celt;
  457. LONG count;
  458. DWORD cb;
  459. PBYTE buf;
  460. HRESULT hr;
  461. PDIA pdia;
  462. VARIANT var;
  463. CComPtr< IDiaEnumDebugStreams > idiaStreams;
  464. CComPtr< IDiaEnumDebugStreamData > idiaStream;
  465. assert (mi && mi->dia);
  466. pdia = (PDIA)mi->dia;
  467. if (!pdia)
  468. return FALSE;
  469. hr = pdia->session->getEnumDebugStreams(&idiaStreams);
  470. if (hr != S_OK)
  471. return FALSE;
  472. var.vt = VT_BSTR;
  473. var.bstrVal = L"XDATA";
  474. hr = idiaStreams->Item(var, &idiaStream);
  475. if (hr != S_OK)
  476. return FALSE;
  477. hr = idiaStream->get_Count(&count);
  478. if (hr != S_OK)
  479. return FALSE;
  480. if (count < 1)
  481. return TRUE;
  482. hr = idiaStream->Next(count, 0, &cb, NULL, &celt);
  483. if (hr != S_OK)
  484. return FALSE;
  485. if (cb < 1)
  486. return TRUE;
  487. CComQIPtr< IDiaImageData, &IID_IDiaImageData > idiaXDataHdr(idiaStream);
  488. if (!idiaXDataHdr.p)
  489. return FALSE;
  490. DWORD relativeVirtualAddress;
  491. if (FAILED(hr = idiaXDataHdr->get_relativeVirtualAddress(&relativeVirtualAddress)))
  492. return FALSE;
  493. buf = (PBYTE)MemAlloc(cb + sizeof(DWORD));
  494. if (!buf)
  495. return FALSE;
  496. memcpy(buf, &relativeVirtualAddress, sizeof(relativeVirtualAddress));
  497. hr = idiaStream->Next(count, cb, &cb, buf + sizeof(DWORD), &celt);
  498. if (hr != S_OK) {
  499. MemFree(buf);
  500. return FALSE;
  501. }
  502. mi->dsExceptions = dsDia;
  503. mi->cXData = count;
  504. mi->cbXData = cb;
  505. mi->pXData = buf;
  506. return TRUE;
  507. }
  508. BOOL
  509. diaGetOmaps(
  510. PIMGHLP_DEBUG_DATA pIDD
  511. )
  512. {
  513. DWORD celt;
  514. LONG count;
  515. DWORD cb;
  516. PBYTE tbuf = NULL;
  517. PBYTE fbuf = NULL;
  518. HRESULT hr;
  519. PDIA pdia;
  520. VARIANT var;
  521. CComPtr< IDiaEnumDebugStreams > idiaStreams;
  522. CComPtr< IDiaEnumDebugStreamData > idiaStream;
  523. assert (pIDD && pIDD->dia);
  524. pdia = (PDIA)pIDD->dia;
  525. hr = pdia->session->getEnumDebugStreams(&idiaStreams);
  526. if (hr != S_OK)
  527. return FALSE;
  528. var.vt = VT_BSTR;
  529. var.bstrVal = L"OMAPTO";
  530. hr = idiaStreams->Item(var, &idiaStream);
  531. if (hr != S_OK)
  532. return FALSE;
  533. hr = idiaStream->get_Count(&count);
  534. if (hr != S_OK)
  535. return FALSE;
  536. if (count < 1)
  537. return TRUE;
  538. hr = idiaStream->Next(count, 0, &cb, NULL, &celt);
  539. if (hr != S_OK)
  540. return FALSE;
  541. if (cb < 1)
  542. return TRUE;
  543. tbuf = (PBYTE)MemAlloc(cb);
  544. if (!tbuf)
  545. return FALSE;
  546. hr = idiaStream->Next(count, cb, &cb, tbuf, &celt);
  547. if (hr != S_OK)
  548. goto CleanReturnFalse;
  549. pIDD->cOmapTo = count;
  550. pIDD->pOmapTo = (POMAP)tbuf;
  551. idiaStream = NULL;
  552. var.vt = VT_BSTR;
  553. var.bstrVal = L"OMAPFROM";
  554. hr = idiaStreams->Item(var, &idiaStream);
  555. if (hr != S_OK)
  556. return FALSE;
  557. hr = idiaStream->get_Count(&count);
  558. if (hr != S_OK)
  559. return FALSE;
  560. if (count < 1)
  561. return TRUE;
  562. hr = idiaStream->Next(count, 0, &cb, NULL, &celt);
  563. if (hr != S_OK)
  564. return FALSE;
  565. if (cb < 1)
  566. return TRUE;
  567. fbuf = (PBYTE)MemAlloc(cb);
  568. if (!fbuf)
  569. return FALSE;
  570. hr = idiaStream->Next(count, cb, &cb, fbuf, &celt);
  571. if (hr != S_OK)
  572. goto CleanReturnFalse;
  573. pIDD->cOmapFrom = count;
  574. pIDD->pOmapFrom = (POMAP)fbuf;
  575. return TRUE;
  576. CleanReturnFalse:
  577. MemFree(tbuf);
  578. MemFree(fbuf);
  579. return FALSE;
  580. }
  581. void
  582. diaRelease(
  583. PVOID dia
  584. )
  585. {
  586. PDIA pdia = (PDIA)dia;
  587. delete pdia;
  588. }
  589. BOOL
  590. diaOpenPdb(
  591. PIMGHLP_DEBUG_DATA pIDD
  592. )
  593. {
  594. HRESULT hr;
  595. PDIA pdia;
  596. PCHAR szLocalSymbolPath = NULL;
  597. DWORD cpathlen = 0;
  598. CHAR szExt[_MAX_EXT] = {0};
  599. int ip;
  600. if (pIDD->SymbolPath)
  601. cpathlen = strlen(pIDD->SymbolPath);
  602. szLocalSymbolPath = (PCHAR)MemAlloc(cpathlen + strlen(pIDD->PdbReferencePath) + 2);
  603. if (!szLocalSymbolPath) {
  604. return FALSE;
  605. }
  606. *szLocalSymbolPath = 0;
  607. ip = ipNone;
  608. if (pIDD->ImageSrc != srcSymSrv)
  609. strcpy(szLocalSymbolPath, pIDD->PdbReferencePath);
  610. if (*szLocalSymbolPath) {
  611. if (pIDD->SymbolPath)
  612. strcat(szLocalSymbolPath, ";");
  613. ip = ipFirst;
  614. }
  615. if (pIDD->SymbolPath)
  616. strcat(szLocalSymbolPath, pIDD->SymbolPath);
  617. if (pIDD->ImageSrc == srcSymSrv) {
  618. if (pIDD->PdbReferencePath) {
  619. if (*szLocalSymbolPath)
  620. strcat(szLocalSymbolPath, ";");
  621. strcat(szLocalSymbolPath, pIDD->PdbReferencePath);
  622. ip = ipLast;
  623. }
  624. }
  625. if (*pIDD->ImageFilePath) {
  626. _splitpath(pIDD->ImageFilePath, NULL, NULL, NULL, szExt);
  627. } else if (*pIDD->ImageName) {
  628. _splitpath(pIDD->ImageName, NULL, NULL, NULL, szExt);
  629. }
  630. // if we have no valid filename, then this must be an executable
  631. if (!*szExt)
  632. strcpy(szExt, ".exe");
  633. // get interface to dia
  634. pdia = new DIA;
  635. if (!pdia) {
  636. hr = E_PDB_OUT_OF_MEMORY;
  637. goto error;
  638. }
  639. pIDD->dia = pdia;
  640. pdia->source = NULL;
  641. hr = DiaCoCreate(CLSID_DiaSourceAlt, IID_IDiaDataSource, (void **)&pdia->source);
  642. if (hr != S_OK)
  643. goto error;
  644. // go ahead and get pdb
  645. SetCriticalErrorMode();
  646. hr = diaLocatePdb(pIDD,
  647. pIDD->PdbFileName,
  648. &pIDD->PdbGUID,
  649. pIDD->PdbSignature,
  650. pIDD->PdbAge,
  651. szLocalSymbolPath,
  652. &szExt[1],
  653. ip);
  654. ResetCriticalErrorMode();
  655. MemFree(szLocalSymbolPath);
  656. szLocalSymbolPath = NULL;
  657. if (hr != S_OK) {
  658. hr = S_OK; // error was already handled by diaLocatePdb()
  659. goto error;
  660. }
  661. // open the session on the pdb
  662. pdia->session = NULL;
  663. hr = pdia->source->openSession(&pdia->session);
  664. if (hr != S_OK)
  665. goto error;
  666. // Set the module load address so we can use VAs.
  667. hr = pdia->session->put_loadAddress(pIDD->InProcImageBase);
  668. if (hr != S_OK)
  669. goto error;
  670. // fixup the address map so that we can translate rva to full addresses
  671. hr = pdia->session->QueryInterface(IID_IDiaAddressMap, (void**)&pdia->addrmap);
  672. if (hr != S_OK)
  673. goto error;
  674. if (pIDD->pCurrentSections) {
  675. hr = pdia->addrmap->set_imageHeaders(pIDD->cCurrentSections * sizeof(IMAGE_SECTION_HEADER),
  676. (BYTE *)pIDD->pCurrentSections,
  677. FALSE);
  678. if (hr != S_OK)
  679. goto error;
  680. }
  681. // this hack is to fix a problem with v7 pdbs not storing the original image alignment
  682. if (pIDD->ImageAlign) {
  683. hr = pdia->addrmap->put_imageAlign(pIDD->ImageAlign);
  684. if (hr != S_OK)
  685. goto error;
  686. }
  687. // pass in the omap information and setup the proper image alignment to the original
  688. if (pIDD->cOmapFrom && pIDD->pOmapFrom) {
  689. hr = pdia->addrmap->put_imageAlign(pIDD->ImageAlign);
  690. if (hr != S_OK)
  691. goto error;
  692. hr = pdia->addrmap->set_addressMap(pIDD->cOmapTo, (DiaAddressMapEntry *)pIDD->pOmapTo, TRUE);
  693. if (hr != S_OK)
  694. goto error;
  695. hr = pdia->addrmap->set_addressMap(pIDD->cOmapFrom, (DiaAddressMapEntry *)pIDD->pOmapFrom, FALSE);
  696. if (hr != S_OK)
  697. goto error;
  698. hr = pdia->addrmap->put_addressMapEnabled(TRUE);
  699. if (hr != S_OK)
  700. goto error;
  701. }
  702. hr = pdia->addrmap->put_relativeVirtualAddressEnabled(TRUE);
  703. if (hr != S_OK)
  704. goto error;
  705. diaGetFPOTable(pIDD);
  706. diaGetOmaps(pIDD);
  707. return TRUE;
  708. error:
  709. if (hr)
  710. dprint("%s\n", pIDD->PdbFileName, diaErrorText(hr));
  711. MemFree(szLocalSymbolPath);
  712. if (pdia) {
  713. diaRelease(pdia);
  714. pIDD->dia = NULL;
  715. }
  716. return FALSE;
  717. }
  718. DWORD64
  719. GetAddressFromRva(
  720. PMODULE_ENTRY mi,
  721. DWORD rva
  722. )
  723. {
  724. DWORD64 addr;
  725. assert(mi);
  726. addr = rva ? mi->BaseOfDll + rva : 0;
  727. return addr;
  728. }
  729. BOOL
  730. diaFillSymbolInfo(
  731. PSYMBOL_INFO si,
  732. PMODULE_ENTRY mi,
  733. IDiaSymbol *idiaSymbol
  734. )
  735. {
  736. HRESULT hr;
  737. BSTR wname=NULL;
  738. CHAR name[MAX_SYM_NAME + 1];
  739. VARIANT var;
  740. // DWORD tag;
  741. DWORD dw;
  742. ULONG64 size;
  743. BOOL rc;
  744. rc = TRUE;
  745. dw = si->MaxNameLen;
  746. ZeroMemory(si, sizeof(SYMBOL_INFO));
  747. si->MaxNameLen = dw;
  748. // si->SizeOfStruct = IGNORED;
  749. // si->TypeIndex = NYI;
  750. // si->Reserved = IGNORED;
  751. si->ModBase = mi->BaseOfDll;
  752. hr = idiaSymbol->get_symTag(&si->Tag);
  753. if (hr != S_OK)
  754. return FALSE;
  755. switch (si->Tag)
  756. {
  757. case SymTagData:
  758. hr = idiaSymbol->get_locationType(&dw);
  759. if (hr != S_OK)
  760. return FALSE;
  761. switch(dw)
  762. {
  763. case LocIsStatic:
  764. case LocIsTLS:
  765. hr = idiaSymbol->get_relativeVirtualAddress(&dw);
  766. si->Address = GetAddressFromRva(mi, dw);
  767. if (!si->Address)
  768. rc = FALSE;
  769. break;
  770. case LocIsEnregistered:
  771. hr = idiaSymbol->get_registerId(&si->Register);
  772. si->Flags = IMAGEHLP_SYMBOL_INFO_REGISTER;
  773. LookupRegID(si->Register, mi->MachineType,&si->Register) ;
  774. break;
  775. case LocIsRegRel:
  776. si->Flags = IMAGEHLP_SYMBOL_INFO_REGRELATIVE;
  777. hr = idiaSymbol->get_registerId(&si->Register);
  778. if (hr != S_OK)
  779. return FALSE;
  780. hr = idiaSymbol->get_offset((PLONG)&dw);
  781. LookupRegID(si->Register, mi->MachineType,&si->Register) ;
  782. si->Address = (ULONG64) (LONG64) (LONG) dw;
  783. break;
  784. case LocIsThisRel:
  785. // struct members - get_Offset
  786. default:
  787. si->Flags |= 0;
  788. break;
  789. }
  790. break;
  791. case SymTagFunction:
  792. case SymTagPublicSymbol:
  793. case SymTagThunk:
  794. hr = idiaSymbol->get_relativeVirtualAddress(&dw);
  795. si->Address = GetAddressFromRva(mi, dw);
  796. if (!si->Address)
  797. rc = FALSE;
  798. break;
  799. default:
  800. break;
  801. }
  802. if (hr != S_OK)
  803. return FALSE;
  804. hr = idiaSymbol->get_dataKind(&dw);
  805. if (hr == S_OK) {
  806. if (dw == DataIsParam)
  807. si->Flags |= IMAGEHLP_SYMBOL_INFO_PARAMETER;
  808. else if (dw == DataIsConstant)
  809. si->Flags = IMAGEHLP_SYMBOL_INFO_CONSTANT;
  810. }
  811. hr = idiaSymbol->get_typeId(&dw);
  812. if (hr == S_OK)
  813. si->TypeIndex = dw;
  814. hr = idiaSymbol->get_name(&wname);
  815. if (hr != S_OK || !wname)
  816. return FALSE;
  817. if (!wname[0]) {
  818. rc = FALSE;
  819. } else {
  820. wcs2ansi(wname, name, MAX_SYM_NAME);
  821. if (*name == '.')
  822. si->Flags = IMAGEHLP_SYMBOL_FUNCTION;
  823. // if (traceSubName(name)) // for setting debug breakpoints from DBGHELP_TOKEN
  824. // dprint("debug(%s)\n", name);
  825. if (g.SymOptions & SYMOPT_UNDNAME)
  826. SymUnDNameInternal(si->Name,
  827. si->MaxNameLen,
  828. name,
  829. strlen(name),
  830. mi->MachineType,
  831. si->Tag == SymTagPublicSymbol);
  832. else
  833. strcpy(si->Name, name);
  834. // let the caller know this is a $$$XXXAA style symbol
  835. if (strlen(si->Name) == 8 && !strncmp(si->Name, "$$$",3) &&
  836. isxdigit(si->Name[5]) && isxdigit(si->Name[6]) && isxdigit(si->Name[7]) )
  837. {
  838. rc = FALSE;
  839. }
  840. }
  841. if (wname)
  842. LocalFree (wname);
  843. // if (traceSubName(name)) // for setting debug breakpoints from DBGHELP_TOKEN
  844. // dprint("debug(%s)\n", name);
  845. hr = idiaSymbol->get_length(&size);
  846. if (hr == S_OK)
  847. si->Size = (ULONG)size;
  848. else {
  849. CComPtr <IDiaSymbol> pType;
  850. if ((hr = idiaSymbol->get_type(&pType)) == S_OK){
  851. hr = pType->get_length(&size);
  852. if (hr == S_OK)
  853. si->Size = (ULONG)size;
  854. }
  855. pType = NULL;
  856. }
  857. return rc;
  858. }
  859. BOOL
  860. diaSetModFromIP(
  861. PPROCESS_ENTRY pe
  862. )
  863. {
  864. HRESULT hr;
  865. DWORD64 ip;
  866. DWORD rva;
  867. PDIA pdia;
  868. // get the current IP
  869. ip = GetIP(pe);
  870. if (!ip) {
  871. pprint(pe, "IP not set!\n");
  872. return FALSE;
  873. }
  874. // find and load symbols for the module that matches the IP
  875. pe->ipmi = GetModFromAddr(pe, ip);
  876. if (!pe->ipmi)
  877. return FALSE;
  878. if (!pe->ipmi->dia)
  879. return FALSE;
  880. pdia = (PDIA)pe->ipmi->dia;
  881. rva = (DWORD)(ip - pe->ipmi->BaseOfDll);
  882. pdia->scope = NULL; // delete previous scope
  883. CComPtr< IDiaSymbol > idiaScope;
  884. hr = pdia->session->findSymbolByRVA(rva, SymTagNull, &idiaScope);
  885. if (hr != S_OK)
  886. return FALSE;
  887. hr = pdia->session->symsAreEquiv(idiaScope, pdia->scope);
  888. if (hr != S_OK) {
  889. // pprint(pe, "Scope changed [0x%x]\n", rva);
  890. pdia->scope = idiaScope;
  891. return TRUE;
  892. }
  893. return FALSE;
  894. }
  895. PWCHAR
  896. ConvertNameForDia(
  897. LPSTR name,
  898. PWCHAR wname
  899. )
  900. {
  901. assert (name && wname);
  902. if (!name || !*name)
  903. return NULL;
  904. ansi2wcs(name, wname, MAX_SYM_NAME);
  905. return wname;
  906. }
  907. VOID
  908. MakeEmbeddedREStr(
  909. PCHAR out,
  910. PCHAR in
  911. )
  912. {
  913. if (*in != '*')
  914. *out++ = '*';
  915. for (; *in; in++, out++)
  916. *out = *in;
  917. if (*(in - 1) != '*')
  918. *out++ = '*';
  919. *out = 0;
  920. }
  921. BOOL
  922. PrepareForCPPMatch(
  923. LPSTR in,
  924. LPSTR out
  925. )
  926. {
  927. LPSTR p;
  928. assert(in && out);
  929. if (strlen(in) > MAX_SYM_NAME)
  930. return FALSE;
  931. for (; *in; in++, out++) {
  932. if (*in == '_' && *(in + 1) == '_') {
  933. strcpy(out, "[_:][_:]");
  934. out += 7;
  935. in++;
  936. } else {
  937. *out = *in;
  938. }
  939. }
  940. *out = 0;
  941. return TRUE;
  942. }
  943. BOOL
  944. diaGetLocals(
  945. PPROCESS_ENTRY pe,
  946. LPSTR name,
  947. PROC callback,
  948. PVOID context,
  949. BOOL use64,
  950. BOOL unicode
  951. )
  952. {
  953. PMODULE_ENTRY mi;
  954. DWORD64 ip;
  955. DWORD rva;
  956. PDIA pdia;
  957. HRESULT hr;
  958. DWORD rc;
  959. DWORD tag;
  960. DWORD scope;
  961. DWORD celt;
  962. DWORD opt;
  963. CHAR symname[MAX_SYM_NAME + 1];
  964. WCHAR wbuf[MAX_SYM_NAME + 1];
  965. PWCHAR wname;
  966. assert(pe);
  967. CComPtr< IDiaSymbol > idiaSymbols;
  968. opt = (g.SymOptions & SYMOPT_CASE_INSENSITIVE) ? nsCaseInRegularExpression : nsRegularExpression;
  969. // get the current scope
  970. mi = pe->ipmi;
  971. if (!mi)
  972. return FALSE;
  973. pdia = (PDIA)mi->dia;
  974. if (!pdia)
  975. return FALSE;
  976. idiaSymbols = pdia->scope;
  977. if (!PrepareForCPPMatch(name, symname))
  978. return FALSE;
  979. wname = ConvertNameForDia(symname, wbuf);
  980. // loop through all symbols
  981. for ( ; idiaSymbols != NULL; ) {
  982. CComPtr< IDiaEnumSymbols > idiaEnum;
  983. // local data search
  984. hr = idiaSymbols->findChildren(SymTagNull, wname, opt, &idiaEnum);
  985. if (hr != S_OK)
  986. return FALSE;
  987. idiaSymbols->get_symTag(&scope);
  988. if (hr != S_OK)
  989. return FALSE;
  990. if (scope == SymTagExe) { // sanity check, never enumerate all exe's symbols
  991. break;
  992. }
  993. // this walks the local symbol list for the loaded enumeration
  994. CComPtr< IDiaSymbol > idiaSymbol;
  995. for (;
  996. SUCCEEDED(hr = idiaEnum->Next( 1, &idiaSymbol, &celt)) && celt == 1;
  997. idiaSymbol = NULL)
  998. {
  999. ULONG DataKind;
  1000. idiaSymbol->get_symTag(&tag);
  1001. switch (tag)
  1002. {
  1003. case SymTagData:
  1004. case SymTagFunction:
  1005. if (!diaFillSymbolInfo(&mi->si, mi, idiaSymbol))
  1006. continue;
  1007. if (!strcmp(mi->si.Name, "`string'"))
  1008. continue;
  1009. mi->si.Scope = scope;
  1010. mi->si.Flags |= IMAGEHLP_SYMBOL_INFO_LOCAL;
  1011. if (!callback)
  1012. return TRUE;
  1013. if (mi->si.Flags & IMAGEHLP_SYMBOL_INFO_CONSTANT)
  1014. continue;
  1015. rc = DoEnumCallback(pe, &mi->si, mi->si.Size, callback, context, use64, unicode);
  1016. if (!rc) {
  1017. mi->code = ERROR_CANCELLED;
  1018. return rc;
  1019. }
  1020. break;
  1021. default:
  1022. break;
  1023. }
  1024. }
  1025. if (callback && scope == SymTagFunction) // stop when at function scope
  1026. break;
  1027. // move to lexical parent
  1028. CComPtr< IDiaSymbol > idiaParent;
  1029. hr = idiaSymbols->get_lexicalParent(&idiaParent);
  1030. if (hr != S_OK || !idiaParent)
  1031. return FALSE;
  1032. idiaSymbols = idiaParent;
  1033. }
  1034. // We reached the end. If we enumerating (I.E. callback != NULL)
  1035. // then return true. If we are searching for a single match,
  1036. // we have failed and should return FALSE;
  1037. if (callback)
  1038. return TRUE;
  1039. return FALSE;
  1040. }
  1041. int __cdecl
  1042. CompareAddrs(
  1043. const void *addr1,
  1044. const void *addr2
  1045. )
  1046. {
  1047. LONGLONG Diff = *(DWORD64 *)addr1 - *(DWORD64 *)addr2;
  1048. if (Diff < 0) {
  1049. return -1;
  1050. } else if (Diff > 0) {
  1051. return 1;
  1052. } else {
  1053. return 0;
  1054. }
  1055. }
  1056. PDWORD64
  1057. FindAddr(
  1058. PDWORD64 pAddrs,
  1059. ULONG cAddrs,
  1060. DWORD64 addr
  1061. )
  1062. {
  1063. LONG high;
  1064. LONG low;
  1065. LONG i;
  1066. LONG rc;
  1067. low = 0;
  1068. high = ((LONG)cAddrs) - 1;
  1069. while (high >= low) {
  1070. i = (low + high) >> 1;
  1071. rc = CompareAddrs(&addr, &pAddrs[i]);
  1072. if (rc < 0)
  1073. high = i - 1;
  1074. else if (rc > 0)
  1075. low = i + 1;
  1076. else
  1077. return &pAddrs[i];
  1078. }
  1079. return NULL;
  1080. }
  1081. BOOL
  1082. diaGetGlobals(
  1083. PPROCESS_ENTRY pe,
  1084. PMODULE_ENTRY mi,
  1085. LPSTR name,
  1086. PROC callback,
  1087. PVOID context,
  1088. BOOL use64,
  1089. BOOL unicode
  1090. )
  1091. {
  1092. PDIA pdia;
  1093. HRESULT hr;
  1094. DWORD tag;
  1095. DWORD celt;
  1096. DWORD rc;
  1097. LONG cFuncs;
  1098. LONG cGlobals = 0;
  1099. enum SymTagEnum SearchTag;
  1100. PDWORD64 pGlobals = NULL;
  1101. PDWORD64 pg = NULL;
  1102. PWCHAR wname;
  1103. DWORD opt;
  1104. WCHAR wbuf[MAX_SYM_NAME + 1];
  1105. CHAR symname[MAX_SYM_NAME + 1];
  1106. CHAR pname[MAX_SYM_NAME + 1];
  1107. BOOL fCase;
  1108. CComPtr<IDiaSymbol> idiaSymbol;
  1109. CComPtr< IDiaSymbol > idiaGlobals;
  1110. CComPtr< IDiaEnumSymbols > idiaSymbols;
  1111. // check parameters
  1112. assert(pe && mi && name);
  1113. if (!callback && !name)
  1114. return FALSE;
  1115. if (!PrepareForCPPMatch(name, symname))
  1116. return FALSE;
  1117. wname = ConvertNameForDia(symname, wbuf);
  1118. if (g.SymOptions & SYMOPT_CASE_INSENSITIVE) {
  1119. opt = nsCaseInRegularExpression;
  1120. fCase = FALSE;
  1121. } else {
  1122. opt = nsRegularExpression;
  1123. fCase = TRUE;
  1124. };
  1125. // get a session
  1126. pdia = (PDIA)mi->dia;
  1127. if (!pdia)
  1128. return FALSE;
  1129. hr = pdia->session->get_globalScope(&idiaGlobals);
  1130. if (hr != S_OK)
  1131. return FALSE;
  1132. // if this is an enumeration, we will have to store a list of the addresses
  1133. // of all the symbols we found in the global scope. Later we will compare
  1134. // this to the publics so as to eliminate doubles.
  1135. if (callback) {
  1136. hr = idiaGlobals->findChildren(SymTagData, wname, opt, &idiaSymbols);
  1137. if (hr != S_OK)
  1138. return FALSE;
  1139. hr = idiaSymbols->get_Count(&cGlobals);
  1140. if (hr != S_OK)
  1141. return FALSE;
  1142. idiaSymbols = NULL;
  1143. hr = idiaGlobals->findChildren(SymTagFunction, wname, opt, &idiaSymbols);
  1144. if (hr != S_OK)
  1145. return FALSE;
  1146. hr = idiaSymbols->get_Count(&cFuncs);
  1147. if (hr != S_OK)
  1148. return FALSE;
  1149. idiaSymbols = NULL;
  1150. cGlobals += cFuncs;
  1151. pGlobals = (PDWORD64)MemAlloc(cGlobals * sizeof(DWORD64));
  1152. }
  1153. if (callback && (!cGlobals || !pGlobals))
  1154. goto publics;
  1155. if (pGlobals) ZeroMemory(pGlobals, cGlobals * sizeof(DWORD64));
  1156. // First search for data
  1157. SearchTag = SymTagData;
  1158. hr = idiaGlobals->findChildren(SearchTag, wname, opt, &idiaSymbols);
  1159. if (hr != S_OK)
  1160. goto publics;
  1161. for (pg = pGlobals;
  1162. (SUCCEEDED(hr = idiaSymbols->Next( 1, &idiaSymbol, &celt)) && celt == 1) || (SearchTag == SymTagData);
  1163. idiaSymbol = NULL)
  1164. {
  1165. ULONG DataKind;
  1166. if ((SearchTag == SymTagData) && (FAILED(hr) || celt != 1)) {
  1167. // Now search for functions
  1168. SearchTag = SymTagFunction;
  1169. idiaSymbols = NULL;
  1170. hr = idiaGlobals->findChildren(SearchTag, wname, opt, &idiaSymbols);
  1171. if (hr != S_OK)
  1172. goto publics;
  1173. continue;
  1174. }
  1175. idiaSymbol->get_symTag(&tag);
  1176. switch (tag)
  1177. {
  1178. case SymTagData:
  1179. case SymTagFunction:
  1180. assert(!callback || ((LONG)(pg - pGlobals) < cGlobals));
  1181. if (!diaFillSymbolInfo(&mi->si, mi, idiaSymbol))
  1182. continue;
  1183. if (!strcmp(mi->si.Name, "`string'"))
  1184. continue;
  1185. mi->si.Scope = SymTagExe;
  1186. if (!callback)
  1187. return TRUE;
  1188. if (mi->si.Flags & IMAGEHLP_SYMBOL_INFO_CONSTANT)
  1189. continue;
  1190. if (pg)
  1191. *pg++ = mi->si.Address;
  1192. rc = DoEnumCallback(pe, &mi->si, mi->si.Size, callback, context, use64, unicode);
  1193. if (!rc) {
  1194. mi->code = ERROR_CANCELLED;
  1195. goto exit;
  1196. }
  1197. break;
  1198. default:
  1199. break;
  1200. }
  1201. }
  1202. qsort(pGlobals, cGlobals, sizeof(DWORD64), CompareAddrs);
  1203. publics:
  1204. // now check out the publics table
  1205. if (wname) {
  1206. sprintf(pname, "*%s*", symname);
  1207. MakeEmbeddedREStr(pname, symname);
  1208. wname = ConvertNameForDia(pname, wbuf);
  1209. }
  1210. idiaSymbols = NULL;
  1211. opt |= nsfUndecoratedName;
  1212. hr = idiaGlobals->findChildren(SymTagPublicSymbol, wname, opt, &idiaSymbols);
  1213. if (hr != S_OK)
  1214. goto exit;
  1215. for (;
  1216. SUCCEEDED(hr = idiaSymbols->Next( 1, &idiaSymbol, &celt)) && celt == 1;
  1217. idiaSymbol = NULL)
  1218. {
  1219. if (!diaFillSymbolInfo(&mi->si, mi, idiaSymbol))
  1220. continue;
  1221. mi->si.Scope = SymTagPublicSymbol;
  1222. if (!strcmp(mi->si.Name, "`string'"))
  1223. continue;
  1224. // publics names are mangled: this tests the undecorated name against the mask
  1225. if (*name && strcmpre(mi->si.Name, name, fCase))
  1226. continue;
  1227. if (!callback)
  1228. return TRUE;
  1229. if (FindAddr(pGlobals, cGlobals, mi->si.Address))
  1230. continue;
  1231. rc = DoEnumCallback(pe, &mi->si, mi->si.Size, callback, context, use64, unicode);
  1232. if (!rc) {
  1233. mi->code = ERROR_CANCELLED;
  1234. goto exit;
  1235. }
  1236. }
  1237. // We reached the end. If we are not enumerating (I.E. callback == NULL)
  1238. // then return the result of the last call to the callback. If we are
  1239. // searching for a single match, we have failed and should return FALSE;
  1240. exit:
  1241. MemFree(pGlobals);
  1242. if (!callback)
  1243. return FALSE;
  1244. return rc;
  1245. }
  1246. BOOL
  1247. diaGetSymbols(
  1248. PPROCESS_ENTRY pe,
  1249. PMODULE_ENTRY mi,
  1250. LPSTR name,
  1251. PROC callback,
  1252. PVOID context,
  1253. BOOL use64,
  1254. BOOL unicode
  1255. )
  1256. {
  1257. // ENUMFIX:
  1258. LPSTR pname = (name) ? name : "";
  1259. if (mi) {
  1260. return diaGetGlobals(pe, mi, pname, callback, context, use64, unicode);
  1261. } else {
  1262. return diaGetLocals(pe, pname, callback, context, use64, unicode);
  1263. }
  1264. }
  1265. PSYMBOL_ENTRY
  1266. diaFindSymbolByName(
  1267. PPROCESS_ENTRY pe,
  1268. PMODULE_ENTRY mi,
  1269. LPSTR SymName
  1270. )
  1271. {
  1272. SYMPTR sym;
  1273. char sz[MAX_SYM_NAME + 1];
  1274. if (!diaGetSymbols(pe, mi, SymName, NULL, NULL, 0, 0))
  1275. return NULL;
  1276. if (!mi)
  1277. mi = pe->ipmi;
  1278. CopySymbolEntryFromSymbolInfo(&mi->TmpSym, &mi->si);
  1279. return &mi->TmpSym;
  1280. }
  1281. BOOL
  1282. diaEnumerateSymbols(
  1283. IN PPROCESS_ENTRY pe,
  1284. IN PMODULE_ENTRY mi,
  1285. IN LPSTR mask,
  1286. IN PROC callback,
  1287. IN PVOID context,
  1288. IN BOOL use64,
  1289. IN BOOL unicode
  1290. )
  1291. {
  1292. return diaGetSymbols(pe, mi, mask, callback, context, use64, unicode);
  1293. }
  1294. PSYMBOL_ENTRY
  1295. diaGetSymFromAddr(
  1296. DWORD64 addr,
  1297. PMODULE_ENTRY mi,
  1298. PDWORD64 disp
  1299. )
  1300. {
  1301. HRESULT hr;
  1302. PDIA pdia;
  1303. DWORD rva;
  1304. DWORD tag;
  1305. LONG omapadj;
  1306. BOOL fHitBlock;
  1307. // simple sanity check
  1308. if (!addr)
  1309. return NULL;
  1310. assert (mi && mi->dia);
  1311. pdia = (PDIA)mi->dia;
  1312. if (!pdia)
  1313. return NULL;
  1314. // if (traceAddr(addr)) // for debug breakpoints ...
  1315. // dprint("found 0x%I64x\n", addr);
  1316. rva = (DWORD)(addr - mi->BaseOfDll);
  1317. // get the symbol
  1318. CComPtr< IDiaSymbol > idiaSymbol;
  1319. hr = pdia->session->findSymbolByRVAEx(rva, SymTagNull, &idiaSymbol, &omapadj);
  1320. if (hr != S_OK)
  1321. return NULL;
  1322. // if the symbol is a block, keep grabbing the parent
  1323. // until we get a function...
  1324. fHitBlock = FALSE;
  1325. idiaSymbol->get_symTag(&tag);
  1326. while (tag == SymTagBlock) { // SymTagLabel as well?
  1327. CComPtr< IDiaSymbol > idiaParent;
  1328. fHitBlock = TRUE;
  1329. hr = idiaSymbol->get_lexicalParent(&idiaParent);
  1330. if (hr != S_OK || !idiaParent)
  1331. return NULL;
  1332. idiaSymbol = idiaParent;
  1333. idiaSymbol->get_symTag(&tag);
  1334. }
  1335. if (!diaFillSymbolInfo(&mi->si, mi, idiaSymbol)) {
  1336. // return a public symbol
  1337. idiaSymbol = NULL;
  1338. hr = pdia->session->findSymbolByRVAEx(rva, SymTagPublicSymbol, &idiaSymbol, &omapadj);
  1339. if (hr == S_OK)
  1340. diaFillSymbolInfo(&mi->si, mi, idiaSymbol);
  1341. else
  1342. eprint(" couldn't match name! disp=0x%x rva=0x%x addr=0x%I64x\n", omapadj, rva, addr);
  1343. }
  1344. CopySymbolEntryFromSymbolInfo(&mi->TmpSym, &mi->si);
  1345. if (disp)
  1346. *disp = (fHitBlock) ? addr - mi->si.Address : omapadj;
  1347. return &mi->TmpSym;
  1348. }
  1349. BOOL
  1350. diaGetLineFromAddr(
  1351. PMODULE_ENTRY mi,
  1352. DWORD64 addr,
  1353. PDWORD displacement,
  1354. PIMAGEHLP_LINE64 line
  1355. )
  1356. {
  1357. HRESULT hr;
  1358. PDIA pdia;
  1359. DWORD rva;
  1360. DWORD celt;
  1361. BSTR bstr;
  1362. DWORD dw;
  1363. BOOL rc;
  1364. assert(mi && mi->dia);
  1365. pdia = (PDIA)mi->dia;
  1366. if (!pdia)
  1367. return NULL;
  1368. if (line->SizeOfStruct != sizeof(IMAGEHLP_LINE64))
  1369. return FALSE;
  1370. rva = (DWORD)(addr - mi->BaseOfDll);
  1371. CComPtr< IDiaEnumLineNumbers > idiaLines = NULL;
  1372. hr = pdia->session->findLinesByRVA(rva, 1, &idiaLines);
  1373. if (hr != S_OK)
  1374. return FALSE;
  1375. CComPtr< IDiaLineNumber > idiaLine = NULL;
  1376. hr = idiaLines->Next(1, &idiaLine, &celt);
  1377. if (hr != S_OK || !idiaLine)
  1378. return FALSE;
  1379. // line->Key = 0;
  1380. hr = idiaLine->get_lineNumber(&dw);
  1381. if (hr != S_OK)
  1382. return FALSE;
  1383. line->LineNumber = dw;
  1384. pdia->srcfile = NULL;
  1385. hr = idiaLine->get_sourceFile(&pdia->srcfile);
  1386. if (hr != S_OK)
  1387. return FALSE;
  1388. hr = pdia->srcfile->get_fileName(&bstr);
  1389. if (hr != S_OK)
  1390. return FALSE;
  1391. *mi->SrcFile = 0;
  1392. rc = wcs2ansi(bstr, mi->SrcFile, lengthof(mi->SrcFile));
  1393. if (!rc || !*mi->SrcFile) {
  1394. LocalFree(bstr);
  1395. return FALSE;
  1396. }
  1397. LocalFree(bstr);
  1398. line->FileName = mi->SrcFile;
  1399. hr = idiaLine->get_relativeVirtualAddress(&dw);
  1400. if (hr != S_OK)
  1401. return FALSE;
  1402. line->Address = dw + mi->BaseOfDll;
  1403. *displacement = rva - dw;
  1404. return TRUE;
  1405. }
  1406. BOOL
  1407. diaGetLineNextPrev(
  1408. PMODULE_ENTRY mi,
  1409. PIMAGEHLP_LINE64 line,
  1410. DWORD direction
  1411. )
  1412. {
  1413. HRESULT hr;
  1414. PDIA pdia;
  1415. DWORD rva;
  1416. DWORD celt;
  1417. WCHAR wbuf[MAX_PATH + 1];
  1418. BSTR wfname = NULL;
  1419. DWORD lineno;
  1420. DWORD dw;
  1421. // simple sanity checks
  1422. assert(mi && mi->dia);
  1423. pdia = (PDIA)mi->dia;
  1424. if (!pdia)
  1425. return NULL;
  1426. assert(direction == NP_NEXT || direction == NP_PREV);
  1427. if (line->SizeOfStruct != sizeof(IMAGEHLP_LINE64))
  1428. return FALSE;
  1429. // convert file name for DIA
  1430. if (!*line->FileName)
  1431. return FALSE;
  1432. ansi2wcs(line->FileName, wbuf, MAX_PATH);
  1433. wfname = wbuf;
  1434. // all source files in the module that match the 'wfname'
  1435. CComPtr< IDiaEnumSourceFiles > idiaFiles = NULL;
  1436. hr = pdia->session->findFile(NULL, wfname, nsCaseInsensitive, &idiaFiles);
  1437. if (hr != S_OK)
  1438. return FALSE;
  1439. // the first such file in the list, since we don't use wildcards
  1440. CComPtr< IDiaSourceFile > idiaFile = NULL;
  1441. hr = idiaFiles->Next(1, &idiaFile, &dw);
  1442. if (hr != S_OK)
  1443. return FALSE;
  1444. // all objs that use this source file
  1445. CComPtr< IDiaEnumSymbols > idiaObjs = NULL;
  1446. hr = idiaFile->get_compilands(&idiaObjs);
  1447. if (hr != S_OK)
  1448. return FALSE;
  1449. // LOOP THROUGH ALL THE OBJS! AND STORE THE CLOSEST!
  1450. lineno = 0;
  1451. rva = 0;
  1452. // grab the first obj, since we don't care
  1453. CComPtr< IDiaSymbol > idiaObj = NULL;
  1454. CComPtr< IDiaLineNumber > idiaLine = NULL;
  1455. CComPtr< IDiaEnumLineNumbers > idiaLines = NULL;
  1456. hr = idiaObjs->Next(1, &idiaObj, &celt);
  1457. if (hr != S_OK)
  1458. return FALSE;
  1459. while (celt) {
  1460. // get the line for starting with
  1461. hr = pdia->session->findLinesByLinenum(idiaObj, idiaFile, line->LineNumber + direction, 0, &idiaLines);
  1462. if (hr == S_OK) {
  1463. hr = idiaLines->Next(1, &idiaLine, &dw);
  1464. if (hr == S_OK) {
  1465. hr = idiaLine->get_lineNumber(&dw);
  1466. if (hr == S_OK) {
  1467. if (!lineno) {
  1468. lineno = dw;
  1469. hr = idiaLine->get_relativeVirtualAddress(&rva);
  1470. } else if (direction == NP_NEXT) {
  1471. if (dw < lineno)
  1472. lineno = dw;
  1473. hr = idiaLine->get_relativeVirtualAddress(&rva);
  1474. } else if (dw > lineno) {
  1475. lineno = dw;
  1476. hr = idiaLine->get_relativeVirtualAddress(&rva);
  1477. }
  1478. }
  1479. }
  1480. }
  1481. idiaObj = NULL;
  1482. idiaObjs->Next(1, &idiaObj, &celt);
  1483. }
  1484. if (!lineno)
  1485. return FALSE;
  1486. // Line->Key = SrcLine;
  1487. line->LineNumber = lineno;
  1488. line->Address = GetAddressFromRva(mi, rva);
  1489. return TRUE;
  1490. }
  1491. #if 0
  1492. #define DBG_DIA_LINE 1
  1493. #endif
  1494. // #define DIA_LINE_NAME 1
  1495. BOOL
  1496. diaGetLineFromName(
  1497. PMODULE_ENTRY mi,
  1498. LPSTR filename,
  1499. DWORD linenumber,
  1500. PLONG displacement,
  1501. PIMAGEHLP_LINE64 line
  1502. )
  1503. {
  1504. HRESULT hr;
  1505. WCHAR wsz[_MAX_PATH + 1];
  1506. PDIA pdia;
  1507. DWORD celt;
  1508. BSTR bstr;
  1509. DWORD addr;
  1510. DWORD num;
  1511. BOOL rc;
  1512. #if DIA_LINE_NAME
  1513. assert(mi && mi->dia && filename);
  1514. pdia = (PDIA)mi->dia;
  1515. if (!pdia)
  1516. return NULL;
  1517. if (line->SizeOfStruct != sizeof(IMAGEHLP_LINE64))
  1518. return FALSE;
  1519. if (!*filename)
  1520. return FALSE;
  1521. if (!ansi2wcs(filename, wsz, lengthof(wsz)))
  1522. return FALSE;
  1523. if (!*wsz)
  1524. return FALSE;
  1525. CComPtr<IDiaEnumSourceFiles> idiaSrcFiles;
  1526. hr = pdia->session->findFile(NULL, wsz, nsFNameExt, &idiaSrcFiles);
  1527. if (hr != S_OK)
  1528. return FALSE;
  1529. CComPtr<IDiaSourceFile> idiaSrcFile;
  1530. hr = idiaSrcFiles->Next(1, &idiaSrcFile, &celt);
  1531. if (hr != S_OK)
  1532. return FALSE;
  1533. hr = idiaSrcFile->get_fileName(&bstr);
  1534. if (hr != S_OK)
  1535. return FALSE;
  1536. rc = wcs2ansi(bstr, mi->SrcFile, lengthof(mi->SrcFile));
  1537. if (!rc || !*mi->SrcFile) {
  1538. LocalFree(bstr);
  1539. return FALSE;
  1540. }
  1541. LocalFree(bstr);
  1542. line->FileName = mi->SrcFile;
  1543. // this gives us a list of every .obj that uses this source file
  1544. CComPtr<IDiaEnumSymbols> idiaEnum;
  1545. hr = idiaSrcFile->get_compilands(&idiaEnum);
  1546. if (hr != S_OK)
  1547. return FALSE;
  1548. CComPtr<IDiaSymbol> idiaSymbol;
  1549. CComPtr<IDiaEnumLineNumbers> idiaLineNumbers;
  1550. CComPtr<IDiaLineNumber> idiaLineNumber;
  1551. // walk through the .obj's
  1552. hr = idiaEnum->Next(1, &idiaSymbol, &celt);
  1553. while (hr == S_OK) {
  1554. // This gets a list of all code items that were created from this source line.
  1555. // If we want to fully support inlines and the like, we need to loop all of these
  1556. hr = pdia->session->findLinesByLinenum(idiaSymbol, idiaSrcFile, linenumber, 0, &idiaLineNumbers);
  1557. if (hr != S_OK)
  1558. break;
  1559. idiaLineNumber = NULL;
  1560. hr = idiaLineNumbers->Next(1, &idiaLineNumber, &celt);
  1561. if (hr != S_OK)
  1562. break;
  1563. hr = idiaLineNumber->get_lineNumber(&num);
  1564. if (hr != S_OK)
  1565. break;
  1566. line->LineNumber = num;
  1567. hr = idiaLineNumber->get_relativeVirtualAddress(&addr);
  1568. if (hr != S_OK)
  1569. break;
  1570. if (addr) {
  1571. line->Address = mi->BaseOfDll + addr;
  1572. *displacement = linenumber - num;
  1573. return TRUE;
  1574. }
  1575. idiaSymbol = NULL;
  1576. hr = idiaEnum->Next(1, &idiaSymbol, &celt);
  1577. }
  1578. #endif
  1579. return FALSE;
  1580. }
  1581. HRESULT
  1582. diaAddLinesForSourceFile(
  1583. PMODULE_ENTRY mi,
  1584. IDiaSourceFile *idiaSource,
  1585. IDiaSymbol *pComp
  1586. )
  1587. {
  1588. HRESULT hr;
  1589. LPSTR SrcFileName = NULL;
  1590. BSTR wfname = NULL;
  1591. ULONG SrcFileNameLen = 0;
  1592. PSOURCE_ENTRY Src;
  1593. PSOURCE_ENTRY Seg0Src;
  1594. PSOURCE_LINE SrcLine;
  1595. PDIA pdia;
  1596. ULONG celt;
  1597. LONG LineNums;
  1598. ULONG CompId;
  1599. CHAR fname[MAX_PATH + 1];
  1600. DWORD rva;
  1601. ULONG Line;
  1602. if (!idiaSource) {
  1603. return E_INVALIDARG;
  1604. }
  1605. assert((mi != NULL) && (mi->dia));
  1606. pdia = (PDIA)mi->dia;
  1607. if (pComp->get_symIndexId(&CompId) == S_OK) {
  1608. }
  1609. CComPtr <IDiaEnumLineNumbers> idiaEnumLines;
  1610. if (hr = pdia->session->findLines(pComp, idiaSource, &idiaEnumLines) != S_OK) {
  1611. return hr;
  1612. }
  1613. if (hr = idiaEnumLines->get_Count(&LineNums) != S_OK) {
  1614. return hr;
  1615. }
  1616. CComPtr <IDiaLineNumber> idiaLine;
  1617. if (idiaSource->get_fileName(&wfname) == S_OK && wfname) {
  1618. wcs2ansi(wfname, fname, MAX_PATH);
  1619. LocalFree(wfname);
  1620. SrcFileNameLen = strlen(fname);
  1621. }
  1622. Src = (PSOURCE_ENTRY)MemAlloc(sizeof(SOURCE_ENTRY)+
  1623. sizeof(SOURCE_LINE)*LineNums+
  1624. SrcFileNameLen + 1);
  1625. if (!Src) {
  1626. return E_OUTOFMEMORY;
  1627. }
  1628. #ifdef DBG_DIA_LINE
  1629. dprint("diaAddLinesForSourceFile : source : %s\n", fname);
  1630. #endif
  1631. // Retrieve line numbers and offsets from raw data and
  1632. // process them into current pointers.
  1633. SrcLine = (SOURCE_LINE *)(Src+1);
  1634. Src->LineInfo = SrcLine;
  1635. Src->ModuleId = CompId;
  1636. Src->MaxAddr = 0;
  1637. Src->MinAddr = -1;
  1638. Src->Lines = 0;
  1639. idiaLine = NULL;
  1640. for (; (hr = idiaEnumLines->Next(1, &idiaLine, &celt)) == S_OK && (celt == 1); ) {
  1641. hr = idiaLine->get_lineNumber(&Line);
  1642. if (hr != S_OK)
  1643. break;
  1644. hr = idiaLine->get_relativeVirtualAddress(&rva);
  1645. if (hr != S_OK)
  1646. break;
  1647. SrcLine->Line = Line;
  1648. SrcLine->Addr = mi->BaseOfDll + rva;
  1649. // Line symbol information names the IA64 bundle
  1650. // syllables with 0,1,2 whereas the debugger expects
  1651. // 0,4,8. Convert.
  1652. if (mi->MachineType == IMAGE_FILE_MACHINE_IA64 &&
  1653. (SrcLine->Addr & 3)) {
  1654. SrcLine->Addr = (SrcLine->Addr & ~3) |
  1655. ((SrcLine->Addr & 3) << 2);
  1656. }
  1657. if (SrcLine->Addr > Src->MaxAddr) {
  1658. Src->MaxAddr = SrcLine->Addr;
  1659. }
  1660. if (SrcLine->Addr < Src->MinAddr) {
  1661. Src->MinAddr = SrcLine->Addr;
  1662. }
  1663. #ifdef DBG_DIA_LINE
  1664. dprint("Add line %lx, Addr %I64lx\n", SrcLine->Line, SrcLine->Addr);
  1665. #endif
  1666. Src->Lines++;
  1667. SrcLine++;
  1668. idiaLine = NULL;
  1669. }
  1670. // Stick file name at the very end of the data block so
  1671. // it doesn't interfere with alignment.
  1672. Src->File = (LPSTR)SrcLine;
  1673. if (*fname) {
  1674. memcpy(Src->File, fname, SrcFileNameLen);
  1675. }
  1676. Src->File[SrcFileNameLen] = 0;
  1677. AddSourceEntry(mi, Src);
  1678. return S_OK;
  1679. }
  1680. BOOL
  1681. diaAddLinesForMod(
  1682. PMODULE_ENTRY mi,
  1683. IDiaSymbol *diaModule
  1684. )
  1685. {
  1686. LONG Size;
  1687. BOOL Ret;
  1688. PSOURCE_ENTRY Src;
  1689. ULONG ModId;
  1690. HRESULT Hr;
  1691. if (diaModule->get_symIndexId(&ModId) != S_OK) {
  1692. return FALSE;
  1693. }
  1694. #ifdef DBG_DIA_LINE
  1695. dprint("diaAddLinesForMod : ModId %lx\n", ModId);
  1696. #endif
  1697. // Check and see if we've loaded this information already.
  1698. for (Src = mi->SourceFiles; Src != NULL; Src = Src->Next) {
  1699. // Check module index instead of pointer since there's
  1700. // no guarantee the pointer would be the same for different
  1701. // lookups.
  1702. if (Src->ModuleId == ModId) {
  1703. return TRUE;
  1704. }
  1705. }
  1706. PDIA pdia;
  1707. pdia = (PDIA)mi->dia;
  1708. CComPtr< IDiaEnumSourceFiles > idiaEnumFiles;
  1709. Hr = pdia->session->findFile(diaModule, NULL, nsNone, &idiaEnumFiles);
  1710. if (Hr != S_OK) {
  1711. return FALSE;
  1712. }
  1713. ULONG celt;
  1714. CComPtr <IDiaSourceFile> idiaSource;
  1715. for (;SUCCEEDED(idiaEnumFiles->Next(1,&idiaSource, &celt)) && (celt == 1);) {
  1716. diaAddLinesForSourceFile(mi, idiaSource, diaModule);
  1717. idiaSource = NULL;
  1718. }
  1719. return TRUE;
  1720. }
  1721. BOOL
  1722. MatchSourceFile(
  1723. PCHAR filename,
  1724. PCHAR mask
  1725. )
  1726. {
  1727. PCHAR p;
  1728. if (!mask || !*mask)
  1729. return TRUE;
  1730. if (!*filename)
  1731. return FALSE;
  1732. for (p = filename + strlen(filename); p >= filename; p--) {
  1733. if (*p == '\\' || *p == '/') {
  1734. p++;
  1735. break;
  1736. }
  1737. }
  1738. if (!strcmpre(p, mask, FALSE))
  1739. return TRUE;
  1740. return FALSE;
  1741. }
  1742. BOOL
  1743. diaEnumSourceFiles(
  1744. IN PMODULE_ENTRY mi,
  1745. IN PCHAR mask,
  1746. IN PSYM_ENUMSOURCFILES_CALLBACK cbSrcFiles,
  1747. IN PVOID context
  1748. )
  1749. {
  1750. HRESULT hr;
  1751. BSTR wname=NULL;
  1752. char name[_MAX_PATH + 1];
  1753. SOURCEFILE sf;
  1754. assert(mi && cbSrcFiles);
  1755. PDIA pdia;
  1756. pdia = (PDIA)mi->dia;
  1757. sf.ModBase = mi->BaseOfDll ;
  1758. sf.FileName = name;
  1759. CComPtr< IDiaEnumSourceFiles > idiaEnumFiles;
  1760. hr = pdia->session->findFile(NULL, NULL, nsNone, &idiaEnumFiles);
  1761. if (hr != S_OK)
  1762. return FALSE;
  1763. ULONG celt;
  1764. CComPtr <IDiaSourceFile> idiaSource;
  1765. for (;SUCCEEDED(idiaEnumFiles->Next(1, &idiaSource, &celt)) && (celt == 1);) {
  1766. hr = idiaSource->get_fileName(&wname);
  1767. if (hr == S_OK && wname) {
  1768. wcs2ansi(wname, name, _MAX_PATH);
  1769. LocalFree (wname);
  1770. if (MatchSourceFile(name, mask)) {
  1771. if (!cbSrcFiles(&sf, context)) {
  1772. mi->code = ERROR_CANCELLED;
  1773. return FALSE;
  1774. }
  1775. }
  1776. }
  1777. idiaSource = NULL;
  1778. }
  1779. return TRUE;
  1780. }
  1781. BOOL
  1782. diaAddLinesForModAtAddr(
  1783. PMODULE_ENTRY mi,
  1784. DWORD64 Addr
  1785. )
  1786. {
  1787. BOOL Ret;
  1788. DWORD Bias;
  1789. HRESULT hr;
  1790. PDIA pdia;
  1791. DWORD rva;
  1792. assert(mi && mi->dia);
  1793. pdia = (PDIA)mi->dia;
  1794. if (!pdia)
  1795. return NULL;
  1796. rva = (DWORD)(Addr - mi->BaseOfDll);
  1797. CComPtr < IDiaSymbol > pComp;
  1798. hr = pdia->session->findSymbolByRVA(rva, SymTagCompiland, &pComp);
  1799. if (hr != S_OK)
  1800. return FALSE;
  1801. Ret = diaAddLinesForMod(mi, pComp);
  1802. return Ret;
  1803. }
  1804. BOOL
  1805. diaAddLinesForAllMod(
  1806. PMODULE_ENTRY mi
  1807. )
  1808. {
  1809. HRESULT hr;
  1810. PDIA pdia;
  1811. ULONG celt = 1;
  1812. BOOL Ret;
  1813. Ret = FALSE;
  1814. #ifdef DBG_DIA_LINE
  1815. dprint("diaAddLinesForAllMod : Adding lines for all mods in %s\n", mi->ImageName);
  1816. #endif
  1817. assert(mi && mi->dia);
  1818. pdia = (PDIA)mi->dia;
  1819. if (!pdia)
  1820. return NULL;
  1821. CComPtr <IDiaSymbol> idiaSymbols;
  1822. hr = pdia->session->get_globalScope(&idiaSymbols);
  1823. if (hr != S_OK)
  1824. return NULL;
  1825. CComPtr< IDiaEnumSymbols > idiaMods;
  1826. hr = pdia->session->findChildren(idiaSymbols,SymTagCompiland, NULL, nsNone, &idiaMods);
  1827. if (FAILED(hr))
  1828. return FALSE;
  1829. CComPtr< IDiaSymbol > idiaSymbol;
  1830. while (SUCCEEDED(idiaMods->Next( 1, &idiaSymbol, &celt)) && celt == 1) {
  1831. Ret = diaAddLinesForMod(mi, idiaSymbol);
  1832. idiaSymbol = NULL;
  1833. if (!Ret) {
  1834. break;
  1835. }
  1836. }
  1837. return Ret;
  1838. }
  1839. PSYMBOL_ENTRY
  1840. diaGetSymNextPrev(
  1841. PMODULE_ENTRY mi,
  1842. DWORD64 addr,
  1843. int direction
  1844. )
  1845. {
  1846. HRESULT hr;
  1847. PDIA pdia;
  1848. DWORD rva;
  1849. DWORD celt;
  1850. assert(mi && mi->dia);
  1851. pdia = (PDIA)mi->dia;
  1852. if (!pdia)
  1853. return NULL;
  1854. CComPtr<IDiaEnumSymbolsByAddr> idiaSymbols;
  1855. hr = pdia->session->getSymbolsByAddr(&idiaSymbols);
  1856. if (hr != S_OK)
  1857. return NULL;
  1858. rva = addr ? (DWORD)(addr - mi->BaseOfDll) : 0;
  1859. CComPtr<IDiaSymbol> idiaSymbol;
  1860. hr = idiaSymbols->symbolByRVA(rva, &idiaSymbol);
  1861. if (hr != S_OK)
  1862. return NULL;
  1863. findsymbol:
  1864. if (addr) {
  1865. if (direction < 0) {
  1866. idiaSymbol = NULL;
  1867. hr = idiaSymbols->Prev(1, &idiaSymbol, &celt);
  1868. } else {
  1869. idiaSymbol = NULL;
  1870. hr = idiaSymbols->Next(1, &idiaSymbol, &celt);
  1871. }
  1872. if (hr != S_OK)
  1873. return NULL;
  1874. if (celt != 1)
  1875. return NULL;
  1876. }
  1877. diaFillSymbolInfo(&mi->si, mi, idiaSymbol);
  1878. if (!*mi->si.Name) {
  1879. rva = (DWORD)(mi->si.Address - mi->BaseOfDll);
  1880. goto findsymbol;
  1881. }
  1882. CopySymbolEntryFromSymbolInfo(&mi->TmpSym, &mi->si);
  1883. return &mi->TmpSym;
  1884. }
  1885. HRESULT
  1886. diaGetSymTag(IDiaSymbol *pType, PULONG pTag)
  1887. {
  1888. return pType->get_symTag(pTag);
  1889. }
  1890. HRESULT
  1891. diaGetSymIndexId(IDiaSymbol *pType, PULONG pIndex)
  1892. {
  1893. return pType->get_symIndexId(pIndex);
  1894. }
  1895. HRESULT
  1896. diaGetLexicalParentId(IDiaSymbol *pType, PULONG pIndex)
  1897. {
  1898. return pType->get_lexicalParentId(pIndex);
  1899. }
  1900. HRESULT
  1901. diaGetDataKind(IDiaSymbol *pType, PULONG pKind)
  1902. {
  1903. return pType->get_dataKind(pKind);
  1904. }
  1905. HRESULT
  1906. diaGetSymName(IDiaSymbol *pType, BSTR *pname)
  1907. {
  1908. return pType->get_name(pname);
  1909. }
  1910. HRESULT
  1911. diaGetLength(IDiaSymbol *pType, PULONGLONG pLength)
  1912. {
  1913. return pType->get_length(pLength);
  1914. }
  1915. HRESULT
  1916. diaGetType(IDiaSymbol *pType, IDiaSymbol ** pSymbol)
  1917. {
  1918. return pType->get_type(pSymbol);
  1919. }
  1920. HRESULT
  1921. diaGetBaseType(IDiaSymbol *pType, PULONG pBase)
  1922. {
  1923. return pType->get_baseType(pBase);
  1924. }
  1925. HRESULT
  1926. diaGetArrayIndexTypeId(IDiaSymbol *pType, PULONG pSymbol)
  1927. {
  1928. return pType->get_arrayIndexTypeId(pSymbol);
  1929. }
  1930. HRESULT
  1931. diaGetTypeId(IDiaSymbol *pType, PULONG pTypeId)
  1932. {
  1933. return pType->get_typeId(pTypeId);
  1934. }
  1935. HRESULT
  1936. diaGetChildrenCount(IDiaSymbol *pType, LONG *pCount)
  1937. {
  1938. CComPtr <IDiaEnumSymbols> pEnum;
  1939. HRESULT hr;
  1940. ULONG index;
  1941. CComPtr <IDiaSymbol> pSym;
  1942. ULONG Count;
  1943. if ((hr = pType->findChildren(SymTagNull, NULL, nsNone, &pEnum)) != S_OK) {
  1944. return hr;
  1945. }
  1946. return pEnum->get_Count(pCount);
  1947. }
  1948. HRESULT
  1949. diaFindChildren(IDiaSymbol *pType, TI_FINDCHILDREN_PARAMS *Params)
  1950. {
  1951. CComPtr <IDiaEnumSymbols> pEnum;
  1952. HRESULT hr;
  1953. ULONG index;
  1954. CComPtr <IDiaSymbol> pSym;
  1955. ULONG Count;
  1956. if ((hr = pType->findChildren(SymTagNull, NULL, nsNone, &pEnum)) != S_OK) {
  1957. return hr;
  1958. }
  1959. VARIANT var;
  1960. pEnum->Skip(Params->Start);
  1961. for (Count = Params->Count, index = Params->Start; Count > 0; Count--, index++) {
  1962. ULONG celt;
  1963. pSym = NULL;
  1964. if ((hr = pEnum->Next(1, &pSym, &celt)) != S_OK) {
  1965. return hr;
  1966. }
  1967. if ((hr = pSym->get_symIndexId(&Params->ChildId[index])) != S_OK) {
  1968. return hr;
  1969. }
  1970. }
  1971. return S_OK;
  1972. }
  1973. HRESULT
  1974. diaGetAddressOffset(IDiaSymbol *pType, ULONG *pOff)
  1975. {
  1976. return pType->get_addressOffset(pOff);
  1977. }
  1978. HRESULT
  1979. diaGetOffset(IDiaSymbol *pType, LONG *pOff)
  1980. {
  1981. return pType->get_offset(pOff);
  1982. }
  1983. HRESULT
  1984. diaGetValue(IDiaSymbol *pType, VARIANT *pVar)
  1985. {
  1986. return pType->get_value(pVar);
  1987. }
  1988. HRESULT
  1989. diaGetCount(IDiaSymbol *pType, ULONG *pCount)
  1990. {
  1991. return pType->get_count(pCount);
  1992. }
  1993. HRESULT
  1994. diaGetBitPosition(IDiaSymbol *pType, ULONG *pPos)
  1995. {
  1996. return pType->get_bitPosition(pPos);
  1997. }
  1998. HRESULT
  1999. diaGetVirtualBaseClass(IDiaSymbol *pType, BOOL *pBase)
  2000. {
  2001. return pType->get_virtualBaseClass(pBase);
  2002. }
  2003. HRESULT
  2004. diaGetVirtualTableShapeId(IDiaSymbol *pType, PULONG pShape)
  2005. {
  2006. return pType->get_virtualTableShapeId(pShape);
  2007. }
  2008. HRESULT
  2009. diaGetVirtualBasePointerOffset(IDiaSymbol *pType, LONG *pOff)
  2010. {
  2011. return pType->get_virtualBasePointerOffset(pOff);
  2012. }
  2013. HRESULT
  2014. diaGetClassParentId(IDiaSymbol *pType, ULONG *pCid)
  2015. {
  2016. return pType->get_classParentId(pCid);
  2017. }
  2018. HRESULT
  2019. diaGetNested(IDiaSymbol *pType, BOOL *pNested)
  2020. {
  2021. return pType->get_nested(pNested);
  2022. }
  2023. HRESULT
  2024. diaGetSymAddress(IDiaSymbol *pType, ULONG64 ModBase, PULONG64 pAddr)
  2025. {
  2026. ULONG rva;
  2027. HRESULT Hr;
  2028. Hr = pType->get_relativeVirtualAddress(&rva);
  2029. if (Hr == S_OK) *pAddr = ModBase + rva;
  2030. return Hr;
  2031. }
  2032. HRESULT
  2033. diaGetThisAdjust(IDiaSymbol *pType, LONG *pThisAdjust)
  2034. {
  2035. return pType->get_thisAdjust(pThisAdjust);
  2036. }
  2037. BOOL
  2038. diaFindTypeSym(
  2039. IN HANDLE hProcess,
  2040. IN DWORD64 ModBase,
  2041. IN ULONG TypeId,
  2042. OUT IDiaSymbol **pType
  2043. )
  2044. {
  2045. PPROCESS_ENTRY ProcessEntry;
  2046. PDIA pdia;
  2047. PMODULE_ENTRY mi;
  2048. ProcessEntry = FindProcessEntry( hProcess );
  2049. if (!ProcessEntry || !(mi = GetModFromAddr(ProcessEntry, ModBase))) {
  2050. return FALSE;
  2051. }
  2052. pdia = (PDIA)mi->dia;
  2053. if (!pdia) {
  2054. return FALSE;
  2055. }
  2056. return pdia->session->symbolById(TypeId, pType) == S_OK;
  2057. }
  2058. #ifdef USE_CACHE
  2059. ULONG gHits=0, gLook=0;
  2060. void
  2061. diaInsertInCache(
  2062. PDIA_CACHE_ENTRY pCache,
  2063. PDIA_LARGE_DATA plVals,
  2064. ULONGLONG Module,
  2065. ULONG TypeId,
  2066. IMAGEHLP_SYMBOL_TYPE_INFO GetType,
  2067. PVOID pInfo
  2068. )
  2069. {
  2070. int start = CACHE_BLOCK * (TypeId % CACHE_BLOCK);
  2071. int i, found;
  2072. ULONG len,age;
  2073. PDIA_LARGE_DATA pLargeVal=NULL;
  2074. if (GetType == TI_FINDCHILDREN || GetType == TI_GET_SYMNAME) {
  2075. for (pLargeVal = plVals, found=i=0, age=0; i<2*CACHE_BLOCK; i++) {
  2076. if (!plVals[i].Used) {
  2077. pLargeVal = &plVals[i];
  2078. break;
  2079. } else if (pCache[plVals[i].Index].Age > age) {
  2080. pLargeVal = &plVals[i];
  2081. age = pCache[plVals[i].Index].Age;
  2082. assert(DIACH_PLVAL == pCache[pLargeVal->Index].Data.type);
  2083. assert(pLargeVal == pCache[pLargeVal->Index].Data.plVal);
  2084. }
  2085. }
  2086. // } else {
  2087. // return;
  2088. }
  2089. // if (!(gLook % 200)) {
  2090. // if (GetType == TI_FINDCHILDREN || GetType == TI_GET_SYMNAME) {
  2091. // printf("Index \tUsed\tBy\t\tfound %lx\n", pLargeVal);
  2092. // for (found=i=0, age=0; i<2*CACHE_BLOCK; i++) {
  2093. // printf("%08lx \t%lx\t%lx\n",
  2094. // &plVals[i], plVals[i].Used, plVals[i].Index);
  2095. // }
  2096. // }
  2097. // }
  2098. for (i=found=start, age=0; i<(start+CACHE_BLOCK); i++) {
  2099. if (++pCache[i].Age > age) {
  2100. age = pCache[i].Age; found = i;
  2101. }
  2102. }
  2103. i=found;
  2104. if (pCache[i].Data.type == DIACH_PLVAL) {
  2105. assert(pCache[i].Data.plVal->Index == (ULONG) i);
  2106. pCache[i].Data.plVal->Index = 0;
  2107. pCache[i].Data.plVal->Used = 0;
  2108. pCache[i].Data.type = 0;
  2109. pCache[i].Data.ullVal = 0;
  2110. }
  2111. pCache[i].Age = 0;
  2112. pCache[i].s.DataType = GetType;
  2113. pCache[i].s.TypeId = TypeId;
  2114. pCache[i].Module = Module;
  2115. switch (GetType) {
  2116. case TI_GET_SYMTAG:
  2117. case TI_GET_COUNT:
  2118. case TI_GET_CHILDRENCOUNT:
  2119. case TI_GET_BITPOSITION:
  2120. case TI_GET_VIRTUALBASECLASS:
  2121. case TI_GET_VIRTUALTABLESHAPEID:
  2122. case TI_GET_VIRTUALBASEPOINTEROFFSET:
  2123. case TI_GET_CLASSPARENTID:
  2124. case TI_GET_TYPEID:
  2125. case TI_GET_BASETYPE:
  2126. case TI_GET_ARRAYINDEXTYPEID:
  2127. case TI_GET_DATAKIND:
  2128. case TI_GET_ADDRESSOFFSET:
  2129. case TI_GET_OFFSET:
  2130. case TI_GET_NESTED:
  2131. case TI_GET_THISADJUST:
  2132. pCache[i].Data.type = DIACH_ULVAL;
  2133. pCache[i].Data.ulVal = *((PULONG) pInfo);
  2134. break;
  2135. case TI_GET_LENGTH:
  2136. case TI_GET_ADDRESS:
  2137. pCache[i].Data.type = DIACH_ULLVAL;
  2138. pCache[i].Data.ullVal = *((PULONGLONG) pInfo);
  2139. break;
  2140. case TI_GET_SYMNAME: {
  2141. len = 2*(1+wcslen(*((BSTR *) pInfo)));
  2142. if (pLargeVal &&
  2143. len < sizeof(pLargeVal->Bytes)) {
  2144. // dprint("Ins name %08lx %s had %3lx name %ws\n",
  2145. // pLargeVal, pLargeVal->Used ? "used" : "free",
  2146. // pLargeVal->Index, &pLargeVal->Bytes[0]);
  2147. memcpy(&pLargeVal->Bytes[0], *((BSTR *) pInfo), len);
  2148. pLargeVal->LengthUsed = len;
  2149. if (pLargeVal->Used) {
  2150. pCache[pLargeVal->Index].Data.type = 0;
  2151. pCache[pLargeVal->Index].Data.ullVal = 0;
  2152. pCache[pLargeVal->Index].SearchId = 0;
  2153. }
  2154. pCache[i].Data.type = DIACH_PLVAL;
  2155. pCache[i].Data.plVal = pLargeVal;
  2156. pLargeVal->Index = i;
  2157. pLargeVal->Used = TRUE;
  2158. // dprint(Ins %9I64lx ch %3lx lch %08lx name %ws\n",
  2159. // pCache[i].SearchId, i, pLargeVal, &pLargeVal->Bytes[0]);
  2160. } else {
  2161. pCache[i].SearchId = 0;
  2162. }
  2163. break;
  2164. }
  2165. case TI_FINDCHILDREN: {
  2166. TI_FINDCHILDREN_PARAMS *pChild = (TI_FINDCHILDREN_PARAMS *) pInfo;
  2167. len = sizeof(TI_FINDCHILDREN_PARAMS) + pChild->Count*sizeof(pChild->ChildId[0]) - sizeof(pChild->ChildId);
  2168. if (pLargeVal &&
  2169. len < sizeof(pLargeVal->Bytes)) {
  2170. // dprint("Ins child %08lx %s had %3lx name %ws\n",
  2171. // pLargeVal, pLargeVal->Used ? "used" : "free",
  2172. // pLargeVal->Index, &pLargeVal->Bytes[0]);
  2173. memcpy(&pLargeVal->Bytes[0], pChild, len);
  2174. pLargeVal->LengthUsed = len;
  2175. if (pLargeVal->Used) {
  2176. pCache[pLargeVal->Index].Data.type = 0;
  2177. pCache[pLargeVal->Index].Data.ullVal = 0;
  2178. pCache[pLargeVal->Index].SearchId = 0;
  2179. }
  2180. pCache[i].Data.type = DIACH_PLVAL;
  2181. pCache[i].Data.plVal = pLargeVal;
  2182. pLargeVal->Index = i;
  2183. pLargeVal->Used = TRUE;
  2184. } else {
  2185. pCache[i].SearchId = 0;
  2186. }
  2187. break;
  2188. }
  2189. case TI_GET_VALUE:
  2190. default:
  2191. pCache[i].Data.type = 0;
  2192. pCache[i].SearchId = 0;
  2193. return ;
  2194. }
  2195. }
  2196. BOOL
  2197. diaLookupCache(
  2198. PDIA_CACHE_ENTRY pCache,
  2199. ULONG64 Module,
  2200. ULONG TypeId,
  2201. IMAGEHLP_SYMBOL_TYPE_INFO GetType,
  2202. PVOID pInfo
  2203. )
  2204. {
  2205. int start = CACHE_BLOCK * (TypeId % CACHE_BLOCK);
  2206. int i, found;
  2207. ULONGLONG Search = ((ULONGLONG) GetType << 32) + TypeId;
  2208. ++gLook;
  2209. for (i=start,found=-1; i<(start+CACHE_BLOCK); i++) {
  2210. if (pCache[i].SearchId == Search &&
  2211. pCache[i].Module == Module) {
  2212. found = i;
  2213. break;
  2214. }
  2215. }
  2216. if (found == -1) {
  2217. return FALSE;
  2218. }
  2219. i=found;
  2220. pCache[i].Age = 0;
  2221. switch (pCache[i].Data.type) {
  2222. case DIACH_ULVAL:
  2223. *((PULONG) pInfo) = pCache[i].Data.ulVal;
  2224. break;
  2225. case DIACH_ULLVAL:
  2226. *((PULONGLONG) pInfo) = pCache[i].Data.ullVal;
  2227. break;
  2228. case DIACH_PLVAL:
  2229. if (GetType == TI_GET_SYMNAME) {
  2230. *((BSTR *) pInfo) = (BSTR) LocalAlloc(0, pCache[i].Data.plVal->LengthUsed);
  2231. if (*((BSTR *) pInfo)) {
  2232. memcpy(*((BSTR *) pInfo), &pCache[i].Data.plVal->Bytes[0],pCache[i].Data.plVal->LengthUsed);
  2233. // dprint(Lok %9I64lx ch %3lx lch %08lx name %ws\n",
  2234. // pCache[i].SearchId,
  2235. // i,
  2236. // pCache[i].Data.plVal,
  2237. // &pCache[i].Data.plVal->Bytes[0]);
  2238. }
  2239. } else if (GetType == TI_FINDCHILDREN) {
  2240. TI_FINDCHILDREN_PARAMS *pChild = (TI_FINDCHILDREN_PARAMS *) pInfo;
  2241. TI_FINDCHILDREN_PARAMS *pStored = (TI_FINDCHILDREN_PARAMS *) &pCache[i].Data.plVal->Bytes[0];
  2242. // dprint(Lok %9I64lx ch %3lx lch %08lx child %lx\n",
  2243. // pCache[i].SearchId,
  2244. // i,
  2245. // pCache[i].Data.plVal,
  2246. // pStored->Count);
  2247. if (pChild->Count == pStored->Count &&
  2248. pChild->Start == pStored->Start) {
  2249. memcpy(pChild, pStored, pCache[i].Data.plVal->LengthUsed);
  2250. }
  2251. }
  2252. break;
  2253. default:
  2254. assert(FALSE);
  2255. return FALSE;
  2256. }
  2257. if (!(++gHits%50)) {
  2258. // dprint("%ld %% Hits\n", (gHits * 100) / gLook);
  2259. }
  2260. return TRUE;
  2261. }
  2262. #endif // USE_CACHE
  2263. HRESULT
  2264. #ifdef USE_CACHE
  2265. diaGetSymbolInfoEx(
  2266. #else
  2267. diaGetSymbolInfo(
  2268. #endif // USE_CACHE
  2269. IN HANDLE hProcess,
  2270. IN DWORD64 ModBase,
  2271. IN ULONG TypeId,
  2272. IN IMAGEHLP_SYMBOL_TYPE_INFO GetType,
  2273. OUT PVOID pInfo
  2274. )
  2275. {
  2276. assert(pInfo);
  2277. CComPtr <IDiaSymbol> pTypeSym;
  2278. if (!diaFindTypeSym(hProcess, ModBase, TypeId, &pTypeSym)) {
  2279. return E_INVALIDARG;
  2280. }
  2281. switch (GetType) {
  2282. case TI_GET_SYMTAG:
  2283. return diaGetSymTag(pTypeSym, (PULONG) pInfo);
  2284. break;
  2285. case TI_GET_SYMNAME:
  2286. return diaGetSymName(pTypeSym, (BSTR *) pInfo);
  2287. break;
  2288. case TI_GET_LENGTH:
  2289. return diaGetLength(pTypeSym, (PULONGLONG) pInfo);
  2290. break;
  2291. case TI_GET_TYPE:
  2292. case TI_GET_TYPEID:
  2293. return diaGetTypeId(pTypeSym, (PULONG) pInfo);
  2294. break;
  2295. case TI_GET_BASETYPE:
  2296. return diaGetBaseType(pTypeSym, (PULONG) pInfo);
  2297. break;
  2298. case TI_GET_ARRAYINDEXTYPEID:
  2299. return diaGetArrayIndexTypeId(pTypeSym, (PULONG) pInfo);
  2300. break;
  2301. case TI_FINDCHILDREN:
  2302. return diaFindChildren(pTypeSym, (TI_FINDCHILDREN_PARAMS *) pInfo);
  2303. case TI_GET_DATAKIND:
  2304. return diaGetDataKind(pTypeSym, (PULONG) pInfo);
  2305. break;
  2306. case TI_GET_ADDRESSOFFSET:
  2307. return diaGetAddressOffset(pTypeSym, (PULONG) pInfo);
  2308. break;
  2309. case TI_GET_OFFSET:
  2310. return diaGetOffset(pTypeSym, (PLONG) pInfo);
  2311. break;
  2312. case TI_GET_VALUE:
  2313. return diaGetValue(pTypeSym, (VARIANT *) pInfo);
  2314. break;
  2315. case TI_GET_COUNT:
  2316. return diaGetCount(pTypeSym, (PULONG) pInfo);
  2317. break;
  2318. case TI_GET_CHILDRENCOUNT:
  2319. return diaGetChildrenCount(pTypeSym, (PLONG) pInfo);
  2320. break;
  2321. case TI_GET_BITPOSITION:
  2322. return diaGetBitPosition(pTypeSym, (PULONG) pInfo);
  2323. break;
  2324. case TI_GET_VIRTUALBASECLASS:
  2325. return diaGetVirtualBaseClass(pTypeSym, (BOOL *) pInfo);
  2326. break;
  2327. case TI_GET_VIRTUALTABLESHAPEID:
  2328. return diaGetVirtualTableShapeId(pTypeSym, (PULONG) pInfo);
  2329. break;
  2330. case TI_GET_VIRTUALBASEPOINTEROFFSET:
  2331. return diaGetVirtualBasePointerOffset(pTypeSym, (PLONG) pInfo);
  2332. break;
  2333. case TI_GET_CLASSPARENTID:
  2334. return diaGetClassParentId(pTypeSym, (PULONG) pInfo);
  2335. break;
  2336. case TI_GET_NESTED:
  2337. return diaGetNested(pTypeSym, (PBOOL) pInfo);
  2338. break;
  2339. case TI_GET_SYMINDEX:
  2340. return diaGetSymIndexId(pTypeSym, (PULONG) pInfo);
  2341. break;
  2342. case TI_GET_LEXICALPARENT:
  2343. return diaGetLexicalParentId(pTypeSym, (PULONG) pInfo);
  2344. break;
  2345. case TI_GET_ADDRESS:
  2346. return diaGetSymAddress(pTypeSym, ModBase, (PULONG64) pInfo);
  2347. case TI_GET_THISADJUST:
  2348. return diaGetThisAdjust(pTypeSym, (PLONG) pInfo);
  2349. default:
  2350. return E_INVALIDARG;
  2351. }
  2352. }
  2353. #ifdef USE_CACHE
  2354. HRESULT
  2355. diaGetSymbolInfo(
  2356. IN HANDLE hProcess,
  2357. IN DWORD64 ModBase,
  2358. IN ULONG TypeId,
  2359. IN IMAGEHLP_SYMBOL_TYPE_INFO GetType,
  2360. OUT PVOID pInfo
  2361. )
  2362. {
  2363. PPROCESS_ENTRY ProcessEntry;
  2364. ProcessEntry = FindProcessEntry( hProcess );
  2365. if (!ProcessEntry) {
  2366. return E_INVALIDARG;
  2367. }
  2368. if (!diaLookupCache(ProcessEntry->DiaCache, ModBase, TypeId, GetType, pInfo)) {
  2369. HRESULT hr = diaGetSymbolInfoEx(hProcess, ModBase, TypeId, GetType, pInfo);
  2370. if (!hr) {
  2371. diaInsertInCache(ProcessEntry->DiaCache, ProcessEntry->DiaLargeData,
  2372. ModBase, TypeId, GetType, pInfo);
  2373. }
  2374. return hr;
  2375. }
  2376. return S_OK;
  2377. }
  2378. #endif // USE_CACHE
  2379. BOOL
  2380. diaGetTiForUDT(
  2381. PMODULE_ENTRY ModuleEntry,
  2382. LPSTR name,
  2383. PSYMBOL_INFO psi
  2384. )
  2385. {
  2386. BSTR wname=NULL;
  2387. PDIA pdia;
  2388. HRESULT hr;
  2389. ULONG celt;
  2390. if (!ModuleEntry) {
  2391. return FALSE;
  2392. }
  2393. pdia = (PDIA)ModuleEntry->dia;
  2394. if (!pdia)
  2395. return FALSE;
  2396. CComPtr< IDiaSymbol > idiaSymbols;
  2397. hr = pdia->session->get_globalScope(&idiaSymbols);
  2398. if (hr != S_OK)
  2399. return FALSE;
  2400. if (name) {
  2401. wname = AnsiToUnicode(name);
  2402. }
  2403. CComPtr< IDiaEnumSymbols > idiaEnum;
  2404. hr = idiaSymbols->findChildren(SymTagNull, wname, nsCaseSensitive, &idiaEnum);
  2405. if (hr == S_OK) {
  2406. CComPtr< IDiaSymbol > idiaSymbol;
  2407. if ((hr = idiaEnum->Next( 1, &idiaSymbol, &celt)) == S_OK && celt == 1) {
  2408. diaFillSymbolInfo(psi, ModuleEntry, idiaSymbol);
  2409. idiaSymbol->get_symIndexId(&psi->TypeIndex);
  2410. idiaSymbol = NULL;
  2411. }
  2412. }
  2413. MemFree(wname);
  2414. return hr == S_OK;
  2415. }
  2416. BOOL
  2417. diaEnumUDT(
  2418. PMODULE_ENTRY ModuleEntry,
  2419. LPSTR name,
  2420. PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,
  2421. PVOID context
  2422. )
  2423. {
  2424. BSTR wname=NULL;
  2425. PDIA pdia;
  2426. HRESULT hr;
  2427. ULONG celt;
  2428. CHAR buff[MAX_SYM_NAME + sizeof(SYMBOL_INFO)];
  2429. PSYMBOL_INFO psi=(PSYMBOL_INFO) &buff;
  2430. BOOL rc;
  2431. psi->MaxNameLen = MAX_SYM_NAME;
  2432. if (!ModuleEntry) {
  2433. return FALSE;
  2434. }
  2435. pdia = (PDIA)ModuleEntry->dia;
  2436. if (!pdia)
  2437. return FALSE;
  2438. CComPtr< IDiaSymbol > idiaSymbols;
  2439. hr = pdia->session->get_globalScope(&idiaSymbols);
  2440. if (hr != S_OK)
  2441. return FALSE;
  2442. if (name && *name) {
  2443. wname = AnsiToUnicode(name);
  2444. }
  2445. CComPtr< IDiaEnumSymbols > idiaEnum;
  2446. hr = idiaSymbols->findChildren(SymTagNull, wname, nsCaseSensitive, &idiaEnum);
  2447. if (hr == S_OK) {
  2448. CComPtr< IDiaSymbol > idiaSymbol;
  2449. while (SUCCEEDED(idiaEnum->Next( 1, &idiaSymbol, &celt)) && celt == 1) {
  2450. ULONG tag;
  2451. idiaSymbol->get_symTag(&tag);
  2452. switch (tag)
  2453. {
  2454. case SymTagEnum:
  2455. case SymTagTypedef:
  2456. case SymTagUDT:
  2457. if (EnumSymbolsCallback) {
  2458. diaFillSymbolInfo(psi, ModuleEntry, idiaSymbol);
  2459. idiaSymbol->get_symIndexId(&psi->TypeIndex);
  2460. rc = EnumSymbolsCallback(psi, 0, context);
  2461. if (!rc)
  2462. return S_OK;
  2463. }
  2464. break;
  2465. default:
  2466. break;
  2467. }
  2468. idiaSymbol = NULL;
  2469. }
  2470. }
  2471. MemFree(wname);
  2472. return hr == S_OK;
  2473. }
  2474. BOOL
  2475. diaGetFrameData(
  2476. IN HANDLE Process,
  2477. IN ULONGLONG Offset,
  2478. OUT IDiaFrameData** FrameData
  2479. )
  2480. {
  2481. PPROCESS_ENTRY ProcessEntry;
  2482. PDIA Dia;
  2483. PMODULE_ENTRY Mod;
  2484. ProcessEntry = FindProcessEntry(Process);
  2485. if (!ProcessEntry ||
  2486. !(Mod = GetModFromAddr(ProcessEntry, Offset)) ||
  2487. !(Dia = (PDIA)Mod->dia)) {
  2488. return FALSE;
  2489. }
  2490. if (Dia->framedata == NULL) {
  2491. CComPtr<IDiaEnumTables> EnumTables;
  2492. CComPtr<IDiaTable> FdTable;
  2493. VARIANT FdVar;
  2494. FdVar.vt = VT_BSTR;
  2495. FdVar.bstrVal = DiaTable_FrameData;
  2496. if (Dia->session->getEnumTables(&EnumTables) != S_OK ||
  2497. EnumTables->Item(FdVar, &FdTable) != S_OK ||
  2498. FdTable->QueryInterface(IID_IDiaEnumFrameData,
  2499. (void**)&Dia->framedata) != S_OK) {
  2500. return FALSE;
  2501. }
  2502. }
  2503. return Dia->framedata->frameByVA(Offset, FrameData) == S_OK;
  2504. }