Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenkdb_symbols.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS kernel 00004 * FILE: ntoskrnl/dbg/kdb_symbols.c 00005 * PURPOSE: Getting symbol information... 00006 * 00007 * PROGRAMMERS: David Welch (welch@cwcom.net) 00008 * Colin Finck (colin@reactos.org) 00009 */ 00010 00011 /* INCLUDES *****************************************************************/ 00012 00013 #include <ntoskrnl.h> 00014 00015 #define NDEBUG 00016 #include <debug.h> 00017 00018 /* GLOBALS ******************************************************************/ 00019 00020 typedef struct _IMAGE_SYMBOL_INFO_CACHE 00021 { 00022 LIST_ENTRY ListEntry; 00023 ULONG RefCount; 00024 UNICODE_STRING FileName; 00025 PROSSYM_INFO RosSymInfo; 00026 } 00027 IMAGE_SYMBOL_INFO_CACHE, *PIMAGE_SYMBOL_INFO_CACHE; 00028 00029 static BOOLEAN LoadSymbols; 00030 static LIST_ENTRY SymbolFileListHead; 00031 static KSPIN_LOCK SymbolFileListLock; 00032 BOOLEAN KdbpSymbolsInitialized = FALSE; 00033 00034 /* FUNCTIONS ****************************************************************/ 00035 00036 static BOOLEAN 00037 KdbpSymSearchModuleList( 00038 IN PLIST_ENTRY current_entry, 00039 IN PLIST_ENTRY end_entry, 00040 IN PLONG Count, 00041 IN PVOID Address, 00042 IN LPCWSTR Name, 00043 IN INT Index, 00044 OUT PLDR_DATA_TABLE_ENTRY* pLdrEntry) 00045 { 00046 while (current_entry && current_entry != end_entry) 00047 { 00048 *pLdrEntry = CONTAINING_RECORD(current_entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); 00049 00050 if ((Address && Address >= (PVOID)(*pLdrEntry)->DllBase && Address < (PVOID)((ULONG_PTR)(*pLdrEntry)->DllBase + (*pLdrEntry)->SizeOfImage)) || 00051 (Name && !_wcsnicmp((*pLdrEntry)->BaseDllName.Buffer, Name, (*pLdrEntry)->BaseDllName.Length / sizeof(WCHAR))) || 00052 (Index >= 0 && (*Count)++ == Index)) 00053 { 00054 return TRUE; 00055 } 00056 00057 current_entry = current_entry->Flink; 00058 } 00059 00060 return FALSE; 00061 } 00062 00075 BOOLEAN 00076 KdbpSymFindModule( 00077 IN PVOID Address OPTIONAL, 00078 IN LPCWSTR Name OPTIONAL, 00079 IN INT Index OPTIONAL, 00080 OUT PLDR_DATA_TABLE_ENTRY* pLdrEntry) 00081 { 00082 LONG Count = 0; 00083 PEPROCESS CurrentProcess; 00084 00085 /* First try to look up the module in the kernel module list. */ 00086 if(KdbpSymSearchModuleList(PsLoadedModuleList.Flink, 00087 &PsLoadedModuleList, 00088 &Count, 00089 Address, 00090 Name, 00091 Index, 00092 pLdrEntry)) 00093 { 00094 return TRUE; 00095 } 00096 00097 /* That didn't succeed. Try the module list of the current process now. */ 00098 CurrentProcess = PsGetCurrentProcess(); 00099 00100 if(!CurrentProcess || !CurrentProcess->Peb || !CurrentProcess->Peb->Ldr) 00101 return FALSE; 00102 00103 return KdbpSymSearchModuleList(CurrentProcess->Peb->Ldr->InLoadOrderModuleList.Flink, 00104 &CurrentProcess->Peb->Ldr->InLoadOrderModuleList, 00105 &Count, 00106 Address, 00107 Name, 00108 Index, 00109 pLdrEntry); 00110 } 00111 00112 PCHAR 00113 NTAPI 00114 KdbpSymUnicodeToAnsi(IN PUNICODE_STRING Unicode, 00115 OUT PCHAR Ansi, 00116 IN ULONG Length) 00117 { 00118 PCHAR p; 00119 PWCHAR pw; 00120 ULONG i; 00121 00122 /* Set length and normalize it */ 00123 i = Unicode->Length / sizeof(WCHAR); 00124 i = min(i, Length - 1); 00125 00126 /* Set source and destination, and copy */ 00127 pw = Unicode->Buffer; 00128 p = Ansi; 00129 while (i--) *p++ = (CHAR)*pw++; 00130 00131 /* Null terminate and return */ 00132 *p = ANSI_NULL; 00133 return Ansi; 00134 } 00135 00147 BOOLEAN 00148 KdbSymPrintAddress( 00149 IN PVOID Address, 00150 IN PKTRAP_FRAME Context) 00151 { 00152 PLDR_DATA_TABLE_ENTRY LdrEntry; 00153 ULONG_PTR RelativeAddress; 00154 NTSTATUS Status; 00155 ULONG LineNumber; 00156 CHAR FileName[256]; 00157 CHAR FunctionName[256]; 00158 CHAR ModuleNameAnsi[64]; 00159 00160 if (!KdbpSymbolsInitialized || !KdbpSymFindModule(Address, NULL, -1, &LdrEntry)) 00161 return FALSE; 00162 00163 KdbpSymUnicodeToAnsi(&LdrEntry->BaseDllName, 00164 ModuleNameAnsi, 00165 sizeof(ModuleNameAnsi)); 00166 00167 RelativeAddress = (ULONG_PTR)Address - (ULONG_PTR)LdrEntry->DllBase; 00168 Status = KdbSymGetAddressInformation(LdrEntry->PatchInformation, 00169 RelativeAddress, 00170 &LineNumber, 00171 FileName, 00172 FunctionName); 00173 if (NT_SUCCESS(Status)) 00174 { 00175 DbgPrint("<%s:%x (%s:%d (%s))>", 00176 ModuleNameAnsi, RelativeAddress, FileName, LineNumber, FunctionName); 00177 } 00178 else 00179 { 00180 DbgPrint("<%s:%x>", ModuleNameAnsi, RelativeAddress); 00181 } 00182 00183 return TRUE; 00184 } 00185 00186 00203 NTSTATUS 00204 KdbSymGetAddressInformation( 00205 IN PROSSYM_INFO RosSymInfo, 00206 IN ULONG_PTR RelativeAddress, 00207 OUT PULONG LineNumber OPTIONAL, 00208 OUT PCH FileName OPTIONAL, 00209 OUT PCH FunctionName OPTIONAL) 00210 { 00211 if (!KdbpSymbolsInitialized || 00212 !RosSymInfo || 00213 !RosSymGetAddressInformation(RosSymInfo, RelativeAddress, LineNumber, FileName, FunctionName)) 00214 { 00215 return STATUS_UNSUCCESSFUL; 00216 } 00217 00218 return STATUS_SUCCESS; 00219 } 00220 00233 static PROSSYM_INFO 00234 KdbpSymFindCachedFile( 00235 IN PUNICODE_STRING FileName) 00236 { 00237 PIMAGE_SYMBOL_INFO_CACHE Current; 00238 PLIST_ENTRY CurrentEntry; 00239 KIRQL Irql; 00240 00241 DPRINT("Looking for cached symbol file %wZ\n", FileName); 00242 00243 KeAcquireSpinLock(&SymbolFileListLock, &Irql); 00244 00245 CurrentEntry = SymbolFileListHead.Flink; 00246 while (CurrentEntry != (&SymbolFileListHead)) 00247 { 00248 Current = CONTAINING_RECORD(CurrentEntry, IMAGE_SYMBOL_INFO_CACHE, ListEntry); 00249 00250 DPRINT("Current->FileName %wZ FileName %wZ\n", &Current->FileName, FileName); 00251 if (RtlEqualUnicodeString(&Current->FileName, FileName, TRUE)) 00252 { 00253 Current->RefCount++; 00254 KeReleaseSpinLock(&SymbolFileListLock, Irql); 00255 DPRINT("Found cached file!\n"); 00256 return Current->RosSymInfo; 00257 } 00258 00259 CurrentEntry = CurrentEntry->Flink; 00260 } 00261 00262 KeReleaseSpinLock(&SymbolFileListLock, Irql); 00263 00264 DPRINT("Cached file not found!\n"); 00265 return NULL; 00266 } 00267 00275 static VOID 00276 KdbpSymAddCachedFile( 00277 IN PUNICODE_STRING FileName, 00278 IN PROSSYM_INFO RosSymInfo) 00279 { 00280 PIMAGE_SYMBOL_INFO_CACHE CacheEntry; 00281 KIRQL Irql; 00282 00283 DPRINT("Adding symbol file: RosSymInfo = %p\n", RosSymInfo); 00284 00285 /* allocate entry */ 00286 CacheEntry = ExAllocatePoolWithTag(NonPagedPool, sizeof (IMAGE_SYMBOL_INFO_CACHE), TAG_KDBS); 00287 ASSERT(CacheEntry); 00288 RtlZeroMemory(CacheEntry, sizeof (IMAGE_SYMBOL_INFO_CACHE)); 00289 00290 /* fill entry */ 00291 CacheEntry->FileName.Buffer = ExAllocatePoolWithTag(NonPagedPool, 00292 FileName->Length, 00293 TAG_KDBS); 00294 RtlCopyUnicodeString(&CacheEntry->FileName, FileName); 00295 ASSERT(CacheEntry->FileName.Buffer); 00296 CacheEntry->RefCount = 1; 00297 CacheEntry->RosSymInfo = RosSymInfo; 00298 KeAcquireSpinLock(&SymbolFileListLock, &Irql); 00299 InsertTailList(&SymbolFileListHead, &CacheEntry->ListEntry); 00300 KeReleaseSpinLock(&SymbolFileListLock, Irql); 00301 } 00302 00313 static VOID 00314 KdbpSymRemoveCachedFile( 00315 IN PROSSYM_INFO RosSymInfo) 00316 { 00317 PIMAGE_SYMBOL_INFO_CACHE Current; 00318 PLIST_ENTRY CurrentEntry; 00319 KIRQL Irql; 00320 00321 KeAcquireSpinLock(&SymbolFileListLock, &Irql); 00322 00323 CurrentEntry = SymbolFileListHead.Flink; 00324 while (CurrentEntry != (&SymbolFileListHead)) 00325 { 00326 Current = CONTAINING_RECORD(CurrentEntry, IMAGE_SYMBOL_INFO_CACHE, ListEntry); 00327 00328 if (Current->RosSymInfo == RosSymInfo) /* found */ 00329 { 00330 ASSERT(Current->RefCount > 0); 00331 Current->RefCount--; 00332 if (Current->RefCount < 1) 00333 { 00334 RemoveEntryList(&Current->ListEntry); 00335 RosSymDelete(Current->RosSymInfo); 00336 ExFreePool(Current); 00337 } 00338 00339 KeReleaseSpinLock(&SymbolFileListLock, Irql); 00340 return; 00341 } 00342 00343 CurrentEntry = CurrentEntry->Flink; 00344 } 00345 00346 KeReleaseSpinLock(&SymbolFileListLock, Irql); 00347 DPRINT1("Warning: Removing unknown symbol file: RosSymInfo = %p\n", RosSymInfo); 00348 } 00349 00357 static VOID 00358 KdbpSymLoadModuleSymbols( 00359 IN PUNICODE_STRING FileName, 00360 OUT PROSSYM_INFO *RosSymInfo) 00361 { 00362 OBJECT_ATTRIBUTES ObjectAttributes; 00363 HANDLE FileHandle; 00364 NTSTATUS Status; 00365 IO_STATUS_BLOCK IoStatusBlock; 00366 00367 /* Allow KDB to break on module load */ 00368 KdbModuleLoaded(FileName); 00369 00370 if (!LoadSymbols) 00371 { 00372 *RosSymInfo = NULL; 00373 return; 00374 } 00375 00376 /* Try to find cached (already loaded) symbol file */ 00377 *RosSymInfo = KdbpSymFindCachedFile(FileName); 00378 if (*RosSymInfo) 00379 { 00380 DPRINT("Found cached symbol file %wZ\n", FileName); 00381 return; 00382 } 00383 00384 /* Open the file */ 00385 InitializeObjectAttributes(&ObjectAttributes, 00386 FileName, 00387 0, 00388 NULL, 00389 NULL); 00390 00391 DPRINT("Attempting to open image: %wZ\n", FileName); 00392 00393 Status = ZwOpenFile(&FileHandle, 00394 FILE_READ_ACCESS, 00395 &ObjectAttributes, 00396 &IoStatusBlock, 00397 FILE_SHARE_READ|FILE_SHARE_WRITE, 00398 FILE_SYNCHRONOUS_IO_NONALERT); 00399 if (!NT_SUCCESS(Status)) 00400 { 00401 DPRINT("Could not open image file: %wZ\n", FileName); 00402 return; 00403 } 00404 00405 DPRINT("Loading symbols from %wZ...\n", FileName); 00406 00407 if (!RosSymCreateFromFile(&FileHandle, RosSymInfo)) 00408 { 00409 DPRINT("Failed to load symbols from %wZ\n", FileName); 00410 return; 00411 } 00412 00413 ZwClose(FileHandle); 00414 00415 DPRINT("Symbols loaded.\n"); 00416 00417 /* add file to cache */ 00418 KdbpSymAddCachedFile(FileName, *RosSymInfo); 00419 00420 DPRINT("Installed symbols: %wZ %p\n", FileName, *RosSymInfo); 00421 } 00422 00423 VOID 00424 KdbSymProcessSymbols( 00425 IN PLDR_DATA_TABLE_ENTRY LdrEntry) 00426 { 00427 if (!LoadSymbols) 00428 { 00429 LdrEntry->PatchInformation = NULL; 00430 return; 00431 } 00432 00433 /* Remove symbol info if it already exists */ 00434 if (LdrEntry->PatchInformation) 00435 KdbpSymRemoveCachedFile(LdrEntry->PatchInformation); 00436 00437 /* Load new symbol information */ 00438 if (! RosSymCreateFromMem(LdrEntry->DllBase, 00439 LdrEntry->SizeOfImage, 00440 (PROSSYM_INFO*)&LdrEntry->PatchInformation)) 00441 { 00442 /* Error loading symbol info, try to load it from file */ 00443 KdbpSymLoadModuleSymbols(&LdrEntry->FullDllName, 00444 (PROSSYM_INFO*)&LdrEntry->PatchInformation); 00445 00446 /* It already added symbols to cache */ 00447 } 00448 else 00449 { 00450 /* Add file to cache */ 00451 KdbpSymAddCachedFile(&LdrEntry->FullDllName, LdrEntry->PatchInformation); 00452 } 00453 00454 DPRINT("Installed symbols: %wZ@%p-%p %p\n", 00455 &LdrEntry->BaseDllName, 00456 LdrEntry->DllBase, 00457 (PVOID)(LdrEntry->SizeOfImage + (ULONG_PTR)LdrEntry->DllBase), 00458 LdrEntry->PatchInformation); 00459 00460 } 00461 00462 VOID 00463 NTAPI 00464 KdbDebugPrint( 00465 PCH Message, 00466 ULONG Length) 00467 { 00468 /* Nothing here */ 00469 } 00470 00471 00477 VOID 00478 NTAPI 00479 KdbInitialize( 00480 PKD_DISPATCH_TABLE DispatchTable, 00481 ULONG BootPhase) 00482 { 00483 PCHAR p1, p2; 00484 SHORT Found = FALSE; 00485 CHAR YesNo; 00486 PLDR_DATA_TABLE_ENTRY LdrEntry; 00487 00488 DPRINT("KdbSymInit() BootPhase=%d\n", BootPhase); 00489 00490 LoadSymbols = FALSE; 00491 00492 #if DBG 00493 /* Load symbols only if we have 96Mb of RAM or more */ 00494 if (MmNumberOfPhysicalPages >= 0x6000) 00495 LoadSymbols = TRUE; 00496 #endif 00497 00498 if (BootPhase == 0) 00499 { 00500 /* Write out the functions that we support for now */ 00501 DispatchTable->KdpInitRoutine = KdpKdbgInit; 00502 DispatchTable->KdpPrintRoutine = KdbDebugPrint; 00503 00504 /* Register as a Provider */ 00505 InsertTailList(&KdProviders, &DispatchTable->KdProvidersList); 00506 00507 /* Perform actual initialization of symbol module */ 00508 //NtoskrnlModuleObject->PatchInformation = NULL; 00509 //LdrHalModuleObject->PatchInformation = NULL; 00510 00511 InitializeListHead(&SymbolFileListHead); 00512 KeInitializeSpinLock(&SymbolFileListLock); 00513 00514 /* Check the command line for /LOADSYMBOLS, /NOLOADSYMBOLS, 00515 * /LOADSYMBOLS={YES|NO}, /NOLOADSYMBOLS={YES|NO} */ 00516 ASSERT(KeLoaderBlock); 00517 p1 = KeLoaderBlock->LoadOptions; 00518 while('\0' != *p1 && NULL != (p2 = strchr(p1, '/'))) 00519 { 00520 p2++; 00521 Found = 0; 00522 if (0 == _strnicmp(p2, "LOADSYMBOLS", 11)) 00523 { 00524 Found = +1; 00525 p2 += 11; 00526 } 00527 else if (0 == _strnicmp(p2, "NOLOADSYMBOLS", 13)) 00528 { 00529 Found = -1; 00530 p2 += 13; 00531 } 00532 if (0 != Found) 00533 { 00534 while (isspace(*p2)) 00535 { 00536 p2++; 00537 } 00538 if ('=' == *p2) 00539 { 00540 p2++; 00541 while (isspace(*p2)) 00542 { 00543 p2++; 00544 } 00545 YesNo = toupper(*p2); 00546 if ('N' == YesNo || 'F' == YesNo || '0' == YesNo) 00547 { 00548 Found = -1 * Found; 00549 } 00550 } 00551 LoadSymbols = (0 < Found); 00552 } 00553 p1 = p2; 00554 } 00555 00556 RosSymInitKernelMode(); 00557 } 00558 else if (BootPhase == 1) 00559 { 00560 /* Load symbols for NTOSKRNL.EXE. 00561 It is always the first module in PsLoadedModuleList. KeLoaderBlock can't be used here as its content is just temporary. */ 00562 LdrEntry = CONTAINING_RECORD(PsLoadedModuleList.Flink, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); 00563 KdbSymProcessSymbols(LdrEntry); 00564 00565 /* Also load them for HAL.DLL. */ 00566 LdrEntry = CONTAINING_RECORD(PsLoadedModuleList.Flink->Flink, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); 00567 KdbSymProcessSymbols(LdrEntry); 00568 00569 KdbpSymbolsInitialized = TRUE; 00570 } 00571 } 00572 00573 /* EOF */ Generated on Sat May 26 2012 04:36:18 for ReactOS by
1.7.6.1
|