mirror of
https://github.com/reactos/reactos.git
synced 2025-04-27 09:00:27 +00:00
[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:
parent
54ecf703f2
commit
835c30232e
10 changed files with 209 additions and 253 deletions
|
@ -514,6 +514,11 @@ KdpDprintf(
|
||||||
...
|
...
|
||||||
);
|
);
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
NTAPI
|
||||||
|
KdpPrintString(
|
||||||
|
_In_ PSTRING Output);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Global KD Data
|
// Global KD Data
|
||||||
//
|
//
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue