f4e292472312ec1c4eddf4161fce080c59e9d696
[platform/upstream/coreclr.git] / src / vm / peimage.h
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
23 class SimpleRWLock;
24 // --------------------------------------------------------------------------------
25 // Forward declarations
26 // --------------------------------------------------------------------------------
27
28 class Crst;
29 class Thread;
30
31 Thread* 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
49 struct 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
57 typedef DPTR(class PEImage)                PTR_PEImage;
58
59 class PEImage 
60 {
61     friend class PEModule;
62 public:
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
76 public:
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
91 public:
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     const 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     const BOOL HasNTHeaders();
202     const BOOL HasCorHeader(); 
203     const BOOL HasReadyToRunHeader();
204     void SetPassiveDomainOnly();
205     BOOL PassiveDomainOnly();
206     BOOL IsReferenceAssembly();
207 #ifdef FEATURE_PREJIT  
208     const BOOL IsNativeILILOnly();
209     const BOOL IsNativeILDll();
210     void GetNativeILPEKindAndMachine(DWORD* pdwKind, DWORD* pdwMachine);
211     PTR_CVOID GetNativeManifestMetadata(COUNT_T *pSize = NULL);
212 #endif
213     const BOOL HasDirectoryEntry(int entry);
214     const mdToken GetEntryPointToken();
215     const DWORD GetCorHeaderFlags(); 
216     const BOOL IsILOnly();
217     const BOOL IsDll();
218     const WORD GetSubsystem();
219     BOOL  IsFileLocked();
220     const 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
231 private:
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
294 private:
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
302 protected:
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
328 private:
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
353 public:
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
388 private:
389     DWORD m_dwPEKind;
390     DWORD m_dwMachine;
391     BOOL  m_fCachedKindAndMachine;
392
393
394
395 public:
396     void CachePEKindAndMachine();
397     void GetPEKindAndMachine(DWORD* pdwKind, DWORD* pdwMachine);
398
399 };
400
401 FORCEINLINE void PEImageRelease(PEImage *i)
402 {
403     WRAPPER_NO_CONTRACT;
404     i->Release();
405 }
406
407 typedef Wrapper<PEImage *, DoNothing, PEImageRelease> PEImageHolder;
408
409 // ================================================================================
410 // Inline definitions
411 // ================================================================================
412
413 #include "peimage.inl"
414
415 #endif  // PEIMAGE_H_