test: pctohdr.c Source File

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

# pctohdr.c

Go to the documentation of this file.

    00001 /*++
    00002
    00003 Copyright (c) 1992  Microsoft Corporation
    00004
    00005 Module Name:
    00006
    00007     pctohdr.c
    00008
    00009 Abstract:
    00010
    00011     This module implements code to locate the file header for an image or
    00012     dll given a PC value that lies within the image.
    00013
    00014     N.B. This routine is conditionalized for user mode and kernel mode.
    00015
    00016 Author:
    00017
    00018     Steve Wood (stevewo) 18-Aug-1989
    00019
    00020 Environment:
    00021
    00022     User Mode or Kernel Mode
    00023
    00024 Revision History:
    00025
    00026 --*/
    00027
    00028 #if defined(NTOS_KERNEL_RUNTIME)
    00029 #include "ntos.h"
    00030 #else
    00031 #include <nt.h>
    00032 #include <ntrtl.h>
    00033 #include <nturtl.h>
    00034 #endif
    00035
    00036 #if !defined(NTOS_KERNEL_RUNTIME)
    00037 extern PVOID NtDllBase;             // defined in ntos\dll\ldrinit.c
    00038 #endif
    00039
    00040
    00041 PVOID
    00042 RtlPcToFileHeader(
    00043     IN PVOID PcValue,
    00044     OUT PVOID *BaseOfImage
    00045     )
    00046
    00047 /*++
    00048
    00049 Routine Description:
    00050
    00051     This function returns the base of an image that contains the
    00052     specified PcValue. An image contains the PcValue if the PcValue
    00053     is within the ImageBase, and the ImageBase plus the size of the
    00054     virtual image.
    00055
    00056 Arguments:
    00057
    00058     PcValue - Supplies a PcValue.  All of the modules mapped into the
    00059         calling processes address space are scanned to compute which
    00060         module contains the PcValue.
    00061
    00062     BaseOfImage - Returns the base address for the image containing the
    00063         PcValue.  This value must be added to any relative addresses in
    00064         the headers to locate portions of the image.
    00065
    00066 Return Value:
    00067
    00068     NULL - No image was found that contains the PcValue.
    00069
    00070     NON-NULL - Returns the base address of the image that contain the
    00071         PcValue.
    00072
    00073 --*/
    00074
    00075 {
    00076
    00077 #if defined(NTOS_KERNEL_RUNTIME)
    00078
    00079     extern LIST_ENTRY PsLoadedModuleList;
    00080     extern KSPIN_LOCK PsLoadedModuleSpinLock;
    00081
    00082     PVOID Base;
    00083     ULONG_PTR Bounds;
    00084     PLDR_DATA_TABLE_ENTRY Entry;
    00085     PLIST_ENTRY Next;
    00086     KIRQL OldIrql;
    00087
    00088     //
    00089     // Acquire the loaded module list spinlock and scan the list for the
    00090     // specified PC value if the list has been initialized.
    00091     //
    00092
    00093     ExAcquireSpinLock(&PsLoadedModuleSpinLock, &OldIrql);
    00094     Next = PsLoadedModuleList.Flink;
    00095     if (Next != NULL) {
    00096         while (Next != &PsLoadedModuleList) {
    00097             Entry = CONTAINING_RECORD(Next,
    00098                                       LDR_DATA_TABLE_ENTRY,
    00099                                       InLoadOrderLinks);
    00100
    00101             Next = Next->Flink;
    00102             Base = Entry->DllBase;
    00103             Bounds = (ULONG_PTR)Base + Entry->SizeOfImage;
    00104             if (((ULONG_PTR)PcValue >= (ULONG_PTR)Base) && ((ULONG_PTR)PcValue < Bounds)) {
    00105                 ExReleaseSpinLock(&PsLoadedModuleSpinLock, OldIrql);
    00106                 *BaseOfImage = Base;
    00107                 return Base;
    00108             }
    00109         }
    00110     }
    00111
    00112     //
    00113     // Release the loaded module list spin lock and return NULL.
    00114     //
    00115
    00116     ExReleaseSpinLock(&PsLoadedModuleSpinLock, OldIrql);
    00117     *BaseOfImage = NULL;
    00118     return NULL;
    00119
    00120 #else
    00121
    00122     PVOID Base;
    00123     ULONG_PTR Bounds;
    00124     PLDR_DATA_TABLE_ENTRY Entry;
    00125     PLIST_ENTRY ModuleListHead;
    00126     PLIST_ENTRY Next;
    00127     PIMAGE_NT_HEADERS NtHeaders;
    00128     PPEB Peb;
    00129     PTEB Teb;
    00130     MEMORY_BASIC_INFORMATION MemInfo;
    00131     NTSTATUS st;
    00132
    00133     //
    00134     // Acquire the Loader lock for the current process and scan the loaded
    00135     // module list for the specified PC value if all the data structures
    00136     // have been initialized.
    00137     //
    00138
    00139     if ( !RtlTryEnterCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->LoaderLock) ) {
    00140
    00141         //
    00142         // We could not get the loader lock, so call the system to find the image that
    00143         // contains this pc
    00144         //
    00145
    00146         st = NtQueryVirtualMemory(
    00147                 NtCurrentProcess(),
    00148                 PcValue,
    00149                 MemoryBasicInformation,
    00150                 (PVOID)&MemInfo,
    00151                 sizeof(MemInfo),
    00152                 NULL
    00153                 );
    00154         if ( !NT_SUCCESS(st) ) {
    00155             MemInfo.AllocationBase = NULL;;
    00156             }
    00157         else {
    00158             if ( MemInfo.Type == MEM_IMAGE ) {
    00159                 try {
    00160                     *BaseOfImage = MemInfo.AllocationBase;
    00161                     }
    00162                 except (EXCEPTION_EXECUTE_HANDLER) {
    00163                     MemInfo.AllocationBase = NULL;
    00164                     }
    00165                 }
    00166             else {
    00167                 MemInfo.AllocationBase = NULL;;
    00168                 }
    00169             }
    00170         return MemInfo.AllocationBase;
    00171         }
    00172
    00173     try {
    00174         Teb = NtCurrentTeb();
    00175         if (Teb != NULL) {
    00176             Peb = Teb->ProcessEnvironmentBlock;
    00177             if (Peb->Ldr != NULL) {
    00178                 ModuleListHead = &Peb->Ldr->InLoadOrderModuleList;
    00179                 Next = ModuleListHead->Flink;
    00180                 if (Next != NULL) {
    00181                     while (Next != ModuleListHead) {
    00182                         Entry = CONTAINING_RECORD(Next,
    00183                                                   LDR_DATA_TABLE_ENTRY,
    00184                                                   InLoadOrderLinks);
    00185
    00186                         Next = Next->Flink;
    00187                         Base = Entry->DllBase;
    00188                         NtHeaders = RtlImageNtHeader(Base);
    00189                         Bounds = (ULONG_PTR)Base + NtHeaders->OptionalHeader.SizeOfImage;
    00190                         if (((ULONG_PTR)PcValue >= (ULONG_PTR)Base) && ((ULONG_PTR)PcValue < Bounds)) {
    00191                             RtlLeaveCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->LoaderLock);
    00192                             *BaseOfImage = Base;
    00193                             return Base;
    00194                         }
    00195                     }
    00196                 }
    00197
    00198             } else {
    00199
    00200                 //
    00201                 //  ( Peb->Ldr == NULL )
    00202                 //
    00203                 //  If called during process intialization before the Ldr
    00204                 //  module list has been setup, code executing must be in
    00205                 //  NTDLL module.  If NtDllBase is non-NULL and the PcValue
    00206                 //  falls into the NTDLL range, return a valid Base.  This
    00207                 //  allows DbgPrint's during LdrpInitializeProcess to work
    00208                 //  on RISC machines.
    00209                 //
    00210
    00211                 if ( NtDllBase != NULL ) {
    00212                     Base = NtDllBase;
    00213                     NtHeaders = RtlImageNtHeader( Base );
    00214                     Bounds = (ULONG_PTR)Base + NtHeaders->OptionalHeader.SizeOfImage;
    00215                     if (((ULONG_PTR)PcValue >= (ULONG_PTR)Base) && ((ULONG_PTR)PcValue < Bounds)) {
    00216                         RtlLeaveCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->LoaderLock);
    00217                         *BaseOfImage = Base;
    00218                         return Base;
    00219                     }
    00220                 }
    00221             }
    00222         }
    00223
    00224     } except(EXCEPTION_EXECUTE_HANDLER) {
    00225         NOTHING;
    00226     }
    00227
    00228     //
    00229     // Release the Loader lock for the current process a return NULL.
    00230     //
    00231
    00232     RtlLeaveCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->LoaderLock);
    00233     *BaseOfImage = NULL;
    00234     return NULL;
    00235
    00236 #endif
    00237
    00238 }