Leaked source code of windows server 2003
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.

4920 lines
112 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // IDebugSymbols implementation.
  4. //
  5. // Copyright (C) Microsoft Corporation, 1999-2002.
  6. //
  7. //----------------------------------------------------------------------------
  8. #include "ntsdp.hpp"
  9. #define DBG_SYMGROUP_ENABLED 0
  10. // Special type status value that maps to E_UNEXPECTED.
  11. #define TYPE_E_UNEXPECTED 0xfefefefe
  12. BOOL
  13. GetAllModuleName(ULONG64 Base,
  14. PCHAR Name,
  15. ULONG SizeOfName)
  16. {
  17. ImageInfo* Image = g_Process->FindImageByOffset(Base, TRUE);
  18. if (Image)
  19. {
  20. return CopyString(Name, Image->m_ModuleName, SizeOfName);
  21. }
  22. return FALSE;
  23. }
  24. HRESULT
  25. ResultFromTypeStatus(ULONG Status)
  26. {
  27. switch(Status)
  28. {
  29. case NO_ERROR:
  30. return S_OK;
  31. case MEMORY_READ_ERROR:
  32. case EXIT_ON_CONTROLC:
  33. return E_FAIL;
  34. case SYMBOL_TYPE_INDEX_NOT_FOUND:
  35. case SYMBOL_TYPE_INFO_NOT_FOUND:
  36. return E_NOINTERFACE;
  37. case FIELDS_DID_NOT_MATCH:
  38. case NULL_SYM_DUMP_PARAM:
  39. case NULL_FIELD_NAME:
  40. case INCORRECT_VERSION_INFO:
  41. return E_INVALIDARG;
  42. case CANNOT_ALLOCATE_MEMORY:
  43. case INSUFFICIENT_SPACE_TO_COPY:
  44. return E_OUTOFMEMORY;
  45. case TYPE_E_UNEXPECTED:
  46. return E_UNEXPECTED;
  47. }
  48. return E_FAIL;
  49. }
  50. STDMETHODIMP
  51. DebugClient::GetSymbolOptions(
  52. THIS_
  53. OUT PULONG Options
  54. )
  55. {
  56. ENTER_ENGINE();
  57. *Options = g_SymOptions;
  58. LEAVE_ENGINE();
  59. return S_OK;
  60. }
  61. #define ALL_SYMBOL_OPTIONS \
  62. (SYMOPT_CASE_INSENSITIVE | \
  63. SYMOPT_UNDNAME | \
  64. SYMOPT_DEFERRED_LOADS | \
  65. SYMOPT_NO_CPP | \
  66. SYMOPT_LOAD_LINES | \
  67. SYMOPT_OMAP_FIND_NEAREST | \
  68. SYMOPT_LOAD_ANYTHING | \
  69. SYMOPT_IGNORE_CVREC | \
  70. SYMOPT_NO_UNQUALIFIED_LOADS | \
  71. SYMOPT_FAIL_CRITICAL_ERRORS | \
  72. SYMOPT_EXACT_SYMBOLS | \
  73. SYMOPT_ALLOW_ABSOLUTE_SYMBOLS | \
  74. SYMOPT_IGNORE_NT_SYMPATH | \
  75. SYMOPT_INCLUDE_32BIT_MODULES | \
  76. SYMOPT_PUBLICS_ONLY | \
  77. SYMOPT_NO_PUBLICS | \
  78. SYMOPT_AUTO_PUBLICS | \
  79. SYMOPT_NO_IMAGE_SEARCH | \
  80. SYMOPT_SECURE | \
  81. SYMOPT_NO_PROMPTS | \
  82. SYMOPT_DEBUG)
  83. STDMETHODIMP
  84. DebugClient::AddSymbolOptions(
  85. THIS_
  86. IN ULONG Options
  87. )
  88. {
  89. HRESULT Status;
  90. if (Options & ~ALL_SYMBOL_OPTIONS)
  91. {
  92. return E_INVALIDARG;
  93. }
  94. ENTER_ENGINE();
  95. Status = SetSymOptions(g_SymOptions | Options);
  96. LEAVE_ENGINE();
  97. return Status;
  98. }
  99. STDMETHODIMP
  100. DebugClient::RemoveSymbolOptions(
  101. THIS_
  102. IN ULONG Options
  103. )
  104. {
  105. HRESULT Status;
  106. if (Options & ~ALL_SYMBOL_OPTIONS)
  107. {
  108. return E_INVALIDARG;
  109. }
  110. ENTER_ENGINE();
  111. Status = SetSymOptions(g_SymOptions & ~Options);
  112. LEAVE_ENGINE();
  113. return Status;
  114. }
  115. STDMETHODIMP
  116. DebugClient::SetSymbolOptions(
  117. THIS_
  118. IN ULONG Options
  119. )
  120. {
  121. HRESULT Status;
  122. if (Options & ~ALL_SYMBOL_OPTIONS)
  123. {
  124. return E_INVALIDARG;
  125. }
  126. ENTER_ENGINE();
  127. Status = SetSymOptions(Options);
  128. LEAVE_ENGINE();
  129. return Status;
  130. }
  131. STDMETHODIMP
  132. DebugClient::GetNameByOffset(
  133. THIS_
  134. IN ULONG64 Offset,
  135. OUT OPTIONAL PSTR NameBuffer,
  136. IN ULONG NameBufferSize,
  137. OUT OPTIONAL PULONG NameSize,
  138. OUT OPTIONAL PULONG64 Displacement
  139. )
  140. {
  141. HRESULT Status;
  142. ENTER_ENGINE();
  143. if (!IS_CUR_MACHINE_ACCESSIBLE())
  144. {
  145. Status = E_UNEXPECTED;
  146. }
  147. else
  148. {
  149. char Sym[MAX_SYMBOL_LEN];
  150. ULONG64 _Disp;
  151. if (GetSymbol(Offset, Sym, DIMA(Sym), &_Disp))
  152. {
  153. Status = FillStringBuffer(Sym, 0, NameBuffer, NameBufferSize,
  154. NameSize);
  155. if (Displacement)
  156. {
  157. *Displacement = _Disp;
  158. }
  159. }
  160. else
  161. {
  162. Status = E_FAIL;
  163. }
  164. }
  165. LEAVE_ENGINE();
  166. return Status;
  167. }
  168. STDMETHODIMP
  169. DebugClient::GetOffsetByName(
  170. THIS_
  171. IN PCSTR Symbol,
  172. OUT PULONG64 Offset
  173. )
  174. {
  175. HRESULT Status;
  176. ENTER_ENGINE();
  177. ULONG Count;
  178. if (!IS_CUR_MACHINE_ACCESSIBLE())
  179. {
  180. Status = E_UNEXPECTED;
  181. }
  182. else if (Count = GetOffsetFromSym(g_Process, Symbol, Offset, NULL))
  183. {
  184. Status = Count > 1 ? S_FALSE : S_OK;
  185. }
  186. else
  187. {
  188. Status = E_FAIL;
  189. }
  190. LEAVE_ENGINE();
  191. return Status;
  192. }
  193. STDMETHODIMP
  194. DebugClient::GetNearNameByOffset(
  195. THIS_
  196. IN ULONG64 Offset,
  197. IN LONG Delta,
  198. OUT OPTIONAL PSTR NameBuffer,
  199. IN ULONG NameBufferSize,
  200. OUT OPTIONAL PULONG NameSize,
  201. OUT OPTIONAL PULONG64 Displacement
  202. )
  203. {
  204. HRESULT Status;
  205. ENTER_ENGINE();
  206. if (!IS_CUR_MACHINE_ACCESSIBLE())
  207. {
  208. Status = E_UNEXPECTED;
  209. }
  210. else
  211. {
  212. char Sym[MAX_SYMBOL_LEN];
  213. ULONG64 _Disp;
  214. if (GetNearSymbol(Offset, Sym, sizeof(Sym), &_Disp, Delta))
  215. {
  216. Status = FillStringBuffer(Sym, 0, NameBuffer, NameBufferSize,
  217. NameSize);
  218. if (Displacement)
  219. {
  220. *Displacement = _Disp;
  221. }
  222. }
  223. else
  224. {
  225. Status = E_NOINTERFACE;
  226. }
  227. }
  228. LEAVE_ENGINE();
  229. return Status;
  230. }
  231. STDMETHODIMP
  232. DebugClient::GetLineByOffset(
  233. THIS_
  234. IN ULONG64 Offset,
  235. OUT OPTIONAL PULONG Line,
  236. OUT OPTIONAL PSTR FileBuffer,
  237. IN ULONG FileBufferSize,
  238. OUT OPTIONAL PULONG FileSize,
  239. OUT OPTIONAL PULONG64 Displacement
  240. )
  241. {
  242. HRESULT Status;
  243. ENTER_ENGINE();
  244. if (!IS_CUR_MACHINE_ACCESSIBLE())
  245. {
  246. Status = E_UNEXPECTED;
  247. }
  248. else
  249. {
  250. IMAGEHLP_LINE64 DbgLine;
  251. ULONG Disp;
  252. if (GetLineFromAddr(g_Process, Offset, &DbgLine, &Disp))
  253. {
  254. if (Line != NULL)
  255. {
  256. *Line = DbgLine.LineNumber;
  257. }
  258. Status = FillStringBuffer(DbgLine.FileName, 0,
  259. FileBuffer, FileBufferSize, FileSize);
  260. if (Displacement != NULL)
  261. {
  262. *Displacement = Disp;
  263. }
  264. }
  265. else
  266. {
  267. Status = E_FAIL;
  268. }
  269. }
  270. LEAVE_ENGINE();
  271. return Status;
  272. }
  273. STDMETHODIMP
  274. DebugClient::GetOffsetByLine(
  275. THIS_
  276. IN ULONG Line,
  277. IN PCSTR File,
  278. OUT PULONG64 Offset
  279. )
  280. {
  281. HRESULT Status;
  282. ENTER_ENGINE();
  283. if (!IS_CUR_MACHINE_ACCESSIBLE())
  284. {
  285. Status = E_UNEXPECTED;
  286. }
  287. else
  288. {
  289. IMAGEHLP_LINE64 DbgLine;
  290. LONG Disp;
  291. DbgLine.SizeOfStruct = sizeof(DbgLine);
  292. if (SymGetLineFromName64(g_Process->m_SymHandle, NULL, (PSTR)File,
  293. Line, &Disp, &DbgLine))
  294. {
  295. *Offset = DbgLine.Address;
  296. Status = S_OK;
  297. }
  298. else
  299. {
  300. Status = E_FAIL;
  301. }
  302. }
  303. LEAVE_ENGINE();
  304. return Status;
  305. }
  306. STDMETHODIMP
  307. DebugClient::GetNumberModules(
  308. THIS_
  309. OUT PULONG Loaded,
  310. OUT PULONG Unloaded
  311. )
  312. {
  313. HRESULT Status;
  314. ENTER_ENGINE();
  315. if (g_Process == NULL)
  316. {
  317. Status = E_UNEXPECTED;
  318. }
  319. else
  320. {
  321. *Loaded = g_Process->m_NumImages;
  322. *Unloaded = g_Process->m_NumUnloadedModules;
  323. Status = S_OK;
  324. }
  325. LEAVE_ENGINE();
  326. return Status;
  327. }
  328. HRESULT
  329. GetUnloadedModuleByIndex(ULONG Index, UnloadedModuleInfo** IterRet,
  330. PSTR Name, PDEBUG_MODULE_PARAMETERS Params)
  331. {
  332. HRESULT Status;
  333. UnloadedModuleInfo* Iter;
  334. if ((Iter = g_Target->GetUnloadedModuleInfo()) == NULL)
  335. {
  336. return E_FAIL;
  337. }
  338. if ((Status = Iter->Initialize(g_Thread)) != S_OK)
  339. {
  340. return Status;
  341. }
  342. do
  343. {
  344. if ((Status = Iter->GetEntry(Name, Params)) != S_OK)
  345. {
  346. if (Status == S_FALSE)
  347. {
  348. return E_INVALIDARG;
  349. }
  350. return Status;
  351. }
  352. } while (Index-- > 0);
  353. if (IterRet != NULL)
  354. {
  355. *IterRet = Iter;
  356. }
  357. return S_OK;
  358. }
  359. STDMETHODIMP
  360. DebugClient::GetModuleByIndex(
  361. THIS_
  362. IN ULONG Index,
  363. OUT PULONG64 Base
  364. )
  365. {
  366. HRESULT Status;
  367. ENTER_ENGINE();
  368. if (g_Process == NULL)
  369. {
  370. Status = E_UNEXPECTED;
  371. }
  372. else if (Index >= g_Process->m_NumImages)
  373. {
  374. DEBUG_MODULE_PARAMETERS Params;
  375. if ((Status = GetUnloadedModuleByIndex
  376. (Index - g_Process->m_NumImages,
  377. NULL, NULL, &Params)) == S_OK)
  378. {
  379. *Base = Params.Base;
  380. }
  381. }
  382. else
  383. {
  384. *Base = g_Process->FindImageByIndex(Index)->m_BaseOfImage;
  385. Status = S_OK;
  386. }
  387. LEAVE_ENGINE();
  388. return Status;
  389. }
  390. STDMETHODIMP
  391. DebugClient::GetModuleByModuleName(
  392. THIS_
  393. IN PCSTR Name,
  394. IN ULONG StartIndex,
  395. OUT OPTIONAL PULONG Index,
  396. OUT OPTIONAL PULONG64 Base
  397. )
  398. {
  399. HRESULT Status;
  400. ENTER_ENGINE();
  401. if (g_Process == NULL)
  402. {
  403. Status = E_UNEXPECTED;
  404. }
  405. else
  406. {
  407. ULONG Idx = 0;
  408. Status = E_NOINTERFACE;
  409. ImageInfo* Image = g_Process->m_ImageHead;
  410. while (Image != NULL)
  411. {
  412. if (StartIndex == 0 &&
  413. !_strcmpi(Name, Image->m_ModuleName))
  414. {
  415. if (Index != NULL)
  416. {
  417. *Index = Idx;
  418. }
  419. if (Base != NULL)
  420. {
  421. *Base = Image->m_BaseOfImage;
  422. }
  423. Status = S_OK;
  424. break;
  425. }
  426. Image = Image->m_Next;
  427. Idx++;
  428. if (StartIndex > 0)
  429. {
  430. StartIndex--;
  431. }
  432. }
  433. if (Image == NULL)
  434. {
  435. UnloadedModuleInfo* Iter;
  436. char UnlName[MAX_INFO_UNLOADED_NAME];
  437. DEBUG_MODULE_PARAMETERS Params;
  438. Status = GetUnloadedModuleByIndex(StartIndex, &Iter, UnlName,
  439. &Params);
  440. for (;;)
  441. {
  442. if (Status == S_FALSE || Status == E_INVALIDARG)
  443. {
  444. Status = E_NOINTERFACE;
  445. break;
  446. }
  447. else if (Status != S_OK)
  448. {
  449. break;
  450. }
  451. if (!_strcmpi(Name, UnlName))
  452. {
  453. if (Index != NULL)
  454. {
  455. *Index = Idx;
  456. }
  457. if (Base != NULL)
  458. {
  459. *Base = Params.Base;
  460. }
  461. Status = S_OK;
  462. break;
  463. }
  464. Status = Iter->GetEntry(UnlName, &Params);
  465. Idx++;
  466. }
  467. }
  468. }
  469. LEAVE_ENGINE();
  470. return Status;
  471. }
  472. STDMETHODIMP
  473. DebugClient::GetModuleByOffset(
  474. THIS_
  475. IN ULONG64 Offset,
  476. IN ULONG StartIndex,
  477. OUT OPTIONAL PULONG Index,
  478. OUT OPTIONAL PULONG64 Base
  479. )
  480. {
  481. HRESULT Status;
  482. ENTER_ENGINE();
  483. if (g_Process == NULL)
  484. {
  485. Status = E_UNEXPECTED;
  486. }
  487. else
  488. {
  489. ULONG Idx = 0;
  490. Status = E_NOINTERFACE;
  491. ImageInfo* Image = g_Process->m_ImageHead;
  492. while (Image != NULL)
  493. {
  494. if (StartIndex == 0 &&
  495. Offset >= Image->m_BaseOfImage &&
  496. Offset < Image->m_BaseOfImage + Image->m_SizeOfImage)
  497. {
  498. if (Index != NULL)
  499. {
  500. *Index = Idx;
  501. }
  502. if (Base != NULL)
  503. {
  504. *Base = Image->m_BaseOfImage;
  505. }
  506. Status = S_OK;
  507. break;
  508. }
  509. Image = Image->m_Next;
  510. Idx++;
  511. if (StartIndex > 0)
  512. {
  513. StartIndex--;
  514. }
  515. }
  516. if (Image == NULL)
  517. {
  518. UnloadedModuleInfo* Iter;
  519. DEBUG_MODULE_PARAMETERS Params;
  520. Status = GetUnloadedModuleByIndex(StartIndex, &Iter, NULL,
  521. &Params);
  522. for (;;)
  523. {
  524. if (Status == S_FALSE || Status == E_INVALIDARG)
  525. {
  526. Status = E_NOINTERFACE;
  527. break;
  528. }
  529. else if (Status != S_OK)
  530. {
  531. break;
  532. }
  533. if (Offset >= Params.Base &&
  534. Offset < Params.Base + Params.Size)
  535. {
  536. if (Index != NULL)
  537. {
  538. *Index = Idx;
  539. }
  540. if (Base != NULL)
  541. {
  542. *Base = Params.Base;
  543. }
  544. Status = S_OK;
  545. break;
  546. }
  547. Status = Iter->GetEntry(NULL, &Params);
  548. Idx++;
  549. }
  550. }
  551. }
  552. LEAVE_ENGINE();
  553. return Status;
  554. }
  555. STDMETHODIMP
  556. DebugClient::GetModuleNames(
  557. THIS_
  558. IN ULONG Index,
  559. IN ULONG64 Base,
  560. OUT OPTIONAL PSTR ImageNameBuffer,
  561. IN ULONG ImageNameBufferSize,
  562. OUT OPTIONAL PULONG ImageNameSize,
  563. OUT OPTIONAL PSTR ModuleNameBuffer,
  564. IN ULONG ModuleNameBufferSize,
  565. OUT OPTIONAL PULONG ModuleNameSize,
  566. OUT OPTIONAL PSTR LoadedImageNameBuffer,
  567. IN ULONG LoadedImageNameBufferSize,
  568. OUT OPTIONAL PULONG LoadedImageNameSize
  569. )
  570. {
  571. HRESULT Status;
  572. ENTER_ENGINE();
  573. if (g_Process == NULL)
  574. {
  575. Status = E_UNEXPECTED;
  576. }
  577. else
  578. {
  579. ULONG Idx = 0;
  580. Status = E_NOINTERFACE;
  581. ImageInfo* Image = g_Process->m_ImageHead;
  582. while (Image != NULL)
  583. {
  584. if ((Index != DEBUG_ANY_ID && Idx == Index) ||
  585. (Index == DEBUG_ANY_ID && Base == Image->m_BaseOfImage))
  586. {
  587. IMAGEHLP_MODULE64 ModInfo;
  588. ModInfo.SizeOfStruct = sizeof(ModInfo);
  589. if (!SymGetModuleInfo64(g_Process->m_SymHandle,
  590. Image->m_BaseOfImage, &ModInfo))
  591. {
  592. Status = WIN32_LAST_STATUS();
  593. break;
  594. }
  595. Status = FillStringBuffer(Image->m_ImagePath, 0,
  596. ImageNameBuffer,
  597. ImageNameBufferSize,
  598. ImageNameSize);
  599. if (FillStringBuffer(Image->m_ModuleName, 0,
  600. ModuleNameBuffer,
  601. ModuleNameBufferSize,
  602. ModuleNameSize) == S_FALSE)
  603. {
  604. Status = S_FALSE;
  605. }
  606. if (FillStringBuffer(ModInfo.LoadedImageName, 0,
  607. LoadedImageNameBuffer,
  608. LoadedImageNameBufferSize,
  609. LoadedImageNameSize) == S_FALSE)
  610. {
  611. Status = S_FALSE;
  612. }
  613. break;
  614. }
  615. Image = Image->m_Next;
  616. Idx++;
  617. }
  618. if (Image == NULL)
  619. {
  620. UnloadedModuleInfo* Iter;
  621. char UnlName[MAX_INFO_UNLOADED_NAME];
  622. DEBUG_MODULE_PARAMETERS Params;
  623. ULONG StartIndex = 0;
  624. if (Index != DEBUG_ANY_ID)
  625. {
  626. // If the index was already hit we
  627. // shouldn't be here.
  628. DBG_ASSERT(Index >= Idx);
  629. StartIndex = Index - Idx;
  630. }
  631. Status = GetUnloadedModuleByIndex(StartIndex, &Iter, UnlName,
  632. &Params);
  633. Idx += StartIndex;
  634. for (;;)
  635. {
  636. if (Status == S_FALSE || Status == E_INVALIDARG)
  637. {
  638. Status = E_NOINTERFACE;
  639. break;
  640. }
  641. else if (Status != S_OK)
  642. {
  643. break;
  644. }
  645. if ((Index != DEBUG_ANY_ID && Idx == Index) ||
  646. (Index == DEBUG_ANY_ID && Base == Params.Base))
  647. {
  648. Status = FillStringBuffer(UnlName, 0,
  649. ImageNameBuffer,
  650. ImageNameBufferSize,
  651. ImageNameSize);
  652. FillStringBuffer(NULL, 0,
  653. ModuleNameBuffer,
  654. ModuleNameBufferSize,
  655. ModuleNameSize);
  656. FillStringBuffer(NULL, 0,
  657. LoadedImageNameBuffer,
  658. LoadedImageNameBufferSize,
  659. LoadedImageNameSize);
  660. break;
  661. }
  662. Status = Iter->GetEntry(UnlName, &Params);
  663. Idx++;
  664. }
  665. }
  666. }
  667. LEAVE_ENGINE();
  668. return Status;
  669. }
  670. STDMETHODIMP
  671. DebugClient::GetModuleParameters(
  672. THIS_
  673. IN ULONG Count,
  674. IN OPTIONAL /* size_is(Count) */ PULONG64 Bases,
  675. IN ULONG Start,
  676. OUT /* size_is(Count) */ PDEBUG_MODULE_PARAMETERS Params
  677. )
  678. {
  679. HRESULT Status;
  680. ENTER_ENGINE();
  681. UnloadedModuleInfo* Iter;
  682. if (g_Process == NULL)
  683. {
  684. Status = E_UNEXPECTED;
  685. }
  686. else if (Bases != NULL)
  687. {
  688. Status = S_OK;
  689. while (Count-- > 0)
  690. {
  691. ImageInfo* Image = g_Process->m_ImageHead;
  692. while (Image != NULL)
  693. {
  694. if (*Bases == Image->m_BaseOfImage)
  695. {
  696. Image->FillModuleParameters(Params);
  697. break;
  698. }
  699. Image = Image->m_Next;
  700. }
  701. if (Image == NULL)
  702. {
  703. Status = E_NOINTERFACE;
  704. Iter = g_Target->GetUnloadedModuleInfo();
  705. if (Iter != NULL &&
  706. Iter->Initialize(g_Thread) == S_OK)
  707. {
  708. while (Iter->GetEntry(NULL, Params) == S_OK)
  709. {
  710. if (*Bases == Params->Base)
  711. {
  712. Status = S_OK;
  713. break;
  714. }
  715. }
  716. }
  717. if (Status != S_OK)
  718. {
  719. ZeroMemory(Params, sizeof(*Params));
  720. Params->Base = DEBUG_INVALID_OFFSET;
  721. }
  722. }
  723. Bases++;
  724. Params++;
  725. }
  726. }
  727. else
  728. {
  729. ULONG i, End;
  730. HRESULT SingleStatus;
  731. Status = S_OK;
  732. i = Start;
  733. End = Start + Count;
  734. if (i < g_Process->m_NumImages)
  735. {
  736. ImageInfo* Image = g_Process->FindImageByIndex(i);
  737. while (i < g_Process->m_NumImages && i < End)
  738. {
  739. Image->FillModuleParameters(Params);
  740. Image = Image->m_Next;
  741. Params++;
  742. i++;
  743. }
  744. }
  745. if (i < End)
  746. {
  747. DEBUG_MODULE_PARAMETERS Param;
  748. SingleStatus = GetUnloadedModuleByIndex
  749. (i - g_Process->m_NumImages,
  750. &Iter, NULL, &Param);
  751. if (SingleStatus != S_OK)
  752. {
  753. Iter = NULL;
  754. }
  755. while (i < End)
  756. {
  757. if (SingleStatus != S_OK)
  758. {
  759. ZeroMemory(Params, sizeof(*Params));
  760. Params->Base = DEBUG_INVALID_OFFSET;
  761. Status = SingleStatus;
  762. }
  763. else
  764. {
  765. *Params = Param;
  766. }
  767. Params++;
  768. if (Iter != NULL)
  769. {
  770. SingleStatus = Iter->GetEntry(NULL, &Param);
  771. if (SingleStatus == S_FALSE)
  772. {
  773. SingleStatus = E_INVALIDARG;
  774. }
  775. }
  776. i++;
  777. }
  778. }
  779. }
  780. LEAVE_ENGINE();
  781. return Status;
  782. }
  783. STDMETHODIMP
  784. DebugClient::GetSymbolModule(
  785. THIS_
  786. IN PCSTR Symbol,
  787. OUT PULONG64 Base
  788. )
  789. {
  790. HRESULT Status;
  791. ENTER_ENGINE();
  792. if (g_Process == NULL)
  793. {
  794. Status = E_UNEXPECTED;
  795. }
  796. else
  797. {
  798. PCSTR ModEnd;
  799. ULONG Len;
  800. ModEnd = strchr(Symbol, '!');
  801. if (ModEnd == NULL)
  802. {
  803. Status = E_INVALIDARG;
  804. }
  805. else if (*(ModEnd+1) != '\0')
  806. {
  807. SYM_DUMP_PARAM_EX Param =
  808. {
  809. sizeof(Param), (PUCHAR)Symbol, DBG_DUMP_NO_PRINT, 0,
  810. NULL, NULL, NULL, 0, NULL
  811. };
  812. ULONG TypeStatus;
  813. TYPES_INFO TypeInfo;
  814. ZeroMemory(&TypeInfo, sizeof(TypeInfo));
  815. TypeStatus = TypeInfoFound(g_Process->m_SymHandle,
  816. g_Process->m_ImageHead,
  817. &Param, &TypeInfo);
  818. if (TypeStatus == NO_ERROR)
  819. {
  820. *Base = TypeInfo.ModBaseAddress;
  821. }
  822. Status = ResultFromTypeStatus(TypeStatus);
  823. }
  824. else
  825. {
  826. ImageInfo* Image;
  827. Status = E_NOINTERFACE;
  828. Len = (ULONG)(ModEnd - Symbol);
  829. for (Image = g_Process->m_ImageHead;
  830. Image != NULL;
  831. Image = Image->m_Next)
  832. {
  833. if (strlen(Image->m_ModuleName) == Len &&
  834. !_memicmp(Symbol, Image->m_ModuleName, Len))
  835. {
  836. *Base = Image->m_BaseOfImage;
  837. Status = S_OK;
  838. break;
  839. }
  840. }
  841. }
  842. }
  843. LEAVE_ENGINE();
  844. return Status;
  845. }
  846. STDMETHODIMP
  847. DebugClient::GetTypeName(
  848. THIS_
  849. IN ULONG64 Module,
  850. IN ULONG TypeId,
  851. OUT OPTIONAL PSTR NameBuffer,
  852. IN ULONG NameBufferSize,
  853. OUT OPTIONAL PULONG NameSize
  854. )
  855. {
  856. HRESULT Status;
  857. ENTER_ENGINE();
  858. if (!IS_CUR_MACHINE_ACCESSIBLE())
  859. {
  860. Status = E_UNEXPECTED;
  861. }
  862. else
  863. {
  864. TYPES_INFO TypeInfo;
  865. ANSI_STRING TypeName;
  866. char TypeString[MAX_NAME];
  867. ZeroMemory(&TypeInfo, sizeof(TypeInfo));
  868. TypeInfo.TypeIndex = TypeId;
  869. TypeInfo.hProcess = g_Process->m_SymHandle;
  870. TypeInfo.ModBaseAddress = Module;
  871. TypeName.Buffer = TypeString;
  872. TypeName.Length = sizeof(TypeString);
  873. TypeName.MaximumLength = sizeof(TypeString);
  874. Status = ::GetTypeName(NULL, &TypeInfo, &TypeName);
  875. if (Status == S_OK)
  876. {
  877. Status = FillStringBuffer(TypeName.Buffer, TypeName.Length,
  878. NameBuffer, NameBufferSize, NameSize);
  879. }
  880. }
  881. LEAVE_ENGINE();
  882. return Status;
  883. }
  884. STDMETHODIMP
  885. DebugClient::GetConstantName(
  886. THIS_
  887. IN ULONG64 Module,
  888. IN ULONG TypeId,
  889. IN ULONG64 Value,
  890. OUT OPTIONAL PSTR NameBuffer,
  891. IN ULONG NameBufferSize,
  892. OUT OPTIONAL PULONG NameSize
  893. )
  894. {
  895. HRESULT Status;
  896. ENTER_ENGINE();
  897. if (!IS_CUR_MACHINE_ACCESSIBLE())
  898. {
  899. Status = E_UNEXPECTED;
  900. }
  901. else
  902. {
  903. TYPES_INFO TypeInfo;
  904. ANSI_STRING TypeName;
  905. char TypeString[MAX_NAME];
  906. ZeroMemory(&TypeInfo, sizeof(TypeInfo));
  907. TypeInfo.TypeIndex = TypeId;
  908. TypeInfo.hProcess = g_Process->m_SymHandle;
  909. TypeInfo.ModBaseAddress = Module;
  910. TypeInfo.Flag = SYMFLAG_VALUEPRESENT;
  911. TypeInfo.Value = Value;
  912. TypeName.Buffer = TypeString;
  913. TypeName.Length = sizeof(TypeString);
  914. TypeName.MaximumLength = sizeof(TypeString);
  915. Status = ::GetTypeName(NULL, &TypeInfo, &TypeName);
  916. if (Status == S_OK)
  917. {
  918. Status = FillStringBuffer(TypeName.Buffer, TypeName.Length,
  919. NameBuffer, NameBufferSize, NameSize);
  920. }
  921. }
  922. LEAVE_ENGINE();
  923. return Status;
  924. }
  925. typedef struct _COPY_FIELD_NAME_CONTEXT {
  926. ULONG Called;
  927. ULONG IndexToMatch;
  928. PSTR NameBuffer;
  929. ULONG NameBufferSize;
  930. PULONG NameSize;
  931. HRESULT Status;
  932. } COPY_FIELD_NAME_CONTEXT;
  933. ULONG
  934. CopyFieldName(
  935. PFIELD_INFO_EX pField,
  936. PVOID Context
  937. )
  938. {
  939. COPY_FIELD_NAME_CONTEXT* pInfo = (COPY_FIELD_NAME_CONTEXT *) Context;
  940. if (pInfo->Called++ == pInfo->IndexToMatch)
  941. {
  942. pInfo->Status = FillStringBuffer((PSTR) pField->fName, strlen((PCHAR) pField->fName)+1,
  943. pInfo->NameBuffer, pInfo->NameBufferSize, pInfo->NameSize);
  944. return FALSE;
  945. }
  946. return TRUE;
  947. }
  948. STDMETHODIMP
  949. DebugClient::GetFieldName(
  950. THIS_
  951. IN ULONG64 Module,
  952. IN ULONG TypeId,
  953. IN ULONG FieldIndex,
  954. OUT OPTIONAL PSTR NameBuffer,
  955. IN ULONG NameBufferSize,
  956. OUT OPTIONAL PULONG NameSize
  957. )
  958. {
  959. HRESULT Status;
  960. ENTER_ENGINE();
  961. if (!IS_CUR_MACHINE_ACCESSIBLE())
  962. {
  963. Status = E_UNEXPECTED;
  964. }
  965. else
  966. {
  967. ULONG TypeStatus;
  968. COPY_FIELD_NAME_CONTEXT FieldInfo =
  969. {
  970. 0, FieldIndex, NameBuffer, NameBufferSize,
  971. NameSize, E_INVALIDARG
  972. };
  973. SYM_DUMP_PARAM_EX Param =
  974. {
  975. sizeof(Param), NULL, DBG_DUMP_NO_PRINT | DBG_DUMP_CALL_FOR_EACH, 0,
  976. NULL, &FieldInfo, &CopyFieldName, 0, NULL
  977. };
  978. TYPES_INFO TypeInfo;
  979. ZeroMemory(&TypeInfo, sizeof(TypeInfo));
  980. TypeInfo.hProcess = g_Process->m_SymHandle;
  981. TypeInfo.ModBaseAddress = Module;
  982. TypeInfo.TypeIndex = TypeId;
  983. DumpType(&TypeInfo, &Param, &TypeStatus);
  984. if (TypeStatus == NO_ERROR)
  985. {
  986. Status = FieldInfo.Status;
  987. } else
  988. {
  989. Status = ResultFromTypeStatus(TypeStatus);
  990. }
  991. }
  992. LEAVE_ENGINE();
  993. return Status;
  994. }
  995. #define ALL_TYPE_OPTIONS (DEBUG_TYPEOPTS_UNICODE_DISPLAY | DEBUG_TYPEOPTS_LONGSTATUS_DISPLAY)
  996. STDMETHODIMP
  997. DebugClient::GetTypeOptions(
  998. THIS_
  999. OUT PULONG Options
  1000. )
  1001. {
  1002. ENTER_ENGINE();
  1003. *Options = 0;
  1004. *Options |= g_EnableUnicode ? DEBUG_TYPEOPTS_UNICODE_DISPLAY : 0;
  1005. *Options |= g_EnableLongStatus ? DEBUG_TYPEOPTS_LONGSTATUS_DISPLAY : 0;
  1006. LEAVE_ENGINE();
  1007. return S_OK;
  1008. }
  1009. STDMETHODIMP
  1010. DebugClient::SetTypeOptions(
  1011. THIS_
  1012. IN ULONG Options
  1013. )
  1014. {
  1015. if (Options & ~ALL_TYPE_OPTIONS)
  1016. {
  1017. return E_INVALIDARG;
  1018. }
  1019. ENTER_ENGINE();
  1020. g_EnableUnicode = Options & DEBUG_TYPEOPTS_UNICODE_DISPLAY;
  1021. g_EnableLongStatus = Options & DEBUG_TYPEOPTS_LONGSTATUS_DISPLAY;
  1022. g_TypeOptions = Options;
  1023. NotifyChangeSymbolState(DEBUG_CSS_TYPE_OPTIONS, 0, NULL);
  1024. LEAVE_ENGINE();
  1025. return S_OK;
  1026. }
  1027. STDMETHODIMP
  1028. DebugClient::AddTypeOptions(
  1029. THIS_
  1030. IN ULONG Options
  1031. )
  1032. {
  1033. if (Options & ~ALL_TYPE_OPTIONS)
  1034. {
  1035. return E_INVALIDARG;
  1036. }
  1037. ENTER_ENGINE();
  1038. if (Options & DEBUG_TYPEOPTS_UNICODE_DISPLAY)
  1039. {
  1040. g_EnableUnicode = TRUE;
  1041. }
  1042. if (Options & DEBUG_TYPEOPTS_LONGSTATUS_DISPLAY)
  1043. {
  1044. g_EnableLongStatus = TRUE;
  1045. }
  1046. g_TypeOptions |= Options;
  1047. NotifyChangeSymbolState(DEBUG_CSS_TYPE_OPTIONS, 0, NULL);
  1048. LEAVE_ENGINE();
  1049. return S_OK;
  1050. }
  1051. STDMETHODIMP
  1052. DebugClient::RemoveTypeOptions(
  1053. THIS_
  1054. IN ULONG Options
  1055. )
  1056. {
  1057. if (Options & ~ALL_TYPE_OPTIONS)
  1058. {
  1059. return E_INVALIDARG;
  1060. }
  1061. ENTER_ENGINE();
  1062. if (Options & DEBUG_TYPEOPTS_UNICODE_DISPLAY)
  1063. {
  1064. g_EnableUnicode = FALSE;
  1065. }
  1066. if (Options & DEBUG_TYPEOPTS_LONGSTATUS_DISPLAY)
  1067. {
  1068. g_EnableLongStatus = FALSE;
  1069. }
  1070. g_TypeOptions &= ~Options;
  1071. NotifyChangeSymbolState(DEBUG_CSS_TYPE_OPTIONS, 0, NULL);
  1072. LEAVE_ENGINE();
  1073. return S_OK;
  1074. }
  1075. STDMETHODIMP
  1076. DebugClient::GetTypeId(
  1077. THIS_
  1078. IN ULONG64 Module,
  1079. IN PCSTR Name,
  1080. OUT PULONG TypeId
  1081. )
  1082. {
  1083. ULONG TypeStatus;
  1084. ENTER_ENGINE();
  1085. if (!IS_CUR_MACHINE_ACCESSIBLE())
  1086. {
  1087. TypeStatus = TYPE_E_UNEXPECTED;
  1088. }
  1089. else
  1090. {
  1091. SYM_DUMP_PARAM_EX Param =
  1092. {
  1093. sizeof(Param), (PUCHAR)Name, DBG_DUMP_NO_PRINT, 0,
  1094. NULL, NULL, NULL, 0, NULL
  1095. };
  1096. TYPES_INFO TypeInfo;
  1097. PCHAR QualName;
  1098. TypeStatus = CANNOT_ALLOCATE_MEMORY;
  1099. QualName = (PCHAR) malloc(strlen(Name) + 32);
  1100. if (QualName)
  1101. {
  1102. if (!strchr(Name, '!'))
  1103. {
  1104. if (GetAllModuleName(Module, QualName, 30))
  1105. {
  1106. strcat(QualName, "!");
  1107. }
  1108. }
  1109. else // Already qualified name
  1110. {
  1111. *QualName = 0;
  1112. }
  1113. strcat(QualName, Name);
  1114. TypeStatus = SYMBOL_TYPE_INFO_NOT_FOUND;
  1115. Param.sName = (PUCHAR) QualName;
  1116. ZeroMemory(&TypeInfo, sizeof(TypeInfo));
  1117. TypeStatus = TypeInfoFound(g_Process->m_SymHandle,
  1118. g_Process->m_ImageHead,
  1119. &Param, &TypeInfo);
  1120. if (TypeStatus == NO_ERROR)
  1121. {
  1122. *TypeId = TypeInfo.TypeIndex;
  1123. }
  1124. }
  1125. }
  1126. LEAVE_ENGINE();
  1127. return ResultFromTypeStatus(TypeStatus);
  1128. }
  1129. STDMETHODIMP
  1130. DebugClient::GetTypeSize(
  1131. THIS_
  1132. IN ULONG64 Module,
  1133. IN ULONG TypeId,
  1134. OUT PULONG Size
  1135. )
  1136. {
  1137. ULONG TypeStatus;
  1138. ENTER_ENGINE();
  1139. if (!IS_CUR_MACHINE_ACCESSIBLE())
  1140. {
  1141. TypeStatus = TYPE_E_UNEXPECTED;
  1142. }
  1143. else
  1144. {
  1145. SYM_DUMP_PARAM_EX Param =
  1146. {
  1147. sizeof(Param), NULL,
  1148. DBG_DUMP_NO_PRINT | DBG_DUMP_GET_SIZE_ONLY, 0,
  1149. NULL, NULL, NULL, 0, NULL
  1150. };
  1151. TYPES_INFO TypeInfo;
  1152. ZeroMemory(&TypeInfo, sizeof(TypeInfo));
  1153. TypeInfo.hProcess = g_Process->m_SymHandle;
  1154. TypeInfo.ModBaseAddress = Module;
  1155. TypeInfo.TypeIndex = TypeId;
  1156. *Size = DumpType(&TypeInfo, &Param, &TypeStatus);
  1157. }
  1158. LEAVE_ENGINE();
  1159. return ResultFromTypeStatus(TypeStatus);
  1160. }
  1161. STDMETHODIMP
  1162. DebugClient::GetFieldOffset(
  1163. THIS_
  1164. IN ULONG64 Module,
  1165. IN ULONG TypeId,
  1166. IN PCSTR Field,
  1167. OUT PULONG Offset
  1168. )
  1169. {
  1170. ULONG TypeStatus;
  1171. ENTER_ENGINE();
  1172. if (!IS_CUR_MACHINE_ACCESSIBLE())
  1173. {
  1174. TypeStatus = TYPE_E_UNEXPECTED;
  1175. }
  1176. else
  1177. {
  1178. FIELD_INFO_EX FieldInfo =
  1179. {
  1180. (PUCHAR)Field, NULL, 0, DBG_DUMP_FIELD_FULL_NAME, 0, NULL
  1181. };
  1182. SYM_DUMP_PARAM_EX Param =
  1183. {
  1184. sizeof(Param), NULL, DBG_DUMP_NO_PRINT, 0,
  1185. NULL, NULL, NULL, 1, &FieldInfo
  1186. };
  1187. TYPES_INFO TypeInfo;
  1188. ZeroMemory(&TypeInfo, sizeof(TypeInfo));
  1189. TypeInfo.hProcess = g_Process->m_SymHandle;
  1190. TypeInfo.ModBaseAddress = Module;
  1191. TypeInfo.TypeIndex = TypeId;
  1192. DumpType(&TypeInfo, &Param, &TypeStatus);
  1193. if (TypeStatus == NO_ERROR)
  1194. {
  1195. *Offset = (ULONG)FieldInfo.address;
  1196. }
  1197. }
  1198. LEAVE_ENGINE();
  1199. return ResultFromTypeStatus(TypeStatus);
  1200. }
  1201. STDMETHODIMP
  1202. DebugClient::GetSymbolTypeId(
  1203. THIS_
  1204. IN PCSTR Symbol,
  1205. OUT PULONG TypeId,
  1206. OUT OPTIONAL PULONG64 Module
  1207. )
  1208. {
  1209. ULONG TypeStatus;
  1210. ENTER_ENGINE();
  1211. if (!IS_CUR_MACHINE_ACCESSIBLE())
  1212. {
  1213. TypeStatus = TYPE_E_UNEXPECTED;
  1214. }
  1215. else
  1216. {
  1217. TYPES_INFO_ALL TypeInfo;
  1218. ZeroMemory(&TypeInfo, sizeof(TypeInfo));
  1219. TypeStatus = !GetExpressionTypeInfo((PCHAR) Symbol, &TypeInfo);
  1220. if (TypeStatus == NO_ERROR)
  1221. {
  1222. *TypeId = TypeInfo.TypeIndex;
  1223. if (Module != NULL)
  1224. {
  1225. *Module = TypeInfo.Module;
  1226. }
  1227. }
  1228. }
  1229. LEAVE_ENGINE();
  1230. return ResultFromTypeStatus(TypeStatus);
  1231. }
  1232. STDMETHODIMP
  1233. DebugClient::GetOffsetTypeId(
  1234. THIS_
  1235. IN ULONG64 Offset,
  1236. OUT PULONG TypeId,
  1237. OUT OPTIONAL PULONG64 Module
  1238. )
  1239. {
  1240. HRESULT Status;
  1241. ENTER_ENGINE();
  1242. if (!IS_CUR_MACHINE_ACCESSIBLE())
  1243. {
  1244. Status = E_UNEXPECTED;
  1245. }
  1246. else
  1247. {
  1248. SYM_DUMP_PARAM_EX Param =
  1249. {
  1250. sizeof(Param), NULL, DBG_DUMP_NO_PRINT, Offset,
  1251. NULL, NULL, NULL, 0, NULL
  1252. };
  1253. ULONG TypeStatus;
  1254. TYPES_INFO TypeInfo;
  1255. ZeroMemory(&TypeInfo, sizeof(TypeInfo));
  1256. TypeStatus = TypeInfoFound(g_Process->m_SymHandle,
  1257. g_Process->m_ImageHead,
  1258. &Param, &TypeInfo);
  1259. if (TypeStatus == NO_ERROR)
  1260. {
  1261. *TypeId = TypeInfo.TypeIndex;
  1262. if (Module != NULL)
  1263. {
  1264. *Module = TypeInfo.ModBaseAddress;
  1265. }
  1266. }
  1267. Status = ResultFromTypeStatus(TypeStatus);
  1268. }
  1269. LEAVE_ENGINE();
  1270. return Status;
  1271. }
  1272. STDMETHODIMP
  1273. DebugClient::ReadTypedDataVirtual(
  1274. THIS_
  1275. IN ULONG64 Offset,
  1276. IN ULONG64 Module,
  1277. IN ULONG TypeId,
  1278. OUT PVOID Buffer,
  1279. IN ULONG BufferSize,
  1280. OUT OPTIONAL PULONG BytesRead
  1281. )
  1282. {
  1283. HRESULT Status;
  1284. ULONG Size;
  1285. if ((Status = GetTypeSize(Module, TypeId, &Size)) != S_OK)
  1286. {
  1287. return Status;
  1288. }
  1289. if (Size < BufferSize)
  1290. {
  1291. BufferSize = Size;
  1292. }
  1293. if ((Status = ReadVirtual(Offset, Buffer, BufferSize,
  1294. BytesRead)) != S_OK)
  1295. {
  1296. return Status;
  1297. }
  1298. return Size > BufferSize ? S_FALSE : S_OK;
  1299. }
  1300. STDMETHODIMP
  1301. DebugClient::WriteTypedDataVirtual(
  1302. THIS_
  1303. IN ULONG64 Offset,
  1304. IN ULONG64 Module,
  1305. IN ULONG TypeId,
  1306. IN PVOID Buffer,
  1307. IN ULONG BufferSize,
  1308. OUT OPTIONAL PULONG BytesWritten
  1309. )
  1310. {
  1311. HRESULT Status;
  1312. ULONG Size;
  1313. if ((Status = GetTypeSize(Module, TypeId, &Size)) != S_OK)
  1314. {
  1315. return Status;
  1316. }
  1317. if (Size < BufferSize)
  1318. {
  1319. BufferSize = Size;
  1320. }
  1321. if ((Status = WriteVirtual(Offset, Buffer, BufferSize,
  1322. BytesWritten)) != S_OK)
  1323. {
  1324. return Status;
  1325. }
  1326. return Size > BufferSize ? S_FALSE : S_OK;
  1327. }
  1328. #define ALL_OUTPUT_TYPE_FLAGS \
  1329. (DEBUG_OUTTYPE_NO_INDENT | \
  1330. DEBUG_OUTTYPE_NO_OFFSET | \
  1331. DEBUG_OUTTYPE_VERBOSE | \
  1332. DEBUG_OUTTYPE_COMPACT_OUTPUT | \
  1333. DEBUG_OUTTYPE_RECURSION_LEVEL(0xf) | \
  1334. DEBUG_OUTTYPE_ADDRESS_OF_FIELD | \
  1335. DEBUG_OUTTYPE_ADDRESS_AT_END | \
  1336. DEBUG_OUTTYPE_BLOCK_RECURSE )
  1337. ULONG
  1338. OutputTypeFlagsToDumpOptions(ULONG Flags)
  1339. {
  1340. ULONG Options = 0;
  1341. if (Flags & DEBUG_OUTTYPE_NO_INDENT)
  1342. {
  1343. Options |= DBG_DUMP_NO_INDENT;
  1344. }
  1345. if (Flags & DEBUG_OUTTYPE_NO_OFFSET)
  1346. {
  1347. Options |= DBG_DUMP_NO_OFFSET;
  1348. }
  1349. if (Flags & DEBUG_OUTTYPE_VERBOSE)
  1350. {
  1351. Options |= DBG_DUMP_VERBOSE;
  1352. }
  1353. if (Flags & DEBUG_OUTTYPE_COMPACT_OUTPUT)
  1354. {
  1355. Options |= DBG_DUMP_COMPACT_OUT;
  1356. }
  1357. if (Flags & DEBUG_OUTTYPE_ADDRESS_AT_END)
  1358. {
  1359. Options |= DBG_DUMP_ADDRESS_AT_END;
  1360. }
  1361. if (Flags & DEBUG_OUTTYPE_ADDRESS_OF_FIELD)
  1362. {
  1363. Options |= DBG_DUMP_ADDRESS_OF_FIELD;
  1364. }
  1365. if (Flags & DEBUG_OUTTYPE_BLOCK_RECURSE)
  1366. {
  1367. Options |= DBG_DUMP_BLOCK_RECURSE;
  1368. }
  1369. Options |= DBG_DUMP_RECUR_LEVEL(((Flags >> 4) & 0xf));
  1370. return Options;
  1371. }
  1372. STDMETHODIMP
  1373. DebugClient::OutputTypedDataVirtual(
  1374. THIS_
  1375. IN ULONG OutputControl,
  1376. IN ULONG64 Offset,
  1377. IN ULONG64 Module,
  1378. IN ULONG TypeId,
  1379. IN ULONG Flags
  1380. )
  1381. {
  1382. if (Flags & ~ALL_OUTPUT_TYPE_FLAGS)
  1383. {
  1384. return E_INVALIDARG;
  1385. }
  1386. HRESULT Status;
  1387. ENTER_ENGINE();
  1388. OutCtlSave OldCtl;
  1389. if (!IS_CUR_MACHINE_ACCESSIBLE())
  1390. {
  1391. Status = E_UNEXPECTED;
  1392. }
  1393. else if (!PushOutCtl(OutputControl, this, &OldCtl))
  1394. {
  1395. Status = E_INVALIDARG;
  1396. }
  1397. else
  1398. {
  1399. SYM_DUMP_PARAM_EX Param =
  1400. {
  1401. sizeof(Param), NULL, OutputTypeFlagsToDumpOptions(Flags), Offset,
  1402. NULL, NULL, NULL, 0, NULL
  1403. };
  1404. ULONG TypeStatus;
  1405. TYPES_INFO TypeInfo;
  1406. ZeroMemory(&TypeInfo, sizeof(TypeInfo));
  1407. TypeInfo.hProcess = g_Process->m_SymHandle;
  1408. TypeInfo.ModBaseAddress = Module;
  1409. TypeInfo.TypeIndex = TypeId;
  1410. DumpType(&TypeInfo, &Param, &TypeStatus);
  1411. Status = ResultFromTypeStatus(TypeStatus);
  1412. PopOutCtl(&OldCtl);
  1413. }
  1414. LEAVE_ENGINE();
  1415. return Status;
  1416. }
  1417. STDMETHODIMP
  1418. DebugClient::ReadTypedDataPhysical(
  1419. THIS_
  1420. IN ULONG64 Offset,
  1421. IN ULONG64 Module,
  1422. IN ULONG TypeId,
  1423. OUT PVOID Buffer,
  1424. IN ULONG BufferSize,
  1425. OUT OPTIONAL PULONG BytesRead
  1426. )
  1427. {
  1428. HRESULT Status;
  1429. ULONG Size;
  1430. if ((Status = GetTypeSize(Module, TypeId, &Size)) != S_OK)
  1431. {
  1432. return Status;
  1433. }
  1434. if (Size < BufferSize)
  1435. {
  1436. BufferSize = Size;
  1437. }
  1438. if ((Status = ReadPhysical(Offset, Buffer, BufferSize,
  1439. BytesRead)) != S_OK)
  1440. {
  1441. return Status;
  1442. }
  1443. return Size > BufferSize ? S_FALSE : S_OK;
  1444. }
  1445. STDMETHODIMP
  1446. DebugClient::WriteTypedDataPhysical(
  1447. THIS_
  1448. IN ULONG64 Offset,
  1449. IN ULONG64 Module,
  1450. IN ULONG TypeId,
  1451. IN PVOID Buffer,
  1452. IN ULONG BufferSize,
  1453. OUT OPTIONAL PULONG BytesWritten
  1454. )
  1455. {
  1456. HRESULT Status;
  1457. ULONG Size;
  1458. if ((Status = GetTypeSize(Module, TypeId, &Size)) != S_OK)
  1459. {
  1460. return Status;
  1461. }
  1462. if (Size < BufferSize)
  1463. {
  1464. BufferSize = Size;
  1465. }
  1466. if ((Status = WritePhysical(Offset, Buffer, BufferSize,
  1467. BytesWritten)) != S_OK)
  1468. {
  1469. return Status;
  1470. }
  1471. return Size > BufferSize ? S_FALSE : S_OK;
  1472. }
  1473. STDMETHODIMP
  1474. DebugClient::OutputTypedDataPhysical(
  1475. THIS_
  1476. IN ULONG OutputControl,
  1477. IN ULONG64 Offset,
  1478. IN ULONG64 Module,
  1479. IN ULONG TypeId,
  1480. IN ULONG Flags
  1481. )
  1482. {
  1483. if (Flags & ~ALL_OUTPUT_TYPE_FLAGS)
  1484. {
  1485. return E_INVALIDARG;
  1486. }
  1487. HRESULT Status;
  1488. ENTER_ENGINE();
  1489. OutCtlSave OldCtl;
  1490. if (!IS_CUR_MACHINE_ACCESSIBLE())
  1491. {
  1492. Status = E_UNEXPECTED;
  1493. }
  1494. else if (!PushOutCtl(OutputControl, this, &OldCtl))
  1495. {
  1496. Status = E_INVALIDARG;
  1497. }
  1498. else
  1499. {
  1500. SYM_DUMP_PARAM_EX Param =
  1501. {
  1502. sizeof(Param), NULL, OutputTypeFlagsToDumpOptions(Flags) |
  1503. DBG_DUMP_READ_PHYSICAL, Offset, NULL, NULL, NULL, 0, NULL
  1504. };
  1505. ULONG TypeStatus;
  1506. TYPES_INFO TypeInfo;
  1507. ZeroMemory(&TypeInfo, sizeof(TypeInfo));
  1508. TypeInfo.hProcess = g_Process->m_SymHandle;
  1509. TypeInfo.ModBaseAddress = Module;
  1510. TypeInfo.TypeIndex = TypeId;
  1511. DumpType(&TypeInfo, &Param, &TypeStatus);
  1512. Status = ResultFromTypeStatus(TypeStatus);
  1513. PopOutCtl(&OldCtl);
  1514. }
  1515. LEAVE_ENGINE();
  1516. return Status;
  1517. }
  1518. STDMETHODIMP
  1519. DebugClient::GetScope(
  1520. THIS_
  1521. OUT OPTIONAL PULONG64 InstructionOffset,
  1522. OUT OPTIONAL PDEBUG_STACK_FRAME ScopeFrame,
  1523. OUT OPTIONAL PVOID ScopeContext,
  1524. IN ULONG ScopeContextSize
  1525. )
  1526. {
  1527. HRESULT Status;
  1528. ENTER_ENGINE();
  1529. if (!IS_CUR_MACHINE_ACCESSIBLE())
  1530. {
  1531. Status = E_UNEXPECTED;
  1532. goto Exit;
  1533. }
  1534. Status = S_OK;
  1535. // windbg requests the scope IP and only the scope
  1536. // IP at every event. If the scope is a default lazy
  1537. // scope we can satisfy that request very efficiently.
  1538. if (g_ScopeBuffer.State == ScopeDefaultLazy &&
  1539. InstructionOffset &&
  1540. !ScopeFrame &&
  1541. (!ScopeContext ||
  1542. ScopeContextSize == 0))
  1543. {
  1544. ADDR Addr;
  1545. g_Machine->GetPC(&Addr);
  1546. *InstructionOffset = Flat(Addr);
  1547. goto Exit;
  1548. }
  1549. PDEBUG_SCOPE Scope;
  1550. Scope = GetCurrentScope();
  1551. if (InstructionOffset)
  1552. {
  1553. *InstructionOffset = Scope->Frame.InstructionOffset;
  1554. }
  1555. if (ScopeFrame)
  1556. {
  1557. *ScopeFrame = Scope->Frame;
  1558. }
  1559. if (ScopeContext)
  1560. {
  1561. if (Scope->State == ScopeFromContext)
  1562. {
  1563. memcpy(ScopeContext, &Scope->Context,
  1564. min(sizeof(Scope->Context), ScopeContextSize));
  1565. }
  1566. else if (g_Machine->GetContextState(MCTX_FULL) == S_OK)
  1567. {
  1568. memcpy(ScopeContext, &g_Machine->m_Context,
  1569. min(sizeof(g_Machine->m_Context), ScopeContextSize));
  1570. }
  1571. }
  1572. Exit:
  1573. LEAVE_ENGINE();
  1574. return Status;
  1575. }
  1576. STDMETHODIMP
  1577. DebugClient::SetScope(
  1578. THIS_
  1579. IN ULONG64 InstructionOffset,
  1580. IN OPTIONAL PDEBUG_STACK_FRAME ScopeFrame,
  1581. IN OPTIONAL PVOID ScopeContext,
  1582. IN ULONG ScopeContextSize
  1583. )
  1584. {
  1585. HRESULT Status;
  1586. ENTER_ENGINE();
  1587. if (!IS_CUR_MACHINE_ACCESSIBLE())
  1588. {
  1589. Status = E_UNEXPECTED;
  1590. }
  1591. else
  1592. {
  1593. DEBUG_STACK_FRAME LocalFrame;
  1594. if (ScopeFrame)
  1595. {
  1596. LocalFrame = *ScopeFrame;
  1597. }
  1598. else
  1599. {
  1600. ZeroMemory(&LocalFrame, sizeof(LocalFrame));
  1601. LocalFrame.InstructionOffset = InstructionOffset;
  1602. }
  1603. Status = SetCurrentScope(&LocalFrame, ScopeContext, ScopeContextSize) ?
  1604. S_FALSE : S_OK;
  1605. }
  1606. LEAVE_ENGINE();
  1607. return Status;
  1608. }
  1609. STDMETHODIMP
  1610. DebugClient::ResetScope(
  1611. THIS
  1612. )
  1613. {
  1614. HRESULT Status;
  1615. ENTER_ENGINE();
  1616. if (!IS_CUR_MACHINE_ACCESSIBLE())
  1617. {
  1618. Status = E_UNEXPECTED;
  1619. }
  1620. else
  1621. {
  1622. ResetCurrentScope();
  1623. Status = S_OK;
  1624. }
  1625. LEAVE_ENGINE();
  1626. return Status;
  1627. }
  1628. STDMETHODIMP
  1629. DebugClient::GetScopeSymbolGroup(
  1630. THIS_
  1631. IN ULONG Flags,
  1632. IN OPTIONAL PDEBUG_SYMBOL_GROUP Update,
  1633. OUT PDEBUG_SYMBOL_GROUP* Symbols
  1634. )
  1635. {
  1636. HRESULT Status;
  1637. if (Flags == 0 ||
  1638. (Flags & ~DEBUG_SCOPE_GROUP_ALL))
  1639. {
  1640. return E_INVALIDARG;
  1641. }
  1642. ENTER_ENGINE();
  1643. if (Update)
  1644. {
  1645. if (!IS_CUR_MACHINE_ACCESSIBLE())
  1646. {
  1647. Status = E_UNEXPECTED;
  1648. }
  1649. else if (Flags != DEBUG_SCOPE_GROUP_LOCALS &&
  1650. Flags != DEBUG_SCOPE_GROUP_ARGUMENTS)
  1651. {
  1652. Status = E_INVALIDARG;
  1653. }
  1654. else
  1655. {
  1656. Status = ((DebugSymbolGroup *)Update)->AddCurrentLocals();
  1657. if (Status == S_OK)
  1658. {
  1659. *Symbols = Update;
  1660. }
  1661. }
  1662. }
  1663. else
  1664. {
  1665. *Symbols = new DebugSymbolGroup(this, Flags);
  1666. if (*Symbols != NULL)
  1667. {
  1668. Status = S_OK;
  1669. }
  1670. else
  1671. {
  1672. Status = E_OUTOFMEMORY;
  1673. }
  1674. }
  1675. LEAVE_ENGINE();
  1676. return Status;
  1677. }
  1678. STDMETHODIMP
  1679. DebugClient::CreateSymbolGroup(
  1680. THIS_
  1681. OUT PDEBUG_SYMBOL_GROUP* Group
  1682. )
  1683. {
  1684. HRESULT Status;
  1685. ENTER_ENGINE();
  1686. *Group = new DebugSymbolGroup(this, 0);
  1687. if (*Group == NULL)
  1688. {
  1689. Status = E_OUTOFMEMORY;
  1690. }
  1691. else
  1692. {
  1693. Status = S_OK;
  1694. }
  1695. LEAVE_ENGINE();
  1696. return Status;
  1697. }
  1698. struct SymbolMatch
  1699. {
  1700. ProcessInfo* Process;
  1701. BOOL SingleMod;
  1702. ImageInfo* Mod;
  1703. PCHAR Storage, StorageEnd;
  1704. PCHAR Cur, End;
  1705. char Pattern[1];
  1706. };
  1707. STDMETHODIMP
  1708. DebugClient::StartSymbolMatch(
  1709. THIS_
  1710. IN PCSTR Pattern,
  1711. OUT PULONG64 Handle
  1712. )
  1713. {
  1714. HRESULT Status;
  1715. ENTER_ENGINE();
  1716. if (g_Process == NULL)
  1717. {
  1718. Status = E_UNEXPECTED;
  1719. goto EH_Exit;
  1720. }
  1721. ImageInfo* Mod;
  1722. PCSTR Sym;
  1723. // Check for a module qualifier.
  1724. Sym = strchr(Pattern, '!');
  1725. if (Sym != NULL)
  1726. {
  1727. size_t ModLen = Sym - Pattern;
  1728. if (ModLen == 0)
  1729. {
  1730. Status = E_INVALIDARG;
  1731. goto EH_Exit;
  1732. }
  1733. Mod = g_Process->FindImageByName(Pattern, ModLen, INAME_MODULE, FALSE);
  1734. if (Mod == NULL)
  1735. {
  1736. Status = E_NOINTERFACE;
  1737. goto EH_Exit;
  1738. }
  1739. Sym++;
  1740. }
  1741. else
  1742. {
  1743. Sym = Pattern;
  1744. Mod = NULL;
  1745. }
  1746. ULONG SymLen;
  1747. SymLen = strlen(Sym);
  1748. SymbolMatch* Match;
  1749. Match = (SymbolMatch*)malloc(sizeof(SymbolMatch) + SymLen);
  1750. if (Match == NULL)
  1751. {
  1752. Status = E_OUTOFMEMORY;
  1753. goto EH_Exit;
  1754. }
  1755. if (Mod == NULL)
  1756. {
  1757. Match->Process = g_Process;
  1758. Match->Mod = Match->Process->m_ImageHead;
  1759. Match->SingleMod = FALSE;
  1760. }
  1761. else
  1762. {
  1763. Match->Process = g_Process;
  1764. Match->Mod = Mod;
  1765. Match->SingleMod = TRUE;
  1766. }
  1767. Match->Storage = NULL;
  1768. Match->StorageEnd = NULL;
  1769. Match->Cur = NULL;
  1770. strcpy(Match->Pattern, Sym);
  1771. _strupr(Match->Pattern);
  1772. *Handle = (ULONG64)Match;
  1773. Status = S_OK;
  1774. EH_Exit:
  1775. LEAVE_ENGINE();
  1776. return Status;
  1777. }
  1778. #define STORAGE_INC 16384
  1779. BOOL CALLBACK
  1780. FillMatchStorageCb(PSTR Name, ULONG64 Offset, ULONG Size, PVOID Context)
  1781. {
  1782. SymbolMatch* Match = (SymbolMatch*)Context;
  1783. ULONG NameLen = strlen(Name) + 1;
  1784. ULONG RecordLen = NameLen + sizeof(ULONG64);
  1785. if (Match->Cur + RecordLen > Match->StorageEnd)
  1786. {
  1787. PCHAR NewStore;
  1788. size_t NewLen;
  1789. NewLen = (Match->StorageEnd - Match->Storage) + STORAGE_INC;
  1790. NewStore = (PCHAR)realloc(Match->Storage, NewLen);
  1791. if (NewStore == NULL)
  1792. {
  1793. // Terminate the enumeration since there's no more room.
  1794. // This produces a silent failure but it's not
  1795. // important enough to warrant a true failure.
  1796. return FALSE;
  1797. }
  1798. Match->Cur = NewStore + (Match->Cur - Match->Storage);
  1799. Match->Storage = NewStore;
  1800. Match->StorageEnd = NewStore + NewLen;
  1801. DBG_ASSERT(Match->Cur + RecordLen <= Match->StorageEnd);
  1802. }
  1803. strcpy(Match->Cur, Name);
  1804. Match->Cur += NameLen;
  1805. *(ULONG64 UNALIGNED *)Match->Cur = Offset;
  1806. Match->Cur += sizeof(Offset);
  1807. return TRUE;
  1808. }
  1809. STDMETHODIMP
  1810. DebugClient::GetNextSymbolMatch(
  1811. THIS_
  1812. IN ULONG64 Handle,
  1813. OUT OPTIONAL PSTR Buffer,
  1814. IN ULONG BufferSize,
  1815. OUT OPTIONAL PULONG MatchSize,
  1816. OUT OPTIONAL PULONG64 Offset
  1817. )
  1818. {
  1819. ENTER_ENGINE();
  1820. SymbolMatch* Match = (SymbolMatch*)Handle;
  1821. HRESULT Status = E_NOINTERFACE;
  1822. // Loop until a matching symbol is found.
  1823. for (;;)
  1824. {
  1825. if (Match->Mod == NULL)
  1826. {
  1827. // Nothing more to enumerate.
  1828. // Status is already set.
  1829. break;
  1830. }
  1831. if (Match->Cur == NULL)
  1832. {
  1833. // Enumerate all symbols and stash them away.
  1834. Match->Cur = Match->Storage;
  1835. if (!SymEnumerateSymbols64(Match->Process->m_SymHandle,
  1836. Match->Mod->m_BaseOfImage,
  1837. FillMatchStorageCb, Match))
  1838. {
  1839. Status = WIN32_LAST_STATUS();
  1840. break;
  1841. }
  1842. Match->End = Match->Cur;
  1843. Match->Cur = Match->Storage;
  1844. }
  1845. while (Match->Cur < Match->End)
  1846. {
  1847. PCHAR Name;
  1848. ULONG64 Addr;
  1849. Name = Match->Cur;
  1850. Match->Cur += strlen(Name) + 1;
  1851. Addr = *(ULONG64 UNALIGNED *)Match->Cur;
  1852. Match->Cur += sizeof(Addr);
  1853. // If this symbol matches remember it for return.
  1854. if (MatchPattern(Name, Match->Pattern))
  1855. {
  1856. char Sym[MAX_MODULE + MAX_SYMBOL_LEN + 1];
  1857. CopyString(Sym, Match->Mod->m_ModuleName, DIMA(Sym));
  1858. CatString(Sym, "!", DIMA(Sym));
  1859. CatString(Sym, Name, DIMA(Sym));
  1860. Status = FillStringBuffer(Sym, 0, Buffer, BufferSize,
  1861. MatchSize);
  1862. if (Buffer == NULL)
  1863. {
  1864. // Do not advance the enumeration as this
  1865. // is just a size test.
  1866. Match->Cur = Name;
  1867. }
  1868. if (Offset != NULL)
  1869. {
  1870. *Offset = Addr;
  1871. }
  1872. break;
  1873. }
  1874. }
  1875. if (SUCCEEDED(Status))
  1876. {
  1877. break;
  1878. }
  1879. if (Match->SingleMod)
  1880. {
  1881. Match->Mod = NULL;
  1882. }
  1883. else
  1884. {
  1885. Match->Mod = Match->Mod->m_Next;
  1886. }
  1887. Match->Cur = NULL;
  1888. }
  1889. LEAVE_ENGINE();
  1890. return Status;
  1891. }
  1892. STDMETHODIMP
  1893. DebugClient::EndSymbolMatch(
  1894. THIS_
  1895. IN ULONG64 Handle
  1896. )
  1897. {
  1898. ENTER_ENGINE();
  1899. SymbolMatch* Match = (SymbolMatch*)Handle;
  1900. if (Match->Storage != NULL)
  1901. {
  1902. free(Match->Storage);
  1903. }
  1904. free(Match);
  1905. LEAVE_ENGINE();
  1906. return S_OK;
  1907. }
  1908. STDMETHODIMP
  1909. DebugClient::Reload(
  1910. THIS_
  1911. IN PCSTR Module
  1912. )
  1913. {
  1914. ENTER_ENGINE();
  1915. PCSTR ArgsRet;
  1916. HRESULT Status = g_Target->Reload(g_Thread, Module, &ArgsRet);
  1917. LEAVE_ENGINE();
  1918. return Status;
  1919. }
  1920. STDMETHODIMP
  1921. DebugClient::GetSymbolPath(
  1922. THIS_
  1923. OUT OPTIONAL PSTR Buffer,
  1924. IN ULONG BufferSize,
  1925. OUT OPTIONAL PULONG PathSize
  1926. )
  1927. {
  1928. ENTER_ENGINE();
  1929. HRESULT Status =
  1930. FillStringBuffer(g_SymbolSearchPath, 0,
  1931. Buffer, BufferSize, PathSize);
  1932. LEAVE_ENGINE();
  1933. return Status;
  1934. }
  1935. STDMETHODIMP
  1936. DebugClient::SetSymbolPath(
  1937. THIS_
  1938. IN PCSTR Path
  1939. )
  1940. {
  1941. ENTER_ENGINE();
  1942. HRESULT Status;
  1943. Status = ChangeSymPath(Path, FALSE, NULL, 0) ?
  1944. S_OK : E_OUTOFMEMORY;
  1945. if (Status == S_OK)
  1946. {
  1947. CheckPath(g_SymbolSearchPath);
  1948. }
  1949. LEAVE_ENGINE();
  1950. return Status;
  1951. }
  1952. STDMETHODIMP
  1953. DebugClient::AppendSymbolPath(
  1954. THIS_
  1955. IN PCSTR Addition
  1956. )
  1957. {
  1958. ENTER_ENGINE();
  1959. HRESULT Status;
  1960. Status = ChangeSymPath(Addition, TRUE, NULL, 0) ?
  1961. S_OK : E_OUTOFMEMORY;
  1962. if (Status == S_OK)
  1963. {
  1964. CheckPath(g_SymbolSearchPath);
  1965. }
  1966. LEAVE_ENGINE();
  1967. return Status;
  1968. }
  1969. STDMETHODIMP
  1970. DebugClient::GetImagePath(
  1971. THIS_
  1972. OUT OPTIONAL PSTR Buffer,
  1973. IN ULONG BufferSize,
  1974. OUT OPTIONAL PULONG PathSize
  1975. )
  1976. {
  1977. ENTER_ENGINE();
  1978. HRESULT Status = FillStringBuffer(g_ExecutableImageSearchPath, 0,
  1979. Buffer, BufferSize, PathSize);
  1980. LEAVE_ENGINE();
  1981. return Status;
  1982. }
  1983. STDMETHODIMP
  1984. DebugClient::SetImagePath(
  1985. THIS_
  1986. IN PCSTR Path
  1987. )
  1988. {
  1989. ENTER_ENGINE();
  1990. HRESULT Status = ChangePath(&g_ExecutableImageSearchPath, Path, FALSE,
  1991. DEBUG_CSS_PATHS);
  1992. if (Status == S_OK)
  1993. {
  1994. CheckPath(g_ExecutableImageSearchPath);
  1995. }
  1996. LEAVE_ENGINE();
  1997. return Status;
  1998. }
  1999. STDMETHODIMP
  2000. DebugClient::AppendImagePath(
  2001. THIS_
  2002. IN PCSTR Addition
  2003. )
  2004. {
  2005. ENTER_ENGINE();
  2006. HRESULT Status = ChangePath(&g_ExecutableImageSearchPath, Addition, TRUE,
  2007. DEBUG_CSS_PATHS);
  2008. if (Status == S_OK)
  2009. {
  2010. CheckPath(g_ExecutableImageSearchPath);
  2011. }
  2012. LEAVE_ENGINE();
  2013. return Status;
  2014. }
  2015. STDMETHODIMP
  2016. DebugClient::GetSourcePath(
  2017. THIS_
  2018. OUT OPTIONAL PSTR Buffer,
  2019. IN ULONG BufferSize,
  2020. OUT OPTIONAL PULONG PathSize
  2021. )
  2022. {
  2023. ENTER_ENGINE();
  2024. HRESULT Status = FillStringBuffer(g_SrcPath, 0,
  2025. Buffer, BufferSize, PathSize);
  2026. LEAVE_ENGINE();
  2027. return Status;
  2028. }
  2029. STDMETHODIMP
  2030. DebugClient::GetSourcePathElement(
  2031. THIS_
  2032. IN ULONG Index,
  2033. OUT OPTIONAL PSTR Buffer,
  2034. IN ULONG BufferSize,
  2035. OUT OPTIONAL PULONG ElementSize
  2036. )
  2037. {
  2038. ENTER_ENGINE();
  2039. HRESULT Status;
  2040. PSTR Elt, EltEnd;
  2041. Elt = FindPathElement(g_SrcPath, Index, &EltEnd);
  2042. if (Elt == NULL)
  2043. {
  2044. Status = E_NOINTERFACE;
  2045. goto EH_Exit;
  2046. }
  2047. CHAR Save;
  2048. Save = *EltEnd;
  2049. *EltEnd = 0;
  2050. Status = FillStringBuffer(Elt, (ULONG)(EltEnd - Elt) + 1,
  2051. Buffer, BufferSize, ElementSize);
  2052. *EltEnd = Save;
  2053. EH_Exit:
  2054. LEAVE_ENGINE();
  2055. return Status;
  2056. }
  2057. STDMETHODIMP
  2058. DebugClient::SetSourcePath(
  2059. THIS_
  2060. IN PCSTR Path
  2061. )
  2062. {
  2063. ENTER_ENGINE();
  2064. HRESULT Status = ChangePath(&g_SrcPath, Path, FALSE, DEBUG_CSS_PATHS);
  2065. if (Status == S_OK)
  2066. {
  2067. CheckPath(g_SrcPath);
  2068. }
  2069. LEAVE_ENGINE();
  2070. return Status;
  2071. }
  2072. STDMETHODIMP
  2073. DebugClient::AppendSourcePath(
  2074. THIS_
  2075. IN PCSTR Addition
  2076. )
  2077. {
  2078. ENTER_ENGINE();
  2079. HRESULT Status = ChangePath(&g_SrcPath, Addition, TRUE, DEBUG_CSS_PATHS);
  2080. if (Status == S_OK)
  2081. {
  2082. CheckPath(g_SrcPath);
  2083. }
  2084. LEAVE_ENGINE();
  2085. return Status;
  2086. }
  2087. HRESULT
  2088. GetCanonicalPath(PCSTR Path, PSTR Canon, ULONG CanonSize)
  2089. {
  2090. // First make sure it's a full path.
  2091. // XXX drewb - Probably should also convert drive
  2092. // letters to unambiguous names.
  2093. if (!IS_SLASH(Path[0]) &&
  2094. !(((Path[0] >= 'a' && Path[0] <= 'z') ||
  2095. (Path[0] >= 'A' && Path[0] <= 'Z')) &&
  2096. Path[1] == ':') &&
  2097. !IsUrlPathComponent(Path))
  2098. {
  2099. DWORD FullLen;
  2100. PSTR FilePart;
  2101. FullLen = GetFullPathName(Path, CanonSize, Canon, &FilePart);
  2102. if (FullLen == 0 || FullLen >= CanonSize)
  2103. {
  2104. return WIN32_LAST_STATUS();
  2105. }
  2106. }
  2107. else
  2108. {
  2109. CopyString(Canon, Path, CanonSize);
  2110. }
  2111. // Now remove '.' and '..'. This is a full path with a filename
  2112. // at the end so all occurrences must be bracketed with
  2113. // path slashes.
  2114. PSTR Rd = Canon, Wr = Canon;
  2115. while (*Rd != 0)
  2116. {
  2117. if (IS_SLASH(*Rd))
  2118. {
  2119. if (Rd[1] == '.')
  2120. {
  2121. if (IS_SLASH(Rd[2]))
  2122. {
  2123. // Found /./, ignore leading /. and continue
  2124. // with /.
  2125. Rd += 2;
  2126. continue;
  2127. }
  2128. else if (Rd[2] == '.' && IS_SLASH(Rd[3]))
  2129. {
  2130. // Found /../ so back up one path component
  2131. // and continue with /.
  2132. do
  2133. {
  2134. Wr--;
  2135. }
  2136. while (Wr >= Canon && !IS_PATH_DELIM(*Wr));
  2137. DBG_ASSERT(Wr >= Canon);
  2138. Rd += 3;
  2139. continue;
  2140. }
  2141. }
  2142. }
  2143. *Wr++ = *Rd++;
  2144. }
  2145. *Wr = 0;
  2146. return S_OK;
  2147. }
  2148. STDMETHODIMP
  2149. DebugClient::FindSourceFile(
  2150. THIS_
  2151. IN ULONG StartElement,
  2152. IN PCSTR File,
  2153. IN ULONG Flags,
  2154. OUT OPTIONAL PULONG FoundElement,
  2155. OUT OPTIONAL PSTR Buffer,
  2156. IN ULONG BufferSize,
  2157. OUT OPTIONAL PULONG FoundSize
  2158. )
  2159. {
  2160. if (Flags & ~(DEBUG_FIND_SOURCE_DEFAULT |
  2161. DEBUG_FIND_SOURCE_FULL_PATH |
  2162. DEBUG_FIND_SOURCE_BEST_MATCH))
  2163. {
  2164. return E_INVALIDARG;
  2165. }
  2166. HRESULT Status;
  2167. char RwFile[MAX_SOURCE_PATH];
  2168. ULONG FileLen;
  2169. char Found[MAX_SOURCE_PATH];
  2170. PSTR MatchPart;
  2171. ULONG Elt;
  2172. // Make a read-write copy of the file as the searching
  2173. // modifies it.
  2174. FileLen = strlen(File) + 1;
  2175. if (FileLen > sizeof(RwFile))
  2176. {
  2177. return E_INVALIDARG;
  2178. }
  2179. memcpy(RwFile, File, FileLen);
  2180. ENTER_ENGINE();
  2181. if (FindSrcFileOnPath(StartElement, RwFile, Flags, Found, DIMA(Found),
  2182. &MatchPart, &Elt))
  2183. {
  2184. if (Flags & DEBUG_FIND_SOURCE_FULL_PATH)
  2185. {
  2186. Status = GetCanonicalPath(Found, RwFile, DIMA(RwFile));
  2187. if (Status != S_OK)
  2188. {
  2189. goto EH_Exit;
  2190. }
  2191. strcpy(Found, RwFile);
  2192. }
  2193. if (FoundElement != NULL)
  2194. {
  2195. *FoundElement = Elt;
  2196. }
  2197. Status = FillStringBuffer(Found, 0,
  2198. Buffer, BufferSize, FoundSize);
  2199. }
  2200. else
  2201. {
  2202. Status = E_NOINTERFACE;
  2203. }
  2204. EH_Exit:
  2205. LEAVE_ENGINE();
  2206. return Status;
  2207. }
  2208. // XXX drewb - This API is private for the moment due
  2209. // to uncertainty about what dbghelp's API is going to
  2210. // look like in the long term.
  2211. extern "C"
  2212. ULONG
  2213. IMAGEAPI
  2214. SymGetFileLineOffsets64(
  2215. IN HANDLE hProcess,
  2216. IN LPSTR ModuleName,
  2217. IN LPSTR FileName,
  2218. OUT PDWORD64 Buffer,
  2219. IN ULONG BufferLines
  2220. );
  2221. STDMETHODIMP
  2222. DebugClient::GetSourceFileLineOffsets(
  2223. THIS_
  2224. IN PCSTR File,
  2225. OUT OPTIONAL PULONG64 Buffer,
  2226. IN ULONG BufferLines,
  2227. OUT OPTIONAL PULONG FileLines
  2228. )
  2229. {
  2230. HRESULT Status;
  2231. ULONG Line;
  2232. if (Buffer != NULL)
  2233. {
  2234. // Initialize map to empty.
  2235. for (Line = 0; Line < BufferLines; Line++)
  2236. {
  2237. Buffer[Line] = DEBUG_INVALID_OFFSET;
  2238. }
  2239. }
  2240. ENTER_ENGINE();
  2241. if (g_Process == NULL)
  2242. {
  2243. Status = E_UNEXPECTED;
  2244. goto EH_Exit;
  2245. }
  2246. PSTR FilePart;
  2247. ULONG HighestLine;
  2248. // Request the line information from dbghelp.
  2249. FilePart = (PSTR)File;
  2250. HighestLine =
  2251. SymGetFileLineOffsets64(g_Process->m_SymHandle, NULL, FilePart,
  2252. Buffer, BufferLines);
  2253. if (HighestLine == 0xffffffff)
  2254. {
  2255. Status = WIN32_LAST_STATUS();
  2256. goto EH_Exit;
  2257. }
  2258. if (HighestLine == 0)
  2259. {
  2260. // Try again with just the filename because the path
  2261. // may be different than what's in the symbol information.
  2262. // XXX drewb - This can cause ambiguity problems.
  2263. FilePart = (PSTR)File + strlen(File) - 1;
  2264. while (FilePart >= File)
  2265. {
  2266. if (IS_PATH_DELIM(*FilePart))
  2267. {
  2268. break;
  2269. }
  2270. FilePart--;
  2271. }
  2272. FilePart++;
  2273. if (FilePart <= File)
  2274. {
  2275. // No path and no information was found for the
  2276. // given file so return not-found.
  2277. Status = E_NOINTERFACE;
  2278. goto EH_Exit;
  2279. }
  2280. HighestLine =
  2281. SymGetFileLineOffsets64(g_Process->m_SymHandle, NULL, FilePart,
  2282. Buffer, BufferLines);
  2283. if (HighestLine == 0xffffffff)
  2284. {
  2285. Status = WIN32_LAST_STATUS();
  2286. goto EH_Exit;
  2287. }
  2288. else if (HighestLine == 0)
  2289. {
  2290. Status = E_NOINTERFACE;
  2291. goto EH_Exit;
  2292. }
  2293. }
  2294. if (FileLines != NULL)
  2295. {
  2296. *FileLines = HighestLine;
  2297. }
  2298. // Return S_FALSE if lines were missed because of
  2299. // insufficient buffer space.
  2300. Status = HighestLine > BufferLines ? S_FALSE : S_OK;
  2301. EH_Exit:
  2302. LEAVE_ENGINE();
  2303. return Status;
  2304. }
  2305. STDMETHODIMP
  2306. DebugClient::GetModuleVersionInformation(
  2307. THIS_
  2308. IN ULONG Index,
  2309. IN ULONG64 Base,
  2310. IN PCSTR Item,
  2311. OUT OPTIONAL PVOID Buffer,
  2312. IN ULONG BufferSize,
  2313. OUT OPTIONAL PULONG VerInfoSize
  2314. )
  2315. {
  2316. HRESULT Status;
  2317. ENTER_ENGINE();
  2318. if (g_Process == NULL)
  2319. {
  2320. Status = E_UNEXPECTED;
  2321. }
  2322. else
  2323. {
  2324. ImageInfo* Image;
  2325. if (Index == DEBUG_ANY_ID)
  2326. {
  2327. Image = g_Process->FindImageByOffset(Base, FALSE);
  2328. }
  2329. else
  2330. {
  2331. Image = g_Process->FindImageByIndex(Index);
  2332. }
  2333. if (Image == NULL)
  2334. {
  2335. Status = E_NOINTERFACE;
  2336. }
  2337. else
  2338. {
  2339. Status = g_Target->
  2340. GetImageVersionInformation(g_Process, Image->m_ImagePath,
  2341. Image->m_BaseOfImage, Item,
  2342. Buffer, BufferSize, VerInfoSize);
  2343. }
  2344. }
  2345. LEAVE_ENGINE();
  2346. return Status;
  2347. }
  2348. STDMETHODIMP
  2349. DebugClient::GetModuleNameString(
  2350. THIS_
  2351. IN ULONG Which,
  2352. IN ULONG Index,
  2353. IN ULONG64 Base,
  2354. OUT OPTIONAL PSTR Buffer,
  2355. IN ULONG BufferSize,
  2356. OUT OPTIONAL PULONG NameSize
  2357. )
  2358. {
  2359. HRESULT Status;
  2360. if (Which > DEBUG_MODNAME_MAPPED_IMAGE)
  2361. {
  2362. return E_INVALIDARG;
  2363. }
  2364. ENTER_ENGINE();
  2365. if (g_Process == NULL)
  2366. {
  2367. Status = E_UNEXPECTED;
  2368. }
  2369. else
  2370. {
  2371. ULONG Idx = 0;
  2372. Status = E_NOINTERFACE;
  2373. ImageInfo* Image = g_Process->m_ImageHead;
  2374. while (Image != NULL)
  2375. {
  2376. if ((Index != DEBUG_ANY_ID && Idx == Index) ||
  2377. (Index == DEBUG_ANY_ID && Base == Image->m_BaseOfImage))
  2378. {
  2379. PSTR Str;
  2380. IMAGEHLP_MODULE64 ModInfo;
  2381. switch(Which)
  2382. {
  2383. case DEBUG_MODNAME_IMAGE:
  2384. Str = Image->m_ImagePath;
  2385. break;
  2386. case DEBUG_MODNAME_MODULE:
  2387. Str = Image->m_ModuleName;
  2388. break;
  2389. case DEBUG_MODNAME_LOADED_IMAGE:
  2390. ModInfo.SizeOfStruct = sizeof(ModInfo);
  2391. if (!SymGetModuleInfo64(g_Process->m_SymHandle,
  2392. Image->m_BaseOfImage, &ModInfo))
  2393. {
  2394. Status = WIN32_LAST_STATUS();
  2395. goto Exit;
  2396. }
  2397. Str = ModInfo.LoadedImageName;
  2398. break;
  2399. case DEBUG_MODNAME_SYMBOL_FILE:
  2400. ModInfo.SizeOfStruct = sizeof(ModInfo);
  2401. if (!SymGetModuleInfo64(g_Process->m_SymHandle,
  2402. Image->m_BaseOfImage, &ModInfo))
  2403. {
  2404. Status = WIN32_LAST_STATUS();
  2405. goto Exit;
  2406. }
  2407. Str = ModInfoSymFile(&ModInfo);
  2408. break;
  2409. case DEBUG_MODNAME_MAPPED_IMAGE:
  2410. Str = Image->m_MappedImagePath;
  2411. break;
  2412. }
  2413. Status = FillStringBuffer(Str, 0,
  2414. Buffer, BufferSize, NameSize);
  2415. break;
  2416. }
  2417. Image = Image->m_Next;
  2418. Idx++;
  2419. }
  2420. }
  2421. Exit:
  2422. LEAVE_ENGINE();
  2423. return Status;
  2424. }
  2425. //----------------------------------------------------------------------------
  2426. //
  2427. // SymbolGroupEntry.
  2428. //
  2429. //----------------------------------------------------------------------------
  2430. SymbolGroupEntry::SymbolGroupEntry(void)
  2431. {
  2432. m_Parent = NULL;
  2433. m_Next = NULL;
  2434. m_Format = NULL;
  2435. m_Expr = NULL;
  2436. m_Cast = NULL;
  2437. ZeroMemory(&m_Params, sizeof(m_Params));
  2438. m_Flags = 0;
  2439. ZeroMemory(&m_BaseData, sizeof(m_BaseData));
  2440. m_BaseFormatKind = SGFORMAT_TYPED_DATA;
  2441. }
  2442. SymbolGroupEntry::~SymbolGroupEntry(void)
  2443. {
  2444. free(m_Expr);
  2445. free(m_Cast);
  2446. delete m_Format;
  2447. }
  2448. //----------------------------------------------------------------------------
  2449. //
  2450. // SymbolGroupFormat.
  2451. //
  2452. //----------------------------------------------------------------------------
  2453. SymbolGroupFormat::SymbolGroupFormat(SymbolGroupEntry* Entry,
  2454. SymbolGroupFormatKind Kind)
  2455. {
  2456. m_Entry = Entry;
  2457. m_Kind = Kind;
  2458. // There's no expression to start with so
  2459. // start in an error state.
  2460. m_ExprErr = NOTFOUND;
  2461. m_ValueErr = NOTFOUND;
  2462. }
  2463. SymbolGroupFormat::~SymbolGroupFormat(void)
  2464. {
  2465. }
  2466. void
  2467. SymbolGroupFormat::TestImages(void)
  2468. {
  2469. ImageInfo* Image;
  2470. if (m_Entry->m_Params.Module == 0)
  2471. {
  2472. Image = NULL;
  2473. }
  2474. else
  2475. {
  2476. Image = g_Process ?
  2477. g_Process->FindImageByOffset(m_Entry->m_Params.Module, FALSE) :
  2478. NULL;
  2479. }
  2480. if (Image != m_Entry->m_BaseData.m_Image)
  2481. {
  2482. // The module list has changed, avoid
  2483. // referencing a possibly invalid image.
  2484. m_Entry->m_BaseData.ReleaseImage();
  2485. }
  2486. }
  2487. //---------------------------------------------------------------------------
  2488. //
  2489. // TypedDataSymbolGroupFormat.
  2490. //
  2491. //----------------------------------------------------------------------------
  2492. struct TdccContext
  2493. {
  2494. DebugSymbolGroup* Group;
  2495. TypedDataSymbolGroupFormat* Format;
  2496. SymbolGroupEntry* AddAfter;
  2497. ULONG NumChildren;
  2498. };
  2499. ULONG
  2500. TypedDataSymbolGroupFormat::CreateChildren(DebugSymbolGroup* Group)
  2501. {
  2502. if (m_ExprErr)
  2503. {
  2504. return m_ExprErr;
  2505. }
  2506. if (!m_Entry->m_Params.SubElements)
  2507. {
  2508. return NOTFOUND;
  2509. }
  2510. ULONG Err;
  2511. TdccContext Context;
  2512. Context.Group = Group;
  2513. Context.Format = this;
  2514. Context.AddAfter = m_Entry;
  2515. Context.NumChildren = 0;
  2516. // We don't need the actual data for children here,
  2517. // just the children themselves. This allows nodes
  2518. // to be expanded even when they refer to invalid
  2519. // memory.
  2520. // The children's values will be updated on the next Refresh.
  2521. if (Err = m_CastData.GetChildren(g_Machine->m_Ptr64 ? 8 : 4,
  2522. CHLF_DEREF_UDT_POINTERS |
  2523. CHLF_DISALLOW_ACCESS,
  2524. CreateChildrenCb, &Context))
  2525. {
  2526. return Err;
  2527. }
  2528. // The estimated child count may have been different from
  2529. // the actual child count so update it.
  2530. m_Entry->m_Params.SubElements = Context.NumChildren;
  2531. return NO_ERROR;
  2532. }
  2533. ULONG
  2534. TypedDataSymbolGroupFormat::AddChild(SymbolGroupEntry** AddAfter,
  2535. PSTR Name, TypedData* Data)
  2536. {
  2537. SymbolGroupEntry* Child = new SymbolGroupEntry;
  2538. TypedDataSymbolGroupFormat* ChildFormat =
  2539. new TypedDataSymbolGroupFormat(Child);
  2540. if (!Child || !ChildFormat)
  2541. {
  2542. delete Child;
  2543. return NOMEMORY;
  2544. }
  2545. Child->m_Format = ChildFormat;
  2546. Child->m_Expr = _strdup(Name);
  2547. if (!Child->m_Expr)
  2548. {
  2549. delete Child;
  2550. return NOMEMORY;
  2551. }
  2552. Child->m_Parent = m_Entry;
  2553. Child->m_Params.Flags =
  2554. (m_Entry->m_Params.Flags & DEBUG_SYMBOL_EXPANSION_LEVEL_MASK) + 1;
  2555. Child->m_Next = (*AddAfter)->m_Next;
  2556. Child->m_BaseData = *Data;
  2557. Child->m_BaseFormatKind = SGFORMAT_TYPED_DATA;
  2558. ChildFormat->m_ExprErr = NO_ERROR;
  2559. ChildFormat->m_CastData = *Data;
  2560. ChildFormat->UpdateParams();
  2561. (*AddAfter)->m_Next = Child;
  2562. *AddAfter = Child;
  2563. return NO_ERROR;
  2564. }
  2565. ULONG
  2566. TypedDataSymbolGroupFormat::CreateChildrenCb(PVOID _Context,
  2567. PSTR Name, TypedData* Child)
  2568. {
  2569. ULONG Err;
  2570. TdccContext* Context = (TdccContext*)_Context;
  2571. Err = Context->Format->AddChild(&Context->AddAfter, Name, Child);
  2572. if (!Err)
  2573. {
  2574. Context->Group->m_NumEntries++;
  2575. Context->NumChildren++;
  2576. }
  2577. return Err;
  2578. }
  2579. ULONG
  2580. TypedDataSymbolGroupFormat::Refresh(TypedDataAccess AllowAccess)
  2581. {
  2582. ULONG64 OldPtr = m_CastData.m_Ptr;
  2583. if (m_ExprErr)
  2584. {
  2585. return m_ExprErr;
  2586. }
  2587. m_ValueErr = m_CastData.ReadData(AllowAccess);
  2588. if (m_ValueErr)
  2589. {
  2590. return m_ValueErr;
  2591. }
  2592. if (m_CastData.IsPointer() &&
  2593. m_CastData.m_Ptr != OldPtr)
  2594. {
  2595. RefreshChildren();
  2596. }
  2597. return NO_ERROR;
  2598. }
  2599. ULONG
  2600. TypedDataSymbolGroupFormat::Write(PCSTR Value)
  2601. {
  2602. if (m_ExprErr)
  2603. {
  2604. return m_ExprErr;
  2605. }
  2606. g_DisableErrorPrint++;
  2607. EvalExpression* RelChain = g_EvalReleaseChain;
  2608. g_EvalReleaseChain = NULL;
  2609. __try
  2610. {
  2611. TypedData Source;
  2612. EvalExpression* Eval = GetEvaluator(DEBUG_EXPR_CPLUSPLUS, FALSE);
  2613. Eval->Evaluate(Value, NULL, EXPRF_DEFAULT, &Source);
  2614. ReleaseEvaluator(Eval);
  2615. if (!(m_ValueErr = Source.ConvertToSource(&m_CastData)) &&
  2616. !(m_ValueErr = m_CastData.WriteData(&Source, TDACC_REQUIRE)))
  2617. {
  2618. m_CastData.CopyData(&Source);
  2619. }
  2620. }
  2621. __except(CommandExceptionFilter(GetExceptionInformation()))
  2622. {
  2623. m_ValueErr = GetExceptionCode() - COMMAND_EXCEPTION_BASE;
  2624. }
  2625. g_EvalReleaseChain = RelChain;
  2626. g_DisableErrorPrint--;
  2627. return m_ValueErr;
  2628. }
  2629. void
  2630. TypedDataSymbolGroupFormat::OutputValue(void)
  2631. {
  2632. ULONG Tag;
  2633. if (m_ValueErr)
  2634. {
  2635. // windbg puts dummy entries with no expression
  2636. // in symbol groups and expects no output from them,
  2637. // so special case that.
  2638. if (!m_Entry->m_Expr || *m_Entry->m_Expr)
  2639. {
  2640. dprintf("<%s error>", ErrorString(m_ValueErr));
  2641. }
  2642. return;
  2643. }
  2644. m_CastData.OutputSimpleValue();
  2645. // For symbol groups we automatically dereference
  2646. // pointers to UDTs for convenience. Display the
  2647. // UDT type in the value for UDT pointers as there won't be
  2648. // a normal pointer child to display the type.
  2649. if (m_CastData.IsPointer() &&
  2650. m_CastData.m_Image &&
  2651. SymGetTypeInfo(m_CastData.m_Image->m_Process->m_SymHandle,
  2652. m_CastData.m_Image->m_BaseOfImage,
  2653. m_CastData.m_NextType, TI_GET_SYMTAG, &Tag) &&
  2654. Tag == SymTagUDT)
  2655. {
  2656. TypedData Deref = m_CastData;
  2657. if (!Deref.ConvertToDereference(TDACC_NONE,
  2658. g_Machine->m_Ptr64 ? 8 : 4))
  2659. {
  2660. dprintf(" ");
  2661. Deref.OutputType();
  2662. dprintf(" *");
  2663. }
  2664. }
  2665. }
  2666. void
  2667. TypedDataSymbolGroupFormat::OutputOffset(void)
  2668. {
  2669. if (m_ExprErr)
  2670. {
  2671. // Error message will be shown elsewhere.
  2672. return;
  2673. }
  2674. if (m_CastData.m_DataSource == TDATA_NONE)
  2675. {
  2676. return;
  2677. }
  2678. if (m_CastData.m_DataSource & TDATA_REGISTER)
  2679. {
  2680. dprintf("@%s", RegNameFromIndex(m_CastData.m_SourceRegister));
  2681. }
  2682. else
  2683. {
  2684. ULONG Err;
  2685. ULONG64 Addr;
  2686. if (Err = m_CastData.GetAbsoluteAddress(&Addr))
  2687. {
  2688. // No address.
  2689. }
  2690. else
  2691. {
  2692. dprintf("%s", FormatAddr64(Addr));
  2693. if (m_CastData.m_DataSource & TDATA_BITFIELD)
  2694. {
  2695. dprintf(" %d..%d",
  2696. m_CastData.m_BitPos,
  2697. m_CastData.m_BitPos + m_CastData.m_BitSize - 1);
  2698. }
  2699. }
  2700. }
  2701. }
  2702. void
  2703. TypedDataSymbolGroupFormat::OutputType(void)
  2704. {
  2705. if (m_ExprErr)
  2706. {
  2707. // Error message will be shown elsewhere.
  2708. return;
  2709. }
  2710. m_CastData.OutputType();
  2711. }
  2712. struct TdrcContext
  2713. {
  2714. SymbolGroupEntry* Parent;
  2715. SymbolGroupEntry* Child;
  2716. };
  2717. SymbolGroupEntry*
  2718. TypedDataSymbolGroupFormat::RefreshChildren(void)
  2719. {
  2720. if (!(m_Entry->m_Params.Flags & DEBUG_SYMBOL_EXPANDED))
  2721. {
  2722. return m_Entry->m_Next;
  2723. }
  2724. TdrcContext Context;
  2725. Context.Parent = m_Entry;
  2726. Context.Child = m_Entry->m_Next;
  2727. m_CastData.GetChildren(g_Machine->m_Ptr64 ? 8 : 4,
  2728. CHLF_DEREF_UDT_POINTERS |
  2729. CHLF_DISALLOW_ACCESS,
  2730. RefreshChildrenCb, &Context);
  2731. return Context.Child;
  2732. }
  2733. ULONG
  2734. TypedDataSymbolGroupFormat::RefreshChildrenCb(PVOID _Context,
  2735. PSTR Name, TypedData* Child)
  2736. {
  2737. TdrcContext* Context = (TdrcContext*)_Context;
  2738. // The assumption is that the child information gathered
  2739. // by this enumeration will be the same as the original
  2740. // child information so every callback should have a
  2741. // matching child entry. Check just to be sure, though.
  2742. if (Context->Child &&
  2743. Context->Child->m_Parent == Context->Parent)
  2744. {
  2745. if (Context->Child->m_BaseFormatKind == SGFORMAT_TYPED_DATA &&
  2746. !strcmp(Name, Context->Child->m_Expr))
  2747. {
  2748. Context->Child->m_BaseData = *Child;
  2749. if (Context->Child->m_Format->m_Kind == SGFORMAT_TYPED_DATA)
  2750. {
  2751. ((TypedDataSymbolGroupFormat*)Context->Child->m_Format)->
  2752. m_CastData.CopyDataSource(Child);
  2753. }
  2754. }
  2755. // Pass on the refresh to all children.
  2756. if (Context->Child->m_Format->m_Kind == SGFORMAT_TYPED_DATA)
  2757. {
  2758. Context->Child =
  2759. ((TypedDataSymbolGroupFormat*)Context->Child->m_Format)->
  2760. RefreshChildren();
  2761. }
  2762. else
  2763. {
  2764. Context->Child = Context->Child->m_Next;
  2765. }
  2766. }
  2767. //
  2768. // Look for the next sibling.
  2769. //
  2770. ULONG ParentLevel =
  2771. Context->Parent->m_Params.Flags & DEBUG_SYMBOL_EXPANSION_LEVEL_MASK;
  2772. while (Context->Child &&
  2773. (Context->Child->m_Params.Flags &
  2774. DEBUG_SYMBOL_EXPANSION_LEVEL_MASK) > ParentLevel + 1)
  2775. {
  2776. Context->Child = Context->Child->m_Next;
  2777. }
  2778. return NO_ERROR;
  2779. }
  2780. void
  2781. TypedDataSymbolGroupFormat::UpdateParams(void)
  2782. {
  2783. ULONG NameUsed;
  2784. if (m_ExprErr)
  2785. {
  2786. m_Entry->m_Params.Module = 0;
  2787. m_Entry->m_Params.TypeId = 0;
  2788. m_Entry->m_Params.SubElements = 0;
  2789. m_Entry->m_Params.Flags &= ~(DEBUG_SYMBOL_IS_ARRAY |
  2790. DEBUG_SYMBOL_IS_FLOAT |
  2791. DEBUG_SYMBOL_READ_ONLY);
  2792. return;
  2793. }
  2794. m_Entry->m_Params.Module = m_CastData.m_Image ?
  2795. m_CastData.m_Image->m_BaseOfImage : 0;
  2796. m_Entry->m_Params.TypeId = m_CastData.m_Type;
  2797. // If this node was ever expanded the true child count has
  2798. // been determined and set. Otherwise make a quick guess.
  2799. // If the true child count is zero the estimate will be done
  2800. // repeatedly but should be fast as there are no children.
  2801. if (!m_Entry->m_Params.SubElements &&
  2802. m_CastData.EstimateChildrenCounts(CHLF_DEREF_UDT_POINTERS,
  2803. &m_Entry->m_Params.SubElements,
  2804. &NameUsed))
  2805. {
  2806. m_Entry->m_Params.SubElements = 0;
  2807. }
  2808. m_Entry->m_Params.Flags &= ~(DEBUG_SYMBOL_IS_ARRAY |
  2809. DEBUG_SYMBOL_IS_FLOAT |
  2810. DEBUG_SYMBOL_READ_ONLY);
  2811. if (m_CastData.IsArray())
  2812. {
  2813. m_Entry->m_Params.Flags |= DEBUG_SYMBOL_IS_ARRAY;
  2814. }
  2815. else if (m_CastData.IsFloat())
  2816. {
  2817. m_Entry->m_Params.Flags |= DEBUG_SYMBOL_IS_FLOAT;
  2818. }
  2819. if (!m_CastData.IsWritable())
  2820. {
  2821. m_Entry->m_Params.Flags |= DEBUG_SYMBOL_READ_ONLY;
  2822. }
  2823. }
  2824. void
  2825. TypedDataSymbolGroupFormat::TestImages(void)
  2826. {
  2827. ImageInfo* Image;
  2828. if (m_Entry->m_Params.Module == 0)
  2829. {
  2830. Image = NULL;
  2831. }
  2832. else
  2833. {
  2834. Image = g_Process ?
  2835. g_Process->FindImageByOffset(m_Entry->m_Params.Module, FALSE) :
  2836. NULL;
  2837. }
  2838. if (Image != m_CastData.m_Image)
  2839. {
  2840. // The module list has changed, avoid
  2841. // referencing a possibly invalid image.
  2842. m_Entry->m_BaseData.ReleaseImage();
  2843. m_CastType.ReleaseImage();
  2844. m_CastData.ReleaseImage();
  2845. }
  2846. }
  2847. //----------------------------------------------------------------------------
  2848. //
  2849. // ExprSymbolGroupFormat.
  2850. //
  2851. //----------------------------------------------------------------------------
  2852. ULONG
  2853. ExprSymbolGroupFormat::Refresh(TypedDataAccess AllowAccess)
  2854. {
  2855. g_DisableErrorPrint++;
  2856. EvalExpression* RelChain = g_EvalReleaseChain;
  2857. g_EvalReleaseChain = NULL;
  2858. __try
  2859. {
  2860. ULONG64 OldPtr;
  2861. EvalExpression* Eval = GetEvaluator(DEBUG_EXPR_CPLUSPLUS, FALSE);
  2862. if (AllowAccess == TDACC_NONE)
  2863. {
  2864. // Parse-only is automatically reset after evaluation.
  2865. Eval->m_ParseOnly++;
  2866. }
  2867. Eval->Evaluate(m_Entry->m_Expr, NULL, EXPRF_DEFAULT,
  2868. &m_Entry->m_BaseData);
  2869. ReleaseEvaluator(Eval);
  2870. m_ExprErr = NO_ERROR;
  2871. OldPtr = m_CastData.m_Ptr;
  2872. m_CastData = m_Entry->m_BaseData;
  2873. if (m_Entry->m_Cast)
  2874. {
  2875. m_ExprErr = m_CastData.CastTo(&m_CastType);
  2876. }
  2877. if (!m_ExprErr)
  2878. {
  2879. if (m_CastData.IsPointer() &&
  2880. m_CastData.m_Ptr != OldPtr)
  2881. {
  2882. RefreshChildren();
  2883. }
  2884. }
  2885. }
  2886. __except(CommandExceptionFilter(GetExceptionInformation()))
  2887. {
  2888. m_ExprErr = GetExceptionCode() - COMMAND_EXCEPTION_BASE;
  2889. }
  2890. g_EvalReleaseChain = RelChain;
  2891. g_DisableErrorPrint--;
  2892. m_ValueErr = m_ExprErr;
  2893. UpdateParams();
  2894. return m_ExprErr;
  2895. }
  2896. //----------------------------------------------------------------------------
  2897. //
  2898. // ExtSymbolGroupFormat.
  2899. //
  2900. //----------------------------------------------------------------------------
  2901. CHAR g_ExtensionOutputDataBuffer[MAX_NAME];
  2902. class ExtenOutputCallbacks : public IDebugOutputCallbacks
  2903. {
  2904. public:
  2905. // IUnknown.
  2906. STDMETHOD(QueryInterface)(
  2907. THIS_
  2908. IN REFIID InterfaceId,
  2909. OUT PVOID* Interface
  2910. );
  2911. STDMETHOD_(ULONG, AddRef)(
  2912. THIS
  2913. );
  2914. STDMETHOD_(ULONG, Release)(
  2915. THIS
  2916. );
  2917. // IDebugOutputCallbacks.
  2918. STDMETHOD(Output)(
  2919. THIS_
  2920. IN ULONG Mask,
  2921. IN PCSTR Text
  2922. );
  2923. };
  2924. STDMETHODIMP
  2925. ExtenOutputCallbacks::QueryInterface(
  2926. THIS_
  2927. IN REFIID InterfaceId,
  2928. OUT PVOID* Interface
  2929. )
  2930. {
  2931. *Interface = NULL;
  2932. if (IsEqualIID(InterfaceId, IID_IUnknown) ||
  2933. IsEqualIID(InterfaceId, IID_IDebugOutputCallbacks))
  2934. {
  2935. *Interface = (IDebugOutputCallbacks *)this;
  2936. AddRef();
  2937. return S_OK;
  2938. }
  2939. else
  2940. {
  2941. return E_NOINTERFACE;
  2942. }
  2943. }
  2944. STDMETHODIMP_(ULONG)
  2945. ExtenOutputCallbacks::AddRef(
  2946. THIS
  2947. )
  2948. {
  2949. // This class is designed to be static so
  2950. // there's no true refcount.
  2951. return 1;
  2952. }
  2953. STDMETHODIMP_(ULONG)
  2954. ExtenOutputCallbacks::Release(
  2955. THIS
  2956. )
  2957. {
  2958. // This class is designed to be static so
  2959. // there's no true refcount.
  2960. return 0;
  2961. }
  2962. STDMETHODIMP
  2963. ExtenOutputCallbacks::Output(
  2964. THIS_
  2965. IN ULONG Mask,
  2966. IN PCSTR Text
  2967. )
  2968. {
  2969. if ((strlen(Text) + strlen(g_ExtensionOutputDataBuffer)) <
  2970. sizeof(g_ExtensionOutputDataBuffer))
  2971. {
  2972. strcat(g_ExtensionOutputDataBuffer, Text);
  2973. }
  2974. return S_OK;
  2975. }
  2976. ExtenOutputCallbacks g_ExtensionOutputCallback;
  2977. ExtSymbolGroupFormat::ExtSymbolGroupFormat(SymbolGroupEntry* Entry,
  2978. DebugClient* Client)
  2979. : SymbolGroupFormat(Entry, SGFORMAT_EXTENSION)
  2980. {
  2981. m_Client = Client;
  2982. m_Output = NULL;
  2983. }
  2984. ExtSymbolGroupFormat::~ExtSymbolGroupFormat(void)
  2985. {
  2986. delete [] m_Output;
  2987. }
  2988. ULONG
  2989. ExtSymbolGroupFormat::CreateChildren(DebugSymbolGroup* Group)
  2990. {
  2991. if (m_ExprErr)
  2992. {
  2993. return m_ExprErr;
  2994. }
  2995. if (!m_Output || !m_Entry->m_Params.SubElements)
  2996. {
  2997. return NOTFOUND;
  2998. }
  2999. //
  3000. // Create a simple text child for each line past
  3001. // the first.
  3002. //
  3003. ULONG i;
  3004. PSTR Scan;
  3005. SymbolGroupEntry* AddAfter = m_Entry;
  3006. Scan = m_Output + strlen(m_Output) + 1;
  3007. for (i = 0; i < m_Entry->m_Params.SubElements; i++)
  3008. {
  3009. char Line[32];
  3010. sprintf(Line, "%d", i + 1);
  3011. SymbolGroupEntry* Child = new SymbolGroupEntry;
  3012. TextSymbolGroupFormat* ChildFormat =
  3013. new TextSymbolGroupFormat(Child, Scan, FALSE);
  3014. if (!Child || !ChildFormat)
  3015. {
  3016. delete Child;
  3017. return NOMEMORY;
  3018. }
  3019. Child->m_Format = ChildFormat;
  3020. Child->m_Expr = _strdup(Line);
  3021. if (!Child->m_Expr)
  3022. {
  3023. delete Child;
  3024. return NOMEMORY;
  3025. }
  3026. Child->m_Parent = m_Entry;
  3027. Child->m_Params.Flags = ((m_Entry->m_Params.Flags &
  3028. DEBUG_SYMBOL_EXPANSION_LEVEL_MASK) + 1) |
  3029. DEBUG_SYMBOL_READ_ONLY;
  3030. Child->m_Next = AddAfter->m_Next;
  3031. Child->m_BaseFormatKind = SGFORMAT_TEXT;
  3032. ChildFormat->m_ExprErr = NO_ERROR;
  3033. AddAfter->m_Next = Child;
  3034. AddAfter = Child;
  3035. Group->m_NumEntries++;
  3036. }
  3037. return NO_ERROR;
  3038. }
  3039. ULONG
  3040. ExtSymbolGroupFormat::Refresh(TypedDataAccess AllowAccess)
  3041. {
  3042. PDEBUG_OUTPUT_CALLBACKS OutCbSave;
  3043. m_Client->FlushCallbacks();
  3044. OutCbSave = m_Client->m_OutputCb;
  3045. OutCtlSave OldCtl;
  3046. PushOutCtl(DEBUG_OUTCTL_THIS_CLIENT |
  3047. DEBUG_OUTCTL_OVERRIDE_MASK | DEBUG_OUTCTL_NOT_LOGGED,
  3048. m_Client, &OldCtl);
  3049. g_ExtensionOutputDataBuffer[0] = 0;
  3050. m_Client->m_OutputCb = &g_ExtensionOutputCallback;
  3051. EvalExpression* RelChain = g_EvalReleaseChain;
  3052. g_EvalReleaseChain = NULL;
  3053. g_DisableErrorPrint++;
  3054. __try
  3055. {
  3056. char AddrStr[32];
  3057. ULONG64 Addr;
  3058. EvalExpression* Eval = GetEvaluator(DEBUG_EXPR_CPLUSPLUS, FALSE);
  3059. if (AllowAccess == TDACC_NONE)
  3060. {
  3061. // Parse-only is automatically reset after evaluation.
  3062. Eval->m_ParseOnly++;
  3063. }
  3064. Eval->Evaluate(m_Entry->m_Expr, NULL, EXPRF_DEFAULT,
  3065. &m_Entry->m_BaseData);
  3066. ReleaseEvaluator(Eval);
  3067. if (m_Entry->m_BaseData.GetAbsoluteAddress(&Addr))
  3068. {
  3069. m_ExprErr = MEMORY;
  3070. }
  3071. else
  3072. {
  3073. HRESULT ExtStatus;
  3074. sprintf(AddrStr, "0x%I64x", Addr);
  3075. CallAnyExtension(m_Client, NULL, m_Entry->m_Cast + 1, AddrStr,
  3076. FALSE, FALSE, &ExtStatus);
  3077. // Ignore the extension status as it's rarely meaningful.
  3078. m_ExprErr = NO_ERROR;
  3079. }
  3080. }
  3081. __except(CommandExceptionFilter(GetExceptionInformation()))
  3082. {
  3083. m_ExprErr = GetExceptionCode() - COMMAND_EXCEPTION_BASE;
  3084. }
  3085. PopOutCtl(&OldCtl);
  3086. m_Client->FlushCallbacks();
  3087. m_Client->m_OutputCb = OutCbSave;
  3088. g_EvalReleaseChain = RelChain;
  3089. g_DisableErrorPrint--;
  3090. m_ValueErr = m_ExprErr;
  3091. if (m_ExprErr)
  3092. {
  3093. return m_ExprErr;
  3094. }
  3095. if (m_Output)
  3096. {
  3097. delete [] m_Output;
  3098. }
  3099. m_Output = new CHAR[strlen(g_ExtensionOutputDataBuffer) + 1];
  3100. if (!m_Output)
  3101. {
  3102. return NOMEMORY;
  3103. }
  3104. strcpy(m_Output, g_ExtensionOutputDataBuffer);
  3105. //
  3106. // Convert newlines to terminators for convenient output.
  3107. // Number of children == number of newlines - 1.
  3108. //
  3109. // While scanning, also update any children of this
  3110. // node with refreshed pointers.
  3111. //
  3112. PSTR Scan = m_Output;
  3113. SymbolGroupEntry* Child = m_Entry->m_Next;
  3114. m_Entry->m_Params.SubElements = 0;
  3115. while (Scan = strchr(Scan, '\n'))
  3116. {
  3117. m_Entry->m_Params.SubElements++;
  3118. *Scan++ = 0;
  3119. if (Child && Child->m_Parent == m_Entry)
  3120. {
  3121. // It would be cleaner if the child's Refresh()
  3122. // looked up the text value from the parent,
  3123. // but all the per-line lookups would be a lot
  3124. // of wasted effort.
  3125. ((TextSymbolGroupFormat*)Child->m_Format)->m_Text = Scan;
  3126. Child = Child->m_Next;
  3127. }
  3128. }
  3129. if (m_Entry->m_Params.SubElements)
  3130. {
  3131. m_Entry->m_Params.SubElements--;
  3132. }
  3133. //
  3134. // Any excess children are now blank.
  3135. //
  3136. while (Child && Child->m_Parent == m_Entry)
  3137. {
  3138. ((TextSymbolGroupFormat*)Child->m_Format)->m_Text = "";
  3139. Child = Child->m_Next;
  3140. }
  3141. return NO_ERROR;
  3142. }
  3143. ULONG
  3144. ExtSymbolGroupFormat::Write(PCSTR Value)
  3145. {
  3146. // No modifications allowed.
  3147. return MEMORY;
  3148. }
  3149. void
  3150. ExtSymbolGroupFormat::OutputValue(void)
  3151. {
  3152. if (m_ValueErr)
  3153. {
  3154. dprintf("<%s error>", ErrorString(m_ValueErr));
  3155. }
  3156. else
  3157. {
  3158. dprintf("%s", m_Output);
  3159. }
  3160. }
  3161. void
  3162. ExtSymbolGroupFormat::OutputType(void)
  3163. {
  3164. dprintf("%s", m_Entry->m_Cast);
  3165. }
  3166. void
  3167. ExtSymbolGroupFormat::OutputOffset(void)
  3168. {
  3169. // No offset.
  3170. }
  3171. //----------------------------------------------------------------------------
  3172. //
  3173. // TextSymbolGroupFormat.
  3174. //
  3175. //----------------------------------------------------------------------------
  3176. TextSymbolGroupFormat::TextSymbolGroupFormat(SymbolGroupEntry* Entry,
  3177. PSTR Text, BOOL Own)
  3178. : SymbolGroupFormat(Entry, SGFORMAT_TEXT)
  3179. {
  3180. m_Text = Text;
  3181. m_Own = Own;
  3182. Entry->m_Flags |= DEBUG_SYMBOL_READ_ONLY;
  3183. }
  3184. TextSymbolGroupFormat::~TextSymbolGroupFormat(void)
  3185. {
  3186. if (m_Own)
  3187. {
  3188. delete [] m_Text;
  3189. }
  3190. }
  3191. ULONG
  3192. TextSymbolGroupFormat::CreateChildren(DebugSymbolGroup* Group)
  3193. {
  3194. return NOTFOUND;
  3195. }
  3196. ULONG
  3197. TextSymbolGroupFormat::Refresh(TypedDataAccess AllowAccess)
  3198. {
  3199. return NO_ERROR;
  3200. }
  3201. ULONG
  3202. TextSymbolGroupFormat::Write(PCSTR Value)
  3203. {
  3204. // No modifications allowed.
  3205. return MEMORY;
  3206. }
  3207. void
  3208. TextSymbolGroupFormat::OutputValue(void)
  3209. {
  3210. dprintf("%s", m_Text);
  3211. }
  3212. void
  3213. TextSymbolGroupFormat::OutputType(void)
  3214. {
  3215. // No type.
  3216. }
  3217. void
  3218. TextSymbolGroupFormat::OutputOffset(void)
  3219. {
  3220. // No offset.
  3221. }
  3222. //----------------------------------------------------------------------------
  3223. //
  3224. // IDebugSymbolGroup.
  3225. //
  3226. //----------------------------------------------------------------------------
  3227. DebugSymbolGroup::DebugSymbolGroup(DebugClient* Client, ULONG ScopeGroup)
  3228. {
  3229. m_Client = Client;
  3230. m_ScopeGroup = ScopeGroup;
  3231. m_Refs = 1;
  3232. m_NumEntries = 0;
  3233. m_Entries = NULL;
  3234. m_LastClassExpanded = TRUE;
  3235. }
  3236. DebugSymbolGroup::~DebugSymbolGroup(void)
  3237. {
  3238. SymbolGroupEntry* Next;
  3239. while (m_Entries)
  3240. {
  3241. Next = m_Entries->m_Next;
  3242. delete m_Entries;
  3243. m_Entries = Next;
  3244. }
  3245. }
  3246. STDMETHODIMP
  3247. DebugSymbolGroup::QueryInterface(
  3248. THIS_
  3249. IN REFIID InterfaceId,
  3250. OUT PVOID* Interface
  3251. )
  3252. {
  3253. HRESULT Status;
  3254. *Interface = NULL;
  3255. Status = S_OK;
  3256. if (DbgIsEqualIID(InterfaceId, IID_IUnknown) ||
  3257. DbgIsEqualIID(InterfaceId, IID_IDebugSymbolGroup))
  3258. {
  3259. AddRef();
  3260. *Interface = (IDebugSymbolGroup *)this;
  3261. }
  3262. else
  3263. {
  3264. Status = E_NOINTERFACE;
  3265. }
  3266. return Status;
  3267. }
  3268. STDMETHODIMP_(ULONG)
  3269. DebugSymbolGroup::AddRef(
  3270. THIS
  3271. )
  3272. {
  3273. return InterlockedIncrement((PLONG)&m_Refs);
  3274. }
  3275. STDMETHODIMP_(ULONG)
  3276. DebugSymbolGroup::Release(
  3277. THIS
  3278. )
  3279. {
  3280. LONG Refs = InterlockedDecrement((PLONG)&m_Refs);
  3281. if (Refs == 0)
  3282. {
  3283. ENTER_ENGINE();
  3284. delete this;
  3285. LEAVE_ENGINE();
  3286. }
  3287. return Refs;
  3288. }
  3289. STDMETHODIMP
  3290. DebugSymbolGroup::GetNumberSymbols(
  3291. THIS_
  3292. OUT PULONG Number
  3293. )
  3294. {
  3295. ENTER_ENGINE();
  3296. *Number = m_NumEntries;
  3297. LEAVE_ENGINE();
  3298. return S_OK;
  3299. }
  3300. STDMETHODIMP
  3301. DebugSymbolGroup::AddSymbol(
  3302. THIS_
  3303. IN PCSTR Name,
  3304. IN OUT PULONG Index
  3305. )
  3306. {
  3307. HRESULT Status;
  3308. ENTER_ENGINE();
  3309. if (!IS_CUR_MACHINE_ACCESSIBLE())
  3310. {
  3311. Status = E_UNEXPECTED;
  3312. }
  3313. else
  3314. {
  3315. SymbolGroupEntry* Entry;
  3316. if ((Status = NewEntry(Name, NULL, &Entry)) == S_OK)
  3317. {
  3318. LinkEntry(Entry, Index);
  3319. }
  3320. }
  3321. LEAVE_ENGINE();
  3322. return Status;
  3323. }
  3324. STDMETHODIMP
  3325. DebugSymbolGroup::RemoveSymbolByName(
  3326. THIS_
  3327. IN PCSTR Name
  3328. )
  3329. {
  3330. HRESULT Status;
  3331. ENTER_ENGINE();
  3332. // Don't delete children.
  3333. SymbolGroupEntry* Entry = FindEntryByExpr(NULL, NULL, Name);
  3334. if (Entry)
  3335. {
  3336. DeleteEntry(Entry);
  3337. Status = S_OK;
  3338. }
  3339. else
  3340. {
  3341. Status = E_INVALIDARG;
  3342. }
  3343. LEAVE_ENGINE();
  3344. return Status;
  3345. }
  3346. STDMETHODIMP
  3347. DebugSymbolGroup::RemoveSymbolByIndex(
  3348. THIS_
  3349. IN ULONG Index
  3350. )
  3351. {
  3352. HRESULT Status;
  3353. ENTER_ENGINE();
  3354. // Don't delete children.
  3355. SymbolGroupEntry* Entry = FindEntryByIndex(Index);
  3356. if (Entry && !Entry->m_Parent)
  3357. {
  3358. DeleteEntry(Entry);
  3359. Status = S_OK;
  3360. }
  3361. else
  3362. {
  3363. Status = E_INVALIDARG;
  3364. }
  3365. #if DBG_SYMGROUP_ENABLED
  3366. dprintf("Deleted %lx\n", Index);
  3367. ShowAll();
  3368. #endif
  3369. LEAVE_ENGINE();
  3370. return Status;
  3371. }
  3372. STDMETHODIMP
  3373. DebugSymbolGroup::GetSymbolName(
  3374. THIS_
  3375. IN ULONG Index,
  3376. OUT OPTIONAL PSTR Buffer,
  3377. IN ULONG BufferSize,
  3378. OUT OPTIONAL PULONG NameSize
  3379. )
  3380. {
  3381. HRESULT Status;
  3382. ENTER_ENGINE();
  3383. SymbolGroupEntry* Entry = FindEntryByIndex(Index);
  3384. if (Entry)
  3385. {
  3386. Status = FillStringBuffer(Entry->m_Expr, 0,
  3387. Buffer, BufferSize, NameSize);
  3388. }
  3389. else
  3390. {
  3391. Status = E_INVALIDARG;
  3392. }
  3393. LEAVE_ENGINE();
  3394. return Status;
  3395. }
  3396. STDMETHODIMP
  3397. DebugSymbolGroup::GetSymbolParameters(
  3398. THIS_
  3399. IN ULONG Start,
  3400. IN ULONG Count,
  3401. OUT /* size_is(Count) */ PDEBUG_SYMBOL_PARAMETERS Params
  3402. )
  3403. {
  3404. HRESULT Status;
  3405. ENTER_ENGINE();
  3406. SymbolGroupEntry* Entry;
  3407. if (!IS_CUR_MACHINE_ACCESSIBLE())
  3408. {
  3409. Status = E_UNEXPECTED;
  3410. goto Exit;
  3411. }
  3412. else if (!(Entry = FindEntryByIndex(Start)))
  3413. {
  3414. Status = E_INVALIDARG;
  3415. goto Exit;
  3416. }
  3417. TestImages();
  3418. Status = S_OK;
  3419. #if DBG_SYMGROUP_ENABLED
  3420. dprintf("GetSymbolParameters: will return %lx sym params\n", Count);
  3421. ShowAll();
  3422. #endif
  3423. while (Count)
  3424. {
  3425. if (!Entry)
  3426. {
  3427. Status = E_INVALIDARG;
  3428. goto Exit;
  3429. }
  3430. *Params = Entry->m_Params;
  3431. // Update the parent index on demand so that it
  3432. // doesn't have to be tracked through all list updates.
  3433. Params->ParentSymbol = FindEntryIndex(Entry->m_Parent);
  3434. Params++;
  3435. Entry = Entry->m_Next;
  3436. Count--;
  3437. }
  3438. #if DBG_SYMGROUP_ENABLED
  3439. dprintf("End GetSymbolParameters\n");
  3440. ShowAll();
  3441. #endif
  3442. Exit:
  3443. LEAVE_ENGINE();
  3444. return Status;
  3445. }
  3446. STDMETHODIMP
  3447. DebugSymbolGroup::ExpandSymbol(
  3448. THIS_
  3449. IN ULONG Index,
  3450. IN BOOL Expand
  3451. )
  3452. {
  3453. HRESULT Status;
  3454. ENTER_ENGINE();
  3455. SymbolGroupEntry* Entry;
  3456. if (!IS_CUR_MACHINE_ACCESSIBLE())
  3457. {
  3458. Status = E_UNEXPECTED;
  3459. }
  3460. else if (!(Entry = FindEntryByIndex(Index)))
  3461. {
  3462. Status = E_INVALIDARG;
  3463. }
  3464. else
  3465. {
  3466. TestImages();
  3467. Status = SetEntryExpansion(Entry, Expand);
  3468. }
  3469. LEAVE_ENGINE();
  3470. return Status;
  3471. }
  3472. STDMETHODIMP
  3473. DebugSymbolGroup::OutputSymbols(
  3474. THIS_
  3475. IN ULONG OutputControl,
  3476. IN ULONG Flags,
  3477. IN ULONG Start,
  3478. IN ULONG Count
  3479. )
  3480. {
  3481. HRESULT Status;
  3482. if (Flags & ~(DEBUG_OUTPUT_SYMBOLS_NO_NAMES |
  3483. DEBUG_OUTPUT_SYMBOLS_NO_OFFSETS |
  3484. DEBUG_OUTPUT_SYMBOLS_NO_VALUES |
  3485. DEBUG_OUTPUT_SYMBOLS_NO_TYPES))
  3486. {
  3487. return E_INVALIDARG;
  3488. }
  3489. ENTER_ENGINE();
  3490. SymbolGroupEntry* Entry;
  3491. if (!IS_CUR_MACHINE_ACCESSIBLE())
  3492. {
  3493. Status = E_UNEXPECTED;
  3494. goto Exit;
  3495. }
  3496. else if (!(Entry = FindEntryByIndex(Start)))
  3497. {
  3498. Status = E_INVALIDARG;
  3499. goto Exit;
  3500. }
  3501. TestImages();
  3502. #if DBG_SYMGROUP_ENABLED
  3503. dprintf("Output\n");
  3504. ShowAll();
  3505. #endif
  3506. OutCtlSave OldCtl;
  3507. if (!PushOutCtl(OutputControl, m_Client, &OldCtl))
  3508. {
  3509. Status = E_INVALIDARG;
  3510. goto Exit;
  3511. }
  3512. Status = S_OK;
  3513. while (Count)
  3514. {
  3515. if (!Entry)
  3516. {
  3517. Status = E_INVALIDARG;
  3518. break;
  3519. }
  3520. if (!(Entry->m_Flags & SYMBOL_ECLIPSED))
  3521. {
  3522. Entry->m_Format->Refresh(TDACC_REQUIRE);
  3523. }
  3524. if (!(Flags & DEBUG_OUTPUT_SYMBOLS_NO_NAMES))
  3525. {
  3526. dprintf("%s%s", Entry->m_Expr, DEBUG_OUTPUT_NAME_END);
  3527. }
  3528. if (!(Flags & DEBUG_OUTPUT_SYMBOLS_NO_VALUES))
  3529. {
  3530. if (!(Entry->m_Flags & SYMBOL_ECLIPSED))
  3531. {
  3532. Entry->m_Format->OutputValue();
  3533. }
  3534. else
  3535. {
  3536. dprintf("<Eclipsed>");
  3537. }
  3538. dprintf(DEBUG_OUTPUT_VALUE_END);
  3539. }
  3540. if (!(Flags & DEBUG_OUTPUT_SYMBOLS_NO_OFFSETS))
  3541. {
  3542. Entry->m_Format->OutputOffset();
  3543. dprintf(DEBUG_OUTPUT_OFFSET_END);
  3544. }
  3545. if (!(Flags & DEBUG_OUTPUT_SYMBOLS_NO_TYPES))
  3546. {
  3547. Entry->m_Format->OutputType();
  3548. dprintf(DEBUG_OUTPUT_TYPE_END);
  3549. }
  3550. Entry = Entry->m_Next;
  3551. Count--;
  3552. }
  3553. PopOutCtl(&OldCtl);
  3554. Exit:
  3555. LEAVE_ENGINE();
  3556. return Status;
  3557. }
  3558. STDMETHODIMP
  3559. DebugSymbolGroup::WriteSymbol(
  3560. THIS_
  3561. IN ULONG Index,
  3562. IN PCSTR Value
  3563. )
  3564. {
  3565. if (!Value)
  3566. {
  3567. return E_INVALIDARG;
  3568. }
  3569. HRESULT Status;
  3570. ENTER_ENGINE();
  3571. SymbolGroupEntry* Entry;
  3572. if (!IS_CUR_MACHINE_ACCESSIBLE())
  3573. {
  3574. Status = E_UNEXPECTED;
  3575. goto Exit;
  3576. }
  3577. else if (!(Entry = FindEntryByIndex(Index)))
  3578. {
  3579. Status = E_INVALIDARG;
  3580. goto Exit;
  3581. }
  3582. TestImages();
  3583. #if DBG_SYMGROUP_ENABLED
  3584. dprintf("WriteSymbol %lx : %s\n", Index, Value);
  3585. #endif
  3586. Status = Entry->m_Format->Write(Value) ? E_FAIL : S_OK;
  3587. Exit:
  3588. LEAVE_ENGINE();
  3589. return Status;
  3590. }
  3591. STDMETHODIMP
  3592. DebugSymbolGroup::OutputAsType(
  3593. THIS_
  3594. IN ULONG Index,
  3595. IN PCSTR Type
  3596. )
  3597. {
  3598. HRESULT Status;
  3599. ENTER_ENGINE();
  3600. SymbolGroupEntry* Entry;
  3601. PSTR Cast = NULL;
  3602. ULONG CastLen;
  3603. SymbolGroupFormat* NewFormat = NULL;
  3604. if (!IS_CUR_MACHINE_ACCESSIBLE())
  3605. {
  3606. Status = E_UNEXPECTED;
  3607. goto Exit;
  3608. }
  3609. else if (!(Entry = FindEntryByIndex(Index)))
  3610. {
  3611. Status = E_INVALIDARG;
  3612. goto Exit;
  3613. }
  3614. TestImages();
  3615. if ((Entry->m_BaseFormatKind != SGFORMAT_TYPED_DATA &&
  3616. Entry->m_BaseFormatKind != SGFORMAT_EXPRESSION &&
  3617. Entry->m_BaseFormatKind != SGFORMAT_EXTENSION) ||
  3618. Entry->m_Format->m_ExprErr)
  3619. {
  3620. Status = E_INVALIDARG;
  3621. goto Exit;
  3622. }
  3623. if (Type && *Type)
  3624. {
  3625. // Allocate extra space for cast evaluation expression.
  3626. CastLen = strlen(Type) + 1;
  3627. Cast = (PSTR)malloc(CastLen + 3);
  3628. if (!Cast)
  3629. {
  3630. Status = E_OUTOFMEMORY;
  3631. goto Exit;
  3632. }
  3633. memcpy(Cast, Type, CastLen);
  3634. }
  3635. //
  3636. // Entries may need to be shifted between kinds of
  3637. // symbol group formats according to what the cast is.
  3638. //
  3639. if (Cast && *Cast == '!')
  3640. {
  3641. //
  3642. // Entry needs to use an extension format.
  3643. //
  3644. NewFormat = new ExtSymbolGroupFormat(Entry, m_Client);
  3645. if (!NewFormat)
  3646. {
  3647. Status = E_OUTOFMEMORY;
  3648. goto Exit;
  3649. }
  3650. NewFormat->m_ExprErr = NO_ERROR;
  3651. }
  3652. else
  3653. {
  3654. TypedDataSymbolGroupFormat* TdFormat;
  3655. //
  3656. // Entry is not an extension entry.
  3657. //
  3658. TdFormat = Entry->m_BaseFormatKind == SGFORMAT_EXPRESSION ?
  3659. new ExprSymbolGroupFormat(Entry) :
  3660. new TypedDataSymbolGroupFormat(Entry);
  3661. if (!TdFormat)
  3662. {
  3663. Status = E_OUTOFMEMORY;
  3664. goto Exit;
  3665. }
  3666. NewFormat = TdFormat;
  3667. TdFormat->m_CastData = Entry->m_BaseData;
  3668. if (Cast)
  3669. {
  3670. //
  3671. // Determine cast type.
  3672. //
  3673. memmove(Cast + 1, Cast, CastLen);
  3674. Cast[0] = '(';
  3675. Cast[CastLen] = ')';
  3676. Cast[CastLen + 1] = '0';
  3677. Cast[CastLen + 2] = 0;
  3678. g_DisableErrorPrint++;
  3679. EvalExpression* RelChain = g_EvalReleaseChain;
  3680. g_EvalReleaseChain = NULL;
  3681. __try
  3682. {
  3683. EvalExpression* Eval =
  3684. GetEvaluator(DEBUG_EXPR_CPLUSPLUS, FALSE);
  3685. Eval->Evaluate(Cast, NULL, EXPRF_DEFAULT,
  3686. &TdFormat->m_CastType);
  3687. ReleaseEvaluator(Eval);
  3688. }
  3689. __except(CommandExceptionFilter(GetExceptionInformation()))
  3690. {
  3691. g_DisableErrorPrint--;
  3692. Status = E_FAIL;
  3693. goto Exit;
  3694. }
  3695. g_EvalReleaseChain = RelChain;
  3696. g_DisableErrorPrint--;
  3697. memmove(Cast, Cast + 1, CastLen);
  3698. Cast[CastLen - 1] = 0;
  3699. if (TdFormat->m_CastData.CastTo(&TdFormat->m_CastType))
  3700. {
  3701. Status = E_FAIL;
  3702. goto Exit;
  3703. }
  3704. }
  3705. TdFormat->m_ExprErr = NO_ERROR;
  3706. TdFormat->m_ValueErr = TdFormat->m_ExprErr;
  3707. TdFormat->UpdateParams();
  3708. }
  3709. // The cast may have radically altered the subelements
  3710. // for this entry so collapse the entry.
  3711. SetEntryExpansion(Entry, FALSE);
  3712. free(Entry->m_Cast);
  3713. Entry->m_Cast = Cast;
  3714. Cast = NULL;
  3715. delete Entry->m_Format;
  3716. Entry->m_Format = NewFormat;
  3717. NewFormat = NULL;
  3718. Status = S_OK;
  3719. Exit:
  3720. free(Cast);
  3721. delete NewFormat;
  3722. LEAVE_ENGINE();
  3723. return Status;
  3724. }
  3725. //
  3726. // Private DebugSymbolGroup methods
  3727. //
  3728. SymbolGroupEntry*
  3729. DebugSymbolGroup::FindEntryByIndex(ULONG Index)
  3730. {
  3731. SymbolGroupEntry* Entry;
  3732. for (Entry = m_Entries; Entry; Entry = Entry->m_Next)
  3733. {
  3734. if (Index-- == 0)
  3735. {
  3736. return Entry;
  3737. }
  3738. }
  3739. return NULL;
  3740. }
  3741. SymbolGroupEntry*
  3742. DebugSymbolGroup::FindEntryByExpr(SymbolGroupEntry* Parent,
  3743. SymbolGroupEntry* After,
  3744. PCSTR Expr)
  3745. {
  3746. SymbolGroupEntry* Entry;
  3747. // Entries are sorted by parent/child so children will
  3748. // immediately follow a parent.
  3749. if (!After)
  3750. {
  3751. Entry = Parent ? Parent->m_Next : m_Entries;
  3752. }
  3753. else
  3754. {
  3755. Entry = After->m_Next;
  3756. }
  3757. while (Entry)
  3758. {
  3759. if (Entry->m_Parent == Parent &&
  3760. !strcmp(Expr, Entry->m_Expr))
  3761. {
  3762. return Entry;
  3763. }
  3764. Entry = Entry->m_Next;
  3765. }
  3766. return NULL;
  3767. }
  3768. ULONG
  3769. DebugSymbolGroup::FindEntryIndex(SymbolGroupEntry* Entry)
  3770. {
  3771. SymbolGroupEntry* Cur;
  3772. ULONG Index = 0;
  3773. for (Cur = m_Entries; Cur; Cur = Cur->m_Next)
  3774. {
  3775. if (Cur == Entry)
  3776. {
  3777. return Index;
  3778. }
  3779. Index++;
  3780. }
  3781. return DEBUG_ANY_ID;
  3782. }
  3783. void
  3784. DebugSymbolGroup::DeleteEntry(SymbolGroupEntry* Entry)
  3785. {
  3786. SymbolGroupEntry* Prev;
  3787. SymbolGroupEntry* Cur;
  3788. //
  3789. // Locate the entry.
  3790. //
  3791. Prev = NULL;
  3792. for (Cur = m_Entries; Cur; Cur = Cur->m_Next)
  3793. {
  3794. if (Cur == Entry)
  3795. {
  3796. break;
  3797. }
  3798. Prev = Cur;
  3799. }
  3800. if (!Cur)
  3801. {
  3802. return;
  3803. }
  3804. DeleteChildren(Entry);
  3805. if (!Prev)
  3806. {
  3807. m_Entries = Entry->m_Next;
  3808. }
  3809. else
  3810. {
  3811. Prev->m_Next = Entry->m_Next;
  3812. }
  3813. delete Entry;
  3814. m_NumEntries--;
  3815. }
  3816. void
  3817. DebugSymbolGroup::DeleteChildren(SymbolGroupEntry* Parent)
  3818. {
  3819. //
  3820. // The list of entries is sorted by parent/child
  3821. // relationship so any children follow the parent
  3822. // immediately.
  3823. //
  3824. SymbolGroupEntry* Cur;
  3825. SymbolGroupEntry* Del;
  3826. ULONG Level = Parent->m_Params.Flags & DEBUG_SYMBOL_EXPANSION_LEVEL_MASK;
  3827. Cur = Parent->m_Next;
  3828. while (Cur)
  3829. {
  3830. if ((Cur->m_Params.Flags & DEBUG_SYMBOL_EXPANSION_LEVEL_MASK) <= Level)
  3831. {
  3832. // Any entry of the same or less expansion than the parent
  3833. // cannot be a child so stop.
  3834. break;
  3835. }
  3836. else
  3837. {
  3838. // Found a child entry so delete.
  3839. Del = Cur;
  3840. Cur = Cur->m_Next;
  3841. delete Del;
  3842. m_NumEntries--;
  3843. }
  3844. }
  3845. Parent->m_Next = Cur;
  3846. }
  3847. void
  3848. DebugSymbolGroup::LinkEntry(IN SymbolGroupEntry* Entry,
  3849. IN OUT PULONG Index)
  3850. {
  3851. //
  3852. // Find insertion index point.
  3853. //
  3854. SymbolGroupEntry* Prev;
  3855. SymbolGroupEntry* Cur;
  3856. ULONG CurIdx = 0;
  3857. Prev = NULL;
  3858. for (Cur = m_Entries; Cur; Cur = Cur->m_Next)
  3859. {
  3860. if (CurIdx == *Index)
  3861. {
  3862. break;
  3863. }
  3864. CurIdx++;
  3865. Prev = Cur;
  3866. }
  3867. if (!Prev)
  3868. {
  3869. Entry->m_Next = m_Entries;
  3870. m_Entries = Entry;
  3871. }
  3872. else
  3873. {
  3874. Entry->m_Next = Prev->m_Next;
  3875. Prev->m_Next = Entry;
  3876. }
  3877. m_NumEntries++;
  3878. *Index = CurIdx;
  3879. #if DBG_SYMGROUP_ENABLED
  3880. dprintf("Added %s at %lx\n", Entry->m_Expr, *Index);
  3881. ShowAll();
  3882. #endif
  3883. }
  3884. HRESULT
  3885. DebugSymbolGroup::NewEntry(IN PCSTR Expr,
  3886. IN OPTIONAL PSYMBOL_INFO SymInfo,
  3887. OUT SymbolGroupEntry** EntryRet)
  3888. {
  3889. HRESULT Status;
  3890. SymbolGroupEntry* Entry = new SymbolGroupEntry;
  3891. TypedDataSymbolGroupFormat* Format = SymInfo ?
  3892. new TypedDataSymbolGroupFormat(Entry) :
  3893. new ExprSymbolGroupFormat(Entry);
  3894. if (!Entry || !Format)
  3895. {
  3896. delete Entry;
  3897. return E_OUTOFMEMORY;
  3898. }
  3899. Entry->m_Format = Format;
  3900. if (!(Entry->m_Expr = _strdup(Expr)))
  3901. {
  3902. Status = E_OUTOFMEMORY;
  3903. goto Error;
  3904. }
  3905. //
  3906. // We're just creating the entries here so there's
  3907. // no need to attempt to read content yet. Refresh
  3908. // will be called later.
  3909. //
  3910. if (SymInfo)
  3911. {
  3912. Format->m_ExprErr = Entry->m_BaseData.
  3913. SetToSymbol(g_Process, (PSTR)Expr, SymInfo,
  3914. TDACC_NONE, g_Machine->m_Ptr64 ? 8 : 4);
  3915. Entry->m_BaseFormatKind = SGFORMAT_TYPED_DATA;
  3916. Format->m_CastData = Entry->m_BaseData;
  3917. Format->UpdateParams();
  3918. }
  3919. else
  3920. {
  3921. // We have to evaluate in order to determine
  3922. // the result type, but evaluate without access
  3923. // to just evaluate the result type without
  3924. // requiring memory access.
  3925. Format->Refresh(TDACC_NONE);
  3926. Entry->m_BaseFormatKind = SGFORMAT_EXPRESSION;
  3927. Format->m_CastData = Entry->m_BaseData;
  3928. }
  3929. *EntryRet = Entry;
  3930. return S_OK;
  3931. Error:
  3932. delete Entry;
  3933. return Status;
  3934. }
  3935. HRESULT
  3936. DebugSymbolGroup::SetEntryExpansion(IN SymbolGroupEntry* Entry,
  3937. IN BOOL Expand)
  3938. {
  3939. HRESULT Status;
  3940. if (Expand &&
  3941. (Entry->m_Params.Flags & DEBUG_SYMBOL_EXPANSION_LEVEL_MASK) ==
  3942. DEBUG_SYMBOL_EXPANSION_LEVEL_MASK)
  3943. {
  3944. return E_INVALIDARG;
  3945. }
  3946. #if DBG_SYMGROUP_ENABLED
  3947. dprintf("Expanding %s (%lx to be %s)\n",
  3948. Entry->m_Expr, Entry->m_Params.SubElements,
  3949. Expand ? "created" : "deleted");
  3950. ShowAll();
  3951. #endif
  3952. //
  3953. // Special case - check and store if "this" is expanded/collapsed
  3954. //
  3955. if (!strcmp(Entry->m_Expr, "this"))
  3956. {
  3957. m_LastClassExpanded = Expand;
  3958. }
  3959. if (!Expand)
  3960. {
  3961. if (Entry->m_Params.Flags & DEBUG_SYMBOL_EXPANDED)
  3962. {
  3963. DeleteChildren(Entry);
  3964. Entry->m_Params.Flags &= ~DEBUG_SYMBOL_EXPANDED;
  3965. }
  3966. Status = S_OK;
  3967. }
  3968. else
  3969. {
  3970. if (Entry->m_Params.Flags & DEBUG_SYMBOL_EXPANDED)
  3971. {
  3972. Status = S_OK;
  3973. }
  3974. else
  3975. {
  3976. if (!Entry->m_Format->CreateChildren(this))
  3977. {
  3978. Entry->m_Params.Flags |= DEBUG_SYMBOL_EXPANDED;
  3979. Status = S_OK;
  3980. }
  3981. else
  3982. {
  3983. Status = E_FAIL;
  3984. }
  3985. }
  3986. }
  3987. #if DBG_SYMGROUP_ENABLED
  3988. dprintf("Expanded %s (%lx %s)\n",
  3989. Entry->m_Expr, Entry->m_Params.SubElements,
  3990. (Entry->m_Params.Flags & DEBUG_SYMBOL_EXPANDED) ?
  3991. "new" : "deleted");
  3992. ShowAll();
  3993. #endif
  3994. return Status;
  3995. }
  3996. HRESULT
  3997. DebugSymbolGroup::AddCurrentLocals(void)
  3998. {
  3999. // Always return success since this request is
  4000. // processed even if we didn't add anything.
  4001. HRESULT Status = S_OK;
  4002. RequireCurrentScope();
  4003. SymbolGroupEntry* Entry;
  4004. for (Entry = m_Entries; Entry; Entry = Entry->m_Next)
  4005. {
  4006. if (!Entry->m_Parent)
  4007. {
  4008. // Assume everything is visible now.
  4009. Entry->m_Flags &= ~(SYMBOL_ECLIPSED | SYMBOL_IN_SCOPE);
  4010. }
  4011. }
  4012. EnumerateLocals(AddAllScopedSymbols, (PVOID)this);
  4013. Restart:
  4014. #if DBG_SYMGROUP_ENABLED
  4015. dprintf("Enum locals loop:\n");
  4016. ShowAll();
  4017. #endif
  4018. for (Entry = m_Entries; Entry; Entry = Entry->m_Next)
  4019. {
  4020. if (!Entry->m_Parent)
  4021. {
  4022. if (!(Entry->m_Flags & SYMBOL_IN_SCOPE))
  4023. {
  4024. DeleteEntry(Entry);
  4025. // Restart scan as the list just changed.
  4026. goto Restart;
  4027. }
  4028. }
  4029. }
  4030. SymbolGroupEntry* ThisEntry = NULL;
  4031. for (Entry = m_Entries; Entry; Entry = Entry->m_Next)
  4032. {
  4033. if (!Entry->m_Parent)
  4034. {
  4035. if (Entry->m_Flags & SYMBOL_IN_SCOPE)
  4036. {
  4037. Entry->m_Flags &= ~SYMBOL_IN_SCOPE;
  4038. // Remember if there's a plain "this" reference
  4039. // for later expansion.
  4040. if (!strcmp(Entry->m_Expr, "this"))
  4041. {
  4042. ThisEntry = Entry;
  4043. }
  4044. }
  4045. }
  4046. }
  4047. if (ThisEntry && m_LastClassExpanded)
  4048. {
  4049. SetEntryExpansion(ThisEntry, TRUE);
  4050. }
  4051. return Status;
  4052. }
  4053. ULONG
  4054. DebugSymbolGroup::FindLocalInsertionIndex(SymbolGroupEntry* Entry)
  4055. {
  4056. ULONG Index = 0;
  4057. SymbolGroupEntry* Compare;
  4058. for (Compare = m_Entries; Compare; Compare = Compare->m_Next, Index++)
  4059. {
  4060. if (Compare->m_Parent)
  4061. {
  4062. continue;
  4063. }
  4064. //
  4065. // Sort arguments by address and locals by name.
  4066. //
  4067. if ((Compare->m_Params.Flags & DEBUG_SYMBOL_IS_ARGUMENT) ||
  4068. (Entry->m_Params.Flags & DEBUG_SYMBOL_IS_ARGUMENT))
  4069. {
  4070. if ((Compare->m_Params.Flags & DEBUG_SYMBOL_IS_ARGUMENT) &&
  4071. (Entry->m_Params.Flags & DEBUG_SYMBOL_IS_ARGUMENT))
  4072. {
  4073. // We can only meaningfully sort frame-relative
  4074. // arguments.
  4075. if (Compare->m_BaseFormatKind == SGFORMAT_TYPED_DATA &&
  4076. Entry->m_BaseFormatKind == SGFORMAT_TYPED_DATA &&
  4077. (Compare->m_BaseData.m_DataSource &
  4078. TDATA_FRAME_RELATIVE) &&
  4079. (Entry->m_BaseData.m_DataSource &
  4080. TDATA_FRAME_RELATIVE) &&
  4081. Compare->m_BaseData.m_SourceOffset >
  4082. Entry->m_BaseData.m_SourceOffset)
  4083. {
  4084. return Index;
  4085. }
  4086. }
  4087. else if (Entry->m_Params.Flags & DEBUG_SYMBOL_IS_ARGUMENT)
  4088. {
  4089. return Index;
  4090. }
  4091. }
  4092. else
  4093. {
  4094. if (_stricmp(Compare->m_Expr, Entry->m_Expr) > 0)
  4095. {
  4096. return Index;
  4097. }
  4098. }
  4099. }
  4100. // Place at the end.
  4101. return m_NumEntries;
  4102. }
  4103. BOOL CALLBACK
  4104. DebugSymbolGroup::AddAllScopedSymbols(PSYMBOL_INFO SymInfo,
  4105. ULONG Size,
  4106. PVOID Context)
  4107. {
  4108. DebugSymbolGroup* Caller = (DebugSymbolGroup*)Context;
  4109. BOOL SymbolEclipsed = FALSE;
  4110. SymbolGroupEntry* Entry;
  4111. //
  4112. // Ingore symbols which do not match Caller's scope
  4113. //
  4114. if (Caller->m_ScopeGroup == DEBUG_SCOPE_GROUP_ARGUMENTS)
  4115. {
  4116. if (!(SymInfo->Flags & SYMFLAG_PARAMETER))
  4117. {
  4118. return TRUE;
  4119. }
  4120. } else if (Caller->m_ScopeGroup != DEBUG_SCOPE_GROUP_LOCALS)
  4121. {
  4122. return TRUE;
  4123. }
  4124. Entry = Caller->FindEntryByExpr(NULL, NULL, SymInfo->Name);
  4125. while (Entry)
  4126. {
  4127. if (Entry->m_Format->m_Kind == SGFORMAT_TYPED_DATA &&
  4128. Entry->m_BaseData.m_Image &&
  4129. Entry->m_BaseData.m_Image->m_BaseOfImage == SymInfo->ModBase &&
  4130. Entry->m_BaseData.m_Type == SymInfo->TypeIndex &&
  4131. Entry->m_BaseData.EquivInfoSource(SymInfo,
  4132. Entry->m_BaseData.m_Image))
  4133. {
  4134. // The entry matches the enumerated symbol.
  4135. Entry->m_Flags |= SYMBOL_IN_SCOPE;
  4136. return TRUE;
  4137. }
  4138. else if (!(Entry->m_Flags & SYMBOL_IN_SCOPE))
  4139. {
  4140. // The enumerated symbol hasn't been
  4141. // processed by this routine yet, so it
  4142. // must be some old local var from previous scope.
  4143. Entry->m_Flags |= SYMBOL_ECLIPSED;
  4144. }
  4145. else
  4146. {
  4147. // The enumerated symbol is a newer same-named local,
  4148. // so the current entry is the symbol to be eclipsed.
  4149. SymbolEclipsed = TRUE;
  4150. }
  4151. Entry = Caller->FindEntryByExpr(NULL, Entry, SymInfo->Name);
  4152. }
  4153. if (Caller->NewEntry(SymInfo->Name, SymInfo, &Entry) != S_OK)
  4154. {
  4155. return FALSE;
  4156. }
  4157. Entry->m_Flags |= SYMBOL_IN_SCOPE;
  4158. Entry->m_Flags |= SymbolEclipsed ? SYMBOL_ECLIPSED : 0;
  4159. Entry->m_Params.Flags |=
  4160. (SymInfo->Flags & SYMFLAG_PARAMETER) ? DEBUG_SYMBOL_IS_ARGUMENT :
  4161. ((SymInfo->Flags & SYMFLAG_LOCAL) ? DEBUG_SYMBOL_IS_LOCAL : 0);
  4162. ULONG Index = Caller->FindLocalInsertionIndex(Entry);
  4163. if (SymbolEclipsed && Index)
  4164. {
  4165. // Symbol at 'Index' is the symbol with same name,
  4166. // add this *before* 'Index' since order
  4167. // is important when checking for the inner-scope symbol
  4168. Index--;
  4169. }
  4170. Caller->LinkEntry(Entry, &Index);
  4171. #if DBG_SYMGROUP_ENABLED
  4172. dprintf("%lx : Adding local %s %s\n",
  4173. Index, (SymInfo->Flags & SYMFLAG_PARAMETER) ?
  4174. "arg" : " ", SymInfo->Name);
  4175. #endif
  4176. return TRUE;
  4177. }
  4178. void
  4179. DebugSymbolGroup::TestImages(void)
  4180. {
  4181. SymbolGroupEntry* Entry = m_Entries;
  4182. while (Entry)
  4183. {
  4184. Entry->m_Format->TestImages();
  4185. Entry = Entry->m_Next;
  4186. }
  4187. }
  4188. void
  4189. DebugSymbolGroup::ShowAll(void)
  4190. {
  4191. SymbolGroupEntry* Entry = m_Entries;
  4192. ULONG Index = 0;
  4193. dprintf("Total %d syms\n", m_NumEntries);
  4194. dprintf("Idx Sub ExFlags Par Flag Mod Expr (Cast)\n");
  4195. while (Entry)
  4196. {
  4197. dprintf64("%2lx:%4lx %8lx %8lx %4lx %p %s (%s)\n",
  4198. Index++,
  4199. Entry->m_Params.SubElements,
  4200. Entry->m_Params.Flags,
  4201. FindEntryIndex(Entry->m_Parent),
  4202. Entry->m_Flags,
  4203. Entry->m_Params.Module,
  4204. Entry->m_Expr,
  4205. Entry->m_Cast ? Entry->m_Cast : "<none>");
  4206. Entry = Entry->m_Next;
  4207. }
  4208. }