https://git.reactos.org/?p=reactos.git;a=commitdiff;h=6cf426345b425e9328ebd…
commit 6cf426345b425e9328ebd0b481f955b994dc0cd8
Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Thu Nov 28 22:53:10 2024 +0100
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
CommitDate: Tue Dec 3 22:14:02 2024 +0100
[NTOS:KD64] Use KdpDprintf() instead of DbgPrint() for the debugger banner DPRINTs (#7540)
Override DbgPrint(), used by the debugger banner DPRINTs,
because KdInitSystem() can be called under the debugger lock
by KdEnableDebugger(WithLock)().
In this case, when DbgPrint() (re-)enters the debugger via an
interrupt and acquires the debugger lock, a deadlock occurs.
---
ntoskrnl/kd64/kdinit.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/ntoskrnl/kd64/kdinit.c b/ntoskrnl/kd64/kdinit.c
index a49655ff6cb..93f2bd7dfca 100644
--- a/ntoskrnl/kd64/kdinit.c
+++ b/ntoskrnl/kd64/kdinit.c
@@ -11,9 +11,18 @@
#include <ntoskrnl.h>
#include <reactos/buildno.h>
+
#define NDEBUG
#include <debug.h>
+/*
+ * Override DbgPrint(), used by the debugger banner DPRINTs below,
+ * because KdInitSystem() can be called under the debugger lock by
+ * KdEnableDebugger(WithLock)().
+ */
+#define DbgPrint(fmt, ...) (KdpDprintf(fmt, ##__VA_ARGS__), 0)
+#define DbgPrintEx(cmpid, lvl, fmt, ...) (KdpDprintf(fmt, ##__VA_ARGS__), 0)
+
/* UTILITY FUNCTIONS *********************************************************/
/*
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=1a02d3306b1a827dd3a05…
commit 1a02d3306b1a827dd3a059a68cdb7846dee391ad
Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Thu Nov 28 21:26:03 2024 +0100
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
CommitDate: Tue Dec 3 22:13:57 2024 +0100
[NTOS:KD64] Fix usage of the debugging banner code, based on when KdInitSystem() is called (#7540)
- The debugging banner helpers *CANNOT* be in the INIT section, because
it is possible for KdInitSystem() to enable the debugger **MUCH LATER**
after boot time. (Reverts part of commit f239ca0f0 (r72922).)
This can happen in two situations:
* When the debugger is in CRASHDEBUG mode, i.e. initialized at boot
time but not immediately enabled, and a BSOD happens later that
enables the debugger with a `KdInitSystem(0, NULL)` call.
* When the debugger was possibly manually disabled with a
KdDisableDebugger() call, then later re-enabled with a
KdEnableDebugger() call.
- In the same cases as described above, the KeLoaderBlock is freed after
boot time. Thus, KdpGetMemorySizeInMBs() cannot use it and enumerate
the MemoryDescriptors to evaluate the number of physical memory pages
available on the system. Instead, we can use what the memory manager
has already computed, since the latter is already initialized by now.
These two fixes avoid (invisible) crashes when (re-)enabling
the debugger at non-boot run time.
---
ntoskrnl/kd64/kdinit.c | 22 ++++++++++++++++------
1 file changed, 16 insertions(+), 6 deletions(-)
diff --git a/ntoskrnl/kd64/kdinit.c b/ntoskrnl/kd64/kdinit.c
index 917061995fe..a49655ff6cb 100644
--- a/ntoskrnl/kd64/kdinit.c
+++ b/ntoskrnl/kd64/kdinit.c
@@ -23,17 +23,27 @@
*
* Strongly inspired by:
* mm\ARM3\mminit.c : MiScanMemoryDescriptors(...)
- *
- * See also: kd\kdio.c
*/
-static CODE_SEG("INIT")
+static
SIZE_T
-KdpGetMemorySizeInMBs(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
+KdpGetMemorySizeInMBs(
+ _In_opt_ PLOADER_PARAMETER_BLOCK LoaderBlock)
{
PLIST_ENTRY ListEntry;
PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
SIZE_T NumberOfPhysicalPages = 0;
+ /*
+ * If no loader block is present (e.g. the debugger is initialized only
+ * much later after boot), just use the already-initialized Mm-computed
+ * number of physical pages. Otherwise do the evaluation ourselves.
+ */
+ if (!LoaderBlock)
+ {
+ NumberOfPhysicalPages = MmNumberOfPhysicalPages;
+ goto ReturnSize;
+ }
+
/* Loop the memory descriptors */
for (ListEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
ListEntry != &LoaderBlock->MemoryDescriptorListHead;
@@ -62,12 +72,12 @@ KdpGetMemorySizeInMBs(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
}
}
+ReturnSize:
/* Round size up. Assumed to better match actual physical RAM size */
return ALIGN_UP_BY(NumberOfPhysicalPages * PAGE_SIZE, 1024 * 1024) / (1024 * 1024);
}
-/* See also: kd\kdio.c */
-static CODE_SEG("INIT")
+static
VOID
KdpPrintBanner(IN SIZE_T MemSizeMBs)
{
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=76d35dde1d7ba3c5785a9…
commit 76d35dde1d7ba3c5785a90897fd01001eb301bba
Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Thu Nov 28 19:42:06 2024 +0100
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
CommitDate: Tue Dec 3 19:29:12 2024 +0100
[NTOS:KD64] KdInitSystem(): Poll for break-in on symbol load *ONLY* at boot-time (#7539)
I.e. when LoaderBlock != NULL and we have loaded the initial hal and
ntoskrnl symbols. KdBreakAfterSymbolLoad is then checked for when the
other boot symbols have been loaded by ex/init.c!ExpLoadBootSymbols(),
invoked by ExpInitializeExecutive().
---
ntoskrnl/kd64/kdinit.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/ntoskrnl/kd64/kdinit.c b/ntoskrnl/kd64/kdinit.c
index 4f49b48ef28..917061995fe 100644
--- a/ntoskrnl/kd64/kdinit.c
+++ b/ntoskrnl/kd64/kdinit.c
@@ -208,7 +208,7 @@ KdInitSystem(
KdVersionBlock.Unused[0] = 0;
/* Link us in the KPCR */
- KeGetPcr()->KdVersionBlock = &KdVersionBlock;
+ KeGetPcr()->KdVersionBlock = &KdVersionBlock;
}
/* Check if we have a loader block */
@@ -445,10 +445,11 @@ KdInitSystem(
NextEntry = NextEntry->Flink;
i++;
}
- }
- /* Check for incoming breakin and break on symbol load if we have it */
- KdBreakAfterSymbolLoad = KdPollBreakIn();
+ /* Check for incoming break-in and break on symbol load
+ * if requested, see ex/init.c!ExpLoadBootSymbols() */
+ KdBreakAfterSymbolLoad = KdPollBreakIn();
+ }
}
else
{
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=61feb649d188f6a998477…
commit 61feb649d188f6a998477240cfe27712e5e72ac6
Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Fri Nov 22 16:19:41 2024 +0100
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
CommitDate: Tue Dec 3 19:02:21 2024 +0100
[NTOS:KD64] kdx86.c: Fix Dr7 check to verify whether debugger disabling is allowed (#7538)
Don't check the whole Dr7 value, but only the first 8 bits that
correspond to the local/global enable breakpoints.
We cannot check the whole value because some of the Dr7 bits are
reserved always set to 1 (bit 10), or describe other debug state.
References:
- https://en.wikipedia.org/wiki/X86_debug_register#DR7_-_Debug_control
- Intel® 64 and IA-32 Architectures Software Developer’s Manual,
Volume 3 (3A, 3B, 3C, & 3D): System Programming Guide
https://www.intel.com/content/www/us/en/developer/articles/technical/intel-…
Section "19.2.4 Debug Control Register (DR7)" (pgs. 644-646)
---
ntoskrnl/kd64/i386/kdx86.c | 16 ++++++----------
1 file changed, 6 insertions(+), 10 deletions(-)
diff --git a/ntoskrnl/kd64/i386/kdx86.c b/ntoskrnl/kd64/i386/kdx86.c
index a70eb464103..843f6e88b0d 100644
--- a/ntoskrnl/kd64/i386/kdx86.c
+++ b/ntoskrnl/kd64/i386/kdx86.c
@@ -426,23 +426,19 @@ NTSTATUS
NTAPI
KdpAllowDisable(VOID)
{
- LONG i;
- ULONG Dr7;
+ ULONG i;
/* Loop every processor */
for (i = 0; i < KeNumberProcessors; i++)
{
- /* Get its DR7 */
- Dr7 = KiProcessorBlock[i]->ProcessorState.SpecialRegisters.KernelDr7;
+ PKPROCESSOR_STATE ProcessorState = &KiProcessorBlock[i]->ProcessorState;
- /* Check if any processor breakpoints are active */
- if (Dr7 != 0)
- {
- /* We can't allow running without a debugger then */
+ /* If any processor breakpoints are active,
+ * we can't allow running without a debugger */
+ if (ProcessorState->SpecialRegisters.KernelDr7 & 0xFF)
return STATUS_ACCESS_DENIED;
- }
}
- /* No processor breakpoints; allow disabling the debugger */
+ /* No processor breakpoints, allow disabling the debugger */
return STATUS_SUCCESS;
}
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=dfb43905bbdacc277044b…
commit dfb43905bbdacc277044ba7ded8b7df4d2f741c3
Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Mon Nov 25 23:12:13 2024 +0100
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
CommitDate: Tue Dec 3 13:13:38 2024 +0100
[FREELDR] peloader.c: Fix PE import binding (#7537)
Use the PE import table's OriginalFirstThunk array when scanning and
resolving imports during DLL binding.
It points to an array of pointer-sized IMAGE_THUNK_DATA structures
which describe the functions being imported. On the other hand, the
FirstThunk points to an array of pointers, whose initial values are
a copy of those pointed to by OriginalFirstThunk, but are replaced
by the actual function pointers determined at runtime, when a DLL
is loaded (see PeLdrpBindImportName() function).
If we were to use the FirstThunk array to find again later the imports
by name or ordinal, we would fail because these are replaced by the
addresses of the corresponding functions.
This fixes loading kdcom.dll from Windows XP x64 with FreeLDR when
testing on ReactOS x64.
```diff
(freeldr\freeldr\lib\peloader.c:498) trace: PeLdrpScanImportAddressTable() ---- Calling PeLdrpBindImportName() in a loop
(freeldr\freeldr\lib\peloader.c:501) trace: *** ThunkName->u1.AddressOfData = 00000000000070F0
(freeldr\freeldr\lib\peloader.c:502) trace: *** ThunkData->u1.AddressOfData = 0000000000573780
(freeldr\freeldr\lib\peloader.c:209) trace: !!! ExportDirectory->NumberOfNames 1504
-(freeldr\freeldr\lib\peloader.c:210) trace: !!! ImportHint 0 - ExportName 'CcCanIWrite' - ImportDataName ''
+(freeldr\freeldr\lib\peloader.c:210) trace: !!! ImportHint 282 - ExportName 'HalPrivateDispatchTable' - ImportDataName 'HalPrivateDispatchTable'
....
-(freeldr\freeldr\lib\peloader.c:268) err: Did not find export ''!
-(freeldr\freeldr\lib\peloader.c:709) err: PeLdrpScanImportAddressTable() failed: ImportName = 'ntoskrnl.exe', DirectoryPath = 'multi(0)disk(0)rdisk(0)partition(2)\ReactOS\system32\'
```
('-': lines before the fix; '+': lines after the fix)
Code has been adapted based from the following functions:
ntdll/ldr/ldrpe.c!LdrpSnapThunk() and LdrpSnapIAT()
ntoskrnl/mm/ARM3/sysldr.c!MiSnapThunk() and MiResolveImageReferences()
References:
https://devblogs.microsoft.com/oldnewthing/20231129-00/?p=109077https://devblogs.microsoft.com/oldnewthing/20231130-00/?p=109084https://stackoverflow.com/questions/42413937/why-pe-need-original-first-thu…
---
boot/freeldr/freeldr/lib/peloader.c | 62 +++++++++++++++++++++----------------
1 file changed, 36 insertions(+), 26 deletions(-)
diff --git a/boot/freeldr/freeldr/lib/peloader.c b/boot/freeldr/freeldr/lib/peloader.c
index 2096792c05e..06bcf41720b 100644
--- a/boot/freeldr/freeldr/lib/peloader.c
+++ b/boot/freeldr/freeldr/lib/peloader.c
@@ -139,6 +139,7 @@ PeLdrpBindImportName(
_Inout_ PLIST_ENTRY ModuleListHead,
_In_ PVOID DllBase,
_In_ PVOID ImageBase,
+ _In_ PIMAGE_THUNK_DATA ThunkName,
_Inout_ PIMAGE_THUNK_DATA ThunkData,
_In_ PIMAGE_EXPORT_DIRECTORY ExportDirectory,
_In_ ULONG ExportSize,
@@ -155,8 +156,9 @@ PeLdrpBindImportName(
PCHAR ExportName, ForwarderName;
BOOLEAN Success;
- //TRACE("PeLdrpBindImportName(): DllBase 0x%p, ImageBase 0x%p, ThunkData 0x%p, ExportDirectory 0x%p, ExportSize %d, ProcessForwards 0x%X\n",
- // DllBase, ImageBase, ThunkData, ExportDirectory, ExportSize, ProcessForwards);
+ //TRACE("PeLdrpBindImportName(): "
+ // "DllBase 0x%p, ImageBase 0x%p, ThunkName 0x%p, ThunkData 0x%p, ExportDirectory 0x%p, ExportSize %d, ProcessForwards 0x%X\n",
+ // DllBase, ImageBase, ThunkName, ThunkData, ExportDirectory, ExportSize, ProcessForwards);
/* Check passed DllBase */
if (!DllBase)
@@ -166,13 +168,14 @@ PeLdrpBindImportName(
}
/* Convert all non-critical pointers to PA from VA */
+ ThunkName = VaToPa(ThunkName);
ThunkData = VaToPa(ThunkData);
/* Is the reference by ordinal? */
- if (IMAGE_SNAP_BY_ORDINAL(ThunkData->u1.Ordinal) && !ProcessForwards)
+ if (IMAGE_SNAP_BY_ORDINAL(ThunkName->u1.Ordinal) && !ProcessForwards)
{
/* Yes, calculate the ordinal */
- Ordinal = (ULONG)(IMAGE_ORDINAL(ThunkData->u1.Ordinal) - (UINT32)ExportDirectory->Base);
+ Ordinal = (ULONG)(IMAGE_ORDINAL(ThunkName->u1.Ordinal) - (UINT32)ExportDirectory->Base);
//TRACE("PeLdrpBindImportName(): Ordinal %d\n", Ordinal);
}
else
@@ -181,14 +184,14 @@ PeLdrpBindImportName(
if (!ProcessForwards)
{
/* AddressOfData in thunk entry will become a virtual address (from relative) */
- //TRACE("PeLdrpBindImportName(): ThunkData->u1.AOD was %p\n", ThunkData->u1.AddressOfData);
- ThunkData->u1.AddressOfData =
- (ULONG_PTR)RVA(ImageBase, ThunkData->u1.AddressOfData);
- //TRACE("PeLdrpBindImportName(): ThunkData->u1.AOD became %p\n", ThunkData->u1.AddressOfData);
+ //TRACE("PeLdrpBindImportName(): ThunkName->u1.AOD was %p\n", ThunkName->u1.AddressOfData);
+ ThunkName->u1.AddressOfData =
+ (ULONG_PTR)RVA(ImageBase, ThunkName->u1.AddressOfData);
+ //TRACE("PeLdrpBindImportName(): ThunkName->u1.AOD became %p\n", ThunkName->u1.AddressOfData);
}
- /* Get the import name */
- ImportData = VaToPa((PVOID)ThunkData->u1.AddressOfData);
+ /* Get the import name, convert it to a physical pointer */
+ ImportData = VaToPa((PVOID)ThunkName->u1.AddressOfData);
/* Get pointers to Name and Ordinal tables (RVA -> VA) */
NameTable = VaToPa(RVA(DllBase, ExportDirectory->AddressOfNames));
@@ -197,8 +200,8 @@ PeLdrpBindImportName(
//TRACE("NameTable 0x%X, OrdinalTable 0x%X, ED->AddressOfNames 0x%X, ED->AOFO 0x%X\n",
// NameTable, OrdinalTable, ExportDirectory->AddressOfNames, ExportDirectory->AddressOfNameOrdinals);
- /* Get the hint, convert it to a physical pointer */
- Hint = ((PIMAGE_IMPORT_BY_NAME)VaToPa((PVOID)ThunkData->u1.AddressOfData))->Hint;
+ /* Get the hint */
+ Hint = ImportData->Hint;
//TRACE("HintIndex %d\n", Hint);
/* Get the export name from the hint */
@@ -358,6 +361,7 @@ PeLdrpBindImportName(
DataTableEntry->DllBase,
ImageBase,
&RefThunkData,
+ &RefThunkData,
RefExportDirectory,
RefExportSize,
TRUE,
@@ -451,6 +455,7 @@ PeLdrpScanImportAddressTable(
_Inout_ PLIST_ENTRY ModuleListHead,
_In_ PVOID DllBase,
_In_ PVOID ImageBase,
+ _In_ PIMAGE_THUNK_DATA ThunkName,
_Inout_ PIMAGE_THUNK_DATA ThunkData,
_In_ PCSTR DirectoryPath,
_In_ PLIST_ENTRY Parent)
@@ -460,8 +465,8 @@ PeLdrpScanImportAddressTable(
ULONG ExportSize;
TRACE("PeLdrpScanImportAddressTable(): "
- "DllBase 0x%p, ImageBase 0x%p, ThunkData 0x%p\n",
- DllBase, ImageBase, ThunkData);
+ "DllBase 0x%p, ImageBase 0x%p, ThunkName 0x%p, ThunkData 0x%p\n",
+ DllBase, ImageBase, ThunkName, ThunkData);
/* Obtain the export table from the DLL's base */
if (!DllBase)
@@ -486,26 +491,27 @@ PeLdrpScanImportAddressTable(
return FALSE;
}
- /* Go through each entry in the thunk table and bind it */
- while (((PIMAGE_THUNK_DATA)VaToPa(ThunkData))->u1.AddressOfData != 0)
+ /* Go through each thunk in the table and bind it */
+ while (((PIMAGE_THUNK_DATA)VaToPa(ThunkName))->u1.AddressOfData != 0)
{
/* Bind it */
Success = PeLdrpBindImportName(ModuleListHead,
DllBase,
ImageBase,
+ ThunkName,
ThunkData,
ExportDirectory,
ExportSize,
FALSE,
DirectoryPath,
Parent);
-
- /* Move to the next entry */
- ThunkData++;
-
- /* Return error if binding was unsuccessful */
+ /* Fail if binding was unsuccessful */
if (!Success)
return Success;
+
+ /* Move to the next thunk */
+ ThunkName++;
+ ThunkData++;
}
/* Return success */
@@ -649,13 +655,16 @@ PeLdrScanImportDescriptorTable(
}
#endif
- /* If image doesn't have any import directory - just return success */
- if (ImportTable == NULL)
+ /* If the image doesn't have any import directory, just return success */
+ if (!ImportTable)
return TRUE;
- /* Loop through all entries */
- for (;(ImportTable->Name != 0) && (ImportTable->FirstThunk != 0);ImportTable++)
+ /* Loop through all the entries */
+ for (;(ImportTable->Name != 0) && (ImportTable->OriginalFirstThunk != 0);ImportTable++)
{
+ PIMAGE_THUNK_DATA ThunkName = RVA(ScanDTE->DllBase, ImportTable->OriginalFirstThunk);
+ PIMAGE_THUNK_DATA ThunkData = RVA(ScanDTE->DllBase, ImportTable->FirstThunk);
+
/* Get pointer to the name */
ImportName = (PCH)VaToPa(RVA(ScanDTE->DllBase, ImportTable->Name));
TRACE("PeLdrScanImportDescriptorTable(): Looking at %s\n", ImportName);
@@ -683,7 +692,8 @@ PeLdrScanImportDescriptorTable(
Success = PeLdrpScanImportAddressTable(ModuleListHead,
DataTableEntry->DllBase,
ScanDTE->DllBase,
- (PIMAGE_THUNK_DATA)RVA(ScanDTE->DllBase, ImportTable->FirstThunk),
+ ThunkName,
+ ThunkData,
DirectoryPath,
&ScanDTE->InLoadOrderLinks);