[NTOS:KD][NTOS:KD64][NTOS:KDBG] Fix IRQL & spinlock use

KD64: Raise to HIGH_LEVEL when entering trap
KDBG: lower to DISPATCH_LEVEL when applying IRQL hack & use a worker thread to load symbols
KD&KDBG: Actually unload symbols when required
This commit is contained in:
Jérôme Gardou 2021-06-22 19:46:27 +02:00 committed by Jérôme Gardou
parent 54ecf703f2
commit 835c30232e
10 changed files with 209 additions and 253 deletions

View file

@ -514,6 +514,11 @@ KdpDprintf(
... ...
); );
BOOLEAN
NTAPI
KdpPrintString(
_In_ PSTRING Output);
// //
// Global KD Data // Global KD Data
// //

View file

@ -580,13 +580,10 @@ KdSendPacket(
{ {
#ifdef KDBG #ifdef KDBG
PLDR_DATA_TABLE_ENTRY LdrEntry; PLDR_DATA_TABLE_ENTRY LdrEntry;
if (!WaitStateChange->u.LoadSymbols.UnloadSymbols) /* Load symbols. Currently implemented only for KDBG! */
if (KdbpSymFindModule((PVOID)(ULONG_PTR)WaitStateChange->u.LoadSymbols.BaseOfDll, -1, &LdrEntry))
{ {
/* Load symbols. Currently implemented only for KDBG! */ KdbSymProcessSymbols(LdrEntry, !WaitStateChange->u.LoadSymbols.UnloadSymbols);
if (KdbpSymFindModule((PVOID)(ULONG_PTR)WaitStateChange->u.LoadSymbols.BaseOfDll, NULL, -1, &LdrEntry))
{
KdbSymProcessSymbols(LdrEntry);
}
} }
#endif #endif
return; return;

View file

@ -445,7 +445,7 @@ KdpDprintf(
STRING String; STRING String;
USHORT Length; USHORT Length;
va_list ap; va_list ap;
CHAR Buffer[100]; CHAR Buffer[512];
/* Format the string */ /* Format the string */
va_start(ap, Format); va_start(ap, Format);

View file

@ -144,10 +144,11 @@ KdpTrap(IN PKTRAP_FRAME TrapFrame,
BOOLEAN Handled; BOOLEAN Handled;
NTSTATUS ReturnStatus; NTSTATUS ReturnStatus;
USHORT ReturnLength; USHORT ReturnLength;
KIRQL OldIrql; KIRQL OldIrql = DISPATCH_LEVEL;
/* Raise as high as we can. */ /* Raise if we have to. */
KeRaiseIrql(HIGH_LEVEL, &OldIrql); if (KeGetCurrentIrql() < DISPATCH_LEVEL)
OldIrql = KeRaiseIrqlToDpcLevel();
/* /*
* Check if we got a STATUS_BREAKPOINT with a SubID for Print, Prompt or * Check if we got a STATUS_BREAKPOINT with a SubID for Print, Prompt or
@ -261,7 +262,8 @@ KdpTrap(IN PKTRAP_FRAME TrapFrame,
SecondChanceException); SecondChanceException);
} }
KeLowerIrql(OldIrql); if (OldIrql < DISPATCH_LEVEL)
KeLowerIrql(OldIrql);
/* Return TRUE or FALSE to caller */ /* Return TRUE or FALSE to caller */
return Handled; return Handled;

View file

@ -1531,10 +1531,10 @@ KdbEnterDebuggerException(
OldEflags = __readeflags(); OldEflags = __readeflags();
_disable(); _disable();
/* HACK: Save the current IRQL and pretend we are at passive level, /* HACK: Save the current IRQL and pretend we are at dispatch level */
* although interrupts are off. Needed because KDBG calls pageable code. */
OldIrql = KeGetCurrentIrql(); OldIrql = KeGetCurrentIrql();
KeLowerIrql(PASSIVE_LEVEL); if (OldIrql > DISPATCH_LEVEL)
KeLowerIrql(DISPATCH_LEVEL);
/* Exception inside the debugger? Game over. */ /* Exception inside the debugger? Game over. */
if (InterlockedIncrement(&KdbEntryCount) > 1) if (InterlockedIncrement(&KdbEntryCount) > 1)
@ -1579,7 +1579,8 @@ KdbEnterDebuggerException(
InterlockedDecrement(&KdbEntryCount); InterlockedDecrement(&KdbEntryCount);
/* HACK: Raise back to old IRQL */ /* HACK: Raise back to old IRQL */
KeRaiseIrql(OldIrql, &OldIrql); if (OldIrql > DISPATCH_LEVEL)
KeRaiseIrql(OldIrql, &OldIrql);
/* Leave critical section */ /* Leave critical section */
__writeeflags(OldEflags); __writeeflags(OldEflags);

View file

@ -148,7 +148,6 @@ KdbpRpnEvaluateParsedExpression(
BOOLEAN BOOLEAN
KdbpSymFindModule( KdbpSymFindModule(
IN PVOID Address OPTIONAL, IN PVOID Address OPTIONAL,
IN LPCWSTR Name OPTIONAL,
IN INT Index OPTIONAL, IN INT Index OPTIONAL,
OUT PLDR_DATA_TABLE_ENTRY* pLdrEntry); OUT PLDR_DATA_TABLE_ENTRY* pLdrEntry);
@ -160,7 +159,8 @@ KdbSymPrintAddress(
VOID VOID
KdbSymProcessSymbols( KdbSymProcessSymbols(
IN PLDR_DATA_TABLE_ENTRY LdrEntry); _Inout_ PLDR_DATA_TABLE_ENTRY LdrEntry,
_In_ BOOLEAN Load);
/* from kdb.c */ /* from kdb.c */

View file

@ -1977,7 +1977,7 @@ KdbpCmdMod(
Address = (ULONG_PTR)Result; Address = (ULONG_PTR)Result;
if (!KdbpSymFindModule((PVOID)Address, NULL, -1, &LdrEntry)) if (!KdbpSymFindModule((PVOID)Address, -1, &LdrEntry))
{ {
KdbpPrint("No module containing address 0x%p found!\n", Address); KdbpPrint("No module containing address 0x%p found!\n", Address);
return TRUE; return TRUE;
@ -1987,7 +1987,7 @@ KdbpCmdMod(
} }
else else
{ {
if (!KdbpSymFindModule(NULL, NULL, 0, &LdrEntry)) if (!KdbpSymFindModule(NULL, 0, &LdrEntry))
{ {
ULONG_PTR ntoskrnlBase = ((ULONG_PTR)KdbpCmdMod) & 0xfff00000; ULONG_PTR ntoskrnlBase = ((ULONG_PTR)KdbpCmdMod) & 0xfff00000;
KdbpPrint(" Base Size Name\n"); KdbpPrint(" Base Size Name\n");
@ -2003,7 +2003,7 @@ KdbpCmdMod(
{ {
KdbpPrint(" %08x %08x %wZ\n", LdrEntry->DllBase, LdrEntry->SizeOfImage, &LdrEntry->BaseDllName); KdbpPrint(" %08x %08x %wZ\n", LdrEntry->DllBase, LdrEntry->SizeOfImage, &LdrEntry->BaseDllName);
if(DisplayOnlyOneModule || !KdbpSymFindModule(NULL, NULL, i++, &LdrEntry)) if(DisplayOnlyOneModule || !KdbpSymFindModule(NULL, i++, &LdrEntry))
break; break;
} }

View file

@ -27,27 +27,19 @@ typedef struct _IMAGE_SYMBOL_INFO_CACHE
IMAGE_SYMBOL_INFO_CACHE, *PIMAGE_SYMBOL_INFO_CACHE; IMAGE_SYMBOL_INFO_CACHE, *PIMAGE_SYMBOL_INFO_CACHE;
static BOOLEAN LoadSymbols; static BOOLEAN LoadSymbols;
static LIST_ENTRY SymbolFileListHead; static LIST_ENTRY SymbolsToLoad;
static KSPIN_LOCK SymbolFileListLock; static KSPIN_LOCK SymbolsToLoadLock;
BOOLEAN KdbpSymbolsInitialized = FALSE; static KEVENT SymbolsToLoadEvent;
/* FUNCTIONS ****************************************************************/ /* FUNCTIONS ****************************************************************/
static NTSTATUS static
KdbSymGetAddressInformation( BOOLEAN
IN PROSSYM_INFO RosSymInfo,
IN ULONG_PTR RelativeAddress,
OUT PULONG LineNumber OPTIONAL,
OUT PCH FileName OPTIONAL,
OUT PCH FunctionName OPTIONAL);
static BOOLEAN
KdbpSymSearchModuleList( KdbpSymSearchModuleList(
IN PLIST_ENTRY current_entry, IN PLIST_ENTRY current_entry,
IN PLIST_ENTRY end_entry, IN PLIST_ENTRY end_entry,
IN PLONG Count, IN PLONG Count,
IN PVOID Address, IN PVOID Address,
IN LPCWSTR Name,
IN INT Index, IN INT Index,
OUT PLDR_DATA_TABLE_ENTRY* pLdrEntry) OUT PLDR_DATA_TABLE_ENTRY* pLdrEntry)
{ {
@ -56,7 +48,6 @@ KdbpSymSearchModuleList(
*pLdrEntry = CONTAINING_RECORD(current_entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); *pLdrEntry = CONTAINING_RECORD(current_entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
if ((Address && Address >= (PVOID)(*pLdrEntry)->DllBase && Address < (PVOID)((ULONG_PTR)(*pLdrEntry)->DllBase + (*pLdrEntry)->SizeOfImage)) || if ((Address && Address >= (PVOID)(*pLdrEntry)->DllBase && Address < (PVOID)((ULONG_PTR)(*pLdrEntry)->DllBase + (*pLdrEntry)->SizeOfImage)) ||
(Name && !_wcsnicmp((*pLdrEntry)->BaseDllName.Buffer, Name, (*pLdrEntry)->BaseDllName.Length / sizeof(WCHAR))) ||
(Index >= 0 && (*Count)++ == Index)) (Index >= 0 && (*Count)++ == Index))
{ {
return TRUE; return TRUE;
@ -83,7 +74,6 @@ KdbpSymSearchModuleList(
BOOLEAN BOOLEAN
KdbpSymFindModule( KdbpSymFindModule(
IN PVOID Address OPTIONAL, IN PVOID Address OPTIONAL,
IN LPCWSTR Name OPTIONAL,
IN INT Index OPTIONAL, IN INT Index OPTIONAL,
OUT PLDR_DATA_TABLE_ENTRY* pLdrEntry) OUT PLDR_DATA_TABLE_ENTRY* pLdrEntry)
{ {
@ -91,16 +81,18 @@ KdbpSymFindModule(
PEPROCESS CurrentProcess; PEPROCESS CurrentProcess;
/* First try to look up the module in the kernel module list. */ /* First try to look up the module in the kernel module list. */
KeAcquireSpinLockAtDpcLevel(&PsLoadedModuleSpinLock);
if(KdbpSymSearchModuleList(PsLoadedModuleList.Flink, if(KdbpSymSearchModuleList(PsLoadedModuleList.Flink,
&PsLoadedModuleList, &PsLoadedModuleList,
&Count, &Count,
Address, Address,
Name,
Index, Index,
pLdrEntry)) pLdrEntry))
{ {
KeReleaseSpinLockFromDpcLevel(&PsLoadedModuleSpinLock);
return TRUE; return TRUE;
} }
KeReleaseSpinLockFromDpcLevel(&PsLoadedModuleSpinLock);
/* That didn't succeed. Try the module list of the current process now. */ /* That didn't succeed. Try the module list of the current process now. */
CurrentProcess = PsGetCurrentProcess(); CurrentProcess = PsGetCurrentProcess();
@ -112,11 +104,11 @@ KdbpSymFindModule(
&CurrentProcess->Peb->Ldr->InLoadOrderModuleList, &CurrentProcess->Peb->Ldr->InLoadOrderModuleList,
&Count, &Count,
Address, Address,
Name,
Index, Index,
pLdrEntry); pLdrEntry);
} }
static
PCHAR PCHAR
NTAPI NTAPI
KdbpSymUnicodeToAnsi(IN PUNICODE_STRING Unicode, KdbpSymUnicodeToAnsi(IN PUNICODE_STRING Unicode,
@ -159,233 +151,183 @@ KdbSymPrintAddress(
{ {
PLDR_DATA_TABLE_ENTRY LdrEntry; PLDR_DATA_TABLE_ENTRY LdrEntry;
ULONG_PTR RelativeAddress; ULONG_PTR RelativeAddress;
NTSTATUS Status; BOOLEAN Printed = FALSE;
ULONG LineNumber;
CHAR FileName[256];
CHAR FunctionName[256];
CHAR ModuleNameAnsi[64]; CHAR ModuleNameAnsi[64];
if (!KdbpSymbolsInitialized || !KdbpSymFindModule(Address, NULL, -1, &LdrEntry)) if (!KdbpSymFindModule(Address, -1, &LdrEntry))
return FALSE; return FALSE;
KdbpSymUnicodeToAnsi(&LdrEntry->BaseDllName,
ModuleNameAnsi,
sizeof(ModuleNameAnsi));
RelativeAddress = (ULONG_PTR)Address - (ULONG_PTR)LdrEntry->DllBase; RelativeAddress = (ULONG_PTR)Address - (ULONG_PTR)LdrEntry->DllBase;
Status = KdbSymGetAddressInformation(LdrEntry->PatchInformation,
RelativeAddress, KdbpSymUnicodeToAnsi(&LdrEntry->BaseDllName,
&LineNumber, ModuleNameAnsi,
FileName, sizeof(ModuleNameAnsi));
FunctionName);
if (NT_SUCCESS(Status)) if (LdrEntry->PatchInformation)
{ {
KdpDprintf("<%s:%x (%s:%d (%s))>", ULONG LineNumber;
ModuleNameAnsi, RelativeAddress, FileName, LineNumber, FunctionName); CHAR FileName[256];
CHAR FunctionName[256];
if (RosSymGetAddressInformation(LdrEntry->PatchInformation, RelativeAddress, &LineNumber, FileName, FunctionName))
{
STRING str;
/* Use KdpPrintString because KdpDprintf is limited wrt string size */
KdpDprintf("<%s:%x (", ModuleNameAnsi, RelativeAddress);
str.Buffer = FileName;
str.Length = strnlen(FileName, sizeof(FileName));
str.MaximumLength = sizeof(FileName);
KdpPrintString(&str);
KdpDprintf(":%d (%s))>", LineNumber, FunctionName);
Printed = TRUE;
}
} }
else
if (!Printed)
{ {
/* Just print module & address */
KdpDprintf("<%s:%x>", ModuleNameAnsi, RelativeAddress); KdpDprintf("<%s:%x>", ModuleNameAnsi, RelativeAddress);
} }
return TRUE; return TRUE;
} }
static KSTART_ROUTINE LoadSymbolsRoutine;
/*! \brief Get information for an address (source file, line number, /*! \brief The symbol loader thread routine.
* function name) * This opens the image file for reading and loads the symbols
* section from there.
* *
* \param SymbolInfo Pointer to ROSSYM_INFO. * \note We must do this because KdbSymProcessSymbols is
* \param RelativeAddress Relative address to look up. * called at high IRQL and we can't set the event from here
* \param LineNumber Pointer to an ULONG which is filled with the line
* number (can be NULL)
* \param FileName Pointer to an array of CHARs which gets filled with
* the filename (can be NULL)
* \param FunctionName Pointer to an array of CHARs which gets filled with
* the function name (can be NULL)
* *
* \returns NTSTATUS error code. * \param Context Unused
* \retval STATUS_SUCCESS At least one of the requested informations was found.
* \retval STATUS_UNSUCCESSFUL None of the requested information was found.
*/ */
static NTSTATUS _Use_decl_annotations_
KdbSymGetAddressInformation( VOID
IN PROSSYM_INFO RosSymInfo, NTAPI
IN ULONG_PTR RelativeAddress, LoadSymbolsRoutine(
OUT PULONG LineNumber OPTIONAL, _In_ PVOID Context)
OUT PCH FileName OPTIONAL,
OUT PCH FunctionName OPTIONAL)
{ {
if (!KdbpSymbolsInitialized || UNREFERENCED_PARAMETER(Context);
!RosSymInfo ||
!RosSymGetAddressInformation(RosSymInfo, RelativeAddress, LineNumber, FileName, FunctionName)) while (TRUE)
{ {
return STATUS_UNSUCCESSFUL; PLIST_ENTRY ListEntry;
} NTSTATUS Status = KeWaitForSingleObject(&SymbolsToLoadEvent, WrKernel, KernelMode, FALSE, NULL);
if (!NT_SUCCESS(Status))
return STATUS_SUCCESS;
}
/*! \brief Find cached symbol file.
*
* Looks through the list of cached symbol files and tries to find an already
* loaded one.
*
* \param FileName FileName of the symbol file to look for.
*
* \returns A pointer to the cached symbol info.
* \retval NULL No cached info found.
*
* \sa KdbpSymAddCachedFile
*/
static PROSSYM_INFO
KdbpSymFindCachedFile(
IN PUNICODE_STRING FileName)
{
PIMAGE_SYMBOL_INFO_CACHE Current;
PLIST_ENTRY CurrentEntry;
DPRINT("Looking for cached symbol file %wZ\n", FileName);
KeAcquireSpinLockAtDpcLevel(&SymbolFileListLock);
CurrentEntry = SymbolFileListHead.Flink;
while (CurrentEntry != (&SymbolFileListHead))
{
Current = CONTAINING_RECORD(CurrentEntry, IMAGE_SYMBOL_INFO_CACHE, ListEntry);
DPRINT("Current->FileName %wZ FileName %wZ\n", &Current->FileName, FileName);
if (RtlEqualUnicodeString(&Current->FileName, FileName, TRUE))
{ {
Current->RefCount++; DPRINT1("KeWaitForSingleObject failed?! 0x%08x\n", Status);
KeReleaseSpinLockFromDpcLevel(&SymbolFileListLock); LoadSymbols = FALSE;
DPRINT("Found cached file!\n");
return Current->RosSymInfo;
}
CurrentEntry = CurrentEntry->Flink;
}
KeReleaseSpinLockFromDpcLevel(&SymbolFileListLock);
DPRINT("Cached file not found!\n");
return NULL;
}
/*! \brief Add a symbol file to the cache.
*
* \param FileName Filename of the symbol file.
* \param RosSymInfo Pointer to the symbol info.
*
* \sa KdbpSymRemoveCachedFile
*/
static VOID
KdbpSymAddCachedFile(
IN PUNICODE_STRING FileName,
IN PROSSYM_INFO RosSymInfo)
{
PIMAGE_SYMBOL_INFO_CACHE CacheEntry;
KIRQL Irql;
DPRINT("Adding symbol file: RosSymInfo = %p\n", RosSymInfo);
/* allocate entry */
CacheEntry = ExAllocatePoolWithTag(NonPagedPool, sizeof (IMAGE_SYMBOL_INFO_CACHE), TAG_KDBS);
ASSERT(CacheEntry);
RtlZeroMemory(CacheEntry, sizeof (IMAGE_SYMBOL_INFO_CACHE));
/* fill entry */
CacheEntry->FileName.Buffer = ExAllocatePoolWithTag(NonPagedPool,
FileName->Length,
TAG_KDBS);
RtlCopyUnicodeString(&CacheEntry->FileName, FileName);
ASSERT(CacheEntry->FileName.Buffer);
CacheEntry->RefCount = 1;
CacheEntry->RosSymInfo = RosSymInfo;
KeAcquireSpinLock(&SymbolFileListLock, &Irql);
InsertTailList(&SymbolFileListHead, &CacheEntry->ListEntry);
KeReleaseSpinLock(&SymbolFileListLock, Irql);
}
/*! \brief Remove a symbol file (reference) from the cache.
*
* Tries to find a cache entry matching the given symbol info and decreases
* it's reference count. If the refcount is 0 after decreasing it the cache
* entry will be removed from the list and freed.
*
* \param RosSymInfo Pointer to the symbol info.
*
* \sa KdbpSymAddCachedFile
*/
static VOID
KdbpSymRemoveCachedFile(
IN PROSSYM_INFO RosSymInfo)
{
PIMAGE_SYMBOL_INFO_CACHE Current;
PLIST_ENTRY CurrentEntry;
KIRQL Irql;
KeAcquireSpinLock(&SymbolFileListLock, &Irql);
CurrentEntry = SymbolFileListHead.Flink;
while (CurrentEntry != (&SymbolFileListHead))
{
Current = CONTAINING_RECORD(CurrentEntry, IMAGE_SYMBOL_INFO_CACHE, ListEntry);
if (Current->RosSymInfo == RosSymInfo) /* found */
{
ASSERT(Current->RefCount > 0);
Current->RefCount--;
if (Current->RefCount < 1)
{
RemoveEntryList(&Current->ListEntry);
RosSymDelete(Current->RosSymInfo);
ExFreePool(Current);
}
KeReleaseSpinLock(&SymbolFileListLock, Irql);
return; return;
} }
CurrentEntry = CurrentEntry->Flink; while ((ListEntry = ExInterlockedRemoveHeadList(&SymbolsToLoad, &SymbolsToLoadLock)))
} {
PLDR_DATA_TABLE_ENTRY LdrEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks);
HANDLE FileHandle;
OBJECT_ATTRIBUTES Attrib;
IO_STATUS_BLOCK Iosb;
InitializeObjectAttributes(&Attrib, &LdrEntry->FullDllName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
DPRINT1("Trying %wZ\n", &LdrEntry->FullDllName);
Status = ZwOpenFile(&FileHandle,
FILE_READ_ACCESS | SYNCHRONIZE,
&Attrib,
&Iosb,
FILE_SHARE_READ,
FILE_SYNCHRONOUS_IO_NONALERT);
if (!NT_SUCCESS(Status))
{
/* Try system paths */
static const UNICODE_STRING System32Dir = RTL_CONSTANT_STRING(L"\\SystemRoot\\system32\\");
UNICODE_STRING ImagePath;
WCHAR ImagePathBuffer[256];
RtlInitEmptyUnicodeString(&ImagePath, ImagePathBuffer, sizeof(ImagePathBuffer));
RtlCopyUnicodeString(&ImagePath, &System32Dir);
RtlAppendUnicodeStringToString(&ImagePath, &LdrEntry->BaseDllName);
InitializeObjectAttributes(&Attrib, &ImagePath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
DPRINT1("Trying %wZ\n", &ImagePath);
Status = ZwOpenFile(&FileHandle,
FILE_READ_ACCESS | SYNCHRONIZE,
&Attrib,
&Iosb,
FILE_SHARE_READ,
FILE_SYNCHRONOUS_IO_NONALERT);
if (!NT_SUCCESS(Status))
{
static const UNICODE_STRING DriversDir= RTL_CONSTANT_STRING(L"\\SystemRoot\\system32\\drivers\\");
KeReleaseSpinLock(&SymbolFileListLock, Irql); RtlInitEmptyUnicodeString(&ImagePath, ImagePathBuffer, sizeof(ImagePathBuffer));
DPRINT1("Warning: Removing unknown symbol file: RosSymInfo = %p\n", RosSymInfo); RtlCopyUnicodeString(&ImagePath, &DriversDir);
RtlAppendUnicodeStringToString(&ImagePath, &LdrEntry->BaseDllName);
InitializeObjectAttributes(&Attrib, &ImagePath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
DPRINT1("Trying %wZ\n", &ImagePath);
Status = ZwOpenFile(&FileHandle,
FILE_READ_ACCESS | SYNCHRONIZE,
&Attrib,
&Iosb,
FILE_SHARE_READ,
FILE_SYNCHRONOUS_IO_NONALERT);
}
}
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed opening file %wZ (%wZ) for reading symbols (0x%08x)\n", &LdrEntry->FullDllName, &LdrEntry->BaseDllName, Status);
/* We took a ref previously */
MmUnloadSystemImage(LdrEntry);
continue;
}
/* Hand it to Rossym */
if (!RosSymCreateFromFile(&FileHandle, (PROSSYM_INFO*)&LdrEntry->PatchInformation))
LdrEntry->PatchInformation = NULL;
/* We're done for this one. */
NtClose(FileHandle);
MmUnloadSystemImage(LdrEntry);
}
}
} }
/*! \brief Load symbols from image mapping. If this fails,
*
* \param LdrEntry The entry to load symbols from
*/
VOID VOID
KdbSymProcessSymbols( KdbSymProcessSymbols(
IN PLDR_DATA_TABLE_ENTRY LdrEntry) _Inout_ PLDR_DATA_TABLE_ENTRY LdrEntry,
_In_ BOOLEAN Load)
{ {
if (!LoadSymbols) if (!LoadSymbols)
return;
/* Check if this is unload */
if (!Load)
{ {
LdrEntry->PatchInformation = NULL; /* Did we process it */
if (LdrEntry->PatchInformation)
{
RosSymDelete(LdrEntry->PatchInformation);
LdrEntry->PatchInformation = NULL;
}
return; return;
} }
/* Remove symbol info if it already exists */ if (RosSymCreateFromMem(LdrEntry->DllBase, LdrEntry->SizeOfImage, (PROSSYM_INFO*)&LdrEntry->PatchInformation))
if (LdrEntry->PatchInformation)
KdbpSymRemoveCachedFile(LdrEntry->PatchInformation);
/* Check cache */
LdrEntry->PatchInformation = KdbpSymFindCachedFile(&LdrEntry->FullDllName);
if (!LdrEntry->PatchInformation)
{ {
/* Load new symbol information */ return;
if (RosSymCreateFromMem(LdrEntry->DllBase, LdrEntry->SizeOfImage, (PROSSYM_INFO*)&LdrEntry->PatchInformation))
{
/* Add file to cache */
KdbpSymAddCachedFile(&LdrEntry->FullDllName, LdrEntry->PatchInformation);
}
} }
DPRINT("Installed symbols: %wZ@%p-%p %p\n", /* Add a ref until we really process it */
&LdrEntry->BaseDllName, LdrEntry->LoadCount++;
LdrEntry->DllBase,
(PVOID)(LdrEntry->SizeOfImage + (ULONG_PTR)LdrEntry->DllBase), /* Tell our worker thread to read from it */
LdrEntry->PatchInformation); KeAcquireSpinLockAtDpcLevel(&SymbolsToLoadLock);
InsertTailList(&SymbolsToLoad, &LdrEntry->InInitializationOrderLinks);
KeReleaseSpinLockFromDpcLevel(&SymbolsToLoadLock);
KeSetEvent(&SymbolsToLoadEvent, IO_NO_INCREMENT, FALSE);
} }
VOID VOID
@ -412,7 +354,6 @@ KdbInitialize(
PCHAR p1, p2; PCHAR p1, p2;
SHORT Found = FALSE; SHORT Found = FALSE;
CHAR YesNo; CHAR YesNo;
PLDR_DATA_TABLE_ENTRY LdrEntry;
DPRINT("KdbSymInit() BootPhase=%d\n", BootPhase); DPRINT("KdbSymInit() BootPhase=%d\n", BootPhase);
@ -437,9 +378,6 @@ KdbInitialize(
//NtoskrnlModuleObject->PatchInformation = NULL; //NtoskrnlModuleObject->PatchInformation = NULL;
//LdrHalModuleObject->PatchInformation = NULL; //LdrHalModuleObject->PatchInformation = NULL;
InitializeListHead(&SymbolFileListHead);
KeInitializeSpinLock(&SymbolFileListLock);
/* Check the command line for /LOADSYMBOLS, /NOLOADSYMBOLS, /* Check the command line for /LOADSYMBOLS, /NOLOADSYMBOLS,
* /LOADSYMBOLS={YES|NO}, /NOLOADSYMBOLS={YES|NO} */ * /LOADSYMBOLS={YES|NO}, /NOLOADSYMBOLS={YES|NO} */
ASSERT(KeLoaderBlock); ASSERT(KeLoaderBlock);
@ -481,24 +419,39 @@ KdbInitialize(
} }
p1 = p2; p1 = p2;
} }
}
else if ((BootPhase == 1) && LoadSymbols)
{
HANDLE Thread;
NTSTATUS Status;
KIRQL OldIrql;
/* Launch our worker thread */
InitializeListHead(&SymbolsToLoad);
KeInitializeSpinLock(&SymbolsToLoadLock);
KeInitializeEvent(&SymbolsToLoadEvent, SynchronizationEvent, FALSE);
Status = PsCreateSystemThread(&Thread, THREAD_ALL_ACCESS, NULL, NULL, NULL, LoadSymbolsRoutine, NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed starting symbols loader thread: 0x%08x\n", Status);
LoadSymbols = FALSE;
return;
}
RosSymInitKernelMode(); RosSymInitKernelMode();
}
else if (BootPhase == 1)
{
KIRQL OldIrql;
/* Load symbols for NTOSKRNL.EXE.
It is always the first module in PsLoadedModuleList. KeLoaderBlock can't be used here as its content is just temporary. */
OldIrql = KeRaiseIrqlToDpcLevel();
LdrEntry = CONTAINING_RECORD(PsLoadedModuleList.Flink, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
KdbSymProcessSymbols(LdrEntry);
/* Also load them for HAL.DLL. */ KeAcquireSpinLock(&PsLoadedModuleSpinLock, &OldIrql);
LdrEntry = CONTAINING_RECORD(PsLoadedModuleList.Flink->Flink, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
KdbSymProcessSymbols(LdrEntry);
KeLowerIrql(OldIrql);
KdbpSymbolsInitialized = TRUE; PLIST_ENTRY ListEntry = PsLoadedModuleList.Flink;
while (ListEntry != &PsLoadedModuleList)
{
PLDR_DATA_TABLE_ENTRY LdrEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
KdbSymProcessSymbols(LdrEntry, TRUE);
ListEntry = ListEntry->Flink;
}
KeReleaseSpinLock(&PsLoadedModuleSpinLock, OldIrql);
} }
} }

View file

@ -119,7 +119,12 @@ typedef struct _ROSSYM_OWN_FILECONTEXT {
struct Dwarf; struct Dwarf;
typedef struct Dwarf *PROSSYM_INFO; typedef struct Dwarf *PROSSYM_INFO;
#else #else
typedef struct _ROSSYM_INFO *PROSSYM_INFO; typedef struct _ROSSYM_INFO {
PROSSYM_ENTRY Symbols;
ULONG SymbolsCount;
PCHAR Strings;
ULONG StringsLength;
} ROSSYM_INFO, *PROSSYM_INFO;
#endif #endif
VOID RosSymInit(PROSSYM_CALLBACKS Callbacks); VOID RosSymInit(PROSSYM_CALLBACKS Callbacks);

View file

@ -9,13 +9,6 @@
#pragma once #pragma once
typedef struct _ROSSYM_INFO {
PROSSYM_ENTRY Symbols;
ULONG SymbolsCount;
PCHAR Strings;
ULONG StringsLength;
} ROSSYM_INFO;
extern ROSSYM_CALLBACKS RosSymCallbacks; extern ROSSYM_CALLBACKS RosSymCallbacks;
#define RosSymAllocMem(Size) (*RosSymCallbacks.AllocMemProc)(Size) #define RosSymAllocMem(Size) (*RosSymCallbacks.AllocMemProc)(Size)