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.

504 lines
14 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Copyright (c) 1998 Intel Corporation
  4. Module Name:
  5. kdtrap.c
  6. Abstract:
  7. This module contains code to implement the target side of the portable
  8. kernel debugger.
  9. Author:
  10. David N. Cutler 27-July-1990
  11. Revision History:
  12. --*/
  13. #include "kdp.h"
  14. #ifdef _GAMBIT_
  15. #include "ssc.h"
  16. #endif // _GAMBIT_
  17. BOOLEAN
  18. KdpTrap (
  19. IN PKTRAP_FRAME TrapFrame,
  20. IN PKEXCEPTION_FRAME ExceptionFrame,
  21. IN PEXCEPTION_RECORD ExceptionRecord,
  22. IN PCONTEXT ContextRecord,
  23. IN KPROCESSOR_MODE PreviousMode,
  24. IN BOOLEAN SecondChance
  25. )
  26. /*++
  27. Routine Description:
  28. This routine is called whenever a exception is dispatched and the kernel
  29. debugger is active.
  30. Arguments:
  31. TrapFrame - Supplies a pointer to a trap frame that describes the
  32. trap.
  33. ExceptionFrame - Supplies a pointer to a exception frame that describes
  34. the trap.
  35. ExceptionRecord - Supplies a pointer to an exception record that
  36. describes the exception.
  37. ContextRecord - Supplies the context at the time of the exception.
  38. PreviousMode - Supplies the previous processor mode.
  39. SecondChance - Supplies a boolean value that determines whether this is
  40. the second chance (TRUE) that the exception has been raised.
  41. Return Value:
  42. A value of TRUE is returned if the exception is handled. Otherwise a
  43. value of FALSE is returned.
  44. --*/
  45. {
  46. BOOLEAN Completion = FALSE;
  47. BOOLEAN UnloadSymbols = FALSE;
  48. ULONGLONG OldStIIP, OldStIPSR;
  49. //
  50. // Disable all hardware breakpoints
  51. //
  52. KeSetLowPsrBit(PSR_DB, 0);
  53. //
  54. // Synchronize processor execution, save processor state, enter debugger,
  55. // and flush the current TB.
  56. //
  57. KeFlushCurrentTb();
  58. //
  59. // If this is a breakpoint instruction, then check to determine if is
  60. // an internal command.
  61. //
  62. if (((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) &&
  63. (ExceptionRecord->ExceptionInformation[0] >= BREAKPOINT_PRINT)) ||
  64. ((ExceptionRecord->ExceptionCode == STATUS_WX86_BREAKPOINT) &&
  65. (ExceptionRecord->ExceptionInformation[0] == BREAKPOINT_X86_BREAK))) {
  66. //
  67. // Switch on the breakpoint code.
  68. //
  69. switch (ExceptionRecord->ExceptionInformation[0]) {
  70. //
  71. // Print a debug string.
  72. //
  73. // Arguments: IA64 passes arguments via RSE not GR's. Since arguments are not
  74. // part of CONTEXT struct, they need to be copies Temp registers.
  75. // (see NTOS/RTL/IA64/DEBUGSTB.S)
  76. //
  77. // T0 - Supplies a pointer to an output string buffer.
  78. // T1 - Supplies the length of the output string buffer.
  79. // T2 - Supplies the Id of the calling component.
  80. // T3 - Supplies the output filter level.
  81. //
  82. case BREAKPOINT_PRINT:
  83. //
  84. // Advance to next instruction slot so that the BREAK instruction
  85. // does not get re-executed.
  86. //
  87. RtlIa64IncrementIP((ULONG_PTR)ExceptionRecord->ExceptionAddress >> 2,
  88. ContextRecord->StIPSR,
  89. ContextRecord->StIIP);
  90. //
  91. // Print the debug message.
  92. //
  93. ContextRecord->IntV0 = KdpPrint((ULONG)ContextRecord->IntT2,
  94. (ULONG)ContextRecord->IntT3,
  95. (PCHAR)ContextRecord->IntT0,
  96. (USHORT)ContextRecord->IntT1,
  97. PreviousMode,
  98. TrapFrame,
  99. ExceptionFrame,
  100. &Completion);
  101. return Completion;
  102. //
  103. // Print a debug prompt string, then input a string.
  104. //
  105. // T0 - Supplies a pointer to an output string buffer.
  106. // T1 - Supplies the length of the output string buffer..
  107. // T2 - supplies a pointer to an input string buffer.
  108. // T3 - Supplies the length of the input string bufffer.
  109. //
  110. case BREAKPOINT_PROMPT:
  111. //
  112. // Advance to next instruction slot so that the BREAK instruction
  113. // does not get re-executed.
  114. //
  115. RtlIa64IncrementIP((ULONG_PTR)ExceptionRecord->ExceptionAddress >> 2,
  116. ContextRecord->StIPSR,
  117. ContextRecord->StIIP);
  118. ContextRecord->IntV0 = KdpPrompt((PCHAR)ContextRecord->IntT0,
  119. (USHORT)ContextRecord->IntT1,
  120. (PCHAR)ContextRecord->IntT2,
  121. (USHORT)ContextRecord->IntT3,
  122. PreviousMode,
  123. TrapFrame,
  124. ExceptionFrame);
  125. return TRUE;
  126. //
  127. // Load the symbolic information for an image.
  128. //
  129. // Arguments:
  130. //
  131. // T0 - Supplies a pointer to an output string descriptor.
  132. // T1 - Supplies a the base address of the image.
  133. //
  134. case BREAKPOINT_UNLOAD_SYMBOLS:
  135. UnloadSymbols = TRUE;
  136. //
  137. // Fall through
  138. //
  139. case BREAKPOINT_LOAD_SYMBOLS:
  140. OldStIPSR = ContextRecord->StIPSR;
  141. OldStIIP = ContextRecord->StIIP;
  142. KdpSymbol((PSTRING)ContextRecord->IntT0,
  143. (PKD_SYMBOLS_INFO)ContextRecord->IntT1,
  144. UnloadSymbols,
  145. PreviousMode,
  146. ContextRecord,
  147. TrapFrame,
  148. ExceptionFrame);
  149. //
  150. // If the kernel debugger did not update the IP, then increment
  151. // past the breakpoint instruction.
  152. //
  153. if ((ContextRecord->StIIP == OldStIIP) &&
  154. ((ContextRecord->StIPSR & IPSR_RI_MASK) == (OldStIPSR & IPSR_RI_MASK))) {
  155. RtlIa64IncrementIP((ULONG_PTR)ExceptionRecord->ExceptionAddress >> 2,
  156. ContextRecord->StIPSR,
  157. ContextRecord->StIIP);
  158. }
  159. return TRUE;
  160. case BREAKPOINT_COMMAND_STRING:
  161. OldStIPSR = ContextRecord->StIPSR;
  162. OldStIIP = ContextRecord->StIIP;
  163. KdpCommandString((PSTRING)ContextRecord->IntT0,
  164. (PSTRING)ContextRecord->IntT1,
  165. PreviousMode,
  166. ContextRecord,
  167. TrapFrame,
  168. ExceptionFrame);
  169. //
  170. // If the kernel debugger did not update the IP, then increment
  171. // past the breakpoint instruction.
  172. //
  173. if ((ContextRecord->StIIP == OldStIIP) &&
  174. ((ContextRecord->StIPSR & IPSR_RI_MASK) == (OldStIPSR & IPSR_RI_MASK))) {
  175. RtlIa64IncrementIP((ULONG_PTR)ExceptionRecord->ExceptionAddress >> 2,
  176. ContextRecord->StIPSR,
  177. ContextRecord->StIIP);
  178. }
  179. return TRUE;
  180. //
  181. // Kernel breakin break
  182. //
  183. case BREAKPOINT_BREAKIN:
  184. //
  185. // Advance to next instruction slot so that the BREAK instruction
  186. // does not get re-executed
  187. //
  188. RtlIa64IncrementIP((ULONG_PTR)ExceptionRecord->ExceptionAddress >> 2,
  189. ContextRecord->StIPSR,
  190. ContextRecord->StIIP);
  191. break;
  192. //
  193. // Basic breakpoint.
  194. //
  195. case BREAKPOINT_X86_BREAK:
  196. case BREAKPOINT_STOP:
  197. break;
  198. //
  199. // Unknown internal command.
  200. //
  201. default:
  202. return FALSE;
  203. }
  204. }
  205. //
  206. // Report state change to the kernel debugger.
  207. //
  208. return KdpReport(TrapFrame,
  209. ExceptionFrame,
  210. ExceptionRecord,
  211. ContextRecord,
  212. PreviousMode,
  213. SecondChance);
  214. }
  215. BOOLEAN
  216. KdIsThisAKdTrap (
  217. IN PEXCEPTION_RECORD ExceptionRecord,
  218. IN PCONTEXT ContextRecord,
  219. IN KPROCESSOR_MODE PreviousMode
  220. )
  221. /*++
  222. Routine Description:
  223. This routine is called whenever a user-mode exception occurs and
  224. it might be a kernel debugger exception (Like DbgPrint/DbgPrompt ).
  225. Arguments:
  226. ExceptionRecord - Supplies a pointer to an exception record that
  227. describes the exception.
  228. ContextRecord - Supplies the context at the time of the exception.
  229. PreviousMode - Supplies the previous processor mode.
  230. Return Value:
  231. A value of TRUE is returned if this is for the kernel debugger.
  232. Otherwise, a value of FALSE is returned.
  233. --*/
  234. {
  235. ULONG_PTR BreakpointCode;
  236. UNREFERENCED_PARAMETER (ContextRecord);
  237. //
  238. // Single step is also handled by the kernel debugger
  239. //
  240. if (ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP) {
  241. #if DEVL
  242. return TRUE;
  243. #else
  244. if (PreviousMode == KernelMode) {
  245. return TRUE;
  246. } else {
  247. return FALSE;
  248. }
  249. #endif
  250. }
  251. //
  252. // If is is not status breakpoint then it is not a kernel debugger trap.
  253. //
  254. if ((ExceptionRecord->ExceptionCode != STATUS_BREAKPOINT) &&
  255. (ExceptionRecord->ExceptionCode != STATUS_WX86_BREAKPOINT)) {
  256. return FALSE;
  257. }
  258. //
  259. // Isolate the breakpoint code from the breakpoint instruction which
  260. // is stored by the exception dispatch code in the information field
  261. // of the exception record.
  262. //
  263. BreakpointCode = (ULONG) ExceptionRecord->ExceptionInformation[0];
  264. //
  265. // Switch on the breakpoint code.
  266. //
  267. switch (BreakpointCode) {
  268. //
  269. // Kernel breakpoint codes.
  270. //
  271. case KERNEL_BREAKPOINT:
  272. case BREAKPOINT_X86_BREAK:
  273. case BREAKPOINT_BREAKIN:
  274. case BREAKPOINT_PRINT:
  275. case BREAKPOINT_PROMPT:
  276. case BREAKPOINT_STOP:
  277. return TRUE;
  278. case BREAKPOINT_LOAD_SYMBOLS:
  279. case BREAKPOINT_UNLOAD_SYMBOLS:
  280. case BREAKPOINT_COMMAND_STRING:
  281. if (PreviousMode == KernelMode) {
  282. return TRUE;
  283. } else {
  284. return FALSE;
  285. }
  286. //
  287. // All other codes.
  288. //
  289. default:
  290. return FALSE;
  291. }
  292. }
  293. BOOLEAN
  294. KdpStub (
  295. IN PKTRAP_FRAME TrapFrame,
  296. IN PKEXCEPTION_FRAME ExceptionFrame,
  297. IN PEXCEPTION_RECORD ExceptionRecord,
  298. IN PCONTEXT ContextRecord,
  299. IN KPROCESSOR_MODE PreviousMode,
  300. IN BOOLEAN SecondChance
  301. )
  302. /*++
  303. Routine Description:
  304. This routine provides a kernel debugger stub routine that catchs debug
  305. prints in checked systems when the kernel debugger is not active.
  306. Arguments:
  307. TrapFrame - Supplies a pointer to a trap frame that describes the
  308. trap.
  309. ExceptionFrame - Supplies a pointer to a exception frame that describes
  310. the trap.
  311. ExceptionRecord - Supplies a pointer to an exception record that
  312. describes the exception.
  313. ContextRecord - Supplies the context at the time of the exception.
  314. PreviousMode - Supplies the previous processor mode.
  315. SecondChance - Supplies a boolean value that determines whether this is
  316. the second chance (TRUE) that the exception has been raised.
  317. Return Value:
  318. A value of TRUE is returned if the exception is handled. Otherwise a
  319. value of FALSE is returned.
  320. --*/
  321. {
  322. ULONG_PTR BreakpointCode;
  323. UNREFERENCED_PARAMETER (TrapFrame);
  324. UNREFERENCED_PARAMETER (ExceptionFrame);
  325. UNREFERENCED_PARAMETER (PreviousMode);
  326. UNREFERENCED_PARAMETER (SecondChance);
  327. //
  328. // Isolate the breakpoint code from the breakpoint instruction which
  329. // is stored by the exception dispatch code in the information field
  330. // of the exception record.
  331. //
  332. BreakpointCode = (ULONG) ExceptionRecord->ExceptionInformation[0];
  333. //
  334. // If the breakpoint is a debug print, debug load symbols, or debug
  335. // unload symbols, then return TRUE. Otherwise, return FALSE;
  336. //
  337. if ((BreakpointCode == BREAKPOINT_PRINT) ||
  338. (BreakpointCode == BREAKPOINT_COMMAND_STRING) ||
  339. (BreakpointCode == BREAKPOINT_LOAD_SYMBOLS) ||
  340. (BreakpointCode == BREAKPOINT_UNLOAD_SYMBOLS)) {
  341. //
  342. // Advance to next instruction slot so that the BREAK instruction
  343. // does not get re-executed
  344. //
  345. RtlIa64IncrementIP((ULONG_PTR)ExceptionRecord->ExceptionAddress >> 2,
  346. ContextRecord->StIPSR,
  347. ContextRecord->StIIP);
  348. return TRUE;
  349. } else if (!KdPitchDebugger &&
  350. KdAutoEnableOnEvent &&
  351. KdPreviouslyEnabled &&
  352. !KdDebuggerEnabled) {
  353. // If there are multiple disables this may not reenable
  354. // the debugger. Check before calling the full trap routine.
  355. if (NT_SUCCESS(KdEnableDebugger()) &&
  356. KdDebuggerEnabled) {
  357. return KdpTrap(TrapFrame, ExceptionFrame, ExceptionRecord,
  358. ContextRecord, PreviousMode, SecondChance);
  359. } else {
  360. return FALSE;
  361. }
  362. } else {
  363. return FALSE;
  364. }
  365. }