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.

170 lines
5.2 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Disassembly portions of AMD64 machine implementation.
  4. //
  5. // Copyright (C) Microsoft Corporation, 2000-2002.
  6. //
  7. //----------------------------------------------------------------------------
  8. #include "ntsdp.hpp"
  9. #define BIT20(b) ((b) & 0x07)
  10. #define BIT53(b) (((b) >> 3) & 0x07)
  11. #define BIT76(b) (((b) >> 6) & 0x03)
  12. HRESULT
  13. Amd64MachineInfo::NewBreakpoint(DebugClient* Client,
  14. ULONG Type,
  15. ULONG Id,
  16. Breakpoint** RetBp)
  17. {
  18. HRESULT Status;
  19. switch(Type & (DEBUG_BREAKPOINT_CODE | DEBUG_BREAKPOINT_DATA))
  20. {
  21. case DEBUG_BREAKPOINT_CODE:
  22. *RetBp = new CodeBreakpoint(Client, Id, IMAGE_FILE_MACHINE_AMD64);
  23. Status = (*RetBp) ? S_OK : E_OUTOFMEMORY;
  24. break;
  25. case DEBUG_BREAKPOINT_DATA:
  26. *RetBp = new X86DataBreakpoint(Client, Id, AMD64_CR4,
  27. IS_KERNEL_TARGET(m_Target) ?
  28. AMD64_KDR6 : AMD64_DR6,
  29. IMAGE_FILE_MACHINE_AMD64);
  30. Status = (*RetBp) ? S_OK : E_OUTOFMEMORY;
  31. break;
  32. default:
  33. // Unknown breakpoint type.
  34. Status = E_NOINTERFACE;
  35. }
  36. return Status;
  37. }
  38. void
  39. Amd64MachineInfo::InsertThreadDataBreakpoints(void)
  40. {
  41. ULONG64 Dr7Value;
  42. ULONG Dr6Idx, Dr7Idx, Dr0Idx;
  43. BpOut("Thread %d data breaks %d\n",
  44. g_Thread->m_UserId, g_Thread->m_NumDataBreaks);
  45. if (IS_KERNEL_TARGET(m_Target))
  46. {
  47. Dr6Idx = AMD64_KDR6;
  48. Dr7Idx = AMD64_KDR7;
  49. Dr0Idx = AMD64_KDR0;
  50. }
  51. else
  52. {
  53. Dr6Idx = AMD64_DR6;
  54. Dr7Idx = AMD64_DR7;
  55. Dr0Idx = AMD64_DR0;
  56. }
  57. // Start with all breaks turned off.
  58. Dr7Value = GetReg64(Dr7Idx) & ~X86_DR7_CTRL_03_MASK;
  59. if (g_Thread->m_NumDataBreaks > 0)
  60. {
  61. ULONG i;
  62. for (i = 0; i < g_Thread->m_NumDataBreaks; i++)
  63. {
  64. X86DataBreakpoint* Bp =
  65. (X86DataBreakpoint *)g_Thread->m_DataBreakBps[i];
  66. ULONG64 Addr = Flat(*Bp->GetAddr());
  67. BpOut(" dbp %d at %I64x\n", i, Addr);
  68. if (g_DataBreakpointsChanged)
  69. {
  70. SetReg64(Dr0Idx + i, Addr);
  71. }
  72. // There are two enable bits per breakpoint
  73. // and four len/rw bits so split up enables
  74. // and len/rw when shifting into place.
  75. Dr7Value |=
  76. ((Bp->m_Dr7Bits & 0xffff0000) << (i * 4)) |
  77. ((Bp->m_Dr7Bits & X86_DR7_ALL_ENABLES) << (i * 2));
  78. }
  79. // The kernel automatically clears DR6 when it
  80. // processes a DBGKD_CONTROL_SET.
  81. if (IS_USER_TARGET(m_Target))
  82. {
  83. SetReg64(Dr6Idx, 0);
  84. }
  85. // Set local exact match, which is effectively global on NT.
  86. Dr7Value |= X86_DR7_LOCAL_EXACT_ENABLE;
  87. }
  88. BpOut(" thread %d DR7 %I64X\n", g_Thread->m_UserId, Dr7Value);
  89. SetReg64(Dr7Idx, Dr7Value);
  90. }
  91. void
  92. Amd64MachineInfo::RemoveThreadDataBreakpoints(void)
  93. {
  94. SetReg64(IS_KERNEL_TARGET(m_Target) ? AMD64_KDR7 : AMD64_DR7, 0);
  95. }
  96. ULONG
  97. Amd64MachineInfo::IsBreakpointOrStepException(PEXCEPTION_RECORD64 Record,
  98. ULONG FirstChance,
  99. PADDR BpAddr,
  100. PADDR RelAddr)
  101. {
  102. if (Record->ExceptionCode == STATUS_BREAKPOINT)
  103. {
  104. // Data breakpoints hit as STATUS_SINGLE_STEP so
  105. // this can only be a code breakpoint.
  106. if (IS_USER_TARGET(m_Target) && FirstChance)
  107. {
  108. // Back up to the actual breakpoint instruction.
  109. AddrSub(BpAddr, X86_INT3_LEN);
  110. SetPC(BpAddr);
  111. }
  112. return EXBS_BREAKPOINT_CODE;
  113. }
  114. else if (Record->ExceptionCode == STATUS_SINGLE_STEP)
  115. {
  116. ULONG64 Dr6;
  117. ULONG64 Dr7;
  118. if (IS_KERNEL_TARGET(m_Target))
  119. {
  120. Dr6 = GetReg64(AMD64_KDR6);
  121. Dr7 = GetReg64(AMD64_KDR7);
  122. }
  123. else
  124. {
  125. Dr6 = GetReg64(AMD64_DR6);
  126. Dr7 = GetReg64(AMD64_DR7);
  127. }
  128. BpOut("Amd64 step: DR6 %I64X, DR7 %I64X\n", Dr6, Dr7);
  129. // The single step bit should always be clear if a data breakpoint
  130. // is hit but also check the DR7 enables just in case.
  131. // We've also seen cases where DR6 shows no hits, so consider
  132. // that a single step also.
  133. if ((Dr6 & X86_DR6_SINGLE_STEP) || (Dr7 & X86_DR7_ALL_ENABLES) == 0 ||
  134. (Dr6 & X86_DR6_BREAK_03) == 0)
  135. {
  136. // This is a true single step exception, not
  137. // a data breakpoint.
  138. return EXBS_STEP_INSTRUCTION;
  139. }
  140. else
  141. {
  142. // Some data breakpoint must be hit.
  143. // There doesn't appear to be any way to get the
  144. // faulting instruction address so just leave the PC.
  145. return EXBS_BREAKPOINT_DATA;
  146. }
  147. }
  148. return EXBS_NONE;
  149. }