From d83fcae7d1aed916b494f11851f975247059654b Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Thu, 30 Nov 2006 04:16:35 +0000 Subject: [PATCH] - Forgot to actually initialize Dbgk during system initialization, so any API would crash. - Fix some stupid bugs in NtCreateDebugObject. - Add tracing framework and add tracing to all of debug.c. - Dbgk *almost* works: http://www.tinykrnl.org/dbgworking.png. Here I attach to services.exe and the kernel is sending notifications for all threads and DLLs loaded. svn path=/trunk/; revision=24981 --- reactos/ntoskrnl/dbgk/debug.c | 60 ++++++++++++++++++++++-- reactos/ntoskrnl/ex/init.c | 3 ++ reactos/ntoskrnl/include/internal/dbgk.h | 57 ++++++++++++++++++++-- reactos/ntoskrnl/include/internal/ps.h | 12 ++--- 4 files changed, 118 insertions(+), 14 deletions(-) diff --git a/reactos/ntoskrnl/dbgk/debug.c b/reactos/ntoskrnl/dbgk/debug.c index 104a60df4b8..d98c14562fc 100644 --- a/reactos/ntoskrnl/dbgk/debug.c +++ b/reactos/ntoskrnl/dbgk/debug.c @@ -14,6 +14,7 @@ POBJECT_TYPE DbgkDebugObjectType; FAST_MUTEX DbgkpProcessDebugPortMutex; +ULONG DbgkpTraceLevel = -1; GENERIC_MAPPING DbgkDebugObjectMapping = { @@ -47,6 +48,10 @@ DbgkpQueueMessage(IN PEPROCESS Process, NTSTATUS Status; BOOLEAN NewEvent; PAGED_CODE(); + DBGKTRACE(DBGK_MESSAGE_DEBUG, + "Process: %p Thread: %p Message: %p Flags: %lx\n", + Process, Thread, Message, Flags); + DBGKTRACE(DBGK_MESSAGE_DEBUG, "MessageType: %lx\n", Message->ApiNumber); /* Check if we have to allocate a debug event */ NewEvent = (Flags & 2) ? TRUE : FALSE; @@ -191,6 +196,7 @@ DbgkpQueueMessage(IN PEPROCESS Process, } /* Return status */ + DBGKTRACE(DBGK_MESSAGE_DEBUG, "Status: %lx\n", Status); return Status; } @@ -240,6 +246,7 @@ DbgkpSendApiMessage(IN OUT PDBGKM_MSG ApiMsg, { NTSTATUS Status; PAGED_CODE(); + DBGKTRACE(DBGK_MESSAGE_DEBUG, "ApiMsg: %p Flags: %lx\n", ApiMsg, Flags); /* Suspend process if required */ if (Flags) DbgkpSuspendProcess(); @@ -272,6 +279,7 @@ DbgkCopyProcessDebugPort(IN PEPROCESS Process, { PDEBUG_OBJECT DebugObject; PAGED_CODE(); + DBGKTRACE(DBGK_PROCESS_DEBUG, "Process: %p Parent: %p\n", Process, Parent); /* Clear this process's port */ Process->DebugPort = NULL; @@ -318,6 +326,8 @@ DbgkForwardException(IN PEXCEPTION_RECORD ExceptionRecord, PVOID Port; BOOLEAN UseLpc = FALSE; PAGED_CODE(); + DBGKTRACE(DBGK_EXCEPTION_DEBUG, + "ExceptionRecord: %p Port: %p\n", ExceptionRecord, DebugPort); /* Setup the API Message */ ApiMessage.h.u1.Length = sizeof(DBGKM_MSG) << 16 | @@ -379,6 +389,7 @@ DbgkpFreeDebugEvent(IN PDEBUG_EVENT DebugEvent) { PHANDLE Handle = NULL; PAGED_CODE(); + DBGKTRACE(DBGK_OBJECT_DEBUG, "DebugEvent: %p\n", DebugEvent); /* Check if this event had a file handle */ switch (DebugEvent->ApiMsg.ApiNumber) @@ -414,6 +425,7 @@ DbgkpWakeTarget(IN PDEBUG_EVENT DebugEvent) { PETHREAD Thread = DebugEvent->Thread; PAGED_CODE(); + DBGKTRACE(DBGK_OBJECT_DEBUG, "DebugEvent: %p\n", DebugEvent); /* Check if we have to wake the thread */ if (DebugEvent->Flags & 20) PsResumeThread(Thread, NULL); @@ -457,6 +469,8 @@ DbgkpPostFakeModuleMessages(IN PEPROCESS Process, IO_STATUS_BLOCK IoStatusBlock; NTSTATUS Status; PAGED_CODE(); + DBGKTRACE(DBGK_PROCESS_DEBUG, "Process: %p Thread: %p DebugObject: %p\n", + Process, Thread, DebugObject); /* Quit if there's no PEB */ if (!Peb) return STATUS_SUCCESS; @@ -493,6 +507,10 @@ DbgkpPostFakeModuleMessages(IN PEPROCESS Process, LoadDll->DebugInfoSize = NtHeader->FileHeader.NumberOfSymbols; } + /* Trace */ + DBGKTRACE(DBGK_PROCESS_DEBUG, "Name: %wZ. Base: %p\n", + &LdrEntry->FullDllName, LdrEntry->DllBase); + /* Get the name of the DLL */ Status = MmGetFileNameForAddress(NtHeader, &ModuleName); if (NT_SUCCESS(Status)) @@ -561,6 +579,8 @@ DbgkpPostFakeThreadMessages(IN PEPROCESS Process, BOOLEAN First; PIMAGE_NT_HEADERS NtHeader; PAGED_CODE(); + DBGKTRACE(DBGK_THREAD_DEBUG, "Process: %p StartThread: %p Object: %p\n", + Process, StartThread, DebugObject); /* Check if we have a start thread */ if (StartThread) @@ -669,6 +689,12 @@ DbgkpPostFakeThreadMessages(IN PEPROCESS Process, CreateThread->StartAddress = ThisThread->StartAddress; } + /* Trace */ + DBGKTRACE(DBGK_THREAD_DEBUG, "Thread: %p. First: %lx, OldThread: %p\n", + ThisThread, First, OldThread); + DBGKTRACE(DBGK_THREAD_DEBUG, "Start Address: %p\n", + ThisThread->StartAddress); + /* Queue the message */ Status = DbgkpQueueMessage(Process, ThisThread, @@ -726,6 +752,8 @@ DbgkpPostFakeProcessCreateMessages(IN PEPROCESS Process, PETHREAD ReturnThread = NULL; NTSTATUS Status; PAGED_CODE(); + DBGKTRACE(DBGK_PROCESS_DEBUG, "Process: %p DebugObject: %p\n", + Process, DebugObject); /* Attach to the process */ KeStackAttachProcess(&Process->Pcb, &ApcState); @@ -883,6 +911,7 @@ DbgkpMarkProcessPeb(IN PEPROCESS Process) { KAPC_STATE ApcState; PAGED_CODE(); + DBGKTRACE(DBGK_PROCESS_DEBUG, "Process: %p\n", Process); /* Acquire process rundown */ if (!ExAcquireRundownProtection(&Process->RundownProtect)) return; @@ -920,6 +949,8 @@ DbgkpOpenHandles(IN PDBGUI_WAIT_STATE_CHANGE WaitStateChange, HANDLE Handle; PHANDLE DupHandle; PAGED_CODE(); + DBGKTRACE(DBGK_OBJECT_DEBUG, "Process: %p Thread: %p\n", + Process, Thread); /* Check which state this is */ switch (WaitStateChange->NewState) @@ -1035,6 +1066,8 @@ DbgkpCloseObject(IN PEPROCESS OwnerProcess OPTIONAL, BOOLEAN DebugPortCleared = FALSE; PLIST_ENTRY DebugEventList; PDEBUG_EVENT DebugEvent; + DBGKTRACE(DBGK_OBJECT_DEBUG, "OwnerProcess: %p DebugObject: %p\n", + OwnerProcess, DebugObject); /* If this isn't the last handle, do nothing */ if (HandleCount > 1) return; @@ -1122,6 +1155,8 @@ DbgkpSetProcessDebugObject(IN PEPROCESS Process, PETHREAD ThisThread, FirstThread; PLIST_ENTRY NextEntry; PAGED_CODE(); + DBGKTRACE(DBGK_PROCESS_DEBUG, "Process: %p DebugObject: %p\n", + Process, DebugObject); /* Initialize the temporary list */ InitializeListHead(&TempList); @@ -1228,6 +1263,8 @@ ThreadScan: NextEntry = DebugObject->EventList.Flink; while (NextEntry != &DebugObject->EventList) { + DPRINT1("Next Entry: %p\n", NextEntry); + DPRINT1("List: %p\n", &DebugObject->EventList); /* FIXME: TODO */ KEBUGCHECK(0); } @@ -1260,6 +1297,8 @@ DbgkClearProcessDebugObject(IN PEPROCESS Process, IN PDEBUG_OBJECT SourceDebugObject) { /* FIXME: TODO */ + DBGKTRACE(DBGK_PROCESS_DEBUG, "Process: %p DebugObject: %p\n", + Process, SourceDebugObject); return STATUS_UNSUCCESSFUL; } @@ -1330,7 +1369,7 @@ NtCreateDebugObject(OUT PHANDLE DebugHandle, ObjectAttributes, PreviousMode, NULL, - sizeof(PDEBUG_OBJECT), + sizeof(DEBUG_OBJECT), 0, 0, (PVOID*)&DebugObject); @@ -1343,7 +1382,9 @@ NtCreateDebugObject(OUT PHANDLE DebugHandle, InitializeListHead(&DebugObject->EventList); /* Initialize the Debug Object's Wait Event */ - KeInitializeEvent(&DebugObject->EventsPresent, NotificationEvent, 0); + KeInitializeEvent(&DebugObject->EventsPresent, + NotificationEvent, + FALSE); /* Set the Flags */ DebugObject->KillProcessOnExit = KillProcessOnExit; @@ -1355,9 +1396,6 @@ NtCreateDebugObject(OUT PHANDLE DebugHandle, 0, NULL, &hDebug); - ObDereferenceObject(DebugObject); - - /* Check for success and return handle */ if (NT_SUCCESS(Status)) { _SEH_TRY @@ -1372,6 +1410,8 @@ NtCreateDebugObject(OUT PHANDLE DebugHandle, } /* Return Status */ + DBGKTRACE(DBGK_OBJECT_DEBUG, "Handle: %p DebugObject: %p\n", + hDebug, DebugObject); return Status; } @@ -1389,6 +1429,8 @@ NtDebugContinue(IN HANDLE DebugHandle, BOOLEAN NeedsWake = FALSE; CLIENT_ID ClientId; PAGED_CODE(); + DBGKTRACE(DBGK_OBJECT_DEBUG, "Handle: %p Status: %p\n", + DebugHandle, ContinueStatus); /* Check if we were called from user mode*/ if (PreviousMode != KernelMode) @@ -1513,6 +1555,9 @@ NtDebugActiveProcess(IN HANDLE ProcessHandle, KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); PETHREAD LastThread; NTSTATUS Status; + PAGED_CODE(); + DBGKTRACE(DBGK_PROCESS_DEBUG, "Process: %p Handle: %p\n", + ProcessHandle, DebugHandle); /* Reference the process */ Status = ObReferenceObjectByHandle(ProcessHandle, @@ -1576,6 +1621,9 @@ NtRemoveProcessDebug(IN HANDLE ProcessHandle, PDEBUG_OBJECT DebugObject; KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); NTSTATUS Status; + PAGED_CODE(); + DBGKTRACE(DBGK_PROCESS_DEBUG, "Process: %p Handle: %p\n", + ProcessHandle, DebugHandle); /* Reference the process */ Status = ObReferenceObjectByHandle(ProcessHandle, @@ -1705,6 +1753,8 @@ NtWaitForDebugEvent(IN HANDLE DebugHandle, NTSTATUS Status = STATUS_SUCCESS; PDEBUG_EVENT DebugEvent, DebugEvent2; PLIST_ENTRY ListHead, NextEntry; + PAGED_CODE(); + DBGKTRACE(DBGK_OBJECT_DEBUG, "Handle: %p\n", DebugHandle); /* Clear the initial wait state change structure */ RtlZeroMemory(&WaitStateChange, sizeof(WaitStateChange)); diff --git a/reactos/ntoskrnl/ex/init.c b/reactos/ntoskrnl/ex/init.c index df31d1c5d95..068d5d9263c 100644 --- a/reactos/ntoskrnl/ex/init.c +++ b/reactos/ntoskrnl/ex/init.c @@ -792,6 +792,9 @@ ExpInitializeExecutive(IN ULONG Cpu, /* Initialize the Process Manager */ if (!PsInitSystem()) KEBUGCHECK(PROCESS_INITIALIZATION_FAILED); + /* Initialize the User-Mode Debugging Subsystem */ + DbgkInitialize(); + /* Calculate the tick count multiplier */ ExpTickCountMultiplier = ExComputeTickCountMultiplier(KeMaximumIncrement); SharedUserData->TickCountMultiplier = ExpTickCountMultiplier; diff --git a/reactos/ntoskrnl/include/internal/dbgk.h b/reactos/ntoskrnl/include/internal/dbgk.h index 7723648cf98..39cafe992f6 100644 --- a/reactos/ntoskrnl/include/internal/dbgk.h +++ b/reactos/ntoskrnl/include/internal/dbgk.h @@ -1,5 +1,57 @@ -#ifndef __NTOSKRNL_INCLUDE_INTERNAL_DBGK_H -#define __NTOSKRNL_INCLUDE_INTERNAL_DBGK_H +/* + * PROJECT: ReactOS Kernel + * LICENSE: GPL - See COPYING in the top level directory + * FILE: ntoskrnl/include/dbgk.h + * PURPOSE: Internal header for the User-Mode Debugging Backend + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + */ + +// +// Define this if you want debugging support +// +#define _DBGK_DEBUG_ 0x01 + +// +// These define the Debug Masks Supported +// +#define DBGK_THREAD_DEBUG 0x01 +#define DBGK_PROCESS_DEBUG 0x02 +#define DBGK_OBJECT_DEBUG 0x04 +#define DBGK_MESSAGE_DEBUG 0x08 +#define DBGK_EXCEPTION_DEBUG 0x10 + +// +// Debug/Tracing support +// +#if _DBGK_DEBUG_ +#ifdef NEW_DEBUG_SYSTEM_IMPLEMENTED // enable when Debug Filters are implemented +#define DBGKTRACE(x, ...) \ + { \ + DbgPrintEx("%s [%.16s] - ", \ + __FUNCTION__, \ + PsGetCurrentProcess()->ImageFileName); \ + DbgPrintEx(__VA_ARGS__); \ + } +#else +#define DBGKTRACE(x, ...) \ + if (x & DbgkpTraceLevel) \ + { \ + DbgPrint("%s [%.16s] - ", \ + __FUNCTION__, \ + PsGetCurrentProcess()->ImageFileName); \ + DbgPrint(__VA_ARGS__); \ + } +#endif +#else +#define DBGKTRACE(x, ...) DPRINT(__VA_ARGS__); +#endif + +VOID +INIT_FUNCTION +NTAPI +DbgkInitialize( + VOID +); VOID NTAPI @@ -82,6 +134,5 @@ DbgkClearProcessDebugObject( ); extern POBJECT_TYPE DbgkDebugObjectType; -#endif /* EOF */ diff --git a/reactos/ntoskrnl/include/internal/ps.h b/reactos/ntoskrnl/include/internal/ps.h index d4efca8ad5b..306d56cd6db 100644 --- a/reactos/ntoskrnl/include/internal/ps.h +++ b/reactos/ntoskrnl/include/internal/ps.h @@ -1,10 +1,10 @@ /* -* PROJECT: ReactOS Kernel -* LICENSE: GPL - See COPYING in the top level directory -* FILE: ntoskrnl/include/ps.h -* PURPOSE: Internal header for the Process Manager -* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) -*/ + * PROJECT: ReactOS Kernel + * LICENSE: GPL - See COPYING in the top level directory + * FILE: ntoskrnl/include/ps.h + * PURPOSE: Internal header for the Process Manager + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + */ // // Define this if you want debugging support