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.

491 lines
14 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. message.c
  5. Abstract:
  6. This module implements the debugger state change message functions.
  7. Author:
  8. Mark Lucovsky (markl) 31-Aug-1990
  9. Revision History:
  10. --*/
  11. #include "bd.h"
  12. #if ACCASM && !defined(_MSC_VER)
  13. long asm(const char *,...);
  14. #pragma intrinsic(asm)
  15. #endif
  16. KCONTINUE_STATUS
  17. BdSendWaitContinue (
  18. IN ULONG OutPacketType,
  19. IN PSTRING OutMessageHeader,
  20. IN PSTRING OutMessageData OPTIONAL,
  21. IN OUT PCONTEXT ContextRecord
  22. )
  23. /*++
  24. Routine Description:
  25. This function sends a packet and waits for a continue message. BreakIns
  26. received while waiting will always cause a resend of the packet originally
  27. sent out. While waiting state manipulate messages will be serviced.
  28. A resend always resends the original event sent to the debugger, not the
  29. last response to some debugger command.
  30. Arguments:
  31. OutPacketType - Supplies the type of packet to send.
  32. OutMessageHeader - Supplies a pointer to a string descriptor that describes
  33. the message information.
  34. OutMessageData - Supplies a pointer to a string descriptor that describes
  35. the optional message data.
  36. ContextRecord - Exception context
  37. Return Value:
  38. A value of TRUE is returned if the continue message indicates
  39. success, Otherwise, a value of FALSE is returned.
  40. --*/
  41. {
  42. ULONG Length;
  43. STRING MessageData;
  44. STRING MessageHeader;
  45. DBGKD_MANIPULATE_STATE64 ManipulateState;
  46. ULONG ReturnCode;
  47. NTSTATUS Status;
  48. KCONTINUE_STATUS ContinueStatus;
  49. //
  50. // Loop servicing state manipulation message until a continue message
  51. // is received.
  52. //
  53. MessageHeader.MaximumLength = sizeof(DBGKD_MANIPULATE_STATE64);
  54. MessageHeader.Buffer = (PCHAR)&ManipulateState;
  55. MessageData.MaximumLength = BD_MESSAGE_BUFFER_SIZE;
  56. MessageData.Buffer = (PCHAR)(&BdMessageBuffer[0]);
  57. //
  58. // Send event notification packet to debugger on host. Come back here
  59. // any time we see a breakin sequence.
  60. //
  61. ResendPacket:
  62. BdSendPacket(OutPacketType,
  63. OutMessageHeader,
  64. OutMessageData);
  65. //
  66. // After sending packet, if there is no response from debugger and the
  67. // packet is for reporting symbol (un)load, the debugger will be declared
  68. // to be not present. Note If the packet is for reporting exception, the
  69. // BdSendPacket will never stop.
  70. //
  71. if (BdDebuggerNotPresent != FALSE) {
  72. return ContinueSuccess;
  73. }
  74. while (TRUE) {
  75. //
  76. // Wait for State Manipulate Packet without timeout.
  77. //
  78. do {
  79. ReturnCode = BdReceivePacket(PACKET_TYPE_KD_STATE_MANIPULATE,
  80. &MessageHeader,
  81. &MessageData,
  82. &Length);
  83. if (ReturnCode == (USHORT)BD_PACKET_RESEND) {
  84. goto ResendPacket;
  85. }
  86. } while (ReturnCode == BD_PACKET_TIMEOUT);
  87. //
  88. // Switch on the return message API number.
  89. //
  90. // BlPrint("BdSendWait: api number %d\n", ManipulateState.ApiNumber);
  91. switch (ManipulateState.ApiNumber) {
  92. case DbgKdReadVirtualMemoryApi:
  93. BdReadVirtualMemory(&ManipulateState, &MessageData, ContextRecord);
  94. break;
  95. case DbgKdWriteVirtualMemoryApi:
  96. BdWriteVirtualMemory(&ManipulateState, &MessageData, ContextRecord);
  97. break;
  98. case DbgKdReadPhysicalMemoryApi:
  99. BdReadPhysicalMemory(&ManipulateState, &MessageData, ContextRecord);
  100. break;
  101. case DbgKdWritePhysicalMemoryApi:
  102. BdWritePhysicalMemory(&ManipulateState, &MessageData, ContextRecord);
  103. break;
  104. case DbgKdGetContextApi:
  105. BdGetContext(&ManipulateState, &MessageData, ContextRecord);
  106. break;
  107. case DbgKdSetContextApi:
  108. BdSetContext(&ManipulateState, &MessageData, ContextRecord);
  109. break;
  110. case DbgKdWriteBreakPointApi:
  111. BdWriteBreakpoint(&ManipulateState, &MessageData, ContextRecord);
  112. break;
  113. case DbgKdRestoreBreakPointApi:
  114. BdRestoreBreakpoint(&ManipulateState, &MessageData, ContextRecord);
  115. break;
  116. case DbgKdReadControlSpaceApi:
  117. BdReadControlSpace(&ManipulateState, &MessageData, ContextRecord);
  118. break;
  119. case DbgKdWriteControlSpaceApi:
  120. BdWriteControlSpace(&ManipulateState, &MessageData, ContextRecord);
  121. break;
  122. case DbgKdReadIoSpaceApi:
  123. BdReadIoSpace(&ManipulateState, &MessageData, ContextRecord);
  124. break;
  125. case DbgKdWriteIoSpaceApi:
  126. BdWriteIoSpace(&ManipulateState, &MessageData, ContextRecord);
  127. break;
  128. #if defined(_ALPHA_) || defined(_AXP64_)
  129. case DbgKdReadIoSpaceExtendedApi:
  130. BdReadIoSpaceExtended(&ManipulateState, &MessageData, ContextRecord);
  131. break;
  132. case DbgKdWriteIoSpaceExtendedApi:
  133. BdWriteIoSpaceExtended(&ManipulateState, &MessageData, ContextRecord);
  134. break;
  135. #endif
  136. case DbgKdContinueApi:
  137. if (NT_SUCCESS(ManipulateState.u.Continue.ContinueStatus) != FALSE) {
  138. return ContinueSuccess;
  139. } else {
  140. return ContinueError;
  141. }
  142. break;
  143. case DbgKdContinueApi2:
  144. if (NT_SUCCESS(ManipulateState.u.Continue2.ContinueStatus) != FALSE) {
  145. BdGetStateChange(&ManipulateState, ContextRecord);
  146. return ContinueSuccess;
  147. } else {
  148. return ContinueError;
  149. }
  150. break;
  151. case DbgKdRebootApi:
  152. BdReboot();
  153. break;
  154. case DbgKdGetVersionApi:
  155. BdGetVersion(&ManipulateState);
  156. break;
  157. case DbgKdWriteBreakPointExApi:
  158. Status = BdWriteBreakPointEx(&ManipulateState,
  159. &MessageData,
  160. ContextRecord);
  161. if (Status) {
  162. ManipulateState.ApiNumber = DbgKdContinueApi;
  163. ManipulateState.u.Continue.ContinueStatus = Status;
  164. return ContinueError;
  165. }
  166. break;
  167. case DbgKdRestoreBreakPointExApi:
  168. BdRestoreBreakPointEx(&ManipulateState, &MessageData, ContextRecord);
  169. break;
  170. //
  171. // Invalid message.
  172. //
  173. default:
  174. MessageData.Length = 0;
  175. ManipulateState.ReturnStatus = STATUS_UNSUCCESSFUL;
  176. BdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
  177. &MessageHeader,
  178. &MessageData);
  179. break;
  180. }
  181. #ifdef _ALPHA_
  182. //
  183. //jnfix
  184. // this is embarrasing, we have an icache coherency problem that
  185. // the following imb fixes, later we must track this down to the
  186. // exact offending API but for now this statement allows the stub
  187. // work to appropriately for Alpha.
  188. //
  189. #if defined(_MSC_VER)
  190. __PAL_IMB();
  191. #else
  192. asm( "call_pal 0x86" ); // x86 = imb
  193. #endif
  194. #endif
  195. }
  196. }
  197. VOID
  198. BdpSetCommonState(
  199. IN ULONG NewState,
  200. IN PCONTEXT ContextRecord,
  201. OUT PDBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange
  202. )
  203. {
  204. BOOLEAN DeletedBps;
  205. PCHAR PcMemory;
  206. USHORT InstrCount;
  207. PUCHAR InstrStream;
  208. WaitStateChange->NewState = NewState;
  209. WaitStateChange->ProcessorLevel = 0;
  210. WaitStateChange->Processor = 0;
  211. WaitStateChange->NumberProcessors = 1;
  212. WaitStateChange->Thread = 0;
  213. PcMemory = (PCHAR)CONTEXT_TO_PROGRAM_COUNTER(ContextRecord);
  214. WaitStateChange->ProgramCounter = (ULONG64)(LONG64)(LONG_PTR)PcMemory;
  215. RtlZeroMemory(&WaitStateChange->AnyControlReport,
  216. sizeof(WaitStateChange->AnyControlReport));
  217. //
  218. // Copy instruction stream immediately following location of event.
  219. //
  220. InstrStream = WaitStateChange->ControlReport.InstructionStream;
  221. InstrCount = (USHORT)
  222. BdMoveMemory(InstrStream, PcMemory, DBGKD_MAXSTREAM);
  223. WaitStateChange->ControlReport.InstructionCount = InstrCount;
  224. //
  225. // Clear breakpoints in copied area.
  226. // If there were any breakpoints cleared, recopy the instruction area
  227. // without them.
  228. //
  229. if (BdDeleteBreakpointRange((ULONG_PTR)PcMemory,
  230. (ULONG_PTR)PcMemory + InstrCount - 1)) {
  231. BdMoveMemory(InstrStream, PcMemory, InstrCount);
  232. }
  233. }
  234. LOGICAL
  235. BdReportExceptionStateChange (
  236. IN PEXCEPTION_RECORD ExceptionRecord,
  237. IN OUT PCONTEXT ContextRecord
  238. )
  239. /*++
  240. Routine Description:
  241. This routine sends an exception state change packet to the kernel
  242. debugger and waits for a manipulate state message.
  243. Arguments:
  244. ExceptionRecord - Supplies a pointer to an exception record.
  245. ContextRecord - Supplies a pointer to a context record.
  246. Return Value:
  247. A value of TRUE is returned if the exception is handled. Otherwise, a
  248. value of FALSE is returned.
  249. --*/
  250. {
  251. STRING MessageData;
  252. STRING MessageHeader;
  253. DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange;
  254. KCONTINUE_STATUS Status;
  255. do {
  256. //
  257. // Construct the wait state change message and message descriptor.
  258. //
  259. BdpSetCommonState(DbgKdExceptionStateChange, ContextRecord,
  260. &WaitStateChange);
  261. if (sizeof(EXCEPTION_RECORD) ==
  262. sizeof(WaitStateChange.u.Exception.ExceptionRecord)) {
  263. BdCopyMemory((PCHAR)&WaitStateChange.u.Exception.ExceptionRecord,
  264. (PCHAR)ExceptionRecord,
  265. sizeof(EXCEPTION_RECORD));
  266. } else {
  267. ExceptionRecord32To64((PEXCEPTION_RECORD32)ExceptionRecord,
  268. &WaitStateChange.u.Exception.ExceptionRecord);
  269. }
  270. WaitStateChange.u.Exception.FirstChance = TRUE;
  271. BdSetStateChange(&WaitStateChange,
  272. ExceptionRecord,
  273. ContextRecord);
  274. MessageHeader.Length = sizeof(WaitStateChange);
  275. MessageHeader.Buffer = (PCHAR)&WaitStateChange;
  276. MessageData.Length = 0;
  277. //
  278. // Send packet to the kernel debugger on the host machine,
  279. // wait for answer.
  280. //
  281. Status = BdSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64,
  282. &MessageHeader,
  283. &MessageData,
  284. ContextRecord);
  285. } while (Status == ContinueProcessorReselected) ;
  286. return (BOOLEAN) Status;
  287. }
  288. LOGICAL
  289. BdReportLoadSymbolsStateChange (
  290. IN PSTRING PathName,
  291. IN PKD_SYMBOLS_INFO SymbolInfo,
  292. IN LOGICAL UnloadSymbols,
  293. IN OUT PCONTEXT ContextRecord
  294. )
  295. /*++
  296. Routine Description:
  297. This routine sends a load symbols state change packet to the kernel
  298. debugger and waits for a manipulate state message.
  299. Arguments:
  300. PathName - Supplies a pointer to the pathname of the image whose
  301. symbols are to be loaded.
  302. BaseOfDll - Supplies the base address where the image was loaded.
  303. ProcessId - Unique 32-bit identifier for process that is using
  304. the symbols. -1 for system process.
  305. CheckSum - Unique 32-bit identifier from image header.
  306. UnloadSymbol - TRUE if the symbols that were previously loaded for
  307. the named image are to be unloaded from the debugger.
  308. Return Value:
  309. A value of TRUE is returned if the exception is handled. Otherwise, a
  310. value of FALSE is returned.
  311. --*/
  312. {
  313. PSTRING AdditionalData;
  314. STRING MessageData;
  315. STRING MessageHeader;
  316. DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange;
  317. KCONTINUE_STATUS Status;
  318. do {
  319. //
  320. // Construct the wait state change message and message descriptor.
  321. //
  322. BdpSetCommonState(DbgKdLoadSymbolsStateChange, ContextRecord,
  323. &WaitStateChange);
  324. BdSetContextState(&WaitStateChange, ContextRecord);
  325. WaitStateChange.u.LoadSymbols.UnloadSymbols = (BOOLEAN)UnloadSymbols;
  326. WaitStateChange.u.LoadSymbols.BaseOfDll = (ULONG64)SymbolInfo->BaseOfDll;
  327. WaitStateChange.u.LoadSymbols.ProcessId = SymbolInfo->ProcessId;
  328. WaitStateChange.u.LoadSymbols.CheckSum = SymbolInfo->CheckSum;
  329. WaitStateChange.u.LoadSymbols.SizeOfImage = SymbolInfo->SizeOfImage;
  330. if (ARGUMENT_PRESENT(PathName)) {
  331. WaitStateChange.u.LoadSymbols.PathNameLength =
  332. BdMoveMemory((PCHAR)BdMessageBuffer,
  333. (PCHAR)PathName->Buffer,
  334. PathName->Length) + 1;
  335. MessageData.Buffer = (PCHAR)(&BdMessageBuffer[0]);
  336. MessageData.Length = (USHORT)WaitStateChange.u.LoadSymbols.PathNameLength;
  337. MessageData.Buffer[MessageData.Length-1] = '\0';
  338. AdditionalData = &MessageData;
  339. } else {
  340. WaitStateChange.u.LoadSymbols.PathNameLength = 0;
  341. AdditionalData = NULL;
  342. }
  343. MessageHeader.Length = sizeof(WaitStateChange);
  344. MessageHeader.Buffer = (PCHAR)&WaitStateChange;
  345. //
  346. // Send packet to the kernel debugger on the host machine, wait
  347. // for the reply.
  348. //
  349. Status = BdSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64,
  350. &MessageHeader,
  351. AdditionalData,
  352. ContextRecord);
  353. } while (Status == ContinueProcessorReselected);
  354. return (BOOLEAN) Status;
  355. }