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.

822 lines
25 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. ldrreloc.c
  5. Abstract:
  6. This module contains the code to relocate an image when
  7. the preferred base isn't available. This is called by the
  8. boot loader, device driver loader, and system loader.
  9. Author:
  10. Mike O'Leary (mikeol) 03-Feb-1992
  11. Revision History:
  12. --*/
  13. #include "ntrtlp.h"
  14. #if 0 // These are not actually used.
  15. // See also ntrtl.h, RtlUshortByteSwap, RtlUlongByteSwap, RtlUlonglongByteSwap.
  16. //
  17. // byte swapping macros (LE/BE) used for IA64 relocations
  18. // source != destination
  19. //
  20. //#define SWAP_SHORT(_dst,_src) \
  21. // ((((unsigned char *)_dst)[1] = ((unsigned char *)_src)[0]), \
  22. // (((unsigned char *)_dst)[0] = ((unsigned char *)_src)[1]))
  23. //#define SWAP_INT(_dst,_src) \
  24. // ((((unsigned char *)_dst)[3] = ((unsigned char *)_src)[0]), \
  25. // (((unsigned char *)_dst)[2] = ((unsigned char *)_src)[1]), \
  26. // (((unsigned char *)_dst)[1] = ((unsigned char *)_src)[2]), \
  27. // (((unsigned char *)_dst)[0] = ((unsigned char *)_src)[3]))
  28. //#define SWAP_LONG_LONG(_dst,_src) \
  29. // ((((unsigned char *)_dst)[7] = ((unsigned char *)_src)[0]), \
  30. // (((unsigned char *)_dst)[6] = ((unsigned char *)_src)[1]), \
  31. // (((unsigned char *)_dst)[5] = ((unsigned char *)_src)[2]), \
  32. // (((unsigned char *)_dst)[4] = ((unsigned char *)_src)[3]), \
  33. // (((unsigned char *)_dst)[3] = ((unsigned char *)_src)[4]), \
  34. // (((unsigned char *)_dst)[2] = ((unsigned char *)_src)[5]), \
  35. // (((unsigned char *)_dst)[1] = ((unsigned char *)_src)[6]), \
  36. // (((unsigned char *)_dst)[0] = ((unsigned char *)_src)[7]))
  37. #endif
  38. //
  39. // Mark a HIGHADJ entry as needing an increment if reprocessing.
  40. //
  41. #define LDRP_RELOCATION_INCREMENT 0x1
  42. //
  43. // Mark a HIGHADJ entry as not suitable for reprocessing.
  44. //
  45. #define LDRP_RELOCATION_FINAL 0x2
  46. PIMAGE_BASE_RELOCATION
  47. LdrProcessRelocationBlockLongLong(
  48. IN ULONG_PTR VA,
  49. IN ULONG SizeOfBlock,
  50. IN PUSHORT NextOffset,
  51. IN LONGLONG Diff
  52. );
  53. #if defined(NTOS_KERNEL_RUNTIME)
  54. #if defined(ALLOC_PRAGMA)
  55. #pragma alloc_text(PAGE,LdrRelocateImage)
  56. #pragma alloc_text(PAGE,LdrRelocateImageWithBias)
  57. #pragma alloc_text(PAGE,LdrProcessRelocationBlock)
  58. #pragma alloc_text(PAGE,LdrProcessRelocationBlockLongLong)
  59. #endif // ALLOC_PRAGMA
  60. #if defined(_ALPHA_)
  61. PIMAGE_BASE_RELOCATION
  62. LdrpProcessVolatileRelocationBlock(
  63. IN ULONG_PTR VA,
  64. IN ULONG SizeOfBlock,
  65. IN PUSHORT NextOffset,
  66. IN LONG_PTR Diff,
  67. IN LONG_PTR OldDiff,
  68. IN ULONG_PTR OldBase
  69. );
  70. #if defined(ALLOC_PRAGMA)
  71. #pragma alloc_text(INIT,LdrDoubleRelocateImage)
  72. #pragma alloc_text(INIT,LdrpProcessVolatileRelocationBlock)
  73. #endif // ALLOC_PRAGMA
  74. #endif // _ALPHA_
  75. #endif // NTOS_KERNEL_RUNTIME
  76. #if defined(BLDR_KERNEL_RUNTIME)
  77. typedef LDR_RELOCATE_IMAGE_RETURN_TYPE ARC_STATUS;
  78. #else
  79. typedef LDR_RELOCATE_IMAGE_RETURN_TYPE NTSTATUS;
  80. #endif
  81. LDR_RELOCATE_IMAGE_RETURN_TYPE
  82. LdrRelocateImage (
  83. IN PVOID NewBase,
  84. IN CONST CHAR* LoaderName,
  85. IN LDR_RELOCATE_IMAGE_RETURN_TYPE Success,
  86. IN LDR_RELOCATE_IMAGE_RETURN_TYPE Conflict,
  87. IN LDR_RELOCATE_IMAGE_RETURN_TYPE Invalid
  88. )
  89. /*++
  90. Routine Description:
  91. This routine relocates an image file that was not loaded into memory
  92. at the preferred address.
  93. Arguments:
  94. NewBase - Supplies a pointer to the image base.
  95. LoaderName - Indicates which loader routine is being called from.
  96. Success - Value to return if relocation successful.
  97. Conflict - Value to return if can't relocate.
  98. Invalid - Value to return if relocations are invalid.
  99. Return Value:
  100. Success if image is relocated.
  101. Conflict if image can't be relocated.
  102. Invalid if image contains invalid fixups.
  103. --*/
  104. {
  105. //
  106. // Just call LdrRelocateImageWithBias() with a zero bias.
  107. //
  108. return LdrRelocateImageWithBias( NewBase,
  109. 0,
  110. LoaderName,
  111. Success,
  112. Conflict,
  113. Invalid );
  114. }
  115. LDR_RELOCATE_IMAGE_RETURN_TYPE
  116. LdrRelocateImageWithBias (
  117. IN PVOID NewBase,
  118. IN LONGLONG AdditionalBias,
  119. IN CONST CHAR* LoaderName,
  120. IN LDR_RELOCATE_IMAGE_RETURN_TYPE Success,
  121. IN LDR_RELOCATE_IMAGE_RETURN_TYPE Conflict,
  122. IN LDR_RELOCATE_IMAGE_RETURN_TYPE Invalid
  123. )
  124. /*++
  125. Routine Description:
  126. This routine relocates an image file that was not loaded into memory
  127. at the preferred address.
  128. Arguments:
  129. NewBase - Supplies a pointer to the image base.
  130. AdditionalBias - An additional quantity to add to all fixups. The
  131. 32-bit X86 loader uses this when loading 64-bit images
  132. to specify a NewBase that is actually a 64-bit value.
  133. LoaderName - Indicates which loader routine is being called from.
  134. Success - Value to return if relocation successful.
  135. Conflict - Value to return if can't relocate.
  136. Invalid - Value to return if relocations are invalid.
  137. Return Value:
  138. Success if image is relocated.
  139. Conflict if image can't be relocated.
  140. Invalid if image contains invalid fixups.
  141. --*/
  142. {
  143. LONGLONG Diff;
  144. ULONG TotalCountBytes = 0;
  145. ULONG_PTR VA;
  146. ULONGLONG OldBase;
  147. ULONG SizeOfBlock;
  148. PUCHAR FixupVA;
  149. USHORT Offset;
  150. PUSHORT NextOffset = NULL;
  151. PIMAGE_NT_HEADERS NtHeaders;
  152. PIMAGE_BASE_RELOCATION NextBlock;
  153. LDR_RELOCATE_IMAGE_RETURN_TYPE Status;
  154. RTL_PAGED_CODE();
  155. NtHeaders = RtlImageNtHeader( NewBase );
  156. if (NtHeaders == NULL) {
  157. Status = Invalid;
  158. goto Exit;
  159. }
  160. switch (NtHeaders->OptionalHeader.Magic) {
  161. case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
  162. OldBase =
  163. ((PIMAGE_NT_HEADERS32)NtHeaders)->OptionalHeader.ImageBase;
  164. break;
  165. case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
  166. OldBase =
  167. ((PIMAGE_NT_HEADERS64)NtHeaders)->OptionalHeader.ImageBase;
  168. break;
  169. default:
  170. Status = Invalid;
  171. goto Exit;
  172. }
  173. //
  174. // Locate the relocation section.
  175. //
  176. NextBlock = (PIMAGE_BASE_RELOCATION)RtlImageDirectoryEntryToData(
  177. NewBase, TRUE, IMAGE_DIRECTORY_ENTRY_BASERELOC, &TotalCountBytes);
  178. //
  179. // It is possible for a file to have no relocations, but the relocations
  180. // must not have been stripped.
  181. //
  182. if (!NextBlock || !TotalCountBytes) {
  183. if (NtHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) {
  184. #if DBG
  185. DbgPrint("%s: Image can't be relocated, no fixup information.\n", LoaderName);
  186. #endif // DBG
  187. Status = Conflict;
  188. } else {
  189. Status = Success;
  190. }
  191. goto Exit;
  192. }
  193. //
  194. // If the image has a relocation table, then apply the specified fixup
  195. // information to the image.
  196. //
  197. Diff = (ULONG_PTR)NewBase - OldBase + AdditionalBias;
  198. while (TotalCountBytes) {
  199. SizeOfBlock = NextBlock->SizeOfBlock;
  200. TotalCountBytes -= SizeOfBlock;
  201. SizeOfBlock -= sizeof(IMAGE_BASE_RELOCATION);
  202. SizeOfBlock /= sizeof(USHORT);
  203. NextOffset = (PUSHORT)((PCHAR)NextBlock + sizeof(IMAGE_BASE_RELOCATION));
  204. VA = (ULONG_PTR)NewBase + NextBlock->VirtualAddress;
  205. if ( !(NextBlock = LdrProcessRelocationBlockLongLong( VA,
  206. SizeOfBlock,
  207. NextOffset,
  208. Diff)) ) {
  209. #if DBG
  210. DbgPrint("%s: Unknown base relocation type\n", LoaderName);
  211. #endif
  212. Status = Invalid;
  213. goto Exit;
  214. }
  215. }
  216. Status = Success;
  217. Exit:
  218. if (Status != Success) {
  219. DbgPrint(
  220. "%s: %s() failed 0x%lx\n"
  221. "%s: OldBase : %p\n"
  222. "%s: NewBase : %p\n"
  223. "%s: Diff : 0x%I64x\n"
  224. "%s: NextOffset : %p\n"
  225. "%s: *NextOffset : 0x%x\n"
  226. "%s: SizeOfBlock : 0x%lx\n",
  227. LoaderName, __FUNCTION__, Status,
  228. LoaderName, OldBase,
  229. LoaderName, NewBase,
  230. LoaderName, Diff,
  231. LoaderName, NextOffset,
  232. LoaderName, (NextOffset != NULL) ? *NextOffset : 0,
  233. LoaderName, SizeOfBlock
  234. );
  235. #if DBG
  236. DbgBreakPoint();
  237. #endif
  238. }
  239. return Status;
  240. }
  241. PIMAGE_BASE_RELOCATION
  242. LdrProcessRelocationBlock(
  243. IN ULONG_PTR VA,
  244. IN ULONG SizeOfBlock,
  245. IN PUSHORT NextOffset,
  246. IN LONG_PTR Diff
  247. )
  248. {
  249. PIMAGE_BASE_RELOCATION baseRelocation;
  250. baseRelocation = LdrProcessRelocationBlockLongLong( VA,
  251. SizeOfBlock,
  252. NextOffset,
  253. (LONGLONG)Diff );
  254. return baseRelocation;
  255. }
  256. // begin_rebase
  257. PIMAGE_BASE_RELOCATION
  258. LdrProcessRelocationBlockLongLong(
  259. IN ULONG_PTR VA,
  260. IN ULONG SizeOfBlock,
  261. IN PUSHORT NextOffset,
  262. IN LONGLONG Diff
  263. )
  264. {
  265. PUCHAR FixupVA;
  266. USHORT Offset;
  267. LONG Temp;
  268. #if defined(BLDR_KERNEL_RUNTIME)
  269. LONG TempOrig;
  270. LONG_PTR ActualDiff;
  271. #endif
  272. ULONG Temp32;
  273. ULONGLONG Value64;
  274. LONGLONG Temp64;
  275. RTL_PAGED_CODE();
  276. while (SizeOfBlock--) {
  277. Offset = *NextOffset & (USHORT)0xfff;
  278. FixupVA = (PUCHAR)(VA + Offset);
  279. //
  280. // Apply the fixups.
  281. //
  282. switch ((*NextOffset) >> 12) {
  283. case IMAGE_REL_BASED_HIGHLOW :
  284. //
  285. // HighLow - (32-bits) relocate the high and low half
  286. // of an address.
  287. //
  288. *(LONG UNALIGNED *)FixupVA += (ULONG) Diff;
  289. break;
  290. case IMAGE_REL_BASED_HIGH :
  291. //
  292. // High - (16-bits) relocate the high half of an address.
  293. //
  294. Temp = *(PUSHORT)FixupVA << 16;
  295. Temp += (ULONG) Diff;
  296. *(PUSHORT)FixupVA = (USHORT)(Temp >> 16);
  297. break;
  298. case IMAGE_REL_BASED_HIGHADJ :
  299. //
  300. // Adjust high - (16-bits) relocate the high half of an
  301. // address and adjust for sign extension of low half.
  302. //
  303. #if defined(NTOS_KERNEL_RUNTIME)
  304. //
  305. // If the address has already been relocated then don't
  306. // process it again now or information will be lost.
  307. //
  308. if (Offset & LDRP_RELOCATION_FINAL) {
  309. ++NextOffset;
  310. --SizeOfBlock;
  311. break;
  312. }
  313. #endif
  314. Temp = *(PUSHORT)FixupVA << 16;
  315. #if defined(BLDR_KERNEL_RUNTIME)
  316. TempOrig = Temp;
  317. #endif
  318. ++NextOffset;
  319. --SizeOfBlock;
  320. Temp += (LONG)(*(PSHORT)NextOffset);
  321. Temp += (ULONG) Diff;
  322. Temp += 0x8000;
  323. *(PUSHORT)FixupVA = (USHORT)(Temp >> 16);
  324. #if defined(BLDR_KERNEL_RUNTIME)
  325. ActualDiff = ((((ULONG_PTR)(Temp - TempOrig)) >> 16) -
  326. (((ULONG_PTR)Diff) >> 16 ));
  327. if (ActualDiff == 1) {
  328. //
  329. // Mark the relocation as needing an increment if it is
  330. // relocated again.
  331. //
  332. *(NextOffset - 1) |= LDRP_RELOCATION_INCREMENT;
  333. }
  334. else if (ActualDiff != 0) {
  335. //
  336. // Mark the relocation as cannot be reprocessed.
  337. //
  338. *(NextOffset - 1) |= LDRP_RELOCATION_FINAL;
  339. }
  340. #endif
  341. break;
  342. case IMAGE_REL_BASED_LOW :
  343. //
  344. // Low - (16-bit) relocate the low half of an address.
  345. //
  346. Temp = *(PSHORT)FixupVA;
  347. Temp += (ULONG) Diff;
  348. *(PUSHORT)FixupVA = (USHORT)Temp;
  349. break;
  350. case IMAGE_REL_BASED_IA64_IMM64:
  351. //
  352. // Align it to bundle address before fixing up the
  353. // 64-bit immediate value of the movl instruction.
  354. //
  355. FixupVA = (PUCHAR)((ULONG_PTR)FixupVA & ~(15));
  356. Value64 = (ULONGLONG)0;
  357. //
  358. // Extract the lower 32 bits of IMM64 from bundle
  359. //
  360. EXT_IMM64(Value64,
  361. (PULONG)FixupVA + EMARCH_ENC_I17_IMM7B_INST_WORD_X,
  362. EMARCH_ENC_I17_IMM7B_SIZE_X,
  363. EMARCH_ENC_I17_IMM7B_INST_WORD_POS_X,
  364. EMARCH_ENC_I17_IMM7B_VAL_POS_X);
  365. EXT_IMM64(Value64,
  366. (PULONG)FixupVA + EMARCH_ENC_I17_IMM9D_INST_WORD_X,
  367. EMARCH_ENC_I17_IMM9D_SIZE_X,
  368. EMARCH_ENC_I17_IMM9D_INST_WORD_POS_X,
  369. EMARCH_ENC_I17_IMM9D_VAL_POS_X);
  370. EXT_IMM64(Value64,
  371. (PULONG)FixupVA + EMARCH_ENC_I17_IMM5C_INST_WORD_X,
  372. EMARCH_ENC_I17_IMM5C_SIZE_X,
  373. EMARCH_ENC_I17_IMM5C_INST_WORD_POS_X,
  374. EMARCH_ENC_I17_IMM5C_VAL_POS_X);
  375. EXT_IMM64(Value64,
  376. (PULONG)FixupVA + EMARCH_ENC_I17_IC_INST_WORD_X,
  377. EMARCH_ENC_I17_IC_SIZE_X,
  378. EMARCH_ENC_I17_IC_INST_WORD_POS_X,
  379. EMARCH_ENC_I17_IC_VAL_POS_X);
  380. EXT_IMM64(Value64,
  381. (PULONG)FixupVA + EMARCH_ENC_I17_IMM41a_INST_WORD_X,
  382. EMARCH_ENC_I17_IMM41a_SIZE_X,
  383. EMARCH_ENC_I17_IMM41a_INST_WORD_POS_X,
  384. EMARCH_ENC_I17_IMM41a_VAL_POS_X);
  385. EXT_IMM64(Value64,
  386. ((PULONG)FixupVA + EMARCH_ENC_I17_IMM41b_INST_WORD_X),
  387. EMARCH_ENC_I17_IMM41b_SIZE_X,
  388. EMARCH_ENC_I17_IMM41b_INST_WORD_POS_X,
  389. EMARCH_ENC_I17_IMM41b_VAL_POS_X);
  390. EXT_IMM64(Value64,
  391. ((PULONG)FixupVA + EMARCH_ENC_I17_IMM41c_INST_WORD_X),
  392. EMARCH_ENC_I17_IMM41c_SIZE_X,
  393. EMARCH_ENC_I17_IMM41c_INST_WORD_POS_X,
  394. EMARCH_ENC_I17_IMM41c_VAL_POS_X);
  395. EXT_IMM64(Value64,
  396. ((PULONG)FixupVA + EMARCH_ENC_I17_SIGN_INST_WORD_X),
  397. EMARCH_ENC_I17_SIGN_SIZE_X,
  398. EMARCH_ENC_I17_SIGN_INST_WORD_POS_X,
  399. EMARCH_ENC_I17_SIGN_VAL_POS_X);
  400. //
  401. // Update 64-bit address
  402. //
  403. Value64+=Diff;
  404. //
  405. // Insert IMM64 into bundle
  406. //
  407. INS_IMM64(Value64,
  408. ((PULONG)FixupVA + EMARCH_ENC_I17_IMM7B_INST_WORD_X),
  409. EMARCH_ENC_I17_IMM7B_SIZE_X,
  410. EMARCH_ENC_I17_IMM7B_INST_WORD_POS_X,
  411. EMARCH_ENC_I17_IMM7B_VAL_POS_X);
  412. INS_IMM64(Value64,
  413. ((PULONG)FixupVA + EMARCH_ENC_I17_IMM9D_INST_WORD_X),
  414. EMARCH_ENC_I17_IMM9D_SIZE_X,
  415. EMARCH_ENC_I17_IMM9D_INST_WORD_POS_X,
  416. EMARCH_ENC_I17_IMM9D_VAL_POS_X);
  417. INS_IMM64(Value64,
  418. ((PULONG)FixupVA + EMARCH_ENC_I17_IMM5C_INST_WORD_X),
  419. EMARCH_ENC_I17_IMM5C_SIZE_X,
  420. EMARCH_ENC_I17_IMM5C_INST_WORD_POS_X,
  421. EMARCH_ENC_I17_IMM5C_VAL_POS_X);
  422. INS_IMM64(Value64,
  423. ((PULONG)FixupVA + EMARCH_ENC_I17_IC_INST_WORD_X),
  424. EMARCH_ENC_I17_IC_SIZE_X,
  425. EMARCH_ENC_I17_IC_INST_WORD_POS_X,
  426. EMARCH_ENC_I17_IC_VAL_POS_X);
  427. INS_IMM64(Value64,
  428. ((PULONG)FixupVA + EMARCH_ENC_I17_IMM41a_INST_WORD_X),
  429. EMARCH_ENC_I17_IMM41a_SIZE_X,
  430. EMARCH_ENC_I17_IMM41a_INST_WORD_POS_X,
  431. EMARCH_ENC_I17_IMM41a_VAL_POS_X);
  432. INS_IMM64(Value64,
  433. ((PULONG)FixupVA + EMARCH_ENC_I17_IMM41b_INST_WORD_X),
  434. EMARCH_ENC_I17_IMM41b_SIZE_X,
  435. EMARCH_ENC_I17_IMM41b_INST_WORD_POS_X,
  436. EMARCH_ENC_I17_IMM41b_VAL_POS_X);
  437. INS_IMM64(Value64,
  438. ((PULONG)FixupVA + EMARCH_ENC_I17_IMM41c_INST_WORD_X),
  439. EMARCH_ENC_I17_IMM41c_SIZE_X,
  440. EMARCH_ENC_I17_IMM41c_INST_WORD_POS_X,
  441. EMARCH_ENC_I17_IMM41c_VAL_POS_X);
  442. INS_IMM64(Value64,
  443. ((PULONG)FixupVA + EMARCH_ENC_I17_SIGN_INST_WORD_X),
  444. EMARCH_ENC_I17_SIGN_SIZE_X,
  445. EMARCH_ENC_I17_SIGN_INST_WORD_POS_X,
  446. EMARCH_ENC_I17_SIGN_VAL_POS_X);
  447. break;
  448. case IMAGE_REL_BASED_DIR64:
  449. *(ULONGLONG UNALIGNED *)FixupVA += Diff;
  450. break;
  451. case IMAGE_REL_BASED_MIPS_JMPADDR :
  452. //
  453. // JumpAddress - (32-bits) relocate a MIPS jump address.
  454. //
  455. Temp = (*(PULONG)FixupVA & 0x3ffffff) << 2;
  456. Temp += (ULONG) Diff;
  457. *(PULONG)FixupVA = (*(PULONG)FixupVA & ~0x3ffffff) |
  458. ((Temp >> 2) & 0x3ffffff);
  459. break;
  460. case IMAGE_REL_BASED_ABSOLUTE :
  461. //
  462. // Absolute - no fixup required.
  463. //
  464. break;
  465. case IMAGE_REL_BASED_SECTION :
  466. //
  467. // Section Relative reloc. Ignore for now.
  468. //
  469. break;
  470. case IMAGE_REL_BASED_REL32 :
  471. //
  472. // Relative intrasection. Ignore for now.
  473. //
  474. break;
  475. default :
  476. //
  477. // Illegal - illegal relocation type.
  478. //
  479. return (PIMAGE_BASE_RELOCATION)NULL;
  480. }
  481. ++NextOffset;
  482. }
  483. return (PIMAGE_BASE_RELOCATION)NextOffset;
  484. }
  485. // end_rebase
  486. #if defined(NTOS_KERNEL_RUNTIME) && defined(_ALPHA_)
  487. NTSTATUS
  488. LdrDoubleRelocateImage (
  489. IN PVOID NewBase,
  490. IN PVOID CurrentBase,
  491. IN CONST CHAR* LoaderName,
  492. IN NTSTATUS Success,
  493. IN NTSTATUS Conflict,
  494. IN NTSTATUS Invalid
  495. )
  496. /*++
  497. Routine Description:
  498. This routine handles the volatile relocations that cannot be easily repeated
  499. on an image file that has already been relocated at least once.
  500. Since this only needs to be done once (at kernel startup time), the
  501. decision was made to split this into a separate routine so as not to
  502. impact the mainline code.
  503. N.B. This function is for use by memory management ONLY.
  504. Arguments:
  505. NewBase - Supplies a pointer to the new (second relocated) image base.
  506. CurrentBase - Supplies a pointer to the first relocated image base.
  507. LoaderName - Indicates which loader routine is being called from.
  508. Success - Value to return if relocation successful.
  509. Conflict - Value to return if can't relocate.
  510. Invalid - Value to return if relocations are invalid.
  511. Return Value:
  512. Success if image is relocated.
  513. Conflict if image can't be relocated.
  514. Invalid if image contains invalid fixups.
  515. --*/
  516. {
  517. LONG_PTR Diff;
  518. LONG_PTR OldDiff;
  519. ULONG TotalCountBytes;
  520. ULONG_PTR VA;
  521. ULONG_PTR OldBase;
  522. ULONG SizeOfBlock;
  523. PUCHAR FixupVA;
  524. USHORT Offset;
  525. PUSHORT NextOffset;
  526. PIMAGE_NT_HEADERS NtHeaders;
  527. PIMAGE_BASE_RELOCATION NextBlock;
  528. RTL_PAGED_CODE();
  529. NtHeaders = RtlImageNtHeader( NewBase );
  530. OldBase = NtHeaders->OptionalHeader.ImageBase;
  531. OldDiff = (PCHAR)CurrentBase - (PCHAR)OldBase;
  532. //
  533. // Locate the relocation section.
  534. //
  535. NextBlock = (PIMAGE_BASE_RELOCATION)RtlImageDirectoryEntryToData(
  536. NewBase, TRUE, IMAGE_DIRECTORY_ENTRY_BASERELOC, &TotalCountBytes);
  537. if (!NextBlock || !TotalCountBytes) {
  538. //
  539. // The image does not contain a relocation table, and therefore
  540. // cannot be relocated.
  541. //
  542. #if DBG
  543. DbgPrint("%s: Image can't be relocated, no fixup information.\n", LoaderName);
  544. #endif // DBG
  545. return Conflict;
  546. }
  547. //
  548. // If the image has a relocation table, then apply the specified fixup
  549. // information to the image.
  550. //
  551. Diff = (PCHAR)NewBase - (PCHAR)OldBase;
  552. while (TotalCountBytes) {
  553. SizeOfBlock = NextBlock->SizeOfBlock;
  554. TotalCountBytes -= SizeOfBlock;
  555. SizeOfBlock -= sizeof(IMAGE_BASE_RELOCATION);
  556. SizeOfBlock /= sizeof(USHORT);
  557. NextOffset = (PUSHORT)((PCHAR)NextBlock + sizeof(IMAGE_BASE_RELOCATION));
  558. VA = (ULONG_PTR)NewBase + NextBlock->VirtualAddress;
  559. if ( !(NextBlock = LdrpProcessVolatileRelocationBlock(VA,SizeOfBlock,NextOffset,Diff, OldDiff, OldBase)) ) {
  560. #if DBG
  561. DbgPrint("%s: Unknown base relocation type\n", LoaderName);
  562. #endif
  563. return Invalid;
  564. }
  565. }
  566. return Success;
  567. }
  568. PIMAGE_BASE_RELOCATION
  569. LdrpProcessVolatileRelocationBlock(
  570. IN ULONG_PTR VA,
  571. IN ULONG SizeOfBlock,
  572. IN PUSHORT NextOffset,
  573. IN LONG_PTR Diff,
  574. IN LONG_PTR OldDiff,
  575. IN ULONG_PTR OldBase
  576. )
  577. /*++
  578. Routine Description:
  579. This routine handles the volatile relocations that cannot be easily repeated
  580. on an image file that has already been relocated at least once.
  581. Since this only needs to be done once (at kernel startup time), the
  582. decision was made to split this into a separate routine so as not to
  583. impact the mainline code.
  584. N.B. This function is for use by memory management ONLY.
  585. Arguments:
  586. TBD.
  587. Return Value:
  588. Next relocation entry to process.
  589. --*/
  590. {
  591. PUCHAR FixupVA;
  592. USHORT Offset;
  593. LONG Temp;
  594. ULONG Temp32;
  595. USHORT TempShort1;
  596. USHORT TempShort2;
  597. ULONGLONG Value64;
  598. LONGLONG Temp64;
  599. USHORT RelocationType;
  600. IN PVOID CurrentBase;
  601. RTL_PAGED_CODE();
  602. CurrentBase = (PVOID)((ULONG_PTR)OldDiff + OldBase);
  603. while (SizeOfBlock--) {
  604. Offset = *NextOffset & (USHORT)0xfff;
  605. FixupVA = (PUCHAR)(VA + Offset);
  606. //
  607. // Apply the fixups.
  608. //
  609. switch ((*NextOffset) >> 12) {
  610. case IMAGE_REL_BASED_HIGHADJ :
  611. //
  612. // Adjust high - (16-bits) relocate the high half of an
  613. // address and adjust for sign extension of low half.
  614. //
  615. //
  616. // Return the relocation to its original state, checking for
  617. // whether the entry was sign extended the 1st time it was
  618. // relocated.
  619. //
  620. FixupVA = (PUCHAR)((LONG_PTR)FixupVA & (LONG_PTR)~(LDRP_RELOCATION_FINAL | LDRP_RELOCATION_INCREMENT));
  621. Temp = *(PUSHORT)(FixupVA) << 16;
  622. ++NextOffset;
  623. --SizeOfBlock;
  624. // remove the carry bit from the low word
  625. Temp -= ((LONG)(*(PSHORT)NextOffset) + (USHORT)OldDiff + 0x8000) & ~0xFFFF;
  626. Temp -= (LONG)(OldDiff & ~0xffff);
  627. Temp += (LONG)(*(PSHORT)NextOffset);
  628. Temp += (ULONG) Diff;
  629. Temp += 0x8000;
  630. *(PUSHORT)FixupVA = (USHORT)(Temp >> 16);
  631. //
  632. // Mark the relocation as needing no further reprocessing.
  633. //
  634. *(NextOffset - 1) |= LDRP_RELOCATION_FINAL;
  635. break;
  636. default :
  637. break;
  638. }
  639. ++NextOffset;
  640. }
  641. return (PIMAGE_BASE_RELOCATION)NextOffset;
  642. }
  643. #endif // NTOS_KERNEL_RUNTIME && _ALPHA_