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.

653 lines
13 KiB

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