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

5306 lines
128 KiB

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