Add missing "NTAPI"
[reactos.git] / reactos / lib / rtl / image.c
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
9 * Aleksey Bragin
10 */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <rtl.h>
15
16 #define NDEBUG
17 #include <debug.h>
18
19 /* FUNCTIONS *****************************************************************/
20
21 /*
22 * @implemented
23 */
24 PIMAGE_NT_HEADERS NTAPI
25 RtlImageNtHeader (IN PVOID BaseAddress)
26 {
27 PIMAGE_NT_HEADERS NtHeader;
28 PIMAGE_DOS_HEADER DosHeader = (PIMAGE_DOS_HEADER)BaseAddress;
29
30 if (DosHeader && DosHeader->e_magic != IMAGE_DOS_SIGNATURE)
31 {
32 DPRINT1("DosHeader->e_magic %x\n", DosHeader->e_magic);
33 DPRINT1("NtHeader 0x%lx\n", ((ULONG_PTR)BaseAddress + DosHeader->e_lfanew));
34 }
35
36 if (DosHeader && DosHeader->e_magic == IMAGE_DOS_SIGNATURE)
37 {
38 NtHeader = (PIMAGE_NT_HEADERS)((ULONG_PTR)BaseAddress + DosHeader->e_lfanew);
39 if (NtHeader->Signature == IMAGE_NT_SIGNATURE)
40 return NtHeader;
41 }
42
43 return NULL;
44 }
45
46
47 /*
48 * @implemented
49 */
50 PVOID
51 NTAPI
52 RtlImageDirectoryEntryToData(PVOID BaseAddress,
53 BOOLEAN MappedAsImage,
54 USHORT Directory,
55 PULONG Size)
56 {
57 PIMAGE_NT_HEADERS NtHeader;
58 ULONG Va;
59
60 /* Magic flag for non-mapped images. */
61 if ((ULONG_PTR)BaseAddress & 1)
62 {
63 BaseAddress = (PVOID)((ULONG_PTR)BaseAddress & ~1);
64 MappedAsImage = FALSE;
65 }
66
67
68 NtHeader = RtlImageNtHeader (BaseAddress);
69 if (NtHeader == NULL)
70 return NULL;
71
72 if (Directory >= NtHeader->OptionalHeader.NumberOfRvaAndSizes)
73 return NULL;
74
75 Va = NtHeader->OptionalHeader.DataDirectory[Directory].VirtualAddress;
76 if (Va == 0)
77 return NULL;
78
79 *Size = NtHeader->OptionalHeader.DataDirectory[Directory].Size;
80
81 if (MappedAsImage || Va < NtHeader->OptionalHeader.SizeOfHeaders)
82 return (PVOID)((ULONG_PTR)BaseAddress + Va);
83
84 /* image mapped as ordinary file, we must find raw pointer */
85 return RtlImageRvaToVa (NtHeader, BaseAddress, Va, NULL);
86 }
87
88
89 /*
90 * @implemented
91 */
92 PIMAGE_SECTION_HEADER
93 NTAPI
94 RtlImageRvaToSection (
95 PIMAGE_NT_HEADERS NtHeader,
96 PVOID BaseAddress,
97 ULONG Rva
98 )
99 {
100 PIMAGE_SECTION_HEADER Section;
101 ULONG Va;
102 ULONG Count;
103
104 Count = NtHeader->FileHeader.NumberOfSections;
105 Section = (PIMAGE_SECTION_HEADER)((ULONG)&NtHeader->OptionalHeader +
106 NtHeader->FileHeader.SizeOfOptionalHeader);
107 while (Count)
108 {
109 Va = Section->VirtualAddress;
110 if ((Va <= Rva) &&
111 (Rva < Va + Section->SizeOfRawData))
112 return Section;
113 Section++;
114 }
115 return NULL;
116 }
117
118
119 /*
120 * @implemented
121 */
122 PVOID
123 NTAPI
124 RtlImageRvaToVa (
125 PIMAGE_NT_HEADERS NtHeader,
126 PVOID BaseAddress,
127 ULONG Rva,
128 PIMAGE_SECTION_HEADER *SectionHeader
129 )
130 {
131 PIMAGE_SECTION_HEADER Section = NULL;
132
133 if (SectionHeader)
134 Section = *SectionHeader;
135
136 if (Section == NULL ||
137 Rva < Section->VirtualAddress ||
138 Rva >= Section->VirtualAddress + Section->SizeOfRawData)
139 {
140 Section = RtlImageRvaToSection (NtHeader, BaseAddress, Rva);
141 if (Section == NULL)
142 return 0;
143
144 if (SectionHeader)
145 *SectionHeader = Section;
146 }
147
148 return (PVOID)((ULONG_PTR)BaseAddress +
149 Rva +
150 Section->PointerToRawData -
151 (ULONG_PTR)Section->VirtualAddress);
152 }
153
154 PIMAGE_BASE_RELOCATION
155 NTAPI
156 LdrProcessRelocationBlockLongLong(
157 IN ULONG_PTR Address,
158 IN ULONG Count,
159 IN PUSHORT TypeOffset,
160 IN LONGLONG Delta
161 )
162 {
163 SHORT Offset;
164 USHORT Type;
165 USHORT i;
166 PUSHORT ShortPtr;
167 PULONG LongPtr;
168
169 for (i = 0; i < Count; i++)
170 {
171 Offset = *TypeOffset & 0xFFF;
172 Type = *TypeOffset >> 12;
173 ShortPtr = (PUSHORT)(RVA(Address, Offset));
174
175 /*
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
180 */
181 /*
182 if ((ULONG_PTR)ShortPtr < (ULONG_PTR)RelocationDir ||
183 (ULONG_PTR)ShortPtr >= (ULONG_PTR)RelocationEnd)
184 {*/
185 switch (Type)
186 {
187 /* case IMAGE_REL_BASED_SECTION : */
188 /* case IMAGE_REL_BASED_REL32 : */
189 case IMAGE_REL_BASED_ABSOLUTE:
190 break;
191
192 case IMAGE_REL_BASED_HIGH:
193 *ShortPtr = HIWORD(MAKELONG(0, *ShortPtr) + (LONG)Delta);
194 break;
195
196 case IMAGE_REL_BASED_LOW:
197 *ShortPtr += LOWORD(Delta);
198 break;
199
200 case IMAGE_REL_BASED_HIGHLOW:
201 LongPtr = (PULONG)RVA(Address, Offset);
202 *LongPtr += (ULONG)Delta;
203 break;
204
205 case IMAGE_REL_BASED_HIGHADJ:
206 case IMAGE_REL_BASED_MIPS_JMPADDR:
207 default:
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;
211 }
212
213 TypeOffset++;
214 }
215
216 return (PIMAGE_BASE_RELOCATION)TypeOffset;
217 }
218
219 ULONG
220 NTAPI
221 LdrRelocateImageWithBias(
222 IN PVOID BaseAddress,
223 IN LONGLONG AdditionalBias,
224 IN PCCH LoaderName,
225 IN ULONG Success,
226 IN ULONG Conflict,
227 IN ULONG Invalid
228 )
229 {
230 PIMAGE_NT_HEADERS NtHeaders;
231 PIMAGE_DATA_DIRECTORY RelocationDDir;
232 PIMAGE_BASE_RELOCATION RelocationDir, RelocationEnd;
233 ULONG Count;
234 ULONG_PTR Address;
235 PUSHORT TypeOffset;
236 LONGLONG Delta;
237
238 NtHeaders = RtlImageNtHeader(BaseAddress);
239
240 if (NtHeaders == NULL)
241 return Invalid;
242
243 if (NtHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
244 {
245 return Conflict;
246 }
247
248 RelocationDDir = &NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
249
250 if (RelocationDDir->VirtualAddress == 0 || RelocationDDir->Size == 0)
251 {
252 return Success;
253 }
254
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);
258
259 while (RelocationDir < RelocationEnd &&
260 RelocationDir->SizeOfBlock > 0)
261 {
262 Count = (RelocationDir->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(USHORT);
263 Address = (ULONG_PTR)RVA(BaseAddress, RelocationDir->VirtualAddress);
264 TypeOffset = (PUSHORT)(RelocationDir + 1);
265
266 RelocationDir = LdrProcessRelocationBlockLongLong(Address,
267 Count,
268 TypeOffset,
269 Delta);
270
271 if (RelocationDir == NULL)
272 {
273 DPRINT1("Error during call to LdrProcessRelocationBlockLongLong()!\n");
274 return Invalid;
275 }
276 }
277
278 return Success;
279 }
280 /* EOF */