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// PEDecoder.h
6//
7
8// --------------------------------------------------------------------------------
9
10// --------------------------------------------------------------------------------
11// PEDecoder - Utility class for reading and verifying PE files.
12//
13// Note that the Check step is optional if you are willing to trust the
14// integrity of the image.
15// (Or at any rate can be factored into an initial verification step.)
16//
17// Functions which access the memory of the PE file take a "flat" flag - this
18// indicates whether the PE images data has been loaded flat the way it resides in the file,
19// or if the sections have been mapped into memory at the proper base addresses.
20//
21// Finally, some functions take an optional "size" argument, which can be used for
22// range verification. This is an optional parameter, but if you omit it be sure
23// you verify the size in some other way.
24// --------------------------------------------------------------------------------
25
26
27#ifndef PEDECODER_H_
28#define PEDECODER_H_
29
30// --------------------------------------------------------------------------------
31// Required headers
32// --------------------------------------------------------------------------------
33
34#include "windows.h"
35#include "clrtypes.h"
36#include "check.h"
37#include "contract.h"
38#include "cor.h"
39#include "corhdr.h"
40
41#ifdef FEATURE_PREJIT
42#include "corcompile.h"
43#else // FEATURE_PREJIT
44typedef DPTR(struct COR_ILMETHOD) PTR_COR_ILMETHOD;
45struct CORCOMPILE_HEADER { int dummy_field; };
46typedef DPTR(struct CORCOMPILE_HEADER) PTR_CORCOMPILE_HEADER;
47#define CORCOMPILE_IS_POINTER_TAGGED(fixup) (false)
48#endif // FEATURE_PREJIT
49
50#include "readytorun.h"
51typedef DPTR(struct READYTORUN_HEADER) PTR_READYTORUN_HEADER;
52
53typedef DPTR(IMAGE_COR20_HEADER) PTR_IMAGE_COR20_HEADER;
54
55// --------------------------------------------------------------------------------
56// Forward declared types
57// --------------------------------------------------------------------------------
58
59class Module;
60
61// --------------------------------------------------------------------------------
62// RVA definition
63// --------------------------------------------------------------------------------
64
65// Needs to be DWORD to avoid conflict with <imagehlp.h>
66typedef DWORD RVA;
67
68#ifdef _MSC_VER
69// Wrapper to suppress ambigous overload problems with MSVC.
70inline CHECK CheckOverflow(RVA value1, COUNT_T value2)
71{
72 WRAPPER_NO_CONTRACT;
73 CHECK(CheckOverflow((UINT32) value1, (UINT32) value2));
74 CHECK_OK;
75}
76#endif // _MSC_VER
77
78// --------------------------------------------------------------------------------
79// IMAGE_FILE_MACHINE_NATIVE
80// --------------------------------------------------------------------------------
81
82#if defined(_TARGET_X86_)
83#define IMAGE_FILE_MACHINE_NATIVE IMAGE_FILE_MACHINE_I386
84#elif defined(_TARGET_AMD64_)
85#define IMAGE_FILE_MACHINE_NATIVE IMAGE_FILE_MACHINE_AMD64
86#elif defined(_TARGET_ARM_)
87#define IMAGE_FILE_MACHINE_NATIVE IMAGE_FILE_MACHINE_ARMNT
88#elif defined(_TARGET_ARM64_)
89#define IMAGE_FILE_MACHINE_NATIVE IMAGE_FILE_MACHINE_ARM64
90#else
91#error "port me"
92#endif
93
94// Machine code for native images
95#if defined(__APPLE__)
96#define IMAGE_FILE_MACHINE_NATIVE_OS_OVERRIDE 0x4644
97#elif defined(__FreeBSD__)
98#define IMAGE_FILE_MACHINE_NATIVE_OS_OVERRIDE 0xADC4
99#elif defined(__linux__)
100#define IMAGE_FILE_MACHINE_NATIVE_OS_OVERRIDE 0x7B79
101#elif defined(__NetBSD__)
102#define IMAGE_FILE_MACHINE_NATIVE_OS_OVERRIDE 0x1993
103#else
104#define IMAGE_FILE_MACHINE_NATIVE_OS_OVERRIDE 0
105#endif
106
107#define IMAGE_FILE_MACHINE_NATIVE_NI (IMAGE_FILE_MACHINE_NATIVE ^ IMAGE_FILE_MACHINE_NATIVE_OS_OVERRIDE)
108
109// --------------------------------------------------------------------------------
110// Types
111// --------------------------------------------------------------------------------
112
113typedef DPTR(class PEDecoder) PTR_PEDecoder;
114
115class PEDecoder
116{
117 public:
118
119 // ------------------------------------------------------------
120 // Public API
121 // ------------------------------------------------------------
122
123 // Access functions are divided into 3 categories:
124 // Has - check if the element is present
125 // Check - Do consistency checks on the element (requires Has).
126 // This step is optional if you are willing to trust the integrity of the
127 // image. (It is asserted in a checked build.)
128 // Get - Access the element (requires Has and Check)
129
130 PEDecoder();
131 PEDecoder(void *flatBase, COUNT_T size); // flatBase is the raw disk layout data (using MapViewOfFile)
132 PEDecoder(PTR_VOID mappedBase, bool relocated = FALSE); // mappedBase is the mapped/expanded file (using LoadLibrary)
133
134 void Init(void *flatBase, COUNT_T size);
135 HRESULT Init(void *mappedBase, bool relocated = FALSE);
136 void Reset(); //make sure you don't have a thread race
137
138 PTR_VOID GetBase() const; // Currently loaded base, as opposed to GetPreferredBase()
139 BOOL IsMapped() const;
140 BOOL IsRelocated() const;
141 BOOL IsFlat() const;
142 BOOL HasContents() const;
143 COUNT_T GetSize() const; // size of file on disk, as opposed to GetVirtualSize()
144
145 // High level image checks:
146
147 CHECK CheckFormat() const; // Check whatever is present
148 CHECK CheckNTFormat() const; // Check a PE file image
149 CHECK CheckCORFormat() const; // Check a COR image (IL or native)
150 CHECK CheckILFormat() const; // Check a managed image
151 CHECK CheckILOnlyFormat() const; // Check an IL only image
152 CHECK CheckNativeFormat() const; // Check a native image
153
154 // NT header access
155
156 BOOL HasNTHeaders() const;
157 CHECK CheckNTHeaders() const;
158
159 IMAGE_NT_HEADERS32 *GetNTHeaders32() const;
160 IMAGE_NT_HEADERS64 *GetNTHeaders64() const;
161 BOOL Has32BitNTHeaders() const;
162
163 const void *GetHeaders(COUNT_T *pSize = NULL) const;
164
165 BOOL IsDll() const;
166 BOOL HasBaseRelocations() const;
167 const void *GetPreferredBase() const; // OptionalHeaders.ImageBase
168 COUNT_T GetVirtualSize() const; // OptionalHeaders.SizeOfImage - size of mapped/expanded image in memory
169 WORD GetSubsystem() const;
170 WORD GetDllCharacteristics() const;
171 DWORD GetTimeDateStamp() const;
172 DWORD GetCheckSum() const;
173 WORD GetMachine() const;
174 WORD GetCharacteristics() const;
175 DWORD GetFileAlignment() const;
176 DWORD GetSectionAlignment() const;
177 SIZE_T GetSizeOfStackReserve() const;
178 SIZE_T GetSizeOfStackCommit() const;
179 SIZE_T GetSizeOfHeapReserve() const;
180 SIZE_T GetSizeOfHeapCommit() const;
181 UINT32 GetLoaderFlags() const;
182 UINT32 GetWin32VersionValue() const;
183 COUNT_T GetNumberOfRvaAndSizes() const;
184 COUNT_T GetNumberOfSections() const;
185 PTR_IMAGE_SECTION_HEADER FindFirstSection() const;
186 IMAGE_SECTION_HEADER *FindSection(LPCSTR sectionName) const;
187
188 DWORD GetImageIdentity() const;
189
190 BOOL HasWriteableSections() const;
191
192 // Directory entry access
193
194 BOOL HasDirectoryEntry(int entry) const;
195 CHECK CheckDirectoryEntry(int entry, int forbiddenFlags = 0, IsNullOK ok = NULL_NOT_OK) const;
196 IMAGE_DATA_DIRECTORY *GetDirectoryEntry(int entry) const;
197 TADDR GetDirectoryEntryData(int entry, COUNT_T *pSize = NULL) const;
198
199 // IMAGE_DATA_DIRECTORY access
200
201 CHECK CheckDirectory(IMAGE_DATA_DIRECTORY *pDir, int forbiddenFlags = 0, IsNullOK ok = NULL_NOT_OK) const;
202 TADDR GetDirectoryData(IMAGE_DATA_DIRECTORY *pDir) const;
203 TADDR GetDirectoryData(IMAGE_DATA_DIRECTORY *pDir, COUNT_T *pSize) const;
204
205 // Basic RVA access
206
207 CHECK CheckRva(RVA rva, IsNullOK ok = NULL_NOT_OK) const;
208 CHECK CheckRva(RVA rva, COUNT_T size, int forbiddenFlags=0, IsNullOK ok = NULL_NOT_OK) const;
209 TADDR GetRvaData(RVA rva, IsNullOK ok = NULL_NOT_OK) const;
210 // Called with ok=NULL_OK only for mapped fields (RVA statics)
211
212 CHECK CheckData(const void *data, IsNullOK ok = NULL_NOT_OK) const;
213 CHECK CheckData(const void *data, COUNT_T size, IsNullOK ok = NULL_NOT_OK) const;
214 RVA GetDataRva(const TADDR data) const;
215 BOOL PointerInPE(PTR_CVOID data) const;
216
217 // Flat mapping utilities - using PointerToRawData instead of (Relative)VirtualAddress
218 CHECK CheckOffset(COUNT_T fileOffset, IsNullOK ok = NULL_NOT_OK) const;
219 CHECK CheckOffset(COUNT_T fileOffset, COUNT_T size, IsNullOK ok = NULL_NOT_OK) const;
220 TADDR GetOffsetData(COUNT_T fileOffset, IsNullOK ok = NULL_NOT_OK) const;
221 // Called with ok=NULL_OK only for mapped fields (RVA statics)
222
223 // Mapping between RVA and file offsets
224 COUNT_T RvaToOffset(RVA rva) const;
225 RVA OffsetToRva(COUNT_T fileOffset) const;
226
227 // Base intra-image pointer access
228 // (These are for pointers retrieved out of the PE image)
229
230 CHECK CheckInternalAddress(SIZE_T address, IsNullOK ok = NULL_NOT_OK) const;
231 CHECK CheckInternalAddress(SIZE_T address, COUNT_T size, IsNullOK ok = NULL_NOT_OK) const;
232 TADDR GetInternalAddressData(SIZE_T address) const;
233
234 // CLR loader IL Image verification - these checks apply to IL_ONLY images.
235
236 BOOL IsILOnly() const;
237 CHECK CheckILOnly() const;
238
239 void LayoutILOnly(void *base, BOOL allowFullPE = FALSE) const;
240
241 // Strong name & hashing support
242
243 BOOL HasStrongNameSignature() const;
244 CHECK CheckStrongNameSignature() const;
245 PTR_CVOID GetStrongNameSignature(COUNT_T *pSize = NULL) const;
246
247 // CorHeader flag support
248
249 // IsStrongNameSigned indicates whether the signature has been filled in.
250 // (otherwise if it has a signature it is delay signed.)
251 BOOL IsStrongNameSigned() const; // TRUE if the COMIMAGE_FLAGS_STRONGNAMESIGNED flag is set
252
253 // TLS
254
255 BOOL HasTls() const;
256 CHECK CheckTls() const;
257 PTR_VOID GetTlsRange(COUNT_T *pSize = NULL) const;
258 UINT32 GetTlsIndex() const;
259
260#ifndef FEATURE_PAL
261 // Win32 resources
262 void *GetWin32Resource(LPCWSTR lpName, LPCWSTR lpType, COUNT_T *pSize = NULL) const;
263#endif // FEATURE_PAL
264
265 // COR header fields
266
267 BOOL HasCorHeader() const;
268 CHECK CheckCorHeader() const;
269 IMAGE_COR20_HEADER *GetCorHeader() const;
270
271 PTR_CVOID GetMetadata(COUNT_T *pSize = NULL) const;
272
273 const void *GetResources(COUNT_T *pSize = NULL) const;
274 CHECK CheckResource(COUNT_T offset) const;
275 const void *GetResource(COUNT_T offset, COUNT_T *pSize = NULL) const;
276
277 BOOL HasManagedEntryPoint() const;
278 ULONG GetEntryPointToken() const;
279 IMAGE_COR_VTABLEFIXUP *GetVTableFixups(COUNT_T *pCount = NULL) const;
280
281 // Native header access
282 BOOL HasNativeHeader() const;
283 CHECK CheckNativeHeader() const;
284 CORCOMPILE_HEADER *GetNativeHeader() const;
285 BOOL IsNativeMachineFormat() const;
286 BOOL IsI386() const;
287
288 void GetPEKindAndMachine(DWORD * pdwPEKind, DWORD *pdwMachine); // Returns CorPEKind flags
289 BOOL IsPlatformNeutral(); // Returns TRUE for IL-only platform neutral images
290
291 //
292 // Verifies that the IL is within the bounds of the image.
293 //
294 CHECK CheckILMethod(RVA rva);
295
296 //
297 // Compute size of IL blob. Assumes that the IL is within the bounds of the image - make sure
298 // to call CheckILMethod before calling this method.
299 //
300 static SIZE_T ComputeILMethodSize(TADDR pIL);
301
302 // Debug directory access, returns NULL if no such entry
303 PTR_IMAGE_DEBUG_DIRECTORY GetDebugDirectoryEntry(UINT index) const;
304
305#ifdef FEATURE_PREJIT
306 CHECK CheckNativeHeaderVersion() const;
307
308 // ManagedNative fields
309 CORCOMPILE_CODE_MANAGER_ENTRY *GetNativeCodeManagerTable() const;
310 CORCOMPILE_EE_INFO_TABLE *GetNativeEEInfoTable() const;
311 void *GetNativeHelperTable(COUNT_T *pSize = NULL) const;
312 CORCOMPILE_VERSION_INFO *GetNativeVersionInfo() const;
313 CORCOMPILE_VERSION_INFO *GetNativeVersionInfoMaybeNull(bool skipCheckNativeHeader = false) const;
314 BOOL HasNativeDebugMap() const;
315 TADDR GetNativeDebugMap(COUNT_T *pSize = NULL) const;
316 Module *GetPersistedModuleImage(COUNT_T *pSize = NULL) const;
317 PCODE GetNativeHotCode(COUNT_T * pSize = NULL) const;
318 PCODE GetNativeCode(COUNT_T * pSize = NULL) const;
319 PCODE GetNativeColdCode(COUNT_T * pSize = NULL) const;
320
321 CORCOMPILE_METHOD_PROFILE_LIST *GetNativeProfileDataList(COUNT_T *pSize = NULL) const;
322 PTR_CVOID GetNativeManifestMetadata(COUNT_T *pSize = NULL) const;
323 const void *GetNativePreferredBase() const;
324 BOOL GetNativeILHasSecurityDirectory() const;
325 BOOL GetNativeILIsIbcOptimized() const;
326 BOOL GetNativeILHasReadyToRunHeader() const;
327 BOOL IsNativeILILOnly() const;
328 BOOL IsNativeILDll() const;
329 void GetNativeILPEKindAndMachine(DWORD* pdwKind, DWORD* pdwMachine) const;
330 CORCOMPILE_DEPENDENCY * GetNativeDependencies(COUNT_T *pCount = NULL) const;
331
332 PTR_CORCOMPILE_IMPORT_SECTION GetNativeImportSections(COUNT_T *pCount = NULL) const;
333 PTR_CORCOMPILE_IMPORT_SECTION GetNativeImportSectionFromIndex(COUNT_T index) const;
334 PTR_CORCOMPILE_IMPORT_SECTION GetNativeImportSectionForRVA(RVA rva) const;
335
336 TADDR GetStubsTable(COUNT_T *pSize = NULL) const;
337 TADDR GetVirtualSectionsTable(COUNT_T *pSize = NULL) const;
338#endif // FEATURE_PREJIT
339
340 BOOL HasReadyToRunHeader() const;
341 READYTORUN_HEADER *GetReadyToRunHeader() const;
342
343 void GetEXEStackSizes(SIZE_T *PE_SizeOfStackReserve, SIZE_T *PE_SizeOfStackCommit) const;
344
345 CHECK CheckWillCreateGuardPage() const;
346
347 // Native DLLMain Entrypoint
348 BOOL HasNativeEntryPoint() const;
349 void *GetNativeEntryPoint() const;
350
351#ifdef _DEBUG
352 // Stress mode for relocations
353 static BOOL GetForceRelocs();
354 static BOOL ForceRelocForDLL(LPCWSTR lpFileName);
355#endif
356
357#ifdef DACCESS_COMPILE
358 void EnumMemoryRegions(CLRDataEnumMemoryFlags flags, bool enumThis);
359#endif
360
361 protected:
362
363 // ------------------------------------------------------------
364 // Protected API for subclass use
365 // ------------------------------------------------------------
366
367 // Checking utilites
368 static CHECK CheckBounds(RVA rangeBase, COUNT_T rangeSize, RVA rva);
369 static CHECK CheckBounds(RVA rangeBase, COUNT_T rangeSize, RVA rva, COUNT_T size);
370
371 static CHECK CheckBounds(const void *rangeBase, COUNT_T rangeSize, const void *pointer);
372 static CHECK CheckBounds(PTR_CVOID rangeBase, COUNT_T rangeSize, PTR_CVOID pointer, COUNT_T size);
373
374 protected:
375
376 // Flat mapping utilities - using PointerToRawData instead of (Relative)VirtualAddress
377 IMAGE_SECTION_HEADER *RvaToSection(RVA rva) const;
378 IMAGE_SECTION_HEADER *OffsetToSection(COUNT_T fileOffset) const;
379
380 void SetRelocated();
381
382 private:
383
384 // ------------------------------------------------------------
385 // Internal functions
386 // ------------------------------------------------------------
387
388 enum METADATA_SECTION_TYPE
389 {
390 METADATA_SECTION_FULL,
391#ifdef FEATURE_PREJIT
392 METADATA_SECTION_MANIFEST
393#endif
394 };
395
396 IMAGE_DATA_DIRECTORY *GetMetaDataHelper(METADATA_SECTION_TYPE type) const;
397
398 static PTR_IMAGE_SECTION_HEADER FindFirstSection(IMAGE_NT_HEADERS * pNTHeaders);
399
400 IMAGE_NT_HEADERS *FindNTHeaders() const;
401 IMAGE_COR20_HEADER *FindCorHeader() const;
402 CORCOMPILE_HEADER *FindNativeHeader() const;
403 READYTORUN_HEADER *FindReadyToRunHeader() const;
404
405 // Flat mapping utilities
406 RVA InternalAddressToRva(SIZE_T address) const;
407
408 // NT header subchecks
409 CHECK CheckSection(COUNT_T previousAddressEnd, COUNT_T addressStart, COUNT_T addressSize,
410 COUNT_T previousOffsetEnd, COUNT_T offsetStart, COUNT_T offsetSize) const;
411
412 // Pure managed subchecks
413 CHECK CheckILOnlyImportDlls() const;
414 CHECK CheckILOnlyImportByNameTable(RVA rva) const;
415 CHECK CheckILOnlyBaseRelocations() const;
416 CHECK CheckILOnlyEntryPoint() const;
417
418 // ------------------------------------------------------------
419 // Instance members
420 // ------------------------------------------------------------
421
422 enum
423 {
424 FLAG_MAPPED = 0x01, // the file is mapped/hydrated (vs. the raw disk layout)
425 FLAG_CONTENTS = 0x02, // the file has contents
426 FLAG_RELOCATED = 0x04, // relocs have been applied
427 FLAG_NT_CHECKED = 0x10,
428 FLAG_COR_CHECKED = 0x20,
429 FLAG_IL_ONLY_CHECKED = 0x40,
430 FLAG_NATIVE_CHECKED = 0x80,
431
432 FLAG_HAS_NO_READYTORUN_HEADER = 0x100,
433 };
434
435 TADDR m_base;
436 COUNT_T m_size; // size of file on disk, as opposed to OptionalHeaders.SizeOfImage
437 ULONG m_flags;
438
439 PTR_IMAGE_NT_HEADERS m_pNTHeaders;
440 PTR_IMAGE_COR20_HEADER m_pCorHeader;
441 PTR_CORCOMPILE_HEADER m_pNativeHeader;
442 PTR_READYTORUN_HEADER m_pReadyToRunHeader;
443};
444
445//
446// MethodSectionIterator class is used to iterate hot (or) cold method section in an ngen image.
447// It can also iterate nibble maps generated by the JIT in a regular HeapList.
448//
449class MethodSectionIterator
450{
451 private:
452 PTR_DWORD m_codeTableStart;
453 PTR_DWORD m_codeTable;
454 PTR_DWORD m_codeTableEnd;
455
456 BYTE *m_code;
457
458 DWORD m_dword;
459 DWORD m_index;
460
461 BYTE *m_current;
462
463 public:
464
465 //If code is a target pointer, then GetMethodCode and FindMethodCode return
466 //target pointers. codeTable may be a pointer of either type, since it is
467 //converted internally into a host pointer.
468 MethodSectionIterator(const void *code, SIZE_T codeSize,
469 const void *codeTable, SIZE_T codeTableSize);
470 BOOL Next();
471 BYTE *GetMethodCode() { return m_current; } // Get the start of method code of the current method in the iterator
472};
473
474#include "pedecoder.inl"
475
476#endif // PEDECODER_H_
477