Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

dmpstate.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1993 IBM and Microsoft Corporation 00004 00005 Module Name: 00006 00007 dmpstate.c 00008 00009 Abstract: 00010 00011 This module implements the architecture specific routine that dumps 00012 the machine state when a bug check occurs and no debugger is hooked 00013 to the system. It is assumed that it is called from bug check. 00014 00015 Author: 00016 00017 Chuck Bauman 19-Sep-1993 00018 00019 Environment: 00020 00021 Kernel mode. 00022 00023 Revision History: 00024 00025 Based on Dave Cutler's MIPS implemenation 00026 00027 Tom Wood (twood) 19-Aug-1994 00028 Update to use RtlVirtualUnwind even when there isn't a function table 00029 entry. Add stack limit parameters to RtlVirtualUnwind. 00030 00031 Changed KiLookupFunctionEntry to deal with the indirect entries. 00032 00033 --*/ 00034 00035 #include "ki.h" 00036 00037 // 00038 // Define forward referenced prototypes. 00039 // 00040 00041 VOID 00042 KiDisplayString ( 00043 IN ULONG Column, 00044 IN ULONG Row, 00045 IN PCHAR Buffer 00046 ); 00047 00048 PRUNTIME_FUNCTION 00049 KiLookupFunctionEntry ( 00050 IN ULONG ControlPc 00051 ); 00052 00053 PVOID 00054 KiPcToFileHeader( 00055 IN PVOID PcValue, 00056 OUT PVOID *BaseOfImage, 00057 OUT PLDR_DATA_TABLE_ENTRY *DataTableEntry 00058 ); 00059 00060 // 00061 // Define external data. 00062 // 00063 00064 extern LIST_ENTRY PsLoadedModuleList; 00065 00066 VOID 00067 KeDumpMachineState ( 00068 IN PKPROCESSOR_STATE ProcessorState, 00069 IN PCHAR Buffer, 00070 IN PULONG BugCheckParameters, 00071 IN ULONG NumberOfParameters, 00072 IN PKE_BUGCHECK_UNICODE_TO_ANSI UnicodeToAnsiRoutine 00073 ) 00074 00075 /*++ 00076 00077 Routine Description: 00078 00079 This function formats and displays the machine state at the time of the 00080 to bug check. 00081 00082 Arguments: 00083 00084 ProcessorState - Supplies a pointer to a processor state record. 00085 00086 Buffer - Supplies a pointer to a buffer to be used to output machine 00087 state information. 00088 00089 BugCheckParameters - Supplies a pointer to an array of additional 00090 bug check information. 00091 00092 NumberOfParameters - Suppiles the size of the bug check parameters 00093 array. 00094 00095 UnicodeToAnsiRoutine - Supplies a pointer to a routine to convert Unicode strings 00096 to Ansi strings without touching paged translation tables. 00097 00098 Return Value: 00099 00100 None. 00101 00102 --*/ 00103 00104 { 00105 00106 PCONTEXT ContextRecord; 00107 ULONG ControlPc; 00108 PLDR_DATA_TABLE_ENTRY DataTableEntry; 00109 ULONG DisplayColumn; 00110 ULONG DisplayHeight; 00111 ULONG DisplayRow; 00112 ULONG DisplayWidth; 00113 UNICODE_STRING DllName; 00114 ULONG EstablisherFrame; 00115 PRUNTIME_FUNCTION FunctionEntry; 00116 PVOID ImageBase; 00117 ULONG Index; 00118 BOOLEAN InFunction; 00119 ULONG LastStack; 00120 PLIST_ENTRY ModuleListHead; 00121 PLIST_ENTRY NextEntry; 00122 ULONG NextPc; 00123 ULONG StackLimit; 00124 UCHAR AnsiBuffer[ 32 ]; 00125 ULONG DateStamp; 00126 00127 // 00128 // Call the HAL to force all external interrupts to be disabled 00129 // at the interrupt controller. PowerPC optimization does not 00130 // do this when raising to high level. 00131 // 00132 for (Index = 0; Index < MAXIMUM_VECTOR; Index++) { 00133 HalDisableSystemInterrupt(Index, HIGH_LEVEL); 00134 } 00135 00136 // 00137 // Query display parameters. 00138 // 00139 00140 HalQueryDisplayParameters(&DisplayWidth, 00141 &DisplayHeight, 00142 &DisplayColumn, 00143 &DisplayRow); 00144 00145 // 00146 // Display any addresses that fall within the range of any module in 00147 // the loaded module list. 00148 // 00149 00150 for (Index = 0; Index < NumberOfParameters; Index += 1) { 00151 ImageBase = KiPcToFileHeader((PVOID)*BugCheckParameters, 00152 &ImageBase, 00153 &DataTableEntry); 00154 00155 if (ImageBase != NULL) { 00156 sprintf(Buffer, 00157 "*** %08lX has base at %08lX - %s\n", 00158 *BugCheckParameters, 00159 ImageBase, 00160 (*UnicodeToAnsiRoutine)( &DataTableEntry->BaseDllName, AnsiBuffer, sizeof( AnsiBuffer ))); 00161 00162 HalDisplayString(Buffer); 00163 } 00164 00165 BugCheckParameters += 1; 00166 } 00167 00168 // 00169 // Virtually unwind to the caller of bug check. 00170 // 00171 00172 ContextRecord = &ProcessorState->ContextFrame; 00173 LastStack = ContextRecord->Gpr1; 00174 ControlPc = ContextRecord->Lr - 4; 00175 NextPc = ControlPc; 00176 FunctionEntry = KiLookupFunctionEntry(ControlPc); 00177 if (FunctionEntry != NULL) { 00178 NextPc = RtlVirtualUnwind(ControlPc, 00179 FunctionEntry, 00180 ContextRecord, 00181 &InFunction, 00182 &EstablisherFrame, 00183 NULL, 00184 0, 00185 0xffffffff); 00186 } 00187 00188 // 00189 // At this point the context record contains the machine state at the 00190 // call to bug check. 00191 // 00192 // Put out the machine state at the time of the bugcheck. 00193 // 00194 00195 sprintf(Buffer, 00196 "\n Machine State at Call to Bug Check IAR:%08lX MSR:%08lX\n", 00197 ContextRecord->Lr, 00198 ContextRecord->Msr); 00199 00200 HalDisplayString(Buffer); 00201 00202 // 00203 // Format and output the integer registers. 00204 // 00205 00206 sprintf(Buffer, 00207 " R0:%8lX R1:%8lX R2:%8lX R3:%8lX R4:%8lX R5:%8lX\n", 00208 ContextRecord->Gpr0, 00209 ContextRecord->Gpr1, 00210 ContextRecord->Gpr2, 00211 ContextRecord->Gpr3, 00212 ContextRecord->Gpr4, 00213 ContextRecord->Gpr5); 00214 00215 HalDisplayString(Buffer); 00216 00217 sprintf(Buffer, 00218 " R6:%8lX R7:%8lX R8:%8lX R9:%8lX R10:%8lX R11:%8lX\n", 00219 ContextRecord->Gpr6, 00220 ContextRecord->Gpr7, 00221 ContextRecord->Gpr8, 00222 ContextRecord->Gpr9, 00223 ContextRecord->Gpr10, 00224 ContextRecord->Gpr11); 00225 00226 HalDisplayString(Buffer); 00227 00228 sprintf(Buffer, 00229 "R12:%8lX R13:%8lX R14:%8lX R15:%8lX R16:%8lX R17:%8lX\n", 00230 ContextRecord->Gpr12, 00231 ContextRecord->Gpr13, 00232 ContextRecord->Gpr14, 00233 ContextRecord->Gpr15, 00234 ContextRecord->Gpr16, 00235 ContextRecord->Gpr17); 00236 00237 HalDisplayString(Buffer); 00238 00239 sprintf(Buffer, 00240 "R18:%8lX R19:%8lX R20:%8lX R21:%8lX R22:%8lX R23:%8lX\n", 00241 ContextRecord->Gpr18, 00242 ContextRecord->Gpr19, 00243 ContextRecord->Gpr20, 00244 ContextRecord->Gpr21, 00245 ContextRecord->Gpr22, 00246 ContextRecord->Gpr23); 00247 00248 HalDisplayString(Buffer); 00249 00250 sprintf(Buffer, 00251 "R24:%8lX R25:%8lX R26:%8lX R27:%8lX R28:%8lX R29:%8lX\n", 00252 ContextRecord->Gpr24, 00253 ContextRecord->Gpr25, 00254 ContextRecord->Gpr26, 00255 ContextRecord->Gpr27, 00256 ContextRecord->Gpr28, 00257 ContextRecord->Gpr29); 00258 00259 HalDisplayString(Buffer); 00260 00261 sprintf(Buffer, 00262 "R30:%8lX R31:%8lX CR:%8lX CTR:%8lX XER:%8lX\n", 00263 ContextRecord->Gpr30, 00264 ContextRecord->Gpr31, 00265 ContextRecord->Cr, 00266 ContextRecord->Ctr, 00267 ContextRecord->Xer); 00268 00269 HalDisplayString(Buffer); 00270 00271 #if 0 00272 00273 // 00274 // I'd much rather see a longer stack trace and skip the floating 00275 // point stuff when the system crashes. plj 00276 // 00277 00278 // 00279 // Format and output the floating registers. 00280 // 00281 DumpFloat = (PULONG)(&ContextRecord->Fpr0); 00282 sprintf(Buffer, 00283 " F0- F3:%08lX%08lX %08lX%08lX %08lX%08lX %08lX%08lX\n", 00284 *(DumpFloat+1), 00285 *DumpFloat, 00286 *(DumpFloat+3), 00287 *(DumpFloat+2), 00288 *(DumpFloat+5), 00289 *(DumpFloat+4), 00290 *(DumpFloat+7), 00291 *(DumpFloat+6)); 00292 00293 HalDisplayString(Buffer); 00294 00295 DumpFloat = (PULONG)(&ContextRecord->Fpr4); 00296 sprintf(Buffer, 00297 " F4- F7:%08lX%08lX %08lX%08lX %08lX%08lX %08lX%08lX\n", 00298 *(DumpFloat+1), 00299 *DumpFloat, 00300 *(DumpFloat+3), 00301 *(DumpFloat+2), 00302 *(DumpFloat+5), 00303 *(DumpFloat+4), 00304 *(DumpFloat+7), 00305 *(DumpFloat+6)); 00306 00307 HalDisplayString(Buffer); 00308 00309 DumpFloat = (PULONG)(&ContextRecord->Fpr8); 00310 sprintf(Buffer, 00311 " F8-F11:%08lX%08lX %08lX%08lX %08lX%08lX %08lX%08lX\n", 00312 *(DumpFloat+1), 00313 *DumpFloat, 00314 *(DumpFloat+3), 00315 *(DumpFloat+2), 00316 *(DumpFloat+5), 00317 *(DumpFloat+4), 00318 *(DumpFloat+7), 00319 *(DumpFloat+6)); 00320 00321 HalDisplayString(Buffer); 00322 00323 DumpFloat = (PULONG)(&ContextRecord->Fpr12); 00324 sprintf(Buffer, 00325 "F12-F15:%08lX%08lX %08lX%08lX %08lX%08lX %08lX%08lX\n", 00326 *(DumpFloat+1), 00327 *DumpFloat, 00328 *(DumpFloat+3), 00329 *(DumpFloat+2), 00330 *(DumpFloat+5), 00331 *(DumpFloat+4), 00332 *(DumpFloat+7), 00333 *(DumpFloat+6)); 00334 00335 HalDisplayString(Buffer); 00336 00337 DumpFloat = (PULONG)(&ContextRecord->Fpr16); 00338 sprintf(Buffer, 00339 "F16-F19:%08lX%08lX %08lX%08lX %08lX%08lX %08lX%08lX\n", 00340 *(DumpFloat+1), 00341 *DumpFloat, 00342 *(DumpFloat+3), 00343 *(DumpFloat+2), 00344 *(DumpFloat+5), 00345 *(DumpFloat+4), 00346 *(DumpFloat+7), 00347 *(DumpFloat+6)); 00348 00349 HalDisplayString(Buffer); 00350 00351 DumpFloat = (PULONG)(&ContextRecord->Fpr20); 00352 sprintf(Buffer, 00353 "F20-F23:%08lX%08lX %08lX%08lX %08lX%08lX %08lX%08lX\n", 00354 *(DumpFloat+1), 00355 *DumpFloat, 00356 *(DumpFloat+3), 00357 *(DumpFloat+2), 00358 *(DumpFloat+5), 00359 *(DumpFloat+4), 00360 *(DumpFloat+7), 00361 *(DumpFloat+6)); 00362 00363 HalDisplayString(Buffer); 00364 00365 DumpFloat = (PULONG)(&ContextRecord->Fpr24); 00366 sprintf(Buffer, 00367 "F24-F27:%08lX%08lX %08lX%08lX %08lX%08lX %08lX%08lX\n", 00368 *(DumpFloat+1), 00369 *DumpFloat, 00370 *(DumpFloat+3), 00371 *(DumpFloat+2), 00372 *(DumpFloat+5), 00373 *(DumpFloat+4), 00374 *(DumpFloat+7), 00375 *(DumpFloat+6)); 00376 00377 HalDisplayString(Buffer); 00378 00379 DumpFloat = (PULONG)(&ContextRecord->Fpr28); 00380 sprintf(Buffer, 00381 "F28-F31:%08lX%08lX %08lX%08lX %08lX%08lX %08lX%08lX\n", 00382 *(DumpFloat+1), 00383 *DumpFloat, 00384 *(DumpFloat+3), 00385 *(DumpFloat+2), 00386 *(DumpFloat+5), 00387 *(DumpFloat+4), 00388 *(DumpFloat+7), 00389 *(DumpFloat+6)); 00390 00391 HalDisplayString(Buffer); 00392 00393 00394 DumpFloat = (PULONG)(&ContextRecord->Fpscr); 00395 sprintf(Buffer, 00396 " FPSCR:%08lX%08lX\n", 00397 *(DumpFloat+1), 00398 *DumpFloat); 00399 00400 HalDisplayString(Buffer); 00401 00402 #define STAKWALK 4 00403 #else 00404 #define STAKWALK 8 00405 #endif 00406 00407 // 00408 // Output short stack back trace with base address. 00409 // 00410 00411 DllName.Length = 0; 00412 DllName.Buffer = L""; 00413 if (FunctionEntry != NULL) { 00414 StackLimit = (ULONG)KeGetCurrentThread()->KernelStack; 00415 HalDisplayString("Callee-Sp Return-Ra Dll Base - Name\n"); 00416 for (Index = 0; Index < STAKWALK; Index += 1) { 00417 ImageBase = KiPcToFileHeader((PVOID)ControlPc, 00418 &ImageBase, 00419 &DataTableEntry); 00420 00421 sprintf(Buffer, 00422 " %08lX %08lX : %08lX - %s\n", 00423 ContextRecord->Gpr1, 00424 NextPc + 4, 00425 ImageBase, 00426 (*UnicodeToAnsiRoutine)( (ImageBase != NULL) ? &DataTableEntry->BaseDllName : &DllName, 00427 AnsiBuffer, sizeof( AnsiBuffer ))); 00428 00429 HalDisplayString(Buffer); 00430 00431 if ((NextPc != ControlPc) || (ContextRecord->Gpr1 != LastStack)) { 00432 ControlPc = NextPc; 00433 LastStack = ContextRecord->Gpr1; 00434 FunctionEntry = KiLookupFunctionEntry(ControlPc); 00435 if ((FunctionEntry != NULL) && (LastStack < StackLimit)) { 00436 NextPc = RtlVirtualUnwind(ControlPc, 00437 FunctionEntry, 00438 ContextRecord, 00439 &InFunction, 00440 &EstablisherFrame, 00441 NULL, 00442 0, 00443 0xffffffff); 00444 } else { 00445 NextPc = ContextRecord->Lr; 00446 } 00447 00448 } else { 00449 break; 00450 } 00451 } 00452 } 00453 00454 // 00455 // Output the build number and other useful information. 00456 // 00457 00458 sprintf(Buffer, 00459 "\nIRQL : %d, DPC Active : %s, SYSVER 0x%08x\n", 00460 KeGetCurrentIrql(), 00461 KeIsExecutingDpc() ? "TRUE" : "FALSE", 00462 NtBuildNumber); 00463 00464 HalDisplayString(Buffer); 00465 00466 // 00467 // Output the processor id and the primary cache sizes. 00468 // 00469 00470 sprintf(Buffer, 00471 "Processor Id: %d.%d, Icache: %d, Dcache: %d", 00472 PCR->ProcessorVersion, 00473 PCR->ProcessorRevision, 00474 PCR->FirstLevelIcacheSize, 00475 PCR->FirstLevelDcacheSize); 00476 00477 HalDisplayString(Buffer); 00478 00479 // 00480 // If the display width is greater than 80 + 24 (the size of a DLL 00481 // name and base address), then display all the modules loaded in 00482 // the system. 00483 // 00484 00485 HalQueryDisplayParameters(&DisplayWidth, 00486 &DisplayHeight, 00487 &DisplayColumn, 00488 &DisplayRow); 00489 00490 if (DisplayWidth > (80 + 24)) { 00491 HalDisplayString("\n"); 00492 if (KeLoaderBlock != NULL) { 00493 ModuleListHead = &KeLoaderBlock->LoadOrderListHead; 00494 00495 } else { 00496 ModuleListHead = &PsLoadedModuleList; 00497 } 00498 00499 // 00500 // Output display headers. 00501 // 00502 00503 Index = 1; 00504 KiDisplayString(80, Index, "Dll Base DateStmp - Name"); 00505 NextEntry = ModuleListHead->Flink; 00506 if (NextEntry != NULL) { 00507 00508 // 00509 // Scan the list of loaded modules and display their base 00510 // address and name. 00511 // 00512 00513 while (NextEntry != ModuleListHead) { 00514 Index += 1; 00515 DataTableEntry = CONTAINING_RECORD(NextEntry, 00516 LDR_DATA_TABLE_ENTRY, 00517 InLoadOrderLinks); 00518 00519 if (MmDbgReadCheck(DataTableEntry->DllBase) != NULL) { 00520 PIMAGE_NT_HEADERS NtHeaders; 00521 00522 NtHeaders = RtlImageNtHeader(DataTableEntry->DllBase); 00523 DateStamp = NtHeaders->FileHeader.TimeDateStamp; 00524 00525 } else { 00526 DateStamp = 0; 00527 } 00528 sprintf(Buffer, 00529 "%08lX %08lx - %s", 00530 DataTableEntry->DllBase, 00531 DateStamp, 00532 (*UnicodeToAnsiRoutine)( &DataTableEntry->BaseDllName, AnsiBuffer, sizeof( AnsiBuffer ))); 00533 00534 KiDisplayString(80, Index, Buffer); 00535 NextEntry = NextEntry->Flink; 00536 if (Index > DisplayHeight) { 00537 break; 00538 } 00539 } 00540 } 00541 } 00542 00543 // 00544 // Reset the current display position. 00545 // 00546 00547 HalSetDisplayParameters(DisplayColumn, DisplayRow); 00548 00549 // 00550 // The system has crashed, if we are running without the Kernel 00551 // debugger attached, attach it now. 00552 // 00553 00554 KdInitSystem(NULL, FALSE); 00555 00556 return; 00557 } 00558 00559 VOID 00560 KiDisplayString ( 00561 IN ULONG Column, 00562 IN ULONG Row, 00563 IN PCHAR Buffer 00564 ) 00565 00566 /*++ 00567 00568 Routine Description: 00569 00570 This function display a string starting at the specified column and row 00571 position on the screen. 00572 00573 Arguments: 00574 00575 Column - Supplies the starting column of where the string is displayed. 00576 00577 Row - Supplies the starting row of where the string is displayed. 00578 00579 Bufer - Supplies a pointer to the string that is displayed. 00580 00581 Return Value: 00582 00583 None. 00584 00585 --*/ 00586 00587 { 00588 00589 // 00590 // Position the cursor and display the string. 00591 // 00592 00593 HalSetDisplayParameters(Column, Row); 00594 HalDisplayString(Buffer); 00595 return; 00596 } 00597 00598 PRUNTIME_FUNCTION 00599 KiLookupFunctionEntry ( 00600 IN ULONG ControlPc 00601 ) 00602 00603 /*++ 00604 00605 Routine Description: 00606 00607 This function searches the currently active function tables for an entry 00608 that corresponds to the specified PC value. 00609 00610 Arguments: 00611 00612 ControlPc - Supplies the address of an instruction within the specified 00613 function. 00614 00615 Return Value: 00616 00617 If there is no entry in the function table for the specified PC, then 00618 NULL is returned. Otherwise, the address of the function table entry 00619 that corresponds to the specified PC is returned. 00620 00621 --*/ 00622 00623 { 00624 00625 PLDR_DATA_TABLE_ENTRY DataTableEntry; 00626 PRUNTIME_FUNCTION FunctionEntry; 00627 PRUNTIME_FUNCTION FunctionTable; 00628 ULONG SizeOfExceptionTable; 00629 LONG High; 00630 PVOID ImageBase; 00631 LONG Low; 00632 LONG Middle; 00633 00634 // 00635 // Search for the image that includes the specified PC value. 00636 // 00637 00638 ImageBase = KiPcToFileHeader((PVOID)ControlPc, 00639 &ImageBase, 00640 &DataTableEntry); 00641 00642 // 00643 // If an image is found that includes the specified PC, then locate the 00644 // function table for the image. 00645 // 00646 00647 if (ImageBase != NULL) { 00648 FunctionTable = (PRUNTIME_FUNCTION)RtlImageDirectoryEntryToData( 00649 ImageBase, TRUE, IMAGE_DIRECTORY_ENTRY_EXCEPTION, 00650 &SizeOfExceptionTable); 00651 00652 // 00653 // If a function table is located, then search the function table 00654 // for a function table entry for the specified PC. 00655 // 00656 00657 if (FunctionTable != NULL) { 00658 00659 // 00660 // Initialize search indicies. 00661 // 00662 00663 Low = 0; 00664 High = (SizeOfExceptionTable / sizeof(RUNTIME_FUNCTION)) - 1; 00665 00666 // 00667 // Perform binary search on the function table for a function table 00668 // entry that subsumes the specified PC. 00669 // 00670 00671 while (High >= Low) { 00672 00673 // 00674 // Compute next probe index and test entry. If the specified PC 00675 // is greater than of equal to the beginning address and less 00676 // than the ending address of the function table entry, then 00677 // return the address of the function table entry. Otherwise, 00678 // continue the search. 00679 // 00680 00681 Middle = (Low + High) >> 1; 00682 FunctionEntry = &FunctionTable[Middle]; 00683 if (ControlPc < FunctionEntry->BeginAddress) { 00684 High = Middle - 1; 00685 00686 } else if (ControlPc >= FunctionEntry->EndAddress) { 00687 Low = Middle + 1; 00688 00689 } else { 00690 00691 // 00692 // The capability exists for more than one function entry 00693 // to map to the same function. This permits a function to 00694 // have (within reason) discontiguous code segment(s). If 00695 // PrologEndAddress is out of range, it is re-interpreted 00696 // as a pointer to the primary function table entry for 00697 // that function. The out of range test takes into account 00698 // the redundant encoding of millicode and glue code. 00699 // 00700 00701 if (((FunctionEntry->PrologEndAddress < FunctionEntry->BeginAddress) || 00702 (FunctionEntry->PrologEndAddress >= FunctionEntry->EndAddress)) && 00703 (FunctionEntry->PrologEndAddress & 3) == 0) { 00704 FunctionEntry = (PRUNTIME_FUNCTION)FunctionEntry->PrologEndAddress; 00705 } 00706 00707 return FunctionEntry; 00708 } 00709 } 00710 } 00711 } 00712 00713 // 00714 // A function table entry for the specified PC was not found. 00715 // 00716 00717 return NULL; 00718 } 00719 00720 PVOID 00721 KiPcToFileHeader( 00722 IN PVOID PcValue, 00723 OUT PVOID *BaseOfImage, 00724 OUT PLDR_DATA_TABLE_ENTRY *DataTableEntry 00725 ) 00726 00727 /*++ 00728 00729 Routine Description: 00730 00731 This function returns the base of an image that contains the 00732 specified PcValue. An image contains the PcValue if the PcValue 00733 is within the ImageBase, and the ImageBase plus the size of the 00734 virtual image. 00735 00736 Arguments: 00737 00738 PcValue - Supplies a PcValue. 00739 00740 BaseOfImage - Returns the base address for the image containing the 00741 PcValue. This value must be added to any relative addresses in 00742 the headers to locate portions of the image. 00743 00744 DataTableEntry - Suppies a pointer to a variable that receives the 00745 address of the data table entry that describes the image. 00746 00747 Return Value: 00748 00749 NULL - No image was found that contains the PcValue. 00750 00751 NON-NULL - Returns the base address of the image that contain the 00752 PcValue. 00753 00754 --*/ 00755 00756 { 00757 00758 PLIST_ENTRY ModuleListHead; 00759 PLDR_DATA_TABLE_ENTRY Entry; 00760 PLIST_ENTRY Next; 00761 ULONG Bounds; 00762 PVOID ReturnBase, Base; 00763 00764 // 00765 // If the module list has been initialized, then scan the list to 00766 // locate the appropriate entry. 00767 // 00768 00769 if (KeLoaderBlock != NULL) { 00770 ModuleListHead = &KeLoaderBlock->LoadOrderListHead; 00771 00772 } else { 00773 ModuleListHead = &PsLoadedModuleList; 00774 } 00775 00776 ReturnBase = NULL; 00777 Next = ModuleListHead->Flink; 00778 if (Next != NULL) { 00779 while (Next != ModuleListHead) { 00780 Entry = CONTAINING_RECORD(Next, 00781 LDR_DATA_TABLE_ENTRY, 00782 InLoadOrderLinks); 00783 00784 Next = Next->Flink; 00785 Base = Entry->DllBase; 00786 Bounds = (ULONG)Base + Entry->SizeOfImage; 00787 if ((ULONG)PcValue >= (ULONG)Base && (ULONG)PcValue < Bounds) { 00788 *DataTableEntry = Entry; 00789 ReturnBase = Base; 00790 break; 00791 } 00792 } 00793 } 00794 00795 *BaseOfImage = ReturnBase; 00796 return ReturnBase; 00797 }

Generated on Sat May 15 19:39:46 2004 for test by doxygen 1.3.7