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.

837 lines
28 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. rebase.c
  5. Abstract:
  6. Source file for the REBASE utility that takes a group of image files and
  7. rebases them so they are packed as closely together in the virtual address
  8. space as possible.
  9. Author:
  10. Mark Lucovsky (markl) 30-Apr-1993
  11. Revision History:
  12. --*/
  13. #include <private.h>
  14. //
  15. // byte swapping macros (LE/BE) used for IA64 relocations
  16. // source != destination
  17. //
  18. #define SWAP_SHORT(_dst,_src) \
  19. ((((unsigned char *)_dst)[1] = ((unsigned char *)_src)[0]), \
  20. (((unsigned char *)_dst)[0] = ((unsigned char *)_src)[1]))
  21. #define SWAP_INT(_dst,_src) \
  22. ((((unsigned char *)_dst)[3] = ((unsigned char *)_src)[0]), \
  23. (((unsigned char *)_dst)[2] = ((unsigned char *)_src)[1]), \
  24. (((unsigned char *)_dst)[1] = ((unsigned char *)_src)[2]), \
  25. (((unsigned char *)_dst)[0] = ((unsigned char *)_src)[3]))
  26. #define SWAP_LONG_LONG(_dst,_src) \
  27. ((((unsigned char *)_dst)[7] = ((unsigned char *)_src)[0]), \
  28. (((unsigned char *)_dst)[6] = ((unsigned char *)_src)[1]), \
  29. (((unsigned char *)_dst)[5] = ((unsigned char *)_src)[2]), \
  30. (((unsigned char *)_dst)[4] = ((unsigned char *)_src)[3]), \
  31. (((unsigned char *)_dst)[3] = ((unsigned char *)_src)[4]), \
  32. (((unsigned char *)_dst)[2] = ((unsigned char *)_src)[5]), \
  33. (((unsigned char *)_dst)[1] = ((unsigned char *)_src)[6]), \
  34. (((unsigned char *)_dst)[0] = ((unsigned char *)_src)[7]))
  35. #define REBASE_ERR 99
  36. #define REBASE_OK 0
  37. static
  38. PVOID
  39. RvaToVa(
  40. ULONG Rva,
  41. PLOADED_IMAGE Image
  42. );
  43. typedef
  44. PIMAGE_BASE_RELOCATION
  45. (WINAPI *LPRELOCATE_ROUTINE)(
  46. IN ULONG_PTR VA,
  47. IN ULONG SizeOfBlock,
  48. IN PUSHORT NextOffset,
  49. IN LONG_PTR Diff
  50. );
  51. typedef
  52. PIMAGE_BASE_RELOCATION
  53. (WINAPI *LPRELOCATE_ROUTINE64)(
  54. IN ULONG_PTR VA,
  55. IN ULONG SizeOfBlock,
  56. IN PUSHORT NextOffset,
  57. IN LONGLONG Diff
  58. );
  59. static LPRELOCATE_ROUTINE RelocRoutineNative;
  60. static LPRELOCATE_ROUTINE64 RelocRoutine64;
  61. PIMAGE_BASE_RELOCATION
  62. xxLdrProcessRelocationBlock64(
  63. IN ULONG_PTR VA,
  64. IN ULONG SizeOfBlock,
  65. IN PUSHORT NextOffset,
  66. IN LONGLONG Diff
  67. );
  68. #define x256MEG (256*(1024*1024))
  69. #define x256MEGSHIFT 28
  70. #define ROUND_UP( Size, Amount ) (((ULONG)(Size) + ((Amount) - 1)) & ~((Amount) - 1))
  71. VOID
  72. AdjImageBaseSize(
  73. PULONG pImageBase,
  74. PULONG ImageSize,
  75. BOOL fGoingDown
  76. );
  77. BOOL
  78. RelocateImage(
  79. PLOADED_IMAGE LoadedImage,
  80. ULONG64 NewBase,
  81. ULONG64 *Diff,
  82. ULONG tstamp
  83. );
  84. BOOL
  85. ReBaseImage(
  86. IN LPSTR CurrentImageName,
  87. IN LPSTR SymbolPath, // Symbol path (if
  88. IN BOOL fReBase, // TRUE if actually rebasing, false if only summing
  89. IN BOOL fRebaseSysfileOk, // TRUE is system images s/b rebased
  90. IN BOOL fGoingDown, // TRUE if the image s/b rebased below the given base
  91. IN ULONG CheckImageSize, // Max size allowed (0 if don't care)
  92. OUT ULONG *OldImageSize, // Returned from the header
  93. OUT ULONG_PTR *OldImageBase, // Returned from the header
  94. OUT ULONG *NewImageSize, // Image size rounded to next separation boundary
  95. IN OUT ULONG_PTR *NewImageBase, // (in) Desired new address.
  96. // (out) Next new address (above/below this one)
  97. IN ULONG tstamp // new timestamp for image
  98. )
  99. {
  100. ULONG64 xOldImageBase = *OldImageBase;
  101. ULONG64 xNewImageBase = *NewImageBase;
  102. BOOL rc;
  103. rc = ReBaseImage64(
  104. CurrentImageName,
  105. SymbolPath,
  106. fReBase,
  107. fRebaseSysfileOk,
  108. fGoingDown,
  109. CheckImageSize,
  110. OldImageSize,
  111. &xOldImageBase,
  112. NewImageSize,
  113. &xNewImageBase,
  114. tstamp);
  115. *OldImageBase = (ULONG_PTR)xOldImageBase;
  116. *NewImageBase = (ULONG_PTR)xNewImageBase;
  117. return rc;
  118. }
  119. BOOL
  120. ReBaseImage64(
  121. IN LPSTR CurrentImageName,
  122. IN LPSTR SymbolPath, // Symbol path (if
  123. IN BOOL fReBase, // TRUE if actually rebasing, false if only summing
  124. IN BOOL fRebaseSysfileOk, // TRUE is system images s/b rebased
  125. IN BOOL fGoingDown, // TRUE if the image s/b rebased below the given base
  126. IN ULONG CheckImageSize, // Max size allowed (0 if don't care)
  127. OUT ULONG *OldImageSize, // Returned from the header
  128. OUT ULONG64 *OldImageBase, // Returned from the header
  129. OUT ULONG *NewImageSize, // Image size rounded to next separation boundary
  130. IN OUT ULONG64 *NewImageBase, // (in) Desired new address.
  131. // (out) Next new address (above/below this one)
  132. IN ULONG tstamp // new timestamp for image
  133. )
  134. {
  135. BOOL fSymbolsAlreadySplit = FALSE;
  136. CHAR DebugFileName[ MAX_PATH+1 ];
  137. CHAR DebugFilePath[ MAX_PATH+1 ];
  138. ULONG CurrentImageSize;
  139. ULONG64 DesiredImageBase;
  140. ULONG OldChecksum;
  141. ULONG64 Diff = 0;
  142. ULONG UpdateSymbolsError = 0;
  143. LOADED_IMAGE CurrentImage = {0};
  144. BOOL rc = TRUE;
  145. if (fReBase && (*NewImageBase & 0x0000FFFF) != 0) {
  146. rc = FALSE;
  147. UpdateSymbolsError = ERROR_INVALID_ADDRESS;
  148. goto Exit;
  149. }
  150. // Map and load the current image
  151. if ( MapAndLoad( CurrentImageName, NULL, &CurrentImage, FALSE, fReBase ? FALSE : TRUE ) ) {
  152. PVOID pData;
  153. DWORD dwDataSize;
  154. pData = ImageDirectoryEntryToData(
  155. CurrentImage.MappedAddress,
  156. FALSE,
  157. IMAGE_DIRECTORY_ENTRY_SECURITY,
  158. &dwDataSize
  159. );
  160. if (pData || dwDataSize) {
  161. // Certificates in the image, can't rebase
  162. UpdateSymbolsError = ERROR_BAD_EXE_FORMAT;
  163. rc = FALSE;
  164. goto CleanupAndExit;
  165. }
  166. pData = ImageDirectoryEntryToData(
  167. CurrentImage.MappedAddress,
  168. FALSE,
  169. IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR,
  170. &dwDataSize
  171. );
  172. if (pData || dwDataSize) {
  173. // COR header found - see if it's strong signed
  174. if (((IMAGE_COR20_HEADER *)pData)->StrongNameSignature.VirtualAddress &&
  175. ((IMAGE_COR20_HEADER *)pData)->StrongNameSignature.Size)
  176. {
  177. UpdateSymbolsError = ERROR_BAD_EXE_FORMAT;
  178. rc = FALSE;
  179. goto CleanupAndExit;
  180. }
  181. }
  182. if (!(!fRebaseSysfileOk && CurrentImage.fSystemImage)) {
  183. fSymbolsAlreadySplit = CurrentImage.Characteristics & IMAGE_FILE_DEBUG_STRIPPED ? TRUE : FALSE;
  184. if ( fSymbolsAlreadySplit ) {
  185. // Find DebugFileName for later use.
  186. PIMAGE_DEBUG_DIRECTORY DebugDirectories;
  187. ULONG DebugDirectoriesSize;
  188. PIMAGE_DEBUG_MISC MiscDebug;
  189. strcpy( DebugFileName, CurrentImageName );
  190. DebugDirectories = (PIMAGE_DEBUG_DIRECTORY)ImageDirectoryEntryToData(
  191. CurrentImage.MappedAddress,
  192. FALSE,
  193. IMAGE_DIRECTORY_ENTRY_DEBUG,
  194. &DebugDirectoriesSize
  195. );
  196. if (DebugDirectoryIsUseful(DebugDirectories, DebugDirectoriesSize)) {
  197. while (DebugDirectoriesSize != 0) {
  198. if (DebugDirectories->Type == IMAGE_DEBUG_TYPE_MISC) {
  199. MiscDebug = (PIMAGE_DEBUG_MISC)
  200. ((PCHAR)CurrentImage.MappedAddress +
  201. DebugDirectories->PointerToRawData
  202. );
  203. strcpy( DebugFileName, (PCHAR) MiscDebug->Data );
  204. break;
  205. }
  206. else {
  207. DebugDirectories += 1;
  208. DebugDirectoriesSize -= sizeof( *DebugDirectories );
  209. }
  210. }
  211. }
  212. }
  213. if (CurrentImage.FileHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
  214. CurrentImageSize = ((PIMAGE_NT_HEADERS32)CurrentImage.FileHeader)->OptionalHeader.SizeOfImage;
  215. *OldImageBase = ((PIMAGE_NT_HEADERS32)CurrentImage.FileHeader)->OptionalHeader.ImageBase;
  216. } else {
  217. CurrentImageSize = ((PIMAGE_NT_HEADERS64)CurrentImage.FileHeader)->OptionalHeader.SizeOfImage;
  218. *OldImageBase = ((PIMAGE_NT_HEADERS64)CurrentImage.FileHeader)->OptionalHeader.ImageBase;
  219. }
  220. // Save the current settings for the caller.
  221. *OldImageSize = CurrentImageSize;
  222. *NewImageSize = ROUND_UP( CurrentImageSize, IMAGE_SEPARATION );
  223. if (CheckImageSize) {
  224. // The user asked for a max size test.
  225. if ( *NewImageSize > ROUND_UP(CheckImageSize, IMAGE_SEPARATION) ) {
  226. *NewImageBase = 0;
  227. rc = FALSE;
  228. goto CleanupAndExit;
  229. }
  230. }
  231. DesiredImageBase = *NewImageBase;
  232. // So long as we're not basing to zero or rebasing to the same address,
  233. // go for it.
  234. if (fReBase) {
  235. BOOL fAdjust;
  236. if ((CurrentImage.FileHeader->FileHeader.Machine != IMAGE_FILE_MACHINE_I386) &&
  237. (CurrentImage.FileHeader->FileHeader.Machine != IMAGE_FILE_MACHINE_ALPHA) &&
  238. (CurrentImage.FileHeader->FileHeader.Machine != IMAGE_FILE_MACHINE_ALPHA64) &&
  239. (CurrentImage.FileHeader->FileHeader.Machine != IMAGE_FILE_MACHINE_IA64))
  240. {
  241. fAdjust = TRUE;
  242. } else {
  243. fAdjust = FALSE;
  244. }
  245. if (fGoingDown) {
  246. DesiredImageBase -= *NewImageSize;
  247. if (fAdjust) {
  248. AdjImageBaseSize( (PULONG)&DesiredImageBase, &CurrentImageSize, fGoingDown );
  249. }
  250. }
  251. if ((DesiredImageBase) &&
  252. (DesiredImageBase != *OldImageBase)
  253. ) {
  254. if (CurrentImage.FileHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
  255. OldChecksum = ((PIMAGE_NT_HEADERS32)CurrentImage.FileHeader)->OptionalHeader.CheckSum;
  256. } else {
  257. OldChecksum = ((PIMAGE_NT_HEADERS64)CurrentImage.FileHeader)->OptionalHeader.CheckSum;
  258. }
  259. if ( !RelocateImage( &CurrentImage, DesiredImageBase, &Diff, tstamp ) ) {
  260. UpdateSymbolsError = GetLastError();
  261. rc = FALSE;
  262. goto CleanupAndExit;
  263. }
  264. if ( fSymbolsAlreadySplit && Diff ) {
  265. if ( UpdateDebugInfoFileEx(CurrentImageName,
  266. SymbolPath,
  267. DebugFilePath,
  268. (PIMAGE_NT_HEADERS32)(CurrentImage.FileHeader),
  269. OldChecksum )) {
  270. UpdateSymbolsError = GetLastError();
  271. } else {
  272. UpdateSymbolsError = 0;
  273. }
  274. }
  275. } else {
  276. //
  277. // Should this be -1?? shouldn't it be 0 instead? - kentf
  278. //
  279. Diff = (ULONG) -1;
  280. }
  281. if (!fGoingDown && Diff) {
  282. DesiredImageBase += *NewImageSize;
  283. if (fAdjust) {
  284. AdjImageBaseSize( (PULONG)&DesiredImageBase, &CurrentImageSize, fGoingDown );
  285. }
  286. }
  287. }
  288. }
  289. if (fReBase) {
  290. if (Diff) {
  291. *NewImageBase = DesiredImageBase;
  292. } else {
  293. UpdateSymbolsError = ERROR_INVALID_ADDRESS;
  294. rc = FALSE;
  295. goto CleanupAndExit;
  296. }
  297. }
  298. } else {
  299. if (CurrentImage.fDOSImage == TRUE) {
  300. UpdateSymbolsError = ERROR_BAD_EXE_FORMAT;
  301. } else {
  302. UpdateSymbolsError = GetLastError();
  303. }
  304. rc = FALSE;
  305. goto Exit;
  306. }
  307. CleanupAndExit:
  308. UnmapViewOfFile( CurrentImage.MappedAddress );
  309. if ( CurrentImage.hFile != INVALID_HANDLE_VALUE ) {
  310. CloseHandle( CurrentImage.hFile );
  311. }
  312. ZeroMemory( &CurrentImage, sizeof( CurrentImage ) );
  313. Exit:
  314. SetLastError(UpdateSymbolsError);
  315. return(TRUE);
  316. }
  317. VOID
  318. AdjImageBaseSize (
  319. PULONG pulImageBase,
  320. PULONG pulImageSize,
  321. BOOL fGoingDown
  322. )
  323. {
  324. DWORD Meg1, Meg2, Delta;
  325. //
  326. // ImageBase is the base for the current image. Make sure that
  327. // the image does not span a 256Mb boundry. This is due to an r4000
  328. // chip bug that has problems computing the correct address for absolute
  329. // jumps that occur in the last few instructions of a 256mb region
  330. //
  331. Meg1 = *pulImageBase >> x256MEGSHIFT;
  332. Meg2 = ( *pulImageBase + ROUND_UP( *pulImageSize, IMAGE_SEPARATION ) ) >> x256MEGSHIFT;
  333. if ( Meg1 != Meg2 ) {
  334. //
  335. // If we are going down, then subtract the overlap from ThisBase
  336. //
  337. if ( fGoingDown ) {
  338. Delta = ( *pulImageBase + ROUND_UP( *pulImageSize, IMAGE_SEPARATION ) ) -
  339. ( Meg2 << x256MEGSHIFT );
  340. Delta += IMAGE_SEPARATION;
  341. *pulImageBase = *pulImageBase - Delta;
  342. *pulImageSize += Delta;
  343. }
  344. else {
  345. Delta = ( Meg2 << x256MEGSHIFT ) - *pulImageBase;
  346. *pulImageBase += Delta;
  347. *pulImageSize += Delta;
  348. }
  349. }
  350. }
  351. BOOL
  352. RelocateImage(
  353. PLOADED_IMAGE LoadedImage,
  354. ULONG64 NewBase,
  355. ULONG64 *Diff,
  356. ULONG tstamp
  357. )
  358. {
  359. ULONG_PTR VA;
  360. ULONG64 OldBase;
  361. ULONG SizeOfBlock;
  362. PUSHORT NextOffset;
  363. PIMAGE_NT_HEADERS NtHeaders;
  364. PIMAGE_BASE_RELOCATION NextBlock;
  365. ULONG CheckSum;
  366. ULONG HeaderSum;
  367. PIMAGE_FILE_HEADER FileHeader;
  368. BOOL rc = TRUE;
  369. ULONG TotalCountBytes = 0;
  370. static BOOL fInit = FALSE;
  371. if (!fInit) {
  372. RelocRoutineNative = (LPRELOCATE_ROUTINE)GetProcAddress(GetModuleHandle("ntdll"), "LdrProcessRelocationBlock");
  373. #ifdef _WIN64
  374. RelocRoutine64 = RelocRoutineNative;
  375. #else
  376. RelocRoutine64 = xxLdrProcessRelocationBlock64;
  377. #endif
  378. }
  379. __try {
  380. if (LoadedImage->FileHeader->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) {
  381. // Relocations stripped. Nothing to do.
  382. __leave;
  383. }
  384. NtHeaders = LoadedImage->FileHeader;
  385. FileHeader = &NtHeaders->FileHeader;
  386. if (NtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
  387. OldBase = ((PIMAGE_NT_HEADERS32)NtHeaders)->OptionalHeader.ImageBase;
  388. } else {
  389. OldBase = ((PIMAGE_NT_HEADERS64)NtHeaders)->OptionalHeader.ImageBase;
  390. }
  391. //
  392. // Locate the relocation section.
  393. //
  394. NextBlock = (PIMAGE_BASE_RELOCATION)ImageDirectoryEntryToData(
  395. LoadedImage->MappedAddress,
  396. FALSE,
  397. IMAGE_DIRECTORY_ENTRY_BASERELOC,
  398. &TotalCountBytes
  399. );
  400. *Diff = NewBase - OldBase;
  401. //
  402. // If the image has a relocation table, then apply the specified fixup
  403. // information to the image.
  404. //
  405. while (TotalCountBytes) {
  406. SizeOfBlock = NextBlock->SizeOfBlock;
  407. TotalCountBytes -= SizeOfBlock;
  408. SizeOfBlock -= sizeof(IMAGE_BASE_RELOCATION);
  409. SizeOfBlock /= sizeof(USHORT);
  410. NextOffset = (PUSHORT)(NextBlock + 1);
  411. //
  412. // Compute the address and value for the fixup.
  413. //
  414. if ( SizeOfBlock ) {
  415. VA = (ULONG_PTR)RvaToVa(NextBlock->VirtualAddress,LoadedImage);
  416. if ( !VA ) {
  417. NtHeaders->Signature = (ULONG)-1;
  418. rc = FALSE;
  419. __leave;
  420. }
  421. if (NtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
  422. if ( !(NextBlock = (RelocRoutine64)(VA,SizeOfBlock,NextOffset,*Diff)) ) {
  423. NtHeaders->Signature = (ULONG)-1;
  424. rc = FALSE;
  425. __leave;
  426. }
  427. } else {
  428. if ( !(NextBlock = (RelocRoutineNative)(VA,SizeOfBlock,NextOffset,(LONG_PTR)*Diff)) ) {
  429. NtHeaders->Signature = (ULONG)-1;
  430. rc = FALSE;
  431. __leave;
  432. }
  433. }
  434. }
  435. else {
  436. NextBlock++;
  437. }
  438. }
  439. if (tstamp) {
  440. FileHeader->TimeDateStamp = tstamp;
  441. } else {
  442. FileHeader->TimeDateStamp++;
  443. }
  444. if (NtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
  445. ((PIMAGE_NT_HEADERS32)NtHeaders)->OptionalHeader.ImageBase = (ULONG)NewBase;
  446. if ( LoadedImage->hFile != INVALID_HANDLE_VALUE ) {
  447. ((PIMAGE_NT_HEADERS32)NtHeaders)->OptionalHeader.CheckSum = 0;
  448. CheckSumMappedFile(
  449. (PVOID)LoadedImage->MappedAddress,
  450. GetFileSize(LoadedImage->hFile, NULL),
  451. &HeaderSum,
  452. &CheckSum
  453. );
  454. ((PIMAGE_NT_HEADERS32)NtHeaders)->OptionalHeader.CheckSum = CheckSum;
  455. }
  456. } else {
  457. ((PIMAGE_NT_HEADERS64)NtHeaders)->OptionalHeader.ImageBase = NewBase;
  458. if ( LoadedImage->hFile != INVALID_HANDLE_VALUE ) {
  459. ((PIMAGE_NT_HEADERS64)NtHeaders)->OptionalHeader.CheckSum = 0;
  460. CheckSumMappedFile(
  461. (PVOID)LoadedImage->MappedAddress,
  462. GetFileSize(LoadedImage->hFile, NULL),
  463. &HeaderSum,
  464. &CheckSum
  465. );
  466. ((PIMAGE_NT_HEADERS64)NtHeaders)->OptionalHeader.CheckSum = CheckSum;
  467. }
  468. }
  469. FlushViewOfFile(LoadedImage->MappedAddress,0);
  470. TouchFileTimes(LoadedImage->hFile,NULL);
  471. } __except (EXCEPTION_EXECUTE_HANDLER) {
  472. rc = FALSE;
  473. }
  474. return rc;
  475. }
  476. PVOID
  477. RvaToVa(
  478. ULONG Rva,
  479. PLOADED_IMAGE Image
  480. )
  481. {
  482. PIMAGE_SECTION_HEADER Section;
  483. ULONG i;
  484. PVOID Va;
  485. Va = NULL;
  486. Section = Image->LastRvaSection;
  487. if (Rva == 0) {
  488. // a NULL Rva will be sent if there are relocs before the first page
  489. // (ie: we're relocating a system image)
  490. Va = Image->MappedAddress;
  491. } else {
  492. if ( Rva >= Section->VirtualAddress &&
  493. Rva < (Section->VirtualAddress + Section->SizeOfRawData) ) {
  494. Va = (PVOID)(Rva - Section->VirtualAddress + Section->PointerToRawData + Image->MappedAddress);
  495. } else {
  496. for(Section = Image->Sections,i=0; i<Image->NumberOfSections; i++,Section++) {
  497. if ( Rva >= Section->VirtualAddress &&
  498. Rva < (Section->VirtualAddress + Section->SizeOfRawData) ) {
  499. Va = (PVOID)(Rva - Section->VirtualAddress + Section->PointerToRawData + Image->MappedAddress);
  500. Image->LastRvaSection = Section;
  501. break;
  502. }
  503. }
  504. }
  505. }
  506. return Va;
  507. }
  508. #ifndef IMAGE_REL_BASED_SECTION
  509. #define IMAGE_REL_BASED_SECTION 6
  510. #endif
  511. #ifndef IMAGE_REL_BASED_REL32
  512. #define IMAGE_REL_BASED_REL32 7
  513. #endif
  514. PIMAGE_BASE_RELOCATION
  515. xxLdrProcessRelocationBlock64(
  516. IN ULONG_PTR VA,
  517. IN ULONG SizeOfBlock,
  518. IN PUSHORT NextOffset,
  519. IN LONGLONG Diff
  520. )
  521. {
  522. PUCHAR FixupVA;
  523. USHORT Offset;
  524. LONG Temp;
  525. ULONG Temp32;
  526. ULONGLONG Value64;
  527. LONGLONG Temp64;
  528. while (SizeOfBlock--) {
  529. Offset = *NextOffset & (USHORT)0xfff;
  530. FixupVA = (PUCHAR)(VA + Offset);
  531. //
  532. // Apply the fixups.
  533. //
  534. switch ((*NextOffset) >> 12) {
  535. case IMAGE_REL_BASED_HIGHLOW :
  536. //
  537. // HighLow - (32-bits) relocate the high and low half
  538. // of an address.
  539. //
  540. *(LONG UNALIGNED *)FixupVA += (ULONG) Diff;
  541. break;
  542. case IMAGE_REL_BASED_HIGH :
  543. //
  544. // High - (16-bits) relocate the high half of an address.
  545. //
  546. Temp = *(PUSHORT)FixupVA << 16;
  547. Temp += (ULONG) Diff;
  548. *(PUSHORT)FixupVA = (USHORT)(Temp >> 16);
  549. break;
  550. case IMAGE_REL_BASED_HIGHADJ :
  551. //
  552. // Adjust high - (16-bits) relocate the high half of an
  553. // address and adjust for sign extension of low half.
  554. //
  555. Temp = *(PUSHORT)FixupVA << 16;
  556. ++NextOffset;
  557. --SizeOfBlock;
  558. Temp += (LONG)(*(PSHORT)NextOffset);
  559. Temp += (ULONG) Diff;
  560. Temp += 0x8000;
  561. *(PUSHORT)FixupVA = (USHORT)(Temp >> 16);
  562. break;
  563. case IMAGE_REL_BASED_LOW :
  564. //
  565. // Low - (16-bit) relocate the low half of an address.
  566. //
  567. Temp = *(PSHORT)FixupVA;
  568. Temp += (ULONG) Diff;
  569. *(PUSHORT)FixupVA = (USHORT)Temp;
  570. break;
  571. case IMAGE_REL_BASED_IA64_IMM64:
  572. //
  573. // Align it to bundle address before fixing up the
  574. // 64-bit immediate value of the movl instruction.
  575. //
  576. FixupVA = (PUCHAR)((ULONG_PTR)FixupVA & ~(15));
  577. Value64 = (ULONGLONG)0;
  578. //
  579. // Extract the lower 32 bits of IMM64 from bundle
  580. //
  581. EXT_IMM64(Value64,
  582. (PULONG)FixupVA + EMARCH_ENC_I17_IMM7B_INST_WORD_X,
  583. EMARCH_ENC_I17_IMM7B_SIZE_X,
  584. EMARCH_ENC_I17_IMM7B_INST_WORD_POS_X,
  585. EMARCH_ENC_I17_IMM7B_VAL_POS_X);
  586. EXT_IMM64(Value64,
  587. (PULONG)FixupVA + EMARCH_ENC_I17_IMM9D_INST_WORD_X,
  588. EMARCH_ENC_I17_IMM9D_SIZE_X,
  589. EMARCH_ENC_I17_IMM9D_INST_WORD_POS_X,
  590. EMARCH_ENC_I17_IMM9D_VAL_POS_X);
  591. EXT_IMM64(Value64,
  592. (PULONG)FixupVA + EMARCH_ENC_I17_IMM5C_INST_WORD_X,
  593. EMARCH_ENC_I17_IMM5C_SIZE_X,
  594. EMARCH_ENC_I17_IMM5C_INST_WORD_POS_X,
  595. EMARCH_ENC_I17_IMM5C_VAL_POS_X);
  596. EXT_IMM64(Value64,
  597. (PULONG)FixupVA + EMARCH_ENC_I17_IC_INST_WORD_X,
  598. EMARCH_ENC_I17_IC_SIZE_X,
  599. EMARCH_ENC_I17_IC_INST_WORD_POS_X,
  600. EMARCH_ENC_I17_IC_VAL_POS_X);
  601. EXT_IMM64(Value64,
  602. (PULONG)FixupVA + EMARCH_ENC_I17_IMM41a_INST_WORD_X,
  603. EMARCH_ENC_I17_IMM41a_SIZE_X,
  604. EMARCH_ENC_I17_IMM41a_INST_WORD_POS_X,
  605. EMARCH_ENC_I17_IMM41a_VAL_POS_X);
  606. //
  607. // Update 64-bit address
  608. //
  609. Value64+=Diff;
  610. Value64 = (__int64)(__int32)PtrToLong((PULONG)Value64);
  611. //
  612. // Insert IMM64 into bundle
  613. //
  614. INS_IMM64(Value64,
  615. ((PULONG)FixupVA + EMARCH_ENC_I17_IMM7B_INST_WORD_X),
  616. EMARCH_ENC_I17_IMM7B_SIZE_X,
  617. EMARCH_ENC_I17_IMM7B_INST_WORD_POS_X,
  618. EMARCH_ENC_I17_IMM7B_VAL_POS_X);
  619. INS_IMM64(Value64,
  620. ((PULONG)FixupVA + EMARCH_ENC_I17_IMM9D_INST_WORD_X),
  621. EMARCH_ENC_I17_IMM9D_SIZE_X,
  622. EMARCH_ENC_I17_IMM9D_INST_WORD_POS_X,
  623. EMARCH_ENC_I17_IMM9D_VAL_POS_X);
  624. INS_IMM64(Value64,
  625. ((PULONG)FixupVA + EMARCH_ENC_I17_IMM5C_INST_WORD_X),
  626. EMARCH_ENC_I17_IMM5C_SIZE_X,
  627. EMARCH_ENC_I17_IMM5C_INST_WORD_POS_X,
  628. EMARCH_ENC_I17_IMM5C_VAL_POS_X);
  629. INS_IMM64(Value64,
  630. ((PULONG)FixupVA + EMARCH_ENC_I17_IC_INST_WORD_X),
  631. EMARCH_ENC_I17_IC_SIZE_X,
  632. EMARCH_ENC_I17_IC_INST_WORD_POS_X,
  633. EMARCH_ENC_I17_IC_VAL_POS_X);
  634. INS_IMM64(Value64,
  635. ((PULONG)FixupVA + EMARCH_ENC_I17_IMM41a_INST_WORD_X),
  636. EMARCH_ENC_I17_IMM41a_SIZE_X,
  637. EMARCH_ENC_I17_IMM41a_INST_WORD_POS_X,
  638. EMARCH_ENC_I17_IMM41a_VAL_POS_X);
  639. INS_IMM64(Value64,
  640. ((PULONG)FixupVA + EMARCH_ENC_I17_IMM41b_INST_WORD_X),
  641. EMARCH_ENC_I17_IMM41b_SIZE_X,
  642. EMARCH_ENC_I17_IMM41b_INST_WORD_POS_X,
  643. EMARCH_ENC_I17_IMM41b_VAL_POS_X);
  644. INS_IMM64(Value64,
  645. ((PULONG)FixupVA + EMARCH_ENC_I17_IMM41c_INST_WORD_X),
  646. EMARCH_ENC_I17_IMM41c_SIZE_X,
  647. EMARCH_ENC_I17_IMM41c_INST_WORD_POS_X,
  648. EMARCH_ENC_I17_IMM41c_VAL_POS_X);
  649. INS_IMM64(Value64,
  650. ((PULONG)FixupVA + EMARCH_ENC_I17_SIGN_INST_WORD_X),
  651. EMARCH_ENC_I17_SIGN_SIZE_X,
  652. EMARCH_ENC_I17_SIGN_INST_WORD_POS_X,
  653. EMARCH_ENC_I17_SIGN_VAL_POS_X);
  654. break;
  655. case IMAGE_REL_BASED_DIR64:
  656. *(ULONGLONG UNALIGNED *)FixupVA += Diff;
  657. break;
  658. case IMAGE_REL_BASED_MIPS_JMPADDR :
  659. //
  660. // JumpAddress - (32-bits) relocate a MIPS jump address.
  661. //
  662. Temp = (*(PULONG)FixupVA & 0x3ffffff) << 2;
  663. Temp += (ULONG) Diff;
  664. *(PULONG)FixupVA = (*(PULONG)FixupVA & ~0x3ffffff) |
  665. ((Temp >> 2) & 0x3ffffff);
  666. break;
  667. case IMAGE_REL_BASED_ABSOLUTE :
  668. //
  669. // Absolute - no fixup required.
  670. //
  671. break;
  672. case IMAGE_REL_BASED_SECTION :
  673. //
  674. // Section Relative reloc. Ignore for now.
  675. //
  676. break;
  677. case IMAGE_REL_BASED_REL32 :
  678. //
  679. // Relative intrasection. Ignore for now.
  680. //
  681. break;
  682. default :
  683. //
  684. // Illegal - illegal relocation type.
  685. //
  686. return (PIMAGE_BASE_RELOCATION)NULL;
  687. }
  688. ++NextOffset;
  689. }
  690. return (PIMAGE_BASE_RELOCATION)NextOffset;
  691. }
  692. // Dummy stub so the rebase.exe that shipped with VC5/VC6 will load.
  693. VOID
  694. RemoveRelocations(
  695. PCHAR ImageName
  696. )
  697. {
  698. return;
  699. }