* FILE: ntoskrnl/kd64/kdapi.c
* PURPOSE: KD64 Public Routines and Internal Support
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
+ * Stefan Ginsberg (stefan.ginsberg@reactos.org)
*/
/* INCLUDES ******************************************************************/
VOID
NTAPI
-DumpTraceData(IN PSTRING TraceData)
+DumpTraceData(OUT PSTRING TraceData)
{
/* Update the buffer */
TraceDataBuffer[0] = TraceDataBufferPosition;
NTAPI
KdpSetCommonState(IN ULONG NewState,
IN PCONTEXT Context,
- IN PDBGKD_WAIT_STATE_CHANGE64 WaitStateChange)
+ IN PDBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange)
{
USHORT InstructionCount;
BOOLEAN HadBreakpoints;
WaitStateChange->Thread = (ULONG64)(LONG_PTR)KeGetCurrentThread();
WaitStateChange->ProgramCounter = (ULONG64)(LONG_PTR)KeGetContextPc(Context);
- /* Zero out the Control Report */
- RtlZeroMemory(&WaitStateChange->ControlReport,
- sizeof(DBGKD_CONTROL_REPORT));
+ /* Zero out the entire Control Report */
+ RtlZeroMemory(&WaitStateChange->AnyControlReport,
+ sizeof(DBGKD_ANY_CONTROL_REPORT));
/* Now copy the instruction stream and set the count */
RtlCopyMemory(&WaitStateChange->ControlReport.InstructionStream[0],
PDBGKD_READ_MEMORY64 ReadMemory = &State->u.ReadMemory;
STRING Header;
ULONG Length = ReadMemory->TransferCount;
+ ULONG64 TargetBaseAddress = State->u.ReadMemory.TargetBaseAddress;
/* Setup the header */
Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
else
{
/* SMP not yet handled */
- KdpDprintf("SMP UNHANDLED\n");
+ KdpDprintf("KdpGetContext: SMP UNHANDLED\n");
ControlStart = NULL;
while (TRUE);
}
else
{
/* SMP not yet handled */
- KdpDprintf("SMP UNHANDLED\n");
+ KdpDprintf("KdpSetContext: SMP UNHANDLED\n");
ControlStart = NULL;
while (TRUE);
}
State->ReturnStatus = KdpSysReadBusData(GetBusData->BusDataType,
GetBusData->BusNumber,
GetBusData->SlotNumber,
- Data->Buffer,
GetBusData->Offset,
+ Data->Buffer,
Length,
&Length);
State->ReturnStatus = KdpSysWriteBusData(SetBusData->BusDataType,
SetBusData->BusNumber,
SetBusData->SlotNumber,
- Data->Buffer,
SetBusData->Offset,
+ Data->Buffer,
SetBusData->Length,
&Length);
{
PSTRING ExtraData;
STRING Data, Header;
- DBGKD_WAIT_STATE_CHANGE64 WaitStateChange;
+ DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange;
KCONTINUE_STATUS Status;
/* Start wait loop */
}
/* Setup the header */
- Header.Length = sizeof(DBGKD_WAIT_STATE_CHANGE64);
+ Header.Length = sizeof(DBGKD_ANY_WAIT_STATE_CHANGE);
Header.Buffer = (PCHAR)&WaitStateChange;
/* Send the packet */
IN BOOLEAN SecondChanceException)
{
STRING Header, Data;
- DBGKD_WAIT_STATE_CHANGE64 WaitStateChange;
+ DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange;
KCONTINUE_STATUS Status;
/* Start report loop */
KdpSetCommonState(DbgKdExceptionStateChange, Context, &WaitStateChange);
/* Copy the Exception Record and set First Chance flag */
- CopyExceptionRecord(ExceptionRecord,
- &WaitStateChange.u.Exception.ExceptionRecord);
+#if !defined(_WIN64)
+ ExceptionRecord32To64((PEXCEPTION_RECORD32)ExceptionRecord,
+ &WaitStateChange.u.Exception.ExceptionRecord);
+#else
+ RtlCopyMemory(&WaitStateChange.u.Exception.ExceptionRecord,
+ ExceptionRecord,
+ sizeof(EXCEPTION_RECORD));
+#endif
WaitStateChange.u.Exception.FirstChance = !SecondChanceException;
/* Now finish creating the structure */
KdpSetContextState(&WaitStateChange, Context);
/* Setup the actual header to send to KD */
- Header.Length = sizeof(DBGKD_WAIT_STATE_CHANGE64);
+ Header.Length = sizeof(DBGKD_ANY_WAIT_STATE_CHANGE);
Header.Buffer = (PCHAR)&WaitStateChange;
/* Setup the trace data */
return KeQueryPerformanceCounter(NULL);
}
+NTSTATUS
+NTAPI
+KdpAllowDisable(VOID)
+{
+ /* Check if we are on MP */
+ if (KeNumberProcessors > 1)
+ {
+ /* TODO */
+ KdpDprintf("KdpAllowDisable: SMP UNHANDLED\n");
+ while (TRUE);
+ }
+
+ /* Allow disable */
+ return STATUS_SUCCESS;
+}
+
BOOLEAN
NTAPI
KdEnterDebugger(IN PKTRAP_FRAME TrapFrame,
OldIrql = PASSIVE_LEVEL;
#endif
+ /* Check if enabling the debugger is blocked */
+ if (KdBlockEnable)
+ {
+ /* It is, fail the enable */
+ return STATUS_ACCESS_DENIED;
+ }
+
/* Check if we need to acquire the lock */
if (NeedLock)
{
/* Do the unlock */
KeLowerIrql(OldIrql);
KdpPortUnlock();
- }
- /* Fail: We're already enabled */
- return STATUS_INVALID_PARAMETER;
+ /* Fail: We're already enabled */
+ return STATUS_INVALID_PARAMETER;
+ }
+ else
+ {
+ /*
+ * This can only happen if we are called from a bugcheck
+ * and were never initialized, so initialize the debugger now.
+ */
+ KdInitSystem(0, NULL);
+
+ /* Return success since we initialized */
+ return STATUS_SUCCESS;
+ }
}
/* Decrease the disable count */
return STATUS_SUCCESS;
}
+NTSTATUS
+NTAPI
+KdDisableDebuggerWithLock(IN BOOLEAN NeedLock)
+{
+ KIRQL OldIrql;
+ NTSTATUS Status;
+
+#if defined(__GNUC__)
+ /* Make gcc happy */
+ OldIrql = PASSIVE_LEVEL;
+#endif
+
+ /*
+ * If enabling the debugger is blocked
+ * then there is nothing to disable (duh)
+ */
+ if (KdBlockEnable)
+ {
+ /* Fail */
+ return STATUS_ACCESS_DENIED;
+ }
+
+ /* Check if we need to acquire the lock */
+ if (NeedLock)
+ {
+ /* Lock the port */
+ KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
+ KdpPortLock();
+ }
+
+ /* Check if we're not disabled */
+ if (!KdDisableCount)
+ {
+ /* Check if the debugger was never actually initialized */
+ if (!(KdDebuggerEnabled) && !(KdPitchDebugger))
+ {
+ /* It wasn't, so don't re-enable it later */
+ KdPreviouslyEnabled = FALSE;
+ }
+ else
+ {
+ /* It was, so we will re-enable it later */
+ KdPreviouslyEnabled = TRUE;
+ }
+
+ /* Check if we were called from the exported API and are enabled */
+ if ((NeedLock) && (KdPreviouslyEnabled))
+ {
+ /* Check if it is safe to disable the debugger */
+ Status = KdpAllowDisable();
+ if (!NT_SUCCESS(Status))
+ {
+ /* Release the lock and fail */
+ KeLowerIrql(OldIrql);
+ KdpPortUnlock();
+ return Status;
+ }
+ }
+
+ /* Only disable the debugger if it is enabled */
+ if (KdDebuggerEnabled)
+ {
+ /*
+ * Disable the debugger; suspend breakpoints
+ * and reset the debug stub
+ */
+ KdpSuspendAllBreakPoints();
+ KiDebugRoutine = KdpStub;
+
+ /* We are disabled now */
+ KdDebuggerEnabled = FALSE;
+#undef KdDebuggerEnabled
+ SharedUserData->KdDebuggerEnabled = FALSE;
+#define KdDebuggerEnabled _KdDebuggerEnabled
+ }
+ }
+
+ /* Increment the disable count */
+ KdDisableCount++;
+
+ /* Check if we had locked the port before */
+ if (NeedLock)
+ {
+ /* Yes, now unlock it */
+ KeLowerIrql(OldIrql);
+ KdpPortUnlock();
+ }
+
+ /* We're done */
+ return STATUS_SUCCESS;
+}
+
/* PUBLIC FUNCTIONS **********************************************************/
/*
KdEnableDebugger(VOID)
{
/* Use the internal routine */
- KdpDprintf("KdEnableDebugger called\n");
- while (TRUE);
return KdEnableDebuggerWithLock(TRUE);
}
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+KdDisableDebugger(VOID)
+{
+ /* Use the internal routine */
+ return KdDisableDebuggerWithLock(TRUE);
+}
+
/*
* @unimplemented
*/
return STATUS_SUCCESS;
}
-/*
- * @unimplemented
- */
-NTSTATUS
-NTAPI
-KdDisableDebugger(VOID)
-{
- /* HACK */
- return STATUS_SUCCESS;
-}
-
/*
* @unimplemented
*/
return KdDebuggerNotPresent;
}
+/*
+ * @unimplemented
+ */
NTSTATUS
NTAPI
-NtQueryDebugFilterState(ULONG ComponentId,
- ULONG Level)
+NtQueryDebugFilterState(IN ULONG ComponentId,
+ IN ULONG Level)
{
/* HACK */
return STATUS_SUCCESS;
}
+/*
+ * @unimplemented
+ */
NTSTATUS
NTAPI
-NtSetDebugFilterState(ULONG ComponentId,
- ULONG Level,
- BOOLEAN State)
+NtSetDebugFilterState(IN ULONG ComponentId,
+ IN ULONG Level,
+ IN BOOLEAN State)
{
/* HACK */
return STATUS_SUCCESS;
}
-