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(IN PVOID BaseAddress
,
26 IN ULONG NumberOfBytes
,
36 PIMAGE_NT_HEADERS NTAPI
37 RtlImageNtHeader (IN PVOID BaseAddress
)
39 PIMAGE_NT_HEADERS NtHeader
;
40 PIMAGE_DOS_HEADER DosHeader
= (PIMAGE_DOS_HEADER
)BaseAddress
;
42 if (DosHeader
&& SWAPW(DosHeader
->e_magic
) != IMAGE_DOS_SIGNATURE
)
44 DPRINT1("DosHeader->e_magic %x\n", SWAPW(DosHeader
->e_magic
));
45 DPRINT1("NtHeader 0x%lx\n", ((ULONG_PTR
)BaseAddress
+ SWAPD(DosHeader
->e_lfanew
)));
48 if (DosHeader
&& SWAPW(DosHeader
->e_magic
) == IMAGE_DOS_SIGNATURE
)
50 NtHeader
= (PIMAGE_NT_HEADERS
)((ULONG_PTR
)BaseAddress
+ SWAPD(DosHeader
->e_lfanew
));
51 if (SWAPD(NtHeader
->Signature
) == IMAGE_NT_SIGNATURE
)
64 RtlImageDirectoryEntryToData(PVOID BaseAddress
,
65 BOOLEAN MappedAsImage
,
69 PIMAGE_NT_HEADERS NtHeader
;
72 /* Magic flag for non-mapped images. */
73 if ((ULONG_PTR
)BaseAddress
& 1)
75 BaseAddress
= (PVOID
)((ULONG_PTR
)BaseAddress
& ~1);
76 MappedAsImage
= FALSE
;
80 NtHeader
= RtlImageNtHeader (BaseAddress
);
84 if (Directory
>= SWAPD(NtHeader
->OptionalHeader
.NumberOfRvaAndSizes
))
87 Va
= SWAPD(NtHeader
->OptionalHeader
.DataDirectory
[Directory
].VirtualAddress
);
91 *Size
= SWAPD(NtHeader
->OptionalHeader
.DataDirectory
[Directory
].Size
);
93 if (MappedAsImage
|| Va
< SWAPD(NtHeader
->OptionalHeader
.SizeOfHeaders
))
94 return (PVOID
)((ULONG_PTR
)BaseAddress
+ Va
);
96 /* image mapped as ordinary file, we must find raw pointer */
97 return RtlImageRvaToVa (NtHeader
, BaseAddress
, Va
, NULL
);
104 PIMAGE_SECTION_HEADER
106 RtlImageRvaToSection (
107 PIMAGE_NT_HEADERS NtHeader
,
112 PIMAGE_SECTION_HEADER Section
;
116 Count
= SWAPW(NtHeader
->FileHeader
.NumberOfSections
);
117 Section
= IMAGE_FIRST_SECTION(NtHeader
);
121 Va
= SWAPD(Section
->VirtualAddress
);
123 (Rva
< Va
+ SWAPD(Section
->Misc
.VirtualSize
)))
137 PIMAGE_NT_HEADERS NtHeader
,
140 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
,
180 PULONGLONG LongLongPtr
;
182 for (i
= 0; i
< Count
; i
++)
184 Offset
= SWAPW(*TypeOffset
) & 0xFFF;
185 Type
= SWAPW(*TypeOffset
) >> 12;
186 ShortPtr
= (PUSHORT
)(RVA(Address
, Offset
));
189 * Don't relocate within the relocation section itself.
190 * GCC/LD generates sometimes relocation records for the relocation section.
191 * This is a bug in GCC/LD.
192 * Fix for it disabled, since it was only in ntoskrnl and not in ntdll
195 if ((ULONG_PTR)ShortPtr < (ULONG_PTR)RelocationDir ||
196 (ULONG_PTR)ShortPtr >= (ULONG_PTR)RelocationEnd)
200 /* case IMAGE_REL_BASED_SECTION : */
201 /* case IMAGE_REL_BASED_REL32 : */
202 case IMAGE_REL_BASED_ABSOLUTE
:
205 case IMAGE_REL_BASED_HIGH
:
206 *ShortPtr
= HIWORD(MAKELONG(0, *ShortPtr
) + (LONG
)Delta
);
209 case IMAGE_REL_BASED_LOW
:
210 *ShortPtr
= SWAPW(*ShortPtr
) + LOWORD(Delta
);
213 case IMAGE_REL_BASED_HIGHLOW
:
214 LongPtr
= (PULONG
)RVA(Address
, Offset
);
215 *LongPtr
= SWAPD(*LongPtr
) + (ULONG
)Delta
;
218 case IMAGE_REL_BASED_DIR64
:
219 LongLongPtr
= (PUINT64
)RVA(Address
, Offset
);
220 *LongLongPtr
= SWAPQ(*LongLongPtr
) + Delta
;
223 case IMAGE_REL_BASED_HIGHADJ
:
224 case IMAGE_REL_BASED_MIPS_JMPADDR
:
226 DPRINT1("Unknown/unsupported fixup type %hu.\n", Type
);
227 DPRINT1("Address %x, Current %d, Count %d, *TypeOffset %x\n", Address
, i
, Count
, SWAPW(*TypeOffset
));
228 return (PIMAGE_BASE_RELOCATION
)NULL
;
234 return (PIMAGE_BASE_RELOCATION
)TypeOffset
;
239 LdrRelocateImageWithBias(
240 IN PVOID BaseAddress
,
241 IN LONGLONG AdditionalBias
,
248 PIMAGE_NT_HEADERS NtHeaders
;
249 PIMAGE_DATA_DIRECTORY RelocationDDir
;
250 PIMAGE_BASE_RELOCATION RelocationDir
, RelocationEnd
;
256 NtHeaders
= RtlImageNtHeader(BaseAddress
);
258 if (NtHeaders
== NULL
)
261 if (SWAPW(NtHeaders
->FileHeader
.Characteristics
) & IMAGE_FILE_RELOCS_STRIPPED
)
266 RelocationDDir
= &NtHeaders
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
];
268 if (SWAPD(RelocationDDir
->VirtualAddress
) == 0 || SWAPD(RelocationDDir
->Size
) == 0)
273 Delta
= (ULONG_PTR
)BaseAddress
- SWAPD(NtHeaders
->OptionalHeader
.ImageBase
) + AdditionalBias
;
274 RelocationDir
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)BaseAddress
+ SWAPD(RelocationDDir
->VirtualAddress
));
275 RelocationEnd
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)RelocationDir
+ SWAPD(RelocationDDir
->Size
));
277 while (RelocationDir
< RelocationEnd
&&
278 SWAPW(RelocationDir
->SizeOfBlock
) > 0)
280 Count
= (SWAPW(RelocationDir
->SizeOfBlock
) - sizeof(IMAGE_BASE_RELOCATION
)) / sizeof(USHORT
);
281 Address
= (ULONG_PTR
)RVA(BaseAddress
, SWAPD(RelocationDir
->VirtualAddress
));
282 TypeOffset
= (PUSHORT
)(RelocationDir
+ 1);
284 RelocationDir
= LdrProcessRelocationBlockLongLong(Address
,
289 if (RelocationDir
== NULL
)
291 DPRINT1("Error during call to LdrProcessRelocationBlockLongLong()!\n");