ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

kdb_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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.