summaryrefslogtreecommitdiff
path: root/src/vm/pefile.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/vm/pefile.h')
-rw-r--r--src/vm/pefile.h1243
1 files changed, 1243 insertions, 0 deletions
diff --git a/src/vm/pefile.h b/src/vm/pefile.h
new file mode 100644
index 0000000000..413d08c185
--- /dev/null
+++ b/src/vm/pefile.h
@@ -0,0 +1,1243 @@
+// 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"
+#ifdef FEATURE_FUSION
+#include <fusion.h>
+#include <fusionbind.h>
+#include "binderngen.h"
+#endif
+#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);
+
+#ifdef FEATURE_MIXEDMODE
+protected:
+ // Returns TRUE if this file references managed CRT (msvcmNN*).
+ BOOL ReferencesManagedCRT();
+
+ // Checks for unsupported loads of C++/CLI assemblies into multiple runtimes in this process.
+ void CheckForDisallowedInProcSxSLoad();
+#endif // FEATURE_MIXEDMODE
+
+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
+
+#ifndef FEATURE_CORECLR
+ BOOL IsShareable();
+#endif
+
+ 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);
+#ifdef FEATURE_CAS_POLICY
+ COR_TRUST *GetAuthenticodeSignature();
+#endif
+ // ------------------------------------------------------------
+ // 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();
+
+#ifdef FEATURE_CAS_POLICY
+ SAFEHANDLE GetSafeHandle();
+#endif // FEATURE_CAS_POLICY
+
+ // ------------------------------------------------------------
+ // 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);
+
+#ifdef FEATURE_CAS_POLICY
+ // Check the Authenticode signature of a PE file
+ void CheckAuthenticodeSignature();
+#endif // FEATURE_CAS_POLICY
+
+ 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;
+#ifndef FEATURE_CORECLR
+ IMetaDataAssemblyImport *m_pAssemblyImporter;
+ IMetaDataAssemblyEmit *m_pAssemblyEmitter;
+#endif
+ SimpleRWLock *m_pMetadataLock;
+ Volatile<LONG> m_refCount;
+ SBuffer *m_hash; // cached SHA1 hash value
+ int m_flags;
+ BOOL m_fStrongNameVerified;
+#ifdef FEATURE_CAS_POLICY
+ COR_TRUST *m_certificate;
+ BOOL m_fCheckedCertificate;
+ IInternetSecurityManager *m_pSecurityManager;
+ Crst m_securityManagerLock;
+#endif // FEATURE_CAS_POLICY
+
+#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;
+
+#if defined(FEATURE_HOST_ASSEMBLY_RESOLVER)
+ // 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;
+#endif // defined(FEATURE_HOST_ASSEMBLY_RESOLVER)
+
+protected:
+
+ friend class CLRPrivBinderFusion;
+#ifndef DACCESS_COMPILE
+ // CLRPrivBinderFusion calls this for Fusion-bound assemblies in AppX processes.
+ 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(); }
+
+#if defined(FEATURE_HOST_ASSEMBLY_RESOLVER)
+ void SetFallbackLoadContextBinder(ICLRPrivBinder *pFallbackLoadContextBinder)
+ {
+ LIMITED_METHOD_CONTRACT;
+ m_pFallbackLoadContextBinder = pFallbackLoadContextBinder;
+ }
+
+ ICLRPrivBinder *GetFallbackLoadContextBinder()
+ {
+ LIMITED_METHOD_CONTRACT;
+
+ return m_pFallbackLoadContextBinder;
+ }
+#endif //defined(FEATURE_HOST_ASSEMBLY_RESOLVER)
+}; // class PEFile
+
+
+class PEAssembly : public PEFile
+{
+ VPTR_VTABLE_CLASS(PEAssembly, PEFile)
+
+ public:
+ // ------------------------------------------------------------
+ // Statics initialization.
+ // ------------------------------------------------------------
+ static
+ void Attach();
+
+ // ------------------------------------------------------------
+ // Public API
+ // ------------------------------------------------------------
+
+#if !defined(FEATURE_CORECLR)
+ static PEAssembly * Open(
+ PEAssembly * pParentAssembly,
+ PEImage * pPEImageIL,
+ PEImage * pPEImageNI,
+ ICLRPrivAssembly * pHostAssembly,
+ BOOL fIsIntrospectionOnly);
+
+ static PEAssembly * Open(
+ PEAssembly * pParentAssembly,
+ PEImage * pPEImageIL,
+ BOOL isIntrospectionOnly = FALSE);
+#else //!FEATURE_CORECLR
+ // CoreCLR's PrivBinder PEAssembly creation entrypoint
+ static PEAssembly * Open(
+ PEAssembly * pParent,
+ PEImage * pPEImageIL,
+ PEImage * pPEImageNI,
+ ICLRPrivAssembly * pHostAssembly,
+ BOOL fIsIntrospectionOnly = FALSE);
+#endif //!FEATURE_CORECLR
+
+ // This opens the canonical mscorlib.dll
+#ifdef FEATURE_FUSION
+ static PEAssembly *OpenSystem(IApplicationContext *pAppCtx);
+#else
+ static PEAssembly *OpenSystem(IUnknown *pAppCtx);
+#endif
+#ifdef DACCESS_COMPILE
+ virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
+#endif
+
+#ifdef FEATURE_FUSION
+ static PEAssembly *Open(
+ IAssembly *pIAssembly,
+ IBindResult *pNativeFusionAssembly,
+ IFusionBindLog *pFusionLog = NULL,
+ BOOL isSystemAssembly = FALSE,
+ BOOL isIntrospectionOnly = FALSE);
+
+ static PEAssembly *Open(
+ IHostAssembly *pIHostAssembly,
+ BOOL isSystemAssembly = FALSE,
+ BOOL isIntrospectionOnly = FALSE);
+
+#ifdef FEATURE_MIXEDMODE
+ // Use for main exe loading
+ // NOTE: This may also be used for "spontaneous" (IJW) dll loading where
+ // we need to deliver DllMain callbacks, but we should eliminate this case
+
+ static PEAssembly *OpenHMODULE(
+ HMODULE hMod,
+ IAssembly *pFusionAssembly,
+ IBindResult *pNativeFusionAssembly,
+ IFusionBindLog *pFusionLog = NULL,
+ BOOL isIntrospectionOnly = FALSE);
+#endif // FEATURE_MIXEDMODE
+
+ static PEAssembly *DoOpen(
+ IAssembly *pIAssembly,
+ IBindResult *pNativeFusionAssembly,
+ IFusionBindLog *pFusionLog,
+ BOOL isSystemAssembly,
+ BOOL isIntrospectionOnly = FALSE);
+
+ static PEAssembly *DoOpen(
+ IHostAssembly *pIHostAssembly,
+ BOOL isSystemAssembly,
+ BOOL isIntrospectionOnly = FALSE);
+#ifdef FEATURE_MIXEDMODE
+ static PEAssembly *DoOpenHMODULE(
+ HMODULE hMod,
+ IAssembly *pFusionAssembly,
+ IBindResult *pNativeFusionAssembly,
+ IFusionBindLog *pFusionLog,
+ BOOL isIntrospectionOnly = FALSE);
+#endif // FEATURE_MIXEDMODE
+#else
+ static PEAssembly *Open(
+ CoreBindResult* pBindResult,
+ BOOL isSystem,
+ BOOL isIntrospectionOnly);
+#endif // FEATURE_FUSION
+
+ 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
+#ifdef FEATURE_FUSION
+ static PEAssembly *DoOpenSystem(IApplicationContext *pAppCtx);
+#else
+ static PEAssembly *DoOpenSystem(IUnknown *pAppCtx);
+#endif
+
+ public:
+
+ // ------------------------------------------------------------
+ // binding & source
+ // ------------------------------------------------------------
+
+ BOOL IsSourceGAC();
+#ifdef FEATURE_CORECLR
+ BOOL IsProfileAssembly();
+#endif // FEATURE_CORECLR
+
+ ULONG HashIdentity();
+#ifdef FEATURE_FUSION
+
+ BOOL FusionLoggingEnabled()
+ {
+ LIMITED_METHOD_CONTRACT;
+ return m_bFusionLogEnabled && (m_pFusionLog != NULL);
+ };
+ void DisableFusionLogging()
+ {
+ m_bFusionLogEnabled = FALSE;
+ };
+
+ IFusionBindLog *GetFusionBindLog()
+ {
+ LIMITED_METHOD_CONTRACT;
+#ifdef FEATURE_FUSION
+ return (m_bFusionLogEnabled && (m_pFusionLog != NULL)) ? m_pFusionLog : NULL;
+#else
+ return NULL;
+#endif
+ }
+
+
+ BOOL IsBindingCodeBase();
+
+ BOOL IsSourceDownloadCache();
+
+ LOADCTX_TYPE GetLoadContext();
+ BOOL IsContextLoad();
+
+ // Can we avoid exposing these?
+ IAssembly *GetFusionAssembly();
+ IHostAssembly *GetIHostAssembly();
+ IAssemblyName *GetFusionAssemblyName();
+ IAssemblyName *GetFusionAssemblyNameNoCreate();
+ IAssemblyLocation* GetNativeAssemblyLocation();
+ DWORD GetLocationFlags();
+ PEKIND GetFusionProcessorArchitecture();
+#endif
+
+#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();
+#ifdef FEATURE_FUSION
+ void ETWTraceLogMessage(DWORD dwETWLogCategory, PEAssembly *pAsm)
+ {
+ LIMITED_METHOD_CONTRACT
+ if (FusionLoggingEnabled() &&
+ (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_Context, TRACE_LEVEL_INFORMATION, CLR_PRIVATEFUSION_KEYWORD)))
+ {
+ m_pFusionLog->ETWTraceLogMessage(dwETWLogCategory, (pAsm?pAsm->m_pFusionAssemblyName:NULL));
+ }
+ }
+ ULONGLONG GetBindingID()
+ {
+ LIMITED_METHOD_CONTRACT;
+ ULONGLONG ullBindingID = 0;
+ if (FusionLoggingEnabled())
+ m_pFusionLog->GetBindingID(&ullBindingID);
+ return ullBindingID;
+ }
+#endif
+#endif
+
+#ifndef FEATURE_CORECLR
+ BOOL IsReportedToUsageLog();
+ void SetReportedToUsageLog();
+#endif // !FEATURE_CORECLR
+
+ protected:
+
+#ifndef DACCESS_COMPILE
+#ifdef FEATURE_FUSION
+ PEAssembly(
+ PEImage *image,
+ IMetaDataEmit *pEmit,
+ IAssembly *pIAssembly,
+ IBindResult *pNativeFusionAssembly,
+ PEImage *pNIImage,
+ IFusionBindLog *pFusionLog,
+ IHostAssembly *pIHostAssembly,
+ PEFile *creator,
+ BOOL system,
+ BOOL introspectionOnly = FALSE,
+ ICLRPrivAssembly * pHostAssembly = NULL);
+#else
+ PEAssembly(
+ CoreBindResult* pBindResultInfo,
+ IMetaDataEmit *pEmit,
+ PEFile *creator,
+ BOOL system,
+ BOOL introspectionOnly = FALSE,
+ PEImage * pPEImageIL = NULL,
+ PEImage * pPEImageNI = NULL,
+ ICLRPrivAssembly * pHostAssembly = NULL
+ );
+#endif
+ virtual ~PEAssembly();
+#endif
+
+ // ------------------------------------------------------------
+ // Loader access API
+ // ------------------------------------------------------------
+
+ friend class DomainAssembly;
+#ifdef FEATURE_PREJIT
+
+#ifdef FEATURE_FUSION
+ void SetNativeImage(IBindResult *pNativeFusionAssembly);
+#else
+ void SetNativeImage(PEImage *image);
+#endif
+
+ BOOL CheckNativeImageVersion(PEImage *image);
+
+
+#ifdef FEATURE_FUSION
+ void ClearNativeImage();
+ void SetNativeImageClosure(IAssemblyBindingClosure *pClosure)
+ {
+ LIMITED_METHOD_CONTRACT;
+ if (m_pNativeImageClosure!=NULL)
+ m_pNativeImageClosure->Release();
+ if (pClosure)
+ pClosure->AddRef();
+ m_pNativeImageClosure=pClosure;
+ };
+ BOOL HasEqualNativeClosure(DomainAssembly* pDomainAssembly);
+#endif //FEATURE_FUSION
+
+#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;
+#ifdef FEATURE_FUSION
+ IAssemblyName *m_pFusionAssemblyName;
+ IAssembly *m_pFusionAssembly;
+ IFusionBindLog *m_pFusionLog;
+ BOOL m_bFusionLogEnabled;
+ IHostAssembly *m_pIHostAssembly;
+ IAssemblyLocation *m_pNativeAssemblyLocation;
+ IAssemblyBindingClosure *m_pNativeImageClosure; //present only for shared
+ LOADCTX_TYPE m_loadContext;
+ DWORD m_dwLocationFlags;
+#else
+ 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;
+#endif
+#ifdef FEATURE_CORECLR
+ int m_fProfileAssembly; // Tri-state cache
+#else
+ BOOL m_fStrongNameBypassed;
+#endif
+
+ 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;
+#if !defined(FEATURE_APPX_BINDER)
+ return (HasBindableIdentity());
+#else
+ return (PEFile::CanUseWithBindingCache() && HasBindableIdentity());
+#endif // FEATURE_CORECLR
+ }
+};
+
+#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();
+ }
+
+#ifdef FEATURE_FUSION
+ virtual IAssemblyName* FusionAssemblyName()
+ {
+ STANDARD_VM_CONTRACT;
+
+ return m_peAssembly->GetFusionAssemblyName();
+ }
+
+ virtual IFusionBindLog* FusionBindLog()
+ {
+ STANDARD_VM_CONTRACT;
+
+ return m_peAssembly->GetFusionBindLog();
+ }
+#endif // FEATURE_FUSION
+
+ 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_