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(
27 IN ULONG NumberOfBytes
,
39 RtlImageNtHeader(IN PVOID BaseAddress
)
41 PIMAGE_NT_HEADERS NtHeader
;
42 PIMAGE_DOS_HEADER DosHeader
= (PIMAGE_DOS_HEADER
)BaseAddress
;
44 if (DosHeader
&& SWAPW(DosHeader
->e_magic
) != IMAGE_DOS_SIGNATURE
)
46 DPRINT1("DosHeader->e_magic %x\n", SWAPW(DosHeader
->e_magic
));
47 DPRINT1("NtHeader 0x%lx\n", ((ULONG_PTR
)BaseAddress
+ SWAPD(DosHeader
->e_lfanew
)));
51 NtHeader
= (PIMAGE_NT_HEADERS
)((ULONG_PTR
)BaseAddress
+ SWAPD(DosHeader
->e_lfanew
));
52 if (SWAPD(NtHeader
->Signature
) == IMAGE_NT_SIGNATURE
)
65 RtlImageDirectoryEntryToData(
67 BOOLEAN MappedAsImage
,
71 PIMAGE_NT_HEADERS NtHeader
;
74 /* Magic flag for non-mapped images. */
75 if ((ULONG_PTR
)BaseAddress
& 1)
77 BaseAddress
= (PVOID
)((ULONG_PTR
)BaseAddress
& ~1);
78 MappedAsImage
= FALSE
;
82 NtHeader
= RtlImageNtHeader (BaseAddress
);
86 if (Directory
>= SWAPD(NtHeader
->OptionalHeader
.NumberOfRvaAndSizes
))
89 Va
= SWAPD(NtHeader
->OptionalHeader
.DataDirectory
[Directory
].VirtualAddress
);
93 *Size
= SWAPD(NtHeader
->OptionalHeader
.DataDirectory
[Directory
].Size
);
95 if (MappedAsImage
|| Va
< SWAPD(NtHeader
->OptionalHeader
.SizeOfHeaders
))
96 return (PVOID
)((ULONG_PTR
)BaseAddress
+ Va
);
98 /* image mapped as ordinary file, we must find raw pointer */
99 return RtlImageRvaToVa (NtHeader
, BaseAddress
, Va
, NULL
);
106 PIMAGE_SECTION_HEADER
108 RtlImageRvaToSection(
109 PIMAGE_NT_HEADERS NtHeader
,
113 PIMAGE_SECTION_HEADER Section
;
117 Count
= SWAPW(NtHeader
->FileHeader
.NumberOfSections
);
118 Section
= IMAGE_FIRST_SECTION(NtHeader
);
122 Va
= SWAPD(Section
->VirtualAddress
);
124 (Rva
< Va
+ SWAPD(Section
->Misc
.VirtualSize
)))
138 PIMAGE_NT_HEADERS NtHeader
,
141 PIMAGE_SECTION_HEADER
*SectionHeader
)
143 PIMAGE_SECTION_HEADER Section
= NULL
;
146 Section
= *SectionHeader
;
148 if (Section
== NULL
||
149 Rva
< SWAPD(Section
->VirtualAddress
) ||
150 Rva
>= SWAPD(Section
->VirtualAddress
) + SWAPD(Section
->Misc
.VirtualSize
))
152 Section
= RtlImageRvaToSection (NtHeader
, BaseAddress
, Rva
);
157 *SectionHeader
= Section
;
160 return (PVOID
)((ULONG_PTR
)BaseAddress
+
162 SWAPD(Section
->PointerToRawData
) -
163 (ULONG_PTR
)SWAPD(Section
->VirtualAddress
));
166 PIMAGE_BASE_RELOCATION
168 LdrProcessRelocationBlockLongLong(
169 IN ULONG_PTR Address
,
171 IN PUSHORT TypeOffset
,
179 PULONGLONG LongLongPtr
;
181 for (i
= 0; i
< Count
; i
++)
183 Offset
= SWAPW(*TypeOffset
) & 0xFFF;
184 Type
= SWAPW(*TypeOffset
) >> 12;
185 ShortPtr
= (PUSHORT
)(RVA(Address
, Offset
));
188 * Don't relocate within the relocation section itself.
189 * GCC/LD generates sometimes relocation records for the relocation section.
190 * This is a bug in GCC/LD.
191 * Fix for it disabled, since it was only in ntoskrnl and not in ntdll
194 if ((ULONG_PTR)ShortPtr < (ULONG_PTR)RelocationDir ||
195 (ULONG_PTR)ShortPtr >= (ULONG_PTR)RelocationEnd)
199 /* case IMAGE_REL_BASED_SECTION : */
200 /* case IMAGE_REL_BASED_REL32 : */
201 case IMAGE_REL_BASED_ABSOLUTE
:
204 case IMAGE_REL_BASED_HIGH
:
205 *ShortPtr
= HIWORD(MAKELONG(0, *ShortPtr
) + (LONG
)Delta
);
208 case IMAGE_REL_BASED_LOW
:
209 *ShortPtr
= SWAPW(*ShortPtr
) + LOWORD(Delta
);
212 case IMAGE_REL_BASED_HIGHLOW
:
213 LongPtr
= (PULONG
)RVA(Address
, Offset
);
214 *LongPtr
= SWAPD(*LongPtr
) + (ULONG
)Delta
;
217 case IMAGE_REL_BASED_DIR64
:
218 LongLongPtr
= (PUINT64
)RVA(Address
, Offset
);
219 *LongLongPtr
= SWAPQ(*LongLongPtr
) + Delta
;
222 case IMAGE_REL_BASED_HIGHADJ
:
223 case IMAGE_REL_BASED_MIPS_JMPADDR
:
225 DPRINT1("Unknown/unsupported fixup type %hu.\n", Type
);
226 DPRINT1("Address %x, Current %d, Count %d, *TypeOffset %x\n", Address
, i
, Count
, SWAPW(*TypeOffset
));
227 return (PIMAGE_BASE_RELOCATION
)NULL
;
233 return (PIMAGE_BASE_RELOCATION
)TypeOffset
;
238 LdrRelocateImageWithBias(
239 IN PVOID BaseAddress
,
240 IN LONGLONG AdditionalBias
,
246 PIMAGE_NT_HEADERS NtHeaders
;
247 PIMAGE_DATA_DIRECTORY RelocationDDir
;
248 PIMAGE_BASE_RELOCATION RelocationDir
, RelocationEnd
;
254 NtHeaders
= RtlImageNtHeader(BaseAddress
);
256 if (NtHeaders
== NULL
)
259 if (SWAPW(NtHeaders
->FileHeader
.Characteristics
) & IMAGE_FILE_RELOCS_STRIPPED
)
264 RelocationDDir
= &NtHeaders
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
];
266 if (SWAPD(RelocationDDir
->VirtualAddress
) == 0 || SWAPD(RelocationDDir
->Size
) == 0)
271 Delta
= (ULONG_PTR
)BaseAddress
- SWAPD(NtHeaders
->OptionalHeader
.ImageBase
) + AdditionalBias
;
272 RelocationDir
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)BaseAddress
+ SWAPD(RelocationDDir
->VirtualAddress
));
273 RelocationEnd
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)RelocationDir
+ SWAPD(RelocationDDir
->Size
));
275 while (RelocationDir
< RelocationEnd
&&
276 SWAPW(RelocationDir
->SizeOfBlock
) > 0)
278 Count
= (SWAPW(RelocationDir
->SizeOfBlock
) - sizeof(IMAGE_BASE_RELOCATION
)) / sizeof(USHORT
);
279 Address
= (ULONG_PTR
)RVA(BaseAddress
, SWAPD(RelocationDir
->VirtualAddress
));
280 TypeOffset
= (PUSHORT
)(RelocationDir
+ 1);
282 RelocationDir
= LdrProcessRelocationBlockLongLong(Address
,
287 if (RelocationDir
== NULL
)
289 DPRINT1("Error during call to LdrProcessRelocationBlockLongLong()!\n");