📄 kdapi.c
字号:
BOOLEANKdpReportLoadSymbolsStateChange ( IN PSTRING PathName, IN PKD_SYMBOLS_INFO SymbolInfo, IN BOOLEAN UnloadSymbols, IN OUT CONTEXT * ContextRecord )/*++Routine Description: This routine sends a load symbols state change packet to the kernel debugger and waits for a manipulate state message.Arguments: PathName - Supplies a pointer to the pathname of the image whose symbols are to be loaded. BaseOfDll - Supplies the base address where the image was loaded. ProcessId - Unique 32-bit identifier for process that is using the symbols. -1 for system process. CheckSum - Unique 32-bit identifier from image header. UnloadSymbol - TRUE if the symbols that were previously loaded for the named image are to be unloaded from the debugger.Return Value: A value of TRUE is returned if the exception is handled. Otherwise, a value of FALSE is returned.--*/{ PSTRING AdditionalData; STRING MessageData; STRING MessageHeader; DBGKD_WAIT_STATE_CHANGE WaitStateChange; KCONTINUE_STATUS Status; if ((KdpUseTCPSockets || KdpUseUDPSockets) && socketReady[0] == '1') { if (packetsIndex) SendSavedPackets(); } do { // // Construct the wait state change message and message descriptor. // WaitStateChange.NewState = DbgKdLoadSymbolsStateChange; WaitStateChange.ProcessorType = 0; WaitStateChange.Processor = (USHORT)0; WaitStateChange.NumberProcessors = (ULONG)1; WaitStateChange.Thread = pCurThread; WaitStateChange.ProgramCounter = (PVOID)CONTEXT_TO_PROGRAM_COUNTER(ContextRecord); KdpSetLoadState(&WaitStateChange, ContextRecord); WaitStateChange.u.LoadSymbols.UnloadSymbols = UnloadSymbols; WaitStateChange.u.LoadSymbols.BaseOfDll = SymbolInfo->BaseOfDll; WaitStateChange.u.LoadSymbols.ProcessId = SymbolInfo->ProcessId; WaitStateChange.u.LoadSymbols.CheckSum = SymbolInfo->CheckSum; WaitStateChange.u.LoadSymbols.SizeOfImage = SymbolInfo->SizeOfImage; if (ARGUMENT_PRESENT( PathName )) { WaitStateChange.u.LoadSymbols.PathNameLength = KdpMoveMemory( (PCHAR)KdpMessageBuffer, (PCHAR)PathName->Buffer, PathName->Length ) + 1; MessageData.Buffer = KdpMessageBuffer; MessageData.Length = (USHORT)WaitStateChange.u.LoadSymbols.PathNameLength; MessageData.Buffer[MessageData.Length-1] = '\0'; AdditionalData = &MessageData; } else { WaitStateChange.u.LoadSymbols.PathNameLength = 0; AdditionalData = NULL; } MessageHeader.Length = sizeof(DBGKD_WAIT_STATE_CHANGE); MessageHeader.Buffer = (PCHAR)&WaitStateChange; // // Send packet to the kernel debugger on the host machine, wait // for the reply. // DEBUGGERMSG(KDZONE_API, (L"Updating symbols for %a %8.8lx %8.8lx\r\n", PathName->Buffer, WaitStateChange.u.LoadSymbols.BaseOfDll, WaitStateChange.u.LoadSymbols.SizeOfImage)); if (!KdpUseTCPSockets && !KdpUseUDPSockets) { Status = KdpSendWaitContinue( PACKET_TYPE_KD_STATE_CHANGE, &MessageHeader, AdditionalData, ContextRecord ); } else { if (socketReady[0] == '1') { // The socket transport is ready. Send packet. Status = KdpSendWaitContinue( PACKET_TYPE_KD_STATE_CHANGE, &MessageHeader, AdditionalData, ContextRecord ); } else { // The socket transport is not ready. Save packet. memcpy(&SavedPackets[packetsIndex%MAX_LOAD_NOTIFICATIONS].StateChange, &WaitStateChange, sizeof(DBGKD_WAIT_STATE_CHANGE)); if (AdditionalData) { SavedPackets[packetsIndex%MAX_LOAD_NOTIFICATIONS].AdditionalDataLength = MessageData.Length; strncpy(SavedPackets[packetsIndex%MAX_LOAD_NOTIFICATIONS].AdditionalData, MessageData.Buffer, MessageData.Length); } else SavedPackets[packetsIndex%MAX_LOAD_NOTIFICATIONS].AdditionalDataLength = 0; packetsIndex++; return (BOOLEAN) ContinueSuccess; } } } while (Status == ContinueProcessorReselected); return (BOOLEAN) Status;}VOIDKdpReadPhysicalMemory( IN PDBGKD_MANIPULATE_STATE m, IN PSTRING AdditionalData, IN CONTEXT * Context )/*++Routine Description: This function is called in response to a read physical memory state manipulation message. Its function is to read physical memory and return.Arguments: m - Supplies the state manipulation message. AdditionalData - Supplies any additional data for the message. Context - Supplies the current context.Return Value: None.--*/{ PDBGKD_READ_MEMORY a = &m->u.ReadMemory; ULONG Length; STRING MessageHeader; PVOID VirtualAddress; PHYSICAL_ADDRESS Source; PUCHAR Destination; USHORT NumberBytes; USHORT BytesLeft; MessageHeader.Length = sizeof(*m); MessageHeader.Buffer = (PCHAR)m; // // make sure that nothing but a read memory message was transmitted // KD_ASSERT(AdditionalData->Length == 0); // // Trim transfer count to fit in a single message // if (a->TransferCount > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE))) { Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE); } else { Length = a->TransferCount; } // // Since the MmDbgTranslatePhysicalAddress only maps in one physical // page at a time, we need to break the memory move up into smaller // moves which don't cross page boundaries. There are two cases we // need to deal with. The area to be moved may start and end on the // same page, or it may start and end on different pages (with an // arbitrary number of pages in between) // Source = (ULONG)a->TargetBaseAddress; Destination = AdditionalData->Buffer; BytesLeft = (USHORT)Length; if(PAGE_ALIGN((PUCHAR)a->TargetBaseAddress) == PAGE_ALIGN((PUCHAR)(a->TargetBaseAddress)+Length)) { // // Memory move starts and ends on the same page. // VirtualAddress = (PVOID)MmDbgTranslatePhysicalAddress(Source); AdditionalData->Length = (USHORT)KdpMoveMemory( Destination, VirtualAddress, BytesLeft ); BytesLeft -= AdditionalData->Length; } else { // // Memory move spans page boundaries // VirtualAddress = (PVOID)MmDbgTranslatePhysicalAddress(Source); NumberBytes = (USHORT)(PAGE_SIZE - BYTE_OFFSET(VirtualAddress)); AdditionalData->Length = (USHORT)KdpMoveMemory( Destination, VirtualAddress, NumberBytes ); Source += NumberBytes; Destination += NumberBytes; BytesLeft -= NumberBytes; while(BytesLeft > 0) { // // Transfer a full page or the last bit, // whichever is smaller. // VirtualAddress = (PVOID)MmDbgTranslatePhysicalAddress(Source); NumberBytes = (USHORT) ((PAGE_SIZE < BytesLeft) ? PAGE_SIZE : BytesLeft); AdditionalData->Length += (USHORT)KdpMoveMemory( Destination, VirtualAddress, NumberBytes ); Source += NumberBytes; Destination += NumberBytes; BytesLeft -= NumberBytes; } } if (Length == AdditionalData->Length) { m->ReturnStatus = STATUS_SUCCESS; } else { m->ReturnStatus = STATUS_UNSUCCESSFUL; } a->ActualBytesRead = AdditionalData->Length; KdpSendPacket( PACKET_TYPE_KD_STATE_MANIPULATE, &MessageHeader, AdditionalData ); UNREFERENCED_PARAMETER(Context);}VOIDKdpWritePhysicalMemory( IN PDBGKD_MANIPULATE_STATE m, IN PSTRING AdditionalData, IN CONTEXT * Context )/*++Routine Description: This function is called in response to a write physical memory state manipulation message. Its function is to write physical memory and return.Arguments: m - Supplies the state manipulation message. AdditionalData - Supplies any additional data for the message. Context - Supplies the current context.Return Value: None.--*/{ PDBGKD_WRITE_MEMORY a = &m->u.WriteMemory; ULONG Length; STRING MessageHeader; PVOID VirtualAddress; PHYSICAL_ADDRESS Destination; PUCHAR Source; USHORT NumberBytes; USHORT BytesLeft; MessageHeader.Length = sizeof(*m); MessageHeader.Buffer = (PCHAR)m; // // Since the MmDbgTranslatePhysicalAddress only maps in one physical // page at a time, we need to break the memory move up into smaller // moves which don't cross page boundaries. There are two cases we // need to deal with. The area to be moved may start and end on the // same page, or it may start and end on different pages (with an // arbitrary number of pages in between) // Destination = (ULONG)a->TargetBaseAddress; Source = AdditionalData->Buffer; BytesLeft = (USHORT) a->TransferCount; if(PAGE_ALIGN((PUCHAR)Destination) == PAGE_ALIGN((PUCHAR)(Destination)+BytesLeft)) { // // Memory move starts and ends on the same page. // VirtualAddress = (PVOID)MmDbgTranslatePhysicalAddress(Destination); Length = (USHORT)KdpMoveMemory( VirtualAddress, Source, BytesLeft ); BytesLeft -= (USHORT) Length; } else { // // Memory move spans page boundaries // VirtualAddress = (PVOID)MmDbgTranslatePhysicalAddress(Destination); NumberBytes = (USHORT) (PAGE_SIZE - BYTE_OFFSET(VirtualAddress)); Length = (USHORT)KdpMoveMemory( VirtualAddress, Source, NumberBytes ); Source += NumberBytes; Destination += NumberBytes; BytesLeft -= NumberBytes; while(BytesLeft > 0) { // // Transfer a full page or the last bit, // whichever is smaller. // VirtualAddress = (PVOID)MmDbgTranslatePhysicalAddress(Destination); NumberBytes = (USHORT) ((PAGE_SIZE < BytesLeft) ? PAGE_SIZE : BytesLeft); Length += (USHORT)KdpMoveMemory( VirtualAddress, Source, NumberBytes ); Source += NumberBytes; Destination += NumberBytes; BytesLeft -= NumberBytes; } } if (Length == AdditionalData->Length) { m->ReturnStatus = STATUS_SUCCESS; } else { m->ReturnStatus = STATUS_UNSUCCESSFUL; } a->ActualBytesWritten = Length; KdpSendPacket( PACKET_TYPE_KD_STATE_MANIPULATE, &MessageHeader, NULL ); UNREFERENCED_PARAMETER(Context);}const ULONG NtBuildNumber = VER_PRODUCTBUILD | 0xC0000000;typedef enum _TargetCodeType{ tcCeUnknown, tcCeSH3, tcCeSH4, tcCeMIPS, tcCeX86, tcCeARM, tcCePPC} TargetCodeType;#if defined(SH3)#define CURRENT_TARGET_CODE (tcCeSH3)#elif defined(SH4)#define CURRENT_TARGET_CODE (tcCeSH4)#elif defined(x86)#define CURRENT_TARGET_CODE (tcCeX86)#elif defined(PPC)#define CURRENT_TARGET_CODE (tcCePPC)#elif defined(MIPS)#define CURRENT_TARGET_CODE (tcCeMIPS)#elif defined(ARM)#define CURRENT_TARGET_CODE (tcCeARM)#else#define CURRENT_TARGET_CODE (tcCeUnknown)// warning if new cpu architecture is defined: please add new type in TargetCodeType (and in host kernel debugger side too)#endifVOIDKdpGetVersion( IN PDBGKD_MANIPULATE_STATE m )/*++Routine Description: This function returns to the caller a general information packet that contains useful information to a debugger. This packet is also used for a debugger to determine if the writebreakpointex and readbreakpointex apis are available.Arguments: m - Supplies the state manipulation message.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -