1 /* COPYRIGHT: See COPYING in the top level directory
2 * PROJECT: ReactOS system libraries
3 * FILE: lib/rtl/image.c
4 * PURPOSE: Image handling functions
5 * Relocate functions were previously located in
6 * ntoskrnl/ldr/loader.c and
7 * dll/ntdll/ldr/utils.c files
8 * PROGRAMMER: Eric Kohl + original authors from loader.c and utils.c file
12 /* INCLUDES *****************************************************************/
19 /* FUNCTIONS *****************************************************************/
23 LdrVerifyMappedImageMatchesChecksum(IN PVOID BaseAddress
,
24 IN ULONG NumberOfBytes
,
34 PIMAGE_NT_HEADERS NTAPI
35 RtlImageNtHeader (IN PVOID BaseAddress
)
37 PIMAGE_NT_HEADERS NtHeader
;
38 PIMAGE_DOS_HEADER DosHeader
= (PIMAGE_DOS_HEADER
)BaseAddress
;
40 if (DosHeader
&& SWAPW(DosHeader
->e_magic
) != IMAGE_DOS_SIGNATURE
)
42 DPRINT1("DosHeader->e_magic %x\n", SWAPW(DosHeader
->e_magic
));
43 DPRINT1("NtHeader 0x%lx\n", ((ULONG_PTR
)BaseAddress
+ SWAPD(DosHeader
->e_lfanew
)));
46 if (DosHeader
&& SWAPW(DosHeader
->e_magic
) == IMAGE_DOS_SIGNATURE
)
48 NtHeader
= (PIMAGE_NT_HEADERS
)((ULONG_PTR
)BaseAddress
+ SWAPD(DosHeader
->e_lfanew
));
49 if (SWAPD(NtHeader
->Signature
) == IMAGE_NT_SIGNATURE
)
62 RtlImageDirectoryEntryToData(PVOID BaseAddress
,
63 BOOLEAN MappedAsImage
,
67 PIMAGE_NT_HEADERS NtHeader
;
70 /* Magic flag for non-mapped images. */
71 if ((ULONG_PTR
)BaseAddress
& 1)
73 BaseAddress
= (PVOID
)((ULONG_PTR
)BaseAddress
& ~1);
74 MappedAsImage
= FALSE
;
78 NtHeader
= RtlImageNtHeader (BaseAddress
);
82 if (Directory
>= SWAPD(NtHeader
->OptionalHeader
.NumberOfRvaAndSizes
))
85 Va
= SWAPD(NtHeader
->OptionalHeader
.DataDirectory
[Directory
].VirtualAddress
);
89 *Size
= SWAPD(NtHeader
->OptionalHeader
.DataDirectory
[Directory
].Size
);
91 if (MappedAsImage
|| Va
< SWAPD(NtHeader
->OptionalHeader
.SizeOfHeaders
))
92 return (PVOID
)((ULONG_PTR
)BaseAddress
+ Va
);
94 /* image mapped as ordinary file, we must find raw pointer */
95 return RtlImageRvaToVa (NtHeader
, BaseAddress
, Va
, NULL
);
102 PIMAGE_SECTION_HEADER
104 RtlImageRvaToSection (
105 PIMAGE_NT_HEADERS NtHeader
,
110 PIMAGE_SECTION_HEADER Section
;
114 Count
= SWAPW(NtHeader
->FileHeader
.NumberOfSections
);
115 Section
= IMAGE_FIRST_SECTION(NtHeader
);
119 Va
= SWAPD(Section
->VirtualAddress
);
121 (Rva
< Va
+ SWAPD(Section
->Misc
.VirtualSize
)))
135 PIMAGE_NT_HEADERS NtHeader
,
138 PIMAGE_SECTION_HEADER
*SectionHeader
141 PIMAGE_SECTION_HEADER Section
= NULL
;
144 Section
= *SectionHeader
;
146 if (Section
== NULL
||
147 Rva
< SWAPD(Section
->VirtualAddress
) ||
148 Rva
>= SWAPD(Section
->VirtualAddress
) + SWAPD(Section
->Misc
.VirtualSize
))
150 Section
= RtlImageRvaToSection (NtHeader
, BaseAddress
, Rva
);
155 *SectionHeader
= Section
;
158 return (PVOID
)((ULONG_PTR
)BaseAddress
+
160 SWAPD(Section
->PointerToRawData
) -
161 (ULONG_PTR
)SWAPD(Section
->VirtualAddress
));
164 PIMAGE_BASE_RELOCATION
166 LdrProcessRelocationBlockLongLong(
167 IN ULONG_PTR Address
,
169 IN PUSHORT TypeOffset
,
179 for (i
= 0; i
< Count
; i
++)
181 Offset
= SWAPW(*TypeOffset
) & 0xFFF;
182 Type
= SWAPW(*TypeOffset
) >> 12;
183 ShortPtr
= (PUSHORT
)(RVA(Address
, Offset
));
186 * Don't relocate within the relocation section itself.
187 * GCC/LD generates sometimes relocation records for the relocation section.
188 * This is a bug in GCC/LD.
189 * Fix for it disabled, since it was only in ntoskrnl and not in ntdll
192 if ((ULONG_PTR)ShortPtr < (ULONG_PTR)RelocationDir ||
193 (ULONG_PTR)ShortPtr >= (ULONG_PTR)RelocationEnd)
197 /* case IMAGE_REL_BASED_SECTION : */
198 /* case IMAGE_REL_BASED_REL32 : */
199 case IMAGE_REL_BASED_ABSOLUTE
:
202 case IMAGE_REL_BASED_HIGH
:
203 *ShortPtr
= HIWORD(MAKELONG(0, *ShortPtr
) + (LONG
)Delta
);
206 case IMAGE_REL_BASED_LOW
:
207 *ShortPtr
= SWAPW(*ShortPtr
) + LOWORD(Delta
);
210 case IMAGE_REL_BASED_HIGHLOW
:
211 LongPtr
= (PULONG
)RVA(Address
, Offset
);
212 *LongPtr
= SWAPD(*LongPtr
) + (ULONG
)Delta
;
215 case IMAGE_REL_BASED_HIGHADJ
:
216 case IMAGE_REL_BASED_MIPS_JMPADDR
:
218 DPRINT1("Unknown/unsupported fixup type %hu.\n", Type
);
219 DPRINT1("Address %x, Current %d, Count %d, *TypeOffset %x\n", Address
, i
, Count
, SWAPW(*TypeOffset
));
220 return (PIMAGE_BASE_RELOCATION
)NULL
;
226 return (PIMAGE_BASE_RELOCATION
)TypeOffset
;
231 LdrRelocateImageWithBias(
232 IN PVOID BaseAddress
,
233 IN LONGLONG AdditionalBias
,
240 PIMAGE_NT_HEADERS NtHeaders
;
241 PIMAGE_DATA_DIRECTORY RelocationDDir
;
242 PIMAGE_BASE_RELOCATION RelocationDir
, RelocationEnd
;
248 NtHeaders
= RtlImageNtHeader(BaseAddress
);
250 if (NtHeaders
== NULL
)
253 if (SWAPW(NtHeaders
->FileHeader
.Characteristics
) & IMAGE_FILE_RELOCS_STRIPPED
)
258 RelocationDDir
= &NtHeaders
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
];
260 if (SWAPD(RelocationDDir
->VirtualAddress
) == 0 || SWAPD(RelocationDDir
->Size
) == 0)
265 Delta
= (ULONG_PTR
)BaseAddress
- SWAPD(NtHeaders
->OptionalHeader
.ImageBase
) + AdditionalBias
;
266 RelocationDir
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)BaseAddress
+ SWAPD(RelocationDDir
->VirtualAddress
));
267 RelocationEnd
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)RelocationDir
+ SWAPD(RelocationDDir
->Size
));
269 while (RelocationDir
< RelocationEnd
&&
270 SWAPW(RelocationDir
->SizeOfBlock
) > 0)
272 Count
= (SWAPW(RelocationDir
->SizeOfBlock
) - sizeof(IMAGE_BASE_RELOCATION
)) / sizeof(USHORT
);
273 Address
= (ULONG_PTR
)RVA(BaseAddress
, SWAPD(RelocationDir
->VirtualAddress
));
274 TypeOffset
= (PUSHORT
)(RelocationDir
+ 1);
276 RelocationDir
= LdrProcessRelocationBlockLongLong(Address
,
281 if (RelocationDir
== NULL
)
283 DPRINT1("Error during call to LdrProcessRelocationBlockLongLong()!\n");