summaryrefslogtreecommitdiff
path: root/src/vm/peimage.h
blob: 6aa95918bfbc094ccd8e158fd88d9cae8057dad2 (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
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
// --------------------------------------------------------------------------------
// PEImage.h
// 

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


#ifndef PEIMAGE_H_
#define PEIMAGE_H_

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

#include "clrtypes.h"
#include "peimagelayout.h"
#include "sstring.h"
#include "holder.h"
#include "pefingerprint.h"

class SimpleRWLock;
// --------------------------------------------------------------------------------
// Forward declarations
// --------------------------------------------------------------------------------

class Crst;
class Thread;

Thread* GetThreadNULLOk();

// --------------------------------------------------------------------------------
// PEImage is a PE file loaded by our "simulated LoadLibrary" mechanism.  A PEImage 
// can be loaded either FLAT (same layout as on disk) or MAPPED (PE sections 
// mapped into virtual addresses.)
// 
// The MAPPED format is currently limited to "IL only" images - this can be checked
// for via PEDecoder::IsILOnlyImage.
//
// NOTE: PEImage will NEVER call LoadLibrary.
// --------------------------------------------------------------------------------



#define CV_SIGNATURE_RSDS   0x53445352

// CodeView RSDS debug information -> PDB 7.00
struct CV_INFO_PDB70 
{
    DWORD      magic; 
    GUID       signature;       // unique identifier 
    DWORD      age;             // an always-incrementing value 
    char       path[MAX_LONGPATH];  // zero terminated string with the name of the PDB file 
};

typedef DPTR(class PEImage)                PTR_PEImage;

class PEImage 
{
    friend class PEModule;
#ifdef FEATURE_INCLUDE_ALL_INTERFACES
    friend class CCLRDebugManager;
#endif // FEATURE_INCLUDE_ALL_INTERFACES
public:
    // ------------------------------------------------------------
    // Public constants
    // ------------------------------------------------------------

    enum
    {
        LAYOUT_CREATEIFNEEDED=1
    };
    PTR_PEImageLayout GetLayout(DWORD imageLayoutMask,DWORD flags); //with ref
    PTR_PEImageLayout GetLoadedLayout(); //no ref
    PTR_PEImageLayout GetLoadedIntrospectionLayout(); //no ref, introspection only
    BOOL IsOpened();
    BOOL HasLoadedLayout();
    BOOL HasLoadedIntrospectionLayout();
    

public:
    // ------------------------------------------------------------
    // Public API
    // ------------------------------------------------------------

    static void Startup();

    // Normal constructed PEImages do NOT share images between calls and
    // cannot be accessed by Get methods.
    //
    // DO NOT USE these unless you want a private copy-on-write mapping of
    // the file.



public:
    ~PEImage();
    PEImage();

#ifndef DACCESS_COMPILE
    static PTR_PEImage LoadFlat(
        const void *flat,
        COUNT_T size);
#ifndef FEATURE_PAL
    static PTR_PEImage LoadImage(
        HMODULE hMod);
#endif // !FEATURE_PAL        
    static PTR_PEImage OpenImage(
        LPCWSTR pPath,
        MDInternalImportFlags flags = MDInternalImport_Default);

#ifdef FEATURE_FUSION
    static PTR_PEImage OpenImage(
        IStream *pIStream,
        UINT64 uStreamAsmId,
        DWORD dwModuleId,
        BOOL resourceFile,
        MDInternalImportFlags flags = MDInternalImport_Default);
#endif

    // clones the image with new flags (this is pretty much about cached / noncached difference)
    void Clone(MDInternalImportFlags flags, PTR_PEImage* ppImage)
    {
        if (GetPath().IsEmpty())
        {
            AddRef();
            *ppImage = this;
        }
        else
            *ppImage = PEImage::OpenImage(GetPath(), flags);

    };

#ifdef FEATURE_HOSTED_BINDER
    // pUnkResource must be one of the ICLRPrivResource* interfaces defined in CLRPrivBinding.IDL.
    // pUnkResource will be queried for each of these to find a match and 
    static PEImage * OpenImage(
        ICLRPrivResource * pIResource,
        MDInternalImportFlags flags = MDInternalImport_Default);
#endif

    static PTR_PEImage FindById(UINT64 uStreamAsmId, DWORD dwModuleId);
    static PTR_PEImage FindByPath(LPCWSTR pPath);    
    static PTR_PEImage FindByShortPath(LPCWSTR pPath);
    static PTR_PEImage FindByLongPath(LPCWSTR pPath);
    void AddToHashMap();

    void   Load();
    void   SetLoadedHMODULE(HMODULE hMod);
    void   LoadNoMetaData(BOOL bIntrospection);
    void   LoadNoFile();
    void   LoadFromMapped();  
    void   LoadForIntrospection();

    void AllocateLazyCOWPages();
#endif
    
    BOOL   HasID();
    ULONG GetIDHash();
    
    PTR_CVOID GetStrongNameSignature(COUNT_T *pSize = NULL);
    

    // Refcount above images.
    ULONG AddRef();
    ULONG Release();

    // Accessors
    const SString &GetPath();
    BOOL IsFile();
    HANDLE GetFileHandle();
    HANDLE GetFileHandleLocking();
    void SetFileHandle(HANDLE hFile);
    HRESULT TryOpenFile();    

    HANDLE GetProtectingFileHandle(BOOL bProtectIfNotOpenedYet);

    LPCWSTR GetPathForErrorMessages();

    // Equality
    BOOL Equals(PEImage *pImage);
    static ULONG HashStreamIds(UINT64 id1, DWORD id2);

    // Hashing utilities.  (These require a flat version of the file, and 
    // will open one if necessary.)

#ifndef DACCESS_COMPILE
    void GetImageBits(DWORD layout, SBuffer &result);
#endif

    void ComputeHash(ALG_ID algorithm, SBuffer &result);
    CHECK CheckHash(ALG_ID algorithm, const void *pbHash, COUNT_T cbHash);

    void GetMVID(GUID *pMvid);
    const BOOL HasV1Metadata();
    IMDInternalImport* GetMDImport();
    BOOL MDImportLoaded();
    IMDInternalImport* GetNativeMDImport(BOOL loadAllowed = TRUE);    

    BOOL HasSecurityDirectory();
    BOOL HasContents() ;
    BOOL HasNativeHeader() ;
    BOOL IsPtrInImage(PTR_CVOID data);
    CHECK CheckFormat();

    // Check utilites
    CHECK CheckILFormat();
#ifdef FEATURE_PREJIT    
    CHECK CheckNativeFormat();    
#endif // FEATURE_PREJIT
    static CHECK CheckCanonicalFullPath(const SString &path);
    static CHECK CheckStartup();
    PTR_CVOID GetMetadata(COUNT_T *pSize = NULL);
    void GetHashedStrongNameSignature(SBuffer &result);

#ifndef FEATURE_PAL
    static void GetPathFromDll(HINSTANCE hMod, SString &result);
#endif // !FEATURE_PAL    
    static LocaleID GetFileSystemLocale();
    static BOOL PathEquals(const SString &p1, const SString &p2);
    BOOL IsTrustedNativeImage(){LIMITED_METHOD_CONTRACT; return m_bIsTrustedNativeImage;};
    void SetIsTrustedNativeImage(){LIMITED_METHOD_CONTRACT; m_bIsTrustedNativeImage=TRUE;};
    BOOL IsNativeImageInstall(){LIMITED_METHOD_CONTRACT; return m_bIsNativeImageInstall;}
    void SetIsNativeImageInstall(){LIMITED_METHOD_CONTRACT; m_bIsNativeImageInstall=TRUE;};

    void SetModuleFileNameHintForDAC();
#ifdef DACCESS_COMPILE
    void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
    const SString &GetModuleFileNameHintForDAC();
#endif

    const BOOL HasNTHeaders();
    const BOOL HasCorHeader(); 
    const BOOL HasReadyToRunHeader();
    void SetPassiveDomainOnly();
    BOOL PassiveDomainOnly();
    BOOL IsReferenceAssembly();
#ifdef FEATURE_PREJIT  
    const BOOL GetNativeILHasSecurityDirectory();
    const BOOL IsNativeILILOnly();
    const BOOL IsNativeILDll();
    void GetNativeILPEKindAndMachine(DWORD* pdwKind, DWORD* pdwMachine);
    PTR_CVOID GetNativeManifestMetadata(COUNT_T *pSize = NULL);
#endif
    const BOOL HasDirectoryEntry(int entry);
    const mdToken GetEntryPointToken();
    const DWORD GetCorHeaderFlags(); 
    const BOOL IsILOnly();
    const BOOL IsDll();
    const WORD GetSubsystem();
    BOOL  IsFileLocked();
    const BOOL HasStrongNameSignature();
#ifndef DACCESS_COMPILE
    const HRESULT VerifyStrongName(DWORD* verifyOutputFlags);    
#endif

    BOOL IsStrongNameSigned();
    BOOL IsIbcOptimized();
    BOOL Has32BitNTHeaders();

    void VerifyIsAssembly();
    void VerifyIsNIAssembly();

#ifndef FEATURE_CORECLR
    BOOL IsReportedToUsageLog();
    void SetReportedToUsageLog();
#ifndef DACCESS_COMPILE
    HRESULT GetILFingerprint(IILFingerprint **ppFingerprint);
#endif //!DACCESS_COMPILE
#endif //!FEATURE_CORECLR

    static void GetAll(SArray<PEImage*> &images);

private:
#ifndef DACCESS_COMPILE
    // Get or create the layout corresponding to the mask, with an AddRef
    PTR_PEImageLayout GetLayoutInternal(DWORD imageLayoutMask, DWORD flags); 
#endif
    // Get an existing layout corresponding to the mask, no AddRef
    PTR_PEImageLayout GetExistingLayoutInternal(DWORD imageLayoutMask);

    void OpenMDImport();
    void OpenNativeMDImport();    
    // ------------------------------------------------------------
    // Private routines
    // ------------------------------------------------------------

    void  Init(LPCWSTR pPath);
    void  Init(IStream* pStream, UINT64 uStreamAsmId,
               DWORD dwModuleId, BOOL resourceFile);

    void VerifyIsILOrNIAssembly(BOOL fIL);

    struct PEImageLocator
    {
#ifdef FEATURE_FUSION
        BOOL m_fIsIStream;
        DWORD m_dwStreamModuleId;
        UINT64 m_StreamAsmId;
#endif

        LPCWSTR m_pPath;

#ifdef FEATURE_FUSION
        PEImageLocator(LPCWSTR pPath)
            : m_fIsIStream(FALSE), m_pPath(pPath)
        {
        }

        PEImageLocator(UINT64 uStreamAsmId, DWORD dwModuleId)
            : m_fIsIStream(TRUE), m_dwStreamModuleId(dwModuleId), m_StreamAsmId(uStreamAsmId)
        {
        }

        PEImageLocator(PEImage * pImage)
            : m_fIsIStream(pImage->m_fIsIStream),
              m_dwStreamModuleId(pImage->m_dwStreamModuleId),
              m_StreamAsmId(pImage->m_StreamAsmId),
              m_pPath(pImage->m_path.GetUnicode())
        {
        }
#else // FEATURE_FUSION
        PEImageLocator(LPCWSTR pPath)
            : m_pPath(pPath)
        {
        }

        PEImageLocator(PEImage * pImage)
            : m_pPath(pImage->m_path.GetUnicode())
        {
        }
#endif // FEATURE_FUSION
    };

    static BOOL CompareImage(UPTR image1, UPTR image2);
#ifdef FEATURE_MIXEDMODE
    static BOOL CompareIJWDataBase(UPTR base, UPTR mapping);
#endif // FEATURE_MIXEDMODE

    void DECLSPEC_NORETURN ThrowFormat(HRESULT hr);

    static CHECK CheckLayoutFormat(PEDecoder *pe);

    // ------------------------------------------------------------
    // Instance members
    // ------------------------------------------------------------

    SString     m_path;
    LONG        m_refCount;

    // This variable will have the data of module name. 
    // It is only used by DAC to remap fusion loaded modules back to 
    // disk IL. This really is a workaround. The real fix is for fusion loader
    // hook (public API on hosting) to take an additional file name hint.
    // We are piggy backing on the fact that module name is the same as file name!!!
    //
    SString     m_sModuleFileNameHintUsedByDac; // This is only used by DAC
private:
    BOOL        m_bIsTrustedNativeImage;
    BOOL        m_bIsNativeImageInstall;
    BOOL        m_bPassiveDomainOnly;
#ifndef FEATURE_CORECLR
    BOOL        m_fReportedToUsageLog;
#endif // !FEATURE_CORECLR
#ifdef FEATURE_LAZY_COW_PAGES
    BOOL        m_bAllocatedLazyCOWPages;
#endif // FEATURE_LAZY_COW_PAGES

protected:

    enum 
    {
        IMAGE_FLAT=0,
        IMAGE_MAPPED=1,
        IMAGE_LOADED=2,
        IMAGE_LOADED_FOR_INTROSPECTION=3,
        IMAGE_COUNT=4
    };
    
    SimpleRWLock *m_pLayoutLock;
    PTR_PEImageLayout m_pLayouts[IMAGE_COUNT] ;
    BOOL      m_bInHashMap;
#ifndef DACCESS_COMPILE    
    void   SetLayout(DWORD dwLayout, PTR_PEImageLayout pLayout);
#endif // DACCESS_COMPILE


#ifdef METADATATRACKER_DATA
    class MetaDataTracker   *m_pMDTracker;
#endif // METADATATRACKER_DATA

    IMDInternalImport* m_pMDImport;
    IMDInternalImport* m_pNativeMDImport;

#ifdef FEATURE_FUSION
    UINT64      m_StreamAsmId;
    DWORD       m_dwStreamModuleId;
    BOOL        m_fIsIStream;
#endif

private:


    // ------------------------------------------------------------
    // Static members
    // ------------------------------------------------------------

    static CrstStatic   s_hashLock;

    static PtrHashMap   *s_Images;

    HANDLE m_hFile;
    bool   m_bOwnHandle;

    BOOL        m_bSignatureInfoCached;
    HRESULT   m_hrSignatureInfoStatus;
    DWORD        m_dwSignatureInfo;    
#ifdef FEATURE_MIXEDMODE
    //@TODO:workaround: Remove this when we have one PEImage per mapped image,
    //@TODO:workaround: and move the lock there
    // This is for IJW thunk initialization, as it is no longer guaranteed
    // that the initialization will occur under the loader lock.
    static CrstStatic   s_ijwHashLock;
    static PtrHashMap   *s_ijwFixupDataHash;

public:
    class IJWFixupData
    {
    private:
        Crst            m_lock;
        void           *m_base;
        DWORD           m_flags;
        PTR_LoaderHeap  m_DllThunkHeap;

        // the fixup for the next iteration in FixupVTables
        // we use it to make sure that we do not try to fix up the same entry twice
        // if there was a pass that was aborted in the middle
        COUNT_T         m_iNextFixup;
        COUNT_T         m_iNextMethod;

        enum {
            e_FIXED_UP = 0x1
        };

    public:
        IJWFixupData(void *pBase);
        ~IJWFixupData();
        void *GetBase() { LIMITED_METHOD_CONTRACT; return m_base; }
        Crst *GetLock() { LIMITED_METHOD_CONTRACT; return &m_lock; }
        BOOL IsFixedUp() { LIMITED_METHOD_CONTRACT; return m_flags & e_FIXED_UP; }
        void SetIsFixedUp() { LIMITED_METHOD_CONTRACT; m_flags |= e_FIXED_UP; }
        PTR_LoaderHeap  GetThunkHeap();
        void MarkMethodFixedUp(COUNT_T iFixup, COUNT_T iMethod);
        BOOL IsMethodFixedUp(COUNT_T iFixup, COUNT_T iMethod);
    };

    static IJWFixupData *GetIJWData(void *pBase);
    static PTR_LoaderHeap GetDllThunkHeap(void *pBase);
    static void UnloadIJWModule(void *pBase);
#endif //FEATURE_MIXEDMODE
private:
    DWORD m_dwPEKind;
    DWORD m_dwMachine;
    BOOL  m_fCachedKindAndMachine;

#ifdef FEATURE_APTCA
    BOOL  m_fMayBeConditionalAptca;
#endif // FEATURE_APTCA

#ifdef FEATURE_FUSION
    PEFingerprint *m_pILFingerprint; // has to be the real type (as opposed to an interface) so we can delete it
#endif // FEATURE_FUSION

public:
    void CachePEKindAndMachine();
    void GetPEKindAndMachine(DWORD* pdwKind, DWORD* pdwMachine);
#ifdef FEATURE_FUSION	
    PEKIND GetFusionProcessorArchitecture();
#endif

#ifdef FEATURE_APTCA
    inline BOOL MayBeConditionalAptca();
    inline void SetIsNotConditionalAptca();
#endif // FEATURE_APTCA
};

FORCEINLINE void PEImageRelease(PEImage *i)
{
    WRAPPER_NO_CONTRACT;
    i->Release();
}

typedef Wrapper<PEImage *, DoNothing, PEImageRelease> PEImageHolder;

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

#include "peimage.inl"

#endif  // PEIMAGE_H_