test: ldrreloc.c File Reference

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# ldrreloc.c File Reference

`#include "ntrtlp.h"`

Go to the source code of this file.

## Defines

#define | SWAP_SHORT(_dst, _src)
#define | SWAP_INT(_dst, _src)
#define | SWAP_LONG_LONG(_dst, _src)
#define | LDRP_RELOCATION_INCREMENT 0x1
#define | LDRP_RELOCATION_FINAL 0x2

## Functions

ULONG | LdrRelocateImage (IN PVOID NewBase, IN PUCHAR LoaderName, IN ULONG Success, IN ULONG Conflict, IN ULONG Invalid)
PIMAGE_BASE_RELOCATION | LdrProcessRelocationBlock (IN ULONG_PTR VA, IN ULONG SizeOfBlock, IN PUSHORT NextOffset, IN LONG_PTR Diff)

## Define Documentation

#define LDRP_RELOCATION_FINAL 0x2

| Definition at line 58 of file ldrreloc.c. Referenced by LdrProcessRelocationBlock().

#define LDRP_RELOCATION_INCREMENT 0x1

| Definition at line 53 of file ldrreloc.c. Referenced by LdrProcessRelocationBlock().

#define SWAP_INT | ( | _dst,
|  | _src |  | ) |

Value:

    ((((unsigned char *)_dst)[3] = ((unsigned char *)_src)[0]),                 \
        (((unsigned char *)_dst)[2] = ((unsigned char *)_src)[1]),                 \
        (((unsigned char *)_dst)[1] = ((unsigned char *)_src)[2]),                 \
        (((unsigned char *)_dst)[0] = ((unsigned char *)_src)[3]))

Definition at line 34 of file ldrreloc.c.

#define SWAP_LONG_LONG | ( | _dst,
|  | _src |  | ) |

Value:

    ((((unsigned char *)_dst)[7] = ((unsigned char *)_src)[0]),                 \
        (((unsigned char *)_dst)[6] = ((unsigned char *)_src)[1]),                 \
        (((unsigned char *)_dst)[5] = ((unsigned char *)_src)[2]),                 \
        (((unsigned char *)_dst)[4] = ((unsigned char *)_src)[3]),                 \
        (((unsigned char *)_dst)[3] = ((unsigned char *)_src)[4]),                 \
        (((unsigned char *)_dst)[2] = ((unsigned char *)_src)[5]),                 \
        (((unsigned char *)_dst)[1] = ((unsigned char *)_src)[6]),                 \
        (((unsigned char *)_dst)[0] = ((unsigned char *)_src)[7]))

Definition at line 40 of file ldrreloc.c.

#define SWAP_SHORT | ( | _dst,
|  | _src |  | ) |

Value:

    ((((unsigned char *)_dst)[1] = ((unsigned char *)_src)[0]),                 \
        (((unsigned char *)_dst)[0] = ((unsigned char *)_src)[1]))

Definition at line 30 of file ldrreloc.c.

## Function Documentation

PIMAGE_BASE_RELOCATION LdrProcessRelocationBlock | ( | IN ULONG_PTR | VA,
|  | IN ULONG | SizeOfBlock,
|  | IN PUSHORT | NextOffset,
|  | IN LONG_PTR | Diff
| ) |

Definition at line 194 of file ldrreloc.c.

References LDRP_RELOCATION_FINAL, LDRP_RELOCATION_INCREMENT, NULL, Offset, PSHORT, PUSHORT, RTL_PAGED_CODE, SHORT, and USHORT.

Referenced by LdrRelocateImage().

    00200 {
    00201     PUCHAR FixupVA;
    00202     USHORT Offset;
    00203     LONG Temp;
    00204     LONG TempOrig;
    00205     ULONG Temp32;
    00206     ULONGLONG Value64;
    00207     LONGLONG Temp64;
    00208     LONG_PTR ActualDiff;
    00209
    00210     RTL_PAGED_CODE();
    00211
    00212     while (SizeOfBlock--) {
    00213
    00214        Offset = *NextOffset & (USHORT)0xfff;
    00215        FixupVA = (PUCHAR)(VA + Offset);
    00216
    00217        //
    00218        // Apply the fixups.
    00219        //
    00220
    00221        switch ((*NextOffset) >> 12) {
    00222
    00223             case IMAGE_REL_BASED_HIGHLOW :
    00224                 //
    00225                 // HighLow - (32-bits) relocate the high and low half
    00226                 //      of an address.
    00227                 //
    00228                 *(LONG UNALIGNED *)FixupVA += (ULONG) Diff;
    00229                 break;
    00230
    00231             case IMAGE_REL_BASED_HIGH :
    00232                 //
    00233                 // High - (16-bits) relocate the high half of an address.
    00234                 //
    00235                 Temp = *(PUSHORT)FixupVA << 16;
    00236                 Temp += (ULONG) Diff;
    00237                 *(PUSHORT)FixupVA = (USHORT)(Temp >> 16);
    00238                 break;
    00239
    00240             case IMAGE_REL_BASED_HIGHADJ :
    00241                 //
    00242                 // Adjust high - (16-bits) relocate the high half of an
    00243                 //      address and adjust for sign extension of low half.
    00244                 //
    00245
    00246 #if defined(NTOS_KERNEL_RUNTIME)
    00247                 //
    00248                 // If the address has already been relocated then don't
    00249                 // process it again now or information will be lost.
    00250                 //
    00251                 if (Offset & LDRP_RELOCATION_FINAL) {
    00252                     ++NextOffset;
    00253                     --SizeOfBlock;
    00254                     break;
    00255                 }
    00256 #endif
    00257
    00258                 Temp = *(PUSHORT)FixupVA << 16;
    00259 #if defined(BLDR_KERNEL_RUNTIME)
    00260                 TempOrig = Temp;
    00261 #endif
    00262                 ++NextOffset;
    00263                 --SizeOfBlock;
    00264                 Temp += (LONG)(*(PSHORT)NextOffset);
    00265                 Temp += (ULONG) Diff;
    00266                 Temp += 0x8000;
    00267                 *(PUSHORT)FixupVA = (USHORT)(Temp >> 16);
    00268
    00269 #if defined(BLDR_KERNEL_RUNTIME)
    00270                 ActualDiff = ((((ULONG_PTR)(Temp - TempOrig)) >> 16) -
    00271                               (((ULONG_PTR)Diff) >> 16 ));
    00272
    00273                 if (ActualDiff == 1) {
    00274                     //
    00275                     // Mark the relocation as needing an increment if it is
    00276                     // relocated again.
    00277                     //
    00278                     *(NextOffset - 1) |= LDRP_RELOCATION_INCREMENT;
    00279                 }
    00280                 else if (ActualDiff != 0) {
    00281                     //
    00282                     // Mark the relocation as cannot be reprocessed.
    00283                     //
    00284                     *(NextOffset - 1) |= LDRP_RELOCATION_FINAL;
    00285                 }
    00286 #endif
    00287
    00288                 break;
    00289
    00290             case IMAGE_REL_BASED_LOW :
    00291                 //
    00292                 // Low - (16-bit) relocate the low half of an address.
    00293                 //
    00294                 Temp = *(PSHORT)FixupVA;
    00295                 Temp += (ULONG) Diff;
    00296                 *(PUSHORT)FixupVA = (USHORT)Temp;
    00297                 break;
    00298
    00299             case IMAGE_REL_BASED_IA64_IMM64:
    00300
    00301                 //
    00302                 // Align it to bundle address before fixing up the
    00303                 // 64-bit immediate value of the movl instruction.
    00304                 //
    00305
    00306                 FixupVA = (PUCHAR)((ULONG_PTR)FixupVA & ~(15));
    00307                 Value64 = (ULONGLONG)0;
    00308
    00309                 //
    00310                 // Extract the lower 32 bits of IMM64 from bundle
    00311                 //
    00312
    00313
    00314                 EXT_IMM64(Value64,
    00315                         (PULONG)FixupVA + EMARCH_ENC_I17_IMM7B_INST_WORD_X,
    00316                         EMARCH_ENC_I17_IMM7B_SIZE_X,
    00317                         EMARCH_ENC_I17_IMM7B_INST_WORD_POS_X,
    00318                         EMARCH_ENC_I17_IMM7B_VAL_POS_X);
    00319                 EXT_IMM64(Value64,
    00320                         (PULONG)FixupVA + EMARCH_ENC_I17_IMM9D_INST_WORD_X,
    00321                         EMARCH_ENC_I17_IMM9D_SIZE_X,
    00322                         EMARCH_ENC_I17_IMM9D_INST_WORD_POS_X,
    00323                         EMARCH_ENC_I17_IMM9D_VAL_POS_X);
    00324                 EXT_IMM64(Value64,
    00325                         (PULONG)FixupVA + EMARCH_ENC_I17_IMM5C_INST_WORD_X,
    00326                         EMARCH_ENC_I17_IMM5C_SIZE_X,
    00327                         EMARCH_ENC_I17_IMM5C_INST_WORD_POS_X,
    00328                         EMARCH_ENC_I17_IMM5C_VAL_POS_X);
    00329                 EXT_IMM64(Value64,
    00330                         (PULONG)FixupVA + EMARCH_ENC_I17_IC_INST_WORD_X,
    00331                         EMARCH_ENC_I17_IC_SIZE_X,
    00332                         EMARCH_ENC_I17_IC_INST_WORD_POS_X,
    00333                         EMARCH_ENC_I17_IC_VAL_POS_X);
    00334                 EXT_IMM64(Value64,
    00335                         (PULONG)FixupVA + EMARCH_ENC_I17_IMM41a_INST_WORD_X,
    00336                         EMARCH_ENC_I17_IMM41a_SIZE_X,
    00337                         EMARCH_ENC_I17_IMM41a_INST_WORD_POS_X,
    00338                         EMARCH_ENC_I17_IMM41a_VAL_POS_X);
    00339
    00340                 //
    00341                 // Update 64-bit address
    00342                 //
    00343
    00344                 Value64+=Diff;
    00345
    00346                 //
    00347                 // Insert IMM64 into bundle
    00348                 //
    00349
    00350                 INS_IMM64(Value64,
    00351                         ((PULONG)FixupVA + EMARCH_ENC_I17_IMM7B_INST_WORD_X),
    00352                         EMARCH_ENC_I17_IMM7B_SIZE_X,
    00353                         EMARCH_ENC_I17_IMM7B_INST_WORD_POS_X,
    00354                         EMARCH_ENC_I17_IMM7B_VAL_POS_X);
    00355                 INS_IMM64(Value64,
    00356                         ((PULONG)FixupVA + EMARCH_ENC_I17_IMM9D_INST_WORD_X),
    00357                         EMARCH_ENC_I17_IMM9D_SIZE_X,
    00358                         EMARCH_ENC_I17_IMM9D_INST_WORD_POS_X,
    00359                         EMARCH_ENC_I17_IMM9D_VAL_POS_X);
    00360                 INS_IMM64(Value64,
    00361                         ((PULONG)FixupVA + EMARCH_ENC_I17_IMM5C_INST_WORD_X),
    00362                         EMARCH_ENC_I17_IMM5C_SIZE_X,
    00363                         EMARCH_ENC_I17_IMM5C_INST_WORD_POS_X,
    00364                         EMARCH_ENC_I17_IMM5C_VAL_POS_X);
    00365                 INS_IMM64(Value64,
    00366                         ((PULONG)FixupVA + EMARCH_ENC_I17_IC_INST_WORD_X),
    00367                         EMARCH_ENC_I17_IC_SIZE_X,
    00368                         EMARCH_ENC_I17_IC_INST_WORD_POS_X,
    00369                         EMARCH_ENC_I17_IC_VAL_POS_X);
    00370                 INS_IMM64(Value64,
    00371                         ((PULONG)FixupVA + EMARCH_ENC_I17_IMM41a_INST_WORD_X),
    00372                         EMARCH_ENC_I17_IMM41a_SIZE_X,
    00373                         EMARCH_ENC_I17_IMM41a_INST_WORD_POS_X,
    00374                         EMARCH_ENC_I17_IMM41a_VAL_POS_X);
    00375                 INS_IMM64(Value64,
    00376                         ((PULONG)FixupVA + EMARCH_ENC_I17_IMM41b_INST_WORD_X),
    00377                         EMARCH_ENC_I17_IMM41b_SIZE_X,
    00378                         EMARCH_ENC_I17_IMM41b_INST_WORD_POS_X,
    00379                         EMARCH_ENC_I17_IMM41b_VAL_POS_X);
    00380                 INS_IMM64(Value64,
    00381                         ((PULONG)FixupVA + EMARCH_ENC_I17_IMM41c_INST_WORD_X),
    00382                         EMARCH_ENC_I17_IMM41c_SIZE_X,
    00383                         EMARCH_ENC_I17_IMM41c_INST_WORD_POS_X,
    00384                         EMARCH_ENC_I17_IMM41c_VAL_POS_X);
    00385                 INS_IMM64(Value64,
    00386                         ((PULONG)FixupVA + EMARCH_ENC_I17_SIGN_INST_WORD_X),
    00387                         EMARCH_ENC_I17_SIGN_SIZE_X,
    00388                         EMARCH_ENC_I17_SIGN_INST_WORD_POS_X,
    00389                         EMARCH_ENC_I17_SIGN_VAL_POS_X);
    00390                 break;
    00391
    00392             case IMAGE_REL_BASED_DIR64:
    00393
    00394                 *(ULONG_PTR UNALIGNED *)FixupVA += Diff;
    00395
    00396                 break;
    00397
    00398             case IMAGE_REL_BASED_MIPS_JMPADDR :
    00399                 //
    00400                 // JumpAddress - (32-bits) relocate a MIPS jump address.
    00401                 //
    00402                 Temp = (*(PULONG)FixupVA & 0x3ffffff) << 2;
    00403                 Temp += (ULONG) Diff;
    00404                 *(PULONG)FixupVA = (*(PULONG)FixupVA & ~0x3ffffff) |
    00405                                                 ((Temp >> 2) & 0x3ffffff);
    00406
    00407                 break;
    00408
    00409             case IMAGE_REL_BASED_ABSOLUTE :
    00410                 //
    00411                 // Absolute - no fixup required.
    00412                 //
    00413                 break;
    00414
    00415             case IMAGE_REL_BASED_SECTION :
    00416                 //
    00417                 // Section Relative reloc.  Ignore for now.
    00418                 //
    00419                 break;
    00420
    00421             case IMAGE_REL_BASED_REL32 :
    00422                 //
    00423                 // Relative intrasection. Ignore for now.
    00424                 //
    00425                 break;
    00426
    00427            case IMAGE_REL_BASED_HIGH3ADJ :
    00428                //
    00429                // Similar to HIGHADJ except this is the third word.
    00430                //  Adjust low half of high dword of an address and adjust for
    00431                //   sign extension of the low dword.
    00432                //
    00433
    00434                Temp64 = *(PUSHORT)FixupVA << 16;
    00435                ++NextOffset;
    00436                --SizeOfBlock;
    00437                Temp64 += (LONG)((SHORT)NextOffset[1]);
    00438                Temp64 <<= 16;
    00439                Temp64 += (LONG)((USHORT)NextOffset[0]);
    00440                Temp64 += Diff;
    00441                Temp64 += 0x8000;
    00442                Temp64 >>=16;
    00443                Temp64 += 0x8000;
    00444                *(PUSHORT)FixupVA = (USHORT)(Temp64 >> 16);
    00445                ++NextOffset;
    00446                --SizeOfBlock;
    00447                break;
    00448
    00449             default :
    00450                 //
    00451                 // Illegal - illegal relocation type.
    00452                 //
    00453
    00454                 return (PIMAGE_BASE_RELOCATION)NULL;
    00455        }
    00456        ++NextOffset;
    00457     }
    00458     return (PIMAGE_BASE_RELOCATION)NextOffset;
    00459 }

ULONG LdrRelocateImage | ( | IN PVOID | NewBase,
|  | IN PUCHAR | LoaderName,
|  | IN ULONG | Success,
|  | IN ULONG | Conflict,
|  | IN ULONG | Invalid
| ) |

Definition at line 91 of file ldrreloc.c.

References DbgPrint, LdrProcessRelocationBlock(), Offset, PUSHORT, RTL_PAGED_CODE, RtlImageDirectoryEntryToData(), RtlImageNtHeader(), TRUE, and USHORT.

Referenced by LdrpInitializeProcess(), LdrpMapDll(), MiLoadSystemImage(), and MiReloadBootLoadedDrivers().

    00101                    :
    00102
    00103     This routine relocates an image file that was not loaded into memory
    00104     at the preferred address.
    00105
    00106 Arguments:
    00107
    00108     NewBase - Supplies a pointer to the image base.
    00109
    00110     LoaderName - Indicates which loader routine is being called from.
    00111
    00112     Success - Value to return if relocation successful.
    00113
    00114     Conflict - Value to return if can't relocate.
    00115
    00116     Invalid - Value to return if relocations are invalid.
    00117
    00118 Return Value:
    00119
    00120     Success if image is relocated.
    00121     Conflict if image can't be relocated.
    00122     Invalid if image contains invalid fixups.
    00123
    00124 --*/
    00125
    00126 {
    00127     LONG_PTR Diff;
    00128     ULONG TotalCountBytes;
    00129     ULONG_PTR VA;
    00130     ULONG_PTR OldBase;
    00131     ULONG SizeOfBlock;
    00132     PUCHAR FixupVA;
    00133     USHORT Offset;
    00134     PUSHORT NextOffset;
    00135     PIMAGE_NT_HEADERS NtHeaders;
    00136     PIMAGE_BASE_RELOCATION NextBlock;
    00137
    00138     RTL_PAGED_CODE();
    00139
    00140     NtHeaders = RtlImageNtHeader( NewBase );
    00141     if ( NtHeaders ) {
    00142         OldBase = NtHeaders->OptionalHeader.ImageBase;
    00143         }
    00144     else {
    00145         return Invalid;
    00146         }
    00147
    00148     //
    00149     // Locate the relocation section.
    00150     //
    00151
    00152     NextBlock = (PIMAGE_BASE_RELOCATION)RtlImageDirectoryEntryToData(
    00153             NewBase, TRUE, IMAGE_DIRECTORY_ENTRY_BASERELOC, &TotalCountBytes);
    00154
    00155     if (!NextBlock || !TotalCountBytes) {
    00156
    00157         //
    00158         // The image does not contain a relocation table, and therefore
    00159         // cannot be relocated.
    00160         //
    00161 #if DBG
    00162         DbgPrint("%s: Image can't be relocated, no fixup information.\n", LoaderName);
    00163 #endif // DBG
    00164         return Conflict;
    00165     }
    00166
    00167     //
    00168     // If the image has a relocation table, then apply the specified fixup
    00169     // information to the image.
    00170     //
    00171
    00172     while (TotalCountBytes) {
    00173         SizeOfBlock = NextBlock->SizeOfBlock;
    00174         TotalCountBytes -= SizeOfBlock;
    00175         SizeOfBlock -= sizeof(IMAGE_BASE_RELOCATION);
    00176         SizeOfBlock /= sizeof(USHORT);
    00177         NextOffset = (PUSHORT)((PCHAR)NextBlock + sizeof(IMAGE_BASE_RELOCATION));
    00178
    00179         VA = (ULONG_PTR)NewBase + NextBlock->VirtualAddress;
    00180         Diff = (PCHAR)NewBase - (PCHAR)OldBase;
    00181
    00182         if ( !(NextBlock = LdrProcessRelocationBlock(VA,SizeOfBlock,NextOffset,Diff)) ) {
    00183 #if DBG
    00184             DbgPrint("%s: Unknown base relocation type\n", LoaderName);
    00185 #endif
    00186             return Invalid;
    00187         }
    00188     }
    00189
    00190     return Success;
    00191 }