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.

474 lines
12 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. //
  65. // Switch on the breakpoint code.
  66. //
  67. switch (ExceptionRecord->ExceptionInformation[0]) {
  68. //
  69. // Print a debug string.
  70. //
  71. // Arguments: IA64 passes arguments via RSE not GR's. Since arguments are not
  72. // part of CONTEXT struct, they need to be copies Temp registers.
  73. // (see NTOS/RTL/IA64/DEBUGSTB.S)
  74. //
  75. // T0 - Supplies a pointer to an output string buffer.
  76. // T1 - Supplies the length of the output string buffer.
  77. // T2 - Supplies the Id of the calling component.
  78. // T3 - Supplies the output filter level.
  79. //
  80. case BREAKPOINT_PRINT:
  81. //
  82. // Advance to next instruction slot so that the BREAK instruction
  83. // does not get re-executed.
  84. //
  85. RtlIa64IncrementIP((ULONG_PTR)ExceptionRecord->ExceptionAddress >> 2,
  86. ContextRecord->StIPSR,
  87. ContextRecord->StIIP);
  88. //
  89. // Print the debug message.
  90. //
  91. ContextRecord->IntV0 = KdpPrint((ULONG)ContextRecord->IntT2,
  92. (ULONG)ContextRecord->IntT3,
  93. (PCHAR)ContextRecord->IntT0,
  94. (USHORT)ContextRecord->IntT1,
  95. PreviousMode,
  96. TrapFrame,
  97. ExceptionFrame,
  98. &Completion);
  99. return Completion;
  100. //
  101. // Print a debug prompt string, then input a string.
  102. //
  103. // T0 - Supplies a pointer to an output string buffer.
  104. // T1 - Supplies the length of the output string buffer..
  105. // T2 - supplies a pointer to an input string buffer.
  106. // T3 - Supplies the length of the input string bufffer.
  107. //
  108. case BREAKPOINT_PROMPT:
  109. //
  110. // Advance to next instruction slot so that the BREAK instruction
  111. // does not get re-executed.
  112. //
  113. RtlIa64IncrementIP((ULONG_PTR)ExceptionRecord->ExceptionAddress >> 2,
  114. ContextRecord->StIPSR,
  115. ContextRecord->StIIP);
  116. ContextRecord->IntV0 = KdpPrompt((PCHAR)ContextRecord->IntT0,
  117. (USHORT)ContextRecord->IntT1,
  118. (PCHAR)ContextRecord->IntT2,
  119. (USHORT)ContextRecord->IntT3,
  120. PreviousMode,
  121. TrapFrame,
  122. ExceptionFrame);
  123. return TRUE;
  124. //
  125. // Load the symbolic information for an image.
  126. //
  127. // Arguments:
  128. //
  129. // T0 - Supplies a pointer to an output string descriptor.
  130. // T1 - Supplies a the base address of the image.
  131. //
  132. case BREAKPOINT_UNLOAD_SYMBOLS:
  133. UnloadSymbols = TRUE;
  134. //
  135. // Fall through
  136. //
  137. case BREAKPOINT_LOAD_SYMBOLS:
  138. OldStIPSR = ContextRecord->StIPSR;
  139. OldStIIP = ContextRecord->StIIP;
  140. KdpSymbol((PSTRING)ContextRecord->IntT0,
  141. (PKD_SYMBOLS_INFO)ContextRecord->IntT1,
  142. UnloadSymbols,
  143. PreviousMode,
  144. ContextRecord,
  145. TrapFrame,
  146. ExceptionFrame);
  147. //
  148. // If the kernel debugger did not update the IP, then increment
  149. // past the breakpoint instruction.
  150. //
  151. if ((ContextRecord->StIIP == OldStIIP) &&
  152. ((ContextRecord->StIPSR & IPSR_RI_MASK) == (OldStIPSR & IPSR_RI_MASK))) {
  153. RtlIa64IncrementIP((ULONG_PTR)ExceptionRecord->ExceptionAddress >> 2,
  154. ContextRecord->StIPSR,
  155. ContextRecord->StIIP);
  156. }
  157. return TRUE;
  158. case BREAKPOINT_COMMAND_STRING:
  159. OldStIPSR = ContextRecord->StIPSR;
  160. OldStIIP = ContextRecord->StIIP;
  161. KdpCommandString((PSTRING)ContextRecord->IntT0,
  162. (PSTRING)ContextRecord->IntT1,
  163. PreviousMode,
  164. ContextRecord,
  165. TrapFrame,
  166. ExceptionFrame);
  167. //
  168. // If the kernel debugger did not update the IP, then increment
  169. // past the breakpoint instruction.
  170. //
  171. if ((ContextRecord->StIIP == OldStIIP) &&
  172. ((ContextRecord->StIPSR & IPSR_RI_MASK) == (OldStIPSR & IPSR_RI_MASK))) {
  173. RtlIa64IncrementIP((ULONG_PTR)ExceptionRecord->ExceptionAddress >> 2,
  174. ContextRecord->StIPSR,
  175. ContextRecord->StIIP);
  176. }
  177. return TRUE;
  178. //
  179. // Kernel breakin break
  180. //
  181. case BREAKPOINT_BREAKIN:
  182. //
  183. // Advance to next instruction slot so that the BREAK instruction
  184. // does not get re-executed
  185. //
  186. RtlIa64IncrementIP((ULONG_PTR)ExceptionRecord->ExceptionAddress >> 2,
  187. ContextRecord->StIPSR,
  188. ContextRecord->StIIP);
  189. break;
  190. //
  191. // Basic breakpoint.
  192. //
  193. case BREAKPOINT_STOP:
  194. break;
  195. //
  196. // Unknown internal command.
  197. //
  198. default:
  199. return FALSE;
  200. }
  201. }
  202. //
  203. // Report state change to the kernel debugger.
  204. //
  205. return KdpReport(TrapFrame,
  206. ExceptionFrame,
  207. ExceptionRecord,
  208. ContextRecord,
  209. PreviousMode,
  210. SecondChance);
  211. }
  212. BOOLEAN
  213. KdIsThisAKdTrap (
  214. IN PEXCEPTION_RECORD ExceptionRecord,
  215. IN PCONTEXT ContextRecord,
  216. IN KPROCESSOR_MODE PreviousMode
  217. )
  218. /*++
  219. Routine Description:
  220. This routine is called whenever a user-mode exception occurs and
  221. it might be a kernel debugger exception (Like DbgPrint/DbgPrompt ).
  222. Arguments:
  223. ExceptionRecord - Supplies a pointer to an exception record that
  224. describes the exception.
  225. ContextRecord - Supplies the context at the time of the exception.
  226. PreviousMode - Supplies the previous processor mode.
  227. Return Value:
  228. A value of TRUE is returned if this is for the kernel debugger.
  229. Otherwise, a value of FALSE is returned.
  230. --*/
  231. {
  232. ULONG_PTR BreakpointCode;
  233. //
  234. // Single step is also handled by the kernel debugger
  235. //
  236. if (ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP) {
  237. #if DEVL
  238. return TRUE;
  239. #else
  240. if (PreviousMode == KernelMode) {
  241. return TRUE;
  242. } else {
  243. return FALSE;
  244. }
  245. #endif
  246. }
  247. //
  248. // If is is not status breakpoint then it is not a kernel debugger trap.
  249. //
  250. if (ExceptionRecord->ExceptionCode != STATUS_BREAKPOINT) {
  251. return FALSE;
  252. }
  253. //
  254. // Isolate the breakpoint code from the breakpoint instruction which
  255. // is stored by the exception dispatch code in the information field
  256. // of the exception record.
  257. //
  258. BreakpointCode = (ULONG) ExceptionRecord->ExceptionInformation[0];
  259. //
  260. // Switch on the breakpoint code.
  261. //
  262. switch (BreakpointCode) {
  263. //
  264. // Kernel breakpoint codes.
  265. //
  266. case KERNEL_BREAKPOINT:
  267. case BREAKPOINT_BREAKIN:
  268. case BREAKPOINT_PRINT:
  269. case BREAKPOINT_PROMPT:
  270. case BREAKPOINT_STOP:
  271. return TRUE;
  272. case BREAKPOINT_LOAD_SYMBOLS:
  273. case BREAKPOINT_UNLOAD_SYMBOLS:
  274. if (PreviousMode == KernelMode) {
  275. return TRUE;
  276. } else {
  277. return FALSE;
  278. }
  279. //
  280. // All other codes.
  281. //
  282. default:
  283. return FALSE;
  284. }
  285. }
  286. BOOLEAN
  287. KdpStub (
  288. IN PKTRAP_FRAME TrapFrame,
  289. IN PKEXCEPTION_FRAME ExceptionFrame,
  290. IN PEXCEPTION_RECORD ExceptionRecord,
  291. IN PCONTEXT ContextRecord,
  292. IN KPROCESSOR_MODE PreviousMode,
  293. IN BOOLEAN SecondChance
  294. )
  295. /*++
  296. Routine Description:
  297. This routine provides a kernel debugger stub routine that catchs debug
  298. prints in checked systems when the kernel debugger is not active.
  299. Arguments:
  300. TrapFrame - Supplies a pointer to a trap frame that describes the
  301. trap.
  302. ExceptionFrame - Supplies a pointer to a exception frame that describes
  303. the trap.
  304. ExceptionRecord - Supplies a pointer to an exception record that
  305. describes the exception.
  306. ContextRecord - Supplies the context at the time of the exception.
  307. PreviousMode - Supplies the previous processor mode.
  308. SecondChance - Supplies a boolean value that determines whether this is
  309. the second chance (TRUE) that the exception has been raised.
  310. Return Value:
  311. A value of TRUE is returned if the exception is handled. Otherwise a
  312. value of FALSE is returned.
  313. --*/
  314. {
  315. ULONG_PTR BreakpointCode;
  316. //
  317. // Isolate the breakpoint code from the breakpoint instruction which
  318. // is stored by the exception dispatch code in the information field
  319. // of the exception record.
  320. //
  321. BreakpointCode = (ULONG) ExceptionRecord->ExceptionInformation[0];
  322. //
  323. // If the breakpoint is a debug print, debug load symbols, or debug
  324. // unload symbols, then return TRUE. Otherwise, return FALSE;
  325. //
  326. if ((BreakpointCode == BREAKPOINT_PRINT) ||
  327. (BreakpointCode == BREAKPOINT_LOAD_SYMBOLS) ||
  328. (BreakpointCode == BREAKPOINT_UNLOAD_SYMBOLS)) {
  329. //
  330. // Advance to next instruction slot so that the BREAK instruction
  331. // does not get re-executed
  332. //
  333. RtlIa64IncrementIP((ULONG_PTR)ExceptionRecord->ExceptionAddress >> 2,
  334. ContextRecord->StIPSR,
  335. ContextRecord->StIIP);
  336. return TRUE;
  337. } else {
  338. return FALSE;
  339. }
  340. }