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 | // PEFile.inl |
6 | // |
7 | |
8 | // -------------------------------------------------------------------------------- |
9 | |
10 | #ifndef PEFILE_INL_ |
11 | #define PEFILE_INL_ |
12 | |
13 | #include "strongname.h" |
14 | #include "strongnameholders.h" |
15 | #include "check.h" |
16 | #include "simplerwlock.hpp" |
17 | #include "eventtrace.h" |
18 | #include "peimagelayout.inl" |
19 | |
20 | #if CHECK_INVARIANTS |
21 | inline CHECK PEFile::Invariant() |
22 | { |
23 | CONTRACT_CHECK |
24 | { |
25 | INSTANCE_CHECK; |
26 | THROWS; |
27 | GC_TRIGGERS; |
28 | MODE_ANY; |
29 | } |
30 | CONTRACT_CHECK_END; |
31 | |
32 | if (IsDynamic()) |
33 | { |
34 | // dynamic module case |
35 | CHECK(m_openedILimage == NULL); |
36 | #ifdef FEATURE_PREJIT |
37 | CHECK(m_nativeImage == NULL); |
38 | #endif |
39 | CHECK(CheckPointer(m_pEmitter)); |
40 | } |
41 | else |
42 | { |
43 | // If m_image is null, then we should have a native image. However, this is not valid initially |
44 | // during construction. We should find a way to assert this. |
45 | CHECK(CheckPointer((PEImage*) m_openedILimage, NULL_OK)); |
46 | #ifdef FEATURE_PREJIT |
47 | CHECK(CheckPointer((PEImage*) m_nativeImage, NULL_OK)); |
48 | #endif |
49 | } |
50 | CHECK_OK; |
51 | } |
52 | #endif // CHECK_INVARIANTS |
53 | |
54 | // ------------------------------------------------------------ |
55 | // AddRef/Release |
56 | // ------------------------------------------------------------ |
57 | |
58 | inline ULONG PEFile::AddRef() |
59 | { |
60 | CONTRACTL |
61 | { |
62 | PRECONDITION(m_refCount < COUNT_T_MAX); |
63 | NOTHROW; |
64 | GC_NOTRIGGER; |
65 | CANNOT_TAKE_LOCK; |
66 | MODE_ANY; |
67 | } |
68 | CONTRACTL_END; |
69 | |
70 | return FastInterlockIncrement(&m_refCount); |
71 | } |
72 | |
73 | inline ULONG PEFile::Release() |
74 | { |
75 | CONTRACT(COUNT_T) |
76 | { |
77 | DESTRUCTOR_CHECK; |
78 | NOTHROW; |
79 | GC_TRIGGERS; |
80 | MODE_ANY; |
81 | } |
82 | CONTRACT_END; |
83 | |
84 | LONG result = FastInterlockDecrement(&m_refCount); |
85 | _ASSERTE(result >= 0); |
86 | if (result == 0) |
87 | delete this; |
88 | |
89 | RETURN result; |
90 | } |
91 | |
92 | // ------------------------------------------------------------ |
93 | // Identity |
94 | // ------------------------------------------------------------ |
95 | |
96 | inline ULONG PEAssembly::HashIdentity() |
97 | { |
98 | CONTRACTL |
99 | { |
100 | PRECONDITION(CheckPointer(m_identity)); |
101 | MODE_ANY; |
102 | THROWS; |
103 | GC_TRIGGERS; |
104 | } |
105 | CONTRACTL_END; |
106 | return BINDER_SPACE::GetAssemblyFromPrivAssemblyFast(m_pHostAssembly)->GetAssemblyName()->Hash(BINDER_SPACE::AssemblyName::INCLUDE_VERSION); |
107 | } |
108 | |
109 | inline void PEFile::ValidateForExecution() |
110 | { |
111 | CONTRACTL |
112 | { |
113 | MODE_ANY; |
114 | THROWS; |
115 | GC_TRIGGERS; |
116 | } |
117 | CONTRACTL_END; |
118 | |
119 | // We do not need to check NGen images; if it had the attribute, it would have failed to load |
120 | // at NGen time and so there would be no NGen image. |
121 | if (HasNativeImage()) |
122 | return; |
123 | |
124 | // |
125 | // Ensure reference assemblies are not loaded for execution |
126 | // |
127 | ReleaseHolder<IMDInternalImport> mdImport(this->GetMDImportWithRef()); |
128 | if (mdImport->GetCustomAttributeByName(TokenFromRid(1, mdtAssembly), |
129 | g_ReferenceAssemblyAttribute, |
130 | NULL, |
131 | NULL) == S_OK) { |
132 | ThrowHR(COR_E_LOADING_REFERENCE_ASSEMBLY, BFA_REFERENCE_ASSEMBLY); |
133 | } |
134 | |
135 | // |
136 | // Ensure platform is valid for execution |
137 | // |
138 | if (!IsDynamic() && !IsResource()) |
139 | { |
140 | if (IsMarkedAsNoPlatform()) |
141 | { |
142 | if (IsMarkedAsContentTypeWindowsRuntime()) |
143 | { |
144 | ThrowHR(COR_E_LOADING_WINMD_REFERENCE_ASSEMBLY); |
145 | } |
146 | else |
147 | { |
148 | ThrowHR(COR_E_BADIMAGEFORMAT); |
149 | } |
150 | } |
151 | } |
152 | } |
153 | |
154 | |
155 | inline BOOL PEFile::IsMarkedAsNoPlatform() |
156 | { |
157 | WRAPPER_NO_CONTRACT; |
158 | return (IsAfPA_NoPlatform(GetFlags())); |
159 | } |
160 | |
161 | inline BOOL PEFile::IsMarkedAsContentTypeWindowsRuntime() |
162 | { |
163 | WRAPPER_NO_CONTRACT; |
164 | return (IsAfContentType_WindowsRuntime(GetFlags())); |
165 | } |
166 | |
167 | |
168 | inline void PEFile::GetMVID(GUID *pMvid) |
169 | { |
170 | CONTRACTL |
171 | { |
172 | THROWS; |
173 | GC_NOTRIGGER; |
174 | FORBID_FAULT; |
175 | MODE_ANY; |
176 | } |
177 | CONTRACTL_END; |
178 | |
179 | IfFailThrow(GetPersistentMDImport()->GetScopeProps(NULL, pMvid)); |
180 | } |
181 | |
182 | inline BOOL PEFile::PassiveDomainOnly() |
183 | { |
184 | WRAPPER_NO_CONTRACT; |
185 | return HasOpenedILimage() && GetOpenedILimage()->PassiveDomainOnly(); |
186 | } |
187 | |
188 | // ------------------------------------------------------------ |
189 | // Descriptive strings |
190 | // ------------------------------------------------------------ |
191 | |
192 | inline const SString &PEFile::GetPath() |
193 | { |
194 | CONTRACTL |
195 | { |
196 | INSTANCE_CHECK; |
197 | GC_NOTRIGGER; |
198 | NOTHROW; |
199 | CANNOT_TAKE_LOCK; |
200 | MODE_ANY; |
201 | SO_TOLERANT; |
202 | SUPPORTS_DAC; |
203 | } |
204 | CONTRACTL_END; |
205 | |
206 | if (IsDynamic()) |
207 | { |
208 | return SString::Empty(); |
209 | } |
210 | else |
211 | return m_identity->GetPath(); |
212 | } |
213 | |
214 | |
215 | #ifdef DACCESS_COMPILE |
216 | inline const SString &PEFile::GetModuleFileNameHint() |
217 | { |
218 | CONTRACTL |
219 | { |
220 | INSTANCE_CHECK; |
221 | GC_NOTRIGGER; |
222 | NOTHROW; |
223 | MODE_ANY; |
224 | } |
225 | CONTRACTL_END; |
226 | |
227 | if (IsDynamic()) |
228 | { |
229 | return SString::Empty(); |
230 | } |
231 | else |
232 | return m_identity->GetModuleFileNameHintForDAC(); |
233 | } |
234 | #endif // DACCESS_COMPILE |
235 | |
236 | #ifdef LOGGING |
237 | inline LPCWSTR PEFile::GetDebugName() |
238 | { |
239 | CONTRACTL |
240 | { |
241 | INSTANCE_CHECK; |
242 | NOTHROW; |
243 | GC_NOTRIGGER; |
244 | MODE_ANY; |
245 | CANNOT_TAKE_LOCK; |
246 | } |
247 | CONTRACTL_END; |
248 | |
249 | #ifdef _DEBUG |
250 | return m_pDebugName; |
251 | #else |
252 | return GetPath(); |
253 | #endif |
254 | } |
255 | #endif |
256 | |
257 | // ------------------------------------------------------------ |
258 | // Classification |
259 | // ------------------------------------------------------------ |
260 | |
261 | inline BOOL PEFile::IsAssembly() const |
262 | { |
263 | LIMITED_METHOD_DAC_CONTRACT; |
264 | |
265 | return (m_flags & PEFILE_ASSEMBLY) != 0; |
266 | } |
267 | |
268 | inline PTR_PEAssembly PEFile::AsAssembly() |
269 | { |
270 | LIMITED_METHOD_DAC_CONTRACT; |
271 | |
272 | if (this == nullptr) |
273 | return dac_cast<PTR_PEAssembly>(nullptr); |
274 | if (IsAssembly()) |
275 | return dac_cast<PTR_PEAssembly>(this); |
276 | else |
277 | return dac_cast<PTR_PEAssembly>(nullptr); |
278 | } |
279 | |
280 | inline BOOL PEFile::IsModule() const |
281 | { |
282 | LIMITED_METHOD_CONTRACT; |
283 | SUPPORTS_DAC; |
284 | |
285 | return (m_flags & PEFILE_MODULE) != 0; |
286 | } |
287 | |
288 | inline PTR_PEModule PEFile::AsModule() |
289 | { |
290 | LIMITED_METHOD_DAC_CONTRACT; |
291 | |
292 | if (this == nullptr) |
293 | return dac_cast<PTR_PEModule>(nullptr); |
294 | if (IsModule()) |
295 | return dac_cast<PTR_PEModule>(this); |
296 | else |
297 | return dac_cast<PTR_PEModule>(nullptr); |
298 | } |
299 | |
300 | inline BOOL PEFile::IsSystem() const |
301 | { |
302 | LIMITED_METHOD_CONTRACT; |
303 | SUPPORTS_DAC; |
304 | |
305 | return (m_flags & PEFILE_SYSTEM) != 0; |
306 | } |
307 | |
308 | inline BOOL PEFile::IsDynamic() const |
309 | { |
310 | LIMITED_METHOD_CONTRACT; |
311 | SUPPORTS_DAC; |
312 | |
313 | return m_identity == NULL; |
314 | } |
315 | |
316 | inline BOOL PEFile::IsResource() const |
317 | { |
318 | WRAPPER_NO_CONTRACT; |
319 | SUPPORTS_DAC; |
320 | |
321 | return FALSE; |
322 | } |
323 | |
324 | inline BOOL PEFile::IsIStream() const |
325 | { |
326 | LIMITED_METHOD_CONTRACT; |
327 | |
328 | return FALSE; |
329 | } |
330 | |
331 | inline PEAssembly *PEFile::GetAssembly() const |
332 | { |
333 | WRAPPER_NO_CONTRACT; |
334 | _ASSERTE(IsAssembly()); |
335 | return dac_cast<PTR_PEAssembly>(this); |
336 | |
337 | } |
338 | |
339 | // ------------------------------------------------------------ |
340 | // Metadata access |
341 | // ------------------------------------------------------------ |
342 | |
343 | inline BOOL PEFile::HasMetadata() |
344 | { |
345 | CONTRACTL |
346 | { |
347 | INSTANCE_CHECK; |
348 | NOTHROW; |
349 | GC_NOTRIGGER; |
350 | MODE_ANY; |
351 | SUPPORTS_DAC; |
352 | } |
353 | CONTRACTL_END; |
354 | |
355 | return !IsResource(); |
356 | } |
357 | |
358 | inline IMDInternalImportHolder PEFile::GetMDImport() |
359 | { |
360 | WRAPPER_NO_CONTRACT; |
361 | if (m_bHasPersistentMDImport) |
362 | return IMDInternalImportHolder(GetPersistentMDImport(),FALSE); |
363 | else |
364 | return IMDInternalImportHolder(GetMDImportWithRef(),TRUE); |
365 | }; |
366 | |
367 | inline IMDInternalImport* PEFile::GetPersistentMDImport() |
368 | { |
369 | /* |
370 | CONTRACT(IMDInternalImport *) |
371 | { |
372 | INSTANCE_CHECK; |
373 | PRECONDITION(!IsResource()); |
374 | POSTCONDITION(CheckPointer(RETVAL)); |
375 | NOTHROW; |
376 | GC_NOTRIGGER; |
377 | MODE_ANY; |
378 | } |
379 | CONTRACT_END; |
380 | */ |
381 | SUPPORTS_DAC; |
382 | #if !defined(__GNUC__) |
383 | |
384 | _ASSERTE(!IsResource()); |
385 | #endif |
386 | #ifdef DACCESS_COMPILE |
387 | WRAPPER_NO_CONTRACT; |
388 | return DacGetMDImport(this, true); |
389 | #else |
390 | LIMITED_METHOD_CONTRACT; |
391 | |
392 | return m_pMDImport; |
393 | #endif |
394 | } |
395 | |
396 | inline IMDInternalImport *PEFile::GetMDImportWithRef() |
397 | { |
398 | /* |
399 | CONTRACT(IMDInternalImport *) |
400 | { |
401 | INSTANCE_CHECK; |
402 | PRECONDITION(!IsResource()); |
403 | POSTCONDITION(CheckPointer(RETVAL)); |
404 | NOTHROW; |
405 | GC_NOTRIGGER; |
406 | MODE_ANY; |
407 | SO_INTOLERANT; |
408 | } |
409 | CONTRACT_END; |
410 | */ |
411 | #if !defined(__GNUC__) |
412 | _ASSERTE(!IsResource()); |
413 | #endif |
414 | #ifdef DACCESS_COMPILE |
415 | WRAPPER_NO_CONTRACT; |
416 | return DacGetMDImport(this, true); |
417 | #else |
418 | CONTRACTL |
419 | { |
420 | NOTHROW; |
421 | WRAPPER(GC_TRIGGERS); |
422 | MODE_ANY; |
423 | CAN_TAKE_LOCK; |
424 | SO_INTOLERANT; |
425 | } |
426 | CONTRACTL_END; |
427 | |
428 | GCX_PREEMP(); |
429 | SimpleReadLockHolder lock(m_pMetadataLock); |
430 | if(m_pMDImport) |
431 | m_pMDImport->AddRef(); |
432 | return m_pMDImport; |
433 | #endif |
434 | } |
435 | |
436 | #ifndef DACCESS_COMPILE |
437 | |
438 | inline IMetaDataImport2 *PEFile::GetRWImporter() |
439 | { |
440 | CONTRACT(IMetaDataImport2 *) |
441 | { |
442 | INSTANCE_CHECK; |
443 | PRECONDITION(!IsResource()); |
444 | POSTCONDITION(CheckPointer(RETVAL)); |
445 | PRECONDITION(m_bHasPersistentMDImport); |
446 | GC_NOTRIGGER; |
447 | THROWS; |
448 | MODE_ANY; |
449 | } |
450 | CONTRACT_END; |
451 | |
452 | if (m_pImporter == NULL) |
453 | OpenImporter(); |
454 | |
455 | RETURN m_pImporter; |
456 | } |
457 | |
458 | inline IMetaDataEmit *PEFile::GetEmitter() |
459 | { |
460 | CONTRACT(IMetaDataEmit *) |
461 | { |
462 | INSTANCE_CHECK; |
463 | MODE_ANY; |
464 | GC_NOTRIGGER; |
465 | PRECONDITION(!IsResource()); |
466 | POSTCONDITION(CheckPointer(RETVAL)); |
467 | PRECONDITION(m_bHasPersistentMDImport); |
468 | THROWS; |
469 | } |
470 | CONTRACT_END; |
471 | |
472 | if (m_pEmitter == NULL) |
473 | OpenEmitter(); |
474 | |
475 | RETURN m_pEmitter; |
476 | } |
477 | |
478 | |
479 | #endif // DACCESS_COMPILE |
480 | |
481 | // The simple name is not actually very simple. The name returned comes from one of |
482 | // various metadata tables, depending on whether this is a manifest module, |
483 | // non-manifest module, or something else |
484 | inline LPCUTF8 PEFile::GetSimpleName() |
485 | { |
486 | CONTRACT(LPCUTF8) |
487 | { |
488 | INSTANCE_CHECK; |
489 | MODE_ANY; |
490 | POSTCONDITION(CheckPointer(RETVAL)); |
491 | NOTHROW; |
492 | SUPPORTS_DAC; |
493 | WRAPPER(GC_TRIGGERS); |
494 | } |
495 | CONTRACT_END; |
496 | |
497 | if (IsAssembly()) |
498 | RETURN dac_cast<PTR_PEAssembly>(this)->GetSimpleName(); |
499 | else |
500 | { |
501 | LPCUTF8 szScopeName; |
502 | if (FAILED(GetScopeName(&szScopeName))) |
503 | { |
504 | szScopeName = "" ; |
505 | } |
506 | RETURN szScopeName; |
507 | } |
508 | } |
509 | |
510 | |
511 | // Same as the managed Module.ScopeName property, this unconditionally looks in the |
512 | // metadata Module table to get the name. Useful for profilers and others who don't |
513 | // like sugar coating on their names. |
514 | inline HRESULT PEFile::GetScopeName(LPCUTF8 * pszName) |
515 | { |
516 | CONTRACTL |
517 | { |
518 | INSTANCE_CHECK; |
519 | MODE_ANY; |
520 | NOTHROW; |
521 | SUPPORTS_DAC; |
522 | GC_NOTRIGGER; |
523 | } |
524 | CONTRACTL_END; |
525 | |
526 | return GetMDImport()->GetScopeProps(pszName, NULL); |
527 | } |
528 | |
529 | |
530 | // ------------------------------------------------------------ |
531 | // PE file access |
532 | // ------------------------------------------------------------ |
533 | |
534 | inline BOOL PEFile::IsIbcOptimized() |
535 | { |
536 | WRAPPER_NO_CONTRACT; |
537 | |
538 | #ifdef FEATURE_PREJIT |
539 | if (IsNativeLoaded()) |
540 | { |
541 | CONSISTENCY_CHECK(HasNativeImage()); |
542 | |
543 | return m_nativeImage->IsIbcOptimized(); |
544 | } |
545 | #endif |
546 | |
547 | return FALSE; |
548 | } |
549 | |
550 | inline BOOL PEFile::IsILImageReadyToRun() |
551 | { |
552 | CONTRACTL |
553 | { |
554 | INSTANCE_CHECK; |
555 | MODE_ANY; |
556 | NOTHROW; |
557 | GC_NOTRIGGER; |
558 | } |
559 | CONTRACTL_END; |
560 | |
561 | #ifdef FEATURE_PREJIT |
562 | if (IsNativeLoaded()) |
563 | { |
564 | CONSISTENCY_CHECK(HasNativeImage()); |
565 | |
566 | return GetLoadedNative()->GetNativeILHasReadyToRunHeader(); |
567 | } |
568 | else |
569 | #endif // FEATURE_PREJIT |
570 | if (HasOpenedILimage()) |
571 | { |
572 | return GetLoadedIL()->HasReadyToRunHeader(); |
573 | } |
574 | else |
575 | { |
576 | return FALSE; |
577 | } |
578 | } |
579 | |
580 | inline WORD PEFile::GetSubsystem() |
581 | { |
582 | WRAPPER_NO_CONTRACT; |
583 | |
584 | if (IsResource() || IsDynamic()) |
585 | return 0; |
586 | |
587 | #ifdef FEATURE_PREJIT |
588 | if (IsNativeLoaded()) |
589 | { |
590 | CONSISTENCY_CHECK(HasNativeImage()); |
591 | |
592 | return GetLoadedNative()->GetSubsystem(); |
593 | } |
594 | #ifndef DACCESS_COMPILE |
595 | if (!HasOpenedILimage()) |
596 | { |
597 | //don't want to touch the IL image unless we already have |
598 | ReleaseHolder<PEImage> pNativeImage = GetNativeImageWithRef(); |
599 | if (pNativeImage) |
600 | return pNativeImage->GetSubsystem(); |
601 | } |
602 | #endif // DACCESS_COMPILE |
603 | #endif // FEATURE_PREJIT |
604 | |
605 | return GetLoadedIL()->GetSubsystem(); |
606 | } |
607 | |
608 | inline mdToken PEFile::GetEntryPointToken( |
609 | #ifdef _DEBUG |
610 | BOOL bAssumeLoaded |
611 | #endif //_DEBUG |
612 | ) |
613 | { |
614 | WRAPPER_NO_CONTRACT; |
615 | |
616 | if (IsResource() || IsDynamic()) |
617 | return mdTokenNil; |
618 | |
619 | |
620 | #ifdef FEATURE_PREJIT |
621 | if (IsNativeLoaded()) |
622 | { |
623 | CONSISTENCY_CHECK(HasNativeImage()); |
624 | _ASSERTE (!bAssumeLoaded || m_nativeImage->HasLoadedLayout ()); |
625 | return m_nativeImage->GetEntryPointToken(); |
626 | } |
627 | #ifndef DACCESS_COMPILE |
628 | if (!HasOpenedILimage()) |
629 | { |
630 | //don't want to touch the IL image unless we already have |
631 | ReleaseHolder<PEImage> pNativeImage = GetNativeImageWithRef(); |
632 | if (pNativeImage) { |
633 | _ASSERTE (!bAssumeLoaded || pNativeImage->HasLoadedLayout ()); |
634 | return pNativeImage->GetEntryPointToken(); |
635 | } |
636 | } |
637 | #endif // DACCESS_COMPILE |
638 | #endif // FEATURE_PREJIT |
639 | _ASSERTE (!bAssumeLoaded || HasLoadedIL ()); |
640 | return GetOpenedILimage()->GetEntryPointToken(); |
641 | } |
642 | |
643 | #ifdef FEATURE_PREJIT |
644 | inline BOOL PEFile::IsNativeLoaded() |
645 | { |
646 | WRAPPER_NO_CONTRACT; |
647 | return (m_nativeImage && m_bHasPersistentMDImport && m_nativeImage->HasLoadedLayout()); |
648 | } |
649 | inline void PEFile::MarkNativeImageInvalidIfOwned() |
650 | { |
651 | WRAPPER_NO_CONTRACT; |
652 | // If owned, mark the PEFile as dummy, so the image does not get reused |
653 | PEImageHolder nativeImage(GetNativeImageWithRef()); |
654 | Module * pNativeModule = nativeImage->GetLoadedLayout()->GetPersistedModuleImage(); |
655 | PEFile ** ppNativeFile = (PEFile**) (PBYTE(pNativeModule) + Module::GetFileOffset()); |
656 | |
657 | // Attempt to write only if we claimed the ownership. |
658 | if (*ppNativeFile == this) |
659 | FastInterlockCompareExchangePointer(ppNativeFile, Dummy(), this); |
660 | } |
661 | |
662 | |
663 | #endif |
664 | |
665 | inline BOOL PEFile::IsILOnly() |
666 | { |
667 | STATIC_CONTRACT_SO_TOLERANT; |
668 | WRAPPER_NO_CONTRACT; |
669 | SUPPORTS_DAC; |
670 | |
671 | CONTRACT_VIOLATION(ThrowsViolation|GCViolation|FaultViolation); |
672 | |
673 | if (IsResource() || IsDynamic()) |
674 | return FALSE; |
675 | |
676 | #ifdef FEATURE_PREJIT |
677 | if (IsNativeLoaded()) |
678 | { |
679 | CONSISTENCY_CHECK(HasNativeImage()); |
680 | |
681 | return m_nativeImage->IsNativeILILOnly(); |
682 | } |
683 | #ifndef DACCESS_COMPILE |
684 | if (!HasOpenedILimage()) |
685 | { |
686 | BOOL retVal = FALSE; |
687 | |
688 | BEGIN_SO_INTOLERANT_CODE(GetThread()); |
689 | |
690 | //don't want to touch the IL image unless we already have |
691 | ReleaseHolder<PEImage> pNativeImage = GetNativeImageWithRef(); |
692 | if (pNativeImage) |
693 | { |
694 | retVal = pNativeImage->IsNativeILILOnly(); |
695 | } |
696 | |
697 | END_SO_INTOLERANT_CODE; |
698 | |
699 | return retVal; |
700 | } |
701 | #endif // DACCESS_COMPILE |
702 | #endif // FEATURE_PREJIT |
703 | |
704 | return GetOpenedILimage()->IsILOnly(); |
705 | } |
706 | |
707 | inline BOOL PEFile::IsDll() |
708 | { |
709 | WRAPPER_NO_CONTRACT; |
710 | |
711 | if (IsResource() || IsDynamic()) |
712 | return TRUE; |
713 | |
714 | #ifdef FEATURE_PREJIT |
715 | if (IsNativeLoaded()) |
716 | { |
717 | CONSISTENCY_CHECK(HasNativeImage()); |
718 | |
719 | return m_nativeImage->IsNativeILDll(); |
720 | } |
721 | #ifndef DACCESS_COMPILE |
722 | if (!HasOpenedILimage()) |
723 | { |
724 | //don't want to touch the IL image unless we already have |
725 | ReleaseHolder<PEImage> pNativeImage =GetNativeImageWithRef(); |
726 | if (pNativeImage) |
727 | return pNativeImage->IsNativeILDll(); |
728 | } |
729 | EnsureImageOpened(); |
730 | #endif // DACCESS_COMPILE |
731 | #endif // FEATURE_PREJIT |
732 | |
733 | return GetOpenedILimage()->IsDll(); |
734 | } |
735 | |
736 | inline PTR_VOID PEFile::GetRvaField(RVA field) |
737 | { |
738 | CONTRACT(void *) |
739 | { |
740 | INSTANCE_CHECK; |
741 | PRECONDITION(!IsDynamic()); |
742 | PRECONDITION(!IsResource()); |
743 | PRECONDITION(CheckRvaField(field)); |
744 | PRECONDITION(CheckLoaded()); |
745 | NOTHROW; |
746 | GC_NOTRIGGER; |
747 | MODE_ANY; |
748 | SUPPORTS_DAC; |
749 | POSTCONDITION(CheckPointer(RETVAL)); |
750 | } |
751 | CONTRACT_END; |
752 | |
753 | // Note that the native image Rva fields are currently cut off before |
754 | // this point. We should not get here for an IL only native image. |
755 | |
756 | RETURN dac_cast<PTR_VOID>(GetLoadedIL()->GetRvaData(field,NULL_OK)); |
757 | } |
758 | |
759 | inline CHECK PEFile::CheckRvaField(RVA field) |
760 | { |
761 | CONTRACT_CHECK |
762 | { |
763 | INSTANCE_CHECK; |
764 | PRECONDITION(!IsDynamic()); |
765 | PRECONDITION(!IsResource()); |
766 | PRECONDITION(CheckLoaded()); |
767 | NOTHROW; |
768 | GC_NOTRIGGER; |
769 | MODE_ANY; |
770 | } |
771 | CONTRACT_CHECK_END; |
772 | |
773 | // Note that the native image Rva fields are currently cut off before |
774 | // this point. We should not get here for an IL only native image. |
775 | |
776 | CHECK(GetLoadedIL()->CheckRva(field,NULL_OK)); |
777 | CHECK_OK; |
778 | } |
779 | |
780 | inline CHECK PEFile::CheckRvaField(RVA field, COUNT_T size) |
781 | { |
782 | CONTRACT_CHECK |
783 | { |
784 | INSTANCE_CHECK; |
785 | PRECONDITION(!IsDynamic()); |
786 | PRECONDITION(!IsResource()); |
787 | PRECONDITION(CheckLoaded()); |
788 | NOTHROW; |
789 | GC_NOTRIGGER; |
790 | MODE_ANY; |
791 | } |
792 | CONTRACT_CHECK_END; |
793 | |
794 | // Note that the native image Rva fields are currently cut off before |
795 | // this point. We should not get here for an IL only native image. |
796 | |
797 | CHECK(GetLoadedIL()->CheckRva(field, size,0,NULL_OK)); |
798 | CHECK_OK; |
799 | } |
800 | |
801 | inline BOOL PEFile::HasTls() |
802 | { |
803 | CONTRACTL |
804 | { |
805 | INSTANCE_CHECK; |
806 | NOTHROW; |
807 | GC_NOTRIGGER; |
808 | MODE_ANY; |
809 | PRECONDITION(CheckLoaded()); |
810 | } |
811 | CONTRACTL_END; |
812 | |
813 | // Resource modules do not contain TLS data. |
814 | if (IsResource()) |
815 | return FALSE; |
816 | // Dynamic modules do not contain TLS data. |
817 | else if (IsDynamic()) |
818 | return FALSE; |
819 | // ILOnly modules do not contain TLS data. |
820 | else if (IsILOnly()) |
821 | return FALSE; |
822 | else |
823 | return GetLoadedIL()->HasTls(); |
824 | } |
825 | |
826 | inline BOOL PEFile::IsRvaFieldTls(RVA field) |
827 | { |
828 | CONTRACTL |
829 | { |
830 | INSTANCE_CHECK; |
831 | NOTHROW; |
832 | GC_NOTRIGGER; |
833 | MODE_ANY; |
834 | PRECONDITION(CheckLoaded()); |
835 | } |
836 | CONTRACTL_END; |
837 | |
838 | if (!HasTls()) |
839 | return FALSE; |
840 | |
841 | PTR_VOID address = PTR_VOID(GetLoadedIL()->GetRvaData(field)); |
842 | |
843 | COUNT_T tlsSize; |
844 | PTR_VOID tlsRange = GetLoadedIL()->GetTlsRange(&tlsSize); |
845 | |
846 | return (address >= tlsRange |
847 | && address < (dac_cast<PTR_BYTE>(tlsRange)+tlsSize)); |
848 | } |
849 | |
850 | inline UINT32 PEFile::GetFieldTlsOffset(RVA field) |
851 | { |
852 | CONTRACTL |
853 | { |
854 | INSTANCE_CHECK; |
855 | PRECONDITION(CheckRvaField(field)); |
856 | PRECONDITION(IsRvaFieldTls(field)); |
857 | PRECONDITION(CheckLoaded()); |
858 | NOTHROW; |
859 | GC_NOTRIGGER; |
860 | MODE_ANY; |
861 | } |
862 | CONTRACTL_END; |
863 | |
864 | return (UINT32)(dac_cast<PTR_BYTE>(GetRvaField(field)) - |
865 | dac_cast<PTR_BYTE>(GetLoadedIL()->GetTlsRange())); |
866 | } |
867 | |
868 | inline UINT32 PEFile::GetTlsIndex() |
869 | { |
870 | CONTRACTL |
871 | { |
872 | PRECONDITION(CheckLoaded()); |
873 | INSTANCE_CHECK; |
874 | PRECONDITION(HasTls()); |
875 | NOTHROW; |
876 | GC_NOTRIGGER; |
877 | MODE_ANY; |
878 | } |
879 | CONTRACTL_END; |
880 | |
881 | return GetLoadedIL()->GetTlsIndex(); |
882 | } |
883 | |
884 | inline const void *PEFile::GetInternalPInvokeTarget(RVA target) |
885 | { |
886 | CONTRACT(void *) |
887 | { |
888 | INSTANCE_CHECK; |
889 | PRECONDITION(!IsDynamic()); |
890 | PRECONDITION(!IsResource()); |
891 | PRECONDITION(CheckInternalPInvokeTarget(target)); |
892 | PRECONDITION(CheckLoaded()); |
893 | NOTHROW; |
894 | GC_NOTRIGGER; |
895 | MODE_ANY; |
896 | POSTCONDITION(CheckPointer(RETVAL)); |
897 | } |
898 | CONTRACT_END; |
899 | |
900 | RETURN (void*)GetLoadedIL()->GetRvaData(target); |
901 | } |
902 | |
903 | inline CHECK PEFile::CheckInternalPInvokeTarget(RVA target) |
904 | { |
905 | CONTRACT_CHECK |
906 | { |
907 | INSTANCE_CHECK; |
908 | PRECONDITION(!IsDynamic()); |
909 | PRECONDITION(!IsResource()); |
910 | PRECONDITION(CheckLoaded()); |
911 | NOTHROW; |
912 | GC_NOTRIGGER; |
913 | MODE_ANY; |
914 | } |
915 | CONTRACT_CHECK_END; |
916 | |
917 | CHECK(!IsILOnly()); |
918 | CHECK(GetLoadedIL()->CheckRva(target)); |
919 | |
920 | CHECK_OK; |
921 | } |
922 | |
923 | inline IMAGE_COR_VTABLEFIXUP *PEFile::GetVTableFixups(COUNT_T *pCount/*=NULL*/) |
924 | { |
925 | CONTRACT(IMAGE_COR_VTABLEFIXUP *) |
926 | { |
927 | PRECONDITION(CheckLoaded()); |
928 | INSTANCE_CHECK; |
929 | NOTHROW; |
930 | GC_NOTRIGGER; |
931 | MODE_ANY; |
932 | POSTCONDITION(CheckPointer(RETVAL, NULL_OK)); |
933 | } |
934 | CONTRACT_END; |
935 | |
936 | if (IsResource() || IsDynamic() || IsILOnly()) |
937 | { |
938 | if (pCount != NULL) |
939 | *pCount = 0; |
940 | RETURN NULL; |
941 | } |
942 | else |
943 | RETURN GetLoadedIL()->GetVTableFixups(pCount); |
944 | } |
945 | |
946 | inline void *PEFile::GetVTable(RVA rva) |
947 | { |
948 | CONTRACT(void *) |
949 | { |
950 | INSTANCE_CHECK; |
951 | PRECONDITION(!IsDynamic()); |
952 | PRECONDITION(!IsResource()); |
953 | PRECONDITION(CheckLoaded()); |
954 | PRECONDITION(!IsILOnly()); |
955 | PRECONDITION(GetLoadedIL()->CheckRva(rva)); |
956 | NOTHROW; |
957 | GC_NOTRIGGER; |
958 | MODE_ANY; |
959 | POSTCONDITION(CheckPointer(RETVAL)); |
960 | } |
961 | CONTRACT_END; |
962 | |
963 | RETURN (void *)GetLoadedIL()->GetRvaData(rva); |
964 | } |
965 | |
966 | // @todo: this is bad to expose. But it is needed to support current IJW thunks |
967 | inline HMODULE PEFile::GetIJWBase() |
968 | { |
969 | CONTRACTL |
970 | { |
971 | INSTANCE_CHECK; |
972 | PRECONDITION(!IsDynamic()); |
973 | PRECONDITION(!IsResource()); |
974 | PRECONDITION(CheckLoaded()); |
975 | PRECONDITION(!IsILOnly()); |
976 | NOTHROW; |
977 | GC_NOTRIGGER; |
978 | MODE_ANY; |
979 | } |
980 | CONTRACTL_END; |
981 | |
982 | return (HMODULE) dac_cast<TADDR>(GetLoadedIL()->GetBase()); |
983 | } |
984 | |
985 | inline PTR_VOID PEFile::GetDebuggerContents(COUNT_T *pSize/*=NULL*/) |
986 | { |
987 | CONTRACT(PTR_VOID) |
988 | { |
989 | INSTANCE_CHECK; |
990 | PRECONDITION(CheckPointer(pSize, NULL_OK)); |
991 | WRAPPER(THROWS); |
992 | WRAPPER(GC_TRIGGERS); |
993 | MODE_ANY; |
994 | POSTCONDITION(CheckPointer(RETVAL, NULL_OK)); |
995 | } |
996 | CONTRACT_END; |
997 | |
998 | // We cannot in general force a LoadLibrary; we might be in the |
999 | // helper thread. The debugger will have to expect a zero base |
1000 | // in some circumstances. |
1001 | |
1002 | if (IsLoaded()) |
1003 | { |
1004 | if (pSize != NULL) |
1005 | *pSize = GetLoaded()->GetSize(); |
1006 | |
1007 | RETURN GetLoaded()->GetBase(); |
1008 | } |
1009 | else |
1010 | { |
1011 | if (pSize != NULL) |
1012 | *pSize = 0; |
1013 | |
1014 | RETURN NULL; |
1015 | } |
1016 | } |
1017 | |
1018 | inline PTR_CVOID PEFile::GetLoadedImageContents(COUNT_T *pSize/*=NULL*/) |
1019 | { |
1020 | CONTRACTL |
1021 | { |
1022 | INSTANCE_CHECK; |
1023 | THROWS; |
1024 | GC_TRIGGERS; |
1025 | MODE_ANY; |
1026 | SUPPORTS_DAC; |
1027 | } |
1028 | CONTRACTL_END; |
1029 | |
1030 | if (IsLoaded() && !IsDynamic()) |
1031 | { |
1032 | if (pSize != NULL) |
1033 | { |
1034 | *pSize = GetLoaded()->GetSize(); |
1035 | } |
1036 | return GetLoaded()->GetBase(); |
1037 | } |
1038 | else |
1039 | { |
1040 | if (pSize != NULL) |
1041 | { |
1042 | *pSize = 0; |
1043 | } |
1044 | return NULL; |
1045 | } |
1046 | } |
1047 | |
1048 | #ifndef DACCESS_COMPILE |
1049 | inline const void *PEFile::GetManagedFileContents(COUNT_T *pSize/*=NULL*/) |
1050 | { |
1051 | CONTRACT(const void *) |
1052 | { |
1053 | INSTANCE_CHECK; |
1054 | PRECONDITION(CheckLoaded()); |
1055 | WRAPPER(THROWS); |
1056 | WRAPPER(GC_TRIGGERS); |
1057 | MODE_ANY; |
1058 | POSTCONDITION((!GetLoaded()->GetSize()) || CheckPointer(RETVAL)); |
1059 | } |
1060 | CONTRACT_END; |
1061 | |
1062 | // Right now, we will trigger a LoadLibrary for the caller's sake, |
1063 | // even if we are in a scenario where we could normally avoid it. |
1064 | LoadLibrary(FALSE); |
1065 | |
1066 | if (pSize != NULL) |
1067 | *pSize = GetLoadedIL()->GetSize(); |
1068 | |
1069 | |
1070 | RETURN GetLoadedIL()->GetBase(); |
1071 | } |
1072 | #endif // DACCESS_COMPILE |
1073 | |
1074 | inline BOOL PEFile::IsPtrInILImage(PTR_CVOID data) |
1075 | { |
1076 | CONTRACTL |
1077 | { |
1078 | INSTANCE_CHECK; |
1079 | NOTHROW; |
1080 | GC_NOTRIGGER; |
1081 | FORBID_FAULT; |
1082 | SO_TOLERANT; |
1083 | SUPPORTS_DAC; |
1084 | } |
1085 | CONTRACTL_END; |
1086 | |
1087 | if (HasOpenedILimage()) |
1088 | { |
1089 | #if defined(FEATURE_PREJIT) |
1090 | if (m_openedILimage == m_nativeImage) |
1091 | { |
1092 | // On Apollo builds, we sometimes open the native image into the slot |
1093 | // normally reserved for the IL image (as the IL image is often not available |
1094 | // on the disk at all). In such a case, data is not coming directly from an |
1095 | // actual IL image, but see if it's coming from the metadata that we copied |
1096 | // from the IL image into the NI. |
1097 | TADDR taddrData = dac_cast<TADDR>(data); |
1098 | PEDecoder * pDecoder = m_nativeImage->GetLoadedLayout(); |
1099 | COUNT_T cbILMetadata; |
1100 | TADDR taddrILMetadata = dac_cast<TADDR>(pDecoder->GetMetadata(&cbILMetadata)); |
1101 | return ((taddrILMetadata <= taddrData) && (taddrData < taddrILMetadata + cbILMetadata)); |
1102 | } |
1103 | #endif // defined(FEATURE_PREJIT) |
1104 | return GetOpenedILimage()->IsPtrInImage(data); |
1105 | } |
1106 | else |
1107 | return FALSE; |
1108 | } |
1109 | // ------------------------------------------------------------ |
1110 | // Native image access |
1111 | // ------------------------------------------------------------ |
1112 | inline BOOL PEFile::HasNativeImage() |
1113 | { |
1114 | CONTRACTL |
1115 | { |
1116 | INSTANCE_CHECK; |
1117 | NOTHROW; |
1118 | GC_NOTRIGGER; |
1119 | MODE_ANY; |
1120 | SO_TOLERANT; |
1121 | CANNOT_TAKE_LOCK; |
1122 | SUPPORTS_DAC; |
1123 | } |
1124 | CONTRACTL_END; |
1125 | |
1126 | #ifdef FEATURE_PREJIT |
1127 | return (m_nativeImage != NULL); |
1128 | #else |
1129 | return FALSE; |
1130 | #endif |
1131 | } |
1132 | |
1133 | inline BOOL PEFile::HasNativeOrReadyToRunImage() |
1134 | { |
1135 | CONTRACTL |
1136 | { |
1137 | INSTANCE_CHECK; |
1138 | NOTHROW; |
1139 | GC_NOTRIGGER; |
1140 | MODE_ANY; |
1141 | SO_TOLERANT; |
1142 | CANNOT_TAKE_LOCK; |
1143 | SUPPORTS_DAC; |
1144 | } |
1145 | CONTRACTL_END; |
1146 | |
1147 | return (HasNativeImage() || IsILImageReadyToRun()); |
1148 | } |
1149 | |
1150 | inline PTR_PEImageLayout PEFile::GetLoadedIL() |
1151 | { |
1152 | LIMITED_METHOD_CONTRACT; |
1153 | SUPPORTS_DAC; |
1154 | |
1155 | _ASSERTE(HasOpenedILimage()); |
1156 | |
1157 | return GetOpenedILimage()->GetLoadedLayout(); |
1158 | }; |
1159 | |
1160 | inline PTR_PEImageLayout PEFile::GetAnyILWithRef() |
1161 | { |
1162 | WRAPPER_NO_CONTRACT; |
1163 | return GetILimage()->GetLayout(PEImageLayout::LAYOUT_ANY,PEImage::LAYOUT_CREATEIFNEEDED); |
1164 | }; |
1165 | |
1166 | |
1167 | inline BOOL PEFile::IsLoaded(BOOL bAllowNative/*=TRUE*/) |
1168 | { |
1169 | CONTRACTL |
1170 | { |
1171 | NOTHROW; |
1172 | GC_NOTRIGGER; |
1173 | SO_TOLERANT; |
1174 | MODE_ANY; |
1175 | } |
1176 | CONTRACTL_END; |
1177 | if(IsDynamic()) |
1178 | return TRUE; |
1179 | #ifdef FEATURE_PREJIT |
1180 | if (bAllowNative && HasNativeImage()) |
1181 | { |
1182 | PEImage *pNativeImage = GetPersistentNativeImage(); |
1183 | return pNativeImage->HasLoadedLayout() && (pNativeImage->GetLoadedLayout()->IsNativeILILOnly() || (HasLoadedIL())); |
1184 | } |
1185 | else |
1186 | #endif |
1187 | return HasLoadedIL(); |
1188 | }; |
1189 | |
1190 | |
1191 | inline PTR_PEImageLayout PEFile::GetLoaded() |
1192 | { |
1193 | WRAPPER_NO_CONTRACT; |
1194 | SUPPORTS_DAC; |
1195 | return HasNativeImage()?GetLoadedNative():GetLoadedIL(); |
1196 | }; |
1197 | |
1198 | inline PTR_PEImageLayout PEFile::GetLoadedNative() |
1199 | { |
1200 | CONTRACTL |
1201 | { |
1202 | NOTHROW; |
1203 | GC_NOTRIGGER; |
1204 | SO_TOLERANT; |
1205 | MODE_ANY; |
1206 | SUPPORTS_DAC; |
1207 | } |
1208 | CONTRACTL_END; |
1209 | |
1210 | #ifdef FEATURE_PREJIT |
1211 | PEImage* pImage=GetPersistentNativeImage(); |
1212 | _ASSERTE(pImage && pImage->GetLoadedLayout()); |
1213 | return pImage->GetLoadedLayout(); |
1214 | #else |
1215 | // Should never get here |
1216 | PRECONDITION(HasNativeImage()); |
1217 | return NULL; |
1218 | #endif |
1219 | }; |
1220 | |
1221 | #ifdef FEATURE_PREJIT |
1222 | inline PEImage *PEFile::GetPersistentNativeImage() |
1223 | { |
1224 | CONTRACT(PEImage *) |
1225 | { |
1226 | INSTANCE_CHECK; |
1227 | PRECONDITION(HasNativeImage()); |
1228 | POSTCONDITION(CheckPointer(RETVAL)); |
1229 | PRECONDITION(m_bHasPersistentMDImport); |
1230 | NOTHROW; |
1231 | GC_NOTRIGGER; |
1232 | MODE_ANY; |
1233 | SO_TOLERANT; |
1234 | CANNOT_TAKE_LOCK; |
1235 | SUPPORTS_DAC; |
1236 | } |
1237 | CONTRACT_END; |
1238 | |
1239 | RETURN m_nativeImage; |
1240 | } |
1241 | |
1242 | #ifndef DACCESS_COMPILE |
1243 | inline PEImage *PEFile::GetNativeImageWithRef() |
1244 | { |
1245 | CONTRACT(PEImage *) |
1246 | { |
1247 | INSTANCE_CHECK; |
1248 | NOTHROW; |
1249 | GC_TRIGGERS; |
1250 | MODE_ANY; |
1251 | POSTCONDITION(CheckPointer(RETVAL,NULL_OK)); |
1252 | } |
1253 | CONTRACT_END; |
1254 | GCX_PREEMP(); |
1255 | SimpleReadLockHolder mdlock(m_pMetadataLock); |
1256 | if(m_nativeImage) |
1257 | m_nativeImage->AddRef(); |
1258 | RETURN m_nativeImage; |
1259 | } |
1260 | #endif // DACCESS_COMPILE |
1261 | |
1262 | inline BOOL PEFile::HasNativeImageMetadata() |
1263 | { |
1264 | CONTRACT(BOOL) |
1265 | { |
1266 | INSTANCE_CHECK; |
1267 | NOTHROW; |
1268 | GC_NOTRIGGER; |
1269 | MODE_ANY; |
1270 | SO_TOLERANT; |
1271 | SUPPORTS_DAC; |
1272 | } |
1273 | CONTRACT_END; |
1274 | |
1275 | RETURN ((m_flags & PEFILE_HAS_NATIVE_IMAGE_METADATA) != 0); |
1276 | } |
1277 | #endif |
1278 | |
1279 | // Function to get the fully qualified name of an assembly |
1280 | inline void PEAssembly::GetFullyQualifiedAssemblyName(IMDInternalImport* pImport, mdAssembly mda, SString &result, DWORD flags) |
1281 | { |
1282 | CONTRACTL |
1283 | { |
1284 | PRECONDITION(CheckValue(result)); |
1285 | #ifndef DACCESS_COMPILE |
1286 | THROWS; |
1287 | #else |
1288 | NOTHROW; |
1289 | #endif // !DACCESS_COMPILE |
1290 | GC_TRIGGERS; |
1291 | MODE_ANY; |
1292 | } |
1293 | CONTRACTL_END; |
1294 | |
1295 | if(pImport != NULL) |
1296 | { |
1297 | // This is for DAC, ONLY for the binding tool. Don't use for other |
1298 | // purposes, since this is not canonicalized through Fusion. |
1299 | LPCSTR name; |
1300 | AssemblyMetaDataInternal context; |
1301 | DWORD dwFlags; |
1302 | PBYTE pbPublicKey; |
1303 | DWORD cbPublicKey; |
1304 | if (FAILED(pImport->GetAssemblyProps( |
1305 | mda, |
1306 | (const void **) &pbPublicKey, |
1307 | &cbPublicKey, |
1308 | NULL, |
1309 | &name, |
1310 | &context, |
1311 | &dwFlags))) |
1312 | { |
1313 | _ASSERTE(!"If this fires, then we have to throw for corrupted images" ); |
1314 | result.SetUTF8("" ); |
1315 | return; |
1316 | } |
1317 | |
1318 | result.SetUTF8(name); |
1319 | |
1320 | result.AppendPrintf(W(", Version=%u.%u.%u.%u" ), |
1321 | context.usMajorVersion, context.usMinorVersion, |
1322 | context.usBuildNumber, context.usRevisionNumber); |
1323 | |
1324 | result.Append(W(", Culture=" )); |
1325 | if (!*context.szLocale) |
1326 | { |
1327 | result.Append(W("neutral" )); |
1328 | } |
1329 | else |
1330 | { |
1331 | result.AppendUTF8(context.szLocale); |
1332 | } |
1333 | |
1334 | if (cbPublicKey != 0) |
1335 | { |
1336 | #ifndef DACCESS_COMPILE |
1337 | |
1338 | StrongNameBufferHolder<BYTE> pbToken; |
1339 | DWORD cbToken; |
1340 | CQuickBytes qb; |
1341 | |
1342 | if (StrongNameTokenFromPublicKey(pbPublicKey, cbPublicKey, |
1343 | &pbToken, &cbToken)) |
1344 | { |
1345 | // two hex digits per byte |
1346 | WCHAR* szToken = (WCHAR*) qb.AllocNoThrow(sizeof(WCHAR) * (cbToken*2+1)); |
1347 | if (szToken) |
1348 | { |
1349 | #define TOHEX(a) ((a)>=10 ? L'a'+(a)-10 : L'0'+(a)) |
1350 | UINT x; |
1351 | UINT y; |
1352 | for ( x = 0, y = 0; x < cbToken; ++x ) |
1353 | { |
1354 | WCHAR v = static_cast<WCHAR>(pbToken[x] >> 4); |
1355 | szToken[y++] = TOHEX( v ); |
1356 | v = static_cast<WCHAR>(pbToken[x] & 0x0F); |
1357 | szToken[y++] = TOHEX( v ); |
1358 | } |
1359 | szToken[y] = L'\0'; |
1360 | |
1361 | result.Append(W(", PublicKeyToken=" )); |
1362 | result.Append(szToken); |
1363 | #undef TOHEX |
1364 | } |
1365 | } |
1366 | #endif |
1367 | |
1368 | } |
1369 | else |
1370 | { |
1371 | result.Append(W(", PublicKeyToken=null" )); |
1372 | } |
1373 | |
1374 | if (dwFlags & afPA_Mask) |
1375 | { |
1376 | result.Append(W(", ProcessorArchitecture=" )); |
1377 | |
1378 | if (dwFlags & afPA_MSIL) |
1379 | result.Append(W("MSIL" )); |
1380 | else if (dwFlags & afPA_x86) |
1381 | result.Append(W("x86" )); |
1382 | else if (dwFlags & afPA_IA64) |
1383 | result.Append(W("IA64" )); |
1384 | else if (dwFlags & afPA_AMD64) |
1385 | result.Append(W("AMD64" )); |
1386 | else if (dwFlags & afPA_ARM) |
1387 | result.Append(W("ARM" )); |
1388 | } |
1389 | } |
1390 | } |
1391 | |
1392 | |
1393 | // ------------------------------------------------------------ |
1394 | // Descriptive strings |
1395 | // ------------------------------------------------------------ |
1396 | inline void PEAssembly::GetDisplayName(SString &result, DWORD flags) |
1397 | { |
1398 | CONTRACTL |
1399 | { |
1400 | PRECONDITION(CheckValue(result)); |
1401 | #ifndef DACCESS_COMPILE |
1402 | THROWS; |
1403 | #else |
1404 | NOTHROW; |
1405 | #endif // DACCESS_COMPILE |
1406 | GC_TRIGGERS; |
1407 | MODE_ANY; |
1408 | } |
1409 | CONTRACTL_END; |
1410 | |
1411 | #ifndef DACCESS_COMPILE |
1412 | |
1413 | if ((flags == (ASM_DISPLAYF_VERSION | ASM_DISPLAYF_CULTURE | ASM_DISPLAYF_PUBLIC_KEY_TOKEN)) && |
1414 | !m_sTextualIdentity.IsEmpty()) |
1415 | { |
1416 | result.Set(m_sTextualIdentity); |
1417 | } |
1418 | else |
1419 | { |
1420 | AssemblySpec spec; |
1421 | spec.InitializeSpec(this); |
1422 | spec.GetFileOrDisplayName(flags, result); |
1423 | } |
1424 | |
1425 | #else |
1426 | IMDInternalImport *pImport = GetMDImport(); |
1427 | GetFullyQualifiedAssemblyName(pImport, TokenFromRid(1, mdtAssembly), result, flags); |
1428 | #endif //DACCESS_COMPILE |
1429 | } |
1430 | |
1431 | // ------------------------------------------------------------ |
1432 | // Metadata access |
1433 | // ------------------------------------------------------------ |
1434 | |
1435 | inline LPCSTR PEAssembly::GetSimpleName() |
1436 | { |
1437 | CONTRACTL |
1438 | { |
1439 | NOTHROW; |
1440 | if (!m_bHasPersistentMDImport) { GC_TRIGGERS;} else {DISABLED(GC_TRIGGERS);}; |
1441 | MODE_ANY; |
1442 | SUPPORTS_DAC; |
1443 | } |
1444 | CONTRACTL_END; |
1445 | |
1446 | LPCSTR name = "" ; |
1447 | IMDInternalImportHolder pImport = GetMDImport(); |
1448 | if (pImport != NULL) |
1449 | { |
1450 | if (FAILED(pImport->GetAssemblyProps(TokenFromRid(1, mdtAssembly), NULL, NULL, NULL, &name, NULL, NULL))) |
1451 | { |
1452 | _ASSERTE(!"If this fires, then we have to throw for corrupted images" ); |
1453 | name = "" ; |
1454 | } |
1455 | } |
1456 | return name; |
1457 | } |
1458 | |
1459 | inline BOOL PEFile::IsStrongNamed() |
1460 | { |
1461 | CONTRACTL |
1462 | { |
1463 | THROWS; |
1464 | WRAPPER(GC_NOTRIGGER); |
1465 | MODE_ANY; |
1466 | } |
1467 | CONTRACTL_END; |
1468 | |
1469 | DWORD flags = 0; |
1470 | IfFailThrow(GetMDImport()->GetAssemblyProps(TokenFromRid(1, mdtAssembly), NULL, NULL, NULL, NULL, NULL, &flags)); |
1471 | return (flags & afPublicKey) != NULL; |
1472 | } |
1473 | |
1474 | |
1475 | //--------------------------------------------------------------------------------------- |
1476 | // |
1477 | // Check to see if this assembly has had its strong name signature verified yet. |
1478 | // |
1479 | |
1480 | inline const void *PEFile::GetPublicKey(DWORD *pcbPK) |
1481 | { |
1482 | CONTRACTL |
1483 | { |
1484 | PRECONDITION(CheckPointer(pcbPK, NULL_OK)); |
1485 | THROWS; |
1486 | WRAPPER(GC_TRIGGERS); |
1487 | MODE_ANY; |
1488 | } |
1489 | CONTRACTL_END; |
1490 | |
1491 | const void *pPK; |
1492 | IfFailThrow(GetMDImport()->GetAssemblyProps(TokenFromRid(1, mdtAssembly), &pPK, pcbPK, NULL, NULL, NULL, NULL)); |
1493 | return pPK; |
1494 | } |
1495 | |
1496 | inline ULONG PEFile::GetHashAlgId() |
1497 | { |
1498 | CONTRACTL |
1499 | { |
1500 | THROWS; |
1501 | WRAPPER(GC_TRIGGERS); |
1502 | MODE_ANY; |
1503 | } |
1504 | CONTRACTL_END; |
1505 | |
1506 | ULONG hashAlgId; |
1507 | IfFailThrow(GetMDImport()->GetAssemblyProps(TokenFromRid(1, mdtAssembly), NULL, NULL, &hashAlgId, NULL, NULL, NULL)); |
1508 | return hashAlgId; |
1509 | } |
1510 | |
1511 | inline LPCSTR PEFile::GetLocale() |
1512 | { |
1513 | CONTRACTL |
1514 | { |
1515 | THROWS; |
1516 | WRAPPER(GC_NOTRIGGER); |
1517 | MODE_ANY; |
1518 | } |
1519 | CONTRACTL_END; |
1520 | |
1521 | AssemblyMetaDataInternal md; |
1522 | IfFailThrow(GetMDImport()->GetAssemblyProps(TokenFromRid(1, mdtAssembly), NULL, NULL, NULL, NULL, &md, NULL)); |
1523 | return md.szLocale; |
1524 | } |
1525 | |
1526 | inline DWORD PEFile::GetFlags() |
1527 | { |
1528 | CONTRACTL |
1529 | { |
1530 | PRECONDITION(IsAssembly()); |
1531 | INSTANCE_CHECK; |
1532 | if (FORBIDGC_LOADER_USE_ENABLED()) NOTHROW; else THROWS; |
1533 | if (FORBIDGC_LOADER_USE_ENABLED()) GC_NOTRIGGER; else GC_TRIGGERS; |
1534 | if (FORBIDGC_LOADER_USE_ENABLED()) FORBID_FAULT; else { INJECT_FAULT(COMPlusThrowOM()); } |
1535 | MODE_ANY; |
1536 | } |
1537 | CONTRACTL_END; |
1538 | |
1539 | DWORD flags; |
1540 | IfFailThrow(GetMDImport()->GetAssemblyProps(TokenFromRid(1, mdtAssembly), NULL, NULL, NULL, NULL, NULL, &flags)); |
1541 | return flags; |
1542 | } |
1543 | |
1544 | // In the cases where you know the module is loaded, and cannot tolerate triggering and |
1545 | // loading, this alternative to PEFile::GetFlags is useful. Profiling API uses this. |
1546 | inline HRESULT PEFile::GetFlagsNoTrigger(DWORD * pdwFlags) |
1547 | { |
1548 | CONTRACTL |
1549 | { |
1550 | PRECONDITION(IsAssembly()); |
1551 | INSTANCE_CHECK; |
1552 | NOTHROW; |
1553 | GC_NOTRIGGER; |
1554 | FORBID_FAULT; |
1555 | MODE_ANY; |
1556 | } |
1557 | CONTRACTL_END; |
1558 | |
1559 | _ASSERTE (pdwFlags != NULL); |
1560 | |
1561 | if (!m_bHasPersistentMDImport) |
1562 | return E_FAIL; |
1563 | |
1564 | return GetPersistentMDImport()->GetAssemblyProps(TokenFromRid(1, mdtAssembly), NULL, NULL, NULL, NULL, NULL, pdwFlags); |
1565 | } |
1566 | |
1567 | |
1568 | // ------------------------------------------------------------ |
1569 | // Hash support |
1570 | // ------------------------------------------------------------ |
1571 | |
1572 | inline BOOL PEAssembly::HasStrongNameSignature() |
1573 | { |
1574 | WRAPPER_NO_CONTRACT; |
1575 | |
1576 | if (IsDynamic()) |
1577 | return FALSE; |
1578 | |
1579 | #ifdef FEATURE_PREJIT |
1580 | if (IsNativeLoaded()) |
1581 | { |
1582 | CONSISTENCY_CHECK(HasNativeImage()); |
1583 | |
1584 | // The NGen images do not have strong name signature |
1585 | return FALSE; |
1586 | } |
1587 | #endif // FEATURE_PREJIT |
1588 | |
1589 | return GetILimage()->HasStrongNameSignature(); |
1590 | } |
1591 | |
1592 | // ------------------------------------------------------------ |
1593 | // Metadata access |
1594 | // ------------------------------------------------------------ |
1595 | |
1596 | #ifndef DACCESS_COMPILE |
1597 | inline void PEFile::RestoreMDImport(IMDInternalImport* pImport) |
1598 | { |
1599 | CONTRACTL |
1600 | { |
1601 | MODE_ANY; |
1602 | GC_NOTRIGGER; |
1603 | NOTHROW; |
1604 | FORBID_FAULT; |
1605 | } |
1606 | CONTRACTL_END; |
1607 | |
1608 | _ASSERTE(m_pMetadataLock->LockTaken() && m_pMetadataLock->IsWriterLock()); |
1609 | if (m_pMDImport != NULL) |
1610 | return; |
1611 | m_pMDImport=pImport; |
1612 | if(m_pMDImport) |
1613 | m_pMDImport->AddRef(); |
1614 | } |
1615 | #endif |
1616 | inline void PEFile::OpenMDImport() |
1617 | { |
1618 | WRAPPER_NO_CONTRACT; |
1619 | //need synchronization |
1620 | _ASSERTE(m_pMetadataLock->LockTaken() && m_pMetadataLock->IsWriterLock()); |
1621 | OpenMDImport_Unsafe(); |
1622 | } |
1623 | |
1624 | inline PEFile* PEFile::Dummy() |
1625 | { |
1626 | return (PEFile*)(-1); |
1627 | } |
1628 | |
1629 | inline bool PEAssembly::HasBindableIdentity() |
1630 | { |
1631 | CONTRACTL |
1632 | { |
1633 | INSTANCE_CHECK; |
1634 | if (FORBIDGC_LOADER_USE_ENABLED()) NOTHROW; else THROWS; |
1635 | if (FORBIDGC_LOADER_USE_ENABLED()) GC_NOTRIGGER; else GC_TRIGGERS; |
1636 | if (FORBIDGC_LOADER_USE_ENABLED()) FORBID_FAULT; else { INJECT_FAULT(COMPlusThrowOM()); } |
1637 | MODE_ANY; |
1638 | SUPPORTS_DAC; |
1639 | } |
1640 | CONTRACTL_END |
1641 | |
1642 | return !IsAfContentType_WindowsRuntime(GetFlags()); |
1643 | } |
1644 | |
1645 | inline bool PEAssembly::IsWindowsRuntime() |
1646 | { |
1647 | CONTRACTL |
1648 | { |
1649 | THROWS; |
1650 | GC_TRIGGERS; |
1651 | MODE_ANY; |
1652 | } |
1653 | CONTRACTL_END; |
1654 | |
1655 | return IsAfContentType_WindowsRuntime(GetFlags()); |
1656 | } |
1657 | |
1658 | #endif // PEFILE_INL_ |
1659 | |