Pipe based communication between debugee and managed debugger on Linux
[platform/upstream/coreclr.git] / src / debug / di / rsclass.cpp
1 //
2 // Copyright (c) Microsoft. All rights reserved.
3 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
4 //
5 //*****************************************************************************
6
7 // 
8 // File: class.cpp
9 //
10 //*****************************************************************************
11 #include "stdafx.h"
12
13 // We have an assert in ceemain.cpp that validates this assumption
14 #define FIELD_OFFSET_NEW_ENC_DB          0x07FFFFFB
15
16 #include "winbase.h"
17 #include "corpriv.h"
18
19
20
21 //-----------------------------------------------------------------------------
22 // class CordbClass
23 // Represents a IL-Class in the debuggee, eg: List<T>, System.Console, etc
24 //
25 // Parameters:
26 //  m - module that the class is contained in.
27 //  classMetadataToken - metadata token for the class, scoped to module m.
28 //-----------------------------------------------------------------------------
29 CordbClass::CordbClass(CordbModule *m, mdTypeDef classMetadataToken)
30   : CordbBase(m->GetProcess(), classMetadataToken, enumCordbClass),
31     m_loadLevel(Constructed),
32     m_fLoadEventSent(FALSE),
33     m_fHasBeenUnloaded(false),
34     m_pModule(m),
35     m_token(classMetadataToken),
36     m_fIsValueClassKnown(false),
37     m_fIsValueClass(false),
38     m_fHasTypeParams(false),
39     m_continueCounterLastSync(0),
40     m_fCustomNotificationsEnabled(false)
41 {
42     m_classInfo.Clear();
43 }
44
45
46 /*
47     A list of which resources owned by this object are accounted for.
48
49     HANDLED:
50         CordbModule*            m_module; // Assigned w/o AddRef()
51         FieldData *m_fields;              // Deleted in ~CordbClass
52         CordbHangingFieldTable  m_hangingFieldsStatic; // by value, ~CHashTableAndData frees
53 */
54
55
56 //-----------------------------------------------------------------------------
57 //  Destructor for CordbClass
58 //-----------------------------------------------------------------------------
59 CordbClass::~CordbClass()
60 {
61     // We should have been explicitly neutered before our internal ref went to 0.
62     _ASSERTE(IsNeutered());
63 }
64
65 //-----------------------------------------------------------------------------
66 // Neutered by CordbModule
67 // See CordbBase::Neuter for semantics.
68 //-----------------------------------------------------------------------------
69 void CordbClass::Neuter()
70 {
71     // Reduce the reference count on the type object for this class
72     m_type.Clear();
73     CordbBase::Neuter();
74 }
75
76
77
78
79 //-----------------------------------------------------------------------------
80 // Standard IUnknown::QI implementation.
81 // See IUnknown::QI  for standard semantics.
82 //-----------------------------------------------------------------------------
83 HRESULT CordbClass::QueryInterface(REFIID id, void **pInterface)
84 {
85     if (id == IID_ICorDebugClass)
86     {
87         *pInterface = static_cast<ICorDebugClass*>(this);
88     }
89     else if (id == IID_ICorDebugClass2)
90     {
91         *pInterface = static_cast<ICorDebugClass2*>(this);
92     }
93     else if (id == IID_IUnknown)
94     {
95         *pInterface = static_cast<IUnknown*>(static_cast<ICorDebugClass*>(this));
96     }
97     else
98     {
99         *pInterface = NULL;
100         return E_NOINTERFACE;
101     }
102
103     ExternalAddRef();
104     return S_OK;
105 }
106
107 //-----------------------------------------------------------------------------
108 // Get a ICorDebugValue for a static field on this class.
109 //
110 // Parameters:
111 //   fieldDef - metadata token for field on this class. Can not be from an 
112 //      inherited class.
113 //   pFrame - frame used to resolve Thread-static, AppDomain-static, etc.
114 //   ppValue - OUT: gets value of the field.
115 //
116 // Returns:
117 //    S_OK on success.
118 //    CORDBG_E_STATIC_VAR_NOT_AVAILABLE 
119 //-----------------------------------------------------------------------------
120 HRESULT CordbClass::GetStaticFieldValue(mdFieldDef fieldDef,
121                                         ICorDebugFrame *pFrame,
122                                         ICorDebugValue **ppValue)
123 {
124     PUBLIC_REENTRANT_API_ENTRY(this);
125     FAIL_IF_NEUTERED(this);
126     VALIDATE_POINTER_TO_OBJECT(ppValue, ICorDebugValue **);
127     ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess());
128
129     HRESULT          hr = S_OK;
130     *ppValue = NULL;
131     BOOL             fEnCHangingField = FALSE;
132
133
134     IMetaDataImport * pImport = NULL;
135     EX_TRY
136     {
137         pImport = GetModule()->GetMetaDataImporter(); // throws
138
139         // Validate the token.
140         if (!pImport->IsValidToken(fieldDef) || (TypeFromToken(fieldDef) != mdtFieldDef))
141         {
142             ThrowHR(E_INVALIDARG);
143         }
144
145         // Make sure we have enough info about the class.
146         Init();
147
148         // Uninstantiated generics (eg, Foo<T>) don't have static data. Must use instantiated (eg Foo<int>)
149         // But all CordbClass instances are uninstantiated. So this should fail for all generic types.
150         // Normally, debuggers should be using ICorDebugType instead.
151         // Though in the forward compat case, they'll hit this.
152         if (HasTypeParams())
153         {
154             ThrowHR(CORDBG_E_STATIC_VAR_NOT_AVAILABLE);
155         }
156
157
158         // Lookup the field given its metadata token.
159         FieldData *pFieldData;
160
161         hr = GetFieldInfo(fieldDef, &pFieldData);
162
163         // This field was added by EnC, need to use EnC specific code path
164         if (hr == CORDBG_E_ENC_HANGING_FIELD)
165         {
166             // Static fields added with EnC hang off the EnCFieldDesc
167             hr = GetEnCHangingField(fieldDef,
168                 &pFieldData,
169                 NULL);
170
171             if (SUCCEEDED(hr))
172             {
173                 fEnCHangingField = TRUE;
174             }
175             // Note: the FieldOffset in pFieldData has been cooked to produce
176             // the correct address of the field in the syncBlock.
177             // @todo: extend Debugger_IPCEFieldData so we don't have to cook the offset here
178         }
179
180         IfFailThrow(hr);
181
182         {
183             Instantiation emptyInst;
184
185             hr = CordbClass::GetStaticFieldValue2(GetModule(),
186                 pFieldData,
187                 fEnCHangingField,
188                 &emptyInst,
189                 pFrame,
190                 ppValue);
191             // Let hr fall through
192         }
193     }
194     EX_CATCH_HRESULT(hr);
195
196     // Translate Failure HRs.
197     if (pImport != NULL)
198     {
199         hr = CordbClass::PostProcessUnavailableHRESULT(hr, pImport, fieldDef);
200     }
201
202     return hr;
203
204 }
205
206 //-----------------------------------------------------------------------------
207 // Common helper for accessing statics from both CordbClass and CordbType.
208 // 
209 // Arguments:
210 //   pModule - module containing the class
211 //   pFieldData - field data describing the field (this is correlated to a 
212 //         mdFieldDef, but has more specific data)
213 //   fEnCHangingField - field storage hangs off the FieldDesc for EnC
214 //   pInst - generic instantiation.
215 //   pFrame - frame used for context for Thread-static, AD-static, etc.
216 //   ppValue - OUT: out parameter to get value.
217 //
218 // Returns:
219 //   S_OK on success. 
220 //   CORDBG_E_FIELD_NOT_STATIC - if field isn't static.
221 //   CORDBG_E_STATIC_VAR_NOT_AVAILABLE - if field storage is not available.
222 //   Else some other failure.
223 /* static */
224 HRESULT CordbClass::GetStaticFieldValue2(CordbModule * pModule,
225                                          FieldData * pFieldData,
226                                          BOOL fEnCHangingField,
227                                          const Instantiation * pInst,
228                                          ICorDebugFrame * pFrame,
229                                          ICorDebugValue ** ppValue)
230 {
231     FAIL_IF_NEUTERED(pModule);
232     INTERNAL_SYNC_API_ENTRY(pModule->GetProcess());
233     _ASSERTE((pModule->GetProcess()->GetShim() == NULL) || pModule->GetProcess()->GetSynchronized());
234     HRESULT hr = S_OK;
235
236     if (!pFieldData->m_fFldIsStatic)
237     {
238         return CORDBG_E_FIELD_NOT_STATIC;
239     }
240
241     CORDB_ADDRESS pRmtStaticValue = NULL;
242     CordbProcess * pProcess = pModule->GetProcess();
243
244     if (pFieldData->m_fFldIsCollectibleStatic)
245     {
246         EX_TRY
247         {
248             pRmtStaticValue = pProcess->GetDAC()->GetCollectibleTypeStaticAddress(pFieldData->m_vmFieldDesc, 
249                                                                                   pModule->GetAppDomain()->GetADToken());
250         }
251         EX_CATCH_HRESULT(hr);
252         if(FAILED(hr)) 
253         {
254             return hr;
255         }
256     }
257     else if (!pFieldData->m_fFldIsTLS && !pFieldData->m_fFldIsContextStatic)
258     {
259         // Statics never move, so we always address them using their absolute address.
260         _ASSERTE(pFieldData->OkToGetOrSetStaticAddress());
261         pRmtStaticValue = pFieldData->GetStaticAddress();
262     }
263     else
264     {
265         // We've got a thread or context local static
266
267         if( fEnCHangingField )
268         {
269             // fEnCHangingField is set for fields added with EnC which hang off the FieldDesc.
270             // Thread-local and context-local statics cannot be added with EnC, so we shouldn't be here
271             // if this is an EnC field is thread- or context-local.
272             _ASSERTE(!pFieldData->m_fFldIsTLS );
273             _ASSERTE(!pFieldData->m_fFldIsContextStatic );
274         }
275         else
276         {
277             if (pFrame == NULL)
278             {
279                 return E_INVALIDARG;
280             }
281
282             CordbFrame * pRealFrame = CordbFrame::GetCordbFrameFromInterface(pFrame);
283             _ASSERTE(pRealFrame != NULL);
284
285             // Get the thread we are working on
286             CordbThread *  pThread  = pRealFrame->m_pThread;
287
288             EX_TRY
289             {
290                 pRmtStaticValue = pProcess->GetDAC()->GetThreadOrContextStaticAddress(pFieldData->m_vmFieldDesc, 
291                                                                                       pThread->m_vmThreadToken);
292             }
293             EX_CATCH_HRESULT(hr);
294             if(FAILED(hr)) 
295             {
296                 return hr;
297             }
298
299         }
300     }
301
302     if (pRmtStaticValue == NULL)
303     {
304         // type probably wasn't loaded yet.
305         // The debugger may chose to func-eval the creation of an instance of this type and try again.
306         return CORDBG_E_STATIC_VAR_NOT_AVAILABLE;
307     }
308
309     SigParser sigParser;
310     hr = S_OK;
311     EX_TRY
312     {
313         hr = pFieldData->GetFieldSignature(pModule, &sigParser);
314     }
315     EX_CATCH_HRESULT(hr);
316     IfFailRet(hr);
317
318     CordbType * pType;
319     IfFailRet (CordbType::SigToType(pModule, &sigParser, pInst, &pType));
320
321     bool fIsValueClass = false;
322     EX_TRY
323     {
324         fIsValueClass = pType->IsValueType(); // throws
325     }
326     EX_CATCH_HRESULT(hr);
327     IfFailRet(hr);
328
329     // Static value classes are stored as handles so that GC can deal with them properly.  Thus, we need to follow the
330     // handle like an objectref.  Do this by forcing CreateValueByType to think this is an objectref. Note: we don't do
331     // this for value classes that have an RVA, since they're layed out at the RVA with no handle.
332     bool fIsBoxed = (fIsValueClass &&
333                      !pFieldData->m_fFldIsRVA &&
334                      !pFieldData->m_fFldIsPrimitive &&
335                      !pFieldData->m_fFldIsTLS &&
336                      !pFieldData->m_fFldIsContextStatic);
337
338     TargetBuffer remoteValue(pRmtStaticValue, CordbValue::GetSizeForType(pType, fIsBoxed ? kBoxed : kUnboxed));
339     ICorDebugValue * pValue;
340     
341     EX_TRY
342     {
343         CordbValue::CreateValueByType(pModule->GetAppDomain(),
344                                       pType,
345                                       fIsBoxed,
346                                       remoteValue, 
347                                       MemoryRange(NULL, 0),
348                                       NULL,
349                                       &pValue);  // throws
350     }
351     EX_CATCH_HRESULT(hr);
352
353     if (SUCCEEDED(hr))
354     {
355         *ppValue = pValue;
356     }
357
358     return hr;
359 }
360
361
362 //-----------------------------------------------------------------------------
363 // Public method to build a CordbType from a CordbClass.
364 // This is used to build up generic types. Eg, build:
365 //    List<T>  + { int  } --> List<int>
366 //
367 // Arguments:
368 //  elementType - element type. Either ELEMENT_TYPE_CLASS, or ELEMENT_TYPE_VALUETYPE.
369 //      We could technically figure this out from the metadata (by looking if it derives
370 //      from System.ValueType).
371 //  cTypeArgs - number of elements in rgpTypeArgs array
372 //  rgpTypeArgs - array for type args.
373 //  ppType - OUT: out parameter to hold resulting type.
374 //
375 // Returns:
376 //   S_OK on success. Else false.
377 //
378 HRESULT CordbClass::GetParameterizedType(CorElementType elementType, 
379                                          ULONG32 cTypeArgs, 
380                                          ICorDebugType * rgpTypeArgs[], 
381                                          ICorDebugType ** ppType)
382 {
383     PUBLIC_API_ENTRY(this);
384     FAIL_IF_NEUTERED(this);
385     VALIDATE_POINTER_TO_OBJECT(ppType, ICorDebugType **);
386     ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess());
387
388   // Note: Do not call Init() to find out if its a VC or not.
389   // Rather expect the client to tell us. This means the debug client
390   // can describe type instantiations not yet seen in the EE.
391
392     if ((elementType != ELEMENT_TYPE_CLASS) && (elementType != ELEMENT_TYPE_VALUETYPE))
393     {
394         return E_INVALIDARG;
395     }
396
397     // Prefast overflow check:
398     S_UINT32 allocSize = S_UINT32( cTypeArgs ) * S_UINT32( sizeof(CordbType *) );
399
400     if (allocSize.IsOverflow())
401     {
402         return E_INVALIDARG;
403     }
404
405     CordbAppDomain * pClassAppDomain = GetAppDomain();
406
407     // Note: casting from (ICorDebugType **) to (CordbType **) is not valid.
408     // Offsets may differ.  Copy and validate the type array.
409     CordbType ** ppArgTypes = reinterpret_cast<CordbType **>(_alloca( allocSize.Value()));
410
411     for (unsigned int i = 0; i < cTypeArgs; i++)
412     {
413         ppArgTypes[i] = static_cast<CordbType *>( rgpTypeArgs[i] );
414
415         CordbAppDomain * pArgAppDomain = ppArgTypes[i]->GetAppDomain();
416
417         if ((pArgAppDomain != NULL) && (pArgAppDomain != pClassAppDomain))
418         {
419             return CORDBG_E_APPDOMAIN_MISMATCH;
420         }
421     }
422
423     {
424         CordbType * pResultType;
425
426         Instantiation typeInstantiation(cTypeArgs, ppArgTypes);
427
428         HRESULT hr = CordbType::MkType(pClassAppDomain, elementType, this, &typeInstantiation, &pResultType);
429
430         if (FAILED(hr))
431         {
432             return hr;
433         }
434
435         *ppType = pResultType;
436     }
437
438     _ASSERTE(*ppType);
439
440     if (*ppType)
441     {
442         (*ppType)->AddRef();
443     }
444     return S_OK;
445 }
446
447 //-----------------------------------------------------------------------------
448 // Returns true if the field is a static literal.
449 // In this case, the debugger should get the value from the metadata.
450 //-----------------------------------------------------------------------------
451 bool IsFieldStaticLiteral(IMetaDataImport *pImport, mdFieldDef fieldDef)
452 {
453     DWORD dwFieldAttr;
454     HRESULT hr2 = pImport->GetFieldProps(
455         fieldDef,
456         NULL,
457         NULL,
458         0,
459         NULL,
460         &dwFieldAttr,
461         NULL,
462         0,
463         NULL,
464         NULL,
465         0);
466
467     if (SUCCEEDED(hr2) && IsFdLiteral(dwFieldAttr))
468     {
469         return true;
470     }
471
472     return false;
473 }
474
475
476 //-----------------------------------------------------------------------------
477 // Filter to determine a more descriptive failing HResult for a field lookup.
478 // 
479 // Parameters: 
480 //   hr - incoming ambiguous HR.
481 //   pImport - metadata importer for this class.
482 //   feildDef - field being looked up.
483 //
484 // Returns:
485 //  hr - the incoming HR if no further HR can be determined.
486 //  else another failing HR that it judged to be more specific that the incoming HR.
487 //-----------------------------------------------------------------------------
488 HRESULT CordbClass::PostProcessUnavailableHRESULT(HRESULT hr,
489                                        IMetaDataImport *pImport,
490                                        mdFieldDef fieldDef)
491 {
492     CONTRACTL
493     {
494         NOTHROW; // just translates an HR. shouldn't need to throw.
495     }
496     CONTRACTL_END;
497
498     if (hr == CORDBG_E_FIELD_NOT_AVAILABLE)
499     {
500         if (IsFieldStaticLiteral(pImport, fieldDef))
501         {
502             return CORDBG_E_VARIABLE_IS_ACTUALLY_LITERAL;
503         }
504     }
505
506     return hr;
507 }
508
509 //-----------------------------------------------------------------------------
510 // Public method to get the Module that this class lives in.
511 //
512 // Parameters:
513 //    ppModule - OUT: holds module that this class gets in. 
514 //
515 // Returns:
516 //   S_OK on success.
517 //-----------------------------------------------------------------------------
518 HRESULT CordbClass::GetModule(ICorDebugModule **ppModule)
519 {
520     FAIL_IF_NEUTERED(this);
521     VALIDATE_POINTER_TO_OBJECT(ppModule, ICorDebugModule **);
522
523     *ppModule = static_cast<ICorDebugModule*> (m_pModule);
524     m_pModule->ExternalAddRef();
525
526     return S_OK;
527 }
528
529 //-----------------------------------------------------------------------------
530 // Get the mdTypeDef token that this class corresponds to.
531 //
532 // Parameters: 
533 //   pTypeDef - OUT: out param to get typedef token.
534 // 
535 // Returns:
536 //   S_OK - on success. 
537 //-----------------------------------------------------------------------------
538 HRESULT CordbClass::GetToken(mdTypeDef *pTypeDef)
539 {
540     FAIL_IF_NEUTERED(this);
541     VALIDATE_POINTER_TO_OBJECT(pTypeDef, mdTypeDef *);
542
543     _ASSERTE(TypeFromToken(m_token) == mdtTypeDef);
544
545     *pTypeDef = m_token;
546
547     return S_OK;
548 }
549
550 //-----------------------------------------------------------------------------
551 // Set the JMC status on all of our member functions.
552 // The current implementation just uses the metadata to enumerate all
553 // methods and then calls SetJMCStatus on each method.
554 // This isn't great perf, but this should never be needed in a
555 // perf-critical situation.
556 //
557 // Parameters:
558 //    fIsUserCode - true to set entire class to user code. False to set to 
559 //       non-user code.
560 //
561 // Returns:
562 //    S_OK on success. On failure, the user-code status of the methods in the 
563 //      class is random.
564 //-----------------------------------------------------------------------------
565 HRESULT CordbClass::SetJMCStatus(BOOL fIsUserCode)
566 {
567     PUBLIC_REENTRANT_API_ENTRY(this);
568     FAIL_IF_NEUTERED(this);
569     ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess());
570
571     // Get the member functions via a meta data interface
572     CordbModule * pModule = GetModule();
573
574     // Ensure that our process is in a sane state.
575     CordbProcess * pProcess = pModule->GetProcess();
576     _ASSERTE(pProcess != NULL);
577
578     IMetaDataImport * pImport = NULL;
579     HCORENUM phEnum = 0;
580
581     HRESULT hr = S_OK;
582
583     mdMethodDef rTokens[100];
584     ULONG i;
585     ULONG count;
586
587     EX_TRY
588     {   
589         pImport = pModule->GetMetaDataImporter();
590         do
591         {
592             hr = pImport->EnumMethods(&phEnum, m_token, rTokens, NumItems(rTokens), &count);
593             IfFailThrow(hr);
594
595             for (i = 0; i < count; i++)
596             {
597                 RSLockHolder lockHolder(pProcess->GetProcessLock());
598                 // Need the ICorDebugFunction to query for JMC status.
599                 CordbFunction * pFunction = pModule->LookupOrCreateFunctionLatestVersion(rTokens[i]);
600
601                 lockHolder.Release(); // Must release before sending an IPC event
602                 hr = pFunction->SetJMCStatus(fIsUserCode);            
603                 IfFailThrow(hr);
604             }
605         }
606         while (count > 0);
607
608         _ASSERTE(SUCCEEDED(hr));
609     }
610     EX_CATCH_HRESULT(hr);
611
612     if ((pImport != NULL) && (phEnum != 0))
613     {
614         pImport->CloseEnum(phEnum);
615     }
616
617     return hr;
618
619 }
620
621 //-----------------------------------------------------------------------------
622 // We have to go the the EE to find out if a class is a value
623 // class or not.  This is because there is no flag for this, but rather
624 // it depends on whether the class subclasses System.ValueType (apart
625 // from System.Enum...).  Replicating all that resoultion logic
626 // does not seem like a good plan.
627 //
628 // We also accept other "evidence" that the class is or isn't a VC, in
629 // particular:
630 //   - It is definitely a VC if it has been used after a
631 //     E_T_VALUETYPE in a signature.
632 //   - It is definitely not a VC if it has been used after a
633 //     E_T_CLASS in a signature.
634 //   - It is definitely a VC if it has been used in combination with
635 //     E_T_VALUETYPE in one of COM API operations that take both
636 //     a ICorDebugClass and a CorElementType (e.g. GetParameterizedType)
637 //
638 // !!!Note the following!!!!
639 //   - A class may still be a VC even if it has been
640 //     used in combination with E_T_CLASS in one of COM API operations that take both
641 //     a ICorDebugClass and a CorElementType (e.g. GetParameterizedType).
642 //     We allow the user of the API to specify E_T_CLASS when the VC status
643 //     is not known or is not important.
644 //
645 // Return Value:
646 //   indicates whether this is a value-class
647 // 
648 // Notes:
649 //   Throws CORDBG_E_CLASS_NOT_LOADED or synchronization errors on failure
650 //-----------------------------------------------------------------------------
651 bool CordbClass::IsValueClass()
652 {
653     INTERNAL_API_ENTRY(this);
654     THROW_IF_NEUTERED(this);
655
656         if (!m_fIsValueClassKnown)
657     {
658         ATT_REQUIRE_STOPPED_MAY_FAIL_OR_THROW(GetProcess(), ThrowHR);
659         Init();
660     }
661     return m_fIsValueClass;
662 }
663
664 //-----------------------------------------------------------------------------
665 // Get a CordbType for the 'this' pointer of a method in a CordbClass.
666 // The 'this' pointer is argument #0 in an instance method.
667 // 
668 // For ReferenceTypes (ELEMENT_TYPE_CLASS), the 'this' pointer is just a 
669 // normal reference, and so GetThisType() behaves like GetParameterizedType().
670 // For ValueTypes, the 'this' pointer is a byref. 
671 //
672 // Arguments:
673 //   pInst - instantiation info (eg, the type parameters) to produce CordbType
674 //   ppResultType - OUT: out parameter to hold outgoing CordbType.
675 //
676 // Returns:
677 //   S_OK on success. Else failure.
678 //
679 HRESULT CordbClass::GetThisType(const Instantiation * pInst, CordbType ** ppResultType)
680 {
681     FAIL_IF_NEUTERED(this);
682     
683     HRESULT hr = S_OK;
684     // Note: We have to call Init() here to find out if it really a VC or not.
685     bool fIsValueClass = false;
686     EX_TRY
687     {
688         fIsValueClass = IsValueClass();
689     }
690     EX_CATCH_HRESULT(hr);
691
692     if (FAILED(hr))
693     {
694         return hr;
695     }
696
697     if (fIsValueClass)
698     {
699         CordbType *pType;
700
701         hr = CordbType::MkType(GetAppDomain(),   // OK: this E_T_VALUETYPE will be normalized by MkType
702                                ELEMENT_TYPE_VALUETYPE, 
703                                this, 
704                                pInst, 
705                                &pType);
706         
707         if (!SUCCEEDED(hr))
708         {
709             return hr;
710         }
711
712         hr = CordbType::MkType(GetAppDomain(), ELEMENT_TYPE_BYREF, 0, pType, ppResultType);
713         
714         if (!SUCCEEDED(hr))
715         {
716             return hr;
717         }
718     }
719     else 
720     {
721         hr = CordbType::MkType(GetAppDomain(), ELEMENT_TYPE_CLASS, this, pInst, ppResultType);
722
723         if (!SUCCEEDED(hr))
724         {
725             return hr;
726         }
727     }
728
729     return hr;
730 }
731
732
733 //-----------------------------------------------------------------------------
734 // Initialize the CordbClass.
735 // This will collect all the field information via the DAC, and also determine
736 // whether this Type is a ReferenceType or ValueType.
737 //
738 // Parameters:
739 //   fForceInit - if true, always reinitialize. If false, may skip 
740 //     initialization if we believe we already have the info.
741 //
742 // Note:
743 //   Throws CORDBG_E_CLASS_NOT_LOADED on failure
744 //-----------------------------------------------------------------------------
745 void CordbClass::Init(ClassLoadLevel desiredLoadLevel)
746 {
747     INTERNAL_SYNC_API_ENTRY(this->GetProcess()); 
748
749     CordbProcess * pProcess = GetProcess();
750     IDacDbiInterface* pDac = pProcess->GetDAC();
751
752     // If we've done a continue since the last time we got hanging static fields,
753     // we should clear out our cache, since everything may have moved.
754     if (m_continueCounterLastSync < GetProcess()->m_continueCounter)
755     {
756         m_hangingFieldsStatic.Clear();
757         m_continueCounterLastSync = GetProcess()->m_continueCounter;
758     }
759
760     if (m_loadLevel < desiredLoadLevel)
761     {
762         // reset everything
763         m_loadLevel = Constructed;
764         m_fIsValueClass = false;
765         m_fIsValueClassKnown = false;
766         m_fHasTypeParams = false;
767         m_classInfo.Clear();
768         // @dbgtodo Microsoft inspection: declare a constant to replace badbad
769         m_classInfo.m_objectSize = 0xbadbad;
770         VMPTR_TypeHandle vmTypeHandle = VMPTR_TypeHandle::NullPtr();
771
772         // basic info load level
773         if(desiredLoadLevel >= BasicInfo)
774         {
775             vmTypeHandle = pDac->GetTypeHandle(m_pModule->GetRuntimeModule(), GetToken());
776             SetIsValueClass(pDac->IsValueType(vmTypeHandle));
777             m_fHasTypeParams = !!pDac->HasTypeParams(vmTypeHandle);
778             m_loadLevel = BasicInfo;
779         }
780
781         // full info load level
782         if(desiredLoadLevel == FullInfo)
783         {
784             VMPTR_AppDomain vmAppDomain = VMPTR_AppDomain::NullPtr();
785             VMPTR_DomainFile vmDomainFile = m_pModule->GetRuntimeDomainFile();
786             if (!vmDomainFile.IsNull())
787             {
788                 DomainFileInfo info;
789                 pDac->GetDomainFileData(vmDomainFile, &info);
790                 vmAppDomain = info.vmAppDomain;
791             }
792             pDac->GetClassInfo(vmAppDomain, vmTypeHandle, &m_classInfo);
793         
794             BOOL fGotUnallocatedStatic = GotUnallocatedStatic(&m_classInfo.m_fieldList);
795             
796             // if we have an unallocated static don't record that we reached FullInfo stage
797             // this seems pretty ugly but I don't want to bite off cleaning this up just yet
798             // Not saving the FullInfo stage effectively means future calls to Init() will
799             // re-init everything and some parts of DBI may be depending on that re-initialization
800             // with alternate data in order to operate correctly
801             if(!fGotUnallocatedStatic)
802                 m_loadLevel = FullInfo;
803         }
804     }
805 } // CordbClass::Init
806
807 // determine if any fields for a type are unallocated statics
808 BOOL CordbClass::GotUnallocatedStatic(DacDbiArrayList<FieldData> * pFieldList)
809 {
810     BOOL fGotUnallocatedStatic = FALSE;
811     int count = 0;
812     while ((count < pFieldList->Count()) && !fGotUnallocatedStatic )
813     {
814         if ((*pFieldList)[count].OkToGetOrSetStaticAddress() &&
815             (*pFieldList)[count].GetStaticAddress() == NULL )
816         {
817             // The address for a regular static field isn't available yet
818             // How can this happen?  Statics appear to get allocated during domain load.
819             // There may be some lazieness or a race-condition involved.
820             fGotUnallocatedStatic = TRUE;
821         }
822         ++count;
823     }
824     return fGotUnallocatedStatic;
825 } // CordbClass::GotUnallocatedStatic
826
827 /*
828  * FieldData::GetFieldSignature
829  *
830  * Get the field's full metadata signature. This may be cached, but for dynamic modules we'll always read it from
831  * the metadata.
832  *
833  * Parameters:
834  *    pModule - pointer to the module that contains the field
835  *
836  *    pSigParser - OUT: the full signature for the field.
837  *
838  * Returns:
839  *    HRESULT for success or failure.
840  *
841  */
842 HRESULT FieldData::GetFieldSignature(CordbModule *pModule, 
843                                                   SigParser *pSigParser)
844 {
845     CONTRACTL
846     {
847         THROWS;
848     }
849     CONTRACTL_END;
850
851     INTERNAL_SYNC_API_ENTRY(pModule->GetProcess());
852
853     HRESULT hr = S_OK;
854
855     IMetaDataImport * pImport = pModule->GetMetaDataImporter(); // throws;
856
857     PCCOR_SIGNATURE fieldSignature = NULL;
858     ULONG size = ((ULONG) -1);
859
860     _ASSERTE(pSigParser != NULL);
861
862     // If the module is dynamic, there had better not be a cached field signature.
863     _ASSERTE(!pModule->IsDynamic() || (m_fldSignatureCache == NULL));
864
865     // If the field signature cache is null, or if this is a dynamic module, then go read the signature from the
866     // matadata. We always read from the metadata for dynamic modules because our metadata blob is constantly
867     // getting deleted and re-allocated. If we kept a pointer to the signature, we'd end up pointing to bad data.
868     if (m_fldSignatureCache == NULL)
869     {
870         // Go to the metadata for all fields: previously the left-side tranferred over
871         // single-byte signatures as part of the field info.  Since the left-side
872         // goes to the metadata anyway, and we already fetch plenty of other metadata,
873         // I don't believe that fetching it here instead of transferring it over
874         // is going to slow things down at all, and
875         // in any case will not be where the primary optimizations lie...
876
877         IfFailRet(pImport->GetFieldProps(m_fldMetadataToken, NULL, NULL, 0, NULL, NULL,
878                                                       &fieldSignature,
879                                                       &size,
880                                                       NULL, NULL, NULL));
881
882         // Point past the calling convention
883         CorCallingConvention conv;
884
885         // Move pointer, 
886         BYTE * pOldPtr = (BYTE*) fieldSignature;
887         conv = (CorCallingConvention) CorSigUncompressData(fieldSignature);
888         _ASSERTE(conv == IMAGE_CEE_CS_CALLCONV_FIELD);
889         size -= (ULONG) (((BYTE*) fieldSignature) - pOldPtr); // since we updated filedSignature, adjust size
890
891         // Although the pointer will keep updating, the size should be the same. So we assert that.
892         _ASSERTE((m_fldSignatureCacheSize == 0) || (m_fldSignatureCacheSize == size));
893         
894         // Cache the value for non-dynamic modules, so this is faster later.
895         // Since we're caching in a FieldData, we can't store the actual SigParser object.
896         if (!pModule->IsDynamic())
897         {
898             m_fldSignatureCache = fieldSignature;
899             m_fldSignatureCacheSize = size;
900         }      
901     }
902     else
903     {
904         // We have a cached value, so return it. Note: we should never have a cached value for a field in a dynamic
905         // module.
906         CONSISTENCY_CHECK_MSGF((!pModule->IsDynamic()),
907                                ("We should never cache a field signature in a dynamic module! Module=%p This=%p",
908                                 pModule, this));
909
910         fieldSignature  = m_fldSignatureCache;
911         size            = m_fldSignatureCacheSize;
912     }
913
914     _ASSERTE(fieldSignature != NULL);
915     _ASSERTE(size != ((ULONG) -1));
916     *pSigParser = SigParser(fieldSignature, size);
917     return hr;
918 }
919
920 // CordbClass::InitEnCFieldInfo
921 // Initializes an instance of EnCHangingFieldInfo.
922 // Arguments:
923 //     input:  fStatic       - flag to indicate whether the EnC field is static
924 //             pObject       - For instance fields, the Object instance containing the the sync-block. 
925 //                             For static fields (if this is being called from GetStaticFieldValue) object is NULL.
926 //             fieldToken    - token for the EnC field
927 //             metadataToken - metadata token for this instance of CordbClass
928 //     output: pEncField     - the fields of this class will be appropriately initialized
929 void CordbClass::InitEnCFieldInfo(EnCHangingFieldInfo * pEncField, 
930                                   BOOL                  fStatic,
931                                   CordbObjectValue *    pObject, 
932                                   mdFieldDef            fieldToken, 
933                                   mdTypeDef             classToken)
934 {
935     IDacDbiInterface * pInterface = GetProcess()->GetDAC();
936
937     if (fStatic)
938     {
939         // the field is static, we don't need any additional data
940         pEncField->Init(VMPTR_Object::NullPtr(),      /* vmObject */
941                         NULL,                         /* offsetToVars */
942                         fieldToken, 
943                         ELEMENT_TYPE_MAX, 
944                         classToken, 
945                         m_pModule->GetRuntimeDomainFile());
946     }
947     else
948     {
949         // This is an instance field, we need to pass a bunch of type information back
950         _ASSERTE(pObject != NULL);
951         
952         pEncField->Init(pInterface->GetObject(pObject->m_id),      // VMPTR to the object instance of interest.
953                         pObject->GetInfo().objOffsetToVars,         // The offset from the beginning of the object 
954                                                                     // to the beginning of the fields. Fields added 
955                                                                     // with EnC don't actually reside in the object 
956                                                                     // (they hang off the sync block instead), so 
957                                                                     // this is used to compute the returned field 
958                                                                     // offset (fieldData.m_fldInstanceOffset). This 
959                                                                     // makes it appear to be an offset from the object.
960                                                                     // Ideally we wouldn't do any of this, and just 
961                                                                     // explicitly deal with absolute addresses (instead
962                                                                     // of "offsets") for EnC hanging instance fields.
963                         fieldToken,                                 // Field token for the added field.
964                         pObject->GetInfo().objTypeData.elementType, // An indication of the type of object to which
965                                                                     // we're adding a field (specifically,
966                                                                     // whether it's a value type or a class).
967                                                                     // This is used only for log messages, and could 
968                                                                     // be removed.
969                         classToken,                                 // metadata token for the class 
970                         m_pModule->GetRuntimeDomainFile());         // Domain file for the class
971     }
972 } // CordbClass::InitFieldData
973
974 // CordbClass::GetEnCFieldFromDac
975 // Get information via the DAC about a field added with Edit and Continue.
976 // Arguments: 
977 //     input: fStatic       - flag to indicate whether the EnC field is static
978 //            pObject       - For instance fields, the Object instance containing the the sync-block. 
979 //                            For static fields (if this is being called from GetStaticFieldValue) object is NULL.
980 //            fieldToken    - token for the EnC field
981 //     output: pointer to an initialized instance of FieldData that has been added to the appropriate table
982 //     in our cache
983 FieldData * CordbClass::GetEnCFieldFromDac(BOOL               fStatic,
984                                            CordbObjectValue * pObject,
985                                            mdFieldDef         fieldToken)
986 {
987     EnCHangingFieldInfo encField;
988     mdTypeDef           metadataToken;
989     FieldData           fieldData, 
990                       * pInfo = NULL;
991     BOOL                fDacStatic;
992     CordbProcess *      pProcess = GetModule()->GetProcess();
993
994     _ASSERTE(pProcess != NULL);
995     IfFailThrow(GetToken(&metadataToken));
996     InitEnCFieldInfo(&encField, fStatic, pObject, fieldToken, metadataToken);
997
998     // Go get this particular field.
999     pProcess->GetDAC()->GetEnCHangingFieldInfo(&encField, &fieldData, &fDacStatic);
1000     _ASSERTE(fStatic == fDacStatic);
1001
1002     // Save the field results in our cache and get a stable pointer to the data
1003     if (fStatic)
1004     {
1005         pInfo = m_hangingFieldsStatic.AddFieldInfo(&fieldData);
1006     }
1007     else
1008     {
1009         pInfo = pObject->GetHangingFieldTable()->AddFieldInfo(&fieldData);
1010     }
1011
1012     // We should have a fresh copy of the data (don't want to return a pointer to data on our stack)
1013     _ASSERTE((void *)pInfo != (void *)&fieldData);
1014     _ASSERTE(pInfo->m_fFldIsStatic == (fStatic == TRUE));
1015     _ASSERTE(pInfo->m_fldMetadataToken == fieldToken);
1016
1017     // Pass a pointer to the data out.
1018     return pInfo;
1019 } // CordbClass::GetEnCFieldFromDac
1020
1021 //-----------------------------------------------------------------------------
1022 // Internal helper to get a FieldData for fields added by EnC after the type
1023 // was loaded.  Since object and MethodTable layout has already been fixed,
1024 // such added fields are "hanging" off some other data structure.  For instance 
1025 // fields, they're stored in a syncblock off the object.  For static fields
1026 // they're stored off the EnCFieldDesc.
1027 //
1028 // The caller must have already determined this is a hanging field (i.e.
1029 // GetFieldInfo returned CORDBG_E_ENC_HANGING_FIELDF).
1030 //
1031 // Arguments:
1032 //     input:  fldToken - field of interest to get.
1033 //             pObject  - For instance fields, the Object instance containing the the sync-block. 
1034 //                        For static fields (if this is being called from GetStaticFieldValue) object is NULL.
1035 //     output: ppFieldData - the FieldData matching the fldToken.
1036 // 
1037 // Returns:
1038 //   S_OK on success, failure code otherwise.
1039 //-----------------------------------------------------------------------------
1040 HRESULT CordbClass::GetEnCHangingField(mdFieldDef fldToken,
1041                                       FieldData **ppFieldData,
1042                                        CordbObjectValue * pObject)
1043 {
1044     FAIL_IF_NEUTERED(this);
1045     INTERNAL_SYNC_API_ENTRY(GetProcess());
1046
1047     HRESULT hr = S_OK;
1048     _ASSERTE(pObject == NULL || !pObject->IsNeutered() );
1049
1050     if (HasTypeParams())
1051     {
1052         _ASSERTE(!"EnC hanging field not yet implemented on constructed types!");
1053         return E_FAIL;
1054     }
1055
1056     // This must be a static field if no object was supplied
1057     BOOL fStatic = (pObject == NULL);
1058
1059     // Look for cached field information
1060     FieldData *pInfo = NULL;
1061     if (fStatic)
1062     {
1063         // Static fields should _NOT_ be cleared, since they stick around.  Thus
1064         // the separate tables.
1065         pInfo = m_hangingFieldsStatic.GetFieldInfo(fldToken);
1066     }
1067     else
1068     {
1069         // We must get new copies each time we call continue b/c we get the
1070         // actual Object ptr from the left side, which can move during a GC.
1071         pInfo = pObject->GetHangingFieldTable()->GetFieldInfo(fldToken);
1072     }
1073
1074     // We've found a previously located entry
1075     if (pInfo != NULL)
1076     {
1077         *ppFieldData = pInfo;
1078         return S_OK;
1079     }
1080
1081     // Field information not already available - go get it
1082     EX_TRY
1083     {
1084
1085         // We're not going to be able to get the instance-specific field
1086         // if we can't get the instance.
1087         if (!fStatic && pObject->GetInfo().objRefBad)
1088         {
1089             ThrowHR(CORDBG_E_INVALID_OBJECT);
1090         }
1091
1092         *ppFieldData = GetEnCFieldFromDac(fStatic, pObject, fldToken);
1093     }
1094     EX_CATCH_HRESULT(hr);
1095     return hr;
1096 }
1097
1098 //-----------------------------------------------------------------------------
1099 // Get a FieldData (which rich information, including details about storage)
1100 //  from a metadata token.
1101 // 
1102 // Parameters:
1103 //   fldToken - incoming metadata token specifying the field.
1104 //   ppFieldData - OUT: resulting FieldData structure.
1105 //
1106 // Returns:
1107 //   S_OK on success. else failure. 
1108 //-----------------------------------------------------------------------------
1109 HRESULT CordbClass::GetFieldInfo(mdFieldDef fldToken, FieldData **ppFieldData)
1110 {
1111     INTERNAL_SYNC_API_ENTRY(GetProcess());
1112
1113     Init();
1114     return SearchFieldInfo(GetModule(), &m_classInfo.m_fieldList, m_token, fldToken, ppFieldData);
1115 }
1116
1117
1118 //-----------------------------------------------------------------------------
1119 // Search an array of FieldData (pFieldList) for a field (fldToken).
1120 // The FieldData array must match the class supplied by classToken, and live 
1121 // in the supplied module.
1122 // 
1123 // Internal helper used by CordbType::GetFieldInfo, CordbClass::GetFieldInfo
1124 // 
1125 // Parameters:
1126 //    module -     module containing the class that the FieldData array matches.
1127 //    pFieldList - array of fields to search through and the number of elements in
1128 //                 the array.
1129 //    classToken - class that the data array matches. class must live in
1130 //                 the supplied moudle.
1131 //    fldToken -   metadata token of the field to search for. This field should be
1132 //                 on the class supplied by classToken.
1133 //
1134 // Returns:
1135 //    CORDBG_E_ENC_HANGING_FIELD for "hanging fields" (fields added via Enc) (common error).
1136 //    Returns S_OK, set ppFieldData = pointer into data array for matching field. (*retval)->m_fldMetadataToken == fldToken)
1137 //    Throws on other errors.
1138 //-----------------------------------------------------------------------------
1139 /* static */ 
1140 HRESULT CordbClass::SearchFieldInfo(
1141     CordbModule * pModule, 
1142     DacDbiArrayList<FieldData> * pFieldList, 
1143     mdTypeDef classToken, 
1144     mdFieldDef fldToken, 
1145     FieldData **ppFieldData
1146 )
1147 {
1148     int i;
1149
1150     IMetaDataImport * pImport = pModule->GetMetaDataImporter(); // throws      
1151
1152     HRESULT hr = S_OK;
1153     for (i = 0; i < pFieldList->Count(); i++)
1154     {
1155         if ((*pFieldList)[i].m_fldMetadataToken == fldToken)
1156         {
1157             // If the storage for this field isn't yet available (i.e. it is newly added with EnC)
1158             if (!(*pFieldList)[i].m_fFldStorageAvailable)
1159             {
1160                 // If we're a static literal, then return special HR to let
1161                 // debugger know that it should look it up via the metadata.
1162                 // Check m_fFldIsStatic first b/c that's fast.
1163                 if ((*pFieldList)[i].m_fFldIsStatic)
1164                 {
1165                     if (IsFieldStaticLiteral(pImport, fldToken))
1166                     {
1167                         ThrowHR(CORDBG_E_VARIABLE_IS_ACTUALLY_LITERAL);
1168                     }
1169                 }
1170
1171                 // This is a field added by EnC, caller needs to get instance-specific info.
1172                 return CORDBG_E_ENC_HANGING_FIELD; 
1173             }
1174
1175             *ppFieldData = &((*pFieldList)[i]);
1176             return S_OK;
1177         }
1178     }
1179
1180     // Hmmm... we didn't find the field on this class. See if the field really belongs to this class or not.
1181     mdTypeDef classTok;
1182
1183     hr = pImport->GetFieldProps(fldToken, &classTok, NULL, 0, NULL, NULL, NULL, 0, NULL, NULL, NULL);
1184     IfFailThrow(hr);
1185
1186     if (classTok == (mdTypeDef) classToken)
1187     {
1188         // Well, the field belongs in this class. The assumption is that the Runtime optimized the field away.
1189         ThrowHR(CORDBG_E_FIELD_NOT_AVAILABLE);
1190     }
1191
1192     // Well, the field doesn't even belong to this class...
1193     ThrowHR(E_INVALIDARG);
1194 }
1195