summaryrefslogtreecommitdiff
path: root/src/vm/pefile.h
blob: 421297303c67a3a86e09290f7694db637d406e90 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// --------------------------------------------------------------------------------
// PEFile.h
// 

// --------------------------------------------------------------------------------


#ifndef PEFILE_H_
#define PEFILE_H_

// --------------------------------------------------------------------------------
// Required headers
// --------------------------------------------------------------------------------

#include <windef.h>

#include <corpolicy.h>
#include "sstring.h"
#include "peimage.h"
#include "metadata.h"
#include "corhlpr.h"
#include "utilcode.h"
#include "loaderheap.h"
#include "sstring.h"
#include "ex.h"
#include "assemblyspecbase.h"
#include "eecontract.h"
#include "metadatatracker.h"
#include "stackwalktypes.h"
#include <specstrings.h>
#include "slist.h"
#include "corperm.h"
#include "eventtrace.h"

#include "clrprivbinderutil.h"

// --------------------------------------------------------------------------------
// Forward declared classes
// --------------------------------------------------------------------------------

class Module;
class EditAndContinueModule;

class PEFile;
class PEModule;
class PEAssembly;
class SimpleRWLock;

class CLRPrivBinderLoadFile;

typedef VPTR(PEModule) PTR_PEModule;
typedef VPTR(PEAssembly) PTR_PEAssembly;

// --------------------------------------------------------------------------------
// Types
// --------------------------------------------------------------------------------

// --------------------------------------------------------------------------------
// A PEFile is an input to the CLR loader.  It is produced as a result of 
// binding, usually through fusion (although there are a few less common methods to 
// obtain one which do not go through fusion, e.g. IJW loads)
//
// Although a PEFile is usually a disk based PE file (hence the name), it is not 
// always the case. Thus it is a conscious decision to not export access to the PE
// file directly; rather the specific information required should be provided via
// individual query API.
//
// There are multiple "flavors" of PEFiles:
//
// 1. HMODULE - these PE Files are loaded in response to "spontaneous" OS callbacks.
//    These should only occur for .exe main modules and IJW dlls loaded via LoadLibrary
//    or static imports in umnanaged code.
//
// 2. Fusion loads - these are the most common case.  A path is obtained from fusion and
//    the result is loaded via PEImage.
//      a. Display name loads - these are metadata-based binds
//      b. Path loads - these are loaded from an explicit path
//
// 3. Byte arrays - loaded explicitly by user code.  These also go through PEImage.
//
// 4. Dynamic - these are not actual PE images at all, but are placeholders
//    for reflection-based modules.
//
// PEFiles are segmented into two subtypes: PEAssembly and PEModule.  The formere
// is a file to be loaded as an assembly, and the latter is to be loaded as a module.
// 
// See also file:..\inc\corhdr.h#ManagedHeader for more on the format of managed images.
// See code:Module for more on modules 
// --------------------------------------------------------------------------------

typedef VPTR(class PEFile) PTR_PEFile;

typedef ReleaseHolder<IMDInternalImport> IMDInternalImportHolder;

class PEFile
{
    // ------------------------------------------------------------
    // SOS support
    // ------------------------------------------------------------
    VPTR_BASE_CONCRETE_VTABLE_CLASS(PEFile)

public:

    // ------------------------------------------------------------
    // Public API
    // ------------------------------------------------------------

    STDMETHOD_(ULONG, AddRef)();
    STDMETHOD_(ULONG, Release)();

#ifdef DACCESS_COMPILE
    virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
#endif

#if CHECK_INVARIANTS
    CHECK Invariant();
#endif

private:
    // ------------------------------------------------------------
    // Loader access API
    // ------------------------------------------------------------

    friend class DomainFile;
    friend class PEModule;
#ifdef DACCESS_COMPILE
    friend class NativeImageDumper;
#endif

    // Load actually triggers loading side effects of the module.  This should ONLY
    // be done after validation has been passed
    BOOL CanLoadLibrary();
public:
    void LoadLibrary(BOOL allowNativeSkip = TRUE);


private:
    void CheckForDisallowedInProcSxSLoadWorker();
    void ValidateImagePlatformNeutrality();

    // For use inside LoadLibrary callback
    friend HRESULT ExecuteDLLForAttach(HINSTANCE hInst,
                                       DWORD dwReason,
                                       LPVOID lpReserved,
                                       BOOL fFromThunk);
    void SetLoadedHMODULE(HMODULE hMod);

    BOOL HasSkipVerification();
    void SetSkipVerification();

    // DO NOT USE !!! this is to be removed when we move to new fusion binding API
    friend class DomainAssembly;

    // Helper for creating metadata for CreateDynamic
    friend class Assembly;
    friend class COMDynamicWrite;
    friend class AssemblyNative;
    static void DefineEmitScope(
        GUID   iid, 
        void **ppEmit);

protected:
    IMDInternalImportHolder GetMDImport();

public:
    // ------------------------------------------------------------
    // Generic PEFile - can be used to access metadata
    // ------------------------------------------------------------
    
    static PEFile *Open(PEImage *image);

    // ------------------------------------------------------------
    // Identity
    // ------------------------------------------------------------

#ifndef DACCESS_COMPILE
    BOOL Equals(PEFile *pFile);
    BOOL Equals(PEImage *pImage);
#endif // DACCESS_COMPILE


    void GetMVID(GUID *pMvid);

    // ------------------------------------------------------------
    // Descriptive strings
    // ------------------------------------------------------------

    // Path is the file path to the file; empty if not a file
    const SString &GetPath();

#ifdef DACCESS_COMPILE
    // This is the metadata module name. Used as a hint as file name. 
    const SString &GetModuleFileNameHint();
#endif // DACCESS_COMPILE

    // Full name is the most descriptive name available (path, codebase, or name as appropriate)
    void GetCodeBaseOrName(SString &result);
    
    // Returns security information for the assembly based on the codebase
    void GetSecurityIdentity(SString &codebase, SecZone *pdwZone, DWORD dwFlags, BYTE *pbUniqueID, DWORD *pcbUniqueID);
    void InitializeSecurityManager();

#ifdef LOGGING
    // This is useful for log messages
    LPCWSTR GetDebugName();
#endif

    // ------------------------------------------------------------
    // Checks
    // ------------------------------------------------------------

    CHECK CheckLoaded(BOOL allowNativeSkip = TRUE);
    void ValidateForExecution();
    BOOL IsMarkedAsNoPlatform();
    BOOL IsMarkedAsContentTypeWindowsRuntime();


    // ------------------------------------------------------------
    // Classification
    // ------------------------------------------------------------

    BOOL IsAssembly() const;
    PTR_PEAssembly AsAssembly();
    BOOL IsModule() const;
    PTR_PEModule AsModule();
    BOOL IsSystem() const;
    BOOL IsDynamic() const;
    BOOL IsResource() const;
    BOOL IsIStream() const;
    BOOL IsIntrospectionOnly() const;
    // Returns self (if assembly) or containing assembly (if module)
    PEAssembly *GetAssembly() const;

    // ------------------------------------------------------------
    // Hash support
    // ------------------------------------------------------------

#ifndef DACCESS_COMPILE
    void GetImageBits(SBuffer &result);
    void GetHash(ALG_ID algorithm, SBuffer &result);
#endif // DACCESS_COMPILE

    void GetSHA1Hash(SBuffer &result);
    CHECK CheckHash(ALG_ID algorithm, const void *hash, COUNT_T size);

    // ------------------------------------------------------------
    // Metadata access
    // ------------------------------------------------------------

    BOOL HasMetadata();

    IMDInternalImport *GetPersistentMDImport();
    IMDInternalImport *GetMDImportWithRef();    
    void MakeMDImportPersistent() {m_bHasPersistentMDImport=TRUE;};

#ifndef DACCESS_COMPILE
    IMetaDataEmit *GetEmitter();
    IMetaDataAssemblyEmit *GetAssemblyEmitter();
    IMetaDataImport2 *GetRWImporter();
    IMetaDataAssemblyImport *GetAssemblyImporter();
#else
    TADDR GetMDInternalRWAddress();
#endif // DACCESS_COMPILE

    LPCUTF8 GetSimpleName();
    HRESULT GetScopeName(LPCUTF8 * pszName);
    BOOL IsStrongNameVerified();
    BOOL IsStrongNamed();
    const void *GetPublicKey(DWORD *pcbPK);
    ULONG GetHashAlgId();
    HRESULT GetVersion(USHORT *pMajor, USHORT *pMinor, USHORT *pBuild, USHORT *pRevision);
    LPCSTR GetLocale();
    DWORD GetFlags();
    HRESULT GetFlagsNoTrigger(DWORD * pdwFlags);
    // ------------------------------------------------------------
    // PE file access
    // ------------------------------------------------------------

    BOOL HasSecurityDirectory();
    BOOL IsIbcOptimized();
    BOOL IsILImageReadyToRun();
    WORD GetSubsystem();
    mdToken GetEntryPointToken(
#ifdef _DEBUG        
        BOOL bAssumeLoaded = FALSE
#endif //_DEBUG               
        );
    BOOL IsILOnly();
    BOOL IsDll();

    TADDR GetIL(RVA il);

    PTR_VOID GetRvaField(RVA field);
    CHECK CheckRvaField(RVA field);
    CHECK CheckRvaField(RVA field, COUNT_T size);

    PCCOR_SIGNATURE GetSignature(RVA signature);
    RVA GetSignatureRva(PCCOR_SIGNATURE signature);
    CHECK CheckSignature(PCCOR_SIGNATURE signature);
    CHECK CheckSignatureRva(RVA signature);

    BOOL HasTls();
    BOOL IsRvaFieldTls(RVA field);
    UINT32 GetFieldTlsOffset(RVA field);
    UINT32 GetTlsIndex();

    const void *GetInternalPInvokeTarget(RVA target);
    CHECK CheckInternalPInvokeTarget(RVA target);

    IMAGE_COR_VTABLEFIXUP *GetVTableFixups(COUNT_T *pCount = NULL);
    void *GetVTable(RVA rva);

    BOOL GetResource(LPCSTR szName, DWORD *cbResource,
                     PBYTE *pbInMemoryResource, DomainAssembly** pAssemblyRef,
                     LPCSTR *szFileName, DWORD *dwLocation, 
                     StackCrawlMark *pStackMark, BOOL fSkipSecurityCheck,
                     BOOL fSkipRaiseResolveEvent, DomainAssembly* pDomainAssembly,
                     AppDomain* pAppDomain);
#ifndef DACCESS_COMPILE
    PTR_CVOID GetMetadata(COUNT_T *pSize);
#endif
    PTR_CVOID GetLoadedMetadata(COUNT_T *pSize);

    void GetPEKindAndMachine(DWORD* pdwKind, DWORD* pdwMachine);

    ULONG GetILImageTimeDateStamp();


    // ------------------------------------------------------------
    // Image memory access
    //
    // WARNING: do not abuse these.  There are scenarios where the image
    // is not in memory as an optimization.  
    //
    // In general, you should add an entry point to get the specific info 
    // you are interested in, rather than using these general purpose 
    // entry points.  The info can then be extracted from the native image
    // in the no-IL image case.
    // ------------------------------------------------------------

    // For IJW purposes only - this asserts that we have an IJW image.
    HMODULE GetIJWBase();

    // The debugger can tolerate a null value here for native only loading cases
    PTR_VOID GetDebuggerContents(COUNT_T *pSize = NULL);

#ifndef DACCESS_COMPILE
    // Returns the IL image range; may force a LoadLibrary
    const void *GetManagedFileContents(COUNT_T *pSize = NULL);
#endif // DACCESS_COMPILE

    PTR_CVOID GetLoadedImageContents(COUNT_T *pSize = NULL);
    
    // SetInProcSxSLoadVerified can run concurrently as we don't hold locks during LoadLibrary but
    // it is the only flag that can be set during this phase so no mutual exclusion is necessary.
    void SetInProcSxSLoadVerified() { LIMITED_METHOD_CONTRACT; m_flags |= PEFILE_SXS_LOAD_VERIFIED; }
    BOOL IsInProcSxSLoadVerified() { LIMITED_METHOD_CONTRACT; return m_flags & PEFILE_SXS_LOAD_VERIFIED; }

    // ------------------------------------------------------------
    // Native image access
    // ------------------------------------------------------------

    // Does the loader support using a native image for this file?
    // Some implementation restrictions prevent native images from being used
    // in some cases.
#ifdef FEATURE_PREJIT 
    BOOL CanUseNativeImage() { LIMITED_METHOD_CONTRACT; return m_fCanUseNativeImage; }
    void SetCannotUseNativeImage() { LIMITED_METHOD_CONTRACT; m_fCanUseNativeImage = FALSE; }
    void SetNativeImageUsedExclusively() { LIMITED_METHOD_CONTRACT; m_flags|=PEFILE_NATIVE_IMAGE_USED_EXCLUSIVELY; }
    BOOL IsNativeImageUsedExclusively() { LIMITED_METHOD_CONTRACT; return m_flags&PEFILE_NATIVE_IMAGE_USED_EXCLUSIVELY; }
    void SetSafeToHardBindTo() { LIMITED_METHOD_CONTRACT; m_flags|=PEFILE_SAFE_TO_HARDBINDTO; }
    BOOL IsSafeToHardBindTo() { LIMITED_METHOD_CONTRACT; return m_flags&PEFILE_SAFE_TO_HARDBINDTO; }

    BOOL IsNativeLoaded();
    PEImage *GetNativeImageWithRef();
    PEImage *GetPersistentNativeImage();
#endif
    BOOL HasNativeImage();
    PTR_PEImageLayout GetLoaded();
    PTR_PEImageLayout GetLoadedNative();
    PTR_PEImageLayout GetLoadedIL();    
    PTR_PEImageLayout GetAnyILWithRef();        //AddRefs!
    IStream * GetPdbStream();       
    void ClearPdbStream();
    BOOL IsLoaded(BOOL bAllowNativeSkip=TRUE) ;
    BOOL PassiveDomainOnly();
    BOOL IsPtrInILImage(PTR_CVOID data);

#ifdef DACCESS_COMPILE    
    PEImage *GetNativeImage()
    {
        LIMITED_METHOD_DAC_CONTRACT;
#ifdef FEATURE_PREJIT 
        return m_nativeImage;
#else
        return NULL;
#endif
    }
#endif

#ifdef FEATURE_PREJIT 
    // ------------------------------------------------------------
    // Native image config utilities
    // ------------------------------------------------------------

    static CorCompileConfigFlags GetNativeImageConfigFlags(BOOL fForceDebug = FALSE,
                                                           BOOL fForceProfiling = FALSE,
                                                           BOOL fForceInstrument = FALSE);
    
    static CorCompileConfigFlags GetNativeImageConfigFlagsWithOverrides();

#ifdef DEBUGGING_SUPPORTED
    static void SetNGENDebugFlags(BOOL fAllowOpt);
    static void GetNGENDebugFlags(BOOL *fAllowOpt);
#endif

#ifdef FEATURE_TREAT_NI_AS_MSIL_DURING_DIAGNOSTICS
    static BOOL ShouldTreatNIAsMSIL();
#endif // FEATURE_TREAT_NI_AS_MSIL_DURING_DIAGNOSTICS
            
#endif  // FEATURE_PREJIT

    // ------------------------------------------------------------
    // Resource access
    // ------------------------------------------------------------

    void GetEmbeddedResource(DWORD dwOffset, DWORD *cbResource, PBYTE *pbInMemoryResource);

    // ------------------------------------------------------------
    // File loading
    // ------------------------------------------------------------

    PEAssembly * LoadAssembly(
            mdAssemblyRef       kAssemblyRef, 
            IMDInternalImport * pImport = NULL, 
            LPCUTF8             szWinRtTypeNamespace = NULL, 
            LPCUTF8             szWinRtTypeClassName = NULL);

    // ------------------------------------------------------------
    // Logging
    // ------------------------------------------------------------

    // The format string is intentionally unicode to avoid globalization bugs
#ifdef FEATURE_PREJIT
    void ExternalLog(DWORD facility, DWORD level, const WCHAR *fmt, ...) DAC_EMPTY();
    void ExternalLog(DWORD level, const WCHAR *fmt, ...) DAC_EMPTY();
    void ExternalLog(DWORD level, const char *msg) DAC_EMPTY();
    virtual void ExternalVLog(DWORD facility, DWORD level, const WCHAR *fmt, va_list args) DAC_EMPTY();
    virtual void FlushExternalLog() DAC_EMPTY();
#endif

protected:
    // ------------------------------------------------------------
    // Internal constants
    // ------------------------------------------------------------

    enum
    { 
        PEFILE_SYSTEM                 = 0x01,
        PEFILE_ASSEMBLY               = 0x02,
        PEFILE_MODULE                 = 0x04,
        PEFILE_SKIP_VERIFICATION      = 0x08,
        PEFILE_SKIP_MODULE_HASH_CHECKS= 0x10,
        PEFILE_ISTREAM                = 0x100,
#ifdef FEATURE_PREJIT        
        PEFILE_HAS_NATIVE_IMAGE_METADATA = 0x200,
        PEFILE_NATIVE_IMAGE_USED_EXCLUSIVELY =0x1000,
        PEFILE_SAFE_TO_HARDBINDTO     = 0x4000, // NGEN-only flag
#endif        
        PEFILE_INTROSPECTIONONLY      = 0x400,
        PEFILE_SXS_LOAD_VERIFIED      = 0x2000
    };

    // ------------------------------------------------------------
    // Internal routines
    // ------------------------------------------------------------

#ifndef DACCESS_COMPILE
    PEFile(PEImage *image, BOOL fCheckAuthenticodeSignature = TRUE);
    virtual ~PEFile();

    virtual void ReleaseIL();
#else    
    virtual ~PEFile() {}
#endif

    void OpenMDImport();
    void RestoreMDImport(IMDInternalImport* pImport);
    void OpenMDImport_Unsafe();
    void OpenImporter();
    void OpenAssemblyImporter();
    void OpenEmitter();
    void OpenAssemblyEmitter();

    void ConvertMDInternalToReadWrite();
    void ReleaseMetadataInterfaces(BOOL bDestructor, BOOL bKeepNativeData=FALSE);


    friend class Module;
#ifdef FEATURE_PREJIT
    void SetNativeImage(PEImage *nativeImage);
#ifndef DACCESS_COMPILE
    virtual void ClearNativeImage();
#endif
#endif

#ifndef DACCESS_COMPILE
    void EnsureImageOpened();
#endif // DACCESS_COMPILE

    friend class ClrDataAccess;
    BOOL HasNativeImageMetadata();

    // ------------------------------------------------------------
    // Instance fields
    // ------------------------------------------------------------
    
#ifdef _DEBUG
    LPCWSTR                 m_pDebugName;
    SString                 m_debugName;
#endif
    
    // Identity image
    PTR_PEImage              m_identity;
    // IL image, NULL if we didn't need to open the file
    PTR_PEImage              m_openedILimage;
#ifdef FEATURE_PREJIT
    // Native image
    PTR_PEImage              m_nativeImage;

    BOOL                     m_fCanUseNativeImage;
#endif
    // This flag is not updated atomically with m_pMDImport. Its fine for debugger usage
    // but don't rely on it in the runtime. In runtime try QI'ing the m_pMDImport for 
    // IID_IMDInternalImportENC
    BOOL                     m_MDImportIsRW_Debugger_Use_Only;
    Volatile<BOOL>           m_bHasPersistentMDImport;
    
#ifndef DACCESS_COMPILE
    IMDInternalImport       *m_pMDImport;
#else
    IMDInternalImport       *m_pMDImport_UseAccessor;
#endif
    IMetaDataImport2        *m_pImporter;
    IMetaDataEmit           *m_pEmitter;
    SimpleRWLock            *m_pMetadataLock;
    Volatile<LONG>           m_refCount;
    SBuffer                 *m_hash;                   // cached SHA1 hash value
    int                     m_flags;
    BOOL                    m_fStrongNameVerified;

#ifdef DEBUGGING_SUPPORTED
#ifdef FEATURE_PREJIT
    SVAL_DECL(DWORD, s_NGENDebugFlags);
#endif
#endif
public:

    PTR_PEImage GetILimage()
    {
        CONTRACTL
        {
            THROWS;
            MODE_ANY;
            GC_TRIGGERS;
        }
        CONTRACTL_END;
#ifndef DACCESS_COMPILE
        if (m_openedILimage == NULL && m_identity != NULL)
        {
            PEImage* pOpenedILimage;
            m_identity->Clone(MDInternalImport_Default,&pOpenedILimage);
            if (InterlockedCompareExchangeT(&m_openedILimage,pOpenedILimage,NULL) != NULL)
                pOpenedILimage->Release();
        }
#endif
        return m_openedILimage;
    }

    PEImage *GetOpenedILimage()
    {
        LIMITED_METHOD_DAC_CONTRACT;
        _ASSERTE(HasOpenedILimage());
        return m_openedILimage;
    }


    BOOL HasOpenedILimage()
    {
        LIMITED_METHOD_DAC_CONTRACT;
        return m_openedILimage != NULL;

    }

    BOOL HasLoadedIL()
    {
        LIMITED_METHOD_DAC_CONTRACT;
        return HasOpenedILimage() &&  GetOpenedILimage()->HasLoadedLayout();
    }

    BOOL IsDesignerBindingContext()
    {
        LIMITED_METHOD_CONTRACT;

        DWORD binderFlags = BINDER_NONE;

        HRESULT hr = E_FAIL;
        if (HasHostAssembly())
            hr = GetHostAssembly()->GetBinderFlags(&binderFlags);

        return hr == S_OK ? binderFlags & BINDER_DESIGNER_BINDING_CONTEXT : FALSE;
    }

    LPCWSTR GetPathForErrorMessages();

    static PEFile* Dummy();
    void MarkNativeImageInvalidIfOwned();
    void ConvertMetadataToRWForEnC();

protected:
    PTR_ICLRPrivAssembly m_pHostAssembly;

    // For certain assemblies, we do not have m_pHostAssembly since they are not bound using an actual binder.
    // An example is Ref-Emitted assemblies. Thus, when such assemblies trigger load of their dependencies, 
    // we need to ensure they are loaded in appropriate load context.
    //
    // To enable this, we maintain a concept of "Fallback LoadContext", which will be set to the Binder of the
    // assembly that created the dynamic assembly. If the creator assembly is dynamic itself, then its fallback
    // load context would be propagated to the assembly being dynamically generated.
    ICLRPrivBinder *m_pFallbackLoadContextBinder;

protected:

#ifndef DACCESS_COMPILE
    void SetHostAssembly(ICLRPrivAssembly * pHostAssembly)
    { LIMITED_METHOD_CONTRACT; m_pHostAssembly = clr::SafeAddRef(pHostAssembly); }
#endif //DACCESS_COMPILE

public:
    // Returns a non-AddRef'ed ICLRPrivAssembly*
    PTR_ICLRPrivAssembly GetHostAssembly()
    { 
        STATIC_CONTRACT_LIMITED_METHOD; 
        return m_pHostAssembly; 
    }

    // Returns the ICLRPrivBinder* instance associated with the PEFile
    PTR_ICLRPrivBinder GetBindingContext();
    
    bool HasHostAssembly()
    { STATIC_CONTRACT_WRAPPER; return GetHostAssembly() != nullptr; }

    bool CanUseWithBindingCache()
    { LIMITED_METHOD_CONTRACT; return !HasHostAssembly(); }

    void SetFallbackLoadContextBinder(ICLRPrivBinder *pFallbackLoadContextBinder)
    { 
        LIMITED_METHOD_CONTRACT; 
        m_pFallbackLoadContextBinder = pFallbackLoadContextBinder; 
    }

    ICLRPrivBinder *GetFallbackLoadContextBinder()
    {
        LIMITED_METHOD_CONTRACT;

        return m_pFallbackLoadContextBinder;
    }
};  // class PEFile


class PEAssembly : public PEFile
{ 
    VPTR_VTABLE_CLASS(PEAssembly, PEFile)

  public:
    // ------------------------------------------------------------
    // Statics initialization.
    // ------------------------------------------------------------
    static
    void Attach();

    // ------------------------------------------------------------
    // Public API
    // ------------------------------------------------------------

    // CoreCLR's PrivBinder PEAssembly creation entrypoint
    static PEAssembly * Open(
        PEAssembly *       pParent,
        PEImage *          pPEImageIL, 
        PEImage *          pPEImageNI, 
        ICLRPrivAssembly * pHostAssembly, 
        BOOL               fIsIntrospectionOnly = FALSE);

    // This opens the canonical mscorlib.dll
    static PEAssembly *OpenSystem(IUnknown *pAppCtx);
#ifdef DACCESS_COMPILE
    virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
#endif

    static PEAssembly *Open(
        CoreBindResult* pBindResult,
        BOOL isSystem,
        BOOL isIntrospectionOnly);

    static PEAssembly *Create(
        PEAssembly *pParentAssembly,
        IMetaDataAssemblyEmit *pEmit,
        BOOL isIntrospectionOnly);

    static PEAssembly *OpenMemory(
        PEAssembly *pParentAssembly,
        const void *flat,
        COUNT_T size, 
        BOOL isIntrospectionOnly = FALSE,
        CLRPrivBinderLoadFile* pBinderToUse = NULL);

    static PEAssembly *DoOpenMemory(
        PEAssembly *pParentAssembly,
        const void *flat,
        COUNT_T size,
        BOOL isIntrospectionOnly,
        CLRPrivBinderLoadFile* pBinderToUse);

  private:
    // Private helpers for crufty exception handling reasons
    static PEAssembly *DoOpenSystem(IUnknown *pAppCtx);

  public:

    // ------------------------------------------------------------
    // binding & source
    // ------------------------------------------------------------

    BOOL IsSourceGAC();
    BOOL IsProfileAssembly();

    ULONG HashIdentity();

#ifndef  DACCESS_COMPILE
    virtual void ReleaseIL();
#endif

    // ------------------------------------------------------------
    // Hash support
    // ------------------------------------------------------------

    BOOL NeedsModuleHashChecks();

    BOOL HasStrongNameSignature();
    BOOL IsFullySigned();

    void SetStrongNameBypassed();
    void VerifyStrongName();

    // ------------------------------------------------------------
    // Descriptive strings
    // ------------------------------------------------------------

    // This returns a non-empty path representing the source of the assembly; it may 
    // be the parent assembly for dynamic or memory assemblies
    const SString &GetEffectivePath();

    // Codebase is the fusion codebase or path for the assembly.  It is in URL format.
    // Note this may be obtained from the parent PEFile if we don't have a path or fusion
    // assembly.
    //
    // fCopiedName means to get the "shadow copied" path rather than the original path, if applicable
    void GetCodeBase(SString &result, BOOL fCopiedName = FALSE);
    // Get the fully qualified assembly name from its metadata token 
    static void GetFullyQualifiedAssemblyName(IMDInternalImport* pImport, mdAssembly mda, SString &result, DWORD flags = 0); 
    
    // Display name is the fusion binding name for an assembly
    void GetDisplayName(SString &result, DWORD flags = 0);

    // ------------------------------------------------------------
    // Metadata access
    // ------------------------------------------------------------

    LPCUTF8 GetSimpleName();

    // ------------------------------------------------------------
    // Utility functions
    // ------------------------------------------------------------

    static void PathToUrl(SString &string);
    static void UrlToPath(SString &string);
    static BOOL FindLastPathSeparator(const SString &path, SString::Iterator &i);

    // ------------------------------------------------------------
    // Logging
    // ------------------------------------------------------------
#ifdef FEATURE_PREJIT
    void ExternalVLog(DWORD facility, DWORD level, const WCHAR *fmt, va_list args) DAC_EMPTY();
    void FlushExternalLog() DAC_EMPTY();
#endif


  protected:

#ifndef DACCESS_COMPILE
    PEAssembly(
        CoreBindResult* pBindResultInfo, 
        IMetaDataEmit *pEmit,
        PEFile *creator, 
        BOOL system, 
        BOOL introspectionOnly = FALSE,
        PEImage * pPEImageIL = NULL,
        PEImage * pPEImageNI = NULL,
        ICLRPrivAssembly * pHostAssembly = NULL
        );
    virtual ~PEAssembly();
#endif

    // ------------------------------------------------------------
    // Loader access API
    // ------------------------------------------------------------

    friend class DomainAssembly;
#ifdef FEATURE_PREJIT

    void SetNativeImage(PEImage *image);

    BOOL CheckNativeImageVersion(PEImage *image);



#endif  // FEATURE_PREJIT

  private:
    // Check both the StrongName and Authenticode signature of an assembly. If the application is using
    // strong name bypass, then this call may not result in a strong name verificaiton. VerifyStrongName
    // should be called if a strong name must be forced to verify.
    void DoLoadSignatureChecks();


  private:
    // ------------------------------------------------------------
    // Instance fields
    // ------------------------------------------------------------

    PTR_PEFile               m_creator;
    BOOL m_bIsFromGAC;
    BOOL m_bIsOnTpaList;
    // Using a separate entry and not m_pHostAssembly because otherwise
    // HasHostAssembly becomes true that trips various other code paths resulting in bad
    // things
    SString                  m_sTextualIdentity;
    int                      m_fProfileAssembly; // Tri-state cache

  public:
    PTR_PEFile GetCreator()
    { LIMITED_METHOD_CONTRACT; return m_creator; }

    // Returns TRUE if the assembly is .winmd file (WinRT assembly)
    bool IsWindowsRuntime();
    
    // Used to determine if this assembly has an identity that may be used for
    // binding purposes. Currently this is true for standard .NET assemblies
    // and false for WinRT assemblies (where assemblies are identified by their
    // member types).
    bool HasBindableIdentity();

    // Indicates if the assembly can be cached in a binding cache such as AssemblySpecBindingCache.
    inline bool CanUseWithBindingCache()
    {
            STATIC_CONTRACT_WRAPPER;
            return (HasBindableIdentity());
    }
};

#ifdef FEATURE_MULTIMODULE_ASSEMBLIES

class PEModule : public PEFile
{
    VPTR_VTABLE_CLASS(PEModule, PEFile)
    
  public:

    // ------------------------------------------------------------
    // Public API
    // ------------------------------------------------------------

    static PEModule *Open(PEAssembly *assembly, mdFile token,
                          const SString &fileName);

    static PEModule *OpenMemory(PEAssembly *assembly, mdFile kToken,
                                const void *flat, COUNT_T size); 

    static PEModule *Create(PEAssembly *assembly, mdFile kToken, IMetaDataEmit *pEmit);

#ifdef DACCESS_COMPILE
    virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
#endif

  private:
    // Private helpers for crufty exception handling reasons
    static PEModule *DoOpen(PEAssembly *assembly, mdFile token,
                            const SString &fileName);

    static PEModule *DoOpenMemory(PEAssembly *assembly, mdFile kToken,
                                  const void *flat, COUNT_T size); 
  public:

    // ------------------------------------------------------------
    // Metadata access
    // ------------------------------------------------------------

    PEAssembly *GetAssembly();
    mdFile GetToken();
    BOOL IsResource();
    BOOL IsIStream();
    LPCUTF8 GetSimpleName();

    // ------------------------------------------------------------
    // Logging
    // ------------------------------------------------------------
#ifdef FEATURE_PREJIT
    void ExternalVLog(DWORD facility, DWORD level, const WCHAR *fmt, va_list args) DAC_EMPTY();
    void FlushExternalLog() DAC_EMPTY();
#endif
private:
    // ------------------------------------------------------------
    // Loader access API
    // ------------------------------------------------------------

    friend class DomainModule;
#ifdef FEATURE_PREJIT
    void SetNativeImage(const SString &fullPath);
#endif  // FEATURE_PREJIT

private:

#ifndef DACCESS_COMPILE
    PEModule(PEImage *image, PEAssembly *assembly, mdFile token, IMetaDataEmit *pEmit);
    virtual ~PEModule();
#endif

    // ------------------------------------------------------------
    // Instance fields
    // ------------------------------------------------------------

    PTR_PEAssembly          m_assembly;
    mdFile                  m_token;
    BOOL                    m_bIsResource;
};
#endif // FEATURE_MULTIMODULE_ASSEMBLIES

typedef ReleaseHolder<PEFile> PEFileHolder;

typedef ReleaseHolder<PEAssembly> PEAssemblyHolder;

#ifdef FEATURE_MULTIMODULE_ASSEMBLIES
typedef ReleaseHolder<PEModule> PEModuleHolder;
#endif // FEATURE_MULTIMODULE_ASSEMBLIES


// A small shim around PEAssemblies/IBindResult that allow us to write Fusion/CLR-agnostic
// for logging native bind failures to the Fusion log/CLR log.
//
// These structures are stack-based, non-thread-safe and created for the duration of a single RuntimeVerify call.
// The methods are expected to compute their data lazily as they are only used in bind failures or in checked builds.
class LoggablePEAssembly : public LoggableAssembly
{
  public:
    virtual SString DisplayString()
    {
        STANDARD_VM_CONTRACT;

        return m_peAssembly->GetPath();
    }


    LoggablePEAssembly(PEAssembly *peAssembly)
    {
        LIMITED_METHOD_CONTRACT;

        m_peAssembly = peAssembly;
        peAssembly->AddRef();
    }

    ~LoggablePEAssembly()
    {
        LIMITED_METHOD_CONTRACT;

        m_peAssembly->Release();
    }

  private:
    PEAssembly  *m_peAssembly;
};


// ================================================================================
// Inline definitions
// ================================================================================


#endif  // PEFILE_H_