📄 kdctrl.c
字号:
/*++
Copyright (c) 1990-2000 Microsoft Corporation. All rights reserved.
Module Name:
kdctrl.c
Abstract:
This module implements CPU specific remote debug APIs.
Environment:
WinCE
--*/
#include "kdp.h"
#if defined(x86)
int __cdecl _inp(unsigned short);
int __cdecl _outp(unsigned short, int);
unsigned short __cdecl _inpw(unsigned short);
unsigned short __cdecl _outpw(unsigned short, unsigned short);
unsigned long __cdecl _inpd(unsigned short);
unsigned long __cdecl _outpd(unsigned short, unsigned long);
#pragma intrinsic(_inp, _inpw, _inpd, _outp, _outpw, _outpd)
extern PTHREAD g_CurFPUOwner;
#endif
extern BOOLEAN KdpSendContext;
extern PROCESS *kdProcArray;
extern ROMHDR * const pTOC;
extern PCALLSTACK pStk;
extern PPROCESS pLastProc;
extern PTHREAD pWalkThread;
//void NKOtherPrintfA(char *szFormat, ...);
BOOLEAN bGlobalBreakPoint;
BOOL fThreadWalk;
DWORD ReloadAllSymbols(LPBYTE lpBuffer, BOOL fDoCopy);
#if defined(MIPS) || defined(x86) || defined(PPC)
void CpuContextToContext(CONTEXT *pCtx, CPUCONTEXT *pCpuCtx);
#endif
//BOOL GetNameandImageBase(PPROCESS pProc, DWORD dwAddress, PNAMEANDBASE pnb, BOOL fRedundant);
VOID
KdpSetLoadState (
IN PDBGKD_WAIT_STATE_CHANGE WaitStateChange,
IN PCONTEXT ContextRecord
)
/*++
Routine Description:
Fill in the Wait_State_Change message record for the load symbol case.
Arguments:
WaitStateChange - Supplies pointer to record to fill in
ContextRecord - Supplies a pointer to a context record.
Return Value:
None.
--*/
{
//
// Copy context record
//
WaitStateChange->Context = *ContextRecord;
return;
}
VOID
KdpSetStateChange (
IN PDBGKD_WAIT_STATE_CHANGE WaitStateChange,
IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT ContextRecord,
IN BOOLEAN SecondChance
)
/*++
Routine Description:
Fill in the Wait_State_Change message record.
Arguments:
WaitStateChange - Supplies pointer to record to fill in
ExceptionRecord - Supplies a pointer to an exception record.
ContextRecord - Supplies a pointer to a context record.
SecondChance - Supplies a boolean value that determines whether this is
the first or second chance for the exception.
Return Value:
None.
--*/
{
ULONG Index;
ULONG Offset;
PVOID Lower;
PVOID Upper;
#if defined(MIPS16SUPPORT) || defined(THUMBSUPPORT)
KDP_BREAKPOINT_TYPE Instruction;
ULONG Length;
#endif
//
// Set up description of event, including exception record
//
WaitStateChange->NewState = DbgKdExceptionStateChange;
WaitStateChange->ProcessorType = 0;
WaitStateChange->Processor = (USHORT)0;
WaitStateChange->NumberProcessors = (ULONG)1;
WaitStateChange->Thread = (PVOID)hCurThread;
WaitStateChange->ProgramCounter = (PVOID)CONTEXT_TO_PROGRAM_COUNTER(ContextRecord);
KdpQuickMoveMemory(
(PCHAR)&WaitStateChange->u.Exception.ExceptionRecord,
(PCHAR)ExceptionRecord,
sizeof(EXCEPTION_RECORD)
);
WaitStateChange->u.Exception.FirstChance = !SecondChance;
//
// Copy instruction stream immediately following location of event
//
WaitStateChange->ControlReport.InstructionCount =
(WORD)KdpMoveMemory(
&(WaitStateChange->ControlReport.InstructionStream[0]),
WaitStateChange->ProgramCounter,
DBGKD_MAXSTREAM
);
#if defined(SH3)
ContextRecord->DebugRegisters.BarA = READ_REGISTER_ULONG(UBCBarA);
ContextRecord->DebugRegisters.BasrA = READ_REGISTER_UCHAR(UBCBasrA);
ContextRecord->DebugRegisters.BamrA = READ_REGISTER_UCHAR(UBCBamrA);
ContextRecord->DebugRegisters.BbrA = READ_REGISTER_USHORT(UBCBbrA);
ContextRecord->DebugRegisters.BarB = READ_REGISTER_ULONG(UBCBarB);
ContextRecord->DebugRegisters.BasrB = READ_REGISTER_UCHAR(UBCBasrB);
ContextRecord->DebugRegisters.BamrB = READ_REGISTER_UCHAR(UBCBamrB);
ContextRecord->DebugRegisters.BbrB = READ_REGISTER_USHORT(UBCBbrB);
ContextRecord->DebugRegisters.BdrB = READ_REGISTER_ULONG(UBCBdrB);
ContextRecord->DebugRegisters.BdmrB = READ_REGISTER_ULONG(UBCBdmrB);
ContextRecord->DebugRegisters.Brcr = READ_REGISTER_USHORT(UBCBrcr);
ContextRecord->DebugRegisters.Align = 0;
#elif defined(SH3e) || defined(SH4)
WaitStateChange->DebugRegisters.BarA = READ_REGISTER_ULONG(UBCBarA);
WaitStateChange->DebugRegisters.BasrA = READ_REGISTER_UCHAR(UBCBasrA);
WaitStateChange->DebugRegisters.BamrA = READ_REGISTER_UCHAR(UBCBamrA);
WaitStateChange->DebugRegisters.BbrA = READ_REGISTER_USHORT(UBCBbrA);
WaitStateChange->DebugRegisters.BarB = READ_REGISTER_ULONG(UBCBarB);
WaitStateChange->DebugRegisters.BasrB = READ_REGISTER_UCHAR(UBCBasrB);
WaitStateChange->DebugRegisters.BamrB = READ_REGISTER_UCHAR(UBCBamrB);
WaitStateChange->DebugRegisters.BbrB = READ_REGISTER_USHORT(UBCBbrB);
WaitStateChange->DebugRegisters.BdrB = READ_REGISTER_ULONG(UBCBdrB);
WaitStateChange->DebugRegisters.BdmrB = READ_REGISTER_ULONG(UBCBdmrB);
WaitStateChange->DebugRegisters.Brcr = READ_REGISTER_USHORT(UBCBrcr);
WaitStateChange->DebugRegisters.Align = 0;
#endif
#if defined(x86)
if (g_CurFPUOwner)
{
KCall((LPVOID)FPUFlushContext,0,0,0);
ContextRecord->FloatSave = *(PTH_TO_FLTSAVEAREAPTR(pCurThread));
}
#endif
//
// Copy context record immediately following instruction stream
//
WaitStateChange->Context = *ContextRecord;
//
// Examine each entry in the table in turn
//
for (Index = 0; Index < BREAKPOINT_TABLE_SIZE; Index++) {
Lower = WaitStateChange->ProgramCounter;
Upper = (PVOID)((PUCHAR)WaitStateChange->ProgramCounter +
WaitStateChange->ControlReport.InstructionCount - 1);
if ( (KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_IN_USE) &&
((KdpBreakpointTable[Index].Address >= Lower) &&
(KdpBreakpointTable[Index].Address <= Upper))
) {
//
// Breakpoint is in use and falls in range, restore original
// code in WaitStateChange InstructionStream
//
#if defined(MIPS16SUPPORT) || defined(THUMBSUPPORT)
if (KdpBreakpointTable[Index].Flags & KD_BREAKPOINT_16BIT) {
Instruction = KDP_BREAKPOINT_16BIT_VALUE;
Length = sizeof(KDP_BREAKPOINT_16BIT_TYPE);
} else {
Instruction = KDP_BREAKPOINT_32BIT_VALUE;
Length = sizeof(KDP_BREAKPOINT_32BIT_TYPE);
}
if (KdpBreakpointTable[Index].Content != Instruction) {
Offset = (ULONG)KdpBreakpointTable[Index].Address -
(ULONG)Lower;
KdpMoveMemory(
&(WaitStateChange->ControlReport.InstructionStream[0])
+ Offset,
(PCHAR)&KdpBreakpointTable[Index].Content,
Length
);
}
#else
if (KdpBreakpointTable[Index].Content != KdpBreakpointInstruction) {
Offset = (ULONG)KdpBreakpointTable[Index].Address -
(ULONG)Lower;
KdpMoveMemory(
&(WaitStateChange->ControlReport.InstructionStream[0])
+ Offset,
(PCHAR)&KdpBreakpointTable[Index].Content,
sizeof(KDP_BREAKPOINT_TYPE)
);
}
#endif
}
}
#if defined(x86)
WaitStateChange->ControlReport.Dr6 = ContextRecord->Dr6;
WaitStateChange->ControlReport.Dr7 = ContextRecord->Dr7;
WaitStateChange->ControlReport.SegCs = (WORD)ContextRecord->SegCs;
WaitStateChange->ControlReport.SegDs = (WORD)ContextRecord->SegDs;
WaitStateChange->ControlReport.SegEs = (WORD)ContextRecord->SegEs;
WaitStateChange->ControlReport.SegFs = (WORD)ContextRecord->SegFs;
WaitStateChange->ControlReport.EFlags = ContextRecord->EFlags;
WaitStateChange->ControlReport.ReportFlags = REPORT_INCLUDES_SEGS;
#endif
}
VOID
KdpGetStateChange (
IN PDBGKD_MANIPULATE_STATE ManipulateState,
IN PCONTEXT ContextRecord
)
/*++
Routine Description:
Extract continuation control data from Manipulate_State message
N.B. This is a noop for MIPS.
Arguments:
ManipulateState - supplies pointer to Manipulate_State packet
ContextRecord - Supplies a pointer to a context record.
Return Value:
None.
--*/
{
#if defined(x86)
PDBGKD_CONTROL_SET pControlSet;
pControlSet = &ManipulateState->u.Continue2.ControlSet;
if (pControlSet->TraceFlag)
{
ContextRecord->EFlags |= 0x00000100; // TF
}
else
{
ContextRecord->EFlags &= ~0x00000100; // TF
}
ContextRecord->Dr6 = 0;
ContextRecord->Dr7 = pControlSet->Dr7;
#endif
}
BOOL CheckIfPThreadExists (PTHREAD pThreadToValidate)
{
DWORD dwProcessIdx;
PTHREAD pThread;
for (dwProcessIdx = 0; dwProcessIdx < MAX_PROCESSES; dwProcessIdx++)
{ // For each process:
if (kdProcArray [dwProcessIdx].dwVMBase)
{ // Only if VM Base Addr of process is valid (not null):
for (pThread = kdProcArray [dwProcessIdx].pTh; // Get process main thread
pThread;
pThread = pThread->pNextInProc) // Next thread
{ // walk list of threads attached to process (until we reach the end of the list or we found the matching pThread)
if (pThreadToValidate == pThread) return TRUE;
}
}
}
return FALSE;
}
// Prevent HIGHADJ/LOW/LOW fixup problem
#if defined(PPC)
#pragma optimize("", off)
#endif
VOID
KdpReadControlSpace (
IN PDBGKD_MANIPULATE_STATE m,
IN PSTRING AdditionalData,
IN PCONTEXT Context
)
/*++
Routine Description:
This function is called in response of a read control space state
manipulation message. Its function is to read implementation
specific system data.
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;
STRING MessageHeader;
ULONG Process;
ULONG NextOffset;
DWORD dwReturnAddr;
DWORD dwFrameTop = 0;
PCALLSTACK pStackTemp;
MessageHeader.Length = sizeof(*m);
MessageHeader.Buffer = (PCHAR)m;
m->ReturnStatus = STATUS_UNSUCCESSFUL; // By default (shorter and safer)
//
// TargetBaseAddress field is being used as the ControlSpace request id
//
switch((ULONG)a->TargetBaseAddress) {
case HANDLE_PROCESS_THREAD_INFO_REQ: // Replacing HANDLE_PROCESS_INFO_REQUEST
GetProcessAndThreadInfo (AdditionalData);
m->ReturnStatus = STATUS_SUCCESS; // the return status is in the message itself
break;
case HANDLE_PROCESS_INFO_REQUEST: // To be replaced by HANDLE_PROCESS_THREAD_INFO_REQ later (when no debugger using it is left)
if (AdditionalData->Length > 0) {
//
// The request is for information on a specific process
//
Process = SH3strtoul(AdditionalData->Buffer, 16);
AdditionalData->Length =
(USHORT)GetSpecificProcessInfo((PPROCESS)Process,
AdditionalData->Buffer,
a->TransferCount);
}
else {
//
// Get process table...(truncation OK -> USHORT always 2 bytes)
//
AdditionalData->Length = (USHORT)GetProcessInfo((PBYTE)AdditionalData->Buffer, a->TransferCount);
}
m->ReturnStatus = STATUS_SUCCESS;
break;
case HANDLE_GET_NEXT_OFFSET_REQUEST:
if (AdditionalData->Length != sizeof(ULONG)) {
AdditionalData->Length = 0;
break; // Unsucessful
}
memcpy((PVOID)&NextOffset, (PVOID)AdditionalData->Buffer, sizeof(ULONG));
if (!TranslateAddress(&NextOffset)) {
AdditionalData->Length = 0;
break; // Unsucessful
}
memcpy((PVOID)AdditionalData->Buffer, (PVOID)&NextOffset, sizeof(ULONG));
m->ReturnStatus = STATUS_SUCCESS;
AdditionalData->Length = sizeof(ULONG);
break;
case HANDLE_STACKWALK_REQUEST:
//
// The request is to translate a stack address
//
DEBUGGERMSG(KDZONE_STACKW, (L"+++ Read HANDLE_STACKWALK_REQUEST\r\n"));
if ((AdditionalData->Length != sizeof(DWORD)) && (AdditionalData->Length != (sizeof(DWORD)*2)))
{
DEBUGGERMSG(KDZONE_STACKW, (L"Bad AdditionalData Length = %i\r\n--- Read HANDLE_STACKWALK_REQUEST\r\n", AdditionalData->Length));
AdditionalData->Length = 0;
break; // Unsucessful
}
memcpy((PVOID)&dwReturnAddr, (PVOID)AdditionalData->Buffer, sizeof(DWORD));
if (AdditionalData->Length == (sizeof(DWORD)*2))
{
memcpy((PVOID)&dwFrameTop, (PVOID)(AdditionalData->Buffer+sizeof(DWORD)), sizeof(DWORD));
}
else
{
dwFrameTop = 0;
}
DEBUGGERMSG(KDZONE_STACKW, (TEXT("RCS: StalkWalk: Additional Length=%8.8lx - dwReturnAddr passed in = %8.8lx - dwFrameTop = %8.8lx \r\n"), AdditionalData->Length, dwReturnAddr, dwFrameTop));
if (!TranslateRA(&dwReturnAddr, pWalkThread, dwFrameTop)) {
DEBUGGERMSG( KDZONE_CTRL, (TEXT("**** RCS: StalkWalk: TranslateRA **** FAILED **** on pWalkThread=%08X RA=%08X FP=%08X\r\n"), pWalkThread, dwReturnAddr, dwFrameTop));
AdditionalData->Length = 0;
DEBUGGERMSG(KDZONE_STACKW, (L"--- Read HANDLE_STACKWALK_REQUEST\r\n"));
break; // Unsucessful
}
DEBUGGERMSG(KDZONE_STACKW, (TEXT("RCS: StalkWalk: pStk=%8.8lx dwReturnAddr=%8.8lx dwFrameTop=%8.8lx pWalkThread=%8.8lx\r\n"), pStk, dwReturnAddr, dwFrameTop, pWalkThread));
memcpy((PVOID)AdditionalData->Buffer, (PVOID)&dwReturnAddr, sizeof(ULONG));
m->ReturnStatus = STATUS_SUCCESS;
AdditionalData->Length = sizeof(DWORD);
DEBUGGERMSG(KDZONE_STACKW, (L"--- Read HANDLE_STACKWALK_REQUEST\r\n"));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -