Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

671 lines
14 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // IDebugRegisters implementation.
  4. //
  5. // Copyright (C) Microsoft Corporation, 1999-2002.
  6. //
  7. //----------------------------------------------------------------------------
  8. #include "ntsdp.hpp"
  9. STDMETHODIMP
  10. DebugClient::GetNumberRegisters(
  11. THIS_
  12. OUT PULONG Number
  13. )
  14. {
  15. HRESULT Status;
  16. ENTER_ENGINE();
  17. if (!g_Machine)
  18. {
  19. Status = E_UNEXPECTED;
  20. }
  21. else
  22. {
  23. *Number = g_Machine->m_NumRegs;
  24. Status = S_OK;
  25. }
  26. LEAVE_ENGINE();
  27. return Status;
  28. }
  29. STDMETHODIMP
  30. DebugClient::GetDescription(
  31. THIS_
  32. IN ULONG Register,
  33. OUT OPTIONAL PSTR NameBuffer,
  34. IN ULONG NameBufferSize,
  35. OUT OPTIONAL PULONG NameSize,
  36. OUT OPTIONAL PDEBUG_REGISTER_DESCRIPTION Desc
  37. )
  38. {
  39. HRESULT Status;
  40. ENTER_ENGINE();
  41. if (!g_Machine)
  42. {
  43. Status = E_UNEXPECTED;
  44. goto Exit;
  45. }
  46. if (Register >= g_Machine->m_NumRegs)
  47. {
  48. Status = E_INVALIDARG;
  49. goto Exit;
  50. }
  51. ULONG Type;
  52. REGDEF* FullDef;
  53. FullDef = g_Machine->RegDefFromCount(Register);
  54. if (!FullDef)
  55. {
  56. Status = E_UNEXPECTED;
  57. goto Exit;
  58. }
  59. Type = g_Machine->GetType(FullDef->Index);
  60. Status = FillStringBuffer(FullDef->Name, 0,
  61. NameBuffer, NameBufferSize, NameSize);
  62. if (Desc != NULL)
  63. {
  64. ZeroMemory(Desc, sizeof(*Desc));
  65. switch(Type)
  66. {
  67. case REGVAL_INT16:
  68. Desc->Type = DEBUG_VALUE_INT16;
  69. break;
  70. case REGVAL_SUB32:
  71. Desc->Flags |= DEBUG_REGISTER_SUB_REGISTER;
  72. // Fall through.
  73. case REGVAL_INT32:
  74. Desc->Type = DEBUG_VALUE_INT32;
  75. break;
  76. case REGVAL_SUB64:
  77. Desc->Flags |= DEBUG_REGISTER_SUB_REGISTER;
  78. // Fall through.
  79. case REGVAL_INT64:
  80. case REGVAL_INT64N:
  81. Desc->Type = DEBUG_VALUE_INT64;
  82. break;
  83. case REGVAL_FLOAT8:
  84. Desc->Type = DEBUG_VALUE_FLOAT64;
  85. break;
  86. case REGVAL_FLOAT10:
  87. Desc->Type = DEBUG_VALUE_FLOAT80;
  88. break;
  89. case REGVAL_FLOAT82:
  90. Desc->Type = DEBUG_VALUE_FLOAT82;
  91. break;
  92. case REGVAL_FLOAT16:
  93. Desc->Type = DEBUG_VALUE_FLOAT128;
  94. break;
  95. case REGVAL_VECTOR64:
  96. Desc->Type = DEBUG_VALUE_VECTOR64;
  97. break;
  98. case REGVAL_VECTOR128:
  99. Desc->Type = DEBUG_VALUE_VECTOR128;
  100. break;
  101. }
  102. if (Desc->Flags & DEBUG_REGISTER_SUB_REGISTER)
  103. {
  104. REGSUBDEF* SubDef = g_Machine->RegSubDefFromIndex(FullDef->Index);
  105. if (!SubDef)
  106. {
  107. Status = E_UNEXPECTED;
  108. goto Exit;
  109. }
  110. // Find fullreg definition and count.
  111. ULONG GroupIdx;
  112. RegisterGroup* Group;
  113. ULONG FullCount = 0;
  114. for (GroupIdx = 0;
  115. GroupIdx < g_Machine->m_NumGroups;
  116. GroupIdx++)
  117. {
  118. Group = g_Machine->m_Groups[GroupIdx];
  119. FullDef = Group->Regs;
  120. while (FullDef->Name != NULL)
  121. {
  122. if (FullDef->Index == SubDef->FullReg)
  123. {
  124. break;
  125. }
  126. FullDef++;
  127. }
  128. FullCount += (ULONG)(FullDef - Group->Regs);
  129. if (FullDef->Name != NULL)
  130. {
  131. break;
  132. }
  133. }
  134. DBG_ASSERT(FullDef->Name != NULL);
  135. Desc->SubregMaster = FullCount;
  136. // Count the bits in the mask to derive length.
  137. ULONG64 Mask;
  138. Mask = SubDef->Mask;
  139. Desc->SubregMask = Mask;
  140. while (Mask != 0)
  141. {
  142. Desc->SubregLength++;
  143. Mask &= Mask - 1;
  144. }
  145. Desc->SubregShift = SubDef->Shift;
  146. }
  147. }
  148. Exit:
  149. LEAVE_ENGINE();
  150. return Status;
  151. }
  152. STDMETHODIMP
  153. DebugClient::GetIndexByName(
  154. THIS_
  155. IN PCSTR Name,
  156. OUT PULONG Index
  157. )
  158. {
  159. HRESULT Status;
  160. ENTER_ENGINE();
  161. if (!g_Machine)
  162. {
  163. Status = E_UNEXPECTED;
  164. }
  165. else
  166. {
  167. RegisterGroup* Group;
  168. ULONG Idx;
  169. ULONG GroupIdx;
  170. Status = E_NOINTERFACE;
  171. Idx = 0;
  172. for (GroupIdx = 0;
  173. GroupIdx < g_Machine->m_NumGroups && Status != S_OK;
  174. GroupIdx++)
  175. {
  176. REGDEF* Def;
  177. Group = g_Machine->m_Groups[GroupIdx];
  178. Def = Group->Regs;
  179. while (Def->Name != NULL)
  180. {
  181. if (!strcmp(Def->Name, Name))
  182. {
  183. Status = S_OK;
  184. break;
  185. }
  186. Idx++;
  187. Def++;
  188. }
  189. }
  190. *Index = Idx;
  191. }
  192. LEAVE_ENGINE();
  193. return Status;
  194. }
  195. STDMETHODIMP
  196. DebugClient::GetValue(
  197. THIS_
  198. IN ULONG Register,
  199. OUT PDEBUG_VALUE Value
  200. )
  201. {
  202. HRESULT Status;
  203. ENTER_ENGINE();
  204. if (!IS_CUR_CONTEXT_ACCESSIBLE())
  205. {
  206. Status = E_UNEXPECTED;
  207. goto Exit;
  208. }
  209. if (Register >= g_Machine->m_NumRegs)
  210. {
  211. Status = E_INVALIDARG;
  212. goto Exit;
  213. }
  214. ZeroMemory(Value, sizeof(*Value));
  215. ULONG Index;
  216. REGVAL Val;
  217. REGDEF* RegDef = g_Machine->RegDefFromCount(Register);
  218. if (!RegDef)
  219. {
  220. Status = E_UNEXPECTED;
  221. goto Exit;
  222. }
  223. g_DisableErrorPrint++;
  224. Index = RegDef->Index;
  225. __try
  226. {
  227. GetPseudoOrRegVal(TRUE, Index, &Val);
  228. }
  229. __except(CommandExceptionFilter(GetExceptionInformation()))
  230. {
  231. Status = E_INVALIDARG;
  232. g_DisableErrorPrint--;
  233. goto Exit;
  234. }
  235. g_DisableErrorPrint--;
  236. switch(Val.Type)
  237. {
  238. case REGVAL_INT16:
  239. Value->Type = DEBUG_VALUE_INT16;
  240. Value->I16 = (USHORT)Val.I32;
  241. break;
  242. case REGVAL_SUB32:
  243. case REGVAL_INT32:
  244. Value->Type = DEBUG_VALUE_INT32;
  245. Value->I32 = Val.I32;
  246. break;
  247. case REGVAL_SUB64:
  248. case REGVAL_INT64:
  249. Val.Nat = FALSE;
  250. // Fall through.
  251. case REGVAL_INT64N:
  252. Value->Type = DEBUG_VALUE_INT64;
  253. Value->I64 = Val.I64;
  254. Value->Nat = Val.Nat;
  255. break;
  256. case REGVAL_FLOAT8:
  257. Value->Type = DEBUG_VALUE_FLOAT64;
  258. Value->F64 = Val.F8;
  259. break;
  260. case REGVAL_FLOAT10:
  261. Value->Type = DEBUG_VALUE_FLOAT80;
  262. memcpy(Value->F80Bytes, Val.F10, sizeof(Value->F80Bytes));
  263. break;
  264. case REGVAL_FLOAT82:
  265. Value->Type = DEBUG_VALUE_FLOAT82;
  266. memcpy(Value->F82Bytes, Val.F82, sizeof(Value->F82Bytes));
  267. break;
  268. case REGVAL_FLOAT16:
  269. Value->Type = DEBUG_VALUE_FLOAT128;
  270. memcpy(Value->F128Bytes, Val.F16, sizeof(Value->F128Bytes));
  271. break;
  272. case REGVAL_VECTOR64:
  273. Value->Type = DEBUG_VALUE_VECTOR64;
  274. memcpy(Value->RawBytes, Val.Bytes, 8);
  275. break;
  276. case REGVAL_VECTOR128:
  277. Value->Type = DEBUG_VALUE_VECTOR128;
  278. memcpy(Value->RawBytes, Val.Bytes, 16);
  279. break;
  280. }
  281. Status = S_OK;
  282. Exit:
  283. LEAVE_ENGINE();
  284. return Status;
  285. }
  286. STDMETHODIMP
  287. DebugClient::SetValue(
  288. THIS_
  289. IN ULONG Register,
  290. IN PDEBUG_VALUE Value
  291. )
  292. {
  293. HRESULT Status;
  294. ENTER_ENGINE();
  295. if (!IS_CUR_CONTEXT_ACCESSIBLE())
  296. {
  297. Status = E_UNEXPECTED;
  298. goto Exit;
  299. }
  300. if (Register >= g_Machine->m_NumRegs)
  301. {
  302. Status = E_INVALIDARG;
  303. goto Exit;
  304. }
  305. ULONG Index;
  306. ULONG Type;
  307. REGVAL Val;
  308. DEBUG_VALUE Coerce;
  309. REGDEF* RegDef = g_Machine->RegDefFromCount(Register);
  310. if (!RegDef)
  311. {
  312. Status = E_UNEXPECTED;
  313. goto Exit;
  314. }
  315. Index = RegDef->Index;
  316. Type = g_Machine->GetType(Index);
  317. Val.Type = Type;
  318. switch(Type)
  319. {
  320. case REGVAL_INT16:
  321. Status = CoerceValue(Value, DEBUG_VALUE_INT16, &Coerce);
  322. Val.I32 = Coerce.I16;
  323. break;
  324. case REGVAL_SUB32:
  325. case REGVAL_INT32:
  326. Status = CoerceValue(Value, DEBUG_VALUE_INT32, &Coerce);
  327. Val.I32 = Coerce.I32;
  328. break;
  329. case REGVAL_INT64:
  330. Val.Type = REGVAL_INT64N;
  331. // Fall through.
  332. case REGVAL_SUB64:
  333. case REGVAL_INT64N:
  334. Status = CoerceValue(Value, DEBUG_VALUE_INT64, &Coerce);
  335. Val.I64 = Coerce.I64;
  336. Val.Nat = Coerce.Nat ? TRUE : FALSE;
  337. break;
  338. case REGVAL_FLOAT8:
  339. Status = CoerceValue(Value, DEBUG_VALUE_FLOAT64, &Coerce);
  340. Val.F8 = Coerce.F64;
  341. break;
  342. case REGVAL_FLOAT10:
  343. Status = CoerceValue(Value, DEBUG_VALUE_FLOAT80, &Coerce);
  344. memcpy(Val.F10, Coerce.F80Bytes, sizeof(Coerce.F80Bytes));
  345. break;
  346. case REGVAL_FLOAT82:
  347. Status = CoerceValue(Value, DEBUG_VALUE_FLOAT82, &Coerce);
  348. memcpy(Val.F82, Coerce.F82Bytes, sizeof(Coerce.F82Bytes));
  349. break;
  350. case REGVAL_FLOAT16:
  351. Status = CoerceValue(Value, DEBUG_VALUE_FLOAT128, &Coerce);
  352. memcpy(Val.F16, Coerce.F128Bytes, sizeof(Coerce.F128Bytes));
  353. break;
  354. case REGVAL_VECTOR64:
  355. Status = CoerceValue(Value, DEBUG_VALUE_VECTOR64, &Coerce);
  356. memcpy(Val.Bytes, Coerce.RawBytes, 8);
  357. break;
  358. case REGVAL_VECTOR128:
  359. Status = CoerceValue(Value, DEBUG_VALUE_VECTOR128, &Coerce);
  360. memcpy(Val.Bytes, Coerce.RawBytes, 16);
  361. break;
  362. }
  363. if (Status == S_OK)
  364. {
  365. g_DisableErrorPrint++;
  366. __try
  367. {
  368. SetPseudoOrRegVal(Index, &Val);
  369. }
  370. __except(CommandExceptionFilter(GetExceptionInformation()))
  371. {
  372. Status = E_INVALIDARG;
  373. }
  374. g_DisableErrorPrint--;
  375. }
  376. Exit:
  377. LEAVE_ENGINE();
  378. return Status;
  379. }
  380. STDMETHODIMP
  381. DebugClient::GetValues(
  382. THIS_
  383. IN ULONG Count,
  384. IN OPTIONAL PULONG Indices,
  385. IN ULONG Start,
  386. OUT PDEBUG_VALUE Values
  387. )
  388. {
  389. HRESULT Status;
  390. ENTER_ENGINE();
  391. if (!IS_CUR_CONTEXT_ACCESSIBLE())
  392. {
  393. Status = E_UNEXPECTED;
  394. goto Exit;
  395. }
  396. HRESULT SingleStatus;
  397. ULONG i;
  398. Status = S_OK;
  399. if (Indices != NULL)
  400. {
  401. for (i = 0; i < Count; i++)
  402. {
  403. SingleStatus = GetValue(Indices[i], Values + i);
  404. if (SingleStatus != S_OK)
  405. {
  406. Status = SingleStatus;
  407. }
  408. }
  409. }
  410. else
  411. {
  412. for (i = 0; i < Count; i++)
  413. {
  414. SingleStatus = GetValue(Start + i, Values + i);
  415. if (SingleStatus != S_OK)
  416. {
  417. Status = SingleStatus;
  418. }
  419. }
  420. }
  421. Exit:
  422. LEAVE_ENGINE();
  423. return Status;
  424. }
  425. STDMETHODIMP
  426. DebugClient::SetValues(
  427. THIS_
  428. IN ULONG Count,
  429. IN OPTIONAL PULONG Indices,
  430. IN ULONG Start,
  431. IN PDEBUG_VALUE Values
  432. )
  433. {
  434. HRESULT Status;
  435. ENTER_ENGINE();
  436. if (!IS_CUR_CONTEXT_ACCESSIBLE())
  437. {
  438. Status = E_UNEXPECTED;
  439. goto Exit;
  440. }
  441. HRESULT SingleStatus;
  442. ULONG i;
  443. Status = S_OK;
  444. if (Indices != NULL)
  445. {
  446. for (i = 0; i < Count; i++)
  447. {
  448. SingleStatus = SetValue(Indices[i], Values + i);
  449. if (SingleStatus != S_OK)
  450. {
  451. Status = SingleStatus;
  452. }
  453. }
  454. }
  455. else
  456. {
  457. for (i = 0; i < Count; i++)
  458. {
  459. SingleStatus = SetValue(Start + i, Values + i);
  460. if (SingleStatus != S_OK)
  461. {
  462. Status = SingleStatus;
  463. }
  464. }
  465. }
  466. Exit:
  467. LEAVE_ENGINE();
  468. return Status;
  469. }
  470. STDMETHODIMP
  471. DebugClient::OutputRegisters(
  472. THIS_
  473. IN ULONG OutputControl,
  474. IN ULONG Flags
  475. )
  476. {
  477. // Ensure that the public flags match the internal flags.
  478. C_ASSERT(DEBUG_REGISTERS_INT32 == REGALL_INT32 &&
  479. DEBUG_REGISTERS_INT64 == REGALL_INT64 &&
  480. DEBUG_REGISTERS_FLOAT == REGALL_FLOAT);
  481. if (Flags & ~DEBUG_REGISTERS_ALL)
  482. {
  483. return E_INVALIDARG;
  484. }
  485. HRESULT Status;
  486. ENTER_ENGINE();
  487. if (!IS_CUR_CONTEXT_ACCESSIBLE())
  488. {
  489. Status = E_UNEXPECTED;
  490. }
  491. else
  492. {
  493. OutCtlSave OldCtl;
  494. if (!PushOutCtl(OutputControl, this, &OldCtl))
  495. {
  496. Status = E_INVALIDARG;
  497. }
  498. else
  499. {
  500. if (Flags == DEBUG_REGISTERS_DEFAULT)
  501. {
  502. Flags = g_Machine->m_AllMask;
  503. }
  504. OutCurInfo(OCI_FORCE_REG, Flags, DEBUG_OUTPUT_NORMAL);
  505. Status = S_OK;
  506. PopOutCtl(&OldCtl);
  507. }
  508. }
  509. LEAVE_ENGINE();
  510. return Status;
  511. }
  512. STDMETHODIMP
  513. DebugClient::GetInstructionOffset(
  514. THIS_
  515. OUT PULONG64 Offset
  516. )
  517. {
  518. HRESULT Status;
  519. ENTER_ENGINE();
  520. if (!IS_CUR_CONTEXT_ACCESSIBLE())
  521. {
  522. Status = E_UNEXPECTED;
  523. }
  524. else
  525. {
  526. ADDR Addr;
  527. g_Machine->GetPC(&Addr);
  528. *Offset = Flat(Addr);
  529. Status = S_OK;
  530. }
  531. LEAVE_ENGINE();
  532. return Status;
  533. }
  534. STDMETHODIMP
  535. DebugClient::GetStackOffset(
  536. THIS_
  537. OUT PULONG64 Offset
  538. )
  539. {
  540. HRESULT Status;
  541. ENTER_ENGINE();
  542. if (!IS_CUR_CONTEXT_ACCESSIBLE())
  543. {
  544. Status = E_UNEXPECTED;
  545. }
  546. else
  547. {
  548. ADDR Addr;
  549. g_Machine->GetSP(&Addr);
  550. *Offset = Flat(Addr);
  551. Status = S_OK;
  552. }
  553. LEAVE_ENGINE();
  554. return Status;
  555. }
  556. STDMETHODIMP
  557. DebugClient::GetFrameOffset(
  558. THIS_
  559. OUT PULONG64 Offset
  560. )
  561. {
  562. HRESULT Status;
  563. ENTER_ENGINE();
  564. if (!IS_CUR_CONTEXT_ACCESSIBLE())
  565. {
  566. Status = E_UNEXPECTED;
  567. }
  568. else
  569. {
  570. ADDR Addr;
  571. g_Machine->GetFP(&Addr);
  572. *Offset = Flat(Addr);
  573. Status = S_OK;
  574. }
  575. LEAVE_ENGINE();
  576. return Status;
  577. }