diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/dbgk | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/ntos/dbgk')
-rw-r--r-- | private/ntos/dbgk/dbgkp.h | 60 | ||||
-rw-r--r-- | private/ntos/dbgk/dbgkport.c | 193 | ||||
-rw-r--r-- | private/ntos/dbgk/dbgkproc.c | 614 | ||||
-rw-r--r-- | private/ntos/dbgk/dirs | 24 | ||||
-rw-r--r-- | private/ntos/dbgk/mp/makefile | 6 | ||||
-rw-r--r-- | private/ntos/dbgk/mp/sources | 29 | ||||
-rw-r--r-- | private/ntos/dbgk/sources.inc | 42 | ||||
-rw-r--r-- | private/ntos/dbgk/udbgk.c | 472 | ||||
-rw-r--r-- | private/ntos/dbgk/up/makefile | 6 | ||||
-rw-r--r-- | private/ntos/dbgk/up/sources | 27 |
10 files changed, 1473 insertions, 0 deletions
diff --git a/private/ntos/dbgk/dbgkp.h b/private/ntos/dbgk/dbgkp.h new file mode 100644 index 000000000..52b511f6e --- /dev/null +++ b/private/ntos/dbgk/dbgkp.h @@ -0,0 +1,60 @@ +/*++ + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + dbgkp.h + +Abstract: + + This header file describes private data structures and functions + that make up the kernel mode portion of the Dbg subsystem. + +Author: + + Mark Lucovsky (markl) 19-Jan-1990 + +[Environment:] + + optional-environment-info (e.g. kernel mode only...) + +[Notes:] + + optional-notes + +Revision History: + +--*/ + +#ifndef _DBGKP_ +#define _DBGKP_ + +#include "ntos.h" +#include "ntdbg.h" +#include <zwapi.h> +#include <string.h> + +NTSTATUS +DbgkpSendApiMessage( + IN OUT PDBGKM_APIMSG ApiMsg, + IN PVOID Port, + IN BOOLEAN SuspendProcess + ); + +VOID +DbgkpSuspendProcess( + IN BOOLEAN CreateDeleteLockHeld + ); + +VOID +DbgkpResumeProcess( + IN BOOLEAN CreateDeleteLockHeld + ); + +HANDLE +DbgkpSectionHandleToFileHandle( + IN HANDLE SectionHandle + ); + +#endif // _DBGKP_ diff --git a/private/ntos/dbgk/dbgkport.c b/private/ntos/dbgk/dbgkport.c new file mode 100644 index 000000000..9541ef21a --- /dev/null +++ b/private/ntos/dbgk/dbgkport.c @@ -0,0 +1,193 @@ +/*++ + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + dbgkport.c + +Abstract: + + This module implements the dbg primitives to access a processes + DebugPort and ExceptionPort. + +Author: + + Mark Lucovsky (markl) 19-Jan-1990 + +Revision History: + +--*/ + +#include "dbgkp.h" + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, DbgkpSendApiMessage) +#pragma alloc_text(PAGE, DbgkForwardException) +#endif + + +NTSTATUS +DbgkpSendApiMessage( + IN OUT PDBGKM_APIMSG ApiMsg, + IN PVOID Port, + IN BOOLEAN SuspendProcess + ) + +/*++ + +Routine Description: + + This function sends the specified API message over the specified + port. It is the callers responsibility to format the API message + prior to calling this function. + + If the SuspendProcess flag is supplied, then all threads in the + calling process are first suspended. Upon receipt of the reply + message, the threads are resumed. + +Arguments: + + ApiMsg - Supplies the API message to send. + + Port - Supplies the address of a port to send the api message. + + SuspendProcess - A flag that if set to true, causes all of the + threads in the process to be suspended prior to the call, + and resumed upon receipt of a reply. + +Return Value: + + TBD + +--*/ + +{ + NTSTATUS st; + + PAGED_CODE(); + + if ( SuspendProcess ) { + DbgkpSuspendProcess(FALSE); + } + + ApiMsg->ReturnedStatus = STATUS_PENDING; + + PsGetCurrentProcess()->CreateProcessReported = TRUE; + + st = LpcRequestWaitReplyPort( + Port, + (PPORT_MESSAGE) ApiMsg, + (PPORT_MESSAGE) ApiMsg + ); + + ZwFlushInstructionCache(NtCurrentProcess(), NULL, 0); + + if ( SuspendProcess ) { + DbgkpResumeProcess(FALSE); + } + + return st; +} + +LARGE_INTEGER DbgkpCalibrationTime; + +BOOLEAN +DbgkForwardException( + IN PEXCEPTION_RECORD ExceptionRecord, + IN BOOLEAN DebugException, + IN BOOLEAN SecondChance + ) + +/*++ + +Routine Description: + + This function is called forward an exception to the calling process's + debug or subsystem exception port. + +Arguments: + + ExceptionRecord - Supplies a pointer to an exception record. + + DebugException - Supplies a boolean variable that specifies whether + this exception is to be forwarded to the process's + DebugPort(TRUE), or to its ExceptionPort(FALSE). + +Return Value: + + TRUE - The process has a DebugPort or an ExceptionPort, and the reply + received from the port indicated that the exception was handled. + + FALSE - The process either does not have a DebugPort or + ExceptionPort, or the process has a port, but the reply received + from the port indicated that the exception was not handled. + +--*/ + +{ + PEPROCESS Process; + PVOID Port; + DBGKM_APIMSG m; + PDBGKM_EXCEPTION args; + NTSTATUS st; + + PAGED_CODE(); + + args = &m.u.Exception; + + // + // Initialize the debug LPC message with default infomaation. + // + + DBGKM_FORMAT_API_MSG(m,DbgKmExceptionApi,sizeof(*args)); + + // + // Get the address of the destination LPC port. + // + + Process = PsGetCurrentProcess(); + if (DebugException) { + Port = Process->DebugPort; + + } else { + Port = Process->ExceptionPort; + m.h.u2.ZeroInit = LPC_EXCEPTION; + } + + // + // If the destination LPC port address is NULL, then return FALSE. + // + + if (Port == NULL) { + return FALSE; + } + + // + // Fill in the remainder of the debug LPC message. + // + + args->ExceptionRecord = *ExceptionRecord; + args->FirstChance = !SecondChance; + + // + // Send the debug message to the destination LPC port. + // + + st = DbgkpSendApiMessage(&m,Port,DebugException); + + // + // If the send was not successful, then return a FALSE indicating that + // the port did not handle the exception. Otherwise, if the debug port + // is specified, then look at the return status in the message. + // + + if (!NT_SUCCESS(st) || + ((DebugException) && + (m.ReturnedStatus == DBG_EXCEPTION_NOT_HANDLED || !NT_SUCCESS(m.ReturnedStatus)))) { + return FALSE; + + } else { + return TRUE; + } +} diff --git a/private/ntos/dbgk/dbgkproc.c b/private/ntos/dbgk/dbgkproc.c new file mode 100644 index 000000000..007ca2911 --- /dev/null +++ b/private/ntos/dbgk/dbgkproc.c @@ -0,0 +1,614 @@ +/*++ + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + dbgkproc.c + +Abstract: + + This module implements process control primitives for the + Dbg component of NT + +Author: + + Mark Lucovsky (markl) 19-Jan-1990 + +Revision History: + +--*/ + +#include "dbgkp.h" + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, DbgkpSuspendProcess) +#pragma alloc_text(PAGE, DbgkpResumeProcess) +#pragma alloc_text(PAGE, DbgkpSectionHandleToFileHandle) +#pragma alloc_text(PAGE, DbgkCreateThread) +#pragma alloc_text(PAGE, DbgkExitThread) +#pragma alloc_text(PAGE, DbgkExitProcess) +#pragma alloc_text(PAGE, DbgkMapViewOfSection) +#pragma alloc_text(PAGE, DbgkUnMapViewOfSection) +#endif + +VOID +DbgkpSuspendProcess( + IN BOOLEAN CreateDeleteLockHeld + ) + +/*++ + +Routine Description: + + This function causes all threads in the calling process except for + the calling thread to suspend. + +Arguments: + + CreateDeleteLockHeld - Supplies a flag that specifies whether or not + the caller is holding the process create delete lock. If the + caller holds the lock, than this function will not aquire the + lock before suspending the process. + +Return Value: + + None. + +--*/ + +{ + PEPROCESS Process; + + PAGED_CODE(); + + Process = PsGetCurrentProcess(); + + // + // Freeze the execution of all threads in the current process, but + // the calling thread. + // + if ( !CreateDeleteLockHeld ) { + PsLockProcess(Process,KernelMode,PsLockWaitForever); + } + + KeFreezeAllThreads(); + + if ( !CreateDeleteLockHeld ) { + PsUnlockProcess(Process); + } + + + return; +} + +VOID +DbgkpResumeProcess( + IN BOOLEAN CreateDeleteLockHeld + ) + +/*++ + +Routine Description: + + This function causes all threads in the calling process except for + the calling thread to resume. + +Arguments: + + CreateDeleteLockHeld - Supplies a flag that specifies whether or not + the caller is holding the process create delete lock. If the + caller holds the lock, than this function will not aquire the + lock before suspending the process. + +Return Value: + + None. + +--*/ + +{ + + PEPROCESS Process; + + PAGED_CODE(); + + Process = PsGetCurrentProcess(); + // + // Thaw the execution of all threads in the current process, but + // the calling thread. + // + + if ( !CreateDeleteLockHeld ) { + PsLockProcess(Process,KernelMode,PsLockWaitForever); + } + + KeThawAllThreads(); + + if ( !CreateDeleteLockHeld ) { + PsUnlockProcess(Process); + } + + return; +} + +HANDLE +DbgkpSectionHandleToFileHandle( + IN HANDLE SectionHandle + ) + +/*++ + +Routine Description: + + This function Opens a handle to the file associated with the processes + section. The file is opened such that it can be dupped all the way to + the UI where the UI can either map the file or read the file to get + the debug info. + +Arguments: + + SectionHandle - Supplies a handle to the section whose associated file + is to be opened. + +Return Value: + + NULL - The file could not be opened. + + NON-NULL - Returns a handle to the file associated with the specified + section. + +--*/ + +{ + NTSTATUS Status; + ANSI_STRING FileName; + UNICODE_STRING UnicodeFileName; + OBJECT_ATTRIBUTES Obja; + IO_STATUS_BLOCK IoStatusBlock; + HANDLE Handle; + + PAGED_CODE(); + + Status = MmGetFileNameForSection(SectionHandle, (PSTRING)&FileName); + if ( !NT_SUCCESS(Status) ) { + return NULL; + } + + Status = RtlAnsiStringToUnicodeString(&UnicodeFileName,&FileName,TRUE); + ExFreePool(FileName.Buffer); + if ( !NT_SUCCESS(Status) ) { + return NULL; + } + + InitializeObjectAttributes( + &Obja, + &UnicodeFileName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL + ); + + Status = ZwOpenFile( + &Handle, + (ACCESS_MASK)(GENERIC_READ | SYNCHRONIZE), + &Obja, + &IoStatusBlock, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_SYNCHRONOUS_IO_NONALERT + ); + RtlFreeUnicodeString(&UnicodeFileName); + if ( !NT_SUCCESS(Status) ) { + return NULL; + } + else { + return Handle; + } +} + + +VOID +DbgkCreateThread( + PVOID StartAddress + ) + +/*++ + +Routine Description: + + This function is called when a new thread begins to execute. If the + thread has an associated DebugPort, then a message is sent thru the + port. + + If this thread is the first thread in the process, then this event + is translated into a CreateProcessInfo message. + + If a message is sent, then while the thread is awaiting a reply, + all other threads in the process are suspended. + +Arguments: + + StartAddress - Supplies the start address for the thread that is + starting. + +Return Value: + + None. + +--*/ + +{ + PVOID Port; + DBGKM_APIMSG m; + PDBGKM_CREATE_THREAD CreateThreadArgs; + PDBGKM_CREATE_PROCESS CreateProcessArgs; + PETHREAD Thread; + PEPROCESS Process; + PDBGKM_LOAD_DLL LoadDllArgs; + NTSTATUS Status; + OBJECT_ATTRIBUTES Obja; + IO_STATUS_BLOCK IoStatusBlock; + PIMAGE_NT_HEADERS NtHeaders; + + PAGED_CODE(); + + Process = PsGetCurrentProcess(); + + Port = Process->DebugPort; + + if ( !Port ) { + return; + } + + Thread = PsGetCurrentThread(); + + if ( Thread->DeadThread ) { + return; + } + + // + // To determine if this should be turned into a create process, + // all threads in the process are suspended. The process list + // is then examined to see if the curent thread is the only thread + // on the list. If so, this becomes a create process message + // + + PsLockProcess(Process,KernelMode,PsLockWaitForever); + + // + // If we are doing a debug attach, then the create process has + // already occured. If this is the case, then the process has + // accumulated some time, so set reported to true + // + + if ( Process->Pcb.UserTime ) { + Process->CreateProcessReported = TRUE; + } + + if ( Process->CreateProcessReported == FALSE ) { + + // + // This is a create process + // + + Process->CreateProcessReported = TRUE; + + CreateThreadArgs = &m.u.CreateProcessInfo.InitialThread; + CreateThreadArgs->SubSystemKey = 0; + + CreateProcessArgs = &m.u.CreateProcessInfo; + CreateProcessArgs->SubSystemKey = 0; + CreateProcessArgs->FileHandle = DbgkpSectionHandleToFileHandle( + Process->SectionHandle + ); + CreateProcessArgs->BaseOfImage = Process->SectionBaseAddress; + + NtHeaders = RtlImageNtHeader(Process->SectionBaseAddress); + if ( NtHeaders ) { + CreateThreadArgs->StartAddress = (PVOID)( + NtHeaders->OptionalHeader.ImageBase + + NtHeaders->OptionalHeader.AddressOfEntryPoint); + + CreateProcessArgs->DebugInfoFileOffset = NtHeaders->FileHeader.PointerToSymbolTable; + CreateProcessArgs->DebugInfoSize = NtHeaders->FileHeader.NumberOfSymbols; + } + else { + CreateThreadArgs->StartAddress = NULL; + CreateProcessArgs->DebugInfoFileOffset = 0; + CreateProcessArgs->DebugInfoSize = 0; + } + + DBGKM_FORMAT_API_MSG(m,DbgKmCreateProcessApi,sizeof(*CreateProcessArgs)); + + PsUnlockProcess(Process); + + DbgkpSendApiMessage(&m,Port,FALSE); + ZwClose(CreateProcessArgs->FileHandle); + + LoadDllArgs = &m.u.LoadDll; + LoadDllArgs->BaseOfDll = PsSystemDllBase; + + NtHeaders = RtlImageNtHeader(PsSystemDllBase); + if ( NtHeaders ) { + LoadDllArgs->DebugInfoFileOffset = NtHeaders->FileHeader.PointerToSymbolTable; + LoadDllArgs->DebugInfoSize = NtHeaders->FileHeader.NumberOfSymbols; + } + else { + LoadDllArgs->DebugInfoFileOffset = 0; + LoadDllArgs->DebugInfoSize = 0; + } + // + // Send load dll section for NT dll ! + // + + InitializeObjectAttributes( + &Obja, + &PsNtDllPathName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL + ); + + Status = ZwOpenFile( + &LoadDllArgs->FileHandle, + (ACCESS_MASK)(GENERIC_READ | SYNCHRONIZE), + &Obja, + &IoStatusBlock, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_SYNCHRONOUS_IO_NONALERT + ); + + if ( NT_SUCCESS(Status) ) { + DBGKM_FORMAT_API_MSG(m,DbgKmLoadDllApi,sizeof(*LoadDllArgs)); + DbgkpSendApiMessage(&m,Port,TRUE); + } + ZwClose(LoadDllArgs->FileHandle); + + } else { + + CreateThreadArgs = &m.u.CreateThread; + CreateThreadArgs->SubSystemKey = 0; + CreateThreadArgs->StartAddress = StartAddress; + + DBGKM_FORMAT_API_MSG(m,DbgKmCreateThreadApi,sizeof(*CreateThreadArgs)); + + PsUnlockProcess(Process); + + DbgkpSendApiMessage(&m,Port,TRUE); + } + + +} + +VOID +DbgkExitThread( + NTSTATUS ExitStatus + ) + +/*++ + +Routine Description: + + This function is called when a new thread terminates. At this + point, the thread will no longer execute in user-mode. No other + exit processing has occured. + + If a message is sent, then while the thread is awaiting a reply, + all other threads in the process are suspended. + +Arguments: + + ExitStatus - Supplies the ExitStatus of the exiting thread. + +Return Value: + + None. + +--*/ + +{ + PVOID Port; + DBGKM_APIMSG m; + PDBGKM_EXIT_THREAD args; + + PAGED_CODE(); + + Port = PsGetCurrentProcess()->DebugPort; + + if ( !Port ) { + return; + } + + if ( PsGetCurrentThread()->DeadThread ) { + return; + } + + args = &m.u.ExitThread; + args->ExitStatus = ExitStatus; + + DBGKM_FORMAT_API_MSG(m,DbgKmExitThreadApi,sizeof(*args)); + + DbgkpSuspendProcess(TRUE); + + DbgkpSendApiMessage(&m,Port,FALSE); + + DbgkpResumeProcess(TRUE); +} + +VOID +DbgkExitProcess( + NTSTATUS ExitStatus + ) + +/*++ + +Routine Description: + + This function is called when a process terminates. The address + space of the process is still intact, but no threads exist in + the process. + +Arguments: + + ExitStatus - Supplies the ExitStatus of the exiting process. + +Return Value: + + None. + +--*/ + +{ + PVOID Port; + DBGKM_APIMSG m; + PDBGKM_EXIT_PROCESS args; + + PAGED_CODE(); + + Port = PsGetCurrentProcess()->DebugPort; + + if ( !Port ) { + return; + } + + if ( PsGetCurrentThread()->DeadThread ) { + return; + } + + // + // this ensures that other timed lockers of the process will bail + // since this call is done while holding the process lock, and lock duration + // is controlled by debugger + // + KeQuerySystemTime(&PsGetCurrentProcess()->ExitTime); + + args = &m.u.ExitProcess; + args->ExitStatus = ExitStatus; + + DBGKM_FORMAT_API_MSG(m,DbgKmExitProcessApi,sizeof(*args)); + + DbgkpSendApiMessage(&m,Port,FALSE); + +} + +VOID +DbgkMapViewOfSection( + IN HANDLE SectionHandle, + IN PVOID BaseAddress, + IN ULONG SectionOffset, + IN ULONG ViewSize + ) + +/*++ + +Routine Description: + + This function is called when the current process successfully + maps a view of an image section. If the process has an associated + debug port, then a load dll message is sent. + +Arguments: + + SectionHandle - Supplies a handle to the section mapped by the + process. + + BaseAddress - Supplies the base address of where the section is + mapped in the current process address space. + + SectionOffset - Supplies the offset in the section where the + processes mapped view begins. + + ViewSize - Supplies the size of the mapped view. + +Return Value: + + None. + +--*/ + +{ + + PVOID Port; + DBGKM_APIMSG m; + PDBGKM_LOAD_DLL LoadDllArgs; + PEPROCESS Process; + PIMAGE_NT_HEADERS NtHeaders; + + PAGED_CODE(); + + Process = PsGetCurrentProcess(); + + Port = Process->DebugPort; + + if ( !Port || KeGetPreviousMode() == KernelMode ) { + return; + } + + LoadDllArgs = &m.u.LoadDll; + LoadDllArgs->FileHandle = DbgkpSectionHandleToFileHandle(SectionHandle); + LoadDllArgs->BaseOfDll = BaseAddress; + NtHeaders = RtlImageNtHeader(BaseAddress); + if ( NtHeaders ) { + LoadDllArgs->DebugInfoFileOffset = NtHeaders->FileHeader.PointerToSymbolTable; + LoadDllArgs->DebugInfoSize = NtHeaders->FileHeader.NumberOfSymbols; + } + else { + LoadDllArgs->DebugInfoFileOffset = 0; + LoadDllArgs->DebugInfoSize = 0; + } + DBGKM_FORMAT_API_MSG(m,DbgKmLoadDllApi,sizeof(*LoadDllArgs)); + + DbgkpSendApiMessage(&m,Port,TRUE); + ZwClose(LoadDllArgs->FileHandle); + +} + +VOID +DbgkUnMapViewOfSection( + IN PVOID BaseAddress + ) + +/*++ + +Routine Description: + + This function is called when the current process successfully + un maps a view of an image section. If the process has an associated + debug port, then an "unmap view of section" message is sent. + +Arguments: + + BaseAddress - Supplies the base address of the section being + unmapped. + +Return Value: + + None. + +--*/ + +{ + + PVOID Port; + DBGKM_APIMSG m; + PDBGKM_UNLOAD_DLL UnloadDllArgs; + PEPROCESS Process; + + PAGED_CODE(); + + Process = PsGetCurrentProcess(); + + Port = Process->DebugPort; + + if ( !Port || KeGetPreviousMode() == KernelMode ) { + return; + } + + UnloadDllArgs = &m.u.UnloadDll; + UnloadDllArgs->BaseAddress = BaseAddress; + + DBGKM_FORMAT_API_MSG(m,DbgKmUnloadDllApi,sizeof(*UnloadDllArgs)); + + DbgkpSendApiMessage(&m,Port,TRUE); + +} diff --git a/private/ntos/dbgk/dirs b/private/ntos/dbgk/dirs new file mode 100644 index 000000000..a2a38f0fd --- /dev/null +++ b/private/ntos/dbgk/dirs @@ -0,0 +1,24 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + dirs. + +Abstract: + + This file specifies the subdirectories of the current directory that + contain component makefiles. + + +Author: + + +NOTE: Commented description of this file is in \nt\bak\bin\dirs.tpl + +!ENDIF + +DIRS=up + +OPTIONAL_DIRS=mp diff --git a/private/ntos/dbgk/mp/makefile b/private/ntos/dbgk/mp/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/ntos/dbgk/mp/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/ntos/dbgk/mp/sources b/private/ntos/dbgk/mp/sources new file mode 100644 index 000000000..dbeb18d62 --- /dev/null +++ b/private/ntos/dbgk/mp/sources @@ -0,0 +1,29 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + Steve Wood (stevewo) 12-Apr-1990 + +NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl + +!ENDIF + +NT_UP=0 + +TARGETPATH=..\..\mpobj + +!include ..\sources.inc diff --git a/private/ntos/dbgk/sources.inc b/private/ntos/dbgk/sources.inc new file mode 100644 index 000000000..e25cec422 --- /dev/null +++ b/private/ntos/dbgk/sources.inc @@ -0,0 +1,42 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + Steve Wood (stevewo) 12-Apr-1990 + +NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl + +!ENDIF + +MAJORCOMP=ntos +MINORCOMP=dbgk + +TARGETNAME=dbgk +TARGETTYPE=LIBRARY + +INCLUDES=..;..\..\inc +MIPS_OPTIONS=-nodwalign +GPSIZE=32 + +C_DEFINES=$(C_DEFINES) -D_NTSYSTEM_ + +SOURCES=..\dbgkport.c \ + ..\dbgkproc.c + +UMTEST=udbgk + +SOURCES_USED=..\sources.inc diff --git a/private/ntos/dbgk/udbgk.c b/private/ntos/dbgk/udbgk.c new file mode 100644 index 000000000..c4c3db876 --- /dev/null +++ b/private/ntos/dbgk/udbgk.c @@ -0,0 +1,472 @@ +/*++ + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + udbg.c + +Abstract: + + Usermode test for debugger + +Author: + + Mark Lucovsky (markl) 19-Jan-1990 + +Revision History: + +--*/ + +#include <nt.h> +#include <ntrtl.h> +#include <nturtl.h> +#include <ntdbg.h> + +HANDLE DebugPort; + + +NTSTATUS +ThreadThatExits ( + IN PVOID ThreadParameter + ) +{ + NtTerminateThread(NtCurrentThread(),(NTSTATUS) ThreadParameter ); +} + +ULONG +foo(PULONG l) +{ + //ULONG x; + //x = *l; + //return x + 1; + + return *l; + +} + +NTSTATUS +ThreadThatExcepts ( + IN PVOID ThreadParameter + ) +{ + foo((PULONG)0x00000001); + NtTerminateThread(NtCurrentThread(),(NTSTATUS) ThreadParameter ); +} + + + +NTSTATUS +ThreadThatSpins ( + IN PVOID ThreadParameter + ) +{ + for(;;); + NtTerminateThread(NtCurrentThread(),STATUS_SUCCESS); +} + + +UdbgTest1() +{ + NTSTATUS st; + HANDLE ExitThread, SpinThread, DebugProcess; + CLIENT_ID ExitClientId, SpinClientId; + DBGKM_APIMSG m; + PDBGKM_CREATE_THREAD CreateThreadArgs; + PDBGKM_CREATE_PROCESS CreateProcessArgs; + PDBGKM_EXIT_THREAD ExitThreadArgs; + PDBGKM_EXIT_PROCESS ExitProcessArgs; + ULONG Psp; + + DbgPrint("UdbgTest1: (1)...\n"); + + // + // Verify that a process can be created with a debug + // port. + // + + st = NtCreateProcess( + &DebugProcess, + PROCESS_ALL_ACCESS, + NULL, + NtCurrentProcess(), + FALSE, + NULL, + DebugPort, + NULL + ); + ASSERT(NT_SUCCESS(st)); + + st = RtlCreateUserThread( + DebugProcess, + NULL, + TRUE, + 0L, + 0L, + 0L, + ThreadThatExits, + (PVOID) STATUS_ABANDONED, + &ExitThread, + &ExitClientId + ); + ASSERT(NT_SUCCESS(st)); + + st = RtlCreateUserThread( + DebugProcess, + NULL, + TRUE, + 0L, + 0L, + 0L, + ThreadThatSpins, + NULL, + &SpinThread, + &SpinClientId + ); + ASSERT(NT_SUCCESS(st)); + + DbgPrint("UdbgTest1: (2)...\n"); + + // + // Verify that CreateProcess Messages Arrive, and that + // they are correct + // + + st = NtResumeThread(SpinThread,NULL); + ASSERT(NT_SUCCESS(st)); + + st = NtReplyWaitReceivePort( + DebugPort, + NULL, + NULL, + (PPORT_MESSAGE)&m + ); + ASSERT(NT_SUCCESS(st)); + ASSERT(m.ApiNumber == DbgKmCreateProcessApi); + + CreateThreadArgs = &m.u.CreateProcess.InitialThread; + CreateProcessArgs = &m.u.CreateProcess; + ASSERT( CreateThreadArgs->SubSystemKey == 0 && CreateThreadArgs->StartAddress == (PVOID)ThreadThatSpins ); + ASSERT( CreateProcessArgs->SubSystemKey == 0); + + DbgPrint("UdbgTest1: (3)...\n"); + + // + // Verify that other threads in the process are properly suspended + // + + st = NtSuspendThread(ExitThread,&Psp); + ASSERT(NT_SUCCESS(st) && Psp == 2); + + st = NtResumeThread(ExitThread,&Psp); + ASSERT(NT_SUCCESS(st) && Psp == 3); + + st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m); + ASSERT(NT_SUCCESS(st)); + + + DbgPrint("UdbgTest1: (4)...\n"); + + // + // Verify that CreateThread Messages Arrive, and that + // they are correct + // + + st = NtResumeThread(ExitThread,&Psp); + ASSERT(NT_SUCCESS(st)); + + st = NtReplyWaitReceivePort( + DebugPort, + NULL, + NULL, + (PPORT_MESSAGE)&m + ); + ASSERT(NT_SUCCESS(st)); + ASSERT(m.ApiNumber == DbgKmCreateThreadApi); + + CreateThreadArgs = &m.u.CreateThread; + ASSERT( CreateThreadArgs->SubSystemKey == 0 && CreateThreadArgs->StartAddress == (PVOID)ThreadThatExits ); + + st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m); + ASSERT(NT_SUCCESS(st)); + + DbgPrint("UdbgTest1: (5)...\n"); + + // + // Verify that ExitThread Messages Arrive, and that + // they are correct + // + + st = NtReplyWaitReceivePort( + DebugPort, + NULL, + NULL, + (PPORT_MESSAGE)&m + ); + ASSERT(NT_SUCCESS(st)); + ASSERT(m.ApiNumber == DbgKmExitThreadApi); + + ExitThreadArgs = &m.u.ExitThread; + ASSERT( ExitThreadArgs->ExitStatus == STATUS_ABANDONED ); + + st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m); + ASSERT(NT_SUCCESS(st)); + + st = NtWaitForSingleObject(ExitThread,FALSE,NULL); + ASSERT(NT_SUCCESS(st)); + + DbgPrint("UdbgTest1: (6)...\n"); + + // + // Verify that ExitThread Messages Arrive, and that + // they are correct + // + + st = NtTerminateProcess(DebugProcess,STATUS_REPARSE); + ASSERT(NT_SUCCESS(st)); + + st = NtReplyWaitReceivePort( + DebugPort, + NULL, + NULL, + (PPORT_MESSAGE)&m + ); + ASSERT(NT_SUCCESS(st)); + ASSERT(m.ApiNumber == DbgKmExitThreadApi); + + ExitThreadArgs = &m.u.ExitThread; + ASSERT( ExitThreadArgs->ExitStatus == STATUS_REPARSE ); + + st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m); + ASSERT(NT_SUCCESS(st)); + + DbgPrint("UdbgTest1: (7)...\n"); + + // + // Verify that ExitProcess Messages Arrive, and that + // they are correct + // + + st = NtReplyWaitReceivePort( + DebugPort, + NULL, + NULL, + (PPORT_MESSAGE)&m + ); + ASSERT(NT_SUCCESS(st)); + ASSERT(m.ApiNumber == DbgKmExitProcessApi); + + ExitProcessArgs = &m.u.ExitProcess; + ASSERT( ExitProcessArgs->ExitStatus == STATUS_REPARSE ); + + st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m); + ASSERT(NT_SUCCESS(st)); + + + st = NtWaitForSingleObject(ExitThread,FALSE,NULL); + ASSERT(NT_SUCCESS(st)); + + st = NtWaitForSingleObject(DebugProcess,FALSE,NULL); + ASSERT(NT_SUCCESS(st)); + + NtClose(ExitThread); + NtClose(SpinThread); + NtClose(DebugProcess); + + DbgPrint("UdbgTest1: END OF TEST ***\n"); + +} + +UdbgTest2() +{ + NTSTATUS st; + HANDLE ExceptionThread, DebugProcess; + DBGKM_APIMSG m; + PDBGKM_CREATE_THREAD CreateThreadArgs; + PDBGKM_CREATE_PROCESS CreateProcessArgs; + PDBGKM_EXIT_THREAD ExitThreadArgs; + PDBGKM_EXIT_PROCESS ExitProcessArgs; + PDBGKM_EXCEPTION ExceptionArgs; + ULONG Psp; + + DbgPrint("UdbgTest2: (1)...\n"); + + // + // Verify that a process can be created with a debug + // port. + // + + st = NtCreateProcess( + &DebugProcess, + PROCESS_ALL_ACCESS, + NULL, + NtCurrentProcess(), + FALSE, + NULL, + DebugPort, + NULL + ); + ASSERT(NT_SUCCESS(st)); + + st = RtlCreateUserThread( + DebugProcess, + NULL, + TRUE, + 0L, + 0L, + 0L, + ThreadThatExcepts, + (PVOID) STATUS_ABANDONED, + &ExceptionThread, + NULL + ); + ASSERT(NT_SUCCESS(st)); + + DbgPrint("UdbgTest2: (2)...\n"); + + // + // Verify that CreateThread Messages Arrive, and that + // they are correct + // + + st = NtResumeThread(ExceptionThread,NULL); + ASSERT(NT_SUCCESS(st)); + + st = NtReplyWaitReceivePort( + DebugPort, + NULL, + NULL, + (PPORT_MESSAGE)&m + ); + ASSERT(NT_SUCCESS(st)); + ASSERT(m.ApiNumber == DbgKmCreateProcessApi); + + CreateThreadArgs = &m.u.CreateProcess.InitialThread; + CreateProcessArgs = &m.u.CreateProcess; + ASSERT( CreateThreadArgs->SubSystemKey == 0 && CreateThreadArgs->StartAddress == (PVOID)ThreadThatExcepts ); + ASSERT( CreateProcessArgs->SubSystemKey == 0); + + st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m); + ASSERT(NT_SUCCESS(st)); + + DbgPrint("UdbgTest2: (3)...\n"); + + // + // Verify that First Chance Exception Messages Arrive, and that + // they are correct + // + + st = NtReplyWaitReceivePort( + DebugPort, + NULL, + NULL, + (PPORT_MESSAGE)&m + ); + ASSERT(NT_SUCCESS(st)); + ASSERT(m.ApiNumber == DbgKmExceptionApi); + + ExceptionArgs = &m.u.Exception; + ASSERT( ExceptionArgs->FirstChance == TRUE ); + + m.ReturnedStatus = DBG_EXCEPTION_NOT_HANDLED; + + st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m); + ASSERT(NT_SUCCESS(st)); + + DbgPrint("UdbgTest2: (4)...\n"); + + // + // Verify that First Chance Exception Messages Arrive, and that + // they are correct + // + + st = NtReplyWaitReceivePort( + DebugPort, + NULL, + NULL, + (PPORT_MESSAGE)&m + ); + ASSERT(NT_SUCCESS(st)); + ASSERT(m.ApiNumber == DbgKmExceptionApi); + + ExceptionArgs = &m.u.Exception; + ASSERT( ExceptionArgs->FirstChance == FALSE ); + + m.ReturnedStatus = DBG_EXCEPTION_HANDLED; +skip4: + st = NtTerminateProcess(DebugProcess,STATUS_REPARSE); + ASSERT(NT_SUCCESS(st)); + + st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m); + ASSERT(NT_SUCCESS(st)); + + st = NtReplyWaitReceivePort( + DebugPort, + NULL, + NULL, + (PPORT_MESSAGE)&m + ); + ASSERT(NT_SUCCESS(st)); + ASSERT(m.ApiNumber == DbgKmExitThreadApi); + + ExitThreadArgs = &m.u.ExitThread; + ASSERT( ExitThreadArgs->ExitStatus == STATUS_REPARSE ); + + st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m); + ASSERT(NT_SUCCESS(st)); + + DbgPrint("UdbgTest2: (5)...\n"); + + // + // Verify that ExitProcess Messages Arrive, and that + // they are correct + // + + st = NtReplyWaitReceivePort( + DebugPort, + NULL, + NULL, + (PPORT_MESSAGE)&m + ); + ASSERT(NT_SUCCESS(st)); + ASSERT(m.ApiNumber == DbgKmExitProcessApi); + + ExitProcessArgs = &m.u.ExitProcess; + ASSERT( ExitProcessArgs->ExitStatus == STATUS_REPARSE ); + + st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m); + ASSERT(NT_SUCCESS(st)); + + + st = NtWaitForSingleObject(ExceptionThread,FALSE,NULL); + ASSERT(NT_SUCCESS(st)); + + st = NtWaitForSingleObject(DebugProcess,FALSE,NULL); + ASSERT(NT_SUCCESS(st)); + + NtClose(ExceptionThread); + NtClose(DebugProcess); + + DbgPrint("UdbgTest2: END OF TEST ***\n"); +} + +main() +{ + NTSTATUS st; + OBJECT_ATTRIBUTES Obja; + + InitializeObjectAttributes(&Obja, NULL, 0, NULL, NULL); + + st = NtCreatePort( + &DebugPort, + &Obja, + 0L, + 256, + 256 * 16 + ); + ASSERT(NT_SUCCESS(st)); + + UdbgTest2(); + UdbgTest1(); + +} diff --git a/private/ntos/dbgk/up/makefile b/private/ntos/dbgk/up/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/ntos/dbgk/up/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/ntos/dbgk/up/sources b/private/ntos/dbgk/up/sources new file mode 100644 index 000000000..6dca9c583 --- /dev/null +++ b/private/ntos/dbgk/up/sources @@ -0,0 +1,27 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + Steve Wood (stevewo) 12-Apr-1990 + +NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl + +!ENDIF + +TARGETPATH=..\..\obj + +!include ..\sources.inc |