Leaked source code of windows server 2003
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.

639 lines
16 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. imagedir.c
  5. Abstract:
  6. The module contains the code to translate an image directory type to
  7. the address of the data for that entry.
  8. Author:
  9. Steve Wood (stevewo) 18-Aug-1989
  10. Environment:
  11. User Mode or Kernel Mode
  12. Revision History:
  13. --*/
  14. #include "ntrtlp.h"
  15. #if defined(NTOS_KERNEL_RUNTIME)
  16. VOID
  17. RtlpTouchMemory(
  18. IN PVOID Address,
  19. IN ULONG Length
  20. );
  21. VOID
  22. RtlpMakeStackTraceDataPresentForImage(
  23. IN PVOID ImageBase
  24. );
  25. #if defined(ALLOC_PRAGMA)
  26. #pragma alloc_text(PAGE,RtlpTouchMemory)
  27. #pragma alloc_text(PAGE,RtlMakeStackTraceDataPresent)
  28. #pragma alloc_text(PAGE,RtlpMakeStackTraceDataPresentForImage)
  29. #endif
  30. #endif
  31. PIMAGE_SECTION_HEADER
  32. RtlSectionTableFromVirtualAddress (
  33. IN PIMAGE_NT_HEADERS NtHeaders,
  34. IN PVOID Base,
  35. IN ULONG Address
  36. )
  37. /*++
  38. Routine Description:
  39. This function locates a VirtualAddress within the image header
  40. of a file that is mapped as a file and returns a pointer to the
  41. section table entry for that virtual address
  42. Arguments:
  43. NtHeaders - Supplies the pointer to the image or data file.
  44. Base - Supplies the base of the image or data file.
  45. Address - Supplies the virtual address to locate.
  46. Return Value:
  47. NULL - The file does not contain data for the specified directory entry.
  48. NON-NULL - Returns the pointer of the section entry containing the data.
  49. --*/
  50. {
  51. ULONG i;
  52. PIMAGE_SECTION_HEADER NtSection;
  53. NtSection = IMAGE_FIRST_SECTION( NtHeaders );
  54. for (i=0; i<NtHeaders->FileHeader.NumberOfSections; i++) {
  55. if ((ULONG)Address >= NtSection->VirtualAddress &&
  56. (ULONG)Address < NtSection->VirtualAddress + NtSection->SizeOfRawData
  57. ) {
  58. return NtSection;
  59. }
  60. ++NtSection;
  61. }
  62. return NULL;
  63. }
  64. PVOID
  65. RtlAddressInSectionTable (
  66. IN PIMAGE_NT_HEADERS NtHeaders,
  67. IN PVOID Base,
  68. IN ULONG Address
  69. )
  70. /*++
  71. Routine Description:
  72. This function locates a VirtualAddress within the image header
  73. of a file that is mapped as a file and returns the seek address
  74. of the data the Directory describes.
  75. Arguments:
  76. NtHeaders - Supplies the pointer to the image or data file.
  77. Base - Supplies the base of the image or data file.
  78. Address - Supplies the virtual address to locate.
  79. Return Value:
  80. NULL - The file does not contain data for the specified directory entry.
  81. NON-NULL - Returns the address of the raw data the directory describes.
  82. --*/
  83. {
  84. PIMAGE_SECTION_HEADER NtSection;
  85. NtSection = RtlSectionTableFromVirtualAddress( NtHeaders,
  86. Base,
  87. Address
  88. );
  89. if (NtSection != NULL) {
  90. return( ((PCHAR)Base + ((ULONG_PTR)Address - NtSection->VirtualAddress) + NtSection->PointerToRawData) );
  91. }
  92. else {
  93. return( NULL );
  94. }
  95. }
  96. PVOID
  97. RtlpImageDirectoryEntryToData32 (
  98. IN PVOID Base,
  99. IN BOOLEAN MappedAsImage,
  100. IN USHORT DirectoryEntry,
  101. OUT PULONG Size,
  102. PIMAGE_NT_HEADERS32 NtHeaders
  103. )
  104. {
  105. ULONG DirectoryAddress;
  106. if (DirectoryEntry >= NtHeaders->OptionalHeader.NumberOfRvaAndSizes) {
  107. return( NULL );
  108. }
  109. if (!(DirectoryAddress = NtHeaders->OptionalHeader.DataDirectory[ DirectoryEntry ].VirtualAddress)) {
  110. return( NULL );
  111. }
  112. #if defined(NTOS_KERNEL_RUNTIME)
  113. if (Base < MM_HIGHEST_USER_ADDRESS) {
  114. if ((PVOID)((PCHAR)Base + DirectoryAddress) >= MM_HIGHEST_USER_ADDRESS) {
  115. return( NULL );
  116. }
  117. }
  118. #endif
  119. *Size = NtHeaders->OptionalHeader.DataDirectory[ DirectoryEntry ].Size;
  120. if (MappedAsImage || DirectoryAddress < NtHeaders->OptionalHeader.SizeOfHeaders) {
  121. return( (PVOID)((PCHAR)Base + DirectoryAddress) );
  122. }
  123. return( RtlAddressInSectionTable((PIMAGE_NT_HEADERS)NtHeaders, Base, DirectoryAddress ));
  124. }
  125. PVOID
  126. RtlpImageDirectoryEntryToData64 (
  127. IN PVOID Base,
  128. IN BOOLEAN MappedAsImage,
  129. IN USHORT DirectoryEntry,
  130. OUT PULONG Size,
  131. PIMAGE_NT_HEADERS64 NtHeaders
  132. )
  133. {
  134. ULONG DirectoryAddress;
  135. if (DirectoryEntry >= NtHeaders->OptionalHeader.NumberOfRvaAndSizes) {
  136. return( NULL );
  137. }
  138. if (!(DirectoryAddress = NtHeaders->OptionalHeader.DataDirectory[ DirectoryEntry ].VirtualAddress)) {
  139. return( NULL );
  140. }
  141. #if defined(NTOS_KERNEL_RUNTIME)
  142. if (Base < MM_HIGHEST_USER_ADDRESS) {
  143. if ((PVOID)((PCHAR)Base + DirectoryAddress) >= MM_HIGHEST_USER_ADDRESS) {
  144. return( NULL );
  145. }
  146. }
  147. #endif
  148. *Size = NtHeaders->OptionalHeader.DataDirectory[ DirectoryEntry ].Size;
  149. if (MappedAsImage || DirectoryAddress < NtHeaders->OptionalHeader.SizeOfHeaders) {
  150. return( (PVOID)((PCHAR)Base + DirectoryAddress) );
  151. }
  152. return( RtlAddressInSectionTable((PIMAGE_NT_HEADERS)NtHeaders, Base, DirectoryAddress ));
  153. }
  154. PVOID
  155. RtlImageDirectoryEntryToData (
  156. IN PVOID Base,
  157. IN BOOLEAN MappedAsImage,
  158. IN USHORT DirectoryEntry,
  159. OUT PULONG Size
  160. )
  161. /*++
  162. Routine Description:
  163. This function locates a Directory Entry within the image header
  164. and returns either the virtual address or seek address of the
  165. data the Directory describes.
  166. Arguments:
  167. Base - Supplies the base of the image or data file.
  168. MappedAsImage - FALSE if the file is mapped as a data file.
  169. - TRUE if the file is mapped as an image.
  170. DirectoryEntry - Supplies the directory entry to locate.
  171. Size - Return the size of the directory.
  172. Return Value:
  173. NULL - The file does not contain data for the specified directory entry.
  174. NON-NULL - Returns the address of the raw data the directory describes.
  175. --*/
  176. {
  177. PIMAGE_NT_HEADERS NtHeaders;
  178. if (LDR_IS_DATAFILE(Base)) {
  179. Base = LDR_DATAFILE_TO_VIEW(Base);
  180. MappedAsImage = FALSE;
  181. }
  182. NtHeaders = RtlImageNtHeader(Base);
  183. if (!NtHeaders)
  184. return NULL;
  185. if (NtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
  186. return (RtlpImageDirectoryEntryToData32(Base,
  187. MappedAsImage,
  188. DirectoryEntry,
  189. Size,
  190. (PIMAGE_NT_HEADERS32)NtHeaders));
  191. } else if (NtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
  192. return (RtlpImageDirectoryEntryToData64(Base,
  193. MappedAsImage,
  194. DirectoryEntry,
  195. Size,
  196. (PIMAGE_NT_HEADERS64)NtHeaders));
  197. } else {
  198. return (NULL);
  199. }
  200. }
  201. #if defined(NTOS_KERNEL_RUNTIME)
  202. VOID
  203. RtlMakeStackTraceDataPresent(
  204. VOID
  205. )
  206. /*++
  207. Routine Description:
  208. This function walks the loaded user-mode images and makes present the
  209. portions of the data necessary to support a kernel-debugger stack
  210. dump of the user-mode stack.
  211. N.B. The necessary pieces are merely touched to be brought in. In a low
  212. memory situation, some of the previously-touched pages may be paged
  213. out in order for the new ones to be brought in. This routine is
  214. not guaranteed to do anything useful, however it does more often than
  215. not.
  216. Arguments:
  217. None.
  218. Return value:
  219. None.
  220. --*/
  221. {
  222. PPEB peb;
  223. PLIST_ENTRY head;
  224. PLIST_ENTRY next;
  225. PVOID imageBase;
  226. ULONG imageCount;
  227. LDR_DATA_TABLE_ENTRY UNALIGNED *ldrDataTableEntry;
  228. RTL_PAGED_CODE();
  229. //
  230. // The image list is in user mode and is not to be trusted. The
  231. // surrounding try/except block will guard against most forms of
  232. // list corruption. imageCount is used to bail in finite time
  233. // in the event of a cyclic image list.
  234. //
  235. imageCount = 0;
  236. try {
  237. peb = NtCurrentPeb();
  238. head = &peb->Ldr->InLoadOrderModuleList;
  239. ProbeForReadSmallStructure( head,
  240. sizeof(LIST_ENTRY),
  241. PROBE_ALIGNMENT(LIST_ENTRY) );
  242. next = head;
  243. while (imageCount < 1000) {
  244. next = next->Flink;
  245. if (next == head) {
  246. break;
  247. }
  248. imageCount += 1;
  249. //
  250. // Locate the base address of the image
  251. //
  252. ldrDataTableEntry = CONTAINING_RECORD(next,
  253. LDR_DATA_TABLE_ENTRY,
  254. InLoadOrderLinks);
  255. ProbeForReadSmallStructure( ldrDataTableEntry,
  256. sizeof(LDR_DATA_TABLE_ENTRY),
  257. PROBE_ALIGNMENT(LDR_DATA_TABLE_ENTRY) );
  258. imageBase = ldrDataTableEntry->DllBase;
  259. ProbeForReadSmallStructure (imageBase, sizeof (IMAGE_DOS_HEADER), sizeof (UCHAR));
  260. //
  261. // Make the stack trace data present for this image. Use a
  262. // seperate try/except block here so that subsequent images
  263. // will be processed in the event of a failure.
  264. //
  265. try {
  266. RtlpMakeStackTraceDataPresentForImage(imageBase);
  267. } except (EXCEPTION_EXECUTE_HANDLER) {
  268. NOTHING;
  269. }
  270. }
  271. } except (EXCEPTION_EXECUTE_HANDLER) {
  272. NOTHING;
  273. }
  274. }
  275. VOID
  276. RtlpMakeStackTraceDataPresentForImage(
  277. IN PVOID ImageBase
  278. )
  279. /*++
  280. Routine Description:
  281. This function attempts to make present the portions of an image necessary
  282. to support a kernel-debugger stack dump of the user-mode stack.
  283. Arguments:
  284. ImageBase - Supplies the VA of the base of the image to process.
  285. Return value:
  286. None.
  287. --*/
  288. {
  289. PVOID directory;
  290. ULONG directorySize;
  291. PIMAGE_RUNTIME_FUNCTION_ENTRY functionEntry;
  292. PIMAGE_RUNTIME_FUNCTION_ENTRY lastFunctionEntry;
  293. PCHAR imageBase;
  294. #if defined(_IA64_)
  295. PUNWIND_INFO unwindInfo;
  296. #endif
  297. RTL_PAGED_CODE();
  298. //
  299. // Make present the IMAGE_DIRECTORY_EXCEPTION section.
  300. //
  301. directory = RtlImageDirectoryEntryToData(ImageBase,
  302. TRUE,
  303. IMAGE_DIRECTORY_ENTRY_EXCEPTION,
  304. &directorySize);
  305. if (directory == NULL) {
  306. return;
  307. }
  308. RtlpTouchMemory(directory, directorySize);
  309. #if defined(_IA64_)
  310. //
  311. // The IMAGE_DIRECTORY_EXCEPTION section is an array of
  312. // IMAGE_RUNTIME_FUNCTION_ENTRY structures. Each function entry
  313. // refers, via UnwindInfoAddress (expressed as an image offset) to
  314. // an UNWIND_INFO structure.
  315. //
  316. // All UNWIND_INFO structures must be made present.
  317. //
  318. functionEntry = (PIMAGE_RUNTIME_FUNCTION_ENTRY)directory;
  319. lastFunctionEntry = functionEntry +
  320. directorySize / sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY);
  321. while (functionEntry < lastFunctionEntry) {
  322. unwindInfo = (PUNWIND_INFO)((PCHAR)ImageBase +
  323. functionEntry->UnwindInfoAddress);
  324. //
  325. // An UNWIND_INFO structure consists of a fixed header plus
  326. // a variable-length portion.
  327. //
  328. RtlpTouchMemory(unwindInfo,
  329. sizeof(UNWIND_INFO) +
  330. unwindInfo->DataLength * sizeof(ULONGLONG));
  331. functionEntry += 1;
  332. }
  333. //
  334. // Make present the IMAGE_DIRECTORY_ENTRY_GLOBALPTR section.
  335. //
  336. directory = RtlImageDirectoryEntryToData(ImageBase,
  337. TRUE,
  338. IMAGE_DIRECTORY_ENTRY_GLOBALPTR,
  339. &directorySize);
  340. if (directory == NULL) {
  341. return;
  342. }
  343. RtlpTouchMemory(directory, directorySize);
  344. #endif // _IA64_
  345. }
  346. VOID
  347. RtlpTouchMemory(
  348. IN PVOID Address,
  349. IN ULONG Length
  350. )
  351. /*++
  352. Routine Description:
  353. This function touches all of the pages within a given region.
  354. Arguments:
  355. Address - Supplies the VA of the start of the image to make present.
  356. Length - Supplies the length, in bytes, of the image to make present.
  357. Return value:
  358. None.
  359. --*/
  360. {
  361. PCHAR regionStart;
  362. PCHAR regionEnd;
  363. RTL_PAGED_CODE();
  364. regionStart = Address;
  365. regionEnd = regionStart + Length;
  366. while (regionStart < regionEnd) {
  367. *(volatile UCHAR *)regionStart;
  368. regionStart = PAGE_ALIGN(regionStart + PAGE_SIZE);
  369. }
  370. }
  371. #endif
  372. #if !defined(NTOS_KERNEL_RUNTIME) && !defined(BLDR_KERNEL_RUNTIME)
  373. PIMAGE_SECTION_HEADER
  374. RtlImageRvaToSection(
  375. IN PIMAGE_NT_HEADERS NtHeaders,
  376. IN PVOID Base,
  377. IN ULONG Rva
  378. )
  379. /*++
  380. Routine Description:
  381. This function locates an RVA within the image header of a file
  382. that is mapped as a file and returns a pointer to the section
  383. table entry for that virtual address
  384. Arguments:
  385. NtHeaders - Supplies the pointer to the image or data file.
  386. Base - Supplies the base of the image or data file. The image
  387. was mapped as a data file.
  388. Rva - Supplies the relative virtual address (RVA) to locate.
  389. Return Value:
  390. NULL - The RVA was not found within any of the sections of the image.
  391. NON-NULL - Returns the pointer to the image section that contains
  392. the RVA
  393. --*/
  394. {
  395. ULONG i;
  396. PIMAGE_SECTION_HEADER NtSection;
  397. NtSection = IMAGE_FIRST_SECTION( NtHeaders );
  398. for (i=0; i<NtHeaders->FileHeader.NumberOfSections; i++) {
  399. if (Rva >= NtSection->VirtualAddress &&
  400. Rva < NtSection->VirtualAddress + NtSection->SizeOfRawData
  401. ) {
  402. return NtSection;
  403. }
  404. ++NtSection;
  405. }
  406. return NULL;
  407. }
  408. PVOID
  409. RtlImageRvaToVa(
  410. IN PIMAGE_NT_HEADERS NtHeaders,
  411. IN PVOID Base,
  412. IN ULONG Rva,
  413. IN OUT PIMAGE_SECTION_HEADER *LastRvaSection OPTIONAL
  414. )
  415. /*++
  416. Routine Description:
  417. This function locates an RVA within the image header of a file that
  418. is mapped as a file and returns the virtual addrees of the
  419. corresponding byte in the file.
  420. Arguments:
  421. NtHeaders - Supplies the pointer to the image or data file.
  422. Base - Supplies the base of the image or data file. The image
  423. was mapped as a data file.
  424. Rva - Supplies the relative virtual address (RVA) to locate.
  425. LastRvaSection - Optional parameter that if specified, points
  426. to a variable that contains the last section value used for
  427. the specified image to translate and RVA to a VA.
  428. Return Value:
  429. NULL - The file does not contain the specified RVA
  430. NON-NULL - Returns the virtual addrees in the mapped file.
  431. --*/
  432. {
  433. PIMAGE_SECTION_HEADER NtSection;
  434. if (!ARGUMENT_PRESENT( LastRvaSection ) ||
  435. (NtSection = *LastRvaSection) == NULL ||
  436. Rva < NtSection->VirtualAddress ||
  437. Rva >= NtSection->VirtualAddress + NtSection->SizeOfRawData
  438. ) {
  439. NtSection = RtlImageRvaToSection( NtHeaders,
  440. Base,
  441. Rva
  442. );
  443. }
  444. if (NtSection != NULL) {
  445. if (LastRvaSection != NULL) {
  446. *LastRvaSection = NtSection;
  447. }
  448. return (PVOID)((PCHAR)Base +
  449. (Rva - NtSection->VirtualAddress) +
  450. NtSection->PointerToRawData
  451. );
  452. }
  453. else {
  454. return NULL;
  455. }
  456. }
  457. #endif