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.

1477 lines
46 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. ldrwx86.c
  5. Abstract:
  6. This module implements the wx86 specific ldr functions.
  7. Author:
  8. 13-Jan-1995 Jonle , created
  9. Revision History:
  10. 15-Oct-1998 CBiks Modified the code that throws the architecture
  11. mismatch exception so the exception is only
  12. thrown for NT 3,0 and lower executables. This was
  13. changed to make the Wx86 loader behave like the
  14. real loader, which does not throw this exception.
  15. Also added a call to the cleanup function when
  16. LdrpWx86LoadDll() fails. There were cases where the
  17. CPU failed to initialize but the Wx86 global pointers
  18. were not cleared and pointed to a invalid memory because
  19. wx86.dll was unloaded.
  20. 13-Mar-2001 SamerA Fix sharing of varialbes inside a SHARED read/write section.
  21. 20-May-2001 SamerA Fix mapping of image sections that have their PointerToRawData
  22. RVA overlap with other sections virtual addresses.
  23. (Fixed corel's WP2002 intro.exe)
  24. 18-Sep-2001 SamerA Change page protection of image-pages to be compatible with what
  25. the section header says (x86 compatibility).
  26. 24-Oct-2001 SamerA Correct calculation of variables offsets inside the relocated
  27. shared section.
  28. --*/
  29. #include "ldrp.h"
  30. #include "ntos.h"
  31. #define PAGE_SIZE_X86 (0x1000)
  32. #if defined(BUILD_WOW6432)
  33. //
  34. // This table is indexed by the last 3 bits of the SectionHeader->Characteristics to get the page protection
  35. // from the section protection value. The result value is to be passed to NtProtectVirtualMemory ()
  36. //
  37. ULONG SectionToPageProtection [8] =
  38. {
  39. PAGE_NOACCESS,
  40. PAGE_EXECUTE,
  41. PAGE_READONLY,
  42. PAGE_EXECUTE_READ,
  43. PAGE_READWRITE,
  44. PAGE_EXECUTE_READWRITE,
  45. PAGE_READWRITE,
  46. PAGE_EXECUTE_READWRITE
  47. };
  48. //
  49. // From mi\mi.h:
  50. //
  51. #define MI_ROUND_TO_SIZE(LENGTH,ALIGNMENT) \
  52. (((LENGTH) + ((ALIGNMENT) - 1)) & ~((ALIGNMENT) - 1))
  53. PIMAGE_BASE_RELOCATION
  54. LdrpWx86ProcessRelocationBlock (
  55. IN ULONG_PTR VA,
  56. IN ULONG SizeOfBlock,
  57. IN PUSHORT NextOffset,
  58. IN ULONG Diff,
  59. IN ULONG_PTR SectionStartVA,
  60. IN ULONG_PTR SectionEndVA);
  61. NTSTATUS
  62. FixupBlockList(
  63. IN PUCHAR ImageBase);
  64. VOID
  65. FixupSectionHeader(
  66. IN PUCHAR ImageBase);
  67. NTSTATUS
  68. LdrpWx86FixupExportedSharedSection (
  69. IN PVOID ImageBase,
  70. IN PIMAGE_NT_HEADERS NtHeaders
  71. );
  72. BOOLEAN
  73. LdrpWx86DetectSectionOverlap (
  74. IN PIMAGE_NT_HEADERS NtHeaders
  75. )
  76. {
  77. PIMAGE_SECTION_HEADER SectionHeader;
  78. ULONG SrcRawData;
  79. ULONG SrcEndRawData;
  80. ULONG SrcSize;
  81. ULONG Section;
  82. ULONG SectionCheck;
  83. ULONG Count;
  84. BOOLEAN Result = FALSE;
  85. //
  86. // Run through the section and see if any one need to be moved down (higher in address space),
  87. // then for each one of those, check if it overlap with any section
  88. // that has already been moved up.
  89. //
  90. SectionHeader = IMAGE_FIRST_SECTION (NtHeaders);
  91. if (NtHeaders->FileHeader.NumberOfSections == 0) {
  92. return FALSE;
  93. }
  94. for (Section = NtHeaders->FileHeader.NumberOfSections-1, Count=0 ;
  95. Count < NtHeaders->FileHeader.NumberOfSections ; Section--, Count++) {
  96. SrcRawData = SectionHeader[Section].PointerToRawData;
  97. SrcSize = SectionHeader[Section].SizeOfRawData;
  98. if ((SectionHeader[Section].Misc.VirtualSize > 0) &&
  99. (SrcRawData > MI_ROUND_TO_SIZE(SectionHeader[Section].Misc.VirtualSize, PAGE_SIZE_X86))) {
  100. SrcSize = MI_ROUND_TO_SIZE(SectionHeader[Section].Misc.VirtualSize, PAGE_SIZE_X86);
  101. }
  102. if (SrcRawData > (MAXULONG - SrcSize)) {
  103. break;
  104. }
  105. SrcEndRawData = SrcRawData + SrcSize;
  106. //
  107. // This section needs to be moved down
  108. //
  109. for (SectionCheck = 0 ; SectionCheck < NtHeaders->FileHeader.NumberOfSections ; SectionCheck++) {
  110. if (Section == SectionCheck) {
  111. continue;
  112. }
  113. SrcSize = SectionHeader[SectionCheck].SizeOfRawData;
  114. if ((SectionHeader[SectionCheck].Misc.VirtualSize > 0) &&
  115. (SrcSize > MI_ROUND_TO_SIZE(SectionHeader[SectionCheck].Misc.VirtualSize, PAGE_SIZE_X86))) {
  116. SrcSize = MI_ROUND_TO_SIZE(SectionHeader[SectionCheck].Misc.VirtualSize, PAGE_SIZE_X86);
  117. }
  118. #if WOW6432_DBG
  119. DbgPrint("SrcRawData=%lx, SrcEndRawData=%lx, SectionFirstVA=%lx, SectionEndVA=%lx\n",
  120. SrcRawData, SrcEndRawData, SectionHeader[SectionCheck].VirtualAddress,
  121. SectionHeader[SectionCheck].VirtualAddress + SrcSize);
  122. #endif
  123. if (SectionHeader[SectionCheck].VirtualAddress > (MAXULONG - SrcSize)) {
  124. break;
  125. }
  126. if (((SrcRawData >= SectionHeader[SectionCheck].VirtualAddress) &&
  127. (SrcRawData < (SectionHeader[SectionCheck].VirtualAddress + SrcSize))) ||
  128. ((SrcEndRawData >= SectionHeader[SectionCheck].VirtualAddress) &&
  129. (SrcEndRawData < (SectionHeader[SectionCheck].VirtualAddress + SrcSize)))) {
  130. Result = TRUE;
  131. break;
  132. }
  133. }
  134. if (Result == TRUE) {
  135. break;
  136. }
  137. }
  138. return Result;
  139. }
  140. NTSTATUS
  141. LdrpWx86CheckVirtualSectionOverlap (
  142. IN PCUNICODE_STRING ImageName OPTIONAL,
  143. IN PIMAGE_NT_HEADERS NtHeaders,
  144. OUT PVOID *SrcImageMap
  145. )
  146. /*++
  147. Routine Description:
  148. This function goes through the image sections based at ImageBase and looks
  149. for any overlap between the section physical locations and their updated virtual
  150. locations.
  151. Arguments:
  152. ImageName - Unicode string pointer to the full path to the image.
  153. ImageBase - Base of image.
  154. SrcImageMap - Pointer to pointer to receive a base pointer to the image mapped
  155. as read-only pages inside this process. The mapped pages need to be released
  156. when done.
  157. Return Value:
  158. NTSTATUS.
  159. SUCCESS - Means the image has been found to have overlapped sections, and an
  160. alternate section has been mapped in.
  161. FAILURE - The image mapping failed or the image doesn't have overlapped sections.
  162. --*/
  163. {
  164. PUNICODE_STRING NtPathName;
  165. PVOID FreeBuffer;
  166. BOOLEAN Result;
  167. OBJECT_ATTRIBUTES ObjectAttributes;
  168. IO_STATUS_BLOCK IoStatusBlock;
  169. HANDLE FileHandle;
  170. HANDLE MappingHandle;
  171. PVOID ViewBase;
  172. SIZE_T ViewSize;
  173. LARGE_INTEGER SectionOffset;
  174. UCHAR Buffer[ DOS_MAX_PATH_LENGTH ];
  175. NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;
  176. //
  177. // Check for any overlap inside the image.
  178. //
  179. Result = LdrpWx86DetectSectionOverlap (NtHeaders);
  180. if (Result == FALSE) {
  181. return NtStatus;
  182. }
  183. FreeBuffer = NULL;
  184. //
  185. // Make sure we have a path.
  186. //
  187. NtPathName = (PUNICODE_STRING)Buffer;
  188. if (ARGUMENT_PRESENT (ImageName) == 0) {
  189. NtStatus = NtQueryInformationProcess(
  190. NtCurrentProcess(),
  191. ProcessImageFileName,
  192. NtPathName,
  193. sizeof (Buffer),
  194. NULL
  195. );
  196. } else {
  197. Result = RtlDosPathNameToNtPathName_U(
  198. ImageName->Buffer,
  199. NtPathName,
  200. NULL,
  201. NULL
  202. );
  203. if (Result != FALSE) {
  204. FreeBuffer = NtPathName->Buffer;
  205. NtStatus = STATUS_SUCCESS;
  206. }
  207. }
  208. if (NT_SUCCESS (NtStatus)) {
  209. InitializeObjectAttributes(
  210. &ObjectAttributes,
  211. NtPathName,
  212. OBJ_CASE_INSENSITIVE,
  213. NULL,
  214. NULL
  215. );
  216. NtStatus = NtCreateFile(
  217. &FileHandle,
  218. (ACCESS_MASK) GENERIC_READ | SYNCHRONIZE | FILE_READ_ATTRIBUTES,
  219. &ObjectAttributes,
  220. &IoStatusBlock,
  221. NULL,
  222. 0L,
  223. FILE_SHARE_READ | FILE_SHARE_DELETE,
  224. FILE_OPEN,
  225. 0L,
  226. NULL,
  227. 0L
  228. );
  229. if (FreeBuffer != NULL) {
  230. RtlFreeHeap (RtlProcessHeap(), 0, FreeBuffer);
  231. }
  232. if (NT_SUCCESS (NtStatus)) {
  233. NtStatus = NtCreateSection(
  234. &MappingHandle,
  235. STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
  236. NULL,
  237. NULL,
  238. PAGE_READONLY,
  239. SEC_COMMIT,
  240. FileHandle
  241. );
  242. NtClose (FileHandle);
  243. if (NT_SUCCESS (NtStatus)) {
  244. SectionOffset.LowPart = 0;
  245. SectionOffset.HighPart = 0;
  246. ViewSize = 0;
  247. ViewBase = NULL;
  248. NtStatus = NtMapViewOfSection(
  249. MappingHandle,
  250. NtCurrentProcess(),
  251. &ViewBase,
  252. 0L,
  253. 0L,
  254. &SectionOffset,
  255. &ViewSize,
  256. ViewShare,
  257. 0L,
  258. PAGE_READONLY
  259. );
  260. NtClose (MappingHandle);
  261. if (NT_SUCCESS (NtStatus)) {
  262. *SrcImageMap = ViewBase;
  263. }
  264. }
  265. }
  266. }
  267. return NtStatus;
  268. }
  269. NTSTATUS
  270. LdrpWx86ProtectImagePages (
  271. IN PVOID Base,
  272. IN BOOLEAN Reset
  273. )
  274. /*++
  275. Routine Description:
  276. This function loops through the image sections, and reset the page protection
  277. to what is specified inside the section header.
  278. Arguments:
  279. Base - Base of image.
  280. Reset - Indicate whether to reset to original section protection.
  281. Return Value:
  282. SUCCESS or reason NtProtectVirtualMemory failed.
  283. --*/
  284. {
  285. NTSTATUS NtStatus = STATUS_SUCCESS;
  286. ULONG SectionIndex;
  287. ULONG RegionSize;
  288. ULONG SectionCharacteristics;
  289. ULONG PageProtection;
  290. ULONG OldProtection;
  291. PIMAGE_NT_HEADERS NtHeaders;
  292. PIMAGE_SECTION_HEADER Section;
  293. PVOID VirtualAddress;
  294. NtHeaders = RtlImageNtHeader (Base);
  295. if (NtHeaders == NULL) {
  296. if (ShowSnaps) {
  297. DbgPrint ("LdrpWx86ProtectImagePages - Failed to read NtImageHeaders. Base=%p\n", Base);
  298. }
  299. return STATUS_INTERNAL_ERROR;
  300. }
  301. NtStatus = Wx86SetRelocatedSharedProtection (Base, Reset);
  302. if (!NT_SUCCESS (NtStatus)) {
  303. if (ShowSnaps) {
  304. DbgPrint("LdrpWx86ProtectImagePages - Wx86SetRelocatedSharedProtection(%p, TRUE) failed - NtStatus\n",
  305. Base, NtStatus);
  306. }
  307. return NtStatus;
  308. }
  309. Section = (PIMAGE_SECTION_HEADER) ((ULONG_PTR)NtHeaders + sizeof (ULONG) +
  310. sizeof (IMAGE_FILE_HEADER) +
  311. NtHeaders->FileHeader.SizeOfOptionalHeader);
  312. //
  313. // Loop through available sections, making sure not to touch sharable pages, as they are relocated to the
  314. // the end of the image.
  315. //
  316. for (SectionIndex = 0 ; SectionIndex < NtHeaders->FileHeader.NumberOfSections ; SectionIndex++, Section++) {
  317. RegionSize = Section->SizeOfRawData;
  318. if (Section->Misc.VirtualSize != 0) {
  319. RegionSize = Section->Misc.VirtualSize;
  320. }
  321. RegionSize = MI_ROUND_TO_SIZE (RegionSize, PAGE_SIZE_X86);
  322. if (RegionSize != 0) {
  323. SectionCharacteristics = Section->Characteristics;
  324. if ((SectionCharacteristics & IMAGE_SCN_MEM_SHARED) == 0) {
  325. if (Reset) {
  326. PageProtection = SectionToPageProtection [SectionCharacteristics >> 29];
  327. } else {
  328. PageProtection = PAGE_READWRITE;
  329. }
  330. VirtualAddress = (PVOID)((ULONG_PTR)Base + Section->VirtualAddress);
  331. NtStatus = NtProtectVirtualMemory (NtCurrentProcess (),
  332. &VirtualAddress,
  333. &RegionSize,
  334. PageProtection,
  335. &OldProtection);
  336. #if WOW6432_DBG
  337. DbgPrint("Protecting %lx - VA=%lx, Prot=%lx, SectionProt=%lx, Size = %lx, ST=%lx\n",
  338. Base, ((ULONG_PTR)Base + Section->VirtualAddress), PageProtection, SectionCharacteristics,
  339. RegionSize, NtStatus);
  340. #endif
  341. if (!NT_SUCCESS (NtStatus)) {
  342. if (ShowSnaps) {
  343. DbgPrint ("LdrpWx86ProtectImagePages - Failed to protect section %lx at %lx with protection %lx\n",
  344. SectionIndex, ((ULONG_PTR)Base + Section->VirtualAddress), PageProtection);
  345. }
  346. return NtStatus;
  347. }
  348. }
  349. }
  350. }
  351. return NtStatus;
  352. }
  353. NTSTATUS
  354. Wx86SetRelocatedSharedProtection (
  355. IN PVOID Base,
  356. IN BOOLEAN Reset
  357. )
  358. /*++
  359. Routine Description:
  360. This function loops thru the images sections/objects, setting
  361. all relocated shared sections/objects marked r/o to r/w. It also resets the
  362. original section/object protections.
  363. Arguments:
  364. Base - Base of image.
  365. Reset - If TRUE, reset section/object protection to original
  366. protection described by the section/object headers.
  367. If FALSE, then set all sections/objects to r/w.
  368. Return Value:
  369. SUCCESS or reason NtProtectVirtualMemory failed.
  370. --*/
  371. {
  372. HANDLE CurrentProcessHandle;
  373. SIZE_T RegionSize;
  374. ULONG NewProtect, OldProtect;
  375. PVOID VirtualAddress;
  376. ULONG i;
  377. PIMAGE_NT_HEADERS NtHeaders;
  378. PIMAGE_SECTION_HEADER SectionHeader;
  379. NTSTATUS st;
  380. ULONG NumberOfSharedDataPages;
  381. SIZE_T NumberOfNativePagesForImage;
  382. CurrentProcessHandle = NtCurrentProcess();
  383. NtHeaders = RtlImageNtHeader(Base);
  384. if (NtHeaders == NULL) {
  385. return STATUS_INVALID_PARAMETER;
  386. }
  387. SectionHeader = (PIMAGE_SECTION_HEADER)((ULONG_PTR)NtHeaders + sizeof(ULONG) +
  388. sizeof(IMAGE_FILE_HEADER) +
  389. NtHeaders->FileHeader.SizeOfOptionalHeader
  390. );
  391. NumberOfSharedDataPages = 0;
  392. NumberOfNativePagesForImage =
  393. NATIVE_BYTES_TO_PAGES (NtHeaders->OptionalHeader.SizeOfImage);
  394. for (i=0; i<NtHeaders->FileHeader.NumberOfSections; i++, SectionHeader++) {
  395. RegionSize = SectionHeader->SizeOfRawData;
  396. if ((SectionHeader->Characteristics & IMAGE_SCN_MEM_SHARED) &&
  397. (!(SectionHeader->Characteristics & IMAGE_SCN_MEM_EXECUTE) ||
  398. (SectionHeader->Characteristics & IMAGE_SCN_MEM_WRITE)) &&
  399. (RegionSize != 0)) {
  400. VirtualAddress = (PVOID)((ULONG_PTR)Base +
  401. ((NumberOfNativePagesForImage + NumberOfSharedDataPages) << NATIVE_PAGE_SHIFT));
  402. NumberOfNativePagesForImage += MI_ROUND_TO_SIZE (RegionSize, NATIVE_PAGE_SIZE) >> NATIVE_PAGE_SHIFT;
  403. if (!(SectionHeader->Characteristics & IMAGE_SCN_MEM_WRITE)) {
  404. //
  405. // Object isn't writeable, so change it.
  406. //
  407. if (Reset) {
  408. if (SectionHeader->Characteristics & IMAGE_SCN_MEM_EXECUTE) {
  409. NewProtect = PAGE_EXECUTE;
  410. }
  411. else {
  412. NewProtect = PAGE_READONLY;
  413. }
  414. NewProtect |= (SectionHeader->Characteristics & IMAGE_SCN_MEM_NOT_CACHED) ? PAGE_NOCACHE : 0;
  415. }
  416. else {
  417. NewProtect = PAGE_READWRITE;
  418. }
  419. st = NtProtectVirtualMemory(CurrentProcessHandle, &VirtualAddress,
  420. &RegionSize, NewProtect, &OldProtect);
  421. if (!NT_SUCCESS(st)) {
  422. if (ShowSnaps) {
  423. DbgPrint("Wx86SetRelocatedSharedProtection - Failed to protect memory: Va=%p, RegionSize=%lx, NewProtect=%lx - %lx\n",
  424. VirtualAddress, RegionSize, NewProtect, st);
  425. }
  426. return st;
  427. }
  428. }
  429. }
  430. }
  431. if (Reset) {
  432. st = NtFlushInstructionCache(
  433. NtCurrentProcess(),
  434. Base,
  435. NumberOfNativePagesForImage << NATIVE_PAGE_SHIFT
  436. );
  437. if (!NT_SUCCESS(st)) {
  438. return st;
  439. }
  440. }
  441. return STATUS_SUCCESS;
  442. }
  443. VOID
  444. LdrpWx86RelocateImageDirectoryEntries (
  445. IN PVOID Base,
  446. IN PIMAGE_NT_HEADERS32 NtHeaders
  447. )
  448. {
  449. ULONG Rva;
  450. ULONG DirectoryEntry;
  451. DirectoryEntry = 0;
  452. while (DirectoryEntry < NtHeaders->OptionalHeader.NumberOfRvaAndSizes) {
  453. //
  454. // [askhalid] - don't relocate resource entries. Somecode check that against imagezise
  455. // if you must relocate resource entry then must change image size that might cause more appcompat.
  456. //
  457. if ((NtHeaders->OptionalHeader.DataDirectory [DirectoryEntry].VirtualAddress != 0) &&
  458. (NtHeaders->OptionalHeader.DataDirectory [DirectoryEntry].Size > 0)&&
  459. ( DirectoryEntry != IMAGE_DIRECTORY_ENTRY_RESOURCE) ) {
  460. Rva = NtHeaders->OptionalHeader.DataDirectory [DirectoryEntry].VirtualAddress;
  461. NtHeaders->OptionalHeader.DataDirectory [DirectoryEntry].VirtualAddress +=
  462. LdrpWx86RelocatedFixupDiff (Base,
  463. NtHeaders,
  464. NtHeaders->OptionalHeader.DataDirectory [DirectoryEntry].VirtualAddress
  465. );
  466. if (ShowSnaps) {
  467. if (Rva != NtHeaders->OptionalHeader.DataDirectory [DirectoryEntry].VirtualAddress) {
  468. DbgPrint("LdrpWx86RelocateImageDirectoryEntry (%p) - Relocating DirEntry %lx from %lx to %lx\n",
  469. Base, DirectoryEntry, Rva, NtHeaders->OptionalHeader.DataDirectory [DirectoryEntry].VirtualAddress);
  470. }
  471. }
  472. }
  473. DirectoryEntry++;
  474. }
  475. return;
  476. }
  477. NTSTATUS
  478. LdrpWx86FormatVirtualImage (
  479. IN PCUNICODE_STRING DosImagePathName OPTIONAL,
  480. IN PIMAGE_NT_HEADERS32 NtHeaders,
  481. IN PVOID DllBase
  482. )
  483. {
  484. PIMAGE_SECTION_HEADER SectionTable, Section, LastSection, FirstSection;
  485. PUCHAR NextVirtualAddress, SrcVirtualAddress, DestVirtualAddress;
  486. PUCHAR ImageBase= DllBase;
  487. LONG Size;
  488. ULONG NumberOfSharedDataPages;
  489. ULONG NumberOfNativePagesForImage;
  490. ULONG NumberOfExtraPagesForImage;
  491. ULONG_PTR PreferredImageBase;
  492. BOOLEAN ImageHasRelocatedSharedSection = FALSE;
  493. ULONG bFirst;
  494. ULONG SubSectionSize;
  495. PVOID AlternateBase;
  496. NTSTATUS st;
  497. AlternateBase = NULL;
  498. st = LdrpWx86CheckVirtualSectionOverlap (DosImagePathName,
  499. NtHeaders,
  500. &AlternateBase);
  501. #if WOW6432_DBG
  502. if (NT_SUCCESS (st) && (AlternateBase != NULL))
  503. {
  504. DbgPrint("Mapping in %wZ with AlternateBase = %p\n", DosImagePathName, AlternateBase);
  505. }
  506. #endif
  507. st = Wx86SetRelocatedSharedProtection (DllBase, FALSE);
  508. if (!NT_SUCCESS(st)) {
  509. DbgPrint("Wx86SetRelocatedSharedProtection failed with return status %x\n", st);
  510. Wx86SetRelocatedSharedProtection(DllBase, TRUE);
  511. if (AlternateBase != NULL) {
  512. NtUnmapViewOfSection (NtCurrentProcess(), AlternateBase);
  513. }
  514. return st;
  515. }
  516. //
  517. // Copy each section from its raw file address to its virtual address
  518. //
  519. SectionTable = IMAGE_FIRST_SECTION(NtHeaders);
  520. LastSection = SectionTable + NtHeaders->FileHeader.NumberOfSections;
  521. if (SectionTable->PointerToRawData == SectionTable->VirtualAddress) {
  522. // If the first section does not need to be moved then we exclude it
  523. // from consideration in passes 1 and 2
  524. FirstSection = SectionTable + 1;
  525. }
  526. else {
  527. FirstSection = SectionTable;
  528. }
  529. //
  530. // First pass starts at the top and works down moving up each section that
  531. // is to be moved up.
  532. //
  533. Section = FirstSection;
  534. while (Section < LastSection) {
  535. SrcVirtualAddress = ImageBase + Section->PointerToRawData;
  536. DestVirtualAddress = Section->VirtualAddress + ImageBase;
  537. if (DestVirtualAddress >= SrcVirtualAddress) {
  538. // Section needs to be moved down
  539. break;
  540. }
  541. // Section needs to be moved up
  542. if (Section->SizeOfRawData != 0) {
  543. if (Section->PointerToRawData != 0) {
  544. RtlMoveMemory(DestVirtualAddress,
  545. SrcVirtualAddress,
  546. Section->SizeOfRawData);
  547. }
  548. }
  549. else {
  550. Section->PointerToRawData = 0;
  551. }
  552. Section++;
  553. }
  554. //
  555. // Second pass is from the end of the image and work backwards since src and
  556. // dst overlap
  557. //
  558. Section = --LastSection;
  559. NextVirtualAddress = ImageBase + MI_ROUND_TO_SIZE(NtHeaders->OptionalHeader.SizeOfImage, PAGE_SIZE_X86);
  560. while (Section >= FirstSection) {
  561. SrcVirtualAddress = ImageBase + Section->PointerToRawData;
  562. DestVirtualAddress = Section->VirtualAddress + ImageBase;
  563. //
  564. // Compute the subsection size. The mm is really flexible here...
  565. // it will allow a SizeOfRawData that far exceeds the virtual size,
  566. // so we can't trust that. If that happens, just use the page-aligned
  567. // virtual size, since that is all that the mm will map in.
  568. //
  569. SubSectionSize = Section->SizeOfRawData;
  570. if (Section->Misc.VirtualSize &&
  571. SubSectionSize > MI_ROUND_TO_SIZE(Section->Misc.VirtualSize, PAGE_SIZE_X86)) {
  572. SubSectionSize = MI_ROUND_TO_SIZE(Section->Misc.VirtualSize, PAGE_SIZE_X86);
  573. }
  574. //
  575. // ensure Virtual section doesn't overlap the next section
  576. //
  577. if (DestVirtualAddress + SubSectionSize > NextVirtualAddress) {
  578. Wx86SetRelocatedSharedProtection(DllBase, TRUE);
  579. if (AlternateBase != NULL) {
  580. NtUnmapViewOfSection (NtCurrentProcess(), AlternateBase);
  581. }
  582. return STATUS_INVALID_IMAGE_FORMAT;
  583. }
  584. if ((DestVirtualAddress <= SrcVirtualAddress) &&
  585. (AlternateBase == NULL)) {
  586. //
  587. // Section needs to be moved up
  588. //
  589. break;
  590. }
  591. //
  592. // Section needs to be moved down
  593. //
  594. if (Section->SizeOfRawData != 0) {
  595. if (Section->PointerToRawData != 0) {
  596. RtlMoveMemory(DestVirtualAddress,
  597. (AlternateBase != NULL) ?
  598. ((PUCHAR)AlternateBase + Section->PointerToRawData) : SrcVirtualAddress,
  599. SubSectionSize);
  600. }
  601. }
  602. else {
  603. Section->PointerToRawData = 0;
  604. }
  605. NextVirtualAddress = DestVirtualAddress;
  606. Section--;
  607. }
  608. //
  609. // Third pass is for zeroing out any memory left between the end of a
  610. // section and the end of the page. We'll do this from end to top
  611. //
  612. Section = LastSection;
  613. NextVirtualAddress = ImageBase + MI_ROUND_TO_SIZE(NtHeaders->OptionalHeader.SizeOfImage, PAGE_SIZE_X86);
  614. NumberOfSharedDataPages = 0;
  615. while (Section >= SectionTable) {
  616. DestVirtualAddress = Section->VirtualAddress + ImageBase;
  617. //
  618. // Shared Data sections cannot be shared, because of
  619. // page misalignment, and are treated as Exec- Copy on Write.
  620. //
  621. if ((Section->Characteristics & IMAGE_SCN_MEM_SHARED) &&
  622. (!(Section->Characteristics & IMAGE_SCN_MEM_EXECUTE) ||
  623. (Section->Characteristics & IMAGE_SCN_MEM_WRITE))) {
  624. ImageHasRelocatedSharedSection = TRUE;
  625. if (ShowSnaps) {
  626. DbgPrint("Unsupported IMAGE_SCN_MEM_SHARED %x\n",
  627. Section->Characteristics
  628. );
  629. }
  630. }
  631. //
  632. // If section was empty zero it out
  633. //
  634. if (Section->SizeOfRawData != 0) {
  635. if (Section->PointerToRawData == 0) {
  636. RtlZeroMemory(DestVirtualAddress,
  637. Section->SizeOfRawData
  638. );
  639. }
  640. }
  641. SubSectionSize = Section->SizeOfRawData;
  642. if (Section->Misc.VirtualSize &&
  643. SubSectionSize > MI_ROUND_TO_SIZE(Section->Misc.VirtualSize, PAGE_SIZE_X86)) {
  644. SubSectionSize = MI_ROUND_TO_SIZE(Section->Misc.VirtualSize, PAGE_SIZE_X86);
  645. }
  646. //
  647. // Zero out remaining bytes up to the next section
  648. //
  649. RtlZeroMemory(DestVirtualAddress + Section->SizeOfRawData,
  650. (ULONG)(NextVirtualAddress - DestVirtualAddress - SubSectionSize)
  651. );
  652. NextVirtualAddress = DestVirtualAddress;
  653. Section--;
  654. }
  655. //
  656. // Unmap the alternate base if it is there
  657. //
  658. if (AlternateBase != NULL) {
  659. NtUnmapViewOfSection (NtCurrentProcess(), AlternateBase);
  660. }
  661. // Pass 4: if the dll has any shared sections, change the shared data
  662. // references to point to additional shared pages at the end of the image.
  663. //
  664. // Note that our fixups are applied assuming that the dll is loaded at
  665. // its preferred base; if it is loaded at some other address, it will
  666. // be relocated again along will all other addresses.
  667. if (!ImageHasRelocatedSharedSection) {
  668. goto LdrwWx86FormatVirtualImageDone;
  669. }
  670. st = FixupBlockList(DllBase);
  671. if (!NT_SUCCESS(st)) {
  672. Wx86SetRelocatedSharedProtection(DllBase, TRUE);
  673. return st;
  674. }
  675. LdrpWx86RelocateImageDirectoryEntries (DllBase, NtHeaders);
  676. NumberOfNativePagesForImage =
  677. NATIVE_BYTES_TO_PAGES (NtHeaders->OptionalHeader.SizeOfImage);
  678. NumberOfExtraPagesForImage = 0;
  679. // Account for raw data that extends beyond SizeOfImage
  680. for (Section = SectionTable; Section <= LastSection; Section++)
  681. {
  682. ULONG EndOfSection;
  683. ULONG ExtraPages;
  684. ULONG ImagePages = NATIVE_BYTES_TO_PAGES (NtHeaders->OptionalHeader.SizeOfImage);
  685. EndOfSection = Section->PointerToRawData + Section->SizeOfRawData;
  686. if (NATIVE_BYTES_TO_PAGES (EndOfSection) > ImagePages) {
  687. ExtraPages = NATIVE_BYTES_TO_PAGES (EndOfSection) - ImagePages;
  688. if (ExtraPages > NumberOfExtraPagesForImage) {
  689. NumberOfExtraPagesForImage = ExtraPages;
  690. }
  691. }
  692. }
  693. PreferredImageBase = NtHeaders->OptionalHeader.ImageBase;
  694. NumberOfNativePagesForImage += NumberOfExtraPagesForImage;
  695. NumberOfSharedDataPages = 0;
  696. bFirst = 1;
  697. for (Section = SectionTable; Section <= LastSection; Section++) {
  698. if ((Section->Characteristics & IMAGE_SCN_MEM_SHARED) &&
  699. (!(Section->Characteristics & IMAGE_SCN_MEM_EXECUTE) ||
  700. (Section->Characteristics & IMAGE_SCN_MEM_WRITE)))
  701. {
  702. PIMAGE_BASE_RELOCATION NextBlock;
  703. PUSHORT NextOffset;
  704. ULONG TotalBytes;
  705. ULONG SizeOfBlock;
  706. ULONG_PTR VA;
  707. ULONG_PTR SectionStartVA;
  708. ULONG_PTR SectionEndVA;
  709. ULONG SectionVirtualSize;
  710. ULONG Diff;
  711. SectionVirtualSize = Section->Misc.VirtualSize;
  712. if (SectionVirtualSize == 0)
  713. {
  714. SectionVirtualSize = Section->SizeOfRawData;
  715. }
  716. SectionStartVA = PreferredImageBase + Section->VirtualAddress;
  717. SectionEndVA = SectionStartVA + SectionVirtualSize;
  718. NextBlock = RtlImageDirectoryEntryToData(DllBase, TRUE,
  719. IMAGE_DIRECTORY_ENTRY_BASERELOC,
  720. &TotalBytes);
  721. if (!NextBlock || !TotalBytes)
  722. {
  723. // Note that if this fails, it should fail in the very
  724. // first iteration and no fixups would have been performed
  725. if (!bFirst)
  726. {
  727. // Trouble
  728. if (ShowSnaps)
  729. {
  730. DbgPrint("LdrpWx86FormatVirtualImage: failure "
  731. "after relocating some sections for image at %x\n",
  732. DllBase);
  733. }
  734. Wx86SetRelocatedSharedProtection(DllBase, TRUE);
  735. return STATUS_INVALID_IMAGE_FORMAT;
  736. }
  737. if (ShowSnaps)
  738. {
  739. DbgPrint("LdrpWx86FormatVirtualImage: No fixup info "
  740. "for image at %x; private sections will be "
  741. "used for shared data sections.\n",
  742. DllBase);
  743. }
  744. break;
  745. }
  746. bFirst = 0;
  747. Diff = (NumberOfNativePagesForImage +
  748. NumberOfSharedDataPages) << NATIVE_PAGE_SHIFT;
  749. Diff -= (ULONG) (SectionStartVA - PreferredImageBase);
  750. if (ShowSnaps)
  751. {
  752. DbgPrint("LdrpWx86FormatVirtualImage: Relocating shared "
  753. "data for shared data section 0x%x of image "
  754. "at %x by 0x%lx bytes\n",
  755. Section - SectionTable + 1, DllBase, Diff);
  756. }
  757. while (TotalBytes)
  758. {
  759. SizeOfBlock = NextBlock->SizeOfBlock;
  760. if (SizeOfBlock == 0) {
  761. if (ShowSnaps) {
  762. DbgPrint("Image at %lx contains invalid block size. Stopping fixups\n",
  763. ImageBase);
  764. }
  765. break;
  766. }
  767. TotalBytes -= SizeOfBlock;
  768. SizeOfBlock -= sizeof(IMAGE_BASE_RELOCATION);
  769. SizeOfBlock /= sizeof(USHORT);
  770. NextOffset = (PUSHORT) ((PCHAR)NextBlock +
  771. sizeof(IMAGE_BASE_RELOCATION));
  772. VA = (ULONG_PTR) DllBase + NextBlock->VirtualAddress;
  773. NextBlock = LdrpWx86ProcessRelocationBlock (VA,
  774. SizeOfBlock,
  775. NextOffset,
  776. Diff,
  777. SectionStartVA,
  778. SectionEndVA);
  779. if (NextBlock == NULL)
  780. {
  781. // Trouble
  782. if (ShowSnaps)
  783. {
  784. DbgPrint("LdrpWx86FormatVirtualImage: failure "
  785. "after relocating some sections for image at %x; "
  786. "Relocation information invalid\n",
  787. DllBase);
  788. }
  789. Wx86SetRelocatedSharedProtection(DllBase, TRUE);
  790. return STATUS_INVALID_IMAGE_FORMAT;
  791. }
  792. }
  793. NumberOfSharedDataPages += MI_ROUND_TO_SIZE (SectionVirtualSize,
  794. NATIVE_PAGE_SIZE) >>
  795. NATIVE_PAGE_SHIFT;
  796. }
  797. }
  798. //
  799. // If any of the variables inside the shared section is exported, then
  800. // we need to fix up its RVA to point to the proper location at
  801. // the end of the image.
  802. //
  803. LdrpWx86FixupExportedSharedSection (DllBase, NtHeaders);
  804. LdrwWx86FormatVirtualImageDone:
  805. //
  806. // Zero out first section's Raw Data up to its VirtualAddress
  807. //
  808. if (SectionTable->PointerToRawData != 0) {
  809. DestVirtualAddress = SectionTable->PointerToRawData + ImageBase;
  810. Size = (LONG)(NextVirtualAddress - DestVirtualAddress);
  811. if (Size > 0) {
  812. RtlZeroMemory(DestVirtualAddress, (ULONG)Size);
  813. }
  814. }
  815. //
  816. // Protect the shared pages
  817. //
  818. st = LdrpWx86ProtectImagePages (DllBase, TRUE);
  819. if (!NT_SUCCESS(st)) {
  820. return st;
  821. }
  822. return STATUS_SUCCESS;
  823. }
  824. NTSTATUS
  825. LdrpWx86FixupExportedSharedSection (
  826. IN PVOID ImageBase,
  827. IN PIMAGE_NT_HEADERS NtHeaders
  828. )
  829. /*++
  830. Routine Description:
  831. This function goes through the exported entries from this module,
  832. and relocates (fixup) any address that lie inside any shared
  833. read/write to the end of the image.
  834. Arguments:
  835. ImageBase - Virtual address for image base.
  836. NtHeaders - Address of the image's header.
  837. Return Value:
  838. NTSTATUS.
  839. --*/
  840. {
  841. PIMAGE_EXPORT_DIRECTORY ImageExportDirectory;
  842. ULONG TotalBytes;
  843. ULONG SharedRelocFixup;
  844. ULONG Export;
  845. PULONG ExportEntry;
  846. NTSTATUS NtStatus = STATUS_SUCCESS;
  847. ImageExportDirectory = RtlImageDirectoryEntryToData (
  848. ImageBase,
  849. TRUE,
  850. IMAGE_DIRECTORY_ENTRY_EXPORT,
  851. &TotalBytes);
  852. if ((ImageExportDirectory == NULL) || (TotalBytes == 0)) {
  853. return NtStatus;
  854. }
  855. ExportEntry = (PULONG)((ULONG)ImageBase + ImageExportDirectory->AddressOfFunctions);
  856. for (Export = 0 ; Export < ImageExportDirectory->NumberOfFunctions ; Export++) {
  857. SharedRelocFixup = LdrpWx86RelocatedFixupDiff (
  858. ImageBase,
  859. NtHeaders,
  860. ExportEntry[Export]
  861. );
  862. if (SharedRelocFixup != 0) {
  863. if (ShowSnaps) {
  864. DbgPrint("LdrpWx86FixupExportedSharedSection: Changing export Export[%lx] from %lx to %lx\n",
  865. Export,
  866. ExportEntry[Export],
  867. ExportEntry [Export] + SharedRelocFixup);
  868. }
  869. ExportEntry [Export] += SharedRelocFixup;
  870. }
  871. }
  872. return NtStatus;
  873. }
  874. ////////////////////////////////////////////////////
  875. ULONG
  876. LdrpWx86RelocatedFixupDiff(
  877. IN PUCHAR ImageBase,
  878. IN PIMAGE_NT_HEADERS NtHeaders,
  879. IN ULONG Offset
  880. )
  881. {
  882. PIMAGE_SECTION_HEADER SectionHeader;
  883. ULONG i;
  884. ULONG NumberOfSharedDataPages;
  885. ULONG NumberOfNativePagesForImage;
  886. ULONG Diff = 0;
  887. ULONG_PTR FixupAddr = (ULONG_PTR)(ImageBase + Offset);
  888. SectionHeader = (PIMAGE_SECTION_HEADER)((ULONG_PTR)NtHeaders + sizeof(ULONG) +
  889. sizeof(IMAGE_FILE_HEADER) +
  890. NtHeaders->FileHeader.SizeOfOptionalHeader
  891. );
  892. NumberOfNativePagesForImage =
  893. NATIVE_BYTES_TO_PAGES (NtHeaders->OptionalHeader.SizeOfImage);
  894. NumberOfSharedDataPages = 0;
  895. for (i=0; i<NtHeaders->FileHeader.NumberOfSections; i++, SectionHeader++)
  896. {
  897. ULONG_PTR SectionStartVA;
  898. ULONG_PTR SectionEndVA;
  899. ULONG SectionVirtualSize;
  900. SectionVirtualSize = SectionHeader->Misc.VirtualSize;
  901. if (SectionVirtualSize == 0) {
  902. SectionVirtualSize = SectionHeader->SizeOfRawData;
  903. }
  904. SectionStartVA = (ULONG_PTR)ImageBase + SectionHeader->VirtualAddress;
  905. SectionEndVA = SectionStartVA + SectionVirtualSize;
  906. if (((ULONG_PTR)FixupAddr >= SectionStartVA) && ((ULONG_PTR)FixupAddr < SectionEndVA)) {
  907. if ((SectionHeader->Characteristics & IMAGE_SCN_MEM_SHARED) &&
  908. (!(SectionHeader->Characteristics & IMAGE_SCN_MEM_EXECUTE) ||
  909. (SectionHeader->Characteristics & IMAGE_SCN_MEM_WRITE))) {
  910. Diff = (NumberOfNativePagesForImage +
  911. NumberOfSharedDataPages) << NATIVE_PAGE_SHIFT;
  912. Diff -= (ULONG)SectionHeader->VirtualAddress;
  913. }
  914. break;
  915. }
  916. if ((SectionHeader->Characteristics & IMAGE_SCN_MEM_SHARED) &&
  917. (!(SectionHeader->Characteristics & IMAGE_SCN_MEM_EXECUTE) ||
  918. (SectionHeader->Characteristics & IMAGE_SCN_MEM_WRITE))) {
  919. NumberOfSharedDataPages += MI_ROUND_TO_SIZE (SectionVirtualSize,
  920. NATIVE_PAGE_SIZE) >>
  921. NATIVE_PAGE_SHIFT;
  922. }
  923. }
  924. return Diff;
  925. }
  926. NTSTATUS
  927. FixupBlockList (
  928. IN PUCHAR ImageBase)
  929. {
  930. PIMAGE_BASE_RELOCATION NextBlock;
  931. PUSHORT NextOffset;
  932. ULONG TotalBytes;
  933. ULONG SizeOfBlock;
  934. PIMAGE_NT_HEADERS NtHeaders;
  935. NextBlock = RtlImageDirectoryEntryToData(ImageBase, TRUE,
  936. IMAGE_DIRECTORY_ENTRY_BASERELOC,
  937. &TotalBytes);
  938. if (!NextBlock || !TotalBytes) {
  939. if (ShowSnaps) {
  940. DbgPrint("LdrpWx86FixupBlockList: No fixup info "
  941. "for image at %x; private sections will be "
  942. "used for shared data sections.\n",
  943. ImageBase);
  944. }
  945. return STATUS_SUCCESS;
  946. }
  947. NtHeaders = RtlImageNtHeader (ImageBase);
  948. if (! NtHeaders) {
  949. if (ShowSnaps) {
  950. DbgPrint("LdrpWx86FixupBlockList: failure "
  951. "to locate image header for image at %x.\n",
  952. ImageBase);
  953. }
  954. return STATUS_INVALID_IMAGE_FORMAT;
  955. }
  956. while (TotalBytes) {
  957. SizeOfBlock = NextBlock->SizeOfBlock;
  958. if (SizeOfBlock == 0) {
  959. if (ShowSnaps) {
  960. DbgPrint("Image at %lx contains invalid block size. Stopping fixups\n",
  961. ImageBase);
  962. }
  963. break;
  964. }
  965. TotalBytes -= SizeOfBlock;
  966. SizeOfBlock -= sizeof(IMAGE_BASE_RELOCATION);
  967. SizeOfBlock /= sizeof(USHORT);
  968. NextOffset = (PUSHORT) ((PCHAR)NextBlock +
  969. sizeof(IMAGE_BASE_RELOCATION));
  970. NextBlock->VirtualAddress += LdrpWx86RelocatedFixupDiff (
  971. ImageBase,
  972. NtHeaders,
  973. NextBlock->VirtualAddress
  974. );
  975. while (SizeOfBlock--) {
  976. switch ((*NextOffset) >> 12) {
  977. case IMAGE_REL_BASED_HIGHLOW :
  978. case IMAGE_REL_BASED_HIGH :
  979. case IMAGE_REL_BASED_LOW :
  980. break;
  981. case IMAGE_REL_BASED_HIGHADJ :
  982. ++NextOffset;
  983. --SizeOfBlock;
  984. break;
  985. case IMAGE_REL_BASED_IA64_IMM64:
  986. case IMAGE_REL_BASED_DIR64:
  987. case IMAGE_REL_BASED_MIPS_JMPADDR :
  988. case IMAGE_REL_BASED_ABSOLUTE :
  989. case IMAGE_REL_BASED_SECTION :
  990. case IMAGE_REL_BASED_REL32 :
  991. break;
  992. default :
  993. return STATUS_INVALID_IMAGE_FORMAT;
  994. }
  995. ++NextOffset;
  996. }
  997. NextBlock = (PIMAGE_BASE_RELOCATION)NextOffset;
  998. if (NextBlock == NULL) {
  999. // Trouble
  1000. if (ShowSnaps) {
  1001. DbgPrint("LdrpWx86FixupBlockList: failure "
  1002. "after relocating some sections for image at %x; "
  1003. "Relocation information invalid\n",
  1004. ImageBase);
  1005. }
  1006. return STATUS_INVALID_IMAGE_FORMAT;
  1007. }
  1008. }
  1009. return STATUS_SUCCESS;
  1010. }
  1011. BOOLEAN
  1012. LdrpWx86DllHasRelocatedSharedSection(
  1013. IN PUCHAR ImageBase)
  1014. {
  1015. PIMAGE_SECTION_HEADER SectionHeader;
  1016. ULONG i;
  1017. PIMAGE_NT_HEADERS32 NtHeaders = (PIMAGE_NT_HEADERS32)RtlImageNtHeader(ImageBase);
  1018. if (! NtHeaders) {
  1019. return FALSE;
  1020. }
  1021. SectionHeader = (PIMAGE_SECTION_HEADER)((ULONG_PTR)NtHeaders + sizeof(ULONG) +
  1022. sizeof(IMAGE_FILE_HEADER) +
  1023. NtHeaders->FileHeader.SizeOfOptionalHeader
  1024. );
  1025. for (i=0; i<NtHeaders->FileHeader.NumberOfSections; i++, SectionHeader++)
  1026. {
  1027. if ((SectionHeader->Characteristics & IMAGE_SCN_MEM_SHARED) &&
  1028. (!(SectionHeader->Characteristics & IMAGE_SCN_MEM_EXECUTE) ||
  1029. (SectionHeader->Characteristics & IMAGE_SCN_MEM_WRITE))) {
  1030. return TRUE;
  1031. }
  1032. }
  1033. return FALSE;
  1034. }
  1035. ////////////////////////////////////////////////
  1036. // Following fn is adapted from rtl\ldrreloc.c; it should be updated when
  1037. // that function changes. Eliminated 64 bit address relocations.
  1038. //
  1039. // Note: Instead of calling this routine, we could call
  1040. // LdrpProcessRelocationBlock(VA, 1, NextOffset, Diff)
  1041. //
  1042. // but we should do that only if the address to be relocated is between
  1043. // SectionStartVA and SectionEndVA. So we would have to replicate all the
  1044. // code in the switch stmt below that computes the address of the data item -
  1045. // which is pretty much the entire function. So we chose to replicate the
  1046. // function as it was and change it to make the test.
  1047. PIMAGE_BASE_RELOCATION
  1048. LdrpWx86ProcessRelocationBlock (
  1049. IN ULONG_PTR VA,
  1050. IN ULONG SizeOfBlock,
  1051. IN PUSHORT NextOffset,
  1052. IN ULONG Diff,
  1053. IN ULONG_PTR SectionStartVA,
  1054. IN ULONG_PTR SectionEndVA)
  1055. {
  1056. PUCHAR FixupVA;
  1057. USHORT Offset;
  1058. LONG Temp;
  1059. ULONG_PTR DataVA;
  1060. while (SizeOfBlock--) {
  1061. Offset = *NextOffset & (USHORT)0xfff;
  1062. FixupVA = (PUCHAR)(VA + Offset);
  1063. //
  1064. // Apply the fixups.
  1065. //
  1066. switch ((*NextOffset) >> 12) {
  1067. case IMAGE_REL_BASED_HIGHLOW :
  1068. //
  1069. // HighLow - (32-bits) relocate the high and low half
  1070. // of an address.
  1071. //
  1072. Temp = *(LONG UNALIGNED *)FixupVA;
  1073. DataVA = (ULONG_PTR) Temp;
  1074. if (DataVA >= SectionStartVA && DataVA <= SectionEndVA)
  1075. {
  1076. Temp += (ULONG) Diff;
  1077. *(LONG UNALIGNED *)FixupVA = Temp;
  1078. }
  1079. break;
  1080. case IMAGE_REL_BASED_HIGH :
  1081. //
  1082. // High - (16-bits) relocate the high half of an address.
  1083. //
  1084. Temp = *(PUSHORT)FixupVA << 16;
  1085. DataVA = (ULONG_PTR) Temp;
  1086. if (DataVA >= SectionStartVA && DataVA <= SectionEndVA)
  1087. {
  1088. Temp += (ULONG) Diff;
  1089. *(PUSHORT)FixupVA = (USHORT)(Temp >> 16);
  1090. }
  1091. break;
  1092. case IMAGE_REL_BASED_HIGHADJ :
  1093. //
  1094. // Adjust high - (16-bits) relocate the high half of an
  1095. // address and adjust for sign extension of low half.
  1096. //
  1097. Temp = *(PUSHORT)FixupVA << 16;
  1098. ++NextOffset;
  1099. --SizeOfBlock;
  1100. Temp += (LONG)(*(PSHORT)NextOffset);
  1101. DataVA = (ULONG_PTR) Temp;
  1102. if (DataVA >= SectionStartVA && DataVA <= SectionEndVA)
  1103. {
  1104. Temp += (ULONG) Diff;
  1105. Temp += 0x8000;
  1106. *(PUSHORT)FixupVA = (USHORT)(Temp >> 16);
  1107. }
  1108. break;
  1109. case IMAGE_REL_BASED_LOW :
  1110. //
  1111. // Low - (16-bit) relocate the low half of an address.
  1112. //
  1113. Temp = *(PSHORT)FixupVA;
  1114. DataVA = (ULONG_PTR) Temp;
  1115. if (DataVA >= SectionStartVA && DataVA <= SectionEndVA)
  1116. {
  1117. Temp += (ULONG) Diff;
  1118. *(PUSHORT)FixupVA = (USHORT)Temp;
  1119. }
  1120. break;
  1121. case IMAGE_REL_BASED_IA64_IMM64:
  1122. //
  1123. // Align it to bundle address before fixing up the
  1124. // 64-bit immediate value of the movl instruction.
  1125. //
  1126. // No need to support
  1127. break;
  1128. case IMAGE_REL_BASED_DIR64:
  1129. //
  1130. // Update 32-bit address
  1131. //
  1132. // No need to support
  1133. break;
  1134. case IMAGE_REL_BASED_MIPS_JMPADDR :
  1135. //
  1136. // JumpAddress - (32-bits) relocate a MIPS jump address.
  1137. //
  1138. // No need to support
  1139. break;
  1140. case IMAGE_REL_BASED_ABSOLUTE :
  1141. //
  1142. // Absolute - no fixup required.
  1143. //
  1144. break;
  1145. case IMAGE_REL_BASED_SECTION :
  1146. //
  1147. // Section Relative reloc. Ignore for now.
  1148. //
  1149. break;
  1150. case IMAGE_REL_BASED_REL32 :
  1151. //
  1152. // Relative intrasection. Ignore for now.
  1153. //
  1154. break;
  1155. default :
  1156. //
  1157. // Illegal - illegal relocation type.
  1158. //
  1159. return (PIMAGE_BASE_RELOCATION)NULL;
  1160. }
  1161. ++NextOffset;
  1162. }
  1163. return (PIMAGE_BASE_RELOCATION)NextOffset;
  1164. }
  1165. #endif // BUILD_WOW6432