Merge my current work done on the kd++ branch:

- FreeLdr is able now to load personalized Kernel Debugger Transport DLLs by reading at the kernel command line and interpreting the /DEBUGPORT=xxx entry (--> loads KDxxx.DLL dll in \SystemRoot\System32\).
  Therefore we can not only load the "default" kdcom.dll, but also 3rd-party ones such as kdbazis.dll from VirtualKD (from revision 58902).
- The GCC-compiled-only version of kdcom, containing legacy COM code, was removed and put directly along KDBG. It remains only a stub / template for future kdcom-like dlls. The MSVC-version remains untouched.
- Make those functions ^ use directly the CPORTLIB library.

svn path=/trunk/; revision=58974
This commit is contained in:
Hermès Bélusca-Maïto 2013-05-09 13:12:58 +00:00
commit 91ef640fe5
27 changed files with 876 additions and 440 deletions

View file

@ -1568,7 +1568,7 @@ LoadBootDeviceDriver(VOID)
ULONG ImportTableSize;
PLDR_DATA_TABLE_ENTRY BootDdDTE, FreeldrDTE;
CHAR NtBootDdPath[MAX_PATH];
PVOID ImageBase;
PVOID ImageBase = NULL;
ULONG (NTAPI *EntryPoint)(IN PVOID DriverObject, IN PVOID RegistryPath);
BOOLEAN Status;

View file

@ -255,11 +255,12 @@ WinLdrAllocateDataTableEntry(IN OUT PLIST_ENTRY ModuleListHead,
return TRUE;
}
/* WinLdrLoadImage loads the specified image from the file (it doesn't
perform any additional operations on the filename, just directly
calls the file I/O routines), and relocates it so that it's ready
to be used when paging is enabled.
Addressing mode: physical
/*
* WinLdrLoadImage loads the specified image from the file (it doesn't
* perform any additional operations on the filename, just directly
* calls the file I/O routines), and relocates it so that it's ready
* to be used when paging is enabled.
* Addressing mode: physical
*/
BOOLEAN
WinLdrLoadImage(IN PCHAR FileName,
@ -430,7 +431,6 @@ WinLdrLoadImage(IN PCHAR FileName,
if (Status != ESUCCESS)
return FALSE;
/* Relocate the image, if it needs it */
if (NtHeaders->OptionalHeader.ImageBase != (ULONG_PTR)VirtualBase)
{
@ -756,7 +756,7 @@ WinLdrpLoadAndScanReferencedDll(PLIST_ENTRY ModuleListHead,
{
CHAR FullDllName[256];
BOOLEAN Status;
PVOID BasePA;
PVOID BasePA = NULL;
/* Prepare the full path to the file to be loaded */
strcpy(FullDllName, DirectoryPath);
@ -781,7 +781,7 @@ WinLdrpLoadAndScanReferencedDll(PLIST_ENTRY ModuleListHead,
DataTableEntry);
if (!Status)
{
ERR("WinLdrAllocateDataTableEntry() failed with Status=0x%X\n", Status);
ERR("WinLdrAllocateDataTableEntry() failed\n");
return Status;
}
@ -791,7 +791,7 @@ WinLdrpLoadAndScanReferencedDll(PLIST_ENTRY ModuleListHead,
Status = WinLdrScanImportDescriptorTable(ModuleListHead, DirectoryPath, *DataTableEntry);
if (!Status)
{
ERR("WinLdrScanImportDescriptorTable() failed with Status=0x%X\n", Status);
ERR("WinLdrScanImportDescriptorTable() failed\n");
return Status;
}

View file

@ -227,7 +227,7 @@ WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock,
static BOOLEAN
WinLdrLoadDeviceDriver(PLIST_ENTRY LoadOrderListHead,
LPSTR BootPath,
LPCSTR BootPath,
PUNICODE_STRING FilePath,
ULONG Flags,
PLDR_DATA_TABLE_ENTRY *DriverDTE)
@ -237,7 +237,7 @@ WinLdrLoadDeviceDriver(PLIST_ENTRY LoadOrderListHead,
CHAR DllName[1024];
PCHAR DriverNamePos;
BOOLEAN Status;
PVOID DriverBase;
PVOID DriverBase = NULL;
// Separate the path to file name and directory path
_snprintf(DriverPath, sizeof(DriverPath), "%wZ", FilePath);
@ -259,7 +259,6 @@ WinLdrLoadDeviceDriver(PLIST_ENTRY LoadOrderListHead,
TRACE("DriverPath: %s, DllName: %s, LPB\n", DriverPath, DllName);
// Check if driver is already loaded
Status = WinLdrCheckForLoadedDll(LoadOrderListHead, DllName, DriverDTE);
if (Status)
@ -299,7 +298,7 @@ WinLdrLoadDeviceDriver(PLIST_ENTRY LoadOrderListHead,
BOOLEAN
WinLdrLoadBootDrivers(PLOADER_PARAMETER_BLOCK LoaderBlock,
LPSTR BootPath)
LPCSTR BootPath)
{
PLIST_ENTRY NextBd;
PBOOT_DRIVER_LIST_ENTRY BootDriver;
@ -318,8 +317,11 @@ WinLdrLoadBootDrivers(PLOADER_PARAMETER_BLOCK LoaderBlock,
// Paths are relative (FIXME: Are they always relative?)
// Load it
Status = WinLdrLoadDeviceDriver(&LoaderBlock->LoadOrderListHead, BootPath, &BootDriver->FilePath,
0, &BootDriver->LdrEntry);
Status = WinLdrLoadDeviceDriver(&LoaderBlock->LoadOrderListHead,
BootPath,
&BootDriver->FilePath,
0,
&BootDriver->LdrEntry);
// If loading failed - cry loudly
//FIXME: Maybe remove it from the list and try to continue?
@ -340,8 +342,10 @@ WinLdrLoadBootDrivers(PLOADER_PARAMETER_BLOCK LoaderBlock,
return TRUE;
}
PVOID WinLdrLoadModule(PCSTR ModuleName, ULONG *Size,
TYPE_OF_MEMORY MemoryType)
PVOID
WinLdrLoadModule(PCSTR ModuleName,
ULONG *Size,
TYPE_OF_MEMORY MemoryType)
{
ULONG FileId;
PVOID PhysicalBase;
@ -398,7 +402,6 @@ PVOID WinLdrLoadModule(PCSTR ModuleName, ULONG *Size,
return PhysicalBase;
}
USHORT
WinLdrDetectVersion()
{
@ -420,19 +423,20 @@ WinLdrDetectVersion()
}
static
PVOID
BOOLEAN
LoadModule(
PLOADER_PARAMETER_BLOCK LoaderBlock,
PCCH Path,
PCCH File,
TYPE_OF_MEMORY MemoryType,
PLDR_DATA_TABLE_ENTRY *Dte,
BOOLEAN IsKdTransportDll,
ULONG Percentage)
{
BOOLEAN Status;
CHAR FullFileName[MAX_PATH];
CHAR ProgressString[256];
NTSTATUS Status;
PVOID BaseAdress;
PVOID BaseAdress = NULL;
UiDrawBackdrop();
sprintf(ProgressString, "Loading %s...", File);
@ -443,15 +447,146 @@ LoadModule(
strcat(FullFileName, File);
Status = WinLdrLoadImage(FullFileName, MemoryType, &BaseAdress);
TRACE("%s loaded with status %d at %p\n",
File, Status, BaseAdress);
if (!Status)
{
TRACE("Loading %s failed\n", File);
return FALSE;
}
TRACE("%s loaded successfully at %p\n", File, BaseAdress);
strcpy(FullFileName, "WINDOWS\\SYSTEM32\\");
strcat(FullFileName, File);
WinLdrAllocateDataTableEntry(&LoaderBlock->LoadOrderListHead, File,
FullFileName, BaseAdress, Dte);
/*
* Cheat about the base DLL name if we are loading
* the Kernel Debugger Transport DLL, to make the
* PE loader happy.
*/
Status = WinLdrAllocateDataTableEntry(&LoaderBlock->LoadOrderListHead,
(IsKdTransportDll ? "KDCOM.DLL" : File),
FullFileName,
BaseAdress,
Dte);
return BaseAdress;
return Status;
}
static
BOOLEAN
LoadWindowsCore(IN USHORT OperatingSystemVersion,
IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
IN LPCSTR BootOptions,
IN LPCSTR BootPath,
IN OUT PLDR_DATA_TABLE_ENTRY* KernelDTE)
{
BOOLEAN Status;
CHAR DirPath[MAX_PATH];
CHAR KdTransportDllName[MAX_PATH];
PLDR_DATA_TABLE_ENTRY HalDTE, KdComDTE = NULL;
if (!KernelDTE) return FALSE;
/* Load the Kernel */
LoadModule(LoaderBlock, BootPath, "NTOSKRNL.EXE", LoaderSystemCode, KernelDTE, FALSE, 30);
/* Load the HAL */
LoadModule(LoaderBlock, BootPath, "HAL.DLL", LoaderHalCode, &HalDTE, FALSE, 45);
/* Load the Kernel Debugger Transport DLL */
if (OperatingSystemVersion > _WIN32_WINNT_WIN2K)
{
/*
* According to http://www.nynaeve.net/?p=173 :
* "[...] Another enhancement that could be done Microsoft-side would be
* a better interface for replacing KD transport modules. Right now, due
* to the fact that ntoskrnl is static linked to KDCOM.DLL, the OS loader
* has a hardcoded hack that interprets the KD type in the OS loader options,
* loads one of the (hardcoded filenames) "kdcom.dll", "kd1394.dll", or
* "kdusb2.dll" modules, and inserts them into the loaded module list under
* the name "kdcom.dll". [...]"
*/
/*
* This loop replaces a dumb call to strstr(..., "DEBUGPORT=").
* Indeed I want it to be case-insensitive to allow "debugport="
* or "DeBuGpOrT=" or... , and I don't want it to match malformed
* command-line options, such as:
*
* "...foo DEBUGPORT=xxx bar..."
* "...foo/DEBUGPORT=xxx bar..."
* "...foo/DEBUGPORT=bar..."
*
* i.e. the "DEBUGPORT=" switch must start with a slash and be separated
* from the rest by whitespace, unless it begins the command-line, e.g.:
*
* "/DEBUGPORT=COM1 foo...bar..."
* "...foo /DEBUGPORT=USB bar..."
* or:
* "...foo /DEBUGPORT= bar..."
* (in that case, we default the port to COM).
*/
while (BootOptions)
{
/* Skip possible initial whitespace */
BootOptions += strspn(BootOptions, " \t");
/* Check whether a new commutator starts and it is the DEBUGPORT one */
if (*BootOptions != '/' || _strnicmp(++BootOptions, "DEBUGPORT=", 10) != 0)
{
/* Search for another whitespace */
BootOptions = strpbrk(BootOptions, " \t");
continue;
}
else
{
/* We found the DEBUGPORT commutator. Move to the port name. */
BootOptions += 10;
break;
}
}
if (BootOptions)
{
/*
* We have found the DEBUGPORT commutator. Parse the port name.
* Format: /DEBUGPORT=COM1 or /DEBUGPORT=FILE:\Device\HarddiskX\PartitionY\debug.log or /DEBUGPORT=FOO
* If we only have /DEBUGPORT= (i.e. without any port name), defaults it to "COM".
*/
strcpy(KdTransportDllName, "KD");
if (_strnicmp(BootOptions, "COM", 3) == 0 && '0' <= BootOptions[3] && BootOptions[3] <= '9')
{
strncat(KdTransportDllName, BootOptions, 3);
}
else
{
size_t i = strcspn(BootOptions, " \t:"); /* Skip valid separators: whitespace or colon */
if (i == 0)
strcat(KdTransportDllName, "COM");
else
strncat(KdTransportDllName, BootOptions, i);
}
strcat(KdTransportDllName, ".DLL");
_strupr(KdTransportDllName);
/*
* Load the transport DLL. Specify it to LoadModule so that it can
* change the base DLL name of the loaded transport DLL to the default
* "KDCOM.DLL" name, to make the PE loader happy.
*/
LoadModule(LoaderBlock, BootPath, KdTransportDllName, LoaderSystemCode, &KdComDTE, TRUE, 60);
}
}
/* Load all referenced DLLs for Kernel, HAL and Kernel Debugger Transport DLL */
strcpy(DirPath, BootPath);
strcat(DirPath, "system32\\");
Status = WinLdrScanImportDescriptorTable(&LoaderBlock->LoadOrderListHead, DirPath, *KernelDTE);
Status &= WinLdrScanImportDescriptorTable(&LoaderBlock->LoadOrderListHead, DirPath, HalDTE);
if (KdComDTE)
{
Status &= WinLdrScanImportDescriptorTable(&LoaderBlock->LoadOrderListHead, DirPath, KdComDTE);
}
return Status;
}
VOID
@ -496,7 +631,7 @@ LoadAndBootWindows(IN OperatingSystemItem* OperatingSystem,
strcat(BootPath, FileName);
}
/* append a backslash */
/* Append a backslash */
if ((strlen(BootPath)==0) || BootPath[strlen(BootPath)] != '\\')
strcat(BootPath, "\\");
@ -547,13 +682,13 @@ LoadAndBootWindows(IN OperatingSystemItem* OperatingSystem,
UiDrawBackdrop();
UiDrawProgressBarCenter(15, 100, "Loading system hive...");
Status = WinLdrInitSystemHive(LoaderBlock, BootPath);
TRACE("SYSTEM hive loaded with status %d\n", Status);
TRACE("SYSTEM hive %s\n", (Status ? "loaded" : "not loaded"));
/* Load NLS data, OEM font, and prepare boot drivers list */
Status = WinLdrScanSystemHive(LoaderBlock, BootPath);
TRACE("SYSTEM hive scanned with status %d\n", Status);
TRACE("SYSTEM hive %s\n", (Status ? "scanned" : "not scanned"));
/* Finish loading */
LoadAndBootWindowsCommon(OperatingSystemVersion,
LoaderBlock,
BootOptions,
@ -571,8 +706,7 @@ LoadAndBootWindowsCommon(
{
PLOADER_PARAMETER_BLOCK LoaderBlockVA;
BOOLEAN Status;
CHAR FileName[MAX_PATH];
PLDR_DATA_TABLE_ENTRY KernelDTE, HalDTE, KdComDTE = NULL;
PLDR_DATA_TABLE_ENTRY KernelDTE;
KERNEL_ENTRY_POINT KiSystemStartup;
LPCSTR SystemRoot;
TRACE("LoadAndBootWindowsCommon()\n");
@ -586,40 +720,30 @@ LoadAndBootWindowsCommon(
if (OperatingSystemVersion == 0)
OperatingSystemVersion = WinLdrDetectVersion();
/* Load kernel */
LoadModule(LoaderBlock, BootPath, "NTOSKRNL.EXE", LoaderSystemCode, &KernelDTE, 30);
/* Load HAL */
LoadModule(LoaderBlock, BootPath, "HAL.DLL", LoaderHalCode, &HalDTE, 45);
/* Load kernel-debugger support dll */
if (OperatingSystemVersion > _WIN32_WINNT_WIN2K)
{
LoadModule(LoaderBlock, BootPath, "KDCOM.DLL", LoaderSystemCode, &KdComDTE, 60);
}
/* Load all referenced DLLs for kernel, HAL and kdcom.dll */
strcpy(FileName, BootPath);
strcat(FileName, "system32\\");
Status = WinLdrScanImportDescriptorTable(&LoaderBlock->LoadOrderListHead, FileName, KernelDTE);
Status &= WinLdrScanImportDescriptorTable(&LoaderBlock->LoadOrderListHead, FileName, HalDTE);
if (KdComDTE)
Status &= WinLdrScanImportDescriptorTable(&LoaderBlock->LoadOrderListHead, FileName, KdComDTE);
/* Load the operating system core: the Kernel, the HAL and the Kernel Debugger Transport DLL */
Status = LoadWindowsCore(OperatingSystemVersion,
LoaderBlock,
BootOptions,
BootPath,
&KernelDTE);
if (!Status)
{
UiMessageBox("Error loading imported dll.");
UiMessageBox("Error loading NTOS core.");
return;
}
/* Load boot drivers */
UiDrawBackdrop();
UiDrawProgressBarCenter(100, 100, "Loading boot drivers...");
Status = WinLdrLoadBootDrivers(LoaderBlock, (PCHAR)BootPath);
Status = WinLdrLoadBootDrivers(LoaderBlock, BootPath);
TRACE("Boot drivers loaded with status %d\n", Status);
/* Initialize Phase 1 - no drivers loading anymore */
WinLdrInitializePhase1(LoaderBlock, BootOptions, SystemRoot, BootPath, OperatingSystemVersion);
WinLdrInitializePhase1(LoaderBlock,
BootOptions,
SystemRoot,
BootPath,
OperatingSystemVersion);
/* Save entry-point pointer and Loader block VAs */
KiSystemStartup = (KERNEL_ENTRY_POINT)KernelDTE->EntryPoint;
@ -644,7 +768,7 @@ LoadAndBootWindowsCommon(
LoaderBlock->Extension->LoaderPagesSpanned = LoaderPagesSpanned;
TRACE("Hello from paged mode, KiSystemStartup %p, LoaderBlockVA %p!\n",
KiSystemStartup, LoaderBlockVA);
KiSystemStartup, LoaderBlockVA);
// Zero KI_USER_SHARED_DATA page
memset((PVOID)KI_USER_SHARED_DATA, 0, MM_PAGE_SIZE);
@ -722,5 +846,3 @@ WinLdrpDumpArcDisks(PLOADER_PARAMETER_BLOCK LoaderBlock)
NextBd = ArcDisk->ListEntry.Flink;
}
}

View file

@ -3,9 +3,10 @@ add_subdirectory(beep)
add_subdirectory(bootvid)
if(_WINKD_)
add_subdirectory(kddll)
else()
add_subdirectory(kdcom)
else()
add_subdirectory(kdrosdbg)
endif()
add_subdirectory(nmidebug)
add_subdirectory(null)

View file

@ -1,19 +1,13 @@
spec2def(kdcom.dll kdcom.spec ADD_IMPORTLIB)
if(ARCH STREQUAL "i386")
list(APPEND SOURCE i386/kdbg.c)
elseif(ARCH STREQUAL "amd64")
list(APPEND SOURCE i386/kdbg.c)
elseif(ARCH STREQUAL "arm")
list(APPEND SOURCE arm/kdbg.c)
endif(ARCH STREQUAL "i386")
list(APPEND SOURCE
add_library(kdcom SHARED
kdcom.c
kddll.c
kdserial.c
kdcom.rc
${CMAKE_CURRENT_BINARY_DIR}/kdcom.def)
add_library(kdcom SHARED ${SOURCE})
set_entrypoint(kdcom 0)
set_subsystem(kdcom native)
set_image_base(kdcom 0x00010000)

View file

@ -17,8 +17,7 @@
#define DEFAULT_DEBUG_COM2_IRQ 3 /* COM2 IRQ */
#define DEFAULT_DEBUG_BAUD_RATE 115200 /* 115200 Baud */
#define DEFAULT_BAUD_RATE 19200
#define DEFAULT_BAUD_RATE 19200
#if defined(_M_IX86) || defined(_M_AMD64)
const ULONG BaseArray[] = {0, 0x3F8, 0x2F8, 0x3E8, 0x2E8};

View file

@ -1,6 +1,6 @@
#define REACTOS_VERSION_DLL
#define REACTOS_STR_FILE_DESCRIPTION "ReactOS KDBG COM Library"
#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Kernel Debugger COM Extension DLL"
#define REACTOS_STR_INTERNAL_NAME "kdcom"
#define REACTOS_STR_ORIGINAL_FILENAME "kdcom.dll"
#include <reactos/version.rc>

View file

@ -1,21 +1,8 @@
; Old KD
@ stdcall KdPortGetByte(ptr)
@ stdcall KdPortGetByteEx(ptr ptr)
@ stdcall KdPortInitialize(ptr long long)
@ stdcall KdPortInitializeEx(ptr long long)
@ stdcall KdPortPollByte(ptr)
@ stdcall KdPortPollByteEx(ptr ptr)
@ stdcall KdPortPutByte(long)
@ stdcall KdPortPutByteEx(ptr long)
@ stdcall KdPortRestore()
@ stdcall KdPortSave()
@ stdcall KdPortDisableInterrupts()
@ stdcall KdPortEnableInterrupts()
; New KD
@ stdcall KdD0Transition()
@ stdcall KdD3Transition()
@ stdcall KdDebuggerInitialize0(ptr)
@ stdcall KdDebuggerInitialize1(ptr)
@ stdcall KdSave(long)
@ stdcall KdRestore(long)
@ stdcall KdReceivePacket(long ptr ptr ptr ptr)
@ stdcall KdRestore(long)
@ stdcall KdSave(long)
@ stdcall KdSendPacket(long ptr ptr ptr)

View file

@ -1,8 +0,0 @@
@ stdcall KdD0Transition()
@ stdcall KdD3Transition()
@ stdcall KdDebuggerInitialize0(ptr)
@ stdcall KdDebuggerInitialize1(ptr)
@ stdcall KdReceivePacket(long ptr ptr ptr ptr)
@ stdcall KdRestore(long)
@ stdcall KdSave(long)
@ stdcall KdSendPacket(long ptr ptr ptr)

View file

@ -1,13 +1,13 @@
spec2def(kdcom.dll kdcom.spec ADD_IMPORTLIB)
spec2def(kdcom.dll kdrosdbg.spec ADD_IMPORTLIB)
add_library(kdcom SHARED
kdcom.c
kddll.c
kdserial.c
kdcom.rc
list(APPEND SOURCE
kdrosdbg.c
kdrosdbg.rc
${CMAKE_CURRENT_BINARY_DIR}/kdcom.def)
add_library(kdcom SHARED ${SOURCE})
set_entrypoint(kdcom 0)
set_subsystem(kdcom native)
set_image_base(kdcom 0x00010000)

View file

@ -0,0 +1,116 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/base/kdcom/kdbg.c
* PURPOSE: Serial i/o functions for the kernel debugger.
* PROGRAMMER: Alex Ionescu
* Hervé Poussineau
*/
/* INCLUDES *****************************************************************/
#define NOEXTAPI
#include <ntifs.h>
#include <halfuncs.h>
#include <stdio.h>
#include <arc/arc.h>
#include <windbgkd.h>
#include <kddll.h>
#define NDEBUG
#include <debug.h>
/* FUNCTIONS ****************************************************************/
/*
* @unimplemented
*/
NTSTATUS
NTAPI
KdDebuggerInitialize0(
IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL)
{
return STATUS_NOT_IMPLEMENTED;
}
/*
* @unimplemented
*/
NTSTATUS
NTAPI
KdDebuggerInitialize1(
IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL)
{
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
KdD0Transition(VOID)
{
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
KdD3Transition(VOID)
{
return STATUS_SUCCESS;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
KdSave(
IN BOOLEAN SleepTransition)
{
/* Nothing to do on COM ports */
return STATUS_SUCCESS;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
KdRestore(
IN BOOLEAN SleepTransition)
{
/* Nothing to do on COM ports */
return STATUS_SUCCESS;
}
/*
* @unimplemented
*/
VOID
NTAPI
KdSendPacket(
IN ULONG PacketType,
IN PSTRING MessageHeader,
IN PSTRING MessageData,
IN OUT PKD_CONTEXT Context)
{
UNIMPLEMENTED;
return;
}
/*
* @unimplemented
*/
KDSTATUS
NTAPI
KdReceivePacket(
IN ULONG PacketType,
OUT PSTRING MessageHeader,
OUT PSTRING MessageData,
OUT PULONG DataLength,
IN OUT PKD_CONTEXT Context)
{
UNIMPLEMENTED;
return 0;
}
/* EOF */

View file

@ -1,6 +1,6 @@
#define REACTOS_VERSION_DLL
#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Kernel Debugger COM Extension DLL"
#define REACTOS_STR_FILE_DESCRIPTION "ReactOS KDBG COM Library"
#define REACTOS_STR_INTERNAL_NAME "kdcom"
#define REACTOS_STR_ORIGINAL_FILENAME "kdcom.dll"
#include <reactos/version.rc>

View file

@ -451,7 +451,7 @@ typedef struct _DBGKD_WAIT_STATE_CHANGE32
ULONG Thread;
ULONG ProgramCounter;
union
{
{
DBGKM_EXCEPTION32 Exception;
DBGKD_LOAD_SYMBOLS32 LoadSymbols;
} u;
@ -481,13 +481,13 @@ typedef struct _DBGKD_ANY_WAIT_STATE_CHANGE
ULONG64 Thread;
ULONG64 ProgramCounter;
union
{
{
DBGKM_EXCEPTION64 Exception;
DBGKD_LOAD_SYMBOLS64 LoadSymbols;
DBGKD_COMMAND_STRING CommandString;
} u;
union
{
{
DBGKD_CONTROL_REPORT ControlReport;
DBGKD_ANY_CONTROL_REPORT AnyControlReport;
};
@ -814,7 +814,7 @@ typedef struct _DBGKD_FILE_IO
ULONG ApiNumber;
ULONG Status;
union
{
{
ULONG64 ReserveSpace[7];
DBGKD_CREATE_FILE CreateFile;
DBGKD_READ_FILE ReadFile;
@ -843,7 +843,7 @@ typedef struct _DBGKD_CONTROL_REQUEST
{
ULONG ApiNumber;
union
{
{
DBGKD_REQUEST_BREAKPOINT RequestBreakpoint;
DBGKD_RELEASE_BREAKPOINT ReleaseBreakpoint;
} u;

View file

@ -363,6 +363,7 @@ endif()
if(NOT _WINKD_)
if(ARCH STREQUAL "i386")
list(APPEND SOURCE
kd/i386/kdbg.c
kd/i386/kdmemsup.c
kd/wrappers/gdbstub.c)
if(KDBG)
@ -372,6 +373,7 @@ if(NOT _WINKD_)
elseif(ARCH STREQUAL "amd64")
list(APPEND SOURCE
kd/amd64/kd.c
kd/i386/kdbg.c # Use the x86 file
kd/amd64/kdmemsup.c)
if(KDBG)
list(APPEND ASM_SOURCE kdbg/amd64/kdb_help.S)
@ -379,6 +381,8 @@ if(NOT _WINKD_)
kdbg/amd64/i386-dis.c
kdbg/amd64/kdb.c)
endif()
elseif(ARCH STREQUAL "arm")
list(APPEND SOURCE kd/arm/kdbg.c)
elseif(ARCH STREQUAL "powerpc")
list(APPEND SOURCE kd/wrappers/gdbstub_powerpc.c)
endif()

View file

@ -1,5 +1,7 @@
#pragma once
#include <cportlib/cportlib.h>
#ifdef _M_PPC
#define KdDebuggerEnabled _KdDebuggerEnabled
#define KdDebuggerNotPresent _KdDebuggerNotPresent
@ -8,58 +10,31 @@
//
// Kernel Debugger Port Definition
//
typedef struct _KD_PORT_INFORMATION
{
ULONG ComPort;
ULONG BaudRate;
ULONG BaseAddress;
} KD_PORT_INFORMATION, *PKD_PORT_INFORMATION;
struct _KD_DISPATCH_TABLE;
extern KD_PORT_INFORMATION GdbPortInfo;
extern CPPORT GdbPortInfo;
extern BOOLEAN _KdDebuggerEnabled;
extern BOOLEAN _KdDebuggerNotPresent;
extern BOOLEAN KdBreakAfterSymbolLoad;
extern BOOLEAN KdPitchDebugger;
extern BOOLEAN KdIgnoreUmExceptions;
BOOLEAN
NTAPI
KdPortInitialize(
PKD_PORT_INFORMATION PortInformation,
ULONG Unknown1,
ULONG Unknown2
);
BOOLEAN
NTAPI
KdPortInitializeEx(
PKD_PORT_INFORMATION PortInformation,
ULONG Unknown1,
ULONG Unknown2
PCPPORT PortInformation,
ULONG ComPortNumber
);
BOOLEAN
NTAPI
KdPortGetByte(
PUCHAR ByteReceived);
BOOLEAN
NTAPI
KdPortGetByteEx(
PKD_PORT_INFORMATION PortInformation,
PCPPORT PortInformation,
PUCHAR ByteReceived);
VOID
NTAPI
KdPortPutByte(
UCHAR ByteToSend
);
VOID
NTAPI
KdPortPutByteEx(
PKD_PORT_INFORMATION PortInformation,
PCPPORT PortInformation,
UCHAR ByteToSend
);
@ -359,7 +334,8 @@ extern ULONG KdpPortIrq;
extern ULONG KdpPort;
/* Port Information for the Serial Native Mode */
extern KD_PORT_INFORMATION SerialPortInfo;
extern ULONG SerialPortNumber;
extern CPPORT SerialPortInfo;
/* Init Functions for Native Providers */
extern PKDP_INIT_ROUTINE InitRoutines[KdMax];

View file

@ -95,10 +95,6 @@
#define TAG_VPB ' BPV'
#define TAG_SYSB 'BSYS'
/* formerly located in kdbg/kdb_symbols.c */
#define TAG_KDBS 'SBDK'
#define TAG_KDBG 'GBDK'
/* formerly located in ldr/loader.c */
#define TAG_DRIVER_MEM 'MVRD' /* drvm */
#define TAG_MODULE_OBJECT 'omlk' /* klmo - kernel ldr module object */

View file

@ -0,0 +1,112 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: BSD - See COPYING.ARM in the top level directory
* FILE: drivers/base/kdcom/arm/kdbg.c
* PURPOSE: Serial Port Kernel Debugging Transport Library
* PROGRAMMERS: ReactOS Portable Systems Group
*/
/* INCLUDES *******************************************************************/
#include <ntoskrnl.h>
#include <arm/peripherals/pl011.h>
#define NDEBUG
#include <debug.h>
/* GLOBALS ********************************************************************/
CPPORT DefaultPort = {0, 0, 0};
//
// We need to build this in the configuration root and use KeFindConfigurationEntry
// to recover it later.
//
#define HACK 24000000
/* REACTOS FUNCTIONS **********************************************************/
NTSTATUS
NTAPI
KdDebuggerInitialize1(IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL)
{
return STATUS_NOT_IMPLEMENTED;
}
BOOLEAN
NTAPI
KdPortInitializeEx(IN PCPPORT PortInformation,
IN ULONG ComPortNumber)
{
ULONG Divider, Remainder, Fraction;
ULONG Baudrate = PortInformation->BaudRate;
//
// Calculate baudrate clock divider and remainder
//
Divider = HACK / (16 * Baudrate);
Remainder = HACK % (16 * Baudrate);
//
// Calculate the fractional part
//
Fraction = (8 * Remainder / Baudrate) >> 1;
Fraction += (8 * Remainder / Baudrate) & 1;
//
// Disable interrupts
//
WRITE_REGISTER_ULONG(UART_PL011_CR, 0);
//
// Set the baud rate
//
WRITE_REGISTER_ULONG(UART_PL011_IBRD, Divider);
WRITE_REGISTER_ULONG(UART_PL011_FBRD, Fraction);
//
// Set 8 bits for data, 1 stop bit, no parity, FIFO enabled
//
WRITE_REGISTER_ULONG(UART_PL011_LCRH,
UART_PL011_LCRH_WLEN_8 | UART_PL011_LCRH_FEN);
//
// Clear and enable FIFO
//
WRITE_REGISTER_ULONG(UART_PL011_CR,
UART_PL011_CR_UARTEN |
UART_PL011_CR_TXE |
UART_PL011_CR_RXE);
//
// Done
//
return TRUE;
}
BOOLEAN
NTAPI
KdPortGetByteEx(IN PCPPORT PortInformation,
OUT PUCHAR ByteReceived)
{
UNIMPLEMENTED;
while (TRUE);
return FALSE;
}
VOID
NTAPI
KdPortPutByteEx(IN PCPPORT PortInformation,
IN UCHAR ByteToSend)
{
//
// Wait for ready
//
while ((READ_REGISTER_ULONG(UART_PL01x_FR) & UART_PL01x_FR_TXFF) != 0);
//
// Send the character
//
WRITE_REGISTER_ULONG(UART_PL01x_DR, ByteToSend);
}
/* EOF */

View file

@ -0,0 +1,151 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/base/kdcom/kdbg.c
* PURPOSE: Serial i/o functions for the kernel debugger.
* PROGRAMMER: Alex Ionescu
* Hervé Poussineau
*/
/* INCLUDES *****************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
#define DEFAULT_BAUD_RATE 19200
#if defined(_M_IX86) || defined(_M_AMD64)
const ULONG BaseArray[] = {0, 0x3F8, 0x2F8, 0x3E8, 0x2E8};
#elif defined(_M_PPC)
const ULONG BaseArray[] = {0, 0x800003F8};
#elif defined(_M_MIPS)
const ULONG BaseArray[] = {0, 0x80006000, 0x80007000};
#elif defined(_M_ARM)
const ULONG BaseArray[] = {0, 0xF1012000};
#else
#error Unknown architecture
#endif
/* STATIC VARIABLES ***********************************************************/
// static CPPORT DefaultPort = {0, 0, 0};
/* The COM port must only be initialized once! */
// static BOOLEAN PortInitialized = FALSE;
/* REACTOS FUNCTIONS **********************************************************/
NTSTATUS
NTAPI
KdDebuggerInitialize1(
IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL)
{
return STATUS_NOT_IMPLEMENTED;
}
BOOLEAN
NTAPI
KdPortInitializeEx(
IN PCPPORT PortInformation,
IN ULONG ComPortNumber)
{
NTSTATUS Status;
CHAR buffer[80];
#if 0 // Deactivated because never used in fact (was in KdPortInitialize but we use KdPortInitializeEx)
/*
* Find the port if needed
*/
SIZE_T i;
if (!PortInitialized)
{
DefaultPort.BaudRate = PortInformation->BaudRate;
if (ComPortNumber == 0)
{
/*
* Start enumerating COM ports from the last one to the first one,
* and break when we find a valid port.
* If we reach the first element of the list, the invalid COM port,
* then it means that no valid port was found.
*/
for (i = sizeof(BaseArray) / sizeof(BaseArray[0]) - 1; i > 0; i--)
{
if (CpDoesPortExist(UlongToPtr(BaseArray[i])))
{
PortInformation->Address = DefaultPort.Address = BaseArray[i];
ComPortNumber = (ULONG)i;
break;
}
}
if (ComPortNumber == 0)
{
sprintf(buffer,
"\nKernel Debugger: No COM port found!\n\n");
HalDisplayString(buffer);
return FALSE;
}
}
PortInitialized = TRUE;
}
#endif
/*
* Initialize the port
*/
Status = CpInitialize(PortInformation,
(ComPortNumber == 0 ? PortInformation->Address
: UlongToPtr(BaseArray[ComPortNumber])),
(PortInformation->BaudRate == 0 ? DEFAULT_BAUD_RATE
: PortInformation->BaudRate));
if (!NT_SUCCESS(Status))
{
sprintf(buffer,
"\nKernel Debugger: Serial port not found!\n\n");
HalDisplayString(buffer);
return FALSE;
}
else
{
#ifndef NDEBUG
/* Print message to blue screen */
sprintf(buffer,
"\nKernel Debugger: Serial port found: COM%ld (Port 0x%lx) BaudRate %ld\n\n",
ComPortNumber,
PortInformation->Address,
PortInformation->BaudRate);
HalDisplayString(buffer);
#endif /* NDEBUG */
#if 0
/* Set global info */
KdComPortInUse = DefaultPort.Address;
#endif
return TRUE;
}
}
BOOLEAN
NTAPI
KdPortGetByteEx(
IN PCPPORT PortInformation,
OUT PUCHAR ByteReceived)
{
return (CpGetByte(PortInformation, ByteReceived, FALSE) == CP_GET_SUCCESS);
}
VOID
NTAPI
KdPortPutByteEx(
IN PCPPORT PortInformation,
IN UCHAR ByteToSend)
{
CpPutByte(PortInformation, ByteToSend);
}
/* EOF */

View file

@ -16,7 +16,8 @@
/* VARIABLES ***************************************************************/
KD_PORT_INFORMATION PortInfo = {DEFAULT_DEBUG_PORT, DEFAULT_DEBUG_BAUD_RATE, 0};
ULONG PortNumber = DEFAULT_DEBUG_PORT;
CPPORT PortInfo = {0, DEFAULT_DEBUG_BAUD_RATE, 0};
ULONG KdpPortIrq;
#ifdef AUTO_ENABLE_BOCHS
KDP_DEBUG_MODE KdpDebugMode = {{{.Bochs=TRUE}}};
@ -68,7 +69,7 @@ KdpGetDebugMode(PCHAR Currentp2)
KdpDebugMode.Serial = TRUE;
/* Set the port to use */
SerialPortInfo.ComPort = Value;
SerialPortNumber = Value;
KdpPort = Value;
}
}
@ -78,8 +79,8 @@ KdpGetDebugMode(PCHAR Currentp2)
if (Value)
{
KdpDebugMode.Serial = TRUE;
SerialPortInfo.BaseAddress = Value;
SerialPortInfo.ComPort = 0;
SerialPortInfo.Address = UlongToPtr(Value);
SerialPortNumber = 0;
KdpPort = 0;
}
}

View file

@ -26,7 +26,8 @@ HANDLE KdpLogFileHandle;
ANSI_STRING KdpLogFileName = RTL_CONSTANT_STRING("\\SystemRoot\\debug.log");
KSPIN_LOCK KdpSerialSpinLock;
KD_PORT_INFORMATION SerialPortInfo = { DEFAULT_DEBUG_PORT, DEFAULT_DEBUG_BAUD_RATE, 0 };
ULONG SerialPortNumber = DEFAULT_DEBUG_PORT;
CPPORT SerialPortInfo = {0, DEFAULT_DEBUG_BAUD_RATE, 0};
/* Current Port in use. FIXME: Do we support more then one? */
ULONG KdpPort;
@ -358,12 +359,12 @@ KdpSerialInit(PKD_DISPATCH_TABLE DispatchTable,
DispatchTable->KdpPrintRoutine = KdpSerialDebugPrint;
/* Initialize the Port */
if (!KdPortInitializeEx(&SerialPortInfo, 0, 0))
if (!KdPortInitializeEx(&SerialPortInfo, SerialPortNumber))
{
KdpDebugMode.Serial = FALSE;
return;
}
KdComPortInUse = (PUCHAR)(ULONG_PTR)SerialPortInfo.BaseAddress;
KdComPortInUse = SerialPortInfo.Address;
/* Initialize spinlock */
KeInitializeSpinLock(&KdpSerialSpinLock);

View file

@ -44,7 +44,8 @@ static FAST_MUTEX GspLock;
extern LIST_ENTRY PsActiveProcessHead;
/* FIXME hardcoded for COM2, 115200 baud */
KD_PORT_INFORMATION GdbPortInfo = { 2, 115200, 0 };
ULONG GdbPortNumber = DEFAULT_DEBUG_PORT;
CPPORT GdbPortInfo = {0, DEFAULT_DEBUG_BAUD_RATE, 0};
static CHAR GspInBuffer[1000];
static CHAR GspOutBuffer[1000];
@ -126,9 +127,7 @@ GdbGetChar(VOID)
{
UCHAR Value;
while (!KdPortGetByteEx(&GdbPortInfo, &Value))
;
while (!KdPortGetByteEx(&GdbPortInfo, &Value)) ;
return Value;
}
@ -145,8 +144,7 @@ GspGetPacket()
while (TRUE)
{
/* wait around for the start character, ignore all other characters */
while ((ch = GdbGetChar()) != '$')
;
while ((ch = GdbGetChar()) != '$') ;
retry:
Checksum = 0;
@ -784,7 +782,6 @@ GspQuery(PCHAR Request)
}
else if (strncmp(Request, "Rcmd,", 5) == 0)
{
;
}
}
@ -943,12 +940,14 @@ GspFindSwBreakpoint(ULONG_PTR Address, PULONG PIndex)
ULONG Index;
for (Index = 0; Index < GspSwBreakpointCount; Index++)
{
if (GspSwBreakpoints[Index].Address == Address)
{
if (PIndex)
*PIndex = Index;
return TRUE;
}
}
return FALSE;
}
@ -1569,7 +1568,7 @@ KdpGdbStubInit(PKD_DISPATCH_TABLE WrapperTable, ULONG BootPhase)
WrapperTable->KdpExceptionRoutine = KdpGdbEnterDebuggerException;
/* Initialize the Port */
KdPortInitializeEx(&GdbPortInfo, 0, 0);
KdPortInitializeEx(&GdbPortInfo, GdbPortNumber);
}
else if (BootPhase == 1)
{

View file

@ -88,12 +88,8 @@
#include <debug.h>
/************************************************************************/
/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
/* at least NUMREGBYTES*2 are needed for register packets */
#define BUFMAX 1000
static BOOLEAN GspInitialized;
static BOOLEAN GspRemoteDebug;
static CONST CHAR HexChars[]="0123456789abcdef";
@ -107,25 +103,32 @@ static FAST_MUTEX GspLock;
extern LIST_ENTRY PsActiveProcessHead;
/* FIXME hardcoded for COM2, 115200 baud */
KD_PORT_INFORMATION GdbPortInfo = { 2, 115200, 0 };
ULONG GdbPortNumber = DEFAULT_DEBUG_PORT;
CPPORT GdbPortInfo = {0, DEFAULT_DEBUG_BAUD_RATE, 0};
/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
/* at least NUMREGBYTES*2 are needed for register packets */
#define BUFMAX 1000
static CHAR GspInBuffer[BUFMAX];
static CHAR GspOutBuffer[BUFMAX];
/* Number of Registers. */
#define NUMREGS 16
enum REGISTER_NAMES
{
EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI,
PC /* also known as eip */,
PS /* also known as eflags */,
CS, SS, DS, ES, FS, GS
EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI,
PC /* also known as eip */,
PS /* also known as eflags */,
CS, SS, DS, ES, FS, GS
};
typedef struct _CPU_REGISTER
{
ULONG Size;
ULONG OffsetInTF;
ULONG OffsetInContext;
BOOLEAN SetInContext;
ULONG Size;
ULONG OffsetInTF;
ULONG OffsetInContext;
BOOLEAN SetInContext;
} CPU_REGISTER, *PCPU_REGISTER;
static CPU_REGISTER GspRegisters[NUMREGS] =
@ -134,54 +137,45 @@ static CPU_REGISTER GspRegisters[NUMREGS] =
static PCHAR GspThreadStates[DeferredReady+1] =
{
"Initialized",
"Ready",
"Running",
"Standby",
"Terminated",
"Waiting",
"Transition",
"DeferredReady"
"Initialized",
"Ready",
"Running",
"Standby",
"Terminated",
"Waiting",
"Transition",
"DeferredReady"
};
LONG
HexValue(CHAR ch)
{
if ((ch >= '0') && (ch <= '9'))
{
return (ch - '0');
}
if ((ch >= 'a') && (ch <= 'f'))
{
return (ch - 'a' + 10);
}
if ((ch >= 'A') && (ch <= 'F'))
{
return (ch - 'A' + 10);
}
if ((ch >= '0') && (ch <= '9'))
return (ch - '0');
return -1;
if ((ch >= 'a') && (ch <= 'f'))
return (ch - 'a' + 10);
if ((ch >= 'A') && (ch <= 'F'))
return (ch - 'A' + 10);
return -1;
}
static CHAR GspInBuffer[BUFMAX];
static CHAR GspOutBuffer[BUFMAX];
VOID
GdbPutChar(UCHAR Value)
{
KdPortPutByteEx(&GdbPortInfo, Value);
KdPortPutByteEx(&GdbPortInfo, Value);
}
UCHAR
GdbGetChar(VOID)
{
UCHAR Value;
UCHAR Value;
while (!KdPortGetByteEx(&GdbPortInfo, &Value))
;
return Value;
while (!KdPortGetByteEx(&GdbPortInfo, &Value)) ;
return Value;
}
/* scan for the sequence $<data>#<Checksum> */
@ -189,57 +183,53 @@ GdbGetChar(VOID)
PCHAR
GspGetPacket()
{
PCHAR Buffer = &GspInBuffer[0];
CHAR Checksum;
CHAR XmitChecksum;
ULONG Count;
CHAR ch;
PCHAR Buffer = &GspInBuffer[0];
CHAR Checksum;
CHAR XmitChecksum;
ULONG Count;
CHAR ch;
while (TRUE)
while (TRUE)
{
/* wait around for the start character, ignore all other characters */
while ((ch = GdbGetChar ()) != '$')
;
/* wait around for the start character, ignore all other characters */
while ((ch = GdbGetChar ()) != '$') ;
retry:
Checksum = 0;
XmitChecksum = -1;
Count = 0;
retry:
Checksum = 0;
XmitChecksum = -1;
Count = 0;
/* now, read until a # or end of Buffer is found */
while (Count < BUFMAX)
/* now, read until a # or end of Buffer is found */
while (Count < BUFMAX)
{
ch = GdbGetChar();
if (ch == '$')
{
goto retry;
}
if (ch == '#')
{
break;
}
Checksum = Checksum + ch;
Buffer[Count] = ch;
Count = Count + 1;
ch = GdbGetChar();
if (ch == '$')
goto retry;
if (ch == '#')
break;
Checksum = Checksum + ch;
Buffer[Count] = ch;
Count = Count + 1;
}
Buffer[Count] = 0;
Buffer[Count] = 0;
if (ch == '#')
if (ch == '#')
{
ch = GdbGetChar();
XmitChecksum = (CHAR)(HexValue(ch) << 4);
ch = GdbGetChar();
XmitChecksum += (CHAR)(HexValue(ch));
ch = GdbGetChar();
XmitChecksum = (CHAR)(HexValue(ch) << 4);
ch = GdbGetChar();
XmitChecksum += (CHAR)(HexValue(ch));
if (Checksum != XmitChecksum)
if (Checksum != XmitChecksum)
{
GdbPutChar('-'); /* failed checksum */
GdbPutChar('-'); /* failed checksum */
}
else
else
{
GdbPutChar('+'); /* successful transfer */
return &Buffer[0];
GdbPutChar('+'); /* successful transfer */
return &Buffer[0];
}
}
}
@ -250,54 +240,54 @@ GspGetPacket()
VOID
GspPutPacket(PCHAR Buffer)
{
CHAR Checksum;
LONG Count;
CHAR ch;
CHAR Checksum;
LONG Count;
CHAR ch;
/* $<packet info>#<Checksum>. */
do
/* $<packet info>#<Checksum>. */
do
{
GdbPutChar('$');
Checksum = 0;
Count = 0;
GdbPutChar('$');
Checksum = 0;
Count = 0;
while ((ch = Buffer[Count]))
while ((ch = Buffer[Count]))
{
GdbPutChar(ch);
Checksum += ch;
Count += 1;
GdbPutChar(ch);
Checksum += ch;
Count += 1;
}
GdbPutChar('#');
GdbPutChar(HexChars[(Checksum >> 4) & 0xf]);
GdbPutChar(HexChars[Checksum & 0xf]);
GdbPutChar('#');
GdbPutChar(HexChars[(Checksum >> 4) & 0xf]);
GdbPutChar(HexChars[Checksum & 0xf]);
}
while (GdbGetChar() != '+');
while (GdbGetChar() != '+');
}
VOID
GspPutPacketNoWait(PCHAR Buffer)
{
CHAR Checksum;
LONG Count;
CHAR ch;
CHAR Checksum;
LONG Count;
CHAR ch;
/* $<packet info>#<Checksum>. */
GdbPutChar('$');
Checksum = 0;
Count = 0;
/* $<packet info>#<Checksum>. */
GdbPutChar('$');
Checksum = 0;
Count = 0;
while ((ch = Buffer[Count]))
while ((ch = Buffer[Count]))
{
GdbPutChar(ch);
Checksum += ch;
Count += 1;
GdbPutChar(ch);
Checksum += ch;
Count += 1;
}
GdbPutChar('#');
GdbPutChar(HexChars[(Checksum >> 4) & 0xf]);
GdbPutChar(HexChars[Checksum & 0xf]);
GdbPutChar('#');
GdbPutChar(HexChars[(Checksum >> 4) & 0xf]);
GdbPutChar(HexChars[Checksum & 0xf]);
}
/* Indicate to caller of GspMem2Hex or GspHex2Mem that there has been an
@ -308,19 +298,33 @@ static volatile void *GspAccessLocation = NULL;
static CHAR
GspReadMemSafe(PCHAR Address)
{
CHAR ch;
CHAR ch;
if (NULL == Address)
if (NULL == Address)
{
GspMemoryError = TRUE;
return '\0';
GspMemoryError = TRUE;
return '\0';
}
GspAccessLocation = Address;
ch = *Address;
GspAccessLocation = NULL;
GspAccessLocation = Address;
ch = *Address;
GspAccessLocation = NULL;
return ch;
return ch;
}
static CHAR
GspWriteMemSafeGetContent(PVOID Context, ULONG Offset)
{
ASSERT(0 == Offset);
return *((PCHAR) Context);
}
static void
GspWriteMemSafe(PCHAR Address,
CHAR Ch)
{
GspWriteMem(Address, 1, TRUE, GspWriteMemSafeGetContent, &Ch);
}
/* Convert the memory pointed to by Address into hex, placing result in Buffer */
@ -329,131 +333,110 @@ GspReadMemSafe(PCHAR Address)
a fault; if FALSE treat a fault like any other fault in the stub. */
static PCHAR
GspMem2Hex(PCHAR Address,
PCHAR Buffer,
LONG Count,
BOOLEAN MayFault)
PCHAR Buffer,
LONG Count,
BOOLEAN MayFault)
{
ULONG i;
CHAR ch;
ULONG i;
CHAR ch;
for (i = 0; i < (ULONG) Count; i++)
for (i = 0; i < (ULONG) Count; i++)
{
if (MayFault)
if (MayFault)
{
ch = GspReadMemSafe(Address);
if (GspMemoryError)
{
return Buffer;
}
ch = GspReadMemSafe(Address);
if (GspMemoryError)
return Buffer;
}
else
else
{
ch = *Address;
ch = *Address;
}
*Buffer++ = HexChars[(ch >> 4) & 0xf];
*Buffer++ = HexChars[ch & 0xf];
Address++;
*Buffer++ = HexChars[(ch >> 4) & 0xf];
*Buffer++ = HexChars[ch & 0xf];
Address++;
}
*Buffer = 0;
return Buffer;
*Buffer = 0;
return Buffer;
}
static ULONG
GspWriteMem(PCHAR Address,
ULONG Count,
BOOLEAN MayFault,
CHAR (*GetContent)(PVOID Context, ULONG Offset),
PVOID Context)
ULONG Count,
BOOLEAN MayFault,
CHAR (*GetContent)(PVOID Context, ULONG Offset),
PVOID Context)
{
PCHAR Current;
PCHAR Page;
ULONG CountInPage;
ULONG i;
CHAR ch;
ULONG OldProt = 0;
PCHAR Current;
PCHAR Page;
ULONG CountInPage;
ULONG i;
CHAR ch;
ULONG OldProt = 0;
Current = Address;
while (Current < Address + Count)
Current = Address;
while (Current < Address + Count)
{
Page = (PCHAR)PAGE_ROUND_DOWN(Current);
if (Address + Count <= Page + PAGE_SIZE)
Page = (PCHAR)PAGE_ROUND_DOWN(Current);
if (Address + Count <= Page + PAGE_SIZE)
{
/* Fits in this page */
CountInPage = Count;
/* Fits in this page */
CountInPage = Count;
}
else
else
{
/* Flows into next page, handle only current page in this iteration */
CountInPage = PAGE_SIZE - (Address - Page);
/* Flows into next page, handle only current page in this iteration */
CountInPage = PAGE_SIZE - (Address - Page);
}
if (MayFault)
if (MayFault)
{
OldProt = MmGetPageProtect(NULL, Address);
MmSetPageProtect(NULL, Address, PAGE_EXECUTE_READWRITE);
OldProt = MmGetPageProtect(NULL, Address);
MmSetPageProtect(NULL, Address, PAGE_EXECUTE_READWRITE);
}
for (i = 0; i < CountInPage && ! GspMemoryError; i++)
for (i = 0; i < CountInPage && ! GspMemoryError; i++)
{
ch = (*GetContent)(Context, Current - Address);
ch = (*GetContent)(Context, Current - Address);
if (MayFault)
{
GspAccessLocation = Current;
}
*Current = ch;
if (MayFault)
{
GspAccessLocation = NULL;
}
Current++;
if (MayFault)
GspAccessLocation = Current;
*Current = ch;
if (MayFault)
GspAccessLocation = NULL;
Current++;
}
if (MayFault)
if (MayFault)
{
MmSetPageProtect(NULL, Page, OldProt);
if (GspMemoryError)
{
return Current - Address;
}
MmSetPageProtect(NULL, Page, OldProt);
if (GspMemoryError)
return Current - Address;
}
}
return Current - Address;
return Current - Address;
}
static CHAR
GspHex2MemGetContent(PVOID Context, ULONG Offset)
{
return (CHAR)((HexValue(*((PCHAR) Context + 2 * Offset)) << 4) +
HexValue(*((PCHAR) Context + 2 * Offset + 1)));
return (CHAR)((HexValue(*((PCHAR) Context + 2 * Offset)) << 4) +
HexValue(*((PCHAR) Context + 2 * Offset + 1)));
}
/* Convert the hex array pointed to by Buffer into binary to be placed at Address */
/* Return a pointer to the character AFTER the last byte read from Buffer */
static PCHAR
GspHex2Mem(PCHAR Buffer,
PCHAR Address,
ULONG Count,
BOOLEAN MayFault)
PCHAR Address,
ULONG Count,
BOOLEAN MayFault)
{
Count = GspWriteMem(Address, Count, MayFault, GspHex2MemGetContent, Buffer);
return Buffer + 2 * Count;
}
static CHAR
GspWriteMemSafeGetContent(PVOID Context, ULONG Offset)
{
ASSERT(0 == Offset);
return *((PCHAR) Context);
}
static void
GspWriteMemSafe(PCHAR Address,
CHAR Ch)
{
GspWriteMem(Address, 1, TRUE, GspWriteMemSafeGetContent, &Ch);
Count = GspWriteMem(Address, Count, MayFault, GspHex2MemGetContent, Buffer);
return Buffer + 2 * Count;
}
@ -462,33 +445,38 @@ GspWriteMemSafe(PCHAR Address,
ULONG
GspComputeSignal(NTSTATUS ExceptionCode)
{
ULONG SigVal;
ULONG SigVal;
switch (ExceptionCode)
switch (ExceptionCode)
{
case STATUS_INTEGER_DIVIDE_BY_ZERO:
SigVal = 8; /* divide by zero */
break;
case STATUS_SINGLE_STEP:
case STATUS_BREAKPOINT:
SigVal = 5; /* breakpoint */
break;
case STATUS_INTEGER_OVERFLOW:
case STATUS_ARRAY_BOUNDS_EXCEEDED:
SigVal = 16; /* bound instruction */
break;
case STATUS_ILLEGAL_INSTRUCTION:
SigVal = 4; /* Invalid opcode */
break;
case STATUS_STACK_OVERFLOW:
case STATUS_DATATYPE_MISALIGNMENT:
case STATUS_ACCESS_VIOLATION:
SigVal = 11; /* access violation */
break;
default:
SigVal = 7; /* "software generated" */
case STATUS_INTEGER_DIVIDE_BY_ZERO:
SigVal = 8; /* divide by zero */
break;
case STATUS_SINGLE_STEP:
case STATUS_BREAKPOINT:
SigVal = 5; /* breakpoint */
break;
case STATUS_INTEGER_OVERFLOW:
case STATUS_ARRAY_BOUNDS_EXCEEDED:
SigVal = 16; /* bound instruction */
break;
case STATUS_ILLEGAL_INSTRUCTION:
SigVal = 4; /* Invalid opcode */
break;
case STATUS_STACK_OVERFLOW:
case STATUS_DATATYPE_MISALIGNMENT:
case STATUS_ACCESS_VIOLATION:
SigVal = 11; /* access violation */
break;
default:
SigVal = 7; /* "software generated" */
}
return SigVal;
return SigVal;
}
@ -1626,43 +1614,39 @@ KdpGdbEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord,
BOOLEAN
NTAPI
GspBreakIn(PKINTERRUPT Interrupt,
PVOID ServiceContext)
PVOID ServiceContext)
{
PKTRAP_FRAME TrapFrame;
BOOLEAN DoBreakIn;
CONTEXT Context;
KIRQL OldIrql;
UCHAR Value;
PKTRAP_FRAME TrapFrame;
BOOLEAN DoBreakIn;
CONTEXT Context;
KIRQL OldIrql;
UCHAR Value;
DPRINT("Break In\n");
DPRINT("Break In\n");
DoBreakIn = FALSE;
while (KdPortGetByteEx(&GdbPortInfo, &Value))
DoBreakIn = FALSE;
while (KdPortGetByteEx(&GdbPortInfo, &Value))
{
if (Value == 0x03)
{
DoBreakIn = TRUE;
}
if (Value == 0x03)
DoBreakIn = TRUE;
}
if (!DoBreakIn)
{
return TRUE;
}
if (!DoBreakIn)
return TRUE;
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
TrapFrame = PsGetCurrentThread()->Tcb.TrapFrame;
TrapFrame = PsGetCurrentThread()->Tcb.TrapFrame;
KeTrapFrameToContext(TrapFrame, NULL, &Context);
KeTrapFrameToContext(TrapFrame, NULL, &Context);
KdpGdbEnterDebuggerException(NULL, &Context, TrapFrame);
KdpGdbEnterDebuggerException(NULL, &Context, TrapFrame);
KeContextToTrapFrame(&Context, NULL, TrapFrame, Context.ContextFlags, KernelMode);
KeContextToTrapFrame(&Context, NULL, TrapFrame, Context.ContextFlags, KernelMode);
KeLowerIrql(OldIrql);
KeLowerIrql(OldIrql);
return TRUE;
return TRUE;
}
VOID
@ -1677,39 +1661,36 @@ NTAPI
KdpGdbStubInit(PKD_DISPATCH_TABLE WrapperTable,
ULONG BootPhase)
{
if (!KdDebuggerEnabled || !KdpDebugMode.Gdb)
if (!KdDebuggerEnabled || !KdpDebugMode.Gdb)
return;
if (BootPhase == 0)
{
return;
ExInitializeFastMutex(&GspLock);
/* Write out the functions that we support for now */
WrapperTable->KdpInitRoutine = KdpGdbStubInit;
WrapperTable->KdpPrintRoutine = KdpGdbDebugPrint;
WrapperTable->KdpExceptionRoutine = KdpGdbEnterDebuggerException;
/* Initialize the Port */
KdPortInitializeEx(&GdbPortInfo, GdbPortNumber);
// KdpPort = GdbPortInfo.ComPort;
}
if (BootPhase == 0)
else if (BootPhase == 1)
{
ExInitializeFastMutex(&GspLock);
GspInitialized = TRUE;
/* Write out the functions that we support for now */
WrapperTable->KdpInitRoutine = KdpGdbStubInit;
WrapperTable->KdpPrintRoutine = KdpGdbDebugPrint;
WrapperTable->KdpExceptionRoutine = KdpGdbEnterDebuggerException;
GspRunThread = NULL;
GspDbgThread = NULL;
GspEnumThread = NULL;
/* Initialize the Port */
KdPortInitializeEx(&GdbPortInfo, 0, 0);
KdpPort = GdbPortInfo.ComPort;
HalDisplayString("Waiting for GDB to attach\n");
DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
}
else if (BootPhase == 1)
else if (BootPhase == 2)
{
GspInitialized = TRUE;
GspRunThread = NULL;
GspDbgThread = NULL;
GspEnumThread = NULL;
HalDisplayString("Waiting for GDB to attach\n");
DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
}
else if (BootPhase == 2)
{
HalDisplayString("\n GDB debugging enabled\n\n");
HalDisplayString("\n GDB debugging enabled\n\n");
}
}

View file

@ -6,6 +6,10 @@
# define RTL_NUMBER_OF(x) (sizeof(x) / sizeof((x)[0]))
#endif
/* formerly located in kdbg/kdb_symbols.c */
#define TAG_KDBS 'SBDK'
#define TAG_KDBG 'GBDK'
/* TYPES *********************************************************************/
/* from kdb.c */