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.cpp
6//
7
8// --------------------------------------------------------------------------------
9
10
11#include "common.h"
12
13#include "peimage.h"
14#include "eeconfig.h"
15#include "apithreadstress.h"
16#include <objbase.h>
17
18#include "sha1.h"
19#include "eventtrace.h"
20#include "peimagelayout.inl"
21
22#ifdef FEATURE_PREJIT
23#include "compile.h"
24#endif
25
26#ifndef DACCESS_COMPILE
27
28
29CrstStatic PEImage::s_hashLock;
30PtrHashMap *PEImage::s_Images = NULL;
31CrstStatic PEImage::s_ijwHashLock;
32PtrHashMap *PEImage::s_ijwFixupDataHash;
33
34extern LocaleID g_lcid; // fusion path comparison lcid
35
36/* static */
37void PEImage::Startup()
38{
39 CONTRACT_VOID
40 {
41 THROWS;
42 GC_NOTRIGGER;
43 MODE_ANY;
44 SO_TOLERANT;
45 POSTCONDITION(CheckStartup());
46 INJECT_FAULT(COMPlusThrowOM(););
47 }
48 CONTRACT_END;
49
50 if (CheckStartup())
51 RETURN;
52
53 BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(COMPlusThrowSO());
54
55 s_hashLock.Init(CrstPEImage, (CrstFlags)(CRST_REENTRANCY|CRST_TAKEN_DURING_SHUTDOWN));
56 LockOwner lock = { &s_hashLock, IsOwnerOfCrst };
57 s_Images = ::new PtrHashMap;
58 s_Images->Init(CompareImage, FALSE, &lock);
59
60 s_ijwHashLock.Init(CrstIJWHash, CRST_REENTRANCY);
61 LockOwner ijwLock = { &s_ijwHashLock, IsOwnerOfCrst };
62 s_ijwFixupDataHash = ::new PtrHashMap;
63 s_ijwFixupDataHash->Init(CompareIJWDataBase, FALSE, &ijwLock);
64
65 PEImageLayout::Startup();
66#ifdef FEATURE_USE_LCID
67 g_lcid = MAKELCID(LOCALE_INVARIANT, SORT_DEFAULT);
68#else // FEATURE_USE_LCID
69 g_lcid = NULL; // invariant
70#endif //FEATURE_USE_LCID
71 END_SO_INTOLERANT_CODE;
72
73 RETURN;
74}
75
76/* static */
77CHECK PEImage::CheckStartup()
78{
79 WRAPPER_NO_CONTRACT;
80 CHECK(s_Images != NULL);
81 CHECK_OK;
82}
83
84/* static */
85CHECK PEImage::CheckLayoutFormat(PEDecoder *pe)
86{
87 CONTRACT_CHECK
88 {
89 THROWS;
90 GC_TRIGGERS;
91 MODE_ANY;
92 INJECT_FAULT(COMPlusThrowOM(););
93 }
94 CONTRACT_CHECK_END;
95
96 // If we are in a compilation domain, we will allow
97 // non-IL only files to be treated as IL only
98
99 // <TODO>@todo: this is not really the right model here. This is a per-app domain
100 // choice, but an image created this way would become available globally.
101 // (Also, this call prevents us from moving peimage into utilcode.)</TODO>
102
103 if (GetAppDomain() == NULL ||
104 (!GetAppDomain()->IsCompilationDomain()))
105 {
106 CHECK(pe->IsILOnly());
107 }
108
109 CHECK(!pe->HasNativeHeader());
110 CHECK_OK;
111}
112
113CHECK PEImage::CheckILFormat()
114{
115 WRAPPER_NO_CONTRACT;
116
117 PTR_PEImageLayout pLayoutToCheck;
118 PEImageLayoutHolder pLayoutHolder;
119
120 if (HasLoadedLayout())
121 {
122 pLayoutToCheck = GetLoadedLayout();
123 }
124 else
125 {
126 pLayoutHolder = GetLayout(PEImageLayout::LAYOUT_ANY,LAYOUT_CREATEIFNEEDED);
127 pLayoutToCheck = pLayoutHolder;
128 }
129
130 if (PEFile::ShouldTreatNIAsMSIL())
131 {
132 // This PEImage may intentionally be an NI image, being used as if it were an
133 // MSIL image. In that case, rather than using CheckILFormat on its layout,
134 // do CheckCORFormat(), which is the same as CheckILFormat, except it allows for
135 // a native header. (CheckILFormat() fails if it finds a native header.)
136 CHECK(pLayoutToCheck->CheckCORFormat());
137 }
138 else
139 {
140 CHECK(pLayoutToCheck->CheckILFormat());
141 }
142
143 CHECK_OK;
144};
145
146/* static */
147// This method is only intended to be called during NGen. It doesn't AddRef to the objects it returns,
148// and can be unsafe for general use.
149void PEImage::GetAll(SArray<PEImage*> &images)
150{
151 CONTRACTL
152 {
153 THROWS;
154 GC_TRIGGERS;
155 MODE_ANY;
156 }
157 CONTRACTL_END;
158
159 CrstHolder holder(&s_hashLock);
160
161 for (PtrHashMap::PtrIterator i = s_Images->begin(); !i.end(); ++i)
162 {
163 PEImage *image = (PEImage*) i.GetValue();
164 images.Append(image);
165 }
166}
167
168PEImage::~PEImage()
169{
170 CONTRACTL
171 {
172 PRECONDITION(CheckStartup());
173 PRECONDITION(m_refCount == 0);
174 DESTRUCTOR_CHECK;
175 NOTHROW;
176 GC_TRIGGERS;
177 MODE_ANY;
178 }
179 CONTRACTL_END;
180
181 GCX_PREEMP();
182
183 if (m_pLayoutLock)
184 delete m_pLayoutLock;
185 if(m_hFile!=INVALID_HANDLE_VALUE && m_bOwnHandle)
186 CloseHandle(m_hFile);
187
188 for (unsigned int i=0;i<COUNTOF(m_pLayouts);i++)
189 {
190 if (m_pLayouts[i]!=NULL)
191 m_pLayouts[i]->Release();
192 }
193
194 if (m_pMDImport)
195 m_pMDImport->Release();
196 if(m_pNativeMDImport)
197 m_pNativeMDImport->Release();
198#ifdef METADATATRACKER_ENABLED
199 if (m_pMDTracker != NULL)
200 m_pMDTracker->Deactivate();
201#endif // METADATATRACKER_ENABLED
202
203}
204
205/* static */
206BOOL PEImage::CompareIJWDataBase(UPTR base, UPTR mapping)
207{
208 CONTRACTL{
209 PRECONDITION(CheckStartup());
210 PRECONDITION(CheckPointer((BYTE *)(base << 1)));
211 PRECONDITION(CheckPointer((IJWFixupData *)mapping));
212 NOTHROW;
213 GC_NOTRIGGER;
214 MODE_ANY;
215 } CONTRACTL_END;
216
217 return ((BYTE *)(base << 1) == ((IJWFixupData*)mapping)->GetBase());
218}
219
220 // Thread stress
221#if 0
222class OpenFileStress : APIThreadStress
223 {
224 public:
225 const SString &path;
226 PEImage::Layout layout;
227 OpenFileStress(const SString &path, PEImage::Layout layout)
228 : path(path), layout(layout)
229 {
230 WRAPPER_NO_CONTRACT;
231
232 path.Normalize();
233 }
234 void Invoke()
235 {
236 WRAPPER_NO_CONTRACT;
237
238 PEImageHolder result(PEImage::Open(path, layout));
239 }
240};
241#endif
242
243ULONG PEImage::Release()
244{
245 CONTRACTL
246 {
247 DESTRUCTOR_CHECK;
248 NOTHROW;
249 MODE_ANY;
250 FORBID_FAULT;
251 }
252 CONTRACTL_END;
253
254 CONTRACT_VIOLATION(FaultViolation|ThrowsViolation);
255 COUNT_T result = 0;
256 {
257 // Use scoping to hold the hash lock
258 CrstHolder holder(&s_hashLock);
259
260 // Decrement and check the refcount - if we hit 0, remove it from the hash and delete it.
261 result=FastInterlockDecrement(&m_refCount);
262 if (result == 0 )
263 {
264 LOG((LF_LOADER, LL_INFO100, "PEImage: Closing Image %S\n", (LPCWSTR) m_path));
265 if(m_bInHashMap)
266 {
267 PEImageLocator locator(this);
268 PEImage* deleted = (PEImage *)s_Images->DeleteValue(GetIDHash(), &locator);
269 _ASSERTE(deleted == this);
270 }
271 }
272 }
273
274#ifdef FEATURE_LAZY_COW_PAGES
275 if (result == 0 && m_bAllocatedLazyCOWPages)
276 ::FreeLazyCOWPages(GetLoadedLayout());
277#endif
278
279 // This needs to be done outside of the hash lock, since this can call FreeLibrary,
280 // which can cause _CorDllMain to be executed, which can cause the hash lock to be
281 // taken again because we need to release the IJW fixup data in another PEImage hash.
282 if (result == 0)
283 delete this;
284
285 return result;
286}
287
288/* static */
289CHECK PEImage::CheckCanonicalFullPath(const SString &path)
290{
291 CONTRACT_CHECK
292 {
293 PRECONDITION(CheckValue(path));
294 GC_NOTRIGGER;
295 MODE_ANY;
296 }
297 CONTRACT_CHECK_END;
298
299 CCHECK_START
300 {
301 // This is not intended to be an exhaustive test, just to provide a sanity check
302
303 SString::CIterator i = path.Begin();
304
305 SString sNetworkPathPrefix(SString::Literal, W("\\\\"));
306 if (path.Skip(i, sNetworkPathPrefix))
307 {
308 // Network path
309 }
310 else if (iswalpha(*i))
311 {
312 // Drive path
313 i++;
314 SString sDrivePath(SString::Literal, ":\\");
315 CCHECK(path.Skip(i, sDrivePath));
316 }
317 else
318 {
319 CCHECK_FAIL("Not a full path");
320 }
321
322 while (i != path.End())
323 {
324 // Check for multiple slashes
325 if(*i != '\\')
326 {
327
328 // Check for . or ..
329 SString sParentDir(SString::Ascii, "..");
330 SString sCurrentDir(SString::Ascii, ".");
331 if ((path.Skip(i, sParentDir) || path.Skip(i, sCurrentDir))
332 && (path.Match(i, '\\')))
333 {
334 CCHECK_FAIL("Illegal . or ..");
335 }
336
337 if (!path.Find(i, '\\'))
338 break;
339 }
340
341 i++;
342 }
343 }
344 CCHECK_END;
345
346 CHECK_OK;
347}
348
349#ifdef FEATURE_USE_LCID
350LCID g_lcid =0; // fusion path comparison lcid
351#else
352LPCWSTR g_lcid=NULL;
353#endif
354/* static */
355LocaleID PEImage::GetFileSystemLocale()
356{
357 LIMITED_METHOD_CONTRACT;
358 return g_lcid;
359}
360
361BOOL PEImage::PathEquals(const SString &p1, const SString &p2)
362{
363 CONTRACTL
364 {
365 THROWS;
366 GC_NOTRIGGER;
367 MODE_ANY;
368 }
369 CONTRACTL_END;
370
371#ifdef FEATURE_CASE_SENSITIVE_FILESYSTEM
372 return p1.Equals(p2);
373#else
374 return p1.EqualsCaseInsensitive(p2, g_lcid);
375#endif
376}
377
378#ifndef FEATURE_PAL
379/* static */
380void PEImage::GetPathFromDll(HINSTANCE hMod, SString &result)
381{
382 CONTRACTL
383 {
384 PRECONDITION(CheckStartup());
385 PRECONDITION(CheckPointer(hMod));
386 PRECONDITION(CheckValue(result));
387 THROWS;
388 GC_NOTRIGGER;
389 MODE_ANY;
390 INJECT_FAULT(COMPlusThrowOM(););
391 }
392 CONTRACTL_END;
393
394 WszGetModuleFileName(hMod, result);
395
396}
397#endif // !FEATURE_PAL
398
399/* static */
400BOOL PEImage::CompareImage(UPTR u1, UPTR u2)
401{
402 CONTRACTL
403 {
404 NOTHROW;
405 GC_NOTRIGGER;
406 MODE_ANY;
407 }
408 CONTRACTL_END;
409
410 // This is the input to the lookup
411 PEImageLocator *pLocator = (PEImageLocator *) (u1<<1);
412
413 // This is the value stored in the table
414 PEImage *pImage = (PEImage *) u2;
415
416
417 BOOL ret = FALSE;
418 HRESULT hr;
419 EX_TRY
420 {
421 SString path(SString::Literal, pLocator->m_pPath);
422 if (PathEquals(path, pImage->GetPath()))
423 ret = TRUE;
424 }
425 EX_CATCH_HRESULT(hr); //<TODO>ignores failure!</TODO>
426 return ret;
427}
428
429BOOL PEImage::Equals(PEImage *pImage)
430{
431 CONTRACTL
432 {
433 INSTANCE_CHECK;
434 PRECONDITION(CheckPointer(pImage));
435 NOTHROW;
436 GC_NOTRIGGER;
437 MODE_ANY;
438 }
439 CONTRACTL_END;
440
441 // PEImage is always unique on CoreCLR so a simple pointer check is sufficient
442 _ASSERTE(m_bInHashMap || GetPath().IsEmpty());
443 _ASSERTE(pImage->m_bInHashMap || pImage->GetPath().IsEmpty());
444
445 return dac_cast<TADDR>(pImage) == dac_cast<TADDR>(this);
446}
447
448
449IMDInternalImport* PEImage::GetMDImport()
450{
451 WRAPPER_NO_CONTRACT;
452 if (!m_pMDImport)
453 OpenMDImport();
454 return m_pMDImport;
455}
456
457#ifdef FEATURE_PREJIT
458IMDInternalImport* PEImage::GetNativeMDImport(BOOL loadAllowed)
459{
460 CONTRACTL
461 {
462 INSTANCE_CHECK;
463 PRECONDITION(HasNativeHeader());
464 if (loadAllowed) GC_TRIGGERS; else GC_NOTRIGGER;
465 if (loadAllowed) THROWS; else NOTHROW;
466 if (loadAllowed) INJECT_FAULT(COMPlusThrowOM()); else FORBID_FAULT;
467 MODE_ANY;
468 }
469 CONTRACTL_END;
470
471 if (m_pNativeMDImport == NULL)
472 {
473 if (loadAllowed)
474 OpenNativeMDImport();
475 else
476 return NULL;
477 }
478
479 _ASSERTE(m_pNativeMDImport);
480 return m_pNativeMDImport;
481}
482
483void PEImage::OpenNativeMDImport()
484{
485 CONTRACTL
486 {
487 INSTANCE_CHECK;
488 PRECONDITION(HasNativeHeader());
489 GC_TRIGGERS;
490 THROWS;
491 MODE_ANY;
492 INJECT_FAULT(COMPlusThrowOM(););
493 }
494 CONTRACTL_END;
495 if (m_pNativeMDImport==NULL)
496 {
497 IMDInternalImport* m_pNewImport;
498 COUNT_T cMeta=0;
499 const void* pMeta=GetNativeManifestMetadata(&cMeta);
500
501 if(pMeta==NULL)
502 return;
503
504 IfFailThrow(GetMetaDataInternalInterface((void *) pMeta,
505 cMeta,
506 ofRead,
507 IID_IMDInternalImport,
508 (void **) &m_pNewImport));
509
510 if(FastInterlockCompareExchangePointer(&m_pNativeMDImport, m_pNewImport, NULL))
511 m_pNewImport->Release();
512 }
513 _ASSERTE(m_pNativeMDImport);
514}
515#endif
516
517void PEImage::OpenMDImport()
518{
519 CONTRACTL
520 {
521 INSTANCE_CHECK;
522 PRECONDITION(HasCorHeader());
523 PRECONDITION(HasContents());
524 GC_TRIGGERS;
525 THROWS;
526 MODE_ANY;
527 INJECT_FAULT(COMPlusThrowOM(););
528 }
529 CONTRACTL_END;
530 if (m_pMDImport==NULL)
531 {
532 IMDInternalImport* m_pNewImport;
533 const void* pMeta=NULL;
534 COUNT_T cMeta=0;
535 if(HasNTHeaders() && HasCorHeader())
536 pMeta=GetMetadata(&cMeta);
537
538 if(pMeta==NULL)
539 return;
540
541#if METADATATRACKER_ENABLED
542 m_pMDTracker = MetaDataTracker::GetOrCreateMetaDataTracker((BYTE *)pMeta,
543 cMeta,
544 GetPath().GetUnicode());
545#endif // METADATATRACKER_ENABLED
546
547 IfFailThrow(GetMetaDataInternalInterface((void *) pMeta,
548 cMeta,
549 ofRead,
550 IID_IMDInternalImport,
551 (void **) &m_pNewImport));
552
553 if(FastInterlockCompareExchangePointer(&m_pMDImport, m_pNewImport, NULL))
554 {
555 m_pNewImport->Release();
556 }
557 else
558 {
559 // grab the module name. This information is only used for dac. But we need to get
560 // it when module is instantiated in the managed process. The module name is stored
561 // in Metadata's module table in UTF8. Convert it to unicode.
562 //
563 if (m_path.IsEmpty())
564 {
565 // No need to check error here since this info is only used by DAC when inspecting
566 // dump file.
567 //
568 LPCSTR strModuleName;
569 IfFailThrow(m_pMDImport->GetScopeProps(&strModuleName, NULL));
570 m_sModuleFileNameHintUsedByDac.SetUTF8(strModuleName);
571 m_sModuleFileNameHintUsedByDac.Normalize();
572 }
573 }
574
575 if (IsCompilationProcess())
576 {
577 m_pMDImport->SetOptimizeAccessForSpeed(TRUE);
578 }
579 }
580 _ASSERTE(m_pMDImport);
581
582}
583
584void PEImage::GetMVID(GUID *pMvid)
585{
586 CONTRACTL
587 {
588 INSTANCE_CHECK;
589 PRECONDITION(CheckPointer(pMvid));
590 PRECONDITION(HasCorHeader());
591 PRECONDITION(HasContents());
592 GC_TRIGGERS;
593 THROWS;
594 MODE_ANY;
595 INJECT_FAULT(COMPlusThrowOM(););
596 }
597 CONTRACTL_END;
598
599 IfFailThrow(GetMDImport()->GetScopeProps(NULL, pMvid));
600
601#ifdef _DEBUG
602 COUNT_T cMeta;
603 const void *pMeta = GetMetadata(&cMeta);
604 GUID MvidDEBUG;
605
606 if (pMeta == NULL)
607 ThrowHR(COR_E_BADIMAGEFORMAT);
608
609 SafeComHolder<IMDInternalImport> pMDImport;
610
611 IfFailThrow(GetMetaDataInternalInterface((void *) pMeta,
612 cMeta,
613 ofRead,
614 IID_IMDInternalImport,
615 (void **) &pMDImport));
616
617 pMDImport->GetScopeProps(NULL, &MvidDEBUG);
618
619 _ASSERTE(memcmp(pMvid, &MvidDEBUG, sizeof(GUID)) == 0);
620
621#endif // _DEBUG
622}
623
624void PEImage::GetHashedStrongNameSignature(SBuffer &result)
625{
626 COUNT_T size;
627 const void *sig = GetStrongNameSignature(&size);
628
629 SHA1Hash hasher;
630 hasher.AddData((BYTE *) sig, size);
631 result.Set(hasher.GetHash(), SHA1_HASH_SIZE);
632}
633
634
635void PEImage::VerifyIsAssembly()
636{
637 CONTRACTL
638 {
639 THROWS;
640 GC_TRIGGERS;
641 MODE_ANY;
642 }
643 CONTRACTL_END;
644
645 VerifyIsILOrNIAssembly(TRUE);
646}
647
648void PEImage::VerifyIsNIAssembly()
649{
650 CONTRACTL
651 {
652 THROWS;
653 GC_TRIGGERS;
654 MODE_ANY;
655 }
656 CONTRACTL_END;
657
658 VerifyIsILOrNIAssembly(FALSE);
659}
660
661void PEImage::VerifyIsILOrNIAssembly(BOOL fIL)
662{
663 CONTRACTL
664 {
665 THROWS;
666 GC_TRIGGERS;
667 MODE_ANY;
668 }
669 CONTRACTL_END;
670
671 // buch of legacy stuff here wrt the error codes...
672
673 if (!HasNTHeaders())
674 ThrowFormat(COR_E_BADIMAGEFORMAT);
675
676 if(!HasCorHeader())
677 ThrowFormat(COR_E_ASSEMBLYEXPECTED);
678
679 CHECK checkGoodFormat;
680 if (fIL)
681 {
682 checkGoodFormat = CheckILFormat();
683 }
684 else
685 {
686 checkGoodFormat = CheckNativeFormat();
687 }
688 if (!checkGoodFormat)
689 ThrowFormat(COR_E_BADIMAGEFORMAT);
690
691 mdAssembly a;
692 if (FAILED(GetMDImport()->GetAssemblyFromScope(&a)))
693 ThrowFormat(COR_E_ASSEMBLYEXPECTED);
694}
695
696void DECLSPEC_NORETURN PEImage::ThrowFormat(HRESULT hrError)
697{
698 CONTRACTL
699 {
700 GC_TRIGGERS;
701 THROWS;
702 MODE_ANY;
703 }
704 CONTRACTL_END;
705
706 EEFileLoadException::Throw(m_path, hrError);
707}
708
709#if !defined(CROSSGEN_COMPILE)
710
711//may outlive PEImage
712PEImage::IJWFixupData::IJWFixupData(void *pBase)
713 : m_lock(CrstIJWFixupData),
714 m_base(pBase), m_flags(0), m_DllThunkHeap(NULL), m_iNextFixup(0), m_iNextMethod(0)
715{
716 WRAPPER_NO_CONTRACT;
717}
718
719PEImage::IJWFixupData::~IJWFixupData()
720{
721 WRAPPER_NO_CONTRACT;
722 if (m_DllThunkHeap)
723 delete m_DllThunkHeap;
724}
725
726
727// Self-initializing accessor for m_DllThunkHeap
728LoaderHeap *PEImage::IJWFixupData::GetThunkHeap()
729{
730 CONTRACT(LoaderHeap *)
731 {
732 INSTANCE_CHECK;
733 THROWS;
734 GC_NOTRIGGER;
735 MODE_ANY;
736 INJECT_FAULT(COMPlusThrowOM());
737 POSTCONDITION(CheckPointer(RETVAL));
738 }
739 CONTRACT_END
740
741 if (!m_DllThunkHeap)
742 {
743 size_t * pPrivatePCLBytes = NULL;
744 size_t * pGlobalPCLBytes = NULL;
745
746 COUNTER_ONLY(pPrivatePCLBytes = &(GetPerfCounters().m_Loading.cbLoaderHeapSize));
747
748 LoaderHeap *pNewHeap = new LoaderHeap(VIRTUAL_ALLOC_RESERVE_GRANULARITY, // DWORD dwReserveBlockSize
749 0, // DWORD dwCommitBlockSize
750 pPrivatePCLBytes,
751 ThunkHeapStubManager::g_pManager->GetRangeList(),
752 TRUE); // BOOL fMakeExecutable
753
754 if (FastInterlockCompareExchangePointer((PVOID*)&m_DllThunkHeap, (VOID*)pNewHeap, (VOID*)0) != 0)
755 {
756 delete pNewHeap;
757 }
758 }
759
760 RETURN m_DllThunkHeap;
761}
762
763void PEImage::IJWFixupData::MarkMethodFixedUp(COUNT_T iFixup, COUNT_T iMethod)
764{
765 LIMITED_METHOD_CONTRACT;
766 // supports only sequential fixup/method
767 _ASSERTE((iFixup == m_iNextFixup + 1 && iMethod == 0) || //first method of the next fixup or
768 (iFixup == m_iNextFixup && iMethod == m_iNextMethod)); //the method that was next to fixup
769
770 m_iNextFixup = iFixup;
771 m_iNextMethod = iMethod + 1;
772}
773
774BOOL PEImage::IJWFixupData::IsMethodFixedUp(COUNT_T iFixup, COUNT_T iMethod)
775{
776 LIMITED_METHOD_CONTRACT;
777 if (iFixup < m_iNextFixup)
778 return TRUE;
779 if (iFixup > m_iNextFixup)
780 return FALSE;
781 if (iMethod < m_iNextMethod)
782 return TRUE;
783
784 return FALSE;
785}
786
787/*static */
788PTR_LoaderHeap PEImage::GetDllThunkHeap(void *pBase)
789{
790 CONTRACTL
791 {
792 THROWS;
793 GC_TRIGGERS;
794 MODE_ANY;
795 }
796 CONTRACTL_END;
797 return GetIJWData(pBase)->GetThunkHeap();
798}
799
800/* static */
801PEImage::IJWFixupData *PEImage::GetIJWData(void *pBase)
802{
803 CONTRACTL{
804 THROWS;
805 GC_TRIGGERS;
806 MODE_ANY;
807 INJECT_FAULT(COMPlusThrowOM(););
808 } CONTRACTL_END
809
810 // Take the IJW hash lock
811 CrstHolder hashLockHolder(&s_ijwHashLock);
812
813 // Try to find the data
814 IJWFixupData *pData = (IJWFixupData *)s_ijwFixupDataHash->LookupValue((UPTR)pBase, pBase);
815
816 // No data, must create
817 if ((UPTR)pData == (UPTR)INVALIDENTRY)
818 {
819 pData = new IJWFixupData(pBase);
820 s_ijwFixupDataHash->InsertValue((UPTR)pBase, pData);
821 }
822
823 // Return the new data
824 return (pData);
825}
826
827/* static */
828void PEImage::UnloadIJWModule(void *pBase)
829{
830 CONTRACTL{
831 NOTHROW;
832 GC_TRIGGERS;
833 MODE_ANY;
834 } CONTRACTL_END
835
836 // Take the IJW hash lock
837 CrstHolder hashLockHolder(&s_ijwHashLock);
838
839 // Try to delete the hash entry
840 IJWFixupData *pData = (IJWFixupData *)s_ijwFixupDataHash->DeleteValue((UPTR)pBase, pBase);
841
842 // Now delete the data
843 if ((UPTR)pData != (UPTR)INVALIDENTRY)
844 delete pData;
845}
846
847#endif // !CROSSGEN_COMPILE
848
849
850
851#endif // #ifndef DACCESS_COMPILE
852
853#ifdef DACCESS_COMPILE
854
855void PEImage::EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
856{
857 CONTRACTL
858 {
859 INSTANCE_CHECK;
860 NOTHROW;
861 GC_NOTRIGGER;
862 MODE_ANY;
863 SUPPORTS_DAC;
864 }
865 CONTRACTL_END;
866
867 // There are codepaths that will enumerate the PEImage without
868 // calling EnumMemoryRegions; ensure that we will still get
869 // these necessary fields enumerated no matter what.
870 m_path.EnumMemoryRegions(flags);
871
872 // We always want this field in mini/triage/heap dumps.
873 m_sModuleFileNameHintUsedByDac.EnumMemoryRegions(CLRDATA_ENUM_MEM_DEFAULT);
874
875
876 EX_TRY
877 {
878 if (HasLoadedLayout() && HasNTHeaders() && HasDirectoryEntry(IMAGE_DIRECTORY_ENTRY_DEBUG))
879 {
880 // Get a pointer to the contents and size of the debug directory and report it
881 COUNT_T cbDebugDir;
882 TADDR taDebugDir = GetLoadedLayout()->GetDirectoryEntryData(IMAGE_DIRECTORY_ENTRY_DEBUG, &cbDebugDir);
883 DacEnumMemoryRegion(taDebugDir, cbDebugDir);
884
885 // Report the memory that each debug directory entry points to
886 UINT cNumEntries = cbDebugDir / sizeof(IMAGE_DEBUG_DIRECTORY);
887 PTR_IMAGE_DEBUG_DIRECTORY pDebugEntry = dac_cast<PTR_IMAGE_DEBUG_DIRECTORY>(taDebugDir);
888 for (UINT iIndex = 0; iIndex < cNumEntries; iIndex++)
889 {
890 TADDR taEntryAddr = GetLoadedLayout()->GetRvaData(pDebugEntry[iIndex].AddressOfRawData);
891 DacEnumMemoryRegion(taEntryAddr, pDebugEntry[iIndex].SizeOfData);
892
893 // Triage dumps must not dump full paths as they may contain PII data.
894 // Thus, we replace debug directory's pdbs full path for with filaname only.
895 if (flags == CLRDATA_ENUM_MEM_TRIAGE &&
896 pDebugEntry[iIndex].Type == IMAGE_DEBUG_TYPE_CODEVIEW)
897 {
898 DWORD CvSignature = *(dac_cast<PTR_DWORD>(taEntryAddr));
899 if(CvSignature == CV_SIGNATURE_RSDS)
900 {
901 CV_INFO_PDB70* pCvInfo = (CV_INFO_PDB70*)DacInstantiateTypeByAddressNoReport(taEntryAddr, sizeof(CV_INFO_PDB70), false);
902
903 if (pCvInfo == NULL || pCvInfo->path == NULL)
904 {
905 continue;
906 }
907 // Because data may be corrupted make sure we null terminate the string.
908 pCvInfo->path[MAX_LONGPATH - 1] = '\0';
909
910 //Find the filename from pdb full path
911 char* fileName = strrchr(pCvInfo->path, '\\');
912 if (fileName != NULL)
913 fileName++;
914 else
915 fileName = pCvInfo->path;
916
917 size_t fileNameLenght = strlen(fileName);
918 size_t fullPathLenght = strlen(pCvInfo->path);
919 memmove(pCvInfo->path, fileName, fileNameLenght);
920
921 // NULL out the rest of the path buffer.
922 for (size_t i = fileNameLenght; i < MAX_PATH_FNAME - 1; i++)
923 {
924 pCvInfo->path[i] = '\0';
925 }
926
927 DacUpdateMemoryRegion( taEntryAddr + offsetof(CV_INFO_PDB70, path), sizeof(pCvInfo->path), (PBYTE)pCvInfo->path );
928 }
929 }
930 }
931 }
932 }
933 EX_CATCH_RETHROW_ONLY_COR_E_OPERATIONCANCELLED
934
935 DAC_ENUM_DTHIS();
936
937 EMEM_OUT(("MEM: %p PEImage\n", dac_cast<TADDR>(this)));
938
939 // This just gets the image headers into the dump.
940 // This is used, for example, for ngen images to ensure we have the debug directory so we
941 // can find the managed PDBs.
942 // No lock here as the processs should be suspended.
943 if (m_pLayouts[IMAGE_FLAT].IsValid() && m_pLayouts[IMAGE_FLAT]!=NULL)
944 m_pLayouts[IMAGE_FLAT]->EnumMemoryRegions(flags);
945 if (m_pLayouts[IMAGE_MAPPED].IsValid() && m_pLayouts[IMAGE_MAPPED]!=NULL)
946 m_pLayouts[IMAGE_MAPPED]->EnumMemoryRegions(flags);
947 if (m_pLayouts[IMAGE_LOADED].IsValid() && m_pLayouts[IMAGE_LOADED]!=NULL)
948 m_pLayouts[IMAGE_LOADED]->EnumMemoryRegions(flags);
949}
950
951#endif // #ifdef DACCESS_COMPILE
952
953
954PEImage::PEImage():
955 m_refCount(1),
956 m_bIsTrustedNativeImage(FALSE),
957 m_bIsNativeImageInstall(FALSE),
958 m_bPassiveDomainOnly(FALSE),
959 m_bInHashMap(FALSE),
960#ifdef METADATATRACKER_DATA
961 m_pMDTracker(NULL),
962#endif // METADATATRACKER_DATA
963 m_pMDImport(NULL),
964 m_pNativeMDImport(NULL),
965 m_hFile(INVALID_HANDLE_VALUE),
966 m_bOwnHandle(true),
967 m_bSignatureInfoCached(FALSE),
968 m_hrSignatureInfoStatus(E_UNEXPECTED),
969 m_dwSignatureInfo(0),
970 m_dwPEKind(0),
971 m_dwMachine(0),
972 m_fCachedKindAndMachine(FALSE)
973#ifdef FEATURE_LAZY_COW_PAGES
974 ,m_bAllocatedLazyCOWPages(FALSE)
975#endif // FEATURE_LAZY_COW_PAGES
976{
977 CONTRACTL
978 {
979 THROWS;
980 GC_NOTRIGGER;
981 MODE_ANY;
982 }
983 CONTRACTL_END;
984 for (DWORD i=0;i<COUNTOF(m_pLayouts);i++)
985 m_pLayouts[i]=NULL ;
986 m_pLayoutLock=new SimpleRWLock(PREEMPTIVE,LOCK_TYPE_DEFAULT);
987}
988
989PTR_PEImageLayout PEImage::GetLayout(DWORD imageLayoutMask,DWORD flags)
990{
991 WRAPPER_NO_CONTRACT;
992 SUPPORTS_DAC;
993
994 PTR_PEImageLayout pRetVal;
995
996#ifndef DACCESS_COMPILE
997 BEGIN_SO_INTOLERANT_CODE(GetThread());
998 // First attempt to find an existing layout matching imageLayoutMask. If that fails,
999 // and the caller has asked us to create layouts if needed, then try again passing
1000 // the create flag to GetLayoutInternal. We need this to be synchronized, but the common
1001 // case is that the layout already exists, so use a reader-writer lock.
1002 GCX_PREEMP();
1003 {
1004 SimpleReadLockHolder lock(m_pLayoutLock);
1005 pRetVal=GetLayoutInternal(imageLayoutMask,flags&(~LAYOUT_CREATEIFNEEDED));
1006 }
1007
1008 if (!(pRetVal || (flags&LAYOUT_CREATEIFNEEDED)==0))
1009 {
1010 SimpleWriteLockHolder lock(m_pLayoutLock);
1011 pRetVal = GetLayoutInternal(imageLayoutMask,flags);
1012 }
1013 END_SO_INTOLERANT_CODE;
1014
1015 return pRetVal;
1016
1017#else
1018 // In DAC builds, we can't create any layouts - we must require that they already exist.
1019 // We also don't take any AddRefs or locks in DAC builds - it's inspection-only.
1020 pRetVal = GetExistingLayoutInternal(imageLayoutMask);
1021 if ((pRetVal==NULL) && (flags & LAYOUT_CREATEIFNEEDED))
1022 {
1023 _ASSERTE_MSG(false, "DACization error - caller expects PEImage layout to exist and it doesn't");
1024 DacError(E_UNEXPECTED);
1025 }
1026 return pRetVal;
1027#endif
1028}
1029
1030#ifndef DACCESS_COMPILE
1031
1032PTR_PEImageLayout PEImage::GetLayoutInternal(DWORD imageLayoutMask,DWORD flags)
1033{
1034 CONTRACTL
1035 {
1036 THROWS;
1037 GC_TRIGGERS;
1038 MODE_ANY;
1039 }
1040 CONTRACTL_END;
1041
1042 PTR_PEImageLayout pRetVal=GetExistingLayoutInternal(imageLayoutMask);
1043
1044 if (pRetVal==NULL && (flags&LAYOUT_CREATEIFNEEDED))
1045 {
1046 _ASSERTE(HasID());
1047
1048 BOOL bIsMappedLayoutSuitable = ((imageLayoutMask & PEImageLayout::LAYOUT_MAPPED) != 0);
1049 BOOL bIsFlatLayoutSuitable = ((imageLayoutMask & PEImageLayout::LAYOUT_FLAT) != 0);
1050
1051#if !defined(PLATFORM_UNIX)
1052 if (bIsMappedLayoutSuitable)
1053 {
1054 bIsFlatLayoutSuitable = FALSE;
1055 }
1056#endif // !PLATFORM_UNIX
1057
1058 _ASSERTE(bIsMappedLayoutSuitable || bIsFlatLayoutSuitable);
1059
1060 BOOL bIsMappedLayoutRequired = !bIsFlatLayoutSuitable;
1061 BOOL bIsFlatLayoutRequired = !bIsMappedLayoutSuitable;
1062
1063 if (bIsFlatLayoutRequired
1064 || (bIsFlatLayoutSuitable && !m_bIsTrustedNativeImage))
1065 {
1066 _ASSERTE(bIsFlatLayoutSuitable);
1067
1068 BOOL bPermitWriteableSections = bIsFlatLayoutRequired;
1069
1070 pRetVal = PEImage::CreateLayoutFlat(bPermitWriteableSections);
1071 }
1072
1073 if (pRetVal == NULL)
1074 {
1075 _ASSERTE(bIsMappedLayoutSuitable);
1076
1077 pRetVal = PEImage::CreateLayoutMapped();
1078 }
1079 }
1080
1081 if (pRetVal != NULL)
1082 {
1083 pRetVal->AddRef();
1084 }
1085
1086 return pRetVal;
1087}
1088
1089PTR_PEImageLayout PEImage::CreateLayoutMapped()
1090{
1091 CONTRACTL
1092 {
1093 THROWS;
1094 GC_TRIGGERS;
1095 MODE_ANY;
1096 PRECONDITION(m_pLayoutLock->IsWriterLock());
1097 }
1098 CONTRACTL_END;
1099
1100 PTR_PEImageLayout pRetVal;
1101
1102 PEImageLayout * pLoadLayout = NULL;
1103
1104 if (m_bIsTrustedNativeImage || IsFile())
1105 {
1106 // For CoreCLR, try to load all files via LoadLibrary first. If LoadLibrary did not work, retry using
1107 // regular mapping - but not for native images.
1108 pLoadLayout = PEImageLayout::Load(this, FALSE /* bNTSafeLoad */, m_bIsTrustedNativeImage /* bThrowOnError */);
1109 }
1110
1111 if (pLoadLayout != NULL)
1112 {
1113 SetLayout(IMAGE_MAPPED,pLoadLayout);
1114 pLoadLayout->AddRef();
1115 SetLayout(IMAGE_LOADED,pLoadLayout);
1116 pRetVal=pLoadLayout;
1117 }
1118 else if (IsFile())
1119 {
1120 PEImageLayoutHolder pLayout(PEImageLayout::Map(GetFileHandle(),this));
1121
1122 bool fMarkAnyCpuImageAsLoaded = false;
1123 // Avoid mapping another image if we can. We can only do this for IL-ONLY images
1124 // since LoadLibrary is needed if we are to actually load code
1125 if (pLayout->HasCorHeader())
1126 {
1127 if (pLayout->IsILOnly())
1128 {
1129 // For CoreCLR, IL only images will always be mapped. We also dont bother doing the conversion of PE header on 64bit,
1130 // as done below for the desktop case, as there is no appcompat burden for CoreCLR on 64bit to have that conversion done.
1131 fMarkAnyCpuImageAsLoaded = true;
1132 }
1133 else
1134 {
1135 // IJW images must be loaded, not mapped
1136 ThrowHR(COR_E_BADIMAGEFORMAT);
1137 }
1138 }
1139
1140 pLayout.SuppressRelease();
1141
1142 SetLayout(IMAGE_MAPPED,pLayout);
1143 if (fMarkAnyCpuImageAsLoaded)
1144 {
1145 pLayout->AddRef();
1146 SetLayout(IMAGE_LOADED, pLayout);
1147 }
1148 pRetVal=pLayout;
1149 }
1150 else
1151 {
1152 PEImageLayoutHolder flatPE(GetLayoutInternal(PEImageLayout::LAYOUT_FLAT,LAYOUT_CREATEIFNEEDED));
1153 if (!flatPE->CheckFormat() || !flatPE->IsILOnly())
1154 ThrowHR(COR_E_BADIMAGEFORMAT);
1155 pRetVal=PEImageLayout::LoadFromFlat(flatPE);
1156 SetLayout(IMAGE_MAPPED,pRetVal);
1157 }
1158
1159 return pRetVal;
1160}
1161
1162PTR_PEImageLayout PEImage::CreateLayoutFlat(BOOL bPermitWriteableSections)
1163{
1164 CONTRACTL
1165 {
1166 GC_TRIGGERS;
1167 MODE_ANY;
1168 PRECONDITION(m_pLayoutLock->IsWriterLock());
1169 }
1170 CONTRACTL_END;
1171
1172 _ASSERTE(m_pLayouts[IMAGE_FLAT] == NULL);
1173
1174 PTR_PEImageLayout pFlatLayout = PEImageLayout::LoadFlat(GetFileHandle(),this);
1175
1176 if (!bPermitWriteableSections
1177 && pFlatLayout->CheckNTHeaders()
1178 && pFlatLayout->HasWriteableSections())
1179 {
1180 pFlatLayout->Release();
1181
1182 return NULL;
1183 }
1184 else
1185 {
1186 m_pLayouts[IMAGE_FLAT] = pFlatLayout;
1187
1188 return pFlatLayout;
1189 }
1190}
1191
1192/* static */
1193PTR_PEImage PEImage::LoadFlat(const void *flat, COUNT_T size)
1194{
1195 CONTRACT(PTR_PEImage)
1196 {
1197 STANDARD_VM_CHECK;
1198 }
1199 CONTRACT_END;
1200
1201 PEImageHolder pImage(new PEImage());
1202 PTR_PEImageLayout pLayout = PEImageLayout::CreateFlat(flat,size,pImage);
1203 _ASSERTE(!pLayout->IsMapped());
1204 pImage->SetLayout(IMAGE_FLAT,pLayout);
1205 RETURN dac_cast<PTR_PEImage>(pImage.Extract());
1206}
1207
1208#ifndef FEATURE_PAL
1209/* static */
1210PTR_PEImage PEImage::LoadImage(HMODULE hMod)
1211{
1212 CONTRACT(PTR_PEImage)
1213 {
1214 STANDARD_VM_CHECK;
1215 PRECONDITION(hMod!=NULL);
1216 POSTCONDITION(RETVAL->HasLoadedLayout());
1217 }
1218 CONTRACT_END;
1219
1220 StackSString path;
1221 GetPathFromDll(hMod, path);
1222 PEImageHolder pImage(PEImage::OpenImage(path,(MDInternalImportFlags)(MDInternalImport_CheckLongPath|MDInternalImport_CheckShortPath)));
1223 if (pImage->HasLoadedLayout())
1224 RETURN dac_cast<PTR_PEImage>(pImage.Extract());
1225
1226 SimpleWriteLockHolder lock(pImage->m_pLayoutLock);
1227
1228 if(pImage->m_pLayouts[IMAGE_LOADED]==NULL)
1229 pImage->SetLayout(IMAGE_LOADED,PEImageLayout::CreateFromHMODULE(hMod,pImage,WszGetModuleHandle(NULL)!=hMod));
1230
1231 if(pImage->m_pLayouts[IMAGE_MAPPED]==NULL)
1232 {
1233 pImage->m_pLayouts[IMAGE_LOADED]->AddRef();
1234 pImage->SetLayout(IMAGE_MAPPED,pImage->m_pLayouts[IMAGE_LOADED]);
1235 }
1236
1237 RETURN dac_cast<PTR_PEImage>(pImage.Extract());
1238}
1239#endif // !FEATURE_PAL
1240
1241void PEImage::Load()
1242{
1243 STANDARD_VM_CONTRACT;
1244
1245 // Performance optimization to avoid lock acquisition
1246 if (HasLoadedLayout())
1247 {
1248 _ASSERTE(GetLoadedLayout()->IsMapped()||GetLoadedLayout()->IsILOnly());
1249 return;
1250 }
1251
1252 SimpleWriteLockHolder lock(m_pLayoutLock);
1253
1254 // Re-check after lock is acquired as HasLoadedLayout here and the above line
1255 // may return a different value in multi-threading environment.
1256 if (HasLoadedLayout())
1257 {
1258 return;
1259 }
1260
1261#ifdef PLATFORM_UNIX
1262 if (m_pLayouts[IMAGE_FLAT] != NULL
1263 && m_pLayouts[IMAGE_FLAT]->CheckILOnlyFormat()
1264 && !m_pLayouts[IMAGE_FLAT]->HasWriteableSections())
1265 {
1266 // IL-only images with writeable sections are mapped in general way,
1267 // because the writeable sections should always be page-aligned
1268 // to make possible setting another protection bits exactly for these sections
1269 _ASSERTE(!m_pLayouts[IMAGE_FLAT]->HasWriteableSections());
1270
1271 // As the image is IL-only, there should no be native code to execute
1272 _ASSERTE(!m_pLayouts[IMAGE_FLAT]->HasNativeEntryPoint());
1273
1274 m_pLayouts[IMAGE_FLAT]->AddRef();
1275
1276 SetLayout(IMAGE_LOADED, m_pLayouts[IMAGE_FLAT]);
1277 }
1278 else
1279#endif // PLATFORM_UNIX
1280 {
1281 if(!IsFile())
1282 {
1283 _ASSERTE(m_pLayouts[IMAGE_FLAT] != NULL);
1284
1285 if (!m_pLayouts[IMAGE_FLAT]->CheckILOnly())
1286 ThrowHR(COR_E_BADIMAGEFORMAT);
1287 if(m_pLayouts[IMAGE_LOADED]==NULL)
1288 SetLayout(IMAGE_LOADED,PEImageLayout::LoadFromFlat(m_pLayouts[IMAGE_FLAT]));
1289 }
1290 else
1291 {
1292 if(m_pLayouts[IMAGE_LOADED]==NULL)
1293 SetLayout(IMAGE_LOADED,PEImageLayout::Load(this,TRUE));
1294 }
1295 }
1296}
1297
1298void PEImage::SetLoadedHMODULE(HMODULE hMod)
1299{
1300 WRAPPER_NO_CONTRACT;
1301 SimpleWriteLockHolder lock(m_pLayoutLock);
1302 if(m_pLayouts[IMAGE_LOADED])
1303 {
1304 _ASSERTE(m_pLayouts[IMAGE_LOADED]->GetBase()==hMod);
1305 return;
1306 }
1307 SetLayout(IMAGE_LOADED,PEImageLayout::CreateFromHMODULE(hMod,this,TRUE));
1308}
1309
1310void PEImage::LoadFromMapped()
1311{
1312 STANDARD_VM_CONTRACT;
1313
1314 if (HasLoadedLayout())
1315 {
1316 _ASSERTE(GetLoadedLayout()->IsMapped());
1317 return;
1318 }
1319
1320 PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_MAPPED,LAYOUT_CREATEIFNEEDED));
1321 SimpleWriteLockHolder lock(m_pLayoutLock);
1322 if(m_pLayouts[IMAGE_LOADED]==NULL)
1323 SetLayout(IMAGE_LOADED,pLayout.Extract());
1324}
1325
1326void PEImage::LoadNoFile()
1327{
1328 CONTRACTL
1329 {
1330 STANDARD_VM_CHECK;
1331 PRECONDITION(!IsFile());
1332 }
1333 CONTRACTL_END;
1334 if (HasLoadedLayout())
1335 return;
1336
1337 PEImageLayoutHolder pLayout(GetLayout(PEImageLayout::LAYOUT_ANY,0));
1338 if (!pLayout->CheckILOnly())
1339 ThrowHR(COR_E_BADIMAGEFORMAT);
1340 SimpleWriteLockHolder lock(m_pLayoutLock);
1341 if(m_pLayouts[IMAGE_LOADED]==NULL)
1342 SetLayout(IMAGE_LOADED,pLayout.Extract());
1343}
1344
1345
1346void PEImage::LoadNoMetaData()
1347{
1348 STANDARD_VM_CONTRACT;
1349
1350 if (HasLoadedLayout())
1351 return;
1352
1353 SimpleWriteLockHolder lock(m_pLayoutLock);
1354 if (m_pLayouts[IMAGE_LOADED]!=NULL)
1355 return;
1356 if (m_pLayouts[IMAGE_FLAT]!=NULL)
1357 {
1358 m_pLayouts[IMAGE_FLAT]->AddRef();
1359 SetLayout(IMAGE_LOADED,m_pLayouts[IMAGE_FLAT]);
1360 }
1361 else
1362 {
1363 _ASSERTE(!m_path.IsEmpty());
1364 SetLayout(IMAGE_LOADED,PEImageLayout::LoadFlat(GetFileHandle(),this));
1365 }
1366}
1367
1368
1369#endif //DACCESS_COMPILE
1370
1371//-------------------------------------------------------------------------------
1372// Make best-case effort to obtain an image name for use in an error message.
1373//
1374// This routine must expect to be called before the this object is fully loaded.
1375// It can return an empty if the name isn't available or the object isn't initialized
1376// enough to get a name, but it mustn't crash.
1377//-------------------------------------------------------------------------------
1378LPCWSTR PEImage::GetPathForErrorMessages()
1379{
1380 CONTRACTL
1381 {
1382 THROWS;
1383 GC_TRIGGERS;
1384 INJECT_FAULT(COMPlusThrowOM(););
1385 SUPPORTS_DAC_HOST_ONLY;
1386 }
1387 CONTRACTL_END
1388
1389 return m_path;
1390}
1391
1392
1393HANDLE PEImage::GetFileHandle()
1394{
1395 CONTRACTL
1396 {
1397 STANDARD_VM_CHECK;
1398 PRECONDITION(m_pLayoutLock->IsWriterLock());
1399 }
1400 CONTRACTL_END;
1401
1402 if (m_hFile!=INVALID_HANDLE_VALUE)
1403 return m_hFile;
1404
1405 {
1406 ErrorModeHolder mode(SEM_NOOPENFILEERRORBOX|SEM_FAILCRITICALERRORS);
1407 m_hFile=WszCreateFile((LPCWSTR) m_path,
1408 GENERIC_READ,
1409 FILE_SHARE_READ|FILE_SHARE_DELETE,
1410 NULL,
1411 OPEN_EXISTING,
1412 FILE_ATTRIBUTE_NORMAL,
1413 NULL);
1414 }
1415
1416 if (m_hFile == INVALID_HANDLE_VALUE)
1417 {
1418#if !defined(DACCESS_COMPILE)
1419 EEFileLoadException::Throw(m_path, HRESULT_FROM_WIN32(GetLastError()));
1420#else // defined(DACCESS_COMPILE)
1421 ThrowLastError();
1422#endif // !defined(DACCESS_COMPILE)
1423 }
1424
1425 return m_hFile;
1426}
1427
1428void PEImage::SetFileHandle(HANDLE hFile)
1429{
1430 CONTRACTL
1431 {
1432 STANDARD_VM_CHECK;
1433 }
1434 CONTRACTL_END;
1435
1436 SimpleWriteLockHolder lock(m_pLayoutLock);
1437 if (m_hFile == INVALID_HANDLE_VALUE)
1438 {
1439 m_hFile = hFile;
1440 m_bOwnHandle = false;
1441 }
1442}
1443
1444HRESULT PEImage::TryOpenFile()
1445{
1446 STANDARD_VM_CONTRACT;
1447
1448 SimpleWriteLockHolder lock(m_pLayoutLock);
1449
1450 if (m_hFile!=INVALID_HANDLE_VALUE)
1451 return S_OK;
1452 {
1453 ErrorModeHolder mode(SEM_NOOPENFILEERRORBOX|SEM_FAILCRITICALERRORS);
1454 m_hFile=WszCreateFile((LPCWSTR) m_path,
1455 GENERIC_READ,
1456 FILE_SHARE_READ|FILE_SHARE_DELETE,
1457 NULL,
1458 OPEN_EXISTING,
1459 FILE_ATTRIBUTE_NORMAL,
1460 NULL);
1461 }
1462 if (m_hFile != INVALID_HANDLE_VALUE)
1463 return S_OK;
1464 if (GetLastError())
1465 return HRESULT_FROM_WIN32(GetLastError());
1466 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
1467}
1468
1469
1470BOOL PEImage::IsPtrInImage(PTR_CVOID data)
1471{
1472 CONTRACTL
1473 {
1474 INSTANCE_CHECK;
1475 NOTHROW;
1476 GC_NOTRIGGER;
1477 FORBID_FAULT;
1478 SO_TOLERANT;
1479 SUPPORTS_DAC;
1480 }
1481 CONTRACTL_END;
1482
1483 for (int i = 0; i < IMAGE_COUNT; i++)
1484 {
1485 if (m_pLayouts[i] != NULL)
1486 {
1487 if (m_pLayouts[i]->PointerInPE(data))
1488 return TRUE;
1489 }
1490 }
1491
1492 return FALSE;
1493}
1494
1495
1496#if !defined(DACCESS_COMPILE)
1497PEImage * PEImage::OpenImage(
1498 ICLRPrivResource * pIResource,
1499 MDInternalImportFlags flags)
1500{
1501 STANDARD_VM_CONTRACT;
1502 HRESULT hr = S_OK;
1503
1504 PEImageHolder pPEImage;
1505
1506
1507 IID iidResource;
1508 IfFailThrow(pIResource->GetResourceType(&iidResource));
1509
1510 if (iidResource == __uuidof(ICLRPrivResourcePath))
1511 {
1512 ReleaseHolder<ICLRPrivResourcePath> pIResourcePath;
1513 IfFailThrow(pIResource->QueryInterface(__uuidof(ICLRPrivResourcePath), (LPVOID*)&pIResourcePath));
1514 WCHAR wzPath[_MAX_PATH];
1515 DWORD cchPath = NumItems(wzPath);
1516 IfFailThrow(pIResourcePath->GetPath(cchPath, &cchPath, wzPath));
1517 pPEImage = PEImage::OpenImage(wzPath, flags);
1518 }
1519#ifndef FEATURE_PAL
1520 else if (iidResource ==__uuidof(ICLRPrivResourceHMODULE))
1521 {
1522 ReleaseHolder<ICLRPrivResourceHMODULE> pIResourceHMODULE;
1523 _ASSERTE(flags == MDInternalImport_Default);
1524 IfFailThrow(pIResource->QueryInterface(__uuidof(ICLRPrivResourceHMODULE), (LPVOID*)&pIResourceHMODULE));
1525 HMODULE hMod;
1526 IfFailThrow(pIResourceHMODULE->GetHMODULE(&hMod));
1527 pPEImage = PEImage::LoadImage(hMod);
1528 }
1529#endif // !FEATURE_PAL
1530 else
1531 {
1532 ThrowHR(COR_E_BADIMAGEFORMAT);
1533 }
1534
1535 return pPEImage.Extract();
1536}
1537#endif
1538
1539
1540