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.inl
6//
7
8// --------------------------------------------------------------------------------
9
10#ifndef PEIMAGE_INL_
11#define PEIMAGE_INL_
12
13#include "peimage.h"
14#include "../dlls/mscorrc/resource.h"
15
16inline ULONG PEImage::AddRef()
17{
18 CONTRACT(ULONG)
19 {
20 PRECONDITION(m_refCount>0 && m_refCount < COUNT_T_MAX);
21 NOTHROW;
22 GC_NOTRIGGER;
23 }
24 CONTRACT_END;
25
26 RETURN (static_cast<ULONG>(FastInterlockIncrement(&m_refCount)));
27}
28
29inline const SString &PEImage::GetPath()
30{
31 LIMITED_METHOD_DAC_CONTRACT;
32 STATIC_CONTRACT_SO_TOLERANT;
33
34 return m_path;
35}
36
37inline void PEImage::SetModuleFileNameHintForDAC()
38{
39 LIMITED_METHOD_DAC_CONTRACT;
40 STATIC_CONTRACT_SO_INTOLERANT;
41
42 // Grab module name only for triage dumps where full paths are excluded
43 // because may contain PII data.
44 // m_sModuleFileNameHintUsedByDac will just point to module name starting character.
45 const WCHAR* pStartPath = m_path.GetUnicode();
46 COUNT_T nChars = m_path.GetCount();
47 if (pStartPath != NULL && nChars > 0 && nChars <= MAX_PATH)
48 {
49 const WCHAR* pChar = pStartPath + nChars;
50 nChars = 0;
51 while ((pChar >= pStartPath) && (*pChar != L'\\'))
52 {
53 pChar--;
54 nChars++;
55 }
56 pChar++;
57 m_sModuleFileNameHintUsedByDac.SetPreallocated(pChar, nChars);
58 }
59}
60
61#ifdef DACCESS_COMPILE
62inline const SString &PEImage::GetModuleFileNameHintForDAC()
63{
64 LIMITED_METHOD_CONTRACT;
65
66 return m_sModuleFileNameHintUsedByDac;
67}
68#endif
69
70
71
72inline BOOL PEImage::IsFile()
73{
74 WRAPPER_NO_CONTRACT;
75
76 return !m_path.IsEmpty();
77}
78
79#ifndef DACCESS_COMPILE
80inline void PEImage::SetLayout(DWORD dwLayout, PEImageLayout* pLayout)
81{
82 LIMITED_METHOD_CONTRACT;
83 _ASSERTE(dwLayout<IMAGE_COUNT);
84 _ASSERTE(m_pLayouts[dwLayout]==NULL);
85 FastInterlockExchangePointer((m_pLayouts+dwLayout),pLayout);
86}
87#endif // DACCESS_COMPILE
88inline PTR_PEImageLayout PEImage::GetLoadedLayout()
89{
90 LIMITED_METHOD_CONTRACT;
91 SUPPORTS_DAC;
92
93 _ASSERTE(m_pLayouts[IMAGE_LOADED]!=NULL);
94 return m_pLayouts[IMAGE_LOADED]; //no addref
95}
96
97//
98// GetExistingLayout - get an layout corresponding to the specified mask, or null if none.
99// Does not take any locks or call AddRef.
100//
101// Arguments:
102// imageLayoutMask - bits from PEImageLayout specifying which layouts the caller would be
103// interested in getting
104//
105// Return value:
106// a PEImageLayout of a type matching one of the bits specified in the mask, or NULL if
107// none exists yet. Does not call AddRef on the returned value.
108//
109inline PTR_PEImageLayout PEImage::GetExistingLayoutInternal(DWORD imageLayoutMask)
110{
111 LIMITED_METHOD_CONTRACT;
112 SUPPORTS_DAC;
113
114 PTR_PEImageLayout pRetVal = NULL;
115
116 if (imageLayoutMask&PEImageLayout::LAYOUT_LOADED)
117 pRetVal=m_pLayouts[IMAGE_LOADED];
118 if (pRetVal==NULL && (imageLayoutMask & PEImageLayout::LAYOUT_MAPPED))
119 pRetVal=m_pLayouts[IMAGE_MAPPED];
120 if (pRetVal==NULL && (imageLayoutMask & PEImageLayout::LAYOUT_FLAT))
121 pRetVal=m_pLayouts[IMAGE_FLAT];
122
123 return pRetVal;
124}
125
126
127inline BOOL PEImage::HasLoadedLayout()
128{
129 LIMITED_METHOD_CONTRACT;
130 SUPPORTS_DAC;
131 return m_pLayouts[IMAGE_LOADED]!=NULL;
132}
133
134inline BOOL PEImage::IsOpened()
135{
136 LIMITED_METHOD_CONTRACT;
137 return m_pLayouts[IMAGE_LOADED]!=NULL ||m_pLayouts[IMAGE_MAPPED]!=NULL || m_pLayouts[IMAGE_FLAT] !=NULL;
138}
139
140
141#ifdef FEATURE_PREJIT
142inline CHECK PEImage::CheckNativeFormat()
143{
144 WRAPPER_NO_CONTRACT;
145 if (HasLoadedLayout())
146 CHECK(GetLoadedLayout()->CheckNativeFormat());
147 else
148 {
149 PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_ANY,LAYOUT_CREATEIFNEEDED));
150 CHECK(pLayout->CheckNativeFormat());
151 }
152 CHECK_OK;
153};
154#endif // FEATURE_PREJIT
155
156inline BOOL PEImage::IsReferenceAssembly()
157{
158 CONTRACTL
159 {
160 PRECONDITION(HasCorHeader());
161 }
162 CONTRACTL_END;
163
164 IMDInternalImport* mdImport = this->GetMDImport();
165 HRESULT hr = mdImport->GetCustomAttributeByName(TokenFromRid(1, mdtAssembly),
166 g_ReferenceAssemblyAttribute,
167 NULL,
168 NULL);
169 IfFailThrow(hr);
170 if (hr == S_OK) {
171 return TRUE;
172 }
173 _ASSERTE(hr == S_FALSE);
174 return FALSE;
175}
176
177
178inline BOOL PEImage::HasNTHeaders()
179{
180 WRAPPER_NO_CONTRACT;
181 if (HasLoadedLayout())
182 return GetLoadedLayout()->HasNTHeaders();
183 else
184 {
185 PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_ANY,LAYOUT_CREATEIFNEEDED));
186 return pLayout->HasNTHeaders();
187 }
188}
189
190inline BOOL PEImage::HasCorHeader()
191{
192 WRAPPER_NO_CONTRACT;
193 if (HasLoadedLayout())
194 return GetLoadedLayout()->HasCorHeader();
195 else
196 {
197 PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_ANY,LAYOUT_CREATEIFNEEDED));
198 return pLayout->HasCorHeader();
199 }
200}
201
202inline BOOL PEImage::HasReadyToRunHeader()
203{
204 WRAPPER_NO_CONTRACT;
205 if (HasLoadedLayout())
206 return GetLoadedLayout()->HasReadyToRunHeader();
207 else
208 {
209 PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_ANY,LAYOUT_CREATEIFNEEDED));
210 return pLayout->HasReadyToRunHeader();
211 }
212}
213
214inline void PEImage::SetPassiveDomainOnly()
215{
216 LIMITED_METHOD_CONTRACT;
217 m_bPassiveDomainOnly=TRUE;
218}
219
220inline BOOL PEImage::PassiveDomainOnly()
221{
222 LIMITED_METHOD_CONTRACT;
223 return m_bPassiveDomainOnly;
224}
225
226inline BOOL PEImage::HasDirectoryEntry(int entry)
227{
228 WRAPPER_NO_CONTRACT;
229 if (HasLoadedLayout())
230 return GetLoadedLayout()->HasDirectoryEntry(entry);
231 else
232 {
233 PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_ANY,LAYOUT_CREATEIFNEEDED));
234 return pLayout->HasDirectoryEntry(entry);
235 }
236}
237
238inline mdToken PEImage::GetEntryPointToken()
239{
240 WRAPPER_NO_CONTRACT;
241 if (HasLoadedLayout())
242 {
243 PTR_PEImageLayout pLayout = GetLoadedLayout();
244 if (!pLayout->HasManagedEntryPoint())
245 return mdTokenNil;
246 return pLayout->GetEntryPointToken();
247 }
248 else
249 {
250 PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_ANY,LAYOUT_CREATEIFNEEDED));
251 if (!pLayout->HasManagedEntryPoint())
252 return mdTokenNil;
253 return pLayout->GetEntryPointToken();
254 }
255}
256
257inline DWORD PEImage::GetCorHeaderFlags()
258{
259 WRAPPER_NO_CONTRACT;
260
261 if (HasLoadedLayout())
262 {
263 PTR_PEImageLayout pLayout = GetLoadedLayout();
264 return VAL32(pLayout->GetCorHeader()->Flags);
265 }
266 else
267 {
268 PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_ANY,LAYOUT_CREATEIFNEEDED));
269 return VAL32(pLayout->GetCorHeader()->Flags);
270 }
271}
272
273inline BOOL PEImage::MDImportLoaded()
274{
275 return m_pMDImport != NULL;
276}
277
278inline BOOL PEImage::HasV1Metadata()
279{
280 WRAPPER_NO_CONTRACT;
281 return GetMDImport()->GetMetadataStreamVersion()==MD_STREAM_VER_1X;
282}
283
284inline BOOL PEImage::IsILOnly()
285{
286 WRAPPER_NO_CONTRACT;
287 if (HasLoadedLayout())
288 return GetLoadedLayout()->IsILOnly();
289 else
290 {
291 PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_ANY,LAYOUT_CREATEIFNEEDED));
292 return pLayout->IsILOnly();
293 }
294}
295
296inline WORD PEImage::GetSubsystem()
297{
298 WRAPPER_NO_CONTRACT;
299 SUPPORTS_DAC;
300
301 if (HasLoadedLayout())
302 return GetLoadedLayout()->GetSubsystem();
303 else
304 {
305 PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_ANY,LAYOUT_CREATEIFNEEDED));
306 return pLayout->GetSubsystem();
307 }
308}
309
310#ifdef FEATURE_PREJIT
311inline BOOL PEImage::IsNativeILILOnly()
312{
313 WRAPPER_NO_CONTRACT;
314 if (HasLoadedLayout())
315 return GetLoadedLayout()->IsNativeILILOnly();
316 else
317 {
318 PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_ANY,LAYOUT_CREATEIFNEEDED));
319 return pLayout->IsNativeILILOnly();
320 }
321}
322
323inline void PEImage::GetNativeILPEKindAndMachine(DWORD* pdwKind, DWORD* pdwMachine)
324{
325 WRAPPER_NO_CONTRACT;
326 if (HasLoadedLayout())
327 GetLoadedLayout()->GetNativeILPEKindAndMachine(pdwKind, pdwMachine);
328 else
329 {
330 PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_ANY,LAYOUT_CREATEIFNEEDED));
331 pLayout->GetNativeILPEKindAndMachine(pdwKind, pdwMachine);
332 }
333}
334
335inline BOOL PEImage::IsNativeILDll()
336{
337 WRAPPER_NO_CONTRACT;
338 if (HasLoadedLayout())
339 return GetLoadedLayout()->IsNativeILDll();
340 else
341 {
342 PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_ANY,LAYOUT_CREATEIFNEEDED));
343 return pLayout->IsNativeILDll();
344 }
345}
346#endif // FEATURE_PREJIT
347
348inline BOOL PEImage::IsDll()
349{
350 WRAPPER_NO_CONTRACT;
351 if (HasLoadedLayout())
352 return GetLoadedLayout()->IsDll();
353 else
354 {
355 PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_ANY,LAYOUT_CREATEIFNEEDED));
356 return pLayout->IsDll();
357 }
358}
359
360inline BOOL PEImage::HasStrongNameSignature()
361{
362 WRAPPER_NO_CONTRACT;
363 if (HasLoadedLayout())
364 return GetLoadedLayout()->HasStrongNameSignature();
365 else
366 {
367 PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_ANY,LAYOUT_CREATEIFNEEDED));
368 return pLayout->HasStrongNameSignature();
369 }
370}
371
372#ifndef DACCESS_COMPILE
373
374
375#endif // !DACCESS_COMPILE
376
377inline BOOL PEImage::IsIbcOptimized()
378{
379#ifdef FEATURE_PREJIT
380 WRAPPER_NO_CONTRACT;
381 if (HasLoadedLayout())
382 return GetLoadedLayout()->GetNativeILIsIbcOptimized();
383 else
384 {
385 PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_ANY,LAYOUT_CREATEIFNEEDED));
386 return pLayout->GetNativeILIsIbcOptimized();
387 }
388#else
389 return false;
390#endif
391}
392
393#ifdef FEATURE_PREJIT
394inline PTR_CVOID PEImage::GetNativeManifestMetadata(COUNT_T *pSize)
395{
396 WRAPPER_NO_CONTRACT;
397 if (HasLoadedLayout())
398 return GetLoadedLayout()->GetNativeManifestMetadata(pSize);
399 else
400 {
401 PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_ANY,LAYOUT_CREATEIFNEEDED));
402 return pLayout->GetNativeManifestMetadata(pSize);
403 }
404}
405#endif
406
407inline PTR_CVOID PEImage::GetMetadata(COUNT_T *pSize)
408{
409 WRAPPER_NO_CONTRACT;
410 if (HasLoadedLayout())
411 return GetLoadedLayout()->GetMetadata(pSize);
412 else
413 {
414 PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_ANY,LAYOUT_CREATEIFNEEDED));
415 return pLayout->GetMetadata(pSize);
416 }
417}
418
419inline BOOL PEImage::HasNativeHeader()
420{
421 WRAPPER_NO_CONTRACT;
422 if (HasLoadedLayout())
423 return GetLoadedLayout()->HasNativeHeader();
424 else
425 {
426 PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_ANY,LAYOUT_CREATEIFNEEDED));
427 return pLayout->HasNativeHeader();
428 }
429}
430
431inline BOOL PEImage::HasContents()
432{
433 WRAPPER_NO_CONTRACT;
434 if (HasLoadedLayout())
435 return GetLoadedLayout()->HasContents();
436 else
437 {
438 PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_ANY,LAYOUT_CREATEIFNEEDED));
439 return pLayout->HasContents();
440 }
441}
442
443
444inline CHECK PEImage::CheckFormat()
445{
446 WRAPPER_NO_CONTRACT;
447 if (HasLoadedLayout())
448 CHECK(GetLoadedLayout()->CheckFormat());
449 else
450 {
451 PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_ANY,LAYOUT_CREATEIFNEEDED));
452 CHECK(pLayout->CheckFormat());
453 }
454 CHECK_OK;
455}
456inline PTR_CVOID PEImage::GetStrongNameSignature(COUNT_T *pSize)
457{
458 WRAPPER_NO_CONTRACT;
459 if (HasLoadedLayout())
460 return GetLoadedLayout()->GetStrongNameSignature(pSize);
461 else
462 {
463 PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_ANY,LAYOUT_CREATEIFNEEDED));
464 return pLayout->GetStrongNameSignature(pSize);
465 }
466}
467
468inline void PEImage::Init(LPCWSTR pPath)
469{
470 CONTRACTL
471 {
472 THROWS;
473 GC_NOTRIGGER;
474 MODE_ANY;
475 }
476 CONTRACTL_END;
477 m_path = pPath;
478 m_path.Normalize();
479 SetModuleFileNameHintForDAC();
480}
481#ifndef DACCESS_COMPILE
482
483
484/*static*/
485inline PTR_PEImage PEImage::FindByPath(LPCWSTR pPath)
486{
487 CONTRACTL
488 {
489 THROWS;
490 GC_TRIGGERS;
491 MODE_ANY;
492 PRECONDITION(s_hashLock.OwnedByCurrentThread());
493 }
494 CONTRACTL_END;
495
496 int CaseHashHelper(const WCHAR *buffer, COUNT_T count, LocaleID lcid);
497
498 PEImageLocator locator(pPath);
499#ifdef FEATURE_CASE_SENSITIVE_FILESYSTEM
500 DWORD dwHash=path.Hash();
501#else
502 DWORD dwHash = CaseHashHelper(pPath, (COUNT_T) wcslen(pPath), PEImage::GetFileSystemLocale());
503#endif
504 return (PEImage *) s_Images->LookupValue(dwHash, &locator);
505
506}
507
508/* static */
509inline PTR_PEImage PEImage::OpenImage(LPCWSTR pPath, MDInternalImportFlags flags /* = MDInternalImport_Default */)
510{
511 BOOL fUseCache = !((flags & MDInternalImport_NoCache) == MDInternalImport_NoCache);
512
513 if (!fUseCache)
514 {
515 PEImageHolder pImage(new PEImage);
516 pImage->Init(pPath);
517 return dac_cast<PTR_PEImage>(pImage.Extract());
518 }
519
520 CrstHolder holder(&s_hashLock);
521
522 PEImage* found = FindByPath(pPath);
523
524
525 if (found == (PEImage*) INVALIDENTRY)
526 {
527 // We did not find the entry in the Cache, and we've been asked to only use the cache.
528 if ((flags & MDInternalImport_OnlyLookInCache) == MDInternalImport_OnlyLookInCache)
529 {
530 return NULL;
531 }
532
533 PEImageHolder pImage(new PEImage);
534#ifdef FEATURE_PREJIT
535 if (flags & MDInternalImport_TrustedNativeImage)
536 pImage->SetIsTrustedNativeImage();
537 if (flags & MDInternalImport_NativeImageInstall)
538 pImage->SetIsNativeImageInstall();
539#endif
540 pImage->Init(pPath);
541
542 pImage->AddToHashMap();
543 return dac_cast<PTR_PEImage>(pImage.Extract());
544 }
545
546 found->AddRef();
547
548 return dac_cast<PTR_PEImage>(found);
549}
550#endif
551
552inline BOOL PEImage::IsFileLocked()
553{
554 WRAPPER_NO_CONTRACT;
555 return (m_pLayouts[IMAGE_FLAT])!=NULL || (m_pLayouts[IMAGE_MAPPED])!=NULL ;
556}
557
558#ifndef DACCESS_COMPILE
559
560
561inline void PEImage::AddToHashMap()
562{
563 CONTRACTL
564 {
565 THROWS;
566 GC_NOTRIGGER;
567 MODE_ANY;
568 }
569 CONTRACTL_END;
570
571 _ASSERTE(s_hashLock.OwnedByCurrentThread());
572 s_Images->InsertValue(GetIDHash(),this);
573 m_bInHashMap=TRUE;
574}
575
576#endif
577
578
579
580
581inline BOOL PEImage::Has32BitNTHeaders()
582{
583 WRAPPER_NO_CONTRACT;
584 if (HasLoadedLayout())
585 return GetLoadedLayout()->Has32BitNTHeaders();
586 else
587 {
588 PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_ANY,LAYOUT_CREATEIFNEEDED));
589 return pLayout->Has32BitNTHeaders();
590 }
591}
592
593inline BOOL PEImage::HasID()
594{
595 LIMITED_METHOD_CONTRACT;
596
597
598 return !GetPath().IsEmpty();
599}
600
601inline ULONG PEImage::GetIDHash()
602{
603 CONTRACT(ULONG)
604 {
605 PRECONDITION(HasID());
606 MODE_ANY;
607 GC_NOTRIGGER;
608 THROWS;
609 }
610 CONTRACT_END;
611
612
613#ifdef FEATURE_CASE_SENSITIVE_FILESYSTEM
614 RETURN m_path.Hash();
615#else
616 RETURN m_path.HashCaseInsensitive(PEImage::GetFileSystemLocale());
617#endif
618}
619
620inline void PEImage::CachePEKindAndMachine()
621{
622 CONTRACTL
623 {
624 THROWS;
625 GC_TRIGGERS;
626 MODE_ANY;
627 }
628 CONTRACTL_END;
629
630 // Do nothing if we have cached the information already
631 if(m_fCachedKindAndMachine)
632 return;
633
634 PEImageLayoutHolder pLayout;
635 if (HasLoadedLayout())
636 {
637 pLayout.Assign(GetLoadedLayout(), false);
638 }
639 else
640 {
641 pLayout.Assign(GetLayout(PEImageLayout::LAYOUT_MAPPED|PEImageLayout::LAYOUT_FLAT,
642 PEImage::LAYOUT_CREATEIFNEEDED));
643 }
644
645 // Compute result into a local variables first
646 DWORD dwPEKind, dwMachine;
647 pLayout->GetPEKindAndMachine(&dwPEKind, &dwMachine);
648
649 // Write the final result into the lock-free cache.
650 m_dwPEKind = dwPEKind;
651 m_dwMachine = dwMachine;
652 MemoryBarrier();
653 m_fCachedKindAndMachine = TRUE;
654}
655
656inline void PEImage::GetPEKindAndMachine(DWORD* pdwKind, DWORD* pdwMachine)
657{
658 WRAPPER_NO_CONTRACT;
659 CachePEKindAndMachine();
660 if (pdwKind)
661 *pdwKind = m_dwPEKind;
662 if (pdwMachine)
663 *pdwMachine = m_dwMachine;
664}
665
666
667
668#ifndef DACCESS_COMPILE
669inline void PEImage::AllocateLazyCOWPages()
670{
671 STANDARD_VM_CONTRACT;
672
673#ifdef FEATURE_LAZY_COW_PAGES
674 if (!m_bAllocatedLazyCOWPages && CLRConfig::GetConfigValue(CLRConfig::INTERNAL_ZapLazyCOWPagesEnabled))
675 {
676 ::AllocateLazyCOWPages(GetLoadedLayout());
677 m_bAllocatedLazyCOWPages = TRUE;
678 }
679#endif
680}
681#endif
682
683#endif // PEIMAGE_INL_
684