1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4
5//
6
7/*============================================================
8**
9** CorImage.cpp
10**
11** IMAGEHLP routines so we can avoid early binding to that DLL.
12**
13===========================================================*/
14
15#include "stdafx.h"
16#include "contract.h"
17#include <daccess.h>
18#include "corimage.h"
19#include "safemath.h"
20
21#define RTL_MEG (1024UL * 1024UL)
22#define RTLP_IMAGE_MAX_DOS_HEADER ( 256UL * RTL_MEG)
23
24// IMAGE_FIRST_SECTION doesn't need 32/64 versions since the file header is
25// the same either way.
26
27#define PTR_IMAGE_FIRST_SECTION( ntheader ) \
28 PTR_IMAGE_SECTION_HEADER \
29 (dac_cast<TADDR>(ntheader) + \
30 FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) + \
31 VAL16((ntheader)->FileHeader.SizeOfOptionalHeader) \
32 )
33
34#ifndef DACCESS_COMPILE
35
36IMAGE_NT_HEADERS *Cor_RtlImageNtHeader(VOID *pvBase, ULONG FileLength)
37{
38 LIMITED_METHOD_CONTRACT;
39 IMAGE_NT_HEADERS *pNtHeaders = NULL;
40 if (pvBase && (pvBase != (VOID*)-1)) {
41 struct Param
42 {
43 IMAGE_DOS_HEADER *pDos;
44 ULONG FileLength;
45 IMAGE_NT_HEADERS *pNtHeaders;
46 } param;
47 param.pDos = (IMAGE_DOS_HEADER*)pvBase;
48 param.FileLength = FileLength;
49 param.pNtHeaders = pNtHeaders;
50
51 PAL_TRY(Param *, pParam, &param) {
52 if ( (pParam->pDos->e_magic == VAL16(IMAGE_DOS_SIGNATURE))
53 && ((DWORD)VAL32(pParam->pDos->e_lfanew) < RTLP_IMAGE_MAX_DOS_HEADER)
54 && ovadd_lt((DWORD)VAL32(pParam->pDos->e_lfanew), sizeof(IMAGE_FILE_HEADER) + sizeof(DWORD), pParam->FileLength)) {
55 pParam->pNtHeaders = (IMAGE_NT_HEADERS*)((BYTE*)pParam->pDos + VAL32(pParam->pDos->e_lfanew));
56 if (pParam->pNtHeaders->Signature != VAL32(IMAGE_NT_SIGNATURE))
57 pParam->pNtHeaders = NULL;
58 }
59 }
60 PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
61 param.pNtHeaders = NULL;
62 }
63 PAL_ENDTRY
64
65 pNtHeaders = param.pNtHeaders;
66 }
67 return pNtHeaders;
68}
69
70#endif // #ifndef DACCESS_COMPILE
71
72EXTERN_C PIMAGE_SECTION_HEADER
73Cor_RtlImageRvaToSection32(PTR_IMAGE_NT_HEADERS32 NtHeaders,
74 ULONG Rva,
75 ULONG FileLength)
76{
77 LIMITED_METHOD_CONTRACT;
78 ULONG i;
79 PTR_IMAGE_SECTION_HEADER NtSection;
80
81 NtSection = PTR_IMAGE_FIRST_SECTION( NtHeaders );
82 for (i=0; i<NtHeaders->FileHeader.NumberOfSections; i++) {
83 if (FileLength &&
84 (((VAL32(NtSection->PointerToRawData) > FileLength)) ||
85 (VAL32(NtSection->SizeOfRawData) > FileLength - VAL32(NtSection->PointerToRawData))))
86 return NULL;
87 if (Rva >= VAL32(NtSection->VirtualAddress) &&
88 Rva < VAL32(NtSection->VirtualAddress) + VAL32(NtSection->SizeOfRawData))
89 return NtSection;
90
91 ++NtSection;
92 }
93
94 return NULL;
95}
96
97EXTERN_C PIMAGE_SECTION_HEADER
98Cor_RtlImageRvaToSection64(PTR_IMAGE_NT_HEADERS64 NtHeaders,
99 ULONG Rva,
100 ULONG FileLength)
101{
102 LIMITED_METHOD_CONTRACT;
103 ULONG i;
104 PTR_IMAGE_SECTION_HEADER NtSection;
105
106 NtSection = PTR_IMAGE_FIRST_SECTION( NtHeaders );
107 for (i=0; i<VAL16(NtHeaders->FileHeader.NumberOfSections); i++) {
108 if (FileLength &&
109 (((VAL32(NtSection->PointerToRawData) > FileLength)) ||
110 (VAL32(NtSection->SizeOfRawData) > FileLength - VAL32(NtSection->PointerToRawData))))
111 return NULL;
112 if (Rva >= VAL32(NtSection->VirtualAddress) &&
113 Rva < VAL32(NtSection->VirtualAddress) + VAL32(NtSection->SizeOfRawData))
114 return NtSection;
115
116 ++NtSection;
117 }
118
119 return NULL;
120}
121
122EXTERN_C PIMAGE_SECTION_HEADER
123Cor_RtlImageRvaToSection(PTR_IMAGE_NT_HEADERS NtHeaders,
124 ULONG Rva,
125 ULONG FileLength)
126{
127 LIMITED_METHOD_CONTRACT;
128 if (NtHeaders->OptionalHeader.Magic == VAL16(IMAGE_NT_OPTIONAL_HDR32_MAGIC))
129 return Cor_RtlImageRvaToSection32((PTR_IMAGE_NT_HEADERS32)NtHeaders,
130 Rva, FileLength);
131 else if(NtHeaders->OptionalHeader.Magic == VAL16(IMAGE_NT_OPTIONAL_HDR64_MAGIC))
132 return Cor_RtlImageRvaToSection64((PTR_IMAGE_NT_HEADERS64)NtHeaders,
133 Rva, FileLength);
134 else {
135 _ASSERTE(!"Invalid File Type");
136 return NULL;
137 }
138}
139
140EXTERN_C PBYTE Cor_RtlImageRvaToVa32(PTR_IMAGE_NT_HEADERS32 NtHeaders,
141 PBYTE Base,
142 ULONG Rva,
143 ULONG FileLength)
144{
145 LIMITED_METHOD_CONTRACT;
146 PIMAGE_SECTION_HEADER NtSection =
147 Cor_RtlImageRvaToSection32(NtHeaders,
148 Rva,
149 FileLength);
150
151 if (NtSection != NULL)
152 return (Base +
153 (Rva - VAL32(NtSection->VirtualAddress)) +
154 VAL32(NtSection->PointerToRawData));
155 else
156 return NULL;
157}
158
159EXTERN_C PBYTE Cor_RtlImageRvaToVa64(PTR_IMAGE_NT_HEADERS64 NtHeaders,
160 PBYTE Base,
161 ULONG Rva,
162 ULONG FileLength)
163{
164 LIMITED_METHOD_CONTRACT;
165 PIMAGE_SECTION_HEADER NtSection =
166 Cor_RtlImageRvaToSection64(NtHeaders,
167 Rva,
168 FileLength);
169
170 if (NtSection != NULL)
171 return (Base +
172 (Rva - VAL32(NtSection->VirtualAddress)) +
173 VAL32(NtSection->PointerToRawData));
174 else
175 return NULL;
176}
177
178EXTERN_C PBYTE Cor_RtlImageRvaToVa(PTR_IMAGE_NT_HEADERS NtHeaders,
179 PBYTE Base,
180 ULONG Rva,
181 ULONG FileLength)
182{
183 LIMITED_METHOD_CONTRACT;
184 if (NtHeaders->OptionalHeader.Magic == VAL16(IMAGE_NT_OPTIONAL_HDR32_MAGIC))
185 return Cor_RtlImageRvaToVa32((PTR_IMAGE_NT_HEADERS32)NtHeaders,
186 Base, Rva, FileLength);
187 else if(NtHeaders->OptionalHeader.Magic == VAL16(IMAGE_NT_OPTIONAL_HDR64_MAGIC))
188 return Cor_RtlImageRvaToVa64((PTR_IMAGE_NT_HEADERS64)NtHeaders,
189 Base, Rva, FileLength);
190 else {
191 _ASSERTE(!"Invalid File Type");
192 return NULL;
193 }
194}
195
196EXTERN_C PBYTE Cor_RtlImageDirToVa(PTR_IMAGE_NT_HEADERS NtHeaders,
197 PBYTE Base,
198 UINT DirIndex,
199 ULONG FileLength)
200{
201 LIMITED_METHOD_CONTRACT;
202 if (NtHeaders->OptionalHeader.Magic == VAL16(IMAGE_NT_OPTIONAL_HDR32_MAGIC))
203 return Cor_RtlImageRvaToVa32((PTR_IMAGE_NT_HEADERS32)NtHeaders, Base,
204 VAL32(((PTR_IMAGE_NT_HEADERS32)NtHeaders)->OptionalHeader.DataDirectory[DirIndex].VirtualAddress),
205 FileLength);
206 else if(NtHeaders->OptionalHeader.Magic == VAL16(IMAGE_NT_OPTIONAL_HDR64_MAGIC))
207 return Cor_RtlImageRvaToVa64((PTR_IMAGE_NT_HEADERS64)NtHeaders, Base,
208 VAL32(((PTR_IMAGE_NT_HEADERS64)NtHeaders)->OptionalHeader.DataDirectory[DirIndex].VirtualAddress),
209 FileLength);
210 else {
211 _ASSERTE(!"Invalid File Type");
212 return NULL;
213 }
214}
215
216EXTERN_C PIMAGE_SECTION_HEADER
217Cor_RtlImageRvaRangeToSection(PTR_IMAGE_NT_HEADERS NtHeaders,
218 ULONG Rva,
219 ULONG Range,
220 ULONG FileLength)
221{
222 LIMITED_METHOD_CONTRACT;
223 ULONG i;
224 PTR_IMAGE_SECTION_HEADER NtSection;
225
226 if (!Range)
227 return Cor_RtlImageRvaToSection(NtHeaders, Rva, FileLength);
228
229 NtSection = PTR_IMAGE_FIRST_SECTION( NtHeaders );
230 for (i=0; i<VAL16(NtHeaders->FileHeader.NumberOfSections); i++) {
231 if (FileLength &&
232 ((VAL32(NtSection->PointerToRawData) > FileLength) ||
233 (VAL32(NtSection->SizeOfRawData) > FileLength - VAL32(NtSection->PointerToRawData))))
234 return NULL;
235 if (Rva >= VAL32(NtSection->VirtualAddress) &&
236 Rva + Range <= VAL32(NtSection->VirtualAddress) + VAL32(NtSection->SizeOfRawData))
237 return NtSection;
238
239 ++NtSection;
240 }
241
242 return NULL;
243}
244
245EXTERN_C DWORD Cor_RtlImageRvaToOffset(PTR_IMAGE_NT_HEADERS NtHeaders,
246 ULONG Rva,
247 ULONG FileLength)
248{
249 LIMITED_METHOD_CONTRACT;
250 PIMAGE_SECTION_HEADER NtSection =
251 Cor_RtlImageRvaToSection(NtHeaders,
252 Rva,
253 FileLength);
254
255 if (NtSection)
256 return ((Rva - VAL32(NtSection->VirtualAddress)) +
257 VAL32(NtSection->PointerToRawData));
258 else
259 return NULL;
260}
261