reactos/ntoskrnl/dbgk/dbgkutil.c

466 lines
15 KiB
C

/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/dbgk/dbgkutil.c
* PURPOSE: User-Mode Debugging Support, Internal Debug Functions.
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
/* FUNCTIONS *****************************************************************/
HANDLE
NTAPI
DbgkpSectionToFileHandle(IN PVOID Section)
{
NTSTATUS Status;
POBJECT_NAME_INFORMATION FileName;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
HANDLE Handle;
PAGED_CODE();
/* Get the filename of the section */
Status = MmGetFileNameForSection(Section, &FileName);
if (!NT_SUCCESS(Status)) return NULL;
/* Initialize object attributes */
InitializeObjectAttributes(&ObjectAttributes,
&FileName->Name,
OBJ_CASE_INSENSITIVE |
OBJ_FORCE_ACCESS_CHECK |
OBJ_KERNEL_HANDLE,
NULL,
NULL);
/* Open the file */
Status = ZwOpenFile(&Handle,
GENERIC_READ | SYNCHRONIZE,
&ObjectAttributes,
&IoStatusBlock,
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_SYNCHRONOUS_IO_NONALERT);
/* Free the name and return the handle if we succeeded */
ExFreePool(FileName);
if (!NT_SUCCESS(Status)) return NULL;
return Handle;
}
BOOLEAN
NTAPI
DbgkpSuspendProcess(VOID)
{
PAGED_CODE();
/* Make sure this isn't a deleted process */
if (!PsGetCurrentProcess()->ProcessDelete)
{
/* Freeze all the threads */
KeFreezeAllThreads();
return TRUE;
}
else
{
/* No suspend was done */
return FALSE;
}
}
VOID
NTAPI
DbgkpResumeProcess(VOID)
{
PAGED_CODE();
/* Thaw all the threads */
KeThawAllThreads();
}
VOID
NTAPI
DbgkCreateThread(IN PETHREAD Thread,
IN PVOID StartAddress)
{
PEPROCESS Process = PsGetCurrentProcess();
ULONG ProcessFlags;
IMAGE_INFO ImageInfo;
PIMAGE_NT_HEADERS NtHeader;
POBJECT_NAME_INFORMATION ModuleName;
UNICODE_STRING NtDllName;
NTSTATUS Status;
PVOID DebugPort;
DBGKM_MSG ApiMessage;
PDBGKM_CREATE_THREAD CreateThread = &ApiMessage.CreateThread;
PDBGKM_CREATE_PROCESS CreateProcess = &ApiMessage.CreateProcess;
PDBGKM_LOAD_DLL LoadDll = &ApiMessage.LoadDll;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
PTEB Teb;
PAGED_CODE();
/* Sanity check */
ASSERT(Thread == PsGetCurrentThread());
/* Try ORing in the create reported and image notify flags */
ProcessFlags = PspSetProcessFlag(Process,
PSF_CREATE_REPORTED_BIT |
PSF_IMAGE_NOTIFY_DONE_BIT);
/* Check if we were the first to set them or if another thread raced us */
if (!(ProcessFlags & PSF_IMAGE_NOTIFY_DONE_BIT) && (PsImageNotifyEnabled))
{
/* It hasn't.. set up the image info for the process */
ImageInfo.Properties = 0;
ImageInfo.ImageAddressingMode = IMAGE_ADDRESSING_MODE_32BIT;
ImageInfo.ImageBase = Process->SectionBaseAddress;
ImageInfo.ImageSize = 0;
ImageInfo.ImageSelector = 0;
ImageInfo.ImageSectionNumber = 0;
/* Get the NT Headers */
NtHeader = RtlImageNtHeader(Process->SectionBaseAddress);
if (NtHeader)
{
/* Set image size */
ImageInfo.ImageSize = NtHeader->OptionalHeader.SizeOfImage;
}
/* Get the image name */
Status = MmGetFileNameForSection(Process->SectionObject, &ModuleName);
if (NT_SUCCESS(Status))
{
/* Call the notify routines and free the name */
PspRunLoadImageNotifyRoutines(&ModuleName->Name,
Process->UniqueProcessId,
&ImageInfo);
ExFreePool(ModuleName);
}
else
{
/* Call the notify routines */
PspRunLoadImageNotifyRoutines(NULL,
Process->UniqueProcessId,
&ImageInfo);
}
/* Setup the info for ntdll.dll */
ImageInfo.Properties = 0;
ImageInfo.ImageAddressingMode = IMAGE_ADDRESSING_MODE_32BIT;
ImageInfo.ImageBase = PspSystemDllBase;
ImageInfo.ImageSize = 0;
ImageInfo.ImageSelector = 0;
ImageInfo.ImageSectionNumber = 0;
/* Get the NT Headers */
NtHeader = RtlImageNtHeader(PspSystemDllBase);
if (NtHeader)
{
/* Set image size */
ImageInfo.ImageSize = NtHeader->OptionalHeader.SizeOfImage;
}
/* Call the notify routines */
RtlInitUnicodeString(&NtDllName,
L"\\SystemRoot\\System32\\ntdll.dll");
PspRunLoadImageNotifyRoutines(&NtDllName,
Process->UniqueProcessId,
&ImageInfo);
}
/* Fail if we have no port */
DebugPort = Process->DebugPort;
if (!DebugPort) return;
/* Check if create was not already reported */
if (!(ProcessFlags & PSF_CREATE_REPORTED_BIT))
{
/* Setup the information structure for the new thread */
CreateProcess->InitialThread.SubSystemKey = 0;
CreateProcess->InitialThread.StartAddress = NULL;
/* And for the new process */
CreateProcess->SubSystemKey = 0;
CreateProcess->FileHandle = DbgkpSectionToFileHandle(Process->
SectionObject);
CreateProcess->BaseOfImage = Process->SectionBaseAddress;
CreateProcess->DebugInfoFileOffset = 0;
CreateProcess->DebugInfoSize = 0;
/* Get the NT Header */
NtHeader = RtlImageNtHeader(Process->SectionBaseAddress);
if (NtHeader)
{
/* Fill out data from the header */
CreateProcess->InitialThread.StartAddress =
(PVOID)((ULONG_PTR)NtHeader->OptionalHeader.ImageBase +
NtHeader->OptionalHeader.AddressOfEntryPoint);
CreateProcess->DebugInfoFileOffset = NtHeader->FileHeader.
PointerToSymbolTable;
CreateProcess->DebugInfoSize = NtHeader->FileHeader.
NumberOfSymbols;
}
/* Setup the API Message */
ApiMessage.h.u1.Length = sizeof(DBGKM_MSG) << 16 |
(8 + sizeof(DBGKM_CREATE_PROCESS));
ApiMessage.h.u2.ZeroInit = 0;
ApiMessage.h.u2.s2.Type = LPC_DEBUG_EVENT;
ApiMessage.ApiNumber = DbgKmCreateProcessApi;
/* Send the message */
DbgkpSendApiMessage(&ApiMessage, FALSE);
/* Close the handle */
ObCloseHandle(CreateProcess->FileHandle, KernelMode);
/* Setup the parameters */
LoadDll->BaseOfDll = PspSystemDllBase;
LoadDll->DebugInfoFileOffset = 0;
LoadDll->DebugInfoSize = 0;
LoadDll->NamePointer = NULL;
/* Get the NT Headers */
NtHeader = RtlImageNtHeader(PspSystemDllBase);
if (NtHeader)
{
/* Fill out debug information */
LoadDll->DebugInfoFileOffset = NtHeader->
FileHeader.PointerToSymbolTable;
LoadDll->DebugInfoSize = NtHeader->FileHeader.NumberOfSymbols;
}
/* Get the TEB */
Teb = Thread->Tcb.Teb;
if (Teb)
{
/* Copy the system library name and link to it */
wcsncpy(Teb->StaticUnicodeBuffer,
L"ntdll.dll",
sizeof(Teb->StaticUnicodeBuffer) / sizeof(WCHAR));
Teb->NtTib.ArbitraryUserPointer = Teb->StaticUnicodeBuffer;
/* Return it in the debug event as well */
LoadDll->NamePointer = &Teb->NtTib.ArbitraryUserPointer;
}
/* Get a handle */
InitializeObjectAttributes(&ObjectAttributes,
&PsNtDllPathName,
OBJ_CASE_INSENSITIVE |
OBJ_KERNEL_HANDLE |
OBJ_FORCE_ACCESS_CHECK,
NULL,
NULL);
Status = ZwOpenFile(&LoadDll->FileHandle,
GENERIC_READ | SYNCHRONIZE,
&ObjectAttributes,
&IoStatusBlock,
FILE_SHARE_DELETE |
FILE_SHARE_READ |
FILE_SHARE_WRITE,
FILE_SYNCHRONOUS_IO_NONALERT);
if (NT_SUCCESS(Status))
{
/* Setup the API Message */
ApiMessage.h.u1.Length = sizeof(DBGKM_MSG) << 16 |
(8 + sizeof(DBGKM_LOAD_DLL));
ApiMessage.h.u2.ZeroInit = 0;
ApiMessage.h.u2.s2.Type = LPC_DEBUG_EVENT;
ApiMessage.ApiNumber = DbgKmLoadDllApi;
/* Send the message */
DbgkpSendApiMessage(&ApiMessage, TRUE);
/* Close the handle */
ObCloseHandle(LoadDll->FileHandle, KernelMode);
}
}
else
{
/* Otherwise, do it just for the thread */
CreateThread->SubSystemKey = 0;
CreateThread->StartAddress = StartAddress;
/* Setup the API Message */
ApiMessage.h.u1.Length = sizeof(DBGKM_MSG) << 16 |
(8 + sizeof(DBGKM_CREATE_THREAD));
ApiMessage.h.u2.ZeroInit = 0;
ApiMessage.h.u2.s2.Type = LPC_DEBUG_EVENT;
ApiMessage.ApiNumber = DbgKmCreateThreadApi;
/* Send the message */
DbgkpSendApiMessage(&ApiMessage, TRUE);
}
}
VOID
NTAPI
DbgkExitProcess(IN NTSTATUS ExitStatus)
{
DBGKM_MSG ApiMessage;
PDBGKM_EXIT_PROCESS ExitProcess = &ApiMessage.ExitProcess;
PEPROCESS Process = PsGetCurrentProcess();
PETHREAD Thread = PsGetCurrentThread();
PAGED_CODE();
/* Check if this thread is hidden, doesn't have a debug port, or died */
if ((Thread->HideFromDebugger) ||
!(Process->DebugPort) ||
(Thread->DeadThread))
{
/* Don't notify the debugger */
return;
}
/* Set the exit status */
ExitProcess->ExitStatus = ExitStatus;
/* Setup the API Message */
ApiMessage.h.u1.Length = sizeof(DBGKM_MSG) << 16 |
(8 + sizeof(DBGKM_EXIT_PROCESS));
ApiMessage.h.u2.ZeroInit = 0;
ApiMessage.h.u2.s2.Type = LPC_DEBUG_EVENT;
ApiMessage.ApiNumber = DbgKmExitProcessApi;
/* Set the current exit time */
KeQuerySystemTime(&Process->ExitTime);
/* Send the message */
DbgkpSendApiMessage(&ApiMessage, FALSE);
}
VOID
NTAPI
DbgkExitThread(IN NTSTATUS ExitStatus)
{
DBGKM_MSG ApiMessage;
PDBGKM_EXIT_THREAD ExitThread = &ApiMessage.ExitThread;
PEPROCESS Process = PsGetCurrentProcess();
PETHREAD Thread = PsGetCurrentThread();
BOOLEAN Suspended;
PAGED_CODE();
/* Check if this thread is hidden, doesn't have a debug port, or died */
if ((Thread->HideFromDebugger) ||
!(Process->DebugPort) ||
(Thread->DeadThread))
{
/* Don't notify the debugger */
return;
}
/* Set the exit status */
ExitThread->ExitStatus = ExitStatus;
/* Setup the API Message */
ApiMessage.h.u1.Length = sizeof(DBGKM_MSG) << 16 |
(8 + sizeof(DBGKM_EXIT_THREAD));
ApiMessage.h.u2.ZeroInit = 0;
ApiMessage.h.u2.s2.Type = LPC_DEBUG_EVENT;
ApiMessage.ApiNumber = DbgKmExitThreadApi;
/* Suspend the process */
Suspended = DbgkpSuspendProcess();
/* Send the message */
DbgkpSendApiMessage(&ApiMessage, FALSE);
/* Resume the process if needed */
if (Suspended) DbgkpResumeProcess();
}
VOID
NTAPI
DbgkMapViewOfSection(IN PVOID Section,
IN PVOID BaseAddress,
IN ULONG SectionOffset,
IN ULONG_PTR ViewSize)
{
DBGKM_MSG ApiMessage;
PDBGKM_LOAD_DLL LoadDll = &ApiMessage.LoadDll;
PEPROCESS Process = PsGetCurrentProcess();
PETHREAD Thread = PsGetCurrentThread();
PIMAGE_NT_HEADERS NtHeader;
PAGED_CODE();
DBGKTRACE(DBGK_PROCESS_DEBUG,
"Section: %p. Base: %p\n", Section, BaseAddress);
/* Check if this thread is kernel, hidden or doesn't have a debug port */
if ((ExGetPreviousMode() == KernelMode) ||
(Thread->HideFromDebugger) ||
!(Process->DebugPort))
{
/* Don't notify the debugger */
return;
}
/* Setup the parameters */
LoadDll->FileHandle = DbgkpSectionToFileHandle(Section);
LoadDll->BaseOfDll = BaseAddress;
LoadDll->DebugInfoFileOffset = 0;
LoadDll->DebugInfoSize = 0;
LoadDll->NamePointer = &NtCurrentTeb()->NtTib.ArbitraryUserPointer;
/* Get the NT Headers */
NtHeader = RtlImageNtHeader(BaseAddress);
if (NtHeader)
{
/* Fill out debug information */
LoadDll->DebugInfoFileOffset = NtHeader->FileHeader.
PointerToSymbolTable;
LoadDll->DebugInfoSize = NtHeader->FileHeader.NumberOfSymbols;
}
/* Setup the API Message */
ApiMessage.h.u1.Length = sizeof(DBGKM_MSG) << 16 |
(8 + sizeof(DBGKM_LOAD_DLL));
ApiMessage.h.u2.ZeroInit = 0;
ApiMessage.h.u2.s2.Type = LPC_DEBUG_EVENT;
ApiMessage.ApiNumber = DbgKmLoadDllApi;
/* Send the message */
DbgkpSendApiMessage(&ApiMessage, TRUE);
/* Close the handle */
ObCloseHandle(LoadDll->FileHandle, KernelMode);
}
VOID
NTAPI
DbgkUnMapViewOfSection(IN PVOID BaseAddress)
{
DBGKM_MSG ApiMessage;
PDBGKM_UNLOAD_DLL UnloadDll = &ApiMessage.UnloadDll;
PEPROCESS Process = PsGetCurrentProcess();
PETHREAD Thread = PsGetCurrentThread();
PAGED_CODE();
/* Check if this thread is kernel, hidden or doesn't have a debug port */
if ((ExGetPreviousMode() == KernelMode) ||
(Thread->HideFromDebugger) ||
!(Process->DebugPort))
{
/* Don't notify the debugger */
return;
}
/* Set the DLL Base */
UnloadDll->BaseAddress = BaseAddress;
/* Setup the API Message */
ApiMessage.h.u1.Length = sizeof(DBGKM_MSG) << 16 |
(8 + sizeof(DBGKM_UNLOAD_DLL));
ApiMessage.h.u2.ZeroInit = 0;
ApiMessage.h.u2.s2.Type = LPC_DEBUG_EVENT;
ApiMessage.ApiNumber = DbgKmUnloadDllApi;
/* Send the message */
DbgkpSendApiMessage(&ApiMessage, TRUE);
}