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// PEImage.h
6//
7
8// --------------------------------------------------------------------------------
9
10
11#ifndef PEIMAGE_H_
12#define PEIMAGE_H_
13
14// --------------------------------------------------------------------------------
15// Required headers
16// --------------------------------------------------------------------------------
17
18#include "clrtypes.h"
19#include "peimagelayout.h"
20#include "sstring.h"
21#include "holder.h"
22
23class SimpleRWLock;
24// --------------------------------------------------------------------------------
25// Forward declarations
26// --------------------------------------------------------------------------------
27
28class Crst;
29class Thread;
30
31Thread* GetThreadNULLOk();
32
33// --------------------------------------------------------------------------------
34// PEImage is a PE file loaded by our "simulated LoadLibrary" mechanism. A PEImage
35// can be loaded either FLAT (same layout as on disk) or MAPPED (PE sections
36// mapped into virtual addresses.)
37//
38// The MAPPED format is currently limited to "IL only" images - this can be checked
39// for via PEDecoder::IsILOnlyImage.
40//
41// NOTE: PEImage will NEVER call LoadLibrary.
42// --------------------------------------------------------------------------------
43
44
45
46#define CV_SIGNATURE_RSDS 0x53445352
47
48// CodeView RSDS debug information -> PDB 7.00
49struct CV_INFO_PDB70
50{
51 DWORD magic;
52 GUID signature; // unique identifier
53 DWORD age; // an always-incrementing value
54 char path[MAX_LONGPATH]; // zero terminated string with the name of the PDB file
55};
56
57typedef DPTR(class PEImage) PTR_PEImage;
58
59class PEImage
60{
61 friend class PEModule;
62public:
63 // ------------------------------------------------------------
64 // Public constants
65 // ------------------------------------------------------------
66
67 enum
68 {
69 LAYOUT_CREATEIFNEEDED=1
70 };
71 PTR_PEImageLayout GetLayout(DWORD imageLayoutMask,DWORD flags); //with ref
72 PTR_PEImageLayout GetLoadedLayout(); //no ref
73 BOOL IsOpened();
74 BOOL HasLoadedLayout();
75
76public:
77 // ------------------------------------------------------------
78 // Public API
79 // ------------------------------------------------------------
80
81 static void Startup();
82
83 // Normal constructed PEImages do NOT share images between calls and
84 // cannot be accessed by Get methods.
85 //
86 // DO NOT USE these unless you want a private copy-on-write mapping of
87 // the file.
88
89
90
91public:
92 ~PEImage();
93 PEImage();
94
95#ifndef DACCESS_COMPILE
96 static PTR_PEImage LoadFlat(
97 const void *flat,
98 COUNT_T size);
99#ifndef FEATURE_PAL
100 static PTR_PEImage LoadImage(
101 HMODULE hMod);
102#endif // !FEATURE_PAL
103 static PTR_PEImage OpenImage(
104 LPCWSTR pPath,
105 MDInternalImportFlags flags = MDInternalImport_Default);
106
107
108 // clones the image with new flags (this is pretty much about cached / noncached difference)
109 void Clone(MDInternalImportFlags flags, PTR_PEImage* ppImage)
110 {
111 if (GetPath().IsEmpty())
112 {
113 AddRef();
114 *ppImage = this;
115 }
116 else
117 *ppImage = PEImage::OpenImage(GetPath(), flags);
118
119 };
120
121 // pUnkResource must be one of the ICLRPrivResource* interfaces defined in CLRPrivBinding.IDL.
122 // pUnkResource will be queried for each of these to find a match and
123 static PEImage * OpenImage(
124 ICLRPrivResource * pIResource,
125 MDInternalImportFlags flags = MDInternalImport_Default);
126
127 static PTR_PEImage FindById(UINT64 uStreamAsmId, DWORD dwModuleId);
128 static PTR_PEImage FindByPath(LPCWSTR pPath);
129 static PTR_PEImage FindByShortPath(LPCWSTR pPath);
130 static PTR_PEImage FindByLongPath(LPCWSTR pPath);
131 void AddToHashMap();
132
133 void Load();
134 void SetLoadedHMODULE(HMODULE hMod);
135 void LoadNoMetaData();
136 void LoadNoFile();
137 void LoadFromMapped();
138
139 void AllocateLazyCOWPages();
140#endif
141
142 BOOL HasID();
143 ULONG GetIDHash();
144
145 PTR_CVOID GetStrongNameSignature(COUNT_T *pSize = NULL);
146
147
148 // Refcount above images.
149 ULONG AddRef();
150 ULONG Release();
151
152 // Accessors
153 const SString &GetPath();
154 BOOL IsFile();
155 HANDLE GetFileHandle();
156 void SetFileHandle(HANDLE hFile);
157 HRESULT TryOpenFile();
158
159 LPCWSTR GetPathForErrorMessages();
160
161 // Equality
162 BOOL Equals(PEImage *pImage);
163
164 void GetMVID(GUID *pMvid);
165 BOOL HasV1Metadata();
166 IMDInternalImport* GetMDImport();
167 BOOL MDImportLoaded();
168 IMDInternalImport* GetNativeMDImport(BOOL loadAllowed = TRUE);
169
170 BOOL HasContents() ;
171 BOOL HasNativeHeader() ;
172 BOOL IsPtrInImage(PTR_CVOID data);
173 CHECK CheckFormat();
174
175 // Check utilites
176 CHECK CheckILFormat();
177#ifdef FEATURE_PREJIT
178 CHECK CheckNativeFormat();
179#endif // FEATURE_PREJIT
180 static CHECK CheckCanonicalFullPath(const SString &path);
181 static CHECK CheckStartup();
182 PTR_CVOID GetMetadata(COUNT_T *pSize = NULL);
183 void GetHashedStrongNameSignature(SBuffer &result);
184
185#ifndef FEATURE_PAL
186 static void GetPathFromDll(HINSTANCE hMod, SString &result);
187#endif // !FEATURE_PAL
188 static LocaleID GetFileSystemLocale();
189 static BOOL PathEquals(const SString &p1, const SString &p2);
190 BOOL IsTrustedNativeImage(){LIMITED_METHOD_CONTRACT; return m_bIsTrustedNativeImage;};
191 void SetIsTrustedNativeImage(){LIMITED_METHOD_CONTRACT; m_bIsTrustedNativeImage=TRUE;};
192 BOOL IsNativeImageInstall(){LIMITED_METHOD_CONTRACT; return m_bIsNativeImageInstall;}
193 void SetIsNativeImageInstall(){LIMITED_METHOD_CONTRACT; m_bIsNativeImageInstall=TRUE;};
194
195 void SetModuleFileNameHintForDAC();
196#ifdef DACCESS_COMPILE
197 void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
198 const SString &GetModuleFileNameHintForDAC();
199#endif
200
201 BOOL HasNTHeaders();
202 BOOL HasCorHeader();
203 BOOL HasReadyToRunHeader();
204 void SetPassiveDomainOnly();
205 BOOL PassiveDomainOnly();
206 BOOL IsReferenceAssembly();
207#ifdef FEATURE_PREJIT
208 BOOL IsNativeILILOnly();
209 BOOL IsNativeILDll();
210 void GetNativeILPEKindAndMachine(DWORD* pdwKind, DWORD* pdwMachine);
211 PTR_CVOID GetNativeManifestMetadata(COUNT_T *pSize = NULL);
212#endif
213 BOOL HasDirectoryEntry(int entry);
214 mdToken GetEntryPointToken();
215 DWORD GetCorHeaderFlags();
216 BOOL IsILOnly();
217 BOOL IsDll();
218 WORD GetSubsystem();
219 BOOL IsFileLocked();
220 BOOL HasStrongNameSignature();
221
222 BOOL IsIbcOptimized();
223 BOOL Has32BitNTHeaders();
224
225 void VerifyIsAssembly();
226 void VerifyIsNIAssembly();
227
228
229 static void GetAll(SArray<PEImage*> &images);
230
231private:
232#ifndef DACCESS_COMPILE
233 // Get or create the layout corresponding to the mask, with an AddRef
234 PTR_PEImageLayout GetLayoutInternal(DWORD imageLayoutMask, DWORD flags);
235
236 // Create the mapped layout
237 PTR_PEImageLayout CreateLayoutMapped();
238
239 // Create the flat layout
240 PTR_PEImageLayout CreateLayoutFlat(BOOL bPermitWriteableSections);
241#endif
242 // Get an existing layout corresponding to the mask, no AddRef
243 PTR_PEImageLayout GetExistingLayoutInternal(DWORD imageLayoutMask);
244
245 void OpenMDImport();
246 void OpenNativeMDImport();
247 // ------------------------------------------------------------
248 // Private routines
249 // ------------------------------------------------------------
250
251 void Init(LPCWSTR pPath);
252 void Init(IStream* pStream, UINT64 uStreamAsmId,
253 DWORD dwModuleId, BOOL resourceFile);
254
255 void VerifyIsILOrNIAssembly(BOOL fIL);
256
257 struct PEImageLocator
258 {
259
260 LPCWSTR m_pPath;
261
262 PEImageLocator(LPCWSTR pPath)
263 : m_pPath(pPath)
264 {
265 }
266
267 PEImageLocator(PEImage * pImage)
268 : m_pPath(pImage->m_path.GetUnicode())
269 {
270 }
271 };
272
273 static BOOL CompareImage(UPTR image1, UPTR image2);
274 static BOOL CompareIJWDataBase(UPTR base, UPTR mapping);
275
276 void DECLSPEC_NORETURN ThrowFormat(HRESULT hr);
277
278 static CHECK CheckLayoutFormat(PEDecoder *pe);
279
280 // ------------------------------------------------------------
281 // Instance members
282 // ------------------------------------------------------------
283
284 SString m_path;
285 LONG m_refCount;
286
287 // This variable will have the data of module name.
288 // It is only used by DAC to remap fusion loaded modules back to
289 // disk IL. This really is a workaround. The real fix is for fusion loader
290 // hook (public API on hosting) to take an additional file name hint.
291 // We are piggy backing on the fact that module name is the same as file name!!!
292 //
293 SString m_sModuleFileNameHintUsedByDac; // This is only used by DAC
294private:
295 BOOL m_bIsTrustedNativeImage;
296 BOOL m_bIsNativeImageInstall;
297 BOOL m_bPassiveDomainOnly;
298#ifdef FEATURE_LAZY_COW_PAGES
299 BOOL m_bAllocatedLazyCOWPages;
300#endif // FEATURE_LAZY_COW_PAGES
301
302protected:
303
304 enum
305 {
306 IMAGE_FLAT=0,
307 IMAGE_MAPPED=1,
308 IMAGE_LOADED=2,
309 IMAGE_COUNT=3
310 };
311
312 SimpleRWLock *m_pLayoutLock;
313 PTR_PEImageLayout m_pLayouts[IMAGE_COUNT] ;
314 BOOL m_bInHashMap;
315#ifndef DACCESS_COMPILE
316 void SetLayout(DWORD dwLayout, PTR_PEImageLayout pLayout);
317#endif // DACCESS_COMPILE
318
319
320#ifdef METADATATRACKER_DATA
321 class MetaDataTracker *m_pMDTracker;
322#endif // METADATATRACKER_DATA
323
324 IMDInternalImport* m_pMDImport;
325 IMDInternalImport* m_pNativeMDImport;
326
327
328private:
329
330
331 // ------------------------------------------------------------
332 // Static members
333 // ------------------------------------------------------------
334
335 static CrstStatic s_hashLock;
336
337 static PtrHashMap *s_Images;
338
339 HANDLE m_hFile;
340 bool m_bOwnHandle;
341
342 BOOL m_bSignatureInfoCached;
343 HRESULT m_hrSignatureInfoStatus;
344 DWORD m_dwSignatureInfo;
345
346 //@TODO:workaround: Remove this when we have one PEImage per mapped image,
347 //@TODO:workaround: and move the lock there
348 // This is for IJW thunk initialization, as it is no longer guaranteed
349 // that the initialization will occur under the loader lock.
350 static CrstStatic s_ijwHashLock;
351 static PtrHashMap *s_ijwFixupDataHash;
352
353public:
354 class IJWFixupData
355 {
356 private:
357 Crst m_lock;
358 void *m_base;
359 DWORD m_flags;
360 PTR_LoaderHeap m_DllThunkHeap;
361
362 // the fixup for the next iteration in FixupVTables
363 // we use it to make sure that we do not try to fix up the same entry twice
364 // if there was a pass that was aborted in the middle
365 COUNT_T m_iNextFixup;
366 COUNT_T m_iNextMethod;
367
368 enum {
369 e_FIXED_UP = 0x1
370 };
371
372 public:
373 IJWFixupData(void *pBase);
374 ~IJWFixupData();
375 void *GetBase() { LIMITED_METHOD_CONTRACT; return m_base; }
376 Crst *GetLock() { LIMITED_METHOD_CONTRACT; return &m_lock; }
377 BOOL IsFixedUp() { LIMITED_METHOD_CONTRACT; return m_flags & e_FIXED_UP; }
378 void SetIsFixedUp() { LIMITED_METHOD_CONTRACT; m_flags |= e_FIXED_UP; }
379 PTR_LoaderHeap GetThunkHeap();
380 void MarkMethodFixedUp(COUNT_T iFixup, COUNT_T iMethod);
381 BOOL IsMethodFixedUp(COUNT_T iFixup, COUNT_T iMethod);
382 };
383
384 static IJWFixupData *GetIJWData(void *pBase);
385 static PTR_LoaderHeap GetDllThunkHeap(void *pBase);
386 static void UnloadIJWModule(void *pBase);
387
388private:
389 DWORD m_dwPEKind;
390 DWORD m_dwMachine;
391 BOOL m_fCachedKindAndMachine;
392
393
394
395public:
396 void CachePEKindAndMachine();
397 void GetPEKindAndMachine(DWORD* pdwKind, DWORD* pdwMachine);
398
399};
400
401FORCEINLINE void PEImageRelease(PEImage *i)
402{
403 WRAPPER_NO_CONTRACT;
404 i->Release();
405}
406
407typedef Wrapper<PEImage *, DoNothing, PEImageRelease> PEImageHolder;
408
409// ================================================================================
410// Inline definitions
411// ================================================================================
412
413#include "peimage.inl"
414
415#endif // PEIMAGE_H_
416