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 *****************************************************************/
24 PIMAGE_NT_HEADERS NTAPI
25 RtlImageNtHeader (IN PVOID BaseAddress
)
27 PIMAGE_NT_HEADERS NtHeader
;
28 PIMAGE_DOS_HEADER DosHeader
= (PIMAGE_DOS_HEADER
)BaseAddress
;
30 if (DosHeader
&& DosHeader
->e_magic
!= IMAGE_DOS_SIGNATURE
)
32 DPRINT1("DosHeader->e_magic %x\n", DosHeader
->e_magic
);
33 DPRINT1("NtHeader 0x%lx\n", ((ULONG_PTR
)BaseAddress
+ DosHeader
->e_lfanew
));
36 if (DosHeader
&& DosHeader
->e_magic
== IMAGE_DOS_SIGNATURE
)
38 NtHeader
= (PIMAGE_NT_HEADERS
)((ULONG_PTR
)BaseAddress
+ DosHeader
->e_lfanew
);
39 if (NtHeader
->Signature
== IMAGE_NT_SIGNATURE
)
52 RtlImageDirectoryEntryToData(PVOID BaseAddress
,
53 BOOLEAN MappedAsImage
,
57 PIMAGE_NT_HEADERS NtHeader
;
60 /* Magic flag for non-mapped images. */
61 if ((ULONG_PTR
)BaseAddress
& 1)
63 BaseAddress
= (PVOID
)((ULONG_PTR
)BaseAddress
& ~1);
64 MappedAsImage
= FALSE
;
68 NtHeader
= RtlImageNtHeader (BaseAddress
);
72 if (Directory
>= NtHeader
->OptionalHeader
.NumberOfRvaAndSizes
)
75 Va
= NtHeader
->OptionalHeader
.DataDirectory
[Directory
].VirtualAddress
;
79 *Size
= NtHeader
->OptionalHeader
.DataDirectory
[Directory
].Size
;
81 if (MappedAsImage
|| Va
< NtHeader
->OptionalHeader
.SizeOfHeaders
)
82 return (PVOID
)((ULONG_PTR
)BaseAddress
+ Va
);
84 /* image mapped as ordinary file, we must find raw pointer */
85 return RtlImageRvaToVa (NtHeader
, BaseAddress
, Va
, NULL
);
94 RtlImageRvaToSection (
95 PIMAGE_NT_HEADERS NtHeader
,
100 PIMAGE_SECTION_HEADER Section
;
104 Count
= NtHeader
->FileHeader
.NumberOfSections
;
105 Section
= (PIMAGE_SECTION_HEADER
)((ULONG
)&NtHeader
->OptionalHeader
+
106 NtHeader
->FileHeader
.SizeOfOptionalHeader
);
109 Va
= Section
->VirtualAddress
;
111 (Rva
< Va
+ Section
->SizeOfRawData
))
125 PIMAGE_NT_HEADERS NtHeader
,
128 PIMAGE_SECTION_HEADER
*SectionHeader
131 PIMAGE_SECTION_HEADER Section
= NULL
;
134 Section
= *SectionHeader
;
136 if (Section
== NULL
||
137 Rva
< Section
->VirtualAddress
||
138 Rva
>= Section
->VirtualAddress
+ Section
->SizeOfRawData
)
140 Section
= RtlImageRvaToSection (NtHeader
, BaseAddress
, Rva
);
145 *SectionHeader
= Section
;
148 return (PVOID
)((ULONG_PTR
)BaseAddress
+
150 Section
->PointerToRawData
-
151 (ULONG_PTR
)Section
->VirtualAddress
);
154 PIMAGE_BASE_RELOCATION
156 LdrProcessRelocationBlockLongLong(
157 IN ULONG_PTR Address
,
159 IN PUSHORT TypeOffset
,
169 for (i
= 0; i
< Count
; i
++)
171 Offset
= *TypeOffset
& 0xFFF;
172 Type
= *TypeOffset
>> 12;
173 ShortPtr
= (PUSHORT
)(RVA(Address
, Offset
));
176 * Don't relocate within the relocation section itself.
177 * GCC/LD generates sometimes relocation records for the relocation section.
178 * This is a bug in GCC/LD.
179 * Fix for it disabled, since it was only in ntoskrnl and not in ntdll
182 if ((ULONG_PTR)ShortPtr < (ULONG_PTR)RelocationDir ||
183 (ULONG_PTR)ShortPtr >= (ULONG_PTR)RelocationEnd)
187 /* case IMAGE_REL_BASED_SECTION : */
188 /* case IMAGE_REL_BASED_REL32 : */
189 case IMAGE_REL_BASED_ABSOLUTE
:
192 case IMAGE_REL_BASED_HIGH
:
193 *ShortPtr
= HIWORD(MAKELONG(0, *ShortPtr
) + (LONG
)Delta
);
196 case IMAGE_REL_BASED_LOW
:
197 *ShortPtr
+= LOWORD(Delta
);
200 case IMAGE_REL_BASED_HIGHLOW
:
201 LongPtr
= (PULONG
)RVA(Address
, Offset
);
202 *LongPtr
+= (ULONG
)Delta
;
205 case IMAGE_REL_BASED_HIGHADJ
:
206 case IMAGE_REL_BASED_MIPS_JMPADDR
:
208 DPRINT1("Unknown/unsupported fixup type %hu.\n", Type
);
209 DPRINT1("Address %x, Current %d, Count %d, *TypeOffset %x\n", Address
, i
, Count
, *TypeOffset
);
210 return (PIMAGE_BASE_RELOCATION
)NULL
;
216 return (PIMAGE_BASE_RELOCATION
)TypeOffset
;
221 LdrRelocateImageWithBias(
222 IN PVOID BaseAddress
,
223 IN LONGLONG AdditionalBias
,
230 PIMAGE_NT_HEADERS NtHeaders
;
231 PIMAGE_DATA_DIRECTORY RelocationDDir
;
232 PIMAGE_BASE_RELOCATION RelocationDir
, RelocationEnd
;
238 NtHeaders
= RtlImageNtHeader(BaseAddress
);
240 if (NtHeaders
== NULL
)
243 if (NtHeaders
->FileHeader
.Characteristics
& IMAGE_FILE_RELOCS_STRIPPED
)
248 RelocationDDir
= &NtHeaders
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
];
250 if (RelocationDDir
->VirtualAddress
== 0 || RelocationDDir
->Size
== 0)
255 Delta
= (ULONG_PTR
)BaseAddress
- NtHeaders
->OptionalHeader
.ImageBase
+ AdditionalBias
;
256 RelocationDir
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)BaseAddress
+ RelocationDDir
->VirtualAddress
);
257 RelocationEnd
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)RelocationDir
+ RelocationDDir
->Size
);
259 while (RelocationDir
< RelocationEnd
&&
260 RelocationDir
->SizeOfBlock
> 0)
262 Count
= (RelocationDir
->SizeOfBlock
- sizeof(IMAGE_BASE_RELOCATION
)) / sizeof(USHORT
);
263 Address
= (ULONG_PTR
)RVA(BaseAddress
, RelocationDir
->VirtualAddress
);
264 TypeOffset
= (PUSHORT
)(RelocationDir
+ 1);
266 RelocationDir
= LdrProcessRelocationBlockLongLong(Address
,
271 if (RelocationDir
== NULL
)
273 DPRINT1("Error during call to LdrProcessRelocationBlockLongLong()!\n");