Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

239 lines
6.6 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. pctohdr.c
  5. Abstract:
  6. This module implements code to locate the file header for an image or
  7. dll given a PC value that lies within the image.
  8. N.B. This routine is conditionalized for user mode and kernel mode.
  9. Author:
  10. Steve Wood (stevewo) 18-Aug-1989
  11. Environment:
  12. User Mode or Kernel Mode
  13. Revision History:
  14. --*/
  15. #if defined(NTOS_KERNEL_RUNTIME)
  16. #include "ntos.h"
  17. #else
  18. #include <nt.h>
  19. #include <ntrtl.h>
  20. #include <nturtl.h>
  21. #endif
  22. #if !defined(NTOS_KERNEL_RUNTIME)
  23. extern PVOID NtDllBase; // defined in ntdll\ldrinit.c
  24. #endif
  25. PVOID
  26. RtlPcToFileHeader(
  27. IN PVOID PcValue,
  28. OUT PVOID *BaseOfImage
  29. )
  30. /*++
  31. Routine Description:
  32. This function returns the base of an image that contains the
  33. specified PcValue. An image contains the PcValue if the PcValue
  34. is within the ImageBase, and the ImageBase plus the size of the
  35. virtual image.
  36. Arguments:
  37. PcValue - Supplies a PcValue. All of the modules mapped into the
  38. calling processes address space are scanned to compute which
  39. module contains the PcValue.
  40. BaseOfImage - Returns the base address for the image containing the
  41. PcValue. This value must be added to any relative addresses in
  42. the headers to locate portions of the image.
  43. Return Value:
  44. NULL - No image was found that contains the PcValue.
  45. NON-NULL - Returns the base address of the image that contain the
  46. PcValue.
  47. --*/
  48. {
  49. #if defined(NTOS_KERNEL_RUNTIME)
  50. extern LIST_ENTRY PsLoadedModuleList;
  51. extern KSPIN_LOCK PsLoadedModuleSpinLock;
  52. PVOID Base;
  53. ULONG_PTR Bounds;
  54. PLDR_DATA_TABLE_ENTRY Entry;
  55. PLIST_ENTRY Next;
  56. KIRQL OldIrql;
  57. //
  58. // Acquire the loaded module list spinlock and scan the list for the
  59. // specified PC value if the list has been initialized.
  60. //
  61. OldIrql = KeGetCurrentIrql();
  62. if (OldIrql < DISPATCH_LEVEL) {
  63. KeRaiseIrqlToDpcLevel();
  64. }
  65. ExAcquireSpinLockAtDpcLevel(&PsLoadedModuleSpinLock);
  66. Next = PsLoadedModuleList.Flink;
  67. if (Next != NULL) {
  68. while (Next != &PsLoadedModuleList) {
  69. Entry = CONTAINING_RECORD(Next,
  70. LDR_DATA_TABLE_ENTRY,
  71. InLoadOrderLinks);
  72. Next = Next->Flink;
  73. Base = Entry->DllBase;
  74. Bounds = (ULONG_PTR)Base + Entry->SizeOfImage;
  75. if (((ULONG_PTR)PcValue >= (ULONG_PTR)Base) && ((ULONG_PTR)PcValue < Bounds)) {
  76. ExReleaseSpinLock(&PsLoadedModuleSpinLock, OldIrql);
  77. *BaseOfImage = Base;
  78. return Base;
  79. }
  80. }
  81. }
  82. //
  83. // Release the loaded module list spin lock and return NULL.
  84. //
  85. ExReleaseSpinLock(&PsLoadedModuleSpinLock, OldIrql);
  86. *BaseOfImage = NULL;
  87. return NULL;
  88. #else
  89. PVOID Base;
  90. ULONG_PTR Bounds;
  91. PLDR_DATA_TABLE_ENTRY Entry;
  92. PLIST_ENTRY ModuleListHead;
  93. PLIST_ENTRY Next;
  94. PIMAGE_NT_HEADERS NtHeaders;
  95. PPEB Peb;
  96. PTEB Teb;
  97. MEMORY_BASIC_INFORMATION MemInfo;
  98. NTSTATUS st;
  99. ULONG LoaderLockDisposition;
  100. PVOID LockCookie = NULL;
  101. //
  102. // Acquire the Loader lock for the current process and scan the loaded
  103. // module list for the specified PC value if all the data structures
  104. // have been initialized.
  105. //
  106. LdrLockLoaderLock(LDR_LOCK_LOADER_LOCK_FLAG_TRY_ONLY | LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS, &LoaderLockDisposition, &LockCookie);
  107. if (LoaderLockDisposition == LDR_LOCK_LOADER_LOCK_DISPOSITION_LOCK_NOT_ACQUIRED) {
  108. //
  109. // We could not get the loader lock, so call the system to find the image that
  110. // contains this pc
  111. //
  112. st = NtQueryVirtualMemory(
  113. NtCurrentProcess(),
  114. PcValue,
  115. MemoryBasicInformation,
  116. &MemInfo,
  117. sizeof(MemInfo),
  118. NULL);
  119. if ( !NT_SUCCESS(st) ) {
  120. MemInfo.AllocationBase = NULL;
  121. } else {
  122. if ( MemInfo.Type == MEM_IMAGE ) {
  123. try {
  124. *BaseOfImage = MemInfo.AllocationBase;
  125. } except (EXCEPTION_EXECUTE_HANDLER) {
  126. MemInfo.AllocationBase = NULL;
  127. }
  128. } else {
  129. MemInfo.AllocationBase = NULL;;
  130. }
  131. }
  132. return MemInfo.AllocationBase;
  133. }
  134. // If we *did* get the loader lock, let's avoid the syscall and search the tables.
  135. __try {
  136. Teb = NtCurrentTeb();
  137. if (Teb != NULL) {
  138. Peb = Teb->ProcessEnvironmentBlock;
  139. if (Peb->Ldr != NULL) {
  140. ModuleListHead = &Peb->Ldr->InLoadOrderModuleList;
  141. Next = ModuleListHead->Flink;
  142. if (Next != NULL) {
  143. while (Next != ModuleListHead) {
  144. Entry = CONTAINING_RECORD(Next, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
  145. Next = Next->Flink;
  146. Base = Entry->DllBase;
  147. NtHeaders = RtlImageNtHeader(Base);
  148. Bounds = (ULONG_PTR)Base + NtHeaders->OptionalHeader.SizeOfImage;
  149. if (((ULONG_PTR)PcValue >= (ULONG_PTR)Base) && ((ULONG_PTR)PcValue < Bounds)) {
  150. goto Done;
  151. }
  152. }
  153. }
  154. } else {
  155. //
  156. // ( Peb->Ldr == NULL )
  157. //
  158. // If called during process intialization before the Ldr
  159. // module list has been setup, code executing must be in
  160. // NTDLL module. If NtDllBase is non-NULL and the PcValue
  161. // falls into the NTDLL range, return a valid Base. This
  162. // allows DbgPrint's during LdrpInitializeProcess to work
  163. // on RISC machines.
  164. //
  165. if (NtDllBase != NULL) {
  166. Base = NtDllBase;
  167. NtHeaders = RtlImageNtHeader(Base);
  168. if (NtHeaders == NULL) {
  169. Base = NULL;
  170. goto Done;
  171. }
  172. Bounds = (ULONG_PTR)Base + NtHeaders->OptionalHeader.SizeOfImage;
  173. if (((ULONG_PTR)PcValue >= (ULONG_PTR)Base) && ((ULONG_PTR)PcValue < Bounds))
  174. goto Done;
  175. }
  176. }
  177. }
  178. Base = NULL;
  179. Done:
  180. ;
  181. } __except(EXCEPTION_EXECUTE_HANDLER) {
  182. Base = NULL;
  183. }
  184. LdrUnlockLoaderLock(LDR_UNLOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS, LockCookie);
  185. *BaseOfImage = Base;
  186. return Base;
  187. #endif
  188. }