|
|
1.1 ! root 1: #include "givit.h" ! 2: ! 3: ! 4: extern HANDLE PipeRead; // see DbgKdpKbdPollThread ! 5: extern HANDLE PipeWrite; ! 6: extern ULONG NumberProcessors; ! 7: static USHORT LastProcessorToPrint = -1; ! 8: ! 9: UCHAR DbgKdpPacketLeader[4] = { ! 10: PACKET_LEADER_BYTE, ! 11: PACKET_LEADER_BYTE, ! 12: PACKET_LEADER_BYTE, ! 13: PACKET_LEADER_BYTE ! 14: }; ! 15: ! 16: // ! 17: // DbgKdpCmdCanceled indicates the fact that the current kd command has ! 18: // been canceled by user (using ctrl-C.) With the Packet Id controlling ! 19: // the packet exchange, the Ctrl-C has to be handled in controlled manner. ! 20: // At each end of DbgKdpXXXX routine, we will check for this flag. If the ! 21: // command has been canceled, a longjmp will be performed to transfer control ! 22: // back to kd prompt. ! 23: // ! 24: ! 25: BOOLEAN DbgKdpCmdCanceled = FALSE; ! 26: ! 27: #ifdef DBG ! 28: BOOLEAN KdDebug = FALSE; ! 29: #endif ! 30: ! 31: BOOLEAN KdResync = FALSE; ! 32: UCHAR PrintBuf[PACKET_MAX_SIZE]; ! 33: ! 34: #define CONTROL_B 2 ! 35: #define CONTROL_D 4 ! 36: #define CONTROL_R 18 ! 37: #define CONTROL_V 22 ! 38: ! 39: ULONG DbgKdpPacketExpected; // ID for expected incoming packet ! 40: ULONG DbgKdpNextPacketToSend; // ID for Next packet to send ! 41: extern VOID DbgKdpSynchronizeTarget ( VOID ); ! 42: ! 43: //++ ! 44: // ! 45: // VOID ! 46: // DbgKdpWaitPacketForever ( ! 47: // IN ULONG PacketType, ! 48: // IN PVOID Buffer ! 49: // ) ! 50: // ! 51: // Routine Description: ! 52: // ! 53: // This macro is invoked to wait for specifi type of message without ! 54: // timeout. ! 55: // ! 56: // Arguments: ! 57: // ! 58: // PacketType - Type of the message we are expecting. ! 59: // ! 60: // Buffer - Buffer to store the message. ! 61: // ! 62: // Return Value: ! 63: // ! 64: // None. ! 65: // ! 66: //-- ! 67: ! 68: #define DbgKdpWaitPacketForever( PacketType, Buffer) { \ ! 69: BOOLEAN rc; \ ! 70: do { \ ! 71: rc = DbgKdpWaitForPacket( \ ! 72: PacketType, \ ! 73: Buffer \ ! 74: ); \ ! 75: } while ( rc == FALSE); \ ! 76: } ! 77: ! 78: DWORD ! 79: DbgKdConnectAndInitialize( ! 80: ) ! 81: { ! 82: ! 83: DWORD BytesWritten; ! 84: BOOL rc; ! 85: USHORT Length; ! 86: ! 87: // ! 88: // Initialize comport, packet queue and start the packet receiving ! 89: // thread. ! 90: // ! 91: ! 92: DbgKdpInitComPort(0L); ! 93: DbgKdpPacketExpected = INITIAL_PACKET_ID; ! 94: DbgKdpNextPacketToSend = INITIAL_PACKET_ID; ! 95: ! 96: DbgKdpStartThreads(); ! 97: ! 98: return ERROR_SUCCESS; ! 99: } ! 100: ! 101: VOID ! 102: DbgKdpHandlePromptString( ! 103: IN PDBGKD_DEBUG_IO IoMessage ! 104: ) ! 105: { ! 106: PUCHAR IoData; ! 107: DWORD i; ! 108: DWORD j; ! 109: BOOL rc; ! 110: UCHAR c; ! 111: PUCHAR d; ! 112: ! 113: IoData = (PUCHAR)(IoMessage+1); ! 114: ! 115: DbgKdpPrint(IoMessage->Processor, ! 116: IoData, ! 117: (USHORT)IoMessage->u.GetString.LengthOfPromptString ! 118: ); ! 119: ! 120: // ! 121: // read the prompt data ! 122: // ! 123: ! 124: j = 0; ! 125: d = IoData; ! 126: rc = DbgKdpGetConsoleByte(&c, 1, &i); ! 127: ! 128: while ( rc == TRUE && ! 129: i == 1 && ! 130: j < (USHORT)IoMessage->u.GetString.LengthOfStringRead) { ! 131: ! 132: if ( c == '\r' ) { ! 133: *d++ = '\0'; ! 134: j++; ! 135: } else if ( c == '\n' ) { ! 136: *d++ = '\0'; ! 137: j++; ! 138: break; ! 139: } else { ! 140: *d++ = c; ! 141: j++; ! 142: } ! 143: rc = DbgKdpGetConsoleByte(&c, 1, &i); ! 144: } ! 145: ! 146: LastProcessorToPrint = -1; ! 147: if ( j < (USHORT)IoMessage->u.GetString.LengthOfStringRead ) { ! 148: IoMessage->u.GetString.LengthOfStringRead = j; ! 149: } ! 150: ! 151: // ! 152: // Send data to the debugger-target ! 153: // ! 154: ! 155: DbgKdpWritePacket( ! 156: IoMessage, ! 157: sizeof(*IoMessage), ! 158: PACKET_TYPE_KD_DEBUG_IO, ! 159: IoData, ! 160: (USHORT)IoMessage->u.GetString.LengthOfStringRead ! 161: ); ! 162: } ! 163: ! 164: VOID ! 165: DbgKdpPrint( ! 166: IN USHORT Processor, ! 167: IN PUCHAR String, ! 168: IN USHORT StringLength ! 169: ) ! 170: { ! 171: DWORD i; ! 172: DWORD j; ! 173: UCHAR c; ! 174: PUCHAR d; ! 175: static USHORT LastProcessor = -1; ! 176: ! 177: assert(StringLength < PACKET_MAX_SIZE - 2); ! 178: ! 179: d = PrintBuf; ! 180: if (NumberProcessors > 1 && Processor != LastProcessorToPrint) { ! 181: assert(Processor < 8); ! 182: LastProcessorToPrint = Processor; ! 183: *d++ = (UCHAR)((UCHAR)Processor + '0'); ! 184: *d++ = ':'; ! 185: j = 2; ! 186: } else { ! 187: j = 0; ! 188: } ! 189: for(i=0;i<StringLength;i++) { ! 190: c = *(String+i); ! 191: if ( c == '\n' ) { ! 192: LastProcessorToPrint = -1; ! 193: *d++ = '\n'; ! 194: *d++ = '\r'; ! 195: j += 2; ! 196: } else { ! 197: if ( c ) { ! 198: *d++ = c; ! 199: j++; ! 200: } ! 201: } ! 202: } ! 203: ! 204: // ! 205: // print the string. someday this should probably ! 206: // be a callout. ! 207: ! 208: WriteFile(ConsoleOutputHandle,PrintBuf,j,&i,NULL); ! 209: } ! 210: ! 211: DWORD ! 212: DbgKdWaitStateChange( ! 213: OUT PDBGKD_WAIT_STATE_CHANGE StateChange, ! 214: OUT PVOID Buffer, ! 215: IN ULONG BufferLength ! 216: ) ! 217: ! 218: /*++ ! 219: ! 220: Routine Description: ! 221: ! 222: This function causes the calling user interface to wait for a state ! 223: change to occur in the system being debugged. Once a state change ! 224: occurs, the user interface can either continue the system using ! 225: DbgKdContinue, or it can manipulate system state using anyone of the ! 226: DbgKd state manipulation APIs. ! 227: ! 228: Arguments: ! 229: ! 230: StateChange - Supplies the address of state change record that ! 231: will contain the state change information. ! 232: ! 233: Buffer - Supplies the address of a buffer that returns additional ! 234: information. ! 235: ! 236: BufferLength - Supplies the length of Buffer. ! 237: ! 238: Return Value: ! 239: ! 240: ERROR_SUCCESS - A state change occured. Valid state change information ! 241: was returned. ! 242: ! 243: --*/ ! 244: ! 245: { ! 246: ! 247: PDBGKD_WAIT_STATE_CHANGE LocalStateChange; ! 248: DWORD st; ! 249: UCHAR *pt; ! 250: ! 251: st = ERROR_INVALID_FUNCTION; ! 252: while ( st != ERROR_SUCCESS ) { ! 253: ! 254: // ! 255: // Waiting for a state change message. Copy the message to the callers ! 256: // buffer, and then free the packet entry. ! 257: // ! 258: ! 259: DbgKdpWaitPacketForever( ! 260: PACKET_TYPE_KD_STATE_CHANGE, ! 261: &LocalStateChange ! 262: ); ! 263: LocalStateChange = (PDBGKD_WAIT_STATE_CHANGE)DbgKdpPacket; ! 264: st = ERROR_SUCCESS; ! 265: assert(StateChange); ! 266: *StateChange = *LocalStateChange; ! 267: ! 268: switch ( (USHORT) StateChange->NewState ) { ! 269: case DbgKdExceptionStateChange: ! 270: break; ! 271: case DbgKdLoadSymbolsStateChange: ! 272: if ( BufferLength < LocalStateChange->u.LoadSymbols.PathNameLength ) { ! 273: st = ERROR_MORE_DATA; ! 274: } else { ! 275: pt = ((UCHAR *) LocalStateChange) + PacketHeader.ByteCount - ! 276: (int)LocalStateChange->u.LoadSymbols.PathNameLength; ! 277: memcpy(Buffer, pt, ! 278: (int)LocalStateChange->u.LoadSymbols.PathNameLength); ! 279: } ! 280: break; ! 281: default: ! 282: assert(FALSE); ! 283: } ! 284: return st; ! 285: } ! 286: } ! 287: ! 288: DWORD ! 289: DbgKdContinue ( ! 290: IN DWORD ContinueStatus ! 291: ) ! 292: ! 293: /*++ ! 294: ! 295: Routine Description: ! 296: ! 297: Continuing a system that previously reported a state change causes ! 298: the system to continue executiontion using the context in effect at ! 299: the time the state change was reported (of course this context could ! 300: have been modified using the DbgKd state manipulation APIs). ! 301: ! 302: Arguments: ! 303: ! 304: ContinueStatus - Supplies the continuation status to the thread ! 305: being continued. Valid values for this are ! 306: DBG_EXCEPTION_HANDLED, DBG_EXCEPTION_NOT_HANDLED ! 307: or DBG_CONTINUE. ! 308: ! 309: Return Value: ! 310: ! 311: ERROR_SUCCESS - Successful call to DbgUiContinue ! 312: ! 313: ERROR_INVALID_PARAMETER - An invalid continue status or was ! 314: specified. ! 315: ! 316: --*/ ! 317: ! 318: { ! 319: DBGKD_MANIPULATE_STATE m; ! 320: PDBGKD_CONTINUE a = &m.u.Continue; ! 321: DWORD st; ! 322: ! 323: if ( ContinueStatus == DBG_EXCEPTION_HANDLED || ! 324: ContinueStatus == DBG_EXCEPTION_NOT_HANDLED || ! 325: ContinueStatus == DBG_CONTINUE ) { ! 326: ! 327: m.ApiNumber = DbgKdContinueApi; ! 328: m.ReturnStatus = ContinueStatus; ! 329: ! 330: a->ContinueStatus = ContinueStatus; ! 331: DbgKdpWritePacket(&m,sizeof(m),PACKET_TYPE_KD_STATE_MANIPULATE,NULL,0); ! 332: st = ERROR_SUCCESS; ! 333: } ! 334: else { ! 335: st = ERROR_INVALID_PARAMETER; ! 336: } ! 337: ! 338: return st; ! 339: } ! 340: ! 341: ! 342: DWORD ! 343: DbgKdContinue2 ( ! 344: IN DWORD ContinueStatus, ! 345: IN DBGKD_CONTROL_SET ControlSet ! 346: ) ! 347: ! 348: /*++ ! 349: ! 350: Routine Description: ! 351: ! 352: Continuing a system that previously reported a state change causes ! 353: the system to continue executiontion using the context in effect at ! 354: the time the state change was reported, modified by the values set ! 355: in the ControlSet structure. (And, of course, the context could have ! 356: been modified by used the DbgKd state manipulation APIs.) ! 357: ! 358: Arguments: ! 359: ! 360: ContinueStatus - Supplies the continuation status to the thread ! 361: being continued. Valid values for this are ! 362: DBG_EXCEPTION_HANDLED, DBG_EXCEPTION_NOT_HANDLED ! 363: or DBG_CONTINUE. ! 364: ! 365: ControlSet - Supplies a pointer to a structure containing the machine ! 366: specific control data to set. For the x86 this is the TraceFlag ! 367: and Dr7. ! 368: ! 369: Return Value: ! 370: ! 371: ERROR_SUCCESS - Successful call to DbgUiContinue ! 372: ! 373: ERROR_INVALID_PARAMETER - An invalid continue status or was ! 374: specified. ! 375: ! 376: --*/ ! 377: ! 378: { ! 379: DBGKD_MANIPULATE_STATE m; ! 380: DWORD st; ! 381: ! 382: if ( ContinueStatus == DBG_EXCEPTION_HANDLED || ! 383: ContinueStatus == DBG_EXCEPTION_NOT_HANDLED || ! 384: ContinueStatus == DBG_CONTINUE ) { ! 385: ! 386: m.ApiNumber = DbgKdContinueApi2; ! 387: m.ReturnStatus = ContinueStatus; ! 388: ! 389: m.u.Continue2.ContinueStatus = ContinueStatus; ! 390: m.u.Continue2.ControlSet = ControlSet; ! 391: ! 392: DbgKdpWritePacket(&m,sizeof(m),PACKET_TYPE_KD_STATE_MANIPULATE,NULL,0); ! 393: st = ERROR_SUCCESS; ! 394: ! 395: } else { ! 396: st = ERROR_INVALID_PARAMETER; ! 397: } ! 398: ! 399: return st; ! 400: } ! 401: ! 402: DWORD ! 403: DbgKdReadVirtualMemory( ! 404: IN PVOID TargetBaseAddress, ! 405: OUT PVOID UserInterfaceBuffer, ! 406: IN ULONG TransferCount, ! 407: OUT PULONG ActualBytesRead OPTIONAL ! 408: ) ! 409: ! 410: /*++ ! 411: ! 412: Routine Description: ! 413: ! 414: This function reads the specified data from the system being debugged ! 415: using the current mapping of the processor. ! 416: ! 417: Arguments: ! 418: ! 419: TargetBaseAddress - Supplies the base address of the memory to read ! 420: from the system being debugged. The virtual address is in terms ! 421: of the current mapping for the processor that reported the last ! 422: state change. Until we figure out how to do this differently, ! 423: the virtual address must refer to a valid page (although it does ! 424: not necesserily have to be in the TB). ! 425: ! 426: UserInterfaceBuffer - Supplies the address of the buffer in the user ! 427: interface that data read is to be placed. ! 428: ! 429: TransferCount - Specifies the number of bytes to read. ! 430: ! 431: ActualBytesRead - An optional parameter that if supplied, returns ! 432: the number of bytes actually read. ! 433: ! 434: Return Value: ! 435: ! 436: ERROR_SUCCESS - The specified read occured. ! 437: ! 438: ERROR_MORE_DATA - A read that is to large was specified. ! 439: ! 440: ERROR_NO_ACCESS - The TargetBaseAddress/TransferCount ! 441: parameters refers to invalid virtual memory. ! 442: ! 443: !ERROR_SUCCESS - TBD ! 444: ! 445: --*/ ! 446: ! 447: { ! 448: DBGKD_MANIPULATE_STATE m; ! 449: PDBGKD_MANIPULATE_STATE Reply; ! 450: PDBGKD_READ_MEMORY a = &m.u.ReadMemory; ! 451: DWORD st; ! 452: BOOLEAN rc; ! 453: ! 454: if ( TransferCount + sizeof(m) > PACKET_MAX_SIZE ) { ! 455: return ERROR_MORE_DATA; ! 456: } ! 457: ! 458: // ! 459: // Format state manipulate message ! 460: // ! 461: ! 462: m.ApiNumber = DbgKdReadVirtualMemoryApi; ! 463: m.ReturnStatus = STATUS_PENDING; ! 464: a->TargetBaseAddress = TargetBaseAddress; ! 465: a->TransferCount = TransferCount; ! 466: a->ActualBytesRead = 0L; ! 467: ! 468: // ! 469: // Send the message and then wait for reply ! 470: // ! 471: ! 472: do { ! 473: DbgKdpWritePacket(&m,sizeof(m),PACKET_TYPE_KD_STATE_MANIPULATE,NULL,0); ! 474: ! 475: rc = DbgKdpWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, ! 476: &Reply ! 477: ); ! 478: } while (rc == FALSE); ! 479: ! 480: // ! 481: // If this is not a ReadMemory response than protocol is screwed up. ! 482: // assert that protocol is ok. ! 483: // ! 484: ! 485: st = Reply->ReturnStatus; ! 486: assert(Reply->ApiNumber == DbgKdReadVirtualMemoryApi); ! 487: ! 488: // ! 489: // Reset message address to reply. ! 490: // ! 491: ! 492: a = &Reply->u.ReadMemory; ! 493: assert(a->ActualBytesRead <= TransferCount); ! 494: ! 495: // ! 496: // Return actual bytes read, and then transfer the bytes ! 497: // ! 498: ! 499: if (ActualBytesRead) { ! 500: *ActualBytesRead = a->ActualBytesRead; ! 501: } ! 502: st = Reply->ReturnStatus; ! 503: ! 504: // ! 505: // Since read response data follows message, Reply+1 should point ! 506: // at the data ! 507: // ! 508: ! 509: memcpy(UserInterfaceBuffer, Reply+1, (int)a->ActualBytesRead); ! 510: ! 511: return st; ! 512: } ! 513: ! 514: ! 515: ! 516: DWORD ! 517: DbgKdWriteVirtualMemory( ! 518: IN PVOID TargetBaseAddress, ! 519: OUT PVOID UserInterfaceBuffer, ! 520: IN ULONG TransferCount, ! 521: OUT PULONG ActualBytesWritten OPTIONAL ! 522: ) ! 523: ! 524: /*++ ! 525: ! 526: Routine Description: ! 527: ! 528: This function writes the specified data to the system being debugged ! 529: using the current mapping of the processor. ! 530: ! 531: Arguments: ! 532: ! 533: TargetBaseAddress - Supplies the base address of the memory to be written ! 534: into the system being debugged. The virtual address is in terms ! 535: of the current mapping for the processor that reported the last ! 536: state change. Until we figure out how to do this differently, ! 537: the virtual address must refer to a valid page (although it does ! 538: not necesserily have to be in the TB). ! 539: ! 540: UserInterfaceBuffer - Supplies the address of the buffer in the user ! 541: interface that contains the data to be written. ! 542: ! 543: TransferCount - Specifies the number of bytes to write. ! 544: ! 545: ActualBytesWritten - An optional parameter that if supplied, returns ! 546: the number of bytes actually written. ! 547: ! 548: Return Value: ! 549: ! 550: ERROR_SUCCESS - The specified read occured. ! 551: ! 552: ERROR_MORE_DATA - A read that is to large was specified. ! 553: ! 554: ERROR_NO_ACCESS - The TargetBaseAddress/TransferCount ! 555: parameters refers to invalid virtual memory. ! 556: ! 557: !ERROR_SUCCESS - TBD ! 558: ! 559: --*/ ! 560: ! 561: { ! 562: DBGKD_MANIPULATE_STATE m; ! 563: PDBGKD_MANIPULATE_STATE Reply; ! 564: PDBGKD_WRITE_MEMORY a = &m.u.WriteMemory; ! 565: DWORD st; ! 566: BOOLEAN rc; ! 567: ! 568: if ( TransferCount + sizeof(m) > PACKET_MAX_SIZE ) { ! 569: return ERROR_MORE_DATA; ! 570: } ! 571: ! 572: // ! 573: // Format state manipulate message ! 574: // ! 575: ! 576: m.ApiNumber = DbgKdWriteVirtualMemoryApi; ! 577: m.ReturnStatus = STATUS_PENDING; ! 578: a->TargetBaseAddress = TargetBaseAddress; ! 579: a->TransferCount = TransferCount; ! 580: a->ActualBytesWritten = 0L; ! 581: ! 582: // ! 583: // Send the message and data to write and then wait for reply ! 584: // ! 585: ! 586: do { ! 587: DbgKdpWritePacket( ! 588: &m, ! 589: sizeof(m), ! 590: PACKET_TYPE_KD_STATE_MANIPULATE, ! 591: UserInterfaceBuffer, ! 592: (USHORT)TransferCount ! 593: ); ! 594: rc = DbgKdpWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, ! 595: &Reply ! 596: ); ! 597: } while (rc == FALSE); ! 598: ! 599: // ! 600: // If this is not a WriteMemory response than protocol is screwed up. ! 601: // assert that protocol is ok. ! 602: // ! 603: ! 604: st = Reply->ReturnStatus; ! 605: assert(Reply->ApiNumber == DbgKdWriteVirtualMemoryApi); ! 606: ! 607: // ! 608: // Reset message address to reply. ! 609: // ! 610: ! 611: a = &Reply->u.WriteMemory; ! 612: assert(a->ActualBytesWritten <= TransferCount); ! 613: ! 614: // ! 615: // Return actual bytes written ! 616: // ! 617: ! 618: if (ActualBytesWritten) { ! 619: *ActualBytesWritten = a->ActualBytesWritten; ! 620: } ! 621: st = Reply->ReturnStatus; ! 622: ! 623: return st; ! 624: } ! 625: ! 626: DWORD ! 627: DbgKdReadControlSpace( ! 628: IN USHORT Processor, ! 629: IN PVOID TargetBaseAddress, ! 630: OUT PVOID UserInterfaceBuffer, ! 631: IN ULONG TransferCount, ! 632: OUT PULONG ActualBytesRead OPTIONAL ! 633: ) ! 634: ! 635: /*++ ! 636: ! 637: Routine Description: ! 638: ! 639: This function reads the specified data from the control space of ! 640: the system being debugged. ! 641: ! 642: Control space is processor dependent. TargetBaseAddress is mapped ! 643: to control space in a processor/implementation defined manner. ! 644: ! 645: Arguments: ! 646: ! 647: Processor - Supplies the processor whoes control space is desired. ! 648: ! 649: TargetBaseAddress - Supplies the base address in control space to ! 650: read. This address is interpreted in an implementation defined ! 651: manner. ! 652: ! 653: ! 654: On x86, control space is a per-processor area which contains: ! 655: ! 656: Current Context (CONTEXT) ! 657: Special Registers (KSPECIAL_REGISTERS) ! 658: ! 659: This means that to read the special registers: ! 660: ! 661: DbgKdReadControlSpace( ! 662: NtsdCurrentProcessor, ! 663: (PVOID)sizeof(CONTEXT), ! 664: (PVOID)&SpecialRegContext, ! 665: sizeof(KSPECIAL_REGISTERS), ! 666: &cBytesRead ! 667: ); ! 668: ! 669: The above will read the special registers of the current processor ! 670: since the control space address is sizeof(CONTEXT) ! 671: ! 672: On MIPS, control space addresses are used to address the translation ! 673: buffer. ! 674: ! 675: UserInterfaceBuffer - Supplies the address of the buffer in the user ! 676: interface that data read is to be placed. ! 677: ! 678: TransferCount - Specifies the number of bytes to read. ! 679: ! 680: ActualBytesRead - An optional parameter that if supplied, returns ! 681: the number of bytes actually read. ! 682: ! 683: Return Value: ! 684: ! 685: ERROR_SUCCESS - The specified read occured. ! 686: ! 687: ERROR_MORE_DATA - A read that is to large was specified. ! 688: ! 689: !ERROR_SUCCESS - TBD ! 690: ! 691: --*/ ! 692: ! 693: { ! 694: DBGKD_MANIPULATE_STATE m; ! 695: PDBGKD_MANIPULATE_STATE Reply; ! 696: PDBGKD_READ_MEMORY a = &m.u.ReadMemory; ! 697: DWORD st; ! 698: BOOLEAN rc; ! 699: ! 700: if ( TransferCount + sizeof(m) > PACKET_MAX_SIZE ) { ! 701: return ERROR_MORE_DATA; ! 702: } ! 703: ! 704: // ! 705: // Format state manipulate message ! 706: // ! 707: ! 708: m.ApiNumber = DbgKdReadControlSpaceApi; ! 709: m.ReturnStatus = STATUS_PENDING; ! 710: m.Processor = Processor; ! 711: a->TargetBaseAddress = TargetBaseAddress; ! 712: a->TransferCount = TransferCount; ! 713: a->ActualBytesRead = 0L; ! 714: ! 715: // ! 716: // Send the message and then wait for reply ! 717: // ! 718: ! 719: do { ! 720: DbgKdpWritePacket(&m,sizeof(m),PACKET_TYPE_KD_STATE_MANIPULATE,NULL,0); ! 721: ! 722: rc = DbgKdpWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply); ! 723: ! 724: } while (rc == FALSE); ! 725: ! 726: // ! 727: // If this is not a ReadControl response than protocol is screwed up. ! 728: // assert that protocol is ok. ! 729: // ! 730: ! 731: st = Reply->ReturnStatus; ! 732: assert(Reply->ApiNumber == DbgKdReadControlSpaceApi); ! 733: ! 734: // ! 735: // Reset message address to reply. ! 736: // ! 737: ! 738: a = &Reply->u.ReadMemory; ! 739: assert(a->ActualBytesRead <= TransferCount); ! 740: ! 741: // ! 742: // Return actual bytes read, and then transfer the bytes ! 743: // ! 744: ! 745: if (ActualBytesRead) { ! 746: *ActualBytesRead = a->ActualBytesRead; ! 747: } ! 748: st = Reply->ReturnStatus; ! 749: ! 750: // ! 751: // Since read response data follows message, Reply+1 should point ! 752: // at the data ! 753: // ! 754: ! 755: memcpy(UserInterfaceBuffer, Reply+1, (int)a->ActualBytesRead); ! 756: ! 757: return st; ! 758: } ! 759: ! 760: ! 761: ! 762: DWORD ! 763: DbgKdWriteControlSpace( ! 764: IN USHORT Processor, ! 765: IN PVOID TargetBaseAddress, ! 766: OUT PVOID UserInterfaceBuffer, ! 767: IN ULONG TransferCount, ! 768: OUT PULONG ActualBytesWritten OPTIONAL ! 769: ) ! 770: ! 771: /*++ ! 772: ! 773: Routine Description: ! 774: ! 775: This function writes the specified data to control space on the system ! 776: being debugged. ! 777: ! 778: Control space is processor dependent. TargetBaseAddress is mapped ! 779: to control space in a processor/implementation defined manner. ! 780: ! 781: Arguments: ! 782: ! 783: Processor - Supplies the processor whoes control space is desired. ! 784: ! 785: TargetBaseAddress - Supplies the base address in control space to be ! 786: written. ! 787: ! 788: UserInterfaceBuffer - Supplies the address of the buffer in the user ! 789: interface that contains the data to be written. ! 790: ! 791: TransferCount - Specifies the number of bytes to write. ! 792: ! 793: ActualBytesWritten - An optional parameter that if supplied, returns ! 794: the number of bytes actually written. ! 795: ! 796: Return Value: ! 797: ! 798: ERROR_SUCCESS - The specified read occured. ! 799: ! 800: ERROR_MORE_DATA - A read that is to large was specified. ! 801: ! 802: !ERROR_SUCCESS - TBD ! 803: ! 804: --*/ ! 805: ! 806: { ! 807: DBGKD_MANIPULATE_STATE m; ! 808: PDBGKD_MANIPULATE_STATE Reply; ! 809: PDBGKD_WRITE_MEMORY a = &m.u.WriteMemory; ! 810: DWORD st; ! 811: BOOLEAN rc; ! 812: ! 813: if ( TransferCount + sizeof(m) > PACKET_MAX_SIZE ) { ! 814: return ERROR_MORE_DATA; ! 815: } ! 816: ! 817: // ! 818: // Format state manipulate message ! 819: // ! 820: ! 821: m.ApiNumber = DbgKdWriteControlSpaceApi; ! 822: m.ReturnStatus = STATUS_PENDING; ! 823: m.Processor = Processor; ! 824: a->TargetBaseAddress = TargetBaseAddress; ! 825: a->TransferCount = TransferCount; ! 826: a->ActualBytesWritten = 0L; ! 827: ! 828: // ! 829: // Send the message and data to write and then wait for reply ! 830: // ! 831: ! 832: do { ! 833: DbgKdpWritePacket( ! 834: &m, ! 835: sizeof(m), ! 836: PACKET_TYPE_KD_STATE_MANIPULATE, ! 837: UserInterfaceBuffer, ! 838: (USHORT)TransferCount ! 839: ); ! 840: ! 841: rc = DbgKdpWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply); ! 842: } while (rc == FALSE); ! 843: ! 844: // ! 845: // If this is not a WriteControl response than protocol is screwed up. ! 846: // assert that protocol is ok. ! 847: // ! 848: ! 849: st = Reply->ReturnStatus; ! 850: assert(Reply->ApiNumber == DbgKdWriteControlSpaceApi); ! 851: ! 852: // ! 853: // Reset message address to reply. ! 854: // ! 855: ! 856: a = &Reply->u.WriteMemory; ! 857: assert(a->ActualBytesWritten <= TransferCount); ! 858: ! 859: // ! 860: // Return actual bytes written ! 861: // ! 862: ! 863: *ActualBytesWritten = a->ActualBytesWritten; ! 864: st = Reply->ReturnStatus; ! 865: ! 866: return st; ! 867: } ! 868: ! 869: ! 870: DWORD ! 871: DbgKdGetContext( ! 872: IN USHORT Processor, ! 873: IN OUT PCONTEXT Context ! 874: ) ! 875: ! 876: /*++ ! 877: ! 878: Routine Description: ! 879: ! 880: This function reads the context from the system being debugged. ! 881: The ContextFlags field determines how much context is read. ! 882: ! 883: Arguments: ! 884: ! 885: Processor - Supplies a processor number to get context from. ! 886: ! 887: Context - On input, the ContextFlags field controls what portions of ! 888: the context record the caller as interested in reading. On ! 889: output, the context record returns the current context for the ! 890: processor that reported the last state change. ! 891: ! 892: Return Value: ! 893: ! 894: ERROR_SUCCESS - The specified get context occured. ! 895: ! 896: !ERROR_SUCCESS - TBD ! 897: ! 898: --*/ ! 899: ! 900: { ! 901: DBGKD_MANIPULATE_STATE m; ! 902: PDBGKD_MANIPULATE_STATE Reply; ! 903: PDBGKD_GET_CONTEXT a = &m.u.GetContext; ! 904: DWORD st; ! 905: BOOLEAN rc; ! 906: ! 907: // ! 908: // Format state manipulate message ! 909: // ! 910: ! 911: m.ApiNumber = DbgKdGetContextApi; ! 912: m.ReturnStatus = STATUS_PENDING; ! 913: m.Processor = Processor; ! 914: a->ContextFlags = Context->ContextFlags; ! 915: ! 916: // ! 917: // Send the message and then wait for reply ! 918: // ! 919: ! 920: do { ! 921: DbgKdpWritePacket(&m,sizeof(m),PACKET_TYPE_KD_STATE_MANIPULATE,NULL,0); ! 922: rc = DbgKdpWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply); ! 923: } while (rc == FALSE); ! 924: ! 925: // ! 926: // If this is not a GetContext response than protocol is screwed up. ! 927: // assert that protocol is ok. ! 928: // ! 929: ! 930: st = Reply->ReturnStatus; ! 931: assert(Reply->ApiNumber == DbgKdGetContextApi); ! 932: ! 933: // ! 934: // Reset message address to reply. ! 935: // ! 936: ! 937: a = &Reply->u.GetContext; ! 938: st = Reply->ReturnStatus; ! 939: ! 940: // ! 941: // Since get context response data follows message, Reply+1 should point ! 942: // at the data ! 943: // ! 944: ! 945: memcpy(Context, Reply+1, sizeof(*Context)); ! 946: ! 947: return st; ! 948: } ! 949: ! 950: ! 951: ! 952: DWORD ! 953: DbgKdSetContext( ! 954: IN USHORT Processor, ! 955: IN PCONTEXT Context ! 956: ) ! 957: ! 958: /*++ ! 959: ! 960: Routine Description: ! 961: ! 962: This function writes the specified context to the system being debugged. ! 963: ! 964: Arguments: ! 965: ! 966: Processor - Supplies a processor number to set the context to. ! 967: ! 968: Context - Supplies a context record used to set the context for the ! 969: processor that reported the last state change. Only the ! 970: portions of the context indicated by the ContextFlags field are ! 971: actually written. ! 972: ! 973: ! 974: Return Value: ! 975: ! 976: ERROR_SUCCESS - The specified set context occured. ! 977: ! 978: !ERROR_SUCCESS - TBD ! 979: ! 980: --*/ ! 981: ! 982: { ! 983: DBGKD_MANIPULATE_STATE m; ! 984: PDBGKD_MANIPULATE_STATE Reply; ! 985: PDBGKD_SET_CONTEXT a = &m.u.SetContext; ! 986: DWORD st; ! 987: BOOLEAN rc; ! 988: ! 989: // ! 990: // Format state manipulate message ! 991: // ! 992: ! 993: m.ApiNumber = DbgKdSetContextApi; ! 994: m.ReturnStatus = STATUS_PENDING; ! 995: m.Processor = Processor; ! 996: a->ContextFlags = Context->ContextFlags; ! 997: ! 998: // ! 999: // Send the message and context and then wait for reply ! 1000: // ! 1001: ! 1002: do { ! 1003: DbgKdpWritePacket( ! 1004: &m, ! 1005: sizeof(m), ! 1006: PACKET_TYPE_KD_STATE_MANIPULATE, ! 1007: Context, ! 1008: sizeof(*Context) ! 1009: ); ! 1010: rc = DbgKdpWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply); ! 1011: } while (rc == FALSE); ! 1012: ! 1013: // ! 1014: // If this is not a SetContext response than protocol is screwed up. ! 1015: // assert that protocol is ok. ! 1016: // ! 1017: ! 1018: st = Reply->ReturnStatus; ! 1019: assert(Reply->ApiNumber == DbgKdSetContextApi); ! 1020: ! 1021: // ! 1022: // Reset message address to reply. ! 1023: // ! 1024: ! 1025: a = &Reply->u.SetContext; ! 1026: st = Reply->ReturnStatus; ! 1027: ! 1028: return st; ! 1029: } ! 1030: ! 1031: DWORD ! 1032: DbgKdWriteBreakPoint( ! 1033: IN PVOID BreakPointAddress, ! 1034: OUT PULONG BreakPointHandle ! 1035: ) ! 1036: ! 1037: /*++ ! 1038: ! 1039: Routine Description: ! 1040: ! 1041: This function is used to write a breakpoint at the address specified. ! 1042: ! 1043: ! 1044: Arguments: ! 1045: ! 1046: BreakPointAddress - Supplies the address that a breakpoint ! 1047: instruction is to be written. This address is interpreted using ! 1048: the current mapping on the processor reporting the previous ! 1049: state change. If the address refers to a page that is not ! 1050: valid, the the breakpoint is remembered by the system. As each ! 1051: page is made valid, the system will check for pending ! 1052: breakpoints and install breakpoints as necessary. ! 1053: ! 1054: BreakPointHandle - Returns a handle to a breakpoint. This handle ! 1055: may be used in a subsequent call to DbgKdRestoreBreakPoint. ! 1056: ! 1057: Return Value: ! 1058: ! 1059: ERROR_SUCCESS - The specified breakpoint write occured. ! 1060: ! 1061: !ERROR_SUCCESS - TBD ! 1062: ! 1063: ! 1064: --*/ ! 1065: ! 1066: { ! 1067: ! 1068: DBGKD_MANIPULATE_STATE m; ! 1069: PDBGKD_MANIPULATE_STATE Reply; ! 1070: PDBGKD_WRITE_BREAKPOINT a = &m.u.WriteBreakPoint; ! 1071: DWORD st; ! 1072: BOOLEAN rc; ! 1073: ! 1074: // ! 1075: // Format state manipulate message ! 1076: // ! 1077: ! 1078: m.ApiNumber = DbgKdWriteBreakPointApi; ! 1079: m.ReturnStatus = STATUS_PENDING; ! 1080: a->BreakPointAddress = BreakPointAddress; ! 1081: ! 1082: // ! 1083: // Send the message and context and then wait for reply ! 1084: // ! 1085: ! 1086: do { ! 1087: DbgKdpWritePacket( ! 1088: &m, ! 1089: sizeof(m), ! 1090: PACKET_TYPE_KD_STATE_MANIPULATE, ! 1091: NULL, ! 1092: 0 ! 1093: ); ! 1094: ! 1095: rc = DbgKdpWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply); ! 1096: } while (rc == FALSE); ! 1097: ! 1098: // ! 1099: // If this is not a WriteBreakPoint response than protocol is screwed up. ! 1100: // assert that protocol is ok. ! 1101: // ! 1102: ! 1103: st = Reply->ReturnStatus; ! 1104: assert(Reply->ApiNumber == DbgKdWriteBreakPointApi); ! 1105: ! 1106: // ! 1107: // Reset message address to reply. ! 1108: // ! 1109: ! 1110: a = &Reply->u.WriteBreakPoint; ! 1111: st = Reply->ReturnStatus; ! 1112: *BreakPointHandle = a->BreakPointHandle; ! 1113: ! 1114: return st; ! 1115: } ! 1116: ! 1117: DWORD ! 1118: DbgKdRestoreBreakPoint( ! 1119: IN ULONG BreakPointHandle ! 1120: ) ! 1121: ! 1122: /*++ ! 1123: ! 1124: Routine Description: ! 1125: ! 1126: This function is used to restore a breakpoint to its original ! 1127: value. ! 1128: ! 1129: Arguments: ! 1130: ! 1131: BreakPointHandle - Supplies a handle returned by ! 1132: DbgKdWriteBreakPoint. This handle must refer to a valid ! 1133: address. The contents of the address must also be a breakpoint ! 1134: instruction. If both of these are true, then the original value ! 1135: at the breakpoint address is restored. ! 1136: ! 1137: Return Value: ! 1138: ! 1139: ERROR_SUCCESS - The specified breakpoint restore occured. ! 1140: ! 1141: !ERROR_SUCCESS - TBD ! 1142: ! 1143: --*/ ! 1144: ! 1145: { ! 1146: ! 1147: DBGKD_MANIPULATE_STATE m; ! 1148: PDBGKD_MANIPULATE_STATE Reply; ! 1149: PDBGKD_RESTORE_BREAKPOINT a = &m.u.RestoreBreakPoint; ! 1150: DWORD st; ! 1151: BOOLEAN rc; ! 1152: ! 1153: // ! 1154: // Format state manipulate message ! 1155: // ! 1156: ! 1157: m.ApiNumber = DbgKdRestoreBreakPointApi; ! 1158: m.ReturnStatus = STATUS_PENDING; ! 1159: a->BreakPointHandle = BreakPointHandle; ! 1160: ! 1161: // ! 1162: // Send the message and context and then wait for reply ! 1163: // ! 1164: ! 1165: do { ! 1166: DbgKdpWritePacket( ! 1167: &m, ! 1168: sizeof(m), ! 1169: PACKET_TYPE_KD_STATE_MANIPULATE, ! 1170: NULL, ! 1171: 0 ! 1172: ); ! 1173: ! 1174: rc = DbgKdpWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply); ! 1175: } while (rc == FALSE); ! 1176: ! 1177: // ! 1178: // If this is not a RestoreBreakPoint response than protocol is screwed up. ! 1179: // assert that protocol is ok. ! 1180: // ! 1181: ! 1182: st = Reply->ReturnStatus; ! 1183: assert(Reply->ApiNumber == DbgKdRestoreBreakPointApi); ! 1184: ! 1185: // ! 1186: // Reset message address to reply. ! 1187: // ! 1188: ! 1189: a = &Reply->u.RestoreBreakPoint; ! 1190: st = Reply->ReturnStatus; ! 1191: ! 1192: // ! 1193: // free the packet ! 1194: // ! 1195: ! 1196: return st; ! 1197: } ! 1198: ! 1199: DWORD ! 1200: DbgKdReadIoSpace( ! 1201: IN PVOID IoAddress, ! 1202: OUT PVOID ReturnedData, ! 1203: IN ULONG DataSize ! 1204: ) ! 1205: ! 1206: /*++ ! 1207: ! 1208: Routine Description: ! 1209: ! 1210: This function is used read a byte, short, or long (1,2,4 bytes) from ! 1211: the specified I/O address. ! 1212: ! 1213: Arguments: ! 1214: ! 1215: IoAddress - Supplies the Io address to read from. ! 1216: ! 1217: ReturnedData - Supplies the value read from the I/O address. ! 1218: ! 1219: DataSize - Supplies the size in bytes to read. Values of 1, 2, or ! 1220: 4 are accepted. ! 1221: ! 1222: Return Value: ! 1223: ! 1224: ERROR_SUCCESS - Data was successfully read from the I/O ! 1225: address. ! 1226: ! 1227: ERROR_INVALID_PARAMETER - A DataSize value other than 1,2, or 4 was ! 1228: specified. ! 1229: ! 1230: !ERROR_SUCCESS - TBD ! 1231: ! 1232: --*/ ! 1233: ! 1234: { ! 1235: ! 1236: DBGKD_MANIPULATE_STATE m; ! 1237: PDBGKD_MANIPULATE_STATE Reply; ! 1238: PDBGKD_READ_WRITE_IO a = &m.u.ReadWriteIo; ! 1239: DWORD st; ! 1240: BOOLEAN rc; ! 1241: ! 1242: switch ( DataSize ) { ! 1243: case 1: ! 1244: case 2: ! 1245: case 4: ! 1246: break; ! 1247: default: ! 1248: return ERROR_INVALID_PARAMETER; ! 1249: } ! 1250: ! 1251: // ! 1252: // Format state manipulate message ! 1253: // ! 1254: ! 1255: m.ApiNumber = DbgKdReadIoSpaceApi; ! 1256: m.ReturnStatus = STATUS_PENDING; ! 1257: ! 1258: a->DataSize = DataSize; ! 1259: a->IoAddress = IoAddress; ! 1260: ! 1261: // ! 1262: // Send the message and then wait for reply ! 1263: // ! 1264: ! 1265: do { ! 1266: DbgKdpWritePacket( ! 1267: &m, ! 1268: sizeof(m), ! 1269: PACKET_TYPE_KD_STATE_MANIPULATE, ! 1270: NULL, ! 1271: 0 ! 1272: ); ! 1273: ! 1274: rc = DbgKdpWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply); ! 1275: } while (rc == FALSE); ! 1276: ! 1277: // ! 1278: // If this is not a ReadIo response than protocol is screwed up. ! 1279: // assert that protocol is ok. ! 1280: // ! 1281: ! 1282: st = Reply->ReturnStatus; ! 1283: assert(Reply->ApiNumber == DbgKdReadIoSpaceApi); ! 1284: ! 1285: // ! 1286: // Reset message address to reply. ! 1287: // ! 1288: ! 1289: a = &Reply->u.ReadWriteIo; ! 1290: st = Reply->ReturnStatus; ! 1291: ! 1292: switch ( DataSize ) { ! 1293: case 1: ! 1294: *(PUCHAR)ReturnedData = (UCHAR)a->DataValue; ! 1295: break; ! 1296: case 2: ! 1297: *(PUSHORT)ReturnedData = (USHORT)a->DataValue; ! 1298: break; ! 1299: case 4: ! 1300: *(PULONG)ReturnedData = a->DataValue; ! 1301: break; ! 1302: } ! 1303: ! 1304: return st; ! 1305: } ! 1306: ! 1307: DWORD ! 1308: DbgKdWriteIoSpace( ! 1309: IN PVOID IoAddress, ! 1310: IN ULONG DataValue, ! 1311: IN ULONG DataSize ! 1312: ) ! 1313: ! 1314: /*++ ! 1315: ! 1316: Routine Description: ! 1317: ! 1318: This function is used write a byte, short, or long (1,2,4 bytes) to ! 1319: the specified I/O address. ! 1320: ! 1321: Arguments: ! 1322: ! 1323: IoAddress - Supplies the Io address to write to. ! 1324: ! 1325: DataValue - Supplies the value to write to the I/O address. ! 1326: ! 1327: DataSize - Supplies the size in bytes to write. Values of 1, 2, or ! 1328: 4 are accepted. ! 1329: ! 1330: Return Value: ! 1331: ! 1332: ERROR_SUCCESS - Data was successfully written to the I/O ! 1333: address. ! 1334: ! 1335: ERROR_INVALID_PARAMETER - A DataSize value other than 1,2, or 4 was ! 1336: specified. ! 1337: ! 1338: !ERROR_SUCCESS - TBD ! 1339: ! 1340: --*/ ! 1341: ! 1342: { ! 1343: ! 1344: DBGKD_MANIPULATE_STATE m; ! 1345: PDBGKD_MANIPULATE_STATE Reply; ! 1346: PDBGKD_READ_WRITE_IO a = &m.u.ReadWriteIo; ! 1347: DWORD st; ! 1348: BOOLEAN rc; ! 1349: ! 1350: switch ( DataSize ) { ! 1351: case 1: ! 1352: case 2: ! 1353: case 4: ! 1354: break; ! 1355: default: ! 1356: return ERROR_INVALID_PARAMETER; ! 1357: } ! 1358: ! 1359: // ! 1360: // Format state manipulate message ! 1361: // ! 1362: ! 1363: m.ApiNumber = DbgKdWriteIoSpaceApi; ! 1364: m.ReturnStatus = STATUS_PENDING; ! 1365: ! 1366: a->DataSize = DataSize; ! 1367: a->IoAddress = IoAddress; ! 1368: a->DataValue = DataValue; ! 1369: ! 1370: // ! 1371: // Send the message and then wait for reply ! 1372: // ! 1373: ! 1374: do { ! 1375: DbgKdpWritePacket( ! 1376: &m, ! 1377: sizeof(m), ! 1378: PACKET_TYPE_KD_STATE_MANIPULATE, ! 1379: NULL, ! 1380: 0 ! 1381: ); ! 1382: ! 1383: rc = DbgKdpWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply); ! 1384: } while (rc == FALSE); ! 1385: ! 1386: // ! 1387: // If this is not a WriteIo response than protocol is screwed up. ! 1388: // assert that protocol is ok. ! 1389: // ! 1390: ! 1391: st = Reply->ReturnStatus; ! 1392: assert(Reply->ApiNumber == DbgKdWriteIoSpaceApi); ! 1393: ! 1394: // ! 1395: // Reset message address to reply. ! 1396: // ! 1397: ! 1398: a = &Reply->u.ReadWriteIo; ! 1399: st = Reply->ReturnStatus; ! 1400: ! 1401: // ! 1402: // free the packet ! 1403: // ! 1404: ! 1405: return st; ! 1406: } ! 1407: ! 1408: ! 1409: VOID far ! 1410: DbgKdpKbdPollThread(VOID) ! 1411: { ! 1412: HANDLE StandardInputHandle; ! 1413: DWORD i; ! 1414: BOOLEAN rc; ! 1415: UCHAR c; ! 1416: ! 1417: // ! 1418: // Capture all typed input immediately so that control-c, ! 1419: // control-break, etc, get processed in a timely fashion. ! 1420: // Stuff the characters into an anonymous pipe, from which ! 1421: // DbgKdpGetConsole byte will read them. ! 1422: // ! 1423: // (WHAT??? A PIPE??? Very very simple way to get data flow ! 1424: // between two threads correctly synchronized, folks.) ! 1425: // ! 1426: ! 1427: StandardInputHandle = GetStdHandle(STD_INPUT_HANDLE); ! 1428: ! 1429: while (TRUE) { ! 1430: rc = ReadFile(StandardInputHandle,&c,1,&i,NULL); ! 1431: if ((rc != TRUE) || (i != 1)) { ! 1432: continue; ! 1433: } ! 1434: if (c == CONTROL_B) { ! 1435: exit(0); ! 1436: } else if (c == CONTROL_D) { ! 1437: chLastCommand[0] = '\0'; ! 1438: if (KdDebug) { ! 1439: KdDebug = FALSE; ! 1440: } else { ! 1441: KdDebug = TRUE; ! 1442: } ! 1443: continue; ! 1444: } else if (c == CONTROL_R) { ! 1445: KdResync = TRUE; ! 1446: chLastCommand[0] = '\0'; ! 1447: continue; ! 1448: } ! 1449: rc = WriteFile(PipeWrite, &c, 1, &i, NULL); ! 1450: if ((rc != TRUE) || (i != 1)) { ! 1451: continue; ! 1452: } ! 1453: // FlushFileBuffers(PipeWrite); ! 1454: } ! 1455: } ! 1456: ! 1457: BOOL ! 1458: DbgKdpGetConsoleByte( ! 1459: PVOID pBuf, ! 1460: DWORD cbBuf, ! 1461: LPDWORD pcbBytesRead ! 1462: ) ! 1463: { ! 1464: return ReadFile(PipeRead,pBuf,cbBuf,pcbBytesRead,NULL); ! 1465: } ! 1466: ! 1467: PUCHAR ! 1468: DbgKdGets( ! 1469: PUCHAR Buffer, ! 1470: USHORT Length ! 1471: ) ! 1472: { ! 1473: DWORD i; ! 1474: BOOLEAN rc; ! 1475: USHORT j; ! 1476: UCHAR c; ! 1477: ! 1478: for (j = 0; (j+1) < Length; j++) { ! 1479: ! 1480: rc = DbgKdpGetConsoleByte(&c, 1, &i); ! 1481: ! 1482: if ((rc != TRUE) || (i != 1)) { ! 1483: } ! 1484: ! 1485: if (c == '\n') { ! 1486: Buffer[j] = '\n'; ! 1487: Buffer[j+1] = '\0'; ! 1488: return Buffer; ! 1489: } ! 1490: ! 1491: Buffer[j] = c; ! 1492: ! 1493: } ! 1494: Buffer[j-1] = '\0'; ! 1495: return Buffer; ! 1496: } ! 1497: ! 1498: ! 1499: ! 1500: DWORD ! 1501: DbgKdReboot( ! 1502: VOID ! 1503: ) ! 1504: ! 1505: /*++ ! 1506: ! 1507: Routine Description: ! 1508: ! 1509: This function reboots being debugged. ! 1510: ! 1511: Arguments: ! 1512: ! 1513: None. ! 1514: ! 1515: Return Value: ! 1516: ! 1517: None. ! 1518: ! 1519: --*/ ! 1520: ! 1521: { ! 1522: DBGKD_MANIPULATE_STATE m; ! 1523: ! 1524: // ! 1525: // Format state manipulate message ! 1526: // ! 1527: ! 1528: m.ApiNumber = DbgKdRebootApi; ! 1529: m.ReturnStatus = STATUS_PENDING; ! 1530: ! 1531: // ! 1532: // Send the message. ! 1533: // ! 1534: ! 1535: DbgKdpWritePacket(&m,sizeof(m),PACKET_TYPE_KD_STATE_MANIPULATE,NULL,0); ! 1536: ! 1537: return ERROR_SUCCESS; ! 1538: } ! 1539: ! 1540: ! 1541: DWORD ! 1542: DbgKdReadPhysicalMemory( ! 1543: IN PHYSICAL_ADDRESS TargetBaseAddress, ! 1544: OUT PVOID UserInterfaceBuffer, ! 1545: IN ULONG TransferCount, ! 1546: OUT PULONG ActualBytesRead OPTIONAL ! 1547: ) ! 1548: ! 1549: /*++ ! 1550: ! 1551: Routine Description: ! 1552: ! 1553: This function reads the specified data from the physical memory of ! 1554: the system being debugged. ! 1555: ! 1556: Arguments: ! 1557: ! 1558: TargetBaseAddress - Supplies the physical address of the memory to read ! 1559: from the system being debugged. ! 1560: ! 1561: UserInterfaceBuffer - Supplies the address of the buffer in the user ! 1562: interface that data read is to be placed. ! 1563: ! 1564: TransferCount - Specifies the number of bytes to read. ! 1565: ! 1566: ActualBytesRead - An optional parameter that if supplied, returns ! 1567: the number of bytes actually read. ! 1568: ! 1569: Return Value: ! 1570: ! 1571: ERROR_SUCCESS - The specified read occured. ! 1572: ! 1573: ERROR_MORE_DATA - A read that is too large was specified. ! 1574: ! 1575: ERROR_NO_ACCESS - TBD // Can you even HAVE an access ! 1576: // violation with a physical ! 1577: // memory access?? ! 1578: ! 1579: !ERROR_SUCCESS - TBD ! 1580: ! 1581: --*/ ! 1582: ! 1583: { ! 1584: DBGKD_MANIPULATE_STATE m; ! 1585: PDBGKD_MANIPULATE_STATE Reply; ! 1586: PDBGKD_READ_MEMORY a = &m.u.ReadMemory; ! 1587: DWORD st; ! 1588: BOOLEAN rc; ! 1589: ! 1590: if ( TransferCount + sizeof(m) > PACKET_MAX_SIZE ) { ! 1591: return ERROR_MORE_DATA; ! 1592: } ! 1593: ! 1594: // ! 1595: // Format state manipulate message ! 1596: // ! 1597: ! 1598: m.ApiNumber = DbgKdReadPhysicalMemoryApi; ! 1599: m.ReturnStatus = STATUS_PENDING; ! 1600: // ! 1601: // BUGBUG TargetBaseAddress should be >32 bits ! 1602: // ! 1603: a->TargetBaseAddress = (PVOID)TargetBaseAddress.LowPart; ! 1604: a->TransferCount = TransferCount; ! 1605: a->ActualBytesRead = 0L; ! 1606: ! 1607: // ! 1608: // Send the message and then wait for reply ! 1609: // ! 1610: ! 1611: do { ! 1612: DbgKdpWritePacket(&m,sizeof(m),PACKET_TYPE_KD_STATE_MANIPULATE,NULL,0); ! 1613: ! 1614: rc = DbgKdpWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply); ! 1615: } while (rc == FALSE); ! 1616: ! 1617: // ! 1618: // If this is not a ReadMemory response then protocol is screwed up. ! 1619: // assert that protocol is ok. ! 1620: // ! 1621: ! 1622: st = Reply->ReturnStatus; ! 1623: assert(Reply->ApiNumber == DbgKdReadPhysicalMemoryApi); ! 1624: ! 1625: // ! 1626: // Reset message address to reply. ! 1627: // ! 1628: ! 1629: a = &Reply->u.ReadMemory; ! 1630: assert(a->ActualBytesRead <= TransferCount); ! 1631: ! 1632: // ! 1633: // Return actual bytes read, and then transfer the bytes ! 1634: // ! 1635: ! 1636: if (ActualBytesRead) { ! 1637: *ActualBytesRead = a->ActualBytesRead; ! 1638: } ! 1639: st = Reply->ReturnStatus; ! 1640: ! 1641: // ! 1642: // Since read response data follows message, Reply+1 should point ! 1643: // at the data ! 1644: // ! 1645: ! 1646: memcpy(UserInterfaceBuffer, Reply+1, (int)a->ActualBytesRead); ! 1647: ! 1648: return st; ! 1649: } ! 1650: ! 1651: ! 1652: DWORD ! 1653: DbgKdWritePhysicalMemory( ! 1654: IN PHYSICAL_ADDRESS TargetBaseAddress, ! 1655: OUT PVOID UserInterfaceBuffer, ! 1656: IN ULONG TransferCount, ! 1657: OUT PULONG ActualBytesWritten OPTIONAL ! 1658: ) ! 1659: ! 1660: /*++ ! 1661: ! 1662: Routine Description: ! 1663: ! 1664: This function writes the specified data to the physical memory of the ! 1665: system being debugged. ! 1666: ! 1667: Arguments: ! 1668: ! 1669: TargetBaseAddress - Supplies the physical address of the memory to write ! 1670: to the system being debugged. ! 1671: ! 1672: UserInterfaceBuffer - Supplies the address of the buffer in the user ! 1673: interface that contains the data to be written. ! 1674: ! 1675: TransferCount - Specifies the number of bytes to write. ! 1676: ! 1677: ActualBytesWritten - An optional parameter that if supplied, returns ! 1678: the number of bytes actually written. ! 1679: ! 1680: Return Value: ! 1681: ! 1682: ERROR_SUCCESS - The specified read occured. ! 1683: ! 1684: ERROR_MORE_DATA - A read that is to large was specified. ! 1685: ! 1686: ERROR_NO_ACCESS - TBD // Can you even HAVE an access ! 1687: // violation with a physical ! 1688: // memory access?? ! 1689: ! 1690: !ERROR_SUCCESS - TBD ! 1691: ! 1692: --*/ ! 1693: ! 1694: { ! 1695: DBGKD_MANIPULATE_STATE m; ! 1696: PDBGKD_MANIPULATE_STATE Reply; ! 1697: PDBGKD_WRITE_MEMORY a = &m.u.WriteMemory; ! 1698: DWORD st; ! 1699: BOOLEAN rc; ! 1700: ! 1701: if ( TransferCount + sizeof(m) > PACKET_MAX_SIZE ) { ! 1702: return ERROR_MORE_DATA; ! 1703: } ! 1704: ! 1705: // ! 1706: // Format state manipulate message ! 1707: // ! 1708: ! 1709: m.ApiNumber = DbgKdWritePhysicalMemoryApi; ! 1710: m.ReturnStatus = STATUS_PENDING; ! 1711: // ! 1712: // BUGBUG TargetBaseAddress should be >32 bits ! 1713: // ! 1714: a->TargetBaseAddress = (PVOID)TargetBaseAddress.LowPart; ! 1715: a->TransferCount = TransferCount; ! 1716: a->ActualBytesWritten = 0L; ! 1717: ! 1718: // ! 1719: // Send the message and data to write and then wait for reply ! 1720: // ! 1721: ! 1722: do { ! 1723: DbgKdpWritePacket( ! 1724: &m, ! 1725: sizeof(m), ! 1726: PACKET_TYPE_KD_STATE_MANIPULATE, ! 1727: UserInterfaceBuffer, ! 1728: (USHORT)TransferCount ! 1729: ); ! 1730: ! 1731: rc = DbgKdpWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply); ! 1732: } while (rc == FALSE); ! 1733: ! 1734: // ! 1735: // If this is not a WriteMemory response than protocol is screwed up. ! 1736: // assert that protocol is ok. ! 1737: // ! 1738: ! 1739: st = Reply->ReturnStatus; ! 1740: assert(Reply->ApiNumber == DbgKdWritePhysicalMemoryApi); ! 1741: ! 1742: // ! 1743: // Reset message address to reply. ! 1744: // ! 1745: ! 1746: a = &Reply->u.WriteMemory; ! 1747: assert(a->ActualBytesWritten <= TransferCount); ! 1748: ! 1749: // ! 1750: // Return actual bytes written ! 1751: // ! 1752: ! 1753: if (ActualBytesWritten) { ! 1754: *ActualBytesWritten = a->ActualBytesWritten; ! 1755: } ! 1756: st = Reply->ReturnStatus; ! 1757: ! 1758: return st; ! 1759: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.