Author: ion Date: Thu Nov 30 04:57:25 2006 New Revision: 24980
URL: http://svn.reactos.org/svn/reactos?rev=24980&view=rev Log: - Implement DbgkPostFakeThreadMessages. - Add Dbgk-calls to NtMap/UnmapViewOfSection to nodify debugging services of new DLL image load. - Dbgk support is now skeletally complete, I will write a simple test app to test some functionality and start finding/fixing bugs.
Modified: trunk/reactos/ntoskrnl/dbgk/debug.c trunk/reactos/ntoskrnl/include/internal/dbgk.h trunk/reactos/ntoskrnl/include/internal/ps.h trunk/reactos/ntoskrnl/mm/section.c
Modified: trunk/reactos/ntoskrnl/dbgk/debug.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/dbgk/debug.c?rev=2... ============================================================================== --- trunk/reactos/ntoskrnl/dbgk/debug.c (original) +++ trunk/reactos/ntoskrnl/dbgk/debug.c Thu Nov 30 04:57:25 2006 @@ -551,8 +551,168 @@ OUT PETHREAD *FirstThread, OUT PETHREAD *LastThread) { - /* FIXME: TODO */ - return STATUS_UNSUCCESSFUL; + PETHREAD pFirstThread = NULL, ThisThread, OldThread = NULL, pLastThread; + NTSTATUS Status = STATUS_UNSUCCESSFUL; + BOOLEAN IsFirstThread; + ULONG Flags; + DBGKM_MSG ApiMessage; + PDBGKM_CREATE_THREAD CreateThread = &ApiMessage.CreateThread; + PDBGKM_CREATE_PROCESS CreateProcess = &ApiMessage.CreateProcess; + BOOLEAN First; + PIMAGE_NT_HEADERS NtHeader; + PAGED_CODE(); + + /* Check if we have a start thread */ + if (StartThread) + { + /* Then the one we'll find won't be the first one */ + IsFirstThread = FALSE; + pFirstThread = StartThread; + ThisThread = StartThread; + + /* Reference it */ + ObReferenceObject(StartThread); + } + else + { + /* Get the first thread ourselves */ + ThisThread = PsGetNextProcessThread(Process, OldThread); + IsFirstThread = TRUE; + } + + /* Start thread loop */ + do + { + /* Dereference the previous thread if we had one */ + if (OldThread) ObDereferenceObject(OldThread); + + /* Set this as the last thread and lock it */ + pLastThread = ThisThread; + ObReferenceObject(ThisThread); + if (ExAcquireRundownProtection(&ThisThread->RundownProtect)) + { + /* Acquire worked, set flags */ + Flags = 0x8 | 0x2; + + /* Check if this is a user thread */ + if (!ThisThread->SystemThread) + { + /* Suspend it */ + if (NT_SUCCESS(PsSuspendThread(ThisThread, NULL))) + { + /* Remember this */ + Flags = 0x8 | 0x2 | 0x20; + } + } + } + else + { + /* Couldn't acquire rundown */ + Flags = 0x10 | 0x2; + } + + /* Clear the API Message */ + RtlZeroMemory(&ApiMessage, sizeof(ApiMessage)); + + /* Check if this is the first thread */ + if ((IsFirstThread) && + !(Flags & 0x10) && + !(ThisThread->SystemThread) && + (ThisThread->GrantedAccess)) + { + /* It is, save the flag */ + First = TRUE; + } + else + { + /* It isn't, save the flag */ + First = FALSE; + } + + /* Check if this is the first */ + if (First) + { + /* So we'll start with the create process message */ + ApiMessage.ApiNumber = DbgKmCreateProcessApi; + + /* Get the file handle */ + if (Process->SectionObject) + { + /* Use the section object */ + CreateProcess->FileHandle = + DbgkpSectionToFileHandle(Process->SectionObject); + } + else + { + /* Don't return any handle */ + CreateProcess->FileHandle = NULL; + } + + /* Set the base address */ + CreateProcess->BaseOfImage = Process->SectionBaseAddress; + + /* Get the NT Header */ + NtHeader = RtlImageNtHeader(Process->SectionBaseAddress); + if (NtHeader) + { + /* Fill out data from the header */ + CreateProcess->DebugInfoFileOffset = NtHeader->FileHeader. + PointerToSymbolTable; + CreateProcess->DebugInfoSize = NtHeader->FileHeader. + NumberOfSymbols; + } + } + else + { + /* Otherwise it's a thread message */ + ApiMessage.ApiNumber = DbgKmCreateThreadApi; + CreateThread->StartAddress = ThisThread->StartAddress; + } + + /* Queue the message */ + Status = DbgkpQueueMessage(Process, + ThisThread, + &ApiMessage, + Flags, + DebugObject); + if (!NT_SUCCESS(Status)) + { + /* We failed. FIXME: Handle this */ + DPRINT1("Unhandled Dbgk codepath!\n"); + KEBUGCHECK(0); + } + + /* Check if this was the first message */ + if (First) + { + /* It isn't the first thread anymore */ + IsFirstThread = FALSE; + + /* Reference this thread and set it as first */ + ObDereferenceObject(ThisThread); + pFirstThread = ThisThread; + } + + /* Get the next thread */ + ThisThread = PsGetNextProcessThread(Process, ThisThread); + OldThread = pLastThread; + } while(ThisThread); + + /* Check the API status */ + if (!NT_SUCCESS(Status)) + { + /* We failed. FIXME: Handle this */ + DPRINT1("Unhandled Dbgk codepath!\n"); + KEBUGCHECK(0); + } + + /* Make sure we have a first thread */ + if (!pFirstThread) return STATUS_UNSUCCESSFUL; + + /* Return thread pointers */ + *FirstThread = pFirstThread; + *LastThread = pLastThread; + return Status; }
NTSTATUS
Modified: trunk/reactos/ntoskrnl/include/internal/dbgk.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/d... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/dbgk.h (original) +++ trunk/reactos/ntoskrnl/include/internal/dbgk.h Thu Nov 30 04:57:25 2006 @@ -19,6 +19,21 @@ IN NTSTATUS ExitStatus );
+VOID +NTAPI +DbgkMapViewOfSection( + IN HANDLE SectionHandle, + IN PVOID BaseAddress, + IN ULONG SectionOffset, + IN ULONG_PTR ViewSize +); + +VOID +NTAPI +DbgkUnMapViewOfSection( + IN PVOID BaseAddress +); + BOOLEAN NTAPI DbgkpSuspendProcess( @@ -36,6 +51,12 @@ DbgkpSendApiMessage( IN OUT PDBGKM_MSG ApiMsg, IN ULONG Flags +); + +HANDLE +NTAPI +DbgkpSectionToFileHandle( + IN PVOID Section );
VOID
Modified: trunk/reactos/ntoskrnl/include/internal/ps.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/p... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/ps.h (original) +++ trunk/reactos/ntoskrnl/include/internal/ps.h Thu Nov 30 04:57:25 2006 @@ -338,6 +338,13 @@ NTSTATUS NTAPI PsResumeThread( + IN PETHREAD Thread, + OUT PULONG PreviousCount OPTIONAL +); + +NTSTATUS +NTAPI +PsSuspendThread( IN PETHREAD Thread, OUT PULONG PreviousCount OPTIONAL );
Modified: trunk/reactos/ntoskrnl/mm/section.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/section.c?rev=2... ============================================================================== --- trunk/reactos/ntoskrnl/mm/section.c (original) +++ trunk/reactos/ntoskrnl/mm/section.c Thu Nov 30 04:57:25 2006 @@ -3742,6 +3742,18 @@ AllocationType, Protect);
+ /* Check if this is an image for the current process */ + if ((Section->AllocationAttributes & SEC_IMAGE) && + (Process == PsGetCurrentProcess()) && + (Status != STATUS_IMAGE_NOT_AT_BASE)) + { + /* Notify the debugger */ + DbgkMapViewOfSection(SectionHandle, + SafeBaseAddress, + SafeSectionOffset.LowPart, + SafeViewSize); + } + ObDereferenceObject(Section); ObDereferenceObject(Process);
@@ -3945,6 +3957,7 @@ PROS_SECTION_OBJECT Section; PMM_PAGEOP PageOp; ULONG_PTR Offset; + PVOID ImageBaseAddress = 0;
DPRINT("Opening memory area Process %x BaseAddress %x\n", Process, BaseAddress); @@ -4007,7 +4020,6 @@ ULONG NrSegments; PMM_IMAGE_SECTION_OBJECT ImageSectionObject; PMM_SECTION_SEGMENT SectionSegments; - PVOID ImageBaseAddress = 0; PMM_SECTION_SEGMENT Segment;
Segment = MemoryArea->Data.SectionData.Segment; @@ -4048,6 +4060,10 @@ { Status = MmUnmapViewOfSegment(AddressSpace, BaseAddress); } + + /* Notify debugger */ + if (ImageBaseAddress) DbgkUnMapViewOfSection(ImageBaseAddress); + MmUnlockAddressSpace(AddressSpace); return(STATUS_SUCCESS); }