/private/ntos/kd64/alpha/kdtrap.c

https://github.com/pustladi/Windows-2000 · C · 466 lines · 179 code · 84 blank · 203 comment · 37 complexity · 79256845a4ea03cb4001f94b432865d8 MD5 · raw file

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Copyright (c) 1992-1993 Digital Equipment 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. Joe Notarangelo 24-June-1992 (ALPHA version)
  12. Revision History:
  13. --*/
  14. #include "kdp.h"
  15. BOOLEAN
  16. KdpTrap (
  17. IN PKTRAP_FRAME TrapFrame,
  18. IN PKEXCEPTION_FRAME ExceptionFrame,
  19. IN PEXCEPTION_RECORD ExceptionRecord,
  20. IN PCONTEXT ContextRecord,
  21. IN KPROCESSOR_MODE PreviousMode,
  22. IN BOOLEAN SecondChance
  23. )
  24. /*++
  25. Routine Description:
  26. This routine is called whenever a exception is dispatched and the kernel
  27. debugger is active.
  28. Arguments:
  29. TrapFrame - Supplies a pointer to a trap frame that describes the
  30. trap.
  31. ExceptionFrame - Supplies a pointer to a exception frame that describes
  32. the trap.
  33. ExceptionRecord - Supplies a pointer to an exception record that
  34. describes the exception.
  35. ContextRecord - Supplies the context at the time of the exception.
  36. PreviousMode - Supplies the previous processor mode.
  37. SecondChance - Supplies a boolean value that determines whether this is
  38. the second chance (TRUE) that the exception has been raised.
  39. Return Value:
  40. A value of TRUE is returned if the exception is handled. Otherwise a
  41. value of FALSE is returned.
  42. --*/
  43. {
  44. BOOLEAN Completion;
  45. BOOLEAN Enable;
  46. BOOLEAN UnloadSymbols = FALSE;
  47. STRING Input;
  48. ULONGLONG OldFir;
  49. STRING Output;
  50. PKPRCB Prcb;
  51. //
  52. // Enter debugger and synchronize processor execution.
  53. //
  54. //
  55. // If this is a breakpoint instruction, then check to determine if is
  56. // an internal command.
  57. //
  58. if ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) &&
  59. (ExceptionRecord->ExceptionInformation[0] >= DEBUG_PRINT_BREAKPOINT)){
  60. //
  61. // Switch on the breakpoint code.
  62. //
  63. switch (ExceptionRecord->ExceptionInformation[0]) {
  64. //
  65. // Print a debug string.
  66. //
  67. // Arguments:
  68. //
  69. // a0 - Supplies a pointer to an output string buffer.
  70. // a1 - Supplies the length of the output string buffer.
  71. //
  72. case DEBUG_PRINT_BREAKPOINT:
  73. ContextRecord->Fir += 4;
  74. Output.Buffer = (PCHAR)ContextRecord->IntA0;
  75. Output.Length = (USHORT)ContextRecord->IntA1;
  76. KdLogDbgPrint(&Output);
  77. if (KdDebuggerNotPresent == FALSE) {
  78. Enable = KdEnterDebugger(TrapFrame, ExceptionFrame);
  79. if (KdpPrintString(&Output)) {
  80. ContextRecord->IntV0 = (ULONG)STATUS_BREAKPOINT;
  81. } else {
  82. ContextRecord->IntV0 = (ULONG)STATUS_SUCCESS;
  83. }
  84. KdExitDebugger(Enable);
  85. } else {
  86. ContextRecord->IntV0 = (ULONG)STATUS_DEVICE_NOT_CONNECTED;
  87. }
  88. return TRUE;
  89. //
  90. // Stop in the debugger
  91. //
  92. // As this is not a normal breakpoint we must increment the
  93. // context past the breakpoint instruction
  94. //
  95. case BREAKIN_BREAKPOINT:
  96. ContextRecord->Fir += 4;
  97. break;
  98. //
  99. // Print a debug prompt string, then input a string.
  100. //
  101. // a0 - Supplies a pointer to an output string buffer.
  102. // a1 - Supplies the length of the output string buffer..
  103. // a2 - supplies a pointer to an input string buffer.
  104. // a3 - Supplies the length of the input string bufffer.
  105. //
  106. case DEBUG_PROMPT_BREAKPOINT:
  107. ContextRecord->Fir += 4;
  108. Output.Buffer = (PCHAR)ContextRecord->IntA0;
  109. Output.Length = (USHORT)ContextRecord->IntA1;
  110. Input.Buffer = (PCHAR)ContextRecord->IntA2;
  111. Input.MaximumLength = (USHORT)ContextRecord->IntA3;
  112. KdLogDbgPrint(&Output);
  113. Enable = KdEnterDebugger(TrapFrame, ExceptionFrame);
  114. KdpPromptString(&Output, &Input);
  115. ContextRecord->IntV0 = Input.Length;
  116. KdExitDebugger(Enable);
  117. return TRUE;
  118. //
  119. // Load the symbolic information for an image.
  120. //
  121. // Arguments:
  122. //
  123. // a0 - Supplies a pointer to an output string descriptor.
  124. // a1 - Supplies a the base address of the image.
  125. // a2 - Supplies the current process id.
  126. //
  127. case DEBUG_UNLOAD_SYMBOLS_BREAKPOINT:
  128. UnloadSymbols = TRUE;
  129. //
  130. // Fall through
  131. //
  132. case DEBUG_LOAD_SYMBOLS_BREAKPOINT:
  133. Enable = KdEnterDebugger(TrapFrame, ExceptionFrame);
  134. Prcb = KeGetCurrentPrcb();
  135. OldFir = ContextRecord->Fir;
  136. RtlCopyMemory(&Prcb->ProcessorState.ContextFrame,
  137. ContextRecord,
  138. sizeof(CONTEXT));
  139. if (KdDebuggerNotPresent == FALSE) {
  140. KdpReportLoadSymbolsStateChange((PSTRING)ContextRecord->IntA0,
  141. (PKD_SYMBOLS_INFO) ContextRecord->IntA1,
  142. UnloadSymbols,
  143. &Prcb->ProcessorState.ContextFrame);
  144. }
  145. RtlCopyMemory(ContextRecord,
  146. &Prcb->ProcessorState.ContextFrame,
  147. sizeof(CONTEXT));
  148. KdExitDebugger(Enable);
  149. //
  150. // If the kernel debugger did not update the FIR, then increment
  151. // past the breakpoint instruction.
  152. //
  153. if (ContextRecord->Fir == OldFir) {
  154. ContextRecord->Fir += 4;
  155. }
  156. return TRUE;
  157. //
  158. // Unknown internal command.
  159. //
  160. default:
  161. break;
  162. }
  163. }
  164. //
  165. // Report state change to kernel debugger on host machine.
  166. //
  167. Enable = KdEnterDebugger(TrapFrame, ExceptionFrame);
  168. Prcb = KeGetCurrentPrcb();
  169. RtlCopyMemory(&Prcb->ProcessorState.ContextFrame,
  170. ContextRecord,
  171. sizeof (CONTEXT));
  172. Completion = KdpReportExceptionStateChange(ExceptionRecord,
  173. &Prcb->ProcessorState.ContextFrame,
  174. SecondChance);
  175. RtlCopyMemory(ContextRecord,
  176. &Prcb->ProcessorState.ContextFrame,
  177. sizeof(CONTEXT));
  178. KdExitDebugger(Enable);
  179. KdpControlCPressed = FALSE;
  180. //
  181. // Always return TRUE if this is the first chance to handle the
  182. // exception. Otherwise, return the completion status of the
  183. // state change reporting.
  184. //
  185. if( SecondChance ){
  186. return Completion;
  187. } else {
  188. return TRUE;
  189. }
  190. }
  191. BOOLEAN
  192. KdIsThisAKdTrap (
  193. IN PEXCEPTION_RECORD ExceptionRecord,
  194. IN PCONTEXT ContextRecord,
  195. IN KPROCESSOR_MODE PreviousMode
  196. )
  197. /*++
  198. Routine Description:
  199. This routine is called whenever a user-mode exception occurs and
  200. it might be a kernel debugger exception (Like DbgPrint/DbgPrompt ).
  201. Arguments:
  202. ExceptionRecord - Supplies a pointer to an exception record that
  203. describes the exception.
  204. ContextRecord - Supplies the context at the time of the exception.
  205. PreviousMode - Supplies the previous processor mode.
  206. Return Value:
  207. A value of TRUE is returned if this is for the kernel debugger.
  208. Otherwise, a value of FALSE is returned.
  209. --*/
  210. {
  211. //
  212. // Isolate the breakpoint code from the breakpoint instruction which
  213. // is stored by the exception dispatch code in the information field
  214. // of the exception record.
  215. //
  216. //
  217. // Switch on the breakpoint code.
  218. //
  219. switch (ExceptionRecord->ExceptionInformation[0]) {
  220. //
  221. // Kernel breakpoint code.
  222. //
  223. case KERNEL_BREAKPOINT:
  224. case BREAKIN_BREAKPOINT:
  225. #if DEVL
  226. return TRUE;
  227. #else
  228. if (PreviousMode == KernelMode) {
  229. return TRUE;
  230. } else {
  231. return FALSE;
  232. }
  233. #endif
  234. //
  235. // Debug print code.
  236. //
  237. case DEBUG_PRINT_BREAKPOINT:
  238. return TRUE;
  239. //
  240. // Debug prompt code.
  241. //
  242. case DEBUG_PROMPT_BREAKPOINT:
  243. return TRUE;
  244. //
  245. // Debug stop code.
  246. //
  247. case DEBUG_STOP_BREAKPOINT:
  248. #if DEVL
  249. return TRUE;
  250. #else
  251. if (PreviousMode == KernelMode) {
  252. return TRUE;
  253. } else {
  254. return FALSE;
  255. }
  256. #endif
  257. //
  258. // Debug load symbols code.
  259. //
  260. case DEBUG_LOAD_SYMBOLS_BREAKPOINT:
  261. if (PreviousMode == KernelMode) {
  262. return TRUE;
  263. } else {
  264. return FALSE;
  265. }
  266. //
  267. // Debug unload symbols code.
  268. //
  269. case DEBUG_UNLOAD_SYMBOLS_BREAKPOINT:
  270. if (PreviousMode == KernelMode) {
  271. return TRUE;
  272. } else {
  273. return FALSE;
  274. }
  275. //
  276. // All other codes.
  277. //
  278. default:
  279. return FALSE;
  280. }
  281. }
  282. BOOLEAN
  283. KdpStub (
  284. IN PKTRAP_FRAME TrapFrame,
  285. IN PKEXCEPTION_FRAME ExceptionFrame,
  286. IN PEXCEPTION_RECORD ExceptionRecord,
  287. IN PCONTEXT ContextRecord,
  288. IN KPROCESSOR_MODE PreviousMode,
  289. IN BOOLEAN SecondChance
  290. )
  291. /*++
  292. Routine Description:
  293. This routine provides a kernel debugger stub routine that catchs debug
  294. prints in checked systems when the kernel debugger is not active.
  295. Arguments:
  296. TrapFrame - Supplies a pointer to a trap frame that describes the
  297. trap.
  298. ExceptionFrame - Supplies a pointer to a exception frame that describes
  299. the trap.
  300. ExceptionRecord - Supplies a pointer to an exception record that
  301. describes the exception.
  302. ContextRecord - Supplies the context at the time of the exception.
  303. PreviousMode - Supplies the previous processor mode.
  304. SecondChance - Supplies a boolean value that determines whether this is
  305. the second chance (TRUE) that the exception has been raised.
  306. Return Value:
  307. A value of TRUE is returned if the exception is handled. Otherwise a
  308. value of FALSE is returned.
  309. --*/
  310. {
  311. ULONG_PTR BreakpointCode;
  312. //
  313. // Isolate the breakpoint code from the breakpoint instruction which
  314. // is stored by the exception dispatch code in the information field
  315. // of the exception record.
  316. //
  317. BreakpointCode = ExceptionRecord->ExceptionInformation[0];
  318. //
  319. // If the breakpoint is a debug print, debug load symbols, or debug
  320. // unload symbols, then return TRUE. Otherwise, return FALSE;
  321. //
  322. if ((BreakpointCode == DEBUG_PRINT_BREAKPOINT) ||
  323. (BreakpointCode == DEBUG_LOAD_SYMBOLS_BREAKPOINT) ||
  324. (BreakpointCode == DEBUG_UNLOAD_SYMBOLS_BREAKPOINT) ||
  325. (BreakpointCode == KERNEL_BREAKPOINT)) {
  326. ContextRecord->Fir += 4;
  327. return TRUE;
  328. } else {
  329. if ( (BreakpointCode == DEBUG_STOP_BREAKPOINT) &&
  330. (PreviousMode == KernelMode) ){
  331. ContextRecord->Fir += 4;
  332. return TRUE;
  333. } else {
  334. return FALSE;
  335. }
  336. }
  337. }