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.

411 lines
9.9 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. bdtrap.c
  5. Abstract:
  6. This module contains code to implement the target side of the boot debugger.
  7. Author:
  8. David N. Cutler (davec) 30-Nov-96
  9. Revision History:
  10. --*/
  11. #include "bd.h"
  12. //
  13. // Define forward referenced function prototypes.
  14. //
  15. VOID
  16. BdRestoreKframe(
  17. IN OUT PKTRAP_FRAME TrapFrame,
  18. IN PCONTEXT ContextRecord
  19. );
  20. VOID
  21. BdSaveKframe(
  22. IN PKTRAP_FRAME TrapFrame,
  23. IN OUT PCONTEXT ContextRecord
  24. );
  25. LOGICAL
  26. BdTrap (
  27. IN PEXCEPTION_RECORD ExceptionRecord,
  28. IN PKEXCEPTION_FRAME ExceptionFrame,
  29. IN PKTRAP_FRAME TrapFrame
  30. )
  31. /*++
  32. Routine Description:
  33. This routine is called whenever a exception is dispatched and the boot
  34. debugger is active.
  35. Arguments:
  36. ExceptionRecord - Supplies a pointer to an exception record that
  37. describes the exception.
  38. ExceptionFrame - Supplies a pointer to an exception frame (NULL).
  39. TrapFrame - Supplies a pointer to a trap frame that describes the
  40. trap.
  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. LOGICAL Completion;
  47. PCONTEXT ContextRecord;
  48. ULONG OldEip;
  49. STRING Input;
  50. STRING Output;
  51. PKD_SYMBOLS_INFO SymbolInfo;
  52. LOGICAL UnloadSymbols;
  53. //
  54. // Set address of context record and set context flags.
  55. //
  56. ContextRecord = &BdPrcb.ProcessorState.ContextFrame;
  57. ContextRecord->ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
  58. //
  59. // Print, prompt, load symbols, and unload symbols are all special cases
  60. // of STATUS_BREAKPOINT.
  61. //
  62. if ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) &&
  63. (ExceptionRecord->ExceptionInformation[0] != BREAKPOINT_BREAK)) {
  64. //
  65. // Switch on the request type.
  66. //
  67. UnloadSymbols = FALSE;
  68. switch (ExceptionRecord->ExceptionInformation[0]) {
  69. //
  70. // Print:
  71. //
  72. // ExceptionInformation[1] is a PSTRING which describes the string
  73. // to print.
  74. //
  75. case BREAKPOINT_PRINT:
  76. Output.Buffer = (PCHAR)ExceptionRecord->ExceptionInformation[1];
  77. Output.Length = (USHORT)ExceptionRecord->ExceptionInformation[2];
  78. if (BdDebuggerNotPresent == FALSE) {
  79. if (BdPrintString(&Output)) {
  80. TrapFrame->Eax = (ULONG)(STATUS_BREAKPOINT);
  81. } else {
  82. TrapFrame->Eax = STATUS_SUCCESS;
  83. }
  84. } else {
  85. TrapFrame->Eax = (ULONG)STATUS_DEVICE_NOT_CONNECTED;
  86. }
  87. TrapFrame->Eip += 1;
  88. return TRUE;
  89. //
  90. // Prompt:
  91. //
  92. // ExceptionInformation[1] is a PSTRING which describes the prompt
  93. // string,
  94. //
  95. // ExceptionInformation[2] is a PSTRING that describes the return
  96. // string.
  97. //
  98. case BREAKPOINT_PROMPT:
  99. Output.Buffer = (PCHAR)ExceptionRecord->ExceptionInformation[1];
  100. Output.Length = (USHORT)ExceptionRecord->ExceptionInformation[2];
  101. Input.Buffer = (PCHAR)TrapFrame->Ebx;;
  102. Input.MaximumLength = (USHORT)TrapFrame->Edi;
  103. //
  104. // Prompt and keep prompting until no breakin seen.
  105. //
  106. do {
  107. } while (BdPromptString(&Output, &Input) != FALSE);
  108. TrapFrame->Eax = Input.Length;
  109. TrapFrame->Eip += 1;
  110. return TRUE;
  111. //
  112. // Unload symbols:
  113. //
  114. // ExceptionInformation[1] is file name of a module.
  115. // ExceptionInformaiton[2] is the base of the dll.
  116. //
  117. case BREAKPOINT_UNLOAD_SYMBOLS:
  118. UnloadSymbols = TRUE;
  119. //
  120. // Fall through to load symbols case.
  121. //
  122. case BREAKPOINT_LOAD_SYMBOLS:
  123. BdSaveKframe(TrapFrame, ContextRecord);
  124. OldEip = ContextRecord->Eip;
  125. SymbolInfo = (PKD_SYMBOLS_INFO)ExceptionRecord->ExceptionInformation[2];
  126. if (BdDebuggerNotPresent == FALSE) {
  127. BdReportLoadSymbolsStateChange((PSTRING)ExceptionRecord->ExceptionInformation[1],
  128. SymbolInfo,
  129. UnloadSymbols,
  130. ContextRecord);
  131. }
  132. //
  133. // If the kernel debugger did not update EIP, then increment
  134. // past the breakpoint instruction.
  135. //
  136. if (ContextRecord->Eip == OldEip) {
  137. ContextRecord->Eip += 1;
  138. }
  139. BdRestoreKframe(TrapFrame, ContextRecord);
  140. return TRUE;
  141. //
  142. // Unknown command
  143. //
  144. default:
  145. return FALSE;
  146. }
  147. } else {
  148. //
  149. // Report state change to kernel debugger on host.
  150. //
  151. BdSaveKframe(TrapFrame, ContextRecord);
  152. Completion =
  153. BdReportExceptionStateChange(ExceptionRecord,
  154. &BdPrcb.ProcessorState.ContextFrame);
  155. BdRestoreKframe(TrapFrame, ContextRecord);
  156. BdControlCPressed = FALSE;
  157. return TRUE;
  158. }
  159. }
  160. LOGICAL
  161. BdStub (
  162. IN PEXCEPTION_RECORD ExceptionRecord,
  163. IN PKEXCEPTION_FRAME ExceptionFrame,
  164. IN PKTRAP_FRAME TrapFrame
  165. )
  166. /*++
  167. Routine Description:
  168. This routine provides a kernel debugger stub routine to catch debug
  169. prints when the boot debugger is not active.
  170. Arguments:
  171. ExceptionRecord - Supplies a pointer to an exception record that
  172. describes the exception.
  173. ExceptionFrame - Supplies a pointer to an exception frame (NULL).
  174. TrapFrame - Supplies a pointer to a trap frame that describes the
  175. trap.
  176. Return Value:
  177. A value of TRUE is returned if the exception is handled. Otherwise a
  178. value of FALSE is returned.
  179. --*/
  180. {
  181. //
  182. // If the exception is a breakpoint and the function is a load symbols,
  183. // unload symbols, or a print, then return TRUE. Otherwise, return FALSE.
  184. //
  185. if ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) &&
  186. (ExceptionRecord->NumberParameters > 0) &&
  187. ((ExceptionRecord->ExceptionInformation[0] == BREAKPOINT_LOAD_SYMBOLS) ||
  188. (ExceptionRecord->ExceptionInformation[0] == BREAKPOINT_UNLOAD_SYMBOLS) ||
  189. (ExceptionRecord->ExceptionInformation[0] == BREAKPOINT_PRINT))) {
  190. TrapFrame->Eip += 1;
  191. return TRUE;
  192. } else {
  193. return FALSE;
  194. }
  195. }
  196. VOID
  197. BdRestoreKframe(
  198. IN OUT PKTRAP_FRAME TrapFrame,
  199. IN PCONTEXT ContextRecord
  200. )
  201. /*++
  202. Routine Description:
  203. This functions copie the processor state from a context record and
  204. the processor control block into the trap frame.
  205. Arguments:
  206. TrapFrame - Supplies a pointer to a trap frame.
  207. ContextRecord - Supplies a pointer to a context record.
  208. Return Value:
  209. None.
  210. --*/
  211. {
  212. //
  213. // Copy information from context record to trap frame.
  214. //
  215. // Copy control information.
  216. //
  217. TrapFrame->Ebp = ContextRecord->Ebp;
  218. TrapFrame->Eip = ContextRecord->Eip;
  219. TrapFrame->SegCs = ContextRecord->SegCs;
  220. TrapFrame->EFlags = ContextRecord->EFlags;
  221. //
  222. // Copy segment register contents.
  223. //
  224. TrapFrame->SegDs = ContextRecord->SegDs;
  225. TrapFrame->SegEs = ContextRecord->SegEs;
  226. TrapFrame->SegFs = ContextRecord->SegFs;
  227. TrapFrame->SegGs = ContextRecord->SegGs;
  228. //
  229. // Copy integer registers contents.
  230. //
  231. TrapFrame->Edi = ContextRecord->Edi;
  232. TrapFrame->Esi = ContextRecord->Esi;
  233. TrapFrame->Ebx = ContextRecord->Ebx;
  234. TrapFrame->Ecx = ContextRecord->Ecx;
  235. TrapFrame->Edx = ContextRecord->Edx;
  236. TrapFrame->Eax = ContextRecord->Eax;
  237. //
  238. // Restore processor state.
  239. //
  240. KiRestoreProcessorControlState(&BdPrcb.ProcessorState);
  241. return;
  242. }
  243. VOID
  244. BdSaveKframe(
  245. IN PKTRAP_FRAME TrapFrame,
  246. IN OUT PCONTEXT ContextRecord
  247. )
  248. /*++
  249. Routine Description:
  250. This functions copis the processor state from a trap frame and the
  251. processor control block into a context record.
  252. Arguments:
  253. TrapFrame - Supplies a pointer to a trap frame.
  254. ContextRecord - Supplies a pointer to a context record.
  255. Return Value:
  256. None.
  257. --*/
  258. {
  259. //
  260. // Copy information from trap frame to context record.
  261. //
  262. // Copy control information.
  263. //
  264. ContextRecord->Ebp = TrapFrame->Ebp;
  265. ContextRecord->Eip = TrapFrame->Eip;
  266. ContextRecord->SegCs = TrapFrame->SegCs & SEGMENT_MASK;
  267. ContextRecord->EFlags = TrapFrame->EFlags;
  268. ContextRecord->Esp = TrapFrame->TempEsp;
  269. ContextRecord->SegSs = TrapFrame->TempSegCs;
  270. //
  271. // Copy segment register contents.
  272. //
  273. ContextRecord->SegDs = TrapFrame->SegDs & SEGMENT_MASK;
  274. ContextRecord->SegEs = TrapFrame->SegEs & SEGMENT_MASK;
  275. ContextRecord->SegFs = TrapFrame->SegFs & SEGMENT_MASK;
  276. ContextRecord->SegGs = TrapFrame->SegGs & SEGMENT_MASK;
  277. //
  278. // Copy the integer register contents.
  279. //
  280. ContextRecord->Eax = TrapFrame->Eax;
  281. ContextRecord->Ebx = TrapFrame->Ebx;
  282. ContextRecord->Ecx = TrapFrame->Ecx;
  283. ContextRecord->Edx = TrapFrame->Edx;
  284. ContextRecord->Edi = TrapFrame->Edi;
  285. ContextRecord->Esi = TrapFrame->Esi;
  286. //
  287. // Copy debug register contents.
  288. //
  289. ContextRecord->Dr0 = TrapFrame->Dr0;
  290. ContextRecord->Dr1 = TrapFrame->Dr1;
  291. ContextRecord->Dr2 = TrapFrame->Dr2;
  292. ContextRecord->Dr3 = TrapFrame->Dr3;
  293. ContextRecord->Dr6 = TrapFrame->Dr6;
  294. ContextRecord->Dr7 = TrapFrame->Dr7;
  295. //
  296. // Save processor control state.
  297. //
  298. KiSaveProcessorControlState(&BdPrcb.ProcessorState);
  299. return;
  300. }