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.

614 lines
16 KiB

  1. /*++
  2. Copyright (c) 2000-2001 Microsoft Corporation
  3. Module Name:
  4. print.c
  5. Abstract:
  6. This module contains the common code to filter and print debug
  7. messages.
  8. Author:
  9. David N. Cutler (davec) 12-Jan-2000
  10. Revision History:
  11. --*/
  12. #include "kdp.h"
  13. #pragma hdrstop
  14. #include <malloc.h>
  15. #ifdef ALLOC_PRAGMA
  16. #pragma alloc_text(PAGEKD, KdpPrint)
  17. #pragma alloc_text(PAGEKD, KdpPrompt)
  18. #pragma alloc_text(PAGEKD, KdpSymbol)
  19. #pragma alloc_text(PAGEKD, KdpCommandString)
  20. #endif // ALLOC_PRAGMA
  21. extern PWD_HANDLER ExpWdHandler;
  22. extern PVOID ExpWdHandlerContext;
  23. #if 0
  24. ULONG gLdrHits;
  25. #endif
  26. NTSTATUS
  27. KdpPrint(
  28. IN ULONG ComponentId,
  29. IN ULONG Level,
  30. IN PCHAR Message,
  31. IN USHORT Length,
  32. IN KPROCESSOR_MODE PreviousMode,
  33. IN PKTRAP_FRAME TrapFrame,
  34. IN PKEXCEPTION_FRAME ExceptionFrame,
  35. OUT PBOOLEAN Completion
  36. )
  37. /*++
  38. Routine Description:
  39. This function filters debug print requests, probes and saves user mode
  40. message buffers on the stack, logs the print message, and prints the
  41. message on the debug terminal if apprpriate.
  42. Arguments:
  43. ComponentId - Supplies the component id of the component that issued
  44. the debug print.
  45. Level - Supplies the debug filer level number or mask.
  46. Message - Supplies a pointer to the output message.
  47. Length - Supplies the length of the output message.
  48. PreviousMode - Supplies the previous processor mode.
  49. TrapFrame - Supplies a pointer to a trap frame.
  50. ExceptionFrame - Supplies a pointer to a exception.
  51. Completion - Supplies a pointer to the variable that receives the
  52. debug print completion status.
  53. Return Value:
  54. STATUS_SUCCESS - Is returned if the debug print is filtered or is
  55. successfully printed.
  56. STATUS_BREAKPOINT - Is returned if ...
  57. STATUS_DEVICE_NOT_CONNECTED - Is returned if the kernel debugger is
  58. not enabled and the debug print message was not filtered.
  59. STATUS_ACCESS_VIOLATION - Is returned if an access violation occurs
  60. while attempting to copy a user mode buffer to the kernel stack.
  61. --*/
  62. {
  63. PCHAR Buffer;
  64. BOOLEAN Enable;
  65. ULONG Mask;
  66. STRING Output;
  67. NTSTATUS Status;
  68. //
  69. // If the the component id if out of range or output is enabled for the
  70. // specified filter level, then attempt to print the output. Otherwise,
  71. // immediately return success.
  72. //
  73. *Completion = FALSE;
  74. if (Level > 31) {
  75. Mask = Level;
  76. } else {
  77. Mask = 1 << Level;
  78. }
  79. if (((Mask & Kd_WIN2000_Mask) == 0) &&
  80. (ComponentId < KdComponentTableSize) &&
  81. ((Mask & *KdComponentTable[ComponentId]) == 0)) {
  82. Status = STATUS_SUCCESS;
  83. } else {
  84. //
  85. // Limit the message length to 512 bytes.
  86. //
  87. if (Length > 512) {
  88. Length = 512;
  89. }
  90. //
  91. // If the previous mode is user, then probe and capture the
  92. // message buffer on the stack.
  93. //
  94. if (PreviousMode != KernelMode) {
  95. try {
  96. ProbeForRead(Message, Length, sizeof(UCHAR));
  97. Buffer = alloca(512);
  98. KdpQuickMoveMemory(Buffer, Message, Length);
  99. Message = Buffer;
  100. } except (EXCEPTION_EXECUTE_HANDLER) {
  101. return STATUS_ACCESS_VIOLATION;
  102. }
  103. }
  104. //
  105. // Log debug output in circular buffer and print output
  106. // if debugger is enabled.
  107. //
  108. Output.Buffer = Message;
  109. Output.Length = Length;
  110. KdLogDbgPrint(&Output);
  111. if (KdDebuggerNotPresent == FALSE) {
  112. Enable = KdEnterDebugger(TrapFrame, ExceptionFrame);
  113. if (KdpPrintString(&Output)) {
  114. Status = STATUS_BREAKPOINT;
  115. } else {
  116. Status = STATUS_SUCCESS;
  117. }
  118. KdExitDebugger(Enable);
  119. } else {
  120. Status = STATUS_DEVICE_NOT_CONNECTED;
  121. }
  122. }
  123. *Completion = TRUE;
  124. return Status;
  125. }
  126. USHORT
  127. KdpPrompt(
  128. IN PCHAR Message,
  129. IN USHORT MessageLength,
  130. IN OUT PCHAR Reply,
  131. IN USHORT ReplyLength,
  132. IN KPROCESSOR_MODE PreviousMode,
  133. IN PKTRAP_FRAME TrapFrame,
  134. IN PKEXCEPTION_FRAME ExceptionFrame
  135. )
  136. /*++
  137. Routine Description:
  138. This function filters debug print requests, probes and saves user mode
  139. message buffers on the stack, logs the print message, and prints the
  140. message on the debug terminal if apprpriate.
  141. Arguments:
  142. Message - Supplies a pointer to the output message.
  143. MessageLength - Supplies the length of the output message.
  144. Reply - Supplies a pointer to the input buffer.
  145. ReplyLength - Supplies the length of the output message.
  146. PreviousMode - Supplies the previous processor mode.
  147. TrapFrame - Supplies a pointer to a trap frame.
  148. ExceptionFrame - Supplies a pointer to a exception.
  149. Return Value:
  150. The length of the input message is returned as the function value.
  151. --*/
  152. {
  153. PCHAR Buffer;
  154. BOOLEAN Enable;
  155. STRING Input;
  156. STRING Output;
  157. //
  158. // Limit the output and input message length to 512 bytes.
  159. //
  160. if (MessageLength > 512) {
  161. MessageLength = 512;
  162. }
  163. if (ReplyLength > 512) {
  164. ReplyLength = 512;
  165. }
  166. //
  167. // If the previous mode is user, then probe and capture the
  168. // message buffer on the stack.
  169. //
  170. if (PreviousMode != KernelMode) {
  171. try {
  172. ProbeForRead(Message, MessageLength, sizeof(UCHAR));
  173. Buffer = alloca(512);
  174. KdpQuickMoveMemory(Buffer, Message, MessageLength);
  175. Message = Buffer;
  176. ProbeForWrite(Reply, ReplyLength, sizeof(UCHAR));
  177. Buffer = alloca(512);
  178. } except (EXCEPTION_EXECUTE_HANDLER) {
  179. return 0;
  180. }
  181. } else {
  182. Buffer = Reply;
  183. }
  184. Input.Buffer = Buffer;
  185. Input.Length = 0;
  186. Input.MaximumLength = ReplyLength;
  187. Output.Buffer = Message;
  188. Output.Length = MessageLength;
  189. //
  190. // Log debug output in circular buffer and print the prompt message.
  191. //
  192. KdLogDbgPrint(&Output);
  193. Enable = KdEnterDebugger(TrapFrame, ExceptionFrame);
  194. do {
  195. } while (KdpPromptString(&Output, &Input) == TRUE);
  196. KdExitDebugger(Enable);
  197. //
  198. // If the previous mode was user, then copy the prompt input to the
  199. // reply buffer.
  200. //
  201. if (PreviousMode == UserMode) {
  202. try {
  203. KdpQuickMoveMemory(Reply, Input.Buffer, Input.Length);
  204. } except (EXCEPTION_EXECUTE_HANDLER) {
  205. }
  206. }
  207. return Input.Length;
  208. }
  209. BOOLEAN
  210. KdpReport(
  211. IN PKTRAP_FRAME TrapFrame,
  212. IN PKEXCEPTION_FRAME ExceptionFrame,
  213. IN PEXCEPTION_RECORD ExceptionRecord,
  214. IN PCONTEXT ContextRecord,
  215. IN KPROCESSOR_MODE PreviousMode,
  216. IN BOOLEAN SecondChance
  217. )
  218. /*++
  219. Routine Description:
  220. This function reports an exception to the host kernel debugger.
  221. Arguments:
  222. TrapFrame - Supplies a pointer to a trap frame that describes the
  223. trap.
  224. ExceptionFrame - Supplies a pointer to a exception frame that describes
  225. the exception.
  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. SecondChance - Supplies a boolean value that determines whether this is
  230. the second chance (TRUE) that the exception has been raised.
  231. Return Value:
  232. The disposition of whether the exception was handled (TRUE) or not is
  233. returned as the function value.
  234. --*/
  235. {
  236. BOOLEAN Completion;
  237. BOOLEAN Enable;
  238. PKPRCB Prcb;
  239. UNREFERENCED_PARAMETER (PreviousMode);
  240. //
  241. // If the exception code is a breakpoint or single step, or stop
  242. // on exeception is set, or this is the second change to handle
  243. // the exception, then attempt to enter the kernel debugger.
  244. //
  245. if ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) ||
  246. #if defined(_WIN64)
  247. (ExceptionRecord->ExceptionCode == STATUS_WX86_BREAKPOINT) ||
  248. #endif
  249. (ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP) ||
  250. ((NtGlobalFlag & FLG_STOP_ON_EXCEPTION) != 0) ||
  251. (SecondChance != FALSE)) {
  252. //
  253. // If this is the first chance to handle the exception and the
  254. // exception code is either a port disconnected or success code,
  255. // then do not enter the kernel debugger.
  256. //
  257. if ((SecondChance == FALSE) &&
  258. #if defined(_WIN64)
  259. (ExceptionRecord->ExceptionCode != STATUS_WX86_BREAKPOINT) &&
  260. #endif
  261. ((ExceptionRecord->ExceptionCode == STATUS_PORT_DISCONNECTED) ||
  262. (NT_SUCCESS(ExceptionRecord->ExceptionCode)))) {
  263. //
  264. // This exception should not be reported to the kernel debugger.
  265. //
  266. return FALSE;
  267. }
  268. //
  269. // Debugging help:
  270. //
  271. // For user mode breakpoints going to the kernel debugger,
  272. // try to get the user mode module list and image headers
  273. // paged in before we call the debugger. Walk the list twice
  274. // in case paging in some modules pages out some
  275. // previously paged in data.
  276. //
  277. #if 0
  278. if (PreviousMode == UserMode)
  279. {
  280. PPEB Peb = PsGetCurrentProcess()->Peb;
  281. PPEB_LDR_DATA Ldr;
  282. PLIST_ENTRY LdrHead, LdrNext;
  283. PLDR_DATA_TABLE_ENTRY LdrEntry;
  284. UCHAR DataHeader;
  285. ULONG i,j;
  286. try {
  287. Ldr = Peb->Ldr;
  288. LdrHead = &Ldr->InLoadOrderModuleList;
  289. ProbeForRead (LdrHead, sizeof (LIST_ENTRY), sizeof (UCHAR));
  290. for (j=0; j<2; j++) {
  291. for (LdrNext = LdrHead->Flink, i = 0;
  292. LdrNext != LdrHead && i < 500;
  293. LdrNext = LdrNext->Flink, i++) {
  294. // BUGBUG
  295. gLdrHits++;
  296. LdrEntry = CONTAINING_RECORD (LdrNext, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
  297. ProbeForRead (LdrEntry, sizeof (LDR_DATA_TABLE_ENTRY), sizeof (UCHAR));
  298. DataHeader = ProbeAndReadUchar((PUCHAR)LdrEntry->DllBase);
  299. }
  300. }
  301. } except (EXCEPTION_EXECUTE_HANDLER) {
  302. }
  303. }
  304. #endif
  305. //
  306. // Report state change to the host kernel debugger.
  307. //
  308. Enable = KdEnterDebugger(TrapFrame, ExceptionFrame);
  309. Prcb = KeGetCurrentPrcb();
  310. KiSaveProcessorControlState(&Prcb->ProcessorState);
  311. KdpQuickMoveMemory((PCHAR)&Prcb->ProcessorState.ContextFrame,
  312. (PCHAR)ContextRecord,
  313. sizeof(CONTEXT));
  314. if (ExpWdHandler != NULL) {
  315. ExpWdHandler( WdActionStopTimer, ExpWdHandlerContext, NULL, TRUE );
  316. }
  317. Completion =
  318. KdpReportExceptionStateChange(ExceptionRecord,
  319. &Prcb->ProcessorState.ContextFrame,
  320. SecondChance);
  321. KdpQuickMoveMemory((PCHAR)ContextRecord,
  322. (PCHAR)&Prcb->ProcessorState.ContextFrame,
  323. sizeof(CONTEXT));
  324. KiRestoreProcessorControlState(&Prcb->ProcessorState);
  325. if (ExpWdHandler != NULL) {
  326. ExpWdHandler( WdActionStartTimer, ExpWdHandlerContext, NULL, TRUE );
  327. }
  328. KdExitDebugger(Enable);
  329. KdpControlCPressed = FALSE;
  330. return Completion;
  331. } else {
  332. //
  333. // This exception should not be reported to the kernel debugger.
  334. //
  335. return FALSE;
  336. }
  337. }
  338. VOID
  339. KdpSymbol(
  340. IN PSTRING String,
  341. IN PKD_SYMBOLS_INFO Symbol,
  342. IN BOOLEAN Unload,
  343. IN KPROCESSOR_MODE PreviousMode,
  344. IN PCONTEXT ContextRecord,
  345. IN PKTRAP_FRAME TrapFrame,
  346. IN PKEXCEPTION_FRAME ExceptionFrame
  347. )
  348. /*++
  349. Routine Description:
  350. This function loads or unloads debug symbols.
  351. Arguments:
  352. String - Supplies a pointer to a string descriptor.
  353. Symbol - Supplies a pointer to the symbol information.
  354. Unload - Supplies a boolean value that determines whether the symbols
  355. are being unloaded (TRUE) or loaded (FALSE).
  356. PreviousMode - Supplies the previous processor mode.
  357. ContextRecord - Supplies a pointer to a context record.
  358. TrapFrame - Supplies a pointer to a trap frame.
  359. ExceptionFrame - Supplies a pointer to a exception.
  360. Return Value:
  361. None.
  362. --*/
  363. {
  364. BOOLEAN Enable;
  365. PKPRCB Prcb;
  366. //
  367. // If the previous mode is kernel and the kernel debugger is present,
  368. // then load or unload symbols.
  369. //
  370. if ((PreviousMode == KernelMode) &&
  371. (KdDebuggerNotPresent == FALSE)) {
  372. //
  373. // Save and restore the processor context in case the
  374. // kernel debugger has been configured to stop on dll
  375. // loads.
  376. //
  377. Enable = KdEnterDebugger(TrapFrame, ExceptionFrame);
  378. Prcb = KeGetCurrentPrcb();
  379. KiSaveProcessorControlState(&Prcb->ProcessorState);
  380. KdpQuickMoveMemory((PCHAR)&Prcb->ProcessorState.ContextFrame,
  381. (PCHAR)ContextRecord,
  382. sizeof(CONTEXT));
  383. KdpReportLoadSymbolsStateChange(String,
  384. Symbol,
  385. Unload,
  386. &Prcb->ProcessorState.ContextFrame);
  387. KdpQuickMoveMemory((PCHAR)ContextRecord,
  388. (PCHAR)&Prcb->ProcessorState.ContextFrame,
  389. sizeof(CONTEXT));
  390. KiRestoreProcessorControlState(&Prcb->ProcessorState);
  391. KdExitDebugger(Enable);
  392. }
  393. return;
  394. }
  395. VOID
  396. KdpCommandString(
  397. IN PSTRING Name,
  398. IN PSTRING Command,
  399. IN KPROCESSOR_MODE PreviousMode,
  400. IN PCONTEXT ContextRecord,
  401. IN PKTRAP_FRAME TrapFrame,
  402. IN PKEXCEPTION_FRAME ExceptionFrame
  403. )
  404. /*++
  405. Routine Description:
  406. This function reports an exception to the host kernel debugger.
  407. Arguments:
  408. Name - Identification of the originator of the command.
  409. Command - Command string.
  410. PreviousMode - Supplies the previous processor mode.
  411. ContextRecord - Supplies a pointer to a context record.
  412. TrapFrame - Supplies a pointer to a trap frame that describes the
  413. trap.
  414. ExceptionFrame - Supplies a pointer to a exception frame that describes
  415. the exception.
  416. Return Value:
  417. None.
  418. --*/
  419. {
  420. //
  421. // Report state change to the host kernel debugger.
  422. //
  423. if ((PreviousMode == KernelMode) &&
  424. (KdDebuggerNotPresent == FALSE)) {
  425. BOOLEAN Enable;
  426. PKPRCB Prcb;
  427. Enable = KdEnterDebugger(TrapFrame, ExceptionFrame);
  428. Prcb = KeGetCurrentPrcb();
  429. KiSaveProcessorControlState(&Prcb->ProcessorState);
  430. KdpQuickMoveMemory((PCHAR)&Prcb->ProcessorState.ContextFrame,
  431. (PCHAR)ContextRecord,
  432. sizeof(CONTEXT));
  433. KdpReportCommandStringStateChange(Name, Command,
  434. &Prcb->ProcessorState.ContextFrame);
  435. KdpQuickMoveMemory((PCHAR)ContextRecord,
  436. (PCHAR)&Prcb->ProcessorState.ContextFrame,
  437. sizeof(CONTEXT));
  438. KiRestoreProcessorControlState(&Prcb->ProcessorState);
  439. KdExitDebugger(Enable);
  440. }
  441. }