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.

1162 lines
28 KiB

  1. /*++
  2. Copyright (c) 1990-2001 Microsoft Corporation
  3. Module Name:
  4. kdcpuapi.c
  5. Abstract:
  6. This module implements CPU specific remote debug APIs.
  7. Author:
  8. Mark Lucovsky (markl) 04-Sep-1990
  9. Revision History:
  10. 24-sep-90 bryanwi
  11. Port to the x86.
  12. --*/
  13. #include <stdio.h>
  14. #include "kdp.h"
  15. #define END_OF_CONTROL_SPACE
  16. extern ULONG KdpCurrentSymbolStart, KdpCurrentSymbolEnd;
  17. extern ULONG KdSpecialCalls[];
  18. extern ULONG KdNumberOfSpecialCalls;
  19. LONG
  20. KdpLevelChange (
  21. ULONG Pc,
  22. PCONTEXT ContextRecord,
  23. PBOOLEAN SpecialCall
  24. );
  25. LONG
  26. regValue(
  27. UCHAR reg,
  28. PCONTEXT ContextRecord
  29. );
  30. BOOLEAN
  31. KdpIsSpecialCall (
  32. ULONG Pc,
  33. PCONTEXT ContextRecord,
  34. UCHAR opcode,
  35. UCHAR ModRM
  36. );
  37. ULONG
  38. KdpGetReturnAddress (
  39. PCONTEXT ContextRecord
  40. );
  41. ULONG
  42. KdpGetCallNextOffset (
  43. ULONG Pc,
  44. PCONTEXT ContextRecord
  45. );
  46. #ifdef ALLOC_PRAGMA
  47. #pragma alloc_text(PAGEKD, KdpLevelChange)
  48. #pragma alloc_text(PAGEKD, regValue)
  49. #pragma alloc_text(PAGEKD, KdpIsSpecialCall)
  50. #pragma alloc_text(PAGEKD, KdpGetReturnAddress)
  51. #pragma alloc_text(PAGEKD, KdpAllowDisable)
  52. #pragma alloc_text(PAGEKD, KdpSetContextState)
  53. #pragma alloc_text(PAGEKD, KdpSetStateChange)
  54. #pragma alloc_text(PAGEKD, KdpGetStateChange)
  55. #pragma alloc_text(PAGEKD, KdpSysReadControlSpace)
  56. #pragma alloc_text(PAGEKD, KdpSysWriteControlSpace)
  57. #pragma alloc_text(PAGEKD, KdpSysReadIoSpace)
  58. #pragma alloc_text(PAGEKD, KdpSysWriteIoSpace)
  59. #pragma alloc_text(PAGEKD, KdpSysReadMsr)
  60. #pragma alloc_text(PAGEKD, KdpSysWriteMsr)
  61. #pragma alloc_text(PAGEKD, KdpGetCallNextOffset)
  62. #endif
  63. /**** KdpIsTryFinallyReturn - detect finally optimization
  64. *
  65. * Input:
  66. * pc - program counter of instruction to check
  67. * ContextRecord - machine specific context
  68. *
  69. * Output:
  70. * returns TRUE if this is a try-finally returning to the same
  71. * scope
  72. ***************************************************************************/
  73. BOOLEAN
  74. KdpIsTryFinallyReturn (
  75. ULONG Pc,
  76. PCONTEXT ContextRecord
  77. )
  78. {
  79. ULONG retaddr;
  80. ULONG calldisp;
  81. UCHAR inst;
  82. //
  83. // The complier generates code for a try-finally that involves having
  84. // a ret instruction that does not match with a call instruction.
  85. // This ret never returns a value (ie, it's a c3 return and not a
  86. // c2). It always returns into the current symbol scope. It is never
  87. // preceeded by a leave, which (hopefully) should differentiate it
  88. // from recursive returns. Check for this, and if we find it count
  89. // it as *0* level change.
  90. //
  91. // As an optimization, the compiler will often change:
  92. // CALL
  93. // RET
  94. // into:
  95. // JMP
  96. // In either case, we figure out the return address. It's the first 4 bytes
  97. // on the stack.
  98. //
  99. if (!NT_SUCCESS(KdpCopyFromPtr(&retaddr, ContextRecord->Esp, 4, NULL))) {
  100. return FALSE;
  101. }
  102. // DPRINT(( "Start %x return %x end %x\n", KdpCurrentSymbolStart, retaddr, KdpCurrentSymbolEnd ));
  103. if ( (KdpCurrentSymbolStart < retaddr) && (retaddr < KdpCurrentSymbolEnd) ) {
  104. //
  105. // Well, things aren't this nice. We may have transferred but not yet
  106. // updated the start/end. This case occurs in a call to a thunk. We
  107. // look to see if the instruction before the return address is a call.
  108. // Gross and not 100% reliable.
  109. //
  110. if (!NT_SUCCESS(KdpCopyFromPtr(&inst, (PCHAR)retaddr - 5, 1, NULL))) {
  111. return FALSE;
  112. }
  113. if (!NT_SUCCESS(KdpCopyFromPtr(&calldisp, (PCHAR)retaddr - 4, 4, NULL))) {
  114. return FALSE;
  115. }
  116. if (inst == 0xe8 && calldisp + retaddr == Pc) {
  117. // DPRINT(( "call to thunk @ %x\n", Pc ));
  118. return FALSE;
  119. }
  120. //
  121. // returning to the current function. Either a finally
  122. // or a recursive return. Check for a leave. This is not 100%
  123. // reliable since we are betting on an instruction longer than a byte
  124. // and not ending with 0xc9.
  125. //
  126. if (!NT_SUCCESS(KdpCopyFromPtr(&inst, (PCHAR)Pc - 1, 1, NULL))) {
  127. return FALSE;
  128. }
  129. if ( inst != 0xc9 ) {
  130. // not a leave. Assume a try-finally.
  131. // DPRINT(( "transfer at %x is try-finally\n", Pc ));
  132. return TRUE;
  133. }
  134. }
  135. //
  136. // This appears to be a true RET instruction
  137. //
  138. return FALSE;
  139. }
  140. /**** KdpLevelChange - say how the instruction affects the call level
  141. *
  142. * Input:
  143. * pc - program counter of instruction to check
  144. * ContextRecord - machine specific context
  145. * SpecialCall - pointer to returned boolean indicating if the
  146. * instruction is a transfer to a special routine
  147. *
  148. * Output:
  149. * returns -1 for a level pop, 1 for a push and 0 if it is
  150. * unchanged.
  151. * NOTE: This function belongs in some other file. I should move it.
  152. ***************************************************************************/
  153. LONG
  154. KdpLevelChange (
  155. ULONG Pc,
  156. PCONTEXT ContextRecord,
  157. PBOOLEAN SpecialCall
  158. )
  159. {
  160. UCHAR membuf[2];
  161. ULONG Addr;
  162. membuf[0] = 0xcc;
  163. membuf[1] = 0xcc;
  164. KdpCopyFromPtr(membuf, Pc, 2, NULL);
  165. switch (membuf[0]) {
  166. case 0xe8: // CALL direct w/32 bit displacement
  167. //
  168. // For try/finally, the compiler may, in addition to the push/ret trick
  169. // below, use a call to the finally thunk. Since we treat a RET to
  170. // within the same symbol scope as not changing levels, we will also
  171. // treat such a call as not changing levels either
  172. //
  173. if (!NT_SUCCESS(KdpCopyFromPtr(&Addr, (PCHAR)Pc + 1, 4, NULL))) {
  174. Addr = 0;
  175. } else {
  176. Addr += Pc + 5;
  177. }
  178. if ((KdpCurrentSymbolStart <= Addr) && (Addr < KdpCurrentSymbolEnd)) {
  179. *SpecialCall = FALSE;
  180. return 0;
  181. }
  182. case 0x9a: // CALL segmented 16:32
  183. *SpecialCall = KdpIsSpecialCall( Pc, ContextRecord, membuf[0], membuf[1] );
  184. return 1;
  185. case 0xff:
  186. //
  187. // This is a compound instruction. Dispatch on operation
  188. //
  189. switch (membuf[1] & 0x38) {
  190. case 0x10: // CALL with mod r/m
  191. *SpecialCall = KdpIsSpecialCall( Pc, ContextRecord, membuf[0], membuf[1] );
  192. return 1;
  193. case 0x20: // JMP with mod r/m
  194. *SpecialCall = KdpIsSpecialCall( Pc, ContextRecord, membuf[0], membuf[1] );
  195. //
  196. // If this is a try/finally, we'd like to treat it as call since the
  197. // return inside the destination will bring us back to this context.
  198. // However, if it is a jmp to a special routine, we must treat it
  199. // as a no-level change operation since we won't see the special
  200. // routines's return.
  201. //
  202. // If it is not a try/finally, we'd like to treat it as a no-level
  203. // change, unless again, it is a transfer to a special call which
  204. // views this as a level up.
  205. //
  206. if (KdpIsTryFinallyReturn( Pc, ContextRecord )) {
  207. if (*SpecialCall) {
  208. //
  209. // We won't see the return, so pretend it is just
  210. // inline code
  211. //
  212. return 0;
  213. } else {
  214. //
  215. // The destinations return will bring us back to this
  216. // context
  217. //
  218. return 1;
  219. }
  220. } else if (*SpecialCall) {
  221. //
  222. // We won't see the return but we are, indeed, doing one.
  223. //
  224. return -1;
  225. } else {
  226. return 0;
  227. }
  228. default:
  229. *SpecialCall = FALSE;
  230. return 0;
  231. }
  232. case 0xc3: // RET
  233. //
  234. // If we are a try/finally ret, then we indicate that it is NOT a level
  235. // change
  236. //
  237. if (KdpIsTryFinallyReturn( Pc, ContextRecord )) {
  238. *SpecialCall = FALSE;
  239. return 0;
  240. }
  241. case 0xc2: // RET w/16 bit esp change
  242. case 0xca: // RETF w/16 bit esp change
  243. case 0xcb: // RETF
  244. *SpecialCall = FALSE;
  245. return -1;
  246. default:
  247. *SpecialCall = FALSE;
  248. return 0;
  249. }
  250. } // KdpLevelChange
  251. LONG
  252. regValue(
  253. UCHAR reg,
  254. PCONTEXT ContextRecord
  255. )
  256. {
  257. switch (reg) {
  258. case 0x0:
  259. return(ContextRecord->Eax);
  260. break;
  261. case 0x1:
  262. return(ContextRecord->Ecx);
  263. break;
  264. case 0x2:
  265. return(ContextRecord->Edx);
  266. break;
  267. case 0x3:
  268. return(ContextRecord->Ebx);
  269. break;
  270. case 0x4:
  271. return(ContextRecord->Esp);
  272. break;
  273. case 0x5:
  274. return(ContextRecord->Ebp);
  275. break;
  276. case 0x6:
  277. return(ContextRecord->Esi);
  278. break;
  279. case 0x7:
  280. return(ContextRecord->Edi);
  281. break;
  282. }
  283. return 0;
  284. }
  285. BOOLEAN
  286. KdpIsSpecialCall (
  287. ULONG Pc,
  288. PCONTEXT ContextRecord,
  289. UCHAR opcode,
  290. UCHAR modRM
  291. )
  292. /*++
  293. Routine Description:
  294. Check to see if the instruction at pc is a call to one of the
  295. SpecialCall routines.
  296. Argument:
  297. Pc - program counter of instruction in question.
  298. --*/
  299. {
  300. UCHAR sib;
  301. ULONG callAddr;
  302. ULONG addrAddr;
  303. LONG offset;
  304. ULONG i;
  305. char d8;
  306. callAddr = 0;
  307. if ( opcode == 0xe8 ) {
  308. //
  309. // Signed offset from pc
  310. //
  311. if (NT_SUCCESS(KdpCopyFromPtr(&offset, (PCHAR)Pc + 1, 4, NULL))) {
  312. callAddr = Pc + offset + 5; // +5 for instr len.
  313. }
  314. } else if ( opcode == 0xff ) {
  315. if ( ((modRM & 0x38) != 0x10) && ((modRM & 0x38) != 0x20) ) {
  316. // not call or jump
  317. return FALSE;
  318. }
  319. if ( (modRM & 0x08) == 0x08 ) {
  320. // m16:16 or m16:32 -- we don't handle this
  321. return FALSE;
  322. }
  323. if ( (modRM & 0xc0) == 0xc0 ) {
  324. /* Direct register addressing */
  325. callAddr = regValue( (UCHAR)(modRM&0x7), ContextRecord );
  326. } else if ( (modRM & 0xc7) == 0x05 ) {
  327. //
  328. // Calls across dll boundaries involve a call into a jump table,
  329. // wherein the jump address is set to the real called routine at DLL
  330. // load time. Check to see if we're calling such an instruction,
  331. // and if so, compute its target address and set callAddr there.
  332. //
  333. // ff15 or ff25 -- call or jump indirect with disp32. Get
  334. // address of address
  335. //
  336. if (NT_SUCCESS(KdpCopyFromPtr(&addrAddr, (PCHAR)Pc + 2, 4, NULL))) {
  337. //
  338. // Get real destination address
  339. //
  340. if (!NT_SUCCESS(KdpCopyFromPtr(&callAddr, addrAddr, 4, NULL))) {
  341. callAddr = 0;
  342. }
  343. }
  344. // DPRINT(( "Indirect call/jmp @ %x\n", Pc ));
  345. } else if ( (modRM & 0x7) == 0x4 ) {
  346. LONG indexValue;
  347. /* sib byte present */
  348. if (!NT_SUCCESS(KdpCopyFromPtr(&sib, (PCHAR)Pc + 2, 1, NULL))) {
  349. sib = 0;
  350. }
  351. indexValue = regValue( (UCHAR)((sib & 0x31) >> 3), ContextRecord );
  352. switch ( sib&0xc0 ) {
  353. case 0x0: /* x1 */
  354. break;
  355. case 0x40:
  356. indexValue *= 2;
  357. break;
  358. case 0x80:
  359. indexValue *= 4;
  360. break;
  361. case 0xc0:
  362. indexValue *= 8;
  363. break;
  364. } /* switch */
  365. switch ( modRM & 0xc0 ) {
  366. case 0x0: /* no displacement */
  367. if ( (sib & 0x7) == 0x5 ) {
  368. // DPRINT(("funny call #1 at %x\n", Pc));
  369. return FALSE;
  370. }
  371. callAddr = indexValue + regValue((UCHAR)(sib&0x7), ContextRecord );
  372. break;
  373. case 0x40:
  374. if ( (sib & 0x6) == 0x4 ) {
  375. // DPRINT(("Funny call #2\n")); /* calling into the stack */
  376. return FALSE;
  377. }
  378. if (!NT_SUCCESS(KdpCopyFromPtr( &d8, (PCHAR)Pc + 3, 1, NULL))) {
  379. d8 = 0;
  380. }
  381. callAddr = indexValue + d8 +
  382. regValue((UCHAR)(sib&0x7), ContextRecord );
  383. break;
  384. case 0x80:
  385. if ( (sib & 0x6) == 0x4 ) {
  386. // DPRINT(("Funny call #3\n")); /* calling into the stack */
  387. return FALSE;
  388. }
  389. if (!NT_SUCCESS(KdpCopyFromPtr(&offset, (PCHAR)Pc + 3, 4, NULL))) {
  390. offset = 0;
  391. }
  392. callAddr = indexValue + offset +
  393. regValue((UCHAR)(sib&0x7), ContextRecord );
  394. break;
  395. case 0xc0:
  396. ASSERT( FALSE );
  397. break;
  398. }
  399. } else {
  400. //KdPrint(( "undecoded call at %x\n",
  401. // CONTEXT_TO_PROGRAM_COUNTER(ContextRecord) ));
  402. return FALSE;
  403. }
  404. } else if ( opcode == 0x9a ) {
  405. /* Absolute address call (best I can tell, cc doesn't generate this) */
  406. if (!NT_SUCCESS(KdpCopyFromPtr( &callAddr, (PCHAR)Pc + 1, 4, NULL))) {
  407. callAddr = 0;
  408. }
  409. } else {
  410. return FALSE;
  411. }
  412. //
  413. // Calls across dll boundaries involve a call into a jump table,
  414. // wherein the jump address is set to the real called routine at DLL
  415. // load time. Check to see if we're calling such an instruction,
  416. // and if so, compute its target address and set callAddr there.
  417. //
  418. #if 0
  419. if (!NT_SUCCESS(KdpCopyFromPtr( &twoBytes, (PCHAR)callAddr, 2, NULL))) {
  420. twoBytes = 0;
  421. }
  422. if ( twoBytes == 0x25ff ) { /* i386 is little-Endian; really 0xff25 */
  423. //
  424. // This is a 'jmp dword ptr [mem]' instruction, which is the sort of
  425. // jump used for a dll-boundary crossing call. Fixup callAddr.
  426. //
  427. if (!NT_SUCCESS(KdpCopyFromPtr( &addrAddr, (PCHAR)callAddr + 2, 4, NULL))) {
  428. callAddr = 0;
  429. } else if (!NT_SUCCESS(KdpCopyFromPtr( &callAddr, addrAddr, 4, NULL))) {
  430. callAddr = 0;
  431. }
  432. }
  433. #endif
  434. for ( i = 0; i < KdNumberOfSpecialCalls; i++ ) {
  435. if ( KdSpecialCalls[i] == callAddr ) {
  436. return TRUE;
  437. }
  438. }
  439. return FALSE;
  440. }
  441. /*
  442. * Find the return address of the current function. Only works when
  443. * locals haven't yet been pushed (ie, on the first instruction of the
  444. * function).
  445. */
  446. ULONG
  447. KdpGetReturnAddress (
  448. PCONTEXT ContextRecord
  449. )
  450. {
  451. ULONG retaddr;
  452. if (!NT_SUCCESS(KdpCopyFromPtr(&retaddr, ContextRecord->Esp, 4, NULL))) {
  453. retaddr = 0;
  454. }
  455. return retaddr;
  456. } // KdpGetReturnAddress
  457. NTSTATUS
  458. KdpAllowDisable(
  459. VOID
  460. )
  461. /*++
  462. Routine Description:
  463. Determines whether the current state of the debugger allows
  464. disabling or not.
  465. Arguments:
  466. None.
  467. Return Value:
  468. NTSTATUS.
  469. --*/
  470. {
  471. PKPRCB Prcb;
  472. ULONG Processor;
  473. //
  474. // If any kernel data breakpoints are active on any processor we can't
  475. // disable the debugger.
  476. //
  477. for (Processor = 0; Processor < (ULONG)KeNumberProcessors; Processor++) {
  478. Prcb = KiProcessorBlock[Processor];
  479. if (Prcb->ProcessorState.SpecialRegisters.KernelDr7 & 0xff) {
  480. return STATUS_ACCESS_DENIED;
  481. }
  482. }
  483. return STATUS_SUCCESS;
  484. }
  485. VOID
  486. KdpSetContextState(
  487. IN OUT PDBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange,
  488. IN PCONTEXT ContextRecord
  489. )
  490. {
  491. PKPRCB Prcb;
  492. //
  493. // Special registers for the x86
  494. //
  495. Prcb = KeGetCurrentPrcb();
  496. WaitStateChange->ControlReport.Dr6 =
  497. Prcb->ProcessorState.SpecialRegisters.KernelDr6;
  498. WaitStateChange->ControlReport.Dr7 =
  499. Prcb->ProcessorState.SpecialRegisters.KernelDr7;
  500. WaitStateChange->ControlReport.SegCs = (USHORT)(ContextRecord->SegCs);
  501. WaitStateChange->ControlReport.SegDs = (USHORT)(ContextRecord->SegDs);
  502. WaitStateChange->ControlReport.SegEs = (USHORT)(ContextRecord->SegEs);
  503. WaitStateChange->ControlReport.SegFs = (USHORT)(ContextRecord->SegFs);
  504. WaitStateChange->ControlReport.EFlags = ContextRecord->EFlags;
  505. WaitStateChange->ControlReport.ReportFlags = X86_REPORT_INCLUDES_SEGS;
  506. // If the current code segment is a known flat code
  507. // segment let the debugger know so that it doesn't
  508. // have to retrieve the descriptor.
  509. if (ContextRecord->SegCs == KGDT_R0_CODE ||
  510. ContextRecord->SegCs == KGDT_R3_CODE + 3) {
  511. WaitStateChange->ControlReport.ReportFlags |= X86_REPORT_STANDARD_CS;
  512. }
  513. }
  514. VOID
  515. KdpSetStateChange(
  516. IN OUT PDBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange,
  517. IN PEXCEPTION_RECORD ExceptionRecord,
  518. IN PCONTEXT ContextRecord,
  519. IN BOOLEAN SecondChance
  520. )
  521. /*++
  522. Routine Description:
  523. Fill in the Wait_State_Change message record.
  524. Arguments:
  525. WaitStateChange - Supplies pointer to record to fill in
  526. ExceptionRecord - Supplies a pointer to an exception record.
  527. ContextRecord - Supplies a pointer to a context record.
  528. SecondChance - Supplies a boolean value that determines whether this is
  529. the first or second chance for the exception.
  530. Return Value:
  531. None.
  532. --*/
  533. {
  534. UNREFERENCED_PARAMETER (ExceptionRecord);
  535. UNREFERENCED_PARAMETER (SecondChance);
  536. KdpSetContextState(WaitStateChange, ContextRecord);
  537. }
  538. VOID
  539. KdpGetStateChange(
  540. IN PDBGKD_MANIPULATE_STATE64 ManipulateState,
  541. IN PCONTEXT ContextRecord
  542. )
  543. /*++
  544. Routine Description:
  545. Extract continuation control data from Manipulate_State message
  546. Arguments:
  547. ManipulateState - supplies pointer to Manipulate_State packet
  548. ContextRecord - Supplies a pointer to a context record.
  549. Return Value:
  550. None.
  551. --*/
  552. {
  553. PKPRCB Prcb;
  554. ULONG Processor;
  555. if (NT_SUCCESS(ManipulateState->u.Continue2.ContinueStatus) == TRUE) {
  556. //
  557. // If NT_SUCCESS returns TRUE, then the debugger is doing a
  558. // continue, and it makes sense to apply control changes.
  559. // Otherwise the debugger is saying that it doesn't know what
  560. // to do with this exception, so control values are ignored.
  561. //
  562. if (ManipulateState->u.Continue2.ControlSet.TraceFlag == TRUE) {
  563. ContextRecord->EFlags |= 0x100L;
  564. } else {
  565. ContextRecord->EFlags &= ~0x100L;
  566. }
  567. for (Processor = 0; Processor < (ULONG)KeNumberProcessors; Processor++) {
  568. Prcb = KiProcessorBlock[Processor];
  569. Prcb->ProcessorState.SpecialRegisters.KernelDr7 =
  570. ManipulateState->u.Continue2.ControlSet.Dr7;
  571. Prcb->ProcessorState.SpecialRegisters.KernelDr6 = 0L;
  572. }
  573. if (ManipulateState->u.Continue2.ControlSet.CurrentSymbolStart != 1) {
  574. KdpCurrentSymbolStart = ManipulateState->u.Continue2.ControlSet.CurrentSymbolStart;
  575. KdpCurrentSymbolEnd = ManipulateState->u.Continue2.ControlSet.CurrentSymbolEnd;
  576. }
  577. }
  578. }
  579. NTSTATUS
  580. KdpSysReadControlSpace(
  581. ULONG Processor,
  582. ULONG64 Address,
  583. PVOID Buffer,
  584. ULONG Request,
  585. PULONG Actual
  586. )
  587. /*++
  588. Routine Description:
  589. Reads implementation specific system data.
  590. IMPLEMENTATION NOTE:
  591. On the X86, control space is defined as follows:
  592. 0: Base of KPROCESSOR_STATE structure. (KPRCB.ProcessorState)
  593. This includes CONTEXT record,
  594. followed by a SPECIAL_REGISTERs record
  595. Arguments:
  596. Processor - Processor's information to access.
  597. Address - Offset in control space.
  598. Buffer - Data buffer.
  599. Request - Amount of data to move.
  600. Actual - Amount of data actually moved.
  601. Return Value:
  602. NTSTATUS.
  603. --*/
  604. {
  605. ULONG Length, t;
  606. PVOID StartAddr;
  607. NTSTATUS Status;
  608. Length = Request;
  609. if ((Address < sizeof(KPROCESSOR_STATE)) &&
  610. (Processor < (ULONG)KeNumberProcessors)) {
  611. t = (ULONG)(sizeof(KPROCESSOR_STATE)) - (ULONG)Address;
  612. if (t < Length) {
  613. Length = t;
  614. }
  615. StartAddr = (PVOID)
  616. ((ULONG)Address +
  617. (ULONG)&(KiProcessorBlock[Processor]->ProcessorState));
  618. Status = KdpCopyToPtr(Buffer,
  619. StartAddr,
  620. Length,
  621. Actual);
  622. } else {
  623. Status = STATUS_UNSUCCESSFUL;
  624. *Actual = 0;
  625. }
  626. return Status;
  627. }
  628. NTSTATUS
  629. KdpSysWriteControlSpace(
  630. ULONG Processor,
  631. ULONG64 Address,
  632. PVOID Buffer,
  633. ULONG Request,
  634. PULONG Actual
  635. )
  636. /*++
  637. Routine Description:
  638. Writes implementation specific system data.
  639. Control space for x86 is as defined above.
  640. Arguments:
  641. Processor - Processor's information to access.
  642. Address - Offset in control space.
  643. Buffer - Data buffer.
  644. Request - Amount of data to move.
  645. Actual - Amount of data actually moved.
  646. Return Value:
  647. NTSTATUS.
  648. --*/
  649. {
  650. PVOID StartAddr;
  651. NTSTATUS Status;
  652. if (((Address + Request) <= sizeof(KPROCESSOR_STATE)) &&
  653. (Processor < (ULONG)KeNumberProcessors)) {
  654. StartAddr = (PVOID)
  655. ((ULONG)Address +
  656. (ULONG)&(KiProcessorBlock[Processor]->ProcessorState));
  657. Status = KdpCopyFromPtr(StartAddr,
  658. Buffer,
  659. Request,
  660. Actual);
  661. } else {
  662. Status = STATUS_UNSUCCESSFUL;
  663. *Actual = 0;
  664. }
  665. return Status;
  666. }
  667. NTSTATUS
  668. KdpSysReadIoSpace(
  669. INTERFACE_TYPE InterfaceType,
  670. ULONG BusNumber,
  671. ULONG AddressSpace,
  672. ULONG64 Address,
  673. PVOID Buffer,
  674. ULONG Request,
  675. PULONG Actual
  676. )
  677. /*++
  678. Routine Description:
  679. Reads system I/O locations.
  680. Arguments:
  681. InterfaceType - I/O interface type.
  682. BusNumber - Bus number.
  683. AddressSpace - Address space.
  684. Address - I/O address.
  685. Buffer - Data buffer.
  686. Request - Amount of data to move.
  687. Actual - Amount of data actually moved.
  688. Return Value:
  689. NTSTATUS.
  690. --*/
  691. {
  692. NTSTATUS Status = STATUS_SUCCESS;
  693. if (InterfaceType != Isa || BusNumber != 0 || AddressSpace != 1) {
  694. *Actual = 0;
  695. return STATUS_UNSUCCESSFUL;
  696. }
  697. //
  698. // Check Size and Alignment
  699. //
  700. switch ( Request ) {
  701. case 1:
  702. *(PUCHAR)Buffer = READ_PORT_UCHAR((PUCHAR)(ULONG_PTR)Address);
  703. *Actual = 1;
  704. break;
  705. case 2:
  706. if ( Address & 1 ) {
  707. Status = STATUS_DATATYPE_MISALIGNMENT;
  708. } else {
  709. *(PUSHORT)Buffer =
  710. READ_PORT_USHORT((PUSHORT)(ULONG_PTR)Address);
  711. *Actual = 2;
  712. }
  713. break;
  714. case 4:
  715. if ( Address & 3 ) {
  716. Status = STATUS_DATATYPE_MISALIGNMENT;
  717. } else {
  718. *(PULONG)Buffer =
  719. READ_PORT_ULONG((PULONG)(ULONG_PTR)Address);
  720. *Actual = 4;
  721. }
  722. break;
  723. default:
  724. Status = STATUS_INVALID_PARAMETER;
  725. *Actual = 0;
  726. break;
  727. }
  728. return Status;
  729. }
  730. NTSTATUS
  731. KdpSysWriteIoSpace(
  732. INTERFACE_TYPE InterfaceType,
  733. ULONG BusNumber,
  734. ULONG AddressSpace,
  735. ULONG64 Address,
  736. PVOID Buffer,
  737. ULONG Request,
  738. PULONG Actual
  739. )
  740. /*++
  741. Routine Description:
  742. Writes system I/O locations.
  743. Arguments:
  744. InterfaceType - I/O interface type.
  745. BusNumber - Bus number.
  746. AddressSpace - Address space.
  747. Address - I/O address.
  748. Buffer - Data buffer.
  749. Request - Amount of data to move.
  750. Actual - Amount of data actually moved.
  751. Return Value:
  752. NTSTATUS.
  753. --*/
  754. {
  755. NTSTATUS Status = STATUS_SUCCESS;
  756. if (InterfaceType != Isa || BusNumber != 0 || AddressSpace != 1) {
  757. *Actual = 0;
  758. return STATUS_UNSUCCESSFUL;
  759. }
  760. //
  761. // Check Size and Alignment
  762. //
  763. switch ( Request ) {
  764. case 1:
  765. WRITE_PORT_UCHAR((PUCHAR)(ULONG_PTR)Address,
  766. *(PUCHAR)Buffer);
  767. *Actual = 1;
  768. break;
  769. case 2:
  770. if ( Address & 1 ) {
  771. Status = STATUS_DATATYPE_MISALIGNMENT;
  772. } else {
  773. WRITE_PORT_USHORT((PUSHORT)(ULONG_PTR)Address,
  774. *(PUSHORT)Buffer);
  775. *Actual = 2;
  776. }
  777. break;
  778. case 4:
  779. if ( Address & 3 ) {
  780. Status = STATUS_DATATYPE_MISALIGNMENT;
  781. } else {
  782. WRITE_PORT_ULONG((PULONG)(ULONG_PTR)Address,
  783. *(PULONG)Buffer);
  784. *Actual = 4;
  785. }
  786. break;
  787. default:
  788. Status = STATUS_INVALID_PARAMETER;
  789. *Actual = 0;
  790. break;
  791. }
  792. return Status;
  793. }
  794. NTSTATUS
  795. KdpSysReadMsr(
  796. ULONG Msr,
  797. PULONG64 Data
  798. )
  799. /*++
  800. Routine Description:
  801. Reads an MSR.
  802. Arguments:
  803. Msr - MSR index.
  804. Data - Data buffer.
  805. Return Value:
  806. NTSTATUS.
  807. --*/
  808. {
  809. NTSTATUS Status = STATUS_SUCCESS;
  810. try {
  811. *Data = RDMSR(Msr);
  812. } except (EXCEPTION_EXECUTE_HANDLER) {
  813. *Data = 0;
  814. Status = STATUS_NO_SUCH_DEVICE;
  815. }
  816. return Status;
  817. }
  818. NTSTATUS
  819. KdpSysWriteMsr(
  820. ULONG Msr,
  821. PULONG64 Data
  822. )
  823. /*++
  824. Routine Description:
  825. Writes an MSR.
  826. Arguments:
  827. Msr - MSR index.
  828. Data - Data buffer.
  829. Return Value:
  830. NTSTATUS.
  831. --*/
  832. {
  833. NTSTATUS Status = STATUS_SUCCESS;
  834. try {
  835. WRMSR (Msr, *Data);
  836. } except (EXCEPTION_EXECUTE_HANDLER) {
  837. Status = STATUS_NO_SUCH_DEVICE;
  838. }
  839. return Status;
  840. }
  841. /*** KdpGetCallNextOffset - compute "next" instruction on a call-like instruction
  842. *
  843. * Purpose:
  844. * Compute how many bytes are in a call-type instruction
  845. * so that a breakpoint can be set upon this instruction's
  846. * return. Treat indirect jmps as if they were call/ret/ret
  847. *
  848. * Returns:
  849. * offset to "next" instruction, or 0 if it wasn't a call instruction.
  850. *
  851. *************************************************************************/
  852. ULONG
  853. KdpGetCallNextOffset (
  854. ULONG Pc,
  855. PCONTEXT ContextRecord
  856. )
  857. {
  858. UCHAR membuf[2];
  859. UCHAR opcode;
  860. ULONG sib;
  861. ULONG disp;
  862. if (!NT_SUCCESS(KdpCopyFromPtr( membuf, Pc, 2, NULL ))) {
  863. return 0;
  864. }
  865. opcode = membuf[0];
  866. if ( opcode == 0xe8 ) { // CALL 32 bit disp
  867. return Pc+5;
  868. } else if ( opcode == 0x9a ) { // CALL 16:32
  869. return Pc+7;
  870. } else if ( opcode == 0xff ) {
  871. if ( membuf[1] == 0x25) { // JMP indirect
  872. return KdpGetReturnAddress( ContextRecord );
  873. }
  874. sib = ((membuf[1] & 0x07) == 0x04) ? 1 : 0;
  875. disp = (membuf[1] & 0xc0) >> 6;
  876. switch (disp) {
  877. case 0:
  878. if ( (membuf[1] & 0x07) == 0x05 ) {
  879. disp = 4; // disp32 alone
  880. } else {
  881. // disp = 0; // no displacement with reg or sib
  882. }
  883. break;
  884. case 1:
  885. // disp = 1; // disp8 with reg or sib
  886. break;
  887. case 2:
  888. disp = 4; // disp32 with reg or sib
  889. break;
  890. case 3:
  891. disp = 0; // direct register addressing (e.g., call esi)
  892. break;
  893. }
  894. return Pc + 2 + sib + disp;
  895. }
  896. return 0;
  897. } // KdpGetCallNextOffset