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