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 #define RVA(m, b) ((PVOID)((ULONG_PTR)(b) + (ULONG_PTR)(m)))
21 /* FUNCTIONS *****************************************************************/
25 LdrVerifyMappedImageMatchesChecksum(
30 PIMAGE_NT_HEADERS Header
;
37 /* Get NT header to check if it's an image at all */
38 Header
= RtlImageNtHeader (BaseAddress
);
39 if (!Header
) return FALSE
;
41 /* Get checksum to match */
42 HeaderSum
= Header
->OptionalHeader
.CheckSum
;
44 /* Zero checksum seems to be accepted */
45 if (HeaderSum
== 0) return TRUE
;
47 /* Calculate the checksum */
49 Ptr
= (PUSHORT
) BaseAddress
;
50 for (i
= 0; i
< ImageSize
/ sizeof (USHORT
); i
++)
55 Sum
= LOWORD(Sum
) + HIWORD(Sum
);
62 Sum
+= (ULONG
)*((PUCHAR
)Ptr
);
65 Sum
= LOWORD(Sum
) + HIWORD(Sum
);
69 CalcSum
= (USHORT
)(LOWORD(Sum
) + HIWORD(Sum
));
71 /* Subtract image checksum from calculated checksum. */
72 /* fix low word of checksum */
73 if (LOWORD(CalcSum
) >= LOWORD(HeaderSum
))
75 CalcSum
-= LOWORD(HeaderSum
);
79 CalcSum
= ((LOWORD(CalcSum
) - LOWORD(HeaderSum
)) & 0xFFFF) - 1;
82 /* Fix high word of checksum */
83 if (LOWORD(CalcSum
) >= HIWORD(HeaderSum
))
85 CalcSum
-= HIWORD(HeaderSum
);
89 CalcSum
= ((LOWORD(CalcSum
) - HIWORD(HeaderSum
)) & 0xFFFF) - 1;
95 if (CalcSum
!= HeaderSum
)
96 DPRINT1("Image %p checksum mismatches! 0x%x != 0x%x\n", BaseAddress
, CalcSum
, HeaderSum
);
98 return (BOOLEAN
)(CalcSum
== HeaderSum
);
106 RtlImageNtHeader(IN PVOID BaseAddress
)
108 PIMAGE_NT_HEADERS NtHeader
;
109 PIMAGE_DOS_HEADER DosHeader
= (PIMAGE_DOS_HEADER
)BaseAddress
;
111 if (DosHeader
&& SWAPW(DosHeader
->e_magic
) != IMAGE_DOS_SIGNATURE
)
113 DPRINT1("DosHeader->e_magic %x\n", SWAPW(DosHeader
->e_magic
));
114 DPRINT1("NtHeader 0x%lx\n", ((ULONG_PTR
)BaseAddress
+ SWAPD(DosHeader
->e_lfanew
)));
118 NtHeader
= (PIMAGE_NT_HEADERS
)((ULONG_PTR
)BaseAddress
+ SWAPD(DosHeader
->e_lfanew
));
119 if (SWAPD(NtHeader
->Signature
) == IMAGE_NT_SIGNATURE
)
132 RtlImageDirectoryEntryToData(
134 BOOLEAN MappedAsImage
,
138 PIMAGE_NT_HEADERS NtHeader
;
141 /* Magic flag for non-mapped images. */
142 if ((ULONG_PTR
)BaseAddress
& 1)
144 BaseAddress
= (PVOID
)((ULONG_PTR
)BaseAddress
& ~1);
145 MappedAsImage
= FALSE
;
149 NtHeader
= RtlImageNtHeader (BaseAddress
);
150 if (NtHeader
== NULL
)
153 if (Directory
>= SWAPD(NtHeader
->OptionalHeader
.NumberOfRvaAndSizes
))
156 Va
= SWAPD(NtHeader
->OptionalHeader
.DataDirectory
[Directory
].VirtualAddress
);
160 *Size
= SWAPD(NtHeader
->OptionalHeader
.DataDirectory
[Directory
].Size
);
162 if (MappedAsImage
|| Va
< SWAPD(NtHeader
->OptionalHeader
.SizeOfHeaders
))
163 return (PVOID
)((ULONG_PTR
)BaseAddress
+ Va
);
165 /* image mapped as ordinary file, we must find raw pointer */
166 return RtlImageRvaToVa (NtHeader
, BaseAddress
, Va
, NULL
);
173 PIMAGE_SECTION_HEADER
175 RtlImageRvaToSection(
176 PIMAGE_NT_HEADERS NtHeader
,
180 PIMAGE_SECTION_HEADER Section
;
184 Count
= SWAPW(NtHeader
->FileHeader
.NumberOfSections
);
185 Section
= IMAGE_FIRST_SECTION(NtHeader
);
189 Va
= SWAPD(Section
->VirtualAddress
);
191 (Rva
< Va
+ SWAPD(Section
->Misc
.VirtualSize
)))
205 PIMAGE_NT_HEADERS NtHeader
,
208 PIMAGE_SECTION_HEADER
*SectionHeader
)
210 PIMAGE_SECTION_HEADER Section
= NULL
;
213 Section
= *SectionHeader
;
215 if (Section
== NULL
||
216 Rva
< SWAPD(Section
->VirtualAddress
) ||
217 Rva
>= SWAPD(Section
->VirtualAddress
) + SWAPD(Section
->Misc
.VirtualSize
))
219 Section
= RtlImageRvaToSection (NtHeader
, BaseAddress
, Rva
);
224 *SectionHeader
= Section
;
227 return (PVOID
)((ULONG_PTR
)BaseAddress
+
229 SWAPD(Section
->PointerToRawData
) -
230 (ULONG_PTR
)SWAPD(Section
->VirtualAddress
));
233 PIMAGE_BASE_RELOCATION
235 LdrProcessRelocationBlockLongLong(
236 IN ULONG_PTR Address
,
238 IN PUSHORT TypeOffset
,
246 PULONGLONG LongLongPtr
;
248 for (i
= 0; i
< Count
; i
++)
250 Offset
= SWAPW(*TypeOffset
) & 0xFFF;
251 Type
= SWAPW(*TypeOffset
) >> 12;
252 ShortPtr
= (PUSHORT
)(RVA(Address
, Offset
));
255 * Don't relocate within the relocation section itself.
256 * GCC/LD generates sometimes relocation records for the relocation section.
257 * This is a bug in GCC/LD.
258 * Fix for it disabled, since it was only in ntoskrnl and not in ntdll
261 if ((ULONG_PTR)ShortPtr < (ULONG_PTR)RelocationDir ||
262 (ULONG_PTR)ShortPtr >= (ULONG_PTR)RelocationEnd)
266 /* case IMAGE_REL_BASED_SECTION : */
267 /* case IMAGE_REL_BASED_REL32 : */
268 case IMAGE_REL_BASED_ABSOLUTE
:
271 case IMAGE_REL_BASED_HIGH
:
272 *ShortPtr
= HIWORD(MAKELONG(0, *ShortPtr
) + (LONG
)Delta
);
275 case IMAGE_REL_BASED_LOW
:
276 *ShortPtr
= SWAPW(*ShortPtr
) + LOWORD(Delta
);
279 case IMAGE_REL_BASED_HIGHLOW
:
280 LongPtr
= (PULONG
)RVA(Address
, Offset
);
281 *LongPtr
= SWAPD(*LongPtr
) + (ULONG
)Delta
;
284 case IMAGE_REL_BASED_DIR64
:
285 LongLongPtr
= (PUINT64
)RVA(Address
, Offset
);
286 *LongLongPtr
= SWAPQ(*LongLongPtr
) + Delta
;
289 case IMAGE_REL_BASED_HIGHADJ
:
290 case IMAGE_REL_BASED_MIPS_JMPADDR
:
292 DPRINT1("Unknown/unsupported fixup type %hu.\n", Type
);
293 DPRINT1("Address %x, Current %d, Count %d, *TypeOffset %x\n", Address
, i
, Count
, SWAPW(*TypeOffset
));
294 return (PIMAGE_BASE_RELOCATION
)NULL
;
300 return (PIMAGE_BASE_RELOCATION
)TypeOffset
;
305 LdrRelocateImageWithBias(
306 IN PVOID BaseAddress
,
307 IN LONGLONG AdditionalBias
,
313 PIMAGE_NT_HEADERS NtHeaders
;
314 PIMAGE_DATA_DIRECTORY RelocationDDir
;
315 PIMAGE_BASE_RELOCATION RelocationDir
, RelocationEnd
;
321 NtHeaders
= RtlImageNtHeader(BaseAddress
);
323 if (NtHeaders
== NULL
)
326 if (SWAPW(NtHeaders
->FileHeader
.Characteristics
) & IMAGE_FILE_RELOCS_STRIPPED
)
331 RelocationDDir
= &NtHeaders
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
];
333 if (SWAPD(RelocationDDir
->VirtualAddress
) == 0 || SWAPD(RelocationDDir
->Size
) == 0)
338 Delta
= (ULONG_PTR
)BaseAddress
- SWAPD(NtHeaders
->OptionalHeader
.ImageBase
) + AdditionalBias
;
339 RelocationDir
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)BaseAddress
+ SWAPD(RelocationDDir
->VirtualAddress
));
340 RelocationEnd
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)RelocationDir
+ SWAPD(RelocationDDir
->Size
));
342 while (RelocationDir
< RelocationEnd
&&
343 SWAPW(RelocationDir
->SizeOfBlock
) > 0)
345 Count
= (SWAPW(RelocationDir
->SizeOfBlock
) - sizeof(IMAGE_BASE_RELOCATION
)) / sizeof(USHORT
);
346 Address
= (ULONG_PTR
)RVA(BaseAddress
, SWAPD(RelocationDir
->VirtualAddress
));
347 TypeOffset
= (PUSHORT
)(RelocationDir
+ 1);
349 RelocationDir
= LdrProcessRelocationBlockLongLong(Address
,
354 if (RelocationDir
== NULL
)
356 DPRINT1("Error during call to LdrProcessRelocationBlockLongLong()!\n");