Remove always defined FEATURE_CORECLR
[platform/upstream/coreclr.git] / src / debug / daccess / dacdbiimpl.cpp
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 // File: DacDbiImpl.cpp
6 // 
7
8 //
9 // Implement DAC/DBI interface
10 //
11 //*****************************************************************************
12
13
14 #include "stdafx.h"
15
16 #include "dacdbiinterface.h"
17
18 #include "typestring.h"
19 #include "holder.h"
20 #include "debuginfostore.h"
21 #include "peimagelayout.inl"
22 #include "encee.h"
23 #include "switches.h"
24 #include "generics.h"
25 #include "stackwalk.h"
26
27 #include "dacdbiimpl.h"
28
29 #ifdef FEATURE_COMINTEROP
30 #include "runtimecallablewrapper.h"
31 #include "comcallablewrapper.h"
32 #endif // FEATURE_COMINTEROP
33
34 //-----------------------------------------------------------------------------
35 // Have standard enter and leave macros at the DacDbi boundary to enforce 
36 // standard behavior. 
37 // 1. catch exceptions and convert them at the boundary.
38 // 2. provide a space to hook logging and transitions.
39 // 3. provide a hook to verify return values.
40 //
41 // Usage notes:
42 // - use this at the DacDbi boundary; but not at internal functions
43 // - it's ok to Return from the middle.
44 //
45 // Expected usage is:
46 //  Foo() 
47 //  {
48 //      DD_ENTER_MAY_THROW
49 //      ...
50 //      if (...) { ThrowHr(E_SOME_FAILURE); }
51 //      ...
52 //      if (...) { return; } // early success case
53 //      ...
54 //  }
55 //-----------------------------------------------------------------------------
56
57
58
59
60 // Global allocator for DD. Access is protected under the g_dacCritSec lock.
61 IDacDbiInterface::IAllocator * g_pAllocator = NULL;
62
63 //---------------------------------------------------------------------------------------
64 //
65 // Extra sugar for wrapping IAllocator under friendly New/Delete operators.
66 //
67 // Sample usage:
68 //     void Foo(TestClass ** ppOut) 
69 //     {
70 //        *ppOut = NULL;
71 //        TestClass * p = new (forDbi) TestClass();
72 //        ...
73 //        if (ok) 
74 //        { 
75 //            *ppOut = p; 
76 //            return; // DBI will then free this memory.
77 //        } 
78 //        ...
79 //        DeleteDbiMemory(p);
80 //     }
81 //
82 //     Be very careful when using this on classes since Dbi and DAC may be in
83 //     separate dlls. This is best used when operating on blittable data-structures.
84 //     (no ctor/dtor, plain data fields) to guarantee the proper DLL isolation.
85 //     You don't want to call the ctor in DAC's context and the dtor in DBI's context
86 //     unless you really know what you're doing and that it's safe.
87 //
88
89 // Need a class to serve as a tag that we can use to overload New/Delete.
90 forDbiWorker forDbi;
91
92 void * operator new(size_t lenBytes, const forDbiWorker &)
93 {
94     _ASSERTE(g_pAllocator != NULL);
95     void *result = g_pAllocator->Alloc(lenBytes);
96     if (result == NULL) 
97     {
98         ThrowOutOfMemory();
99     }
100     return result;
101 }
102
103 void * operator new[](size_t lenBytes, const forDbiWorker &)
104 {
105     _ASSERTE(g_pAllocator != NULL);
106     void *result = g_pAllocator->Alloc(lenBytes);
107     if (result == NULL) 
108     {
109         ThrowOutOfMemory();
110     }
111     return result;
112 }
113
114 // Note: there is no C++ syntax for manually invoking this, but if a constructor throws an exception I understand that
115 // this delete operator will be invoked automatically to destroy the object.
116 void operator delete(void *p, const forDbiWorker &)
117 {
118     if (p == NULL)
119     {
120         return;
121     }
122     
123     _ASSERTE(g_pAllocator != NULL);
124     g_pAllocator->Free((BYTE*) p);
125
126 }
127
128 // Note: there is no C++ syntax for manually invoking this, but if a constructor throws an exception I understand that
129 // this delete operator will be invoked automatically to destroy the object.
130 void operator delete[](void *p, const forDbiWorker &)
131 {
132     if (p == NULL)
133     {
134         return;
135     }
136     
137     _ASSERTE(g_pAllocator != NULL);
138     g_pAllocator->Free((BYTE*) p);
139 }
140
141 // @dbgtodo  dac support: determine how to handle an array of class instances to ensure the dtors get 
142 // called correctly or document that they won't
143 // Delete memory and invoke dtor for memory allocated with 'operator (forDbi) new'
144 template<class T> void DeleteDbiMemory(T *p)
145 {    
146     if (p == NULL)
147     {
148         return;
149     }
150     p->~T();
151
152     _ASSERTE(g_pAllocator != NULL);    
153     g_pAllocator->Free((BYTE*) p);
154 }
155
156
157 //---------------------------------------------------------------------------------------
158 // Creates the DacDbiInterface object, used by Dbi.
159 //
160 // Arguments:
161 //    pTarget     - pointer to a Data-Target
162 //    baseAddress - non-zero base address of mscorwks in target to debug. 
163 //    pAllocator  - pointer to client allocator object. This lets DD allocate objects and
164 //                  pass them out back to the client, which can then delete them.
165 //                  DD takes a weak ref to this, so client must keep it alive until it 
166 //                  calls Destroy.
167 //    pMetadataLookup - callback interface to do internal metadata lookup. This is because
168 //                  metadata is not dac-ized.
169 //    ppInterface - mandatory out-parameter 
170 //
171 // Return Value:
172 //    S_OK on success.
173 //
174 //
175 // Notes:
176 //    On Windows, this is public function that can be retrieved by GetProcAddress.
177
178 //    On Mac, this is used internally by DacDbiMarshalStubInstance below
179 //    This will yield an IDacDbiInterface to provide structured access to the
180 //    data-target.
181 //
182 //    Must call Destroy to on interface to free its resources.
183 //
184 //---------------------------------------------------------------------------------------
185 STDAPI
186 DacDbiInterfaceInstance(
187     ICorDebugDataTarget * pTarget,
188     CORDB_ADDRESS baseAddress,
189     IDacDbiInterface::IAllocator * pAllocator,
190     IDacDbiInterface::IMetaDataLookup * pMetaDataLookup,
191     IDacDbiInterface ** ppInterface)
192 {
193     // No marshalling is done by the instantiationf function - we just need to setup the infrastructure.  
194     // We don't want to warn if this involves creating and accessing undacized data structures, 
195     // because it's for the infrastructure, not DACized code itself.
196     SUPPORTS_DAC_HOST_ONLY;     
197      
198     // Since this is public, verify it.
199     if ((ppInterface == NULL) || (pTarget == NULL) || (baseAddress == 0))
200     {
201         return E_INVALIDARG;
202     }
203
204     *ppInterface = NULL;
205
206     //
207     // Actually allocate the real object and initialize it.
208     //
209     DacDbiInterfaceImpl * pDac = new (nothrow) DacDbiInterfaceImpl(pTarget, baseAddress, pAllocator, pMetaDataLookup);
210     if (!pDac)
211     {
212         return E_OUTOFMEMORY;
213     }
214         
215     HRESULT hrStatus = pDac->Initialize();
216     
217     if (SUCCEEDED(hrStatus))
218     {
219         *ppInterface = pDac;
220     }
221     else
222     {
223         delete pDac;
224     }
225     return hrStatus;
226 }
227
228
229 //---------------------------------------------------------------------------------------
230 // Constructor. Instantiates a DAC/DBI interface around a DataTarget.
231 //
232 // Arguments:
233 //    pTarget     - pointer to a Data-Target
234 //    baseAddress - non-zero base address of mscorwks in target to debug. 
235 //    pAllocator  - pointer to client allocator object. This lets DD allocate objects and
236 //                  pass them out back to the client, which can then delete them.
237 //                  DD takes a weak ref to this, so client must keep it alive until it 
238 //                  calls Destroy.
239 //    pMetadataLookup - callback interface to do internal metadata lookup. This is because
240 //                  metadata is not dac-ized.
241 //
242 // Notes:
243 //    pAllocator is a weak reference. 
244 //---------------------------------------------------------------------------------------
245 DacDbiInterfaceImpl::DacDbiInterfaceImpl(
246     ICorDebugDataTarget* pTarget, 
247     CORDB_ADDRESS baseAddress,
248     IAllocator * pAllocator,
249     IMetaDataLookup * pMetaDataLookup
250 ) : ClrDataAccess(pTarget),
251     m_pAllocator(pAllocator),
252     m_pMetaDataLookup(pMetaDataLookup),
253     m_pCachedPEFile(VMPTR_PEFile::NullPtr()),
254     m_pCachedImporter(NULL),
255     m_isCachedHijackFunctionValid(FALSE)
256 {
257     _ASSERTE(baseAddress != NULL);
258     m_globalBase = CORDB_ADDRESS_TO_TADDR(baseAddress);
259
260     _ASSERTE(pMetaDataLookup != NULL);
261     _ASSERTE(pAllocator != NULL);
262     _ASSERTE(pTarget != NULL);
263
264 #ifdef _DEBUG
265     // Enable verification asserts in ICorDebug scenarios.  ICorDebug never guesses at the DAC path, so any
266     // mismatch should be fatal, and so always of interest to the user.
267     // This overrides the assignment in the base class ctor (which runs first).
268     m_fEnableDllVerificationAsserts = true;
269 #endif
270 }
271
272 //-----------------------------------------------------------------------------
273 // Destructor.
274 //
275 // Notes:
276 //    This gets invoked after Destroy().
277 //-----------------------------------------------------------------------------
278 DacDbiInterfaceImpl::~DacDbiInterfaceImpl()
279 {
280     SUPPORTS_DAC_HOST_ONLY;
281     // This will automatically chain to the base class dtor
282 }
283
284 //-----------------------------------------------------------------------------
285 // Called from DAC-ized code to get a IMDInternalImport
286 //
287 // Arguments:
288 //    pPEFile - PE file for which to get importer for
289 //    fThrowEx - if true, throw instead of returning NULL.
290 //
291 // Returns:
292 //    an Internal importer object for this file.
293 //    May return NULL or throw (depending on fThrowEx).
294 //    May throw in exceptional circumstances (eg, corrupt debuggee).
295 //
296 // Assumptions:
297 //    This is called from DAC-ized code within the VM, which 
298 //    was in turn called from some DD primitive. The returned importer will 
299 //    be used by the DAC-ized code in the callstack, but it won't be cached.
300 //
301 // Notes:
302 //    This is an Internal importer, not a public Metadata importer.
303 //
304 interface IMDInternalImport* DacDbiInterfaceImpl::GetMDImport(
305     const PEFile* pPEFile,
306     const ReflectionModule * pReflectionModule,
307     bool fThrowEx)
308 {
309     // Since this is called from an existing DAC-primitive, we already hold the g_dacCritSec lock.
310     // The lock conveniently protects our cache.
311     SUPPORTS_DAC;
312
313     IDacDbiInterface::IMetaDataLookup * pLookup = m_pMetaDataLookup;
314     _ASSERTE(pLookup != NULL);
315
316     VMPTR_PEFile vmPEFile = VMPTR_PEFile::NullPtr();
317
318     if (pPEFile != NULL)
319     {
320         vmPEFile.SetHostPtr(pPEFile);
321     }
322     else if (pReflectionModule != NULL)
323     {
324         // SOS and ClrDataAccess rely on special logic to find the metadata for methods in dynamic modules.
325         // We don't need to.  The RS has already taken care of the special logic for us.
326         // So here we just grab the PEFile off of the ReflectionModule and continue down the normal
327         // code path.  See code:ClrDataAccess::GetMDImport for comparison.
328         vmPEFile.SetHostPtr(pReflectionModule->GetFile());
329     }
330
331     // Optimize for the case where the VM queries the same Importer many times in a row.
332     if (m_pCachedPEFile == vmPEFile)
333     {
334         return m_pCachedImporter;
335     }
336     
337     // Go to DBI to find the metadata.
338     IMDInternalImport * pInternal = NULL;
339     bool isILMetaDataForNI = false;
340     EX_TRY
341     {
342         // If test needs it in the future, prop isILMetaDataForNI back up to
343         // ClrDataAccess.m_mdImports.Add() call.
344         // example in code:ClrDataAccess::GetMDImport
345         // CordbModule::GetMetaDataInterface also looks up MetaData and would need attention.
346
347         // This is the new codepath that uses ICorDebugMetaDataLookup.
348         // To get the old codepath that uses the v2 metadata lookup methods,
349         // you'd have to load DAC only and then you'll get ClrDataAccess's implementation
350         // of this function.
351         pInternal = pLookup->LookupMetaData(vmPEFile, isILMetaDataForNI);
352     }
353     EX_CATCH
354     {
355         // Any expected error we should ignore.
356         if ((GET_EXCEPTION()->GetHR() != HRESULT_FROM_WIN32(ERROR_PARTIAL_COPY)) &&
357             (GET_EXCEPTION()->GetHR() != CORDBG_E_READVIRTUAL_FAILURE) &&
358             (GET_EXCEPTION()->GetHR() != CORDBG_E_SYMBOLS_NOT_AVAILABLE) &&
359             (GET_EXCEPTION()->GetHR() != CORDBG_E_MODULE_LOADED_FROM_DISK))
360         {
361             EX_RETHROW;
362         }
363     }
364     EX_END_CATCH(SwallowAllExceptions)
365
366     if (pInternal == NULL)
367     {
368         SIMPLIFYING_ASSUMPTION(!"MD lookup failed"); 
369         if (fThrowEx)
370         {
371             ThrowHR(E_FAIL);
372         }
373         return NULL;
374     }
375     else
376     {
377         // Cache it such that it we look for the exact same Importer again, we'll return it.
378         m_pCachedPEFile   = vmPEFile;
379         m_pCachedImporter = pInternal;
380     }
381
382     return pInternal;
383 }
384
385 //-----------------------------------------------------------------------------
386 // Implementation of IDacDbiInterface
387 // See DacDbiInterface.h for full descriptions of all of these functions
388 //-----------------------------------------------------------------------------
389
390 // Destroy the connection, freeing up any resources.  
391 void DacDbiInterfaceImpl::Destroy()
392 {
393     m_pAllocator = NULL;
394
395     this->Release();
396     // Memory is deleted, don't access this object any more
397 }
398
399 // Check whether the version of the DBI matches the version of the runtime.
400 // See code:CordbProcess::CordbProcess#DBIVersionChecking for more information regarding version checking.
401 HRESULT DacDbiInterfaceImpl::CheckDbiVersion(const DbiVersion * pVersion)
402 {
403     DD_ENTER_MAY_THROW;
404
405     if (pVersion->m_dwFormat != kCurrentDbiVersionFormat)
406     {
407         return CORDBG_E_INCOMPATIBLE_PROTOCOL;
408     }
409     
410     if ((pVersion->m_dwProtocolBreakingChangeCounter != kCurrentDacDbiProtocolBreakingChangeCounter) ||
411         (pVersion->m_dwReservedMustBeZero1 != 0))
412     {
413         return CORDBG_E_INCOMPATIBLE_PROTOCOL;
414     }
415
416     return S_OK;
417 }
418
419 // Flush the DAC cache. This should be called when target memory changes.
420 HRESULT DacDbiInterfaceImpl::FlushCache()
421 {
422     // Non-reentrant. We don't want to flush cached instances from a callback.
423     // That would remove host DAC instances while they're being used.
424     DD_NON_REENTRANT_MAY_THROW; 
425
426     m_pCachedPEFile = VMPTR_PEFile::NullPtr();
427     m_pCachedImporter = NULL;
428     m_isCachedHijackFunctionValid = FALSE;
429
430     HRESULT hr  = ClrDataAccess::Flush();
431
432     // Current impl of Flush() should always succeed. If it ever fails, we want to know.
433     _ASSERTE(SUCCEEDED(hr));
434     return hr;
435 }
436
437 // enable or disable DAC target consistency checks
438 void DacDbiInterfaceImpl::DacSetTargetConsistencyChecks(bool fEnableAsserts)
439 {
440     // forward on to our ClrDataAccess base class
441     ClrDataAccess::SetTargetConsistencyChecks(fEnableAsserts);
442 }
443
444 // Query if Left-side is started up?  
445 BOOL DacDbiInterfaceImpl::IsLeftSideInitialized()
446 {
447     DD_ENTER_MAY_THROW;
448
449     if (g_pDebugger != NULL)
450     {
451         // This check is "safe".
452         // The initialize order in the left-side is:
453         // 1) g_pDebugger is an RVA based global initialized to NULL when the module is loaded.
454         // 2) Allocate a "Debugger" object.
455         // 3) run the ctor, which will set m_fLeftSideInitialized = FALSE.
456         // 4) assign the object to g_pDebugger.
457         // 5) later, LS initialization code will assign g_pDebugger->m_fLeftSideInitialized = TRUE.
458         //
459         // The memory write in #5 is atomic.  There is no window where we're reading unitialized data.
460         
461         return (g_pDebugger->m_fLeftSideInitialized != 0);
462     }
463
464     return FALSE;
465 }
466
467
468 // Determines if a given adddress is a CLR stub.
469 BOOL DacDbiInterfaceImpl::IsTransitionStub(CORDB_ADDRESS address)
470 {
471     DD_ENTER_MAY_THROW;
472
473     BOOL fIsStub = FALSE;     
474
475 #if defined(FEATURE_PAL)
476     // Currently IsIPInModule() is not implemented in the PAL.  Rather than skipping the check, we should
477     // either E_NOTIMPL this API or implement IsIPInModule() in the PAL.  Since ICDProcess::IsTransitionStub()
478     // is only called by VS in mixed-mode debugging scenarios, and mixed-mode debugging is not supported on 
479     // POSIX systems, there is really no incentive to implement this API at this point.
480     ThrowHR(E_NOTIMPL);
481
482 #else // !FEATURE_PAL    
483
484     TADDR ip = (TADDR)address;
485
486     if (ip == NULL)
487     {
488         fIsStub = FALSE;
489     }
490     else
491     {
492         fIsStub = StubManager::IsStub(ip);
493     }
494
495     // If it's in Mscorwks, count that as a stub too.
496     if (fIsStub == FALSE)
497     {
498         fIsStub = IsIPInModule(m_globalBase, ip);
499     }
500
501 #endif // FEATURE_PAL
502
503     return fIsStub;
504 }
505
506 // Gets the type of 'address'.
507 IDacDbiInterface::AddressType DacDbiInterfaceImpl::GetAddressType(CORDB_ADDRESS address)
508 {
509     DD_ENTER_MAY_THROW;
510     TADDR taAddr = CORDB_ADDRESS_TO_TADDR(address);
511
512     if (IsPossibleCodeAddress(taAddr) == S_OK)
513     {
514         if (ExecutionManager::IsManagedCode(taAddr))
515         {
516             return kAddressManagedMethod;
517         }
518
519         if (StubManager::IsStub(taAddr))
520         {
521             return kAddressRuntimeUnmanagedStub;
522         }
523     }
524
525     return kAddressUnrecognized;
526 }
527
528
529 // Get a VM appdomain pointer that matches the appdomain ID 
530 VMPTR_AppDomain DacDbiInterfaceImpl::GetAppDomainFromId(ULONG appdomainId)
531 {
532     DD_ENTER_MAY_THROW;
533
534     VMPTR_AppDomain vmAppDomain;
535
536     // @dbgtodo   dac support - We would like to wean ourselves off the IXClrData interfaces. 
537     IXCLRDataProcess *   pDAC = this;
538     ReleaseHolder<IXCLRDataAppDomain> pDacAppDomain;
539     
540     HRESULT hrStatus = pDAC->GetAppDomainByUniqueID(appdomainId, &pDacAppDomain);    
541     IfFailThrow(hrStatus);
542     
543     IXCLRDataAppDomain * pIAppDomain = pDacAppDomain;
544     AppDomain * pAppDomain = (static_cast<ClrDataAppDomain *> (pIAppDomain))->GetAppDomain();
545     SIMPLIFYING_ASSUMPTION(pAppDomain != NULL);
546     if (pAppDomain == NULL)
547     {
548         ThrowHR(E_FAIL); // corrupted left-side?
549     }
550         
551     TADDR addrAppDomain = PTR_HOST_TO_TADDR(pAppDomain);
552     vmAppDomain.SetDacTargetPtr(addrAppDomain);
553
554     return vmAppDomain;
555 }
556
557
558 // Get the AppDomain ID for an AppDomain.
559 ULONG DacDbiInterfaceImpl::GetAppDomainId(VMPTR_AppDomain   vmAppDomain)
560 {
561     DD_ENTER_MAY_THROW;
562
563     if (vmAppDomain.IsNull())
564     {
565         return 0;
566     }
567     else
568     {
569         AppDomain * pAppDomain = vmAppDomain.GetDacPtr();
570         return pAppDomain->GetId().m_dwId;
571     }
572 }
573
574 // Get the managed AppDomain object for an AppDomain.
575 VMPTR_OBJECTHANDLE DacDbiInterfaceImpl::GetAppDomainObject(VMPTR_AppDomain vmAppDomain)
576 {
577     DD_ENTER_MAY_THROW;
578
579     AppDomain* pAppDomain = vmAppDomain.GetDacPtr();
580     OBJECTHANDLE hAppDomainManagedObject = pAppDomain->GetRawExposedObjectHandleForDebugger();
581     VMPTR_OBJECTHANDLE vmObj = VMPTR_OBJECTHANDLE::NullPtr();
582     vmObj.SetDacTargetPtr(hAppDomainManagedObject);
583     return vmObj;
584
585 }
586
587 // Determine if the specified AppDomain is the default domain
588 BOOL DacDbiInterfaceImpl::IsDefaultDomain(VMPTR_AppDomain   vmAppDomain)
589 {   
590     DD_ENTER_MAY_THROW;
591
592     AppDomain * pAppDomain = vmAppDomain.GetDacPtr();
593     BOOL fDefaultDomain = pAppDomain->IsDefaultDomain();
594
595     return fDefaultDomain;
596 }
597
598
599 // Get the full AD friendly name for the given EE AppDomain.
600 void DacDbiInterfaceImpl::GetAppDomainFullName(
601     VMPTR_AppDomain   vmAppDomain, 
602     IStringHolder *   pStrName )
603 {
604     DD_ENTER_MAY_THROW;
605     AppDomain * pAppDomain = vmAppDomain.GetDacPtr();
606     
607     // Get the AppDomain name from the VM without changing anything
608     // We might be able to simplify this, eg. by returning an SString.
609     bool fIsUtf8;
610     PVOID pRawName = pAppDomain->GetFriendlyNameNoSet(&fIsUtf8);
611
612     if (!pRawName)
613     {
614         ThrowHR(E_NOINTERFACE);
615     }
616
617     HRESULT hrStatus = S_OK;
618     if (fIsUtf8)
619     {
620         // we have to allocate a temporary string
621         // we could avoid this by adding a version of IStringHolder::AssignCopy that takes a UTF8 string
622         // We should also probably check to see when fIsUtf8 is ever true (it looks like it should normally be false).
623         ULONG32 dwNameLen = 0;
624         hrStatus = ConvertUtf8((LPCUTF8)pRawName, 0, &dwNameLen, NULL);
625         if (SUCCEEDED( hrStatus ))
626         {
627             NewArrayHolder<WCHAR> pwszName(new WCHAR[dwNameLen]);
628             hrStatus = ConvertUtf8((LPCUTF8)pRawName, dwNameLen, &dwNameLen, pwszName );
629             IfFailThrow(hrStatus);
630             
631             hrStatus =  pStrName->AssignCopy(pwszName);
632         }
633     }
634     else
635     {
636         hrStatus =  pStrName->AssignCopy(static_cast<PCWSTR>(pRawName));
637     }
638     
639     // Very important that this either sets pStrName or Throws. 
640     // Don't set it and then then throw.
641     IfFailThrow(hrStatus);
642 }
643
644 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
645 // JIT Compiler Flags
646 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
647
648 // Get the values of the JIT Optimization and EnC flags.
649 void DacDbiInterfaceImpl::GetCompilerFlags (
650     VMPTR_DomainFile vmDomainFile,
651     BOOL *pfAllowJITOpts,
652     BOOL *pfEnableEnC)
653 {
654     DD_ENTER_MAY_THROW;
655
656     DomainFile * pDomainFile = vmDomainFile.GetDacPtr();
657
658     if (pDomainFile == NULL)
659     {
660         ThrowHR(E_FAIL);
661     }
662
663     // Get the underlying module - none of this is AppDomain specific
664     Module * pModule = pDomainFile->GetModule();
665     DWORD dwBits = pModule->GetDebuggerInfoBits();
666     *pfAllowJITOpts = !CORDisableJITOptimizations(dwBits);
667     *pfEnableEnC = pModule->IsEditAndContinueEnabled();
668
669
670 } //GetCompilerFlags
671
672 //-----------------------------------------------------------------------------
673 // Helper function for SetCompilerFlags to set EnC status.
674 // Arguments: 
675 //     Input:
676 //         pModule - The runtime module for which flags are being set.
677 //
678 // Return value: 
679 //   true if the Enc bits can be set on this module
680 //-----------------------------------------------------------------------------
681
682 bool DacDbiInterfaceImpl::CanSetEnCBits(Module * pModule)
683 {
684     _ASSERTE(pModule != NULL);
685 #ifdef EnC_SUPPORTED
686     // If we're using explicit sequence points (from the PDB), then we can't do EnC
687     // because EnC won't get updated pdbs and so the sequence points will be wrong.
688     bool fIgnorePdbs = ((pModule->GetDebuggerInfoBits() & DACF_IGNORE_PDBS) != 0);
689
690     bool fAllowEnc = pModule->IsEditAndContinueCapable() &&
691
692 #ifdef PROFILING_SUPPORTED_DATA
693         !CORProfilerPresent() && // this queries target
694 #endif
695         fIgnorePdbs;
696 #else   // ! EnC_SUPPORTED
697     // Enc not supported on any other platforms.
698     bool fAllowEnc = false;
699 #endif
700
701     return fAllowEnc;    
702 } // DacDbiInterfaceImpl::SetEnCBits
703
704 // Set the values of the JIT optimization and EnC flags. 
705 HRESULT DacDbiInterfaceImpl::SetCompilerFlags(VMPTR_DomainFile vmDomainFile,
706                                            BOOL             fAllowJitOpts,
707                                            BOOL             fEnableEnC)
708 {
709     DD_ENTER_MAY_THROW;
710
711     DWORD        dwBits      = 0;
712     DomainFile * pDomainFile = vmDomainFile.GetDacPtr();
713     Module *     pModule     = pDomainFile->GetCurrentModule();
714     HRESULT      hr          = S_OK;
715
716
717 #ifdef FEATURE_PREJIT
718     if (pModule->HasNativeImage())
719     {
720         ThrowHR(CORDBG_E_CANT_CHANGE_JIT_SETTING_FOR_ZAP_MODULE);
721     }
722 #endif
723     _ASSERTE(pModule != NULL);
724     
725     // Initialize dwBits.
726     dwBits = (pModule->GetDebuggerInfoBits() & ~(DACF_ALLOW_JIT_OPTS | DACF_ENC_ENABLED));
727     dwBits &= DACF_CONTROL_FLAGS_MASK;
728
729     if (fAllowJitOpts)
730     {
731         dwBits |= DACF_ALLOW_JIT_OPTS;
732     }
733     if (fEnableEnC)
734     {
735         if (CanSetEnCBits(pModule))
736         {
737             dwBits |= DACF_ENC_ENABLED;
738         }
739         else
740         {
741             hr = CORDBG_S_NOT_ALL_BITS_SET;
742         }
743     }
744     // Settings from the debugger take precedence over all other settings.
745     dwBits |= DACF_USER_OVERRIDE;
746
747     // set flags. This will write back to the target
748     pModule->SetDebuggerInfoBits((DebuggerAssemblyControlFlags)dwBits);
749     
750
751     LOG((LF_CORDB, LL_INFO100, "D::HIPCE, Changed Jit-Debug-Info: fOpt=%d, fEnableEnC=%d, new bits=0x%08x\n",
752            (dwBits & DACF_ALLOW_JIT_OPTS) != 0,
753            (dwBits & DACF_ENC_ENABLED) != 0,
754             dwBits));
755
756     _ASSERTE(SUCCEEDED(hr));
757     return hr;
758
759 } // DacDbiInterfaceImpl::SetCompilerFlags
760
761
762 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
763 // sequence points and var info
764 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
765
766 // Initialize the native/IL sequence points and native var info for a function.
767 void DacDbiInterfaceImpl::GetNativeCodeSequencePointsAndVarInfo(VMPTR_MethodDesc  vmMethodDesc,
768                                                                 CORDB_ADDRESS     startAddr,
769                                                                 BOOL              fCodeAvailable, 
770                                                                 NativeVarData *   pNativeVarData,
771                                                                 SequencePoints *  pSequencePoints)
772 {
773     DD_ENTER_MAY_THROW;
774
775     _ASSERTE(!vmMethodDesc.IsNull());
776
777     MethodDesc * pMD = vmMethodDesc.GetDacPtr();
778
779     _ASSERTE(fCodeAvailable != 0);
780
781     // get information about the locations of arguments and local variables
782     GetNativeVarData(pMD, startAddr, GetArgCount(pMD), pNativeVarData);
783
784     // get the sequence points
785     GetSequencePoints(pMD, startAddr, pSequencePoints);
786
787 } // GetNativeCodeSequencePointsAndVarInfo
788
789 //-----------------------------------------------------------------------------
790 // Get the number of fixed arguments to a function, i.e., the explicit args and the "this" pointer.
791 // This does not include other implicit arguments or varargs. This is used to compute a variable ID
792 // (see comment in CordbJITILFrame::ILVariableToNative for more detail)
793 // Arguments: 
794 //    input:  pMD    pointer to the method desc for the function
795 //    output: none
796 // Return value:
797 //    the number of fixed arguments to the function
798 //-----------------------------------------------------------------------------
799 SIZE_T DacDbiInterfaceImpl::GetArgCount(MethodDesc * pMD) 
800 {
801    
802     // Create a MetaSig for the given method's sig. (Easier than
803     // picking the sig apart ourselves.)
804     PCCOR_SIGNATURE pCallSig;
805     DWORD cbCallSigSize;
806
807     pMD->GetSig(&pCallSig, &cbCallSigSize);
808
809     if (pCallSig == NULL)
810     {
811         // Sig should only be null if the image is corrupted. (Even for lightweight-codegen)
812         // We expect the jit+verifier to catch this, so that we never land here.
813         // But just in case ...
814         CONSISTENCY_CHECK_MSGF(false, ("Corrupted image, null sig.(%s::%s)", 
815                                pMD->m_pszDebugClassName, pMD->m_pszDebugMethodName));
816         return 0;
817     }
818
819     MetaSig msig(pCallSig, cbCallSigSize, pMD->GetModule(), NULL, MetaSig::sigMember);
820
821     // Get the arg count.
822     UINT32 NumArguments = msig.NumFixedArgs();
823
824     // Account for the 'this' argument.
825     if (!pMD->IsStatic())
826     {
827         NumArguments++;
828     }
829 /*
830     SigParser sigParser(pCallSig, cbCallSigSize);
831     sigParser.SkipMethodHeaderSignature(&m_allArgsCount);
832 */
833     return NumArguments;
834 } //GetArgCount
835
836 // Allocator to pass to DebugInfoStores, allocating forDBI
837 BYTE* InfoStoreForDbiNew(void * pData, size_t cBytes)
838 {
839     return new(forDbi) BYTE[cBytes];
840 }
841
842 // Allocator to pass to the debug-info-stores...
843 BYTE* InfoStoreNew(void * pData, size_t cBytes)
844 {
845     return new BYTE[cBytes];
846 }
847
848 //-----------------------------------------------------------------------------
849 // Get locations and code offsets for local variables and arguments in a function
850 // This information is used to find the location of a value at a given IP.
851 // Arguments:
852 //    input: 
853 //        pMethodDesc   pointer to the method desc for the function
854 //        startAddr     starting address of the function--used to differentiate
855 //                      EnC versions
856 //        fixedArgCount number of fixed arguments to the function
857 //    output: 
858 //        pVarInfo      data structure containing a list of variable and
859 //                      argument locations by range of IP offsets
860 // Note: this function may throw
861 //-----------------------------------------------------------------------------
862 void DacDbiInterfaceImpl::GetNativeVarData(MethodDesc *    pMethodDesc,
863                                            CORDB_ADDRESS   startAddr,
864                                            SIZE_T          fixedArgCount,
865                                            NativeVarData * pVarInfo)
866 {
867     // make sure we haven't done this already 
868     if (pVarInfo->IsInitialized())
869     {
870         return;
871     }
872
873     NewHolder<ICorDebugInfo::NativeVarInfo> nativeVars(NULL);
874
875     DebugInfoRequest request;
876     request.InitFromStartingAddr(pMethodDesc, CORDB_ADDRESS_TO_TADDR(startAddr));
877
878     ULONG32 entryCount;
879
880     BOOL success = DebugInfoManager::GetBoundariesAndVars(request,
881                                                 InfoStoreNew, NULL, // allocator
882                                                 NULL, NULL,
883                                                 &entryCount, &nativeVars);
884
885     if (!success)
886         ThrowHR(E_FAIL);
887
888     // set key fields of pVarInfo
889     pVarInfo->InitVarDataList(nativeVars, (int)fixedArgCount, (int)entryCount);
890 } // GetNativeVarData
891
892
893 //-----------------------------------------------------------------------------
894 // Given a instrumented IL map from the profiler that maps:
895 //   Original offset IL_A -> Instrumentend offset IL_B
896 // And a native mapping from the JIT that maps:
897 //   Instrumented offset IL_B -> native offset Native_C
898 // This function merges the two maps and stores the result back into the nativeMap.
899 // The nativeMap now maps:
900 //   Original offset IL_A -> native offset Native_C
901 // pEntryCount is the number of valid entries in nativeMap, and it may be adjusted downwards
902 // as part of the composition.
903 //-----------------------------------------------------------------------------
904 void DacDbiInterfaceImpl::ComposeMapping(InstrumentedILOffsetMapping profilerILMap, ICorDebugInfo::OffsetMapping nativeMap[], ULONG32* pEntryCount)
905 {
906     // Translate the IL offset if the profiler has provided us with a mapping.
907     // The ICD public API should always expose the original IL offsets, but GetBoundaries() 
908     // directly accesses the debug info, which stores the instrumented IL offsets.
909
910     ULONG32 entryCount = *pEntryCount;
911     if (!profilerILMap.IsNull())
912     {
913         // If we did instrument, then we can't have any sequence points that
914         // are "in-between" the old-->new map that the profiler gave us.
915         // Ex, if map is:
916         // (6 old -> 36 new)
917         // (8 old -> 50 new)
918         // And the jit gives us an entry for 44 new, that will map back to 6 old.
919         // Since the map can only have one entry for 6 old, we remove 44 new.
920
921         // First Pass: invalidate all the duplicate entries by setting their IL offset to MAX_ILNUM
922         ULONG32 cDuplicate = 0;
923         ULONG32 prevILOffset = (ULONG32)(ICorDebugInfo::MAX_ILNUM);
924         for (ULONG32 i = 0; i < entryCount; i++)
925         {
926             ULONG32 origILOffset = TranslateInstrumentedILOffsetToOriginal(nativeMap[i].ilOffset, &profilerILMap);
927
928             if (origILOffset == prevILOffset)
929             {
930                 // mark this sequence point as invalid; refer to the comment above
931                 nativeMap[i].ilOffset = (ULONG32)(ICorDebugInfo::MAX_ILNUM);
932                 cDuplicate += 1;
933             }
934             else
935             {
936                 // overwrite the instrumented IL offset with the original IL offset
937                 nativeMap[i].ilOffset = origILOffset;
938                 prevILOffset = origILOffset;
939             }
940         }
941
942         // Second Pass: move all the valid entries up front
943         ULONG32 realIndex = 0;
944         for (ULONG32 curIndex = 0; curIndex < entryCount; curIndex++)
945         {
946             if (nativeMap[curIndex].ilOffset != (ULONG32)(ICorDebugInfo::MAX_ILNUM))
947             {
948                 // This is a valid entry.  Move it up front.
949                 nativeMap[realIndex] = nativeMap[curIndex];
950                 realIndex += 1;
951             }
952         }
953
954         // make sure we have done the bookkeeping correctly
955         _ASSERTE((realIndex + cDuplicate) == entryCount);
956
957         // Final Pass: derecement entryCount
958         entryCount -= cDuplicate;
959         *pEntryCount = entryCount;
960     }
961 }
962
963
964 //-----------------------------------------------------------------------------
965 // Get the native/IL sequence points for a function
966 // Arguments:
967 //    input: 
968 //        pMethodDesc   pointer to the method desc for the function
969 //        startAddr     starting address of the function--used to differentiate
970 //    output: 
971 //        pNativeMap    data structure containing a list of sequence points
972 // Note: this function may throw
973 //-----------------------------------------------------------------------------
974 void DacDbiInterfaceImpl::GetSequencePoints(MethodDesc *     pMethodDesc,
975                                             CORDB_ADDRESS    startAddr,
976                                             SequencePoints * pSeqPoints)
977 {
978
979     // make sure we haven't done this already 
980     if (pSeqPoints->IsInitialized())
981     {
982         return;
983     }
984
985     // Use the DebugInfoStore to get IL->Native maps.
986     // It doesn't matter whether we're jitted, ngenned etc.
987     DebugInfoRequest request;
988     request.InitFromStartingAddr(pMethodDesc, CORDB_ADDRESS_TO_TADDR(startAddr));
989
990
991     // Bounds info.
992     NewArrayHolder<ICorDebugInfo::OffsetMapping> mapCopy(NULL);
993
994     ULONG32 entryCount;
995     BOOL success = DebugInfoManager::GetBoundariesAndVars(request,
996                                                       InfoStoreNew, NULL, // allocator
997                                                       &entryCount, &mapCopy,
998                                                       NULL, NULL);
999     if (!success)
1000         ThrowHR(E_FAIL);
1001
1002     // if there is a rejit IL map for this function, apply that in preference to load-time mapping
1003 #ifdef FEATURE_REJIT
1004     ReJitManager * pReJitMgr = pMethodDesc->GetReJitManager();
1005     ReJitInfo* pReJitInfo = pReJitMgr->FindReJitInfo(dac_cast<PTR_MethodDesc>(pMethodDesc), (PCODE)startAddr, 0);
1006     if (pReJitInfo != NULL)
1007     {
1008         InstrumentedILOffsetMapping rejitMapping = pReJitInfo->m_pShared->m_instrumentedILMap;
1009         ComposeMapping(rejitMapping, mapCopy, &entryCount);
1010     }
1011     else
1012     {
1013 #endif
1014         // if there is a profiler load-time mapping and not a rejit mapping, apply that instead
1015         InstrumentedILOffsetMapping loadTimeMapping =
1016             pMethodDesc->GetModule()->GetInstrumentedILOffsetMapping(pMethodDesc->GetMemberDef());
1017         ComposeMapping(loadTimeMapping, mapCopy, &entryCount);
1018 #ifdef FEATURE_REJIT
1019     }
1020 #endif
1021
1022     pSeqPoints->InitSequencePoints(entryCount);
1023
1024     // mapCopy and pSeqPoints have elements of different types. Thus, we
1025     // need to copy the individual members from the elements of mapCopy to the
1026     // elements of pSeqPoints. Once we're done, we can release mapCopy
1027     pSeqPoints->CopyAndSortSequencePoints(mapCopy);
1028
1029 } // GetSequencePoints
1030
1031 // ----------------------------------------------------------------------------
1032 // DacDbiInterfaceImpl::TranslateInstrumentedILOffsetToOriginal
1033 //
1034 // Description: 
1035 //    Helper function to convert an instrumented IL offset to the corresponding original IL offset.
1036 //
1037 // Arguments:
1038 //    * ilOffset - offset to be translated
1039 //    * pMapping - the profiler-provided mapping between original IL offsets and instrumented IL offsets
1040 //
1041 // Return Value:
1042 //    Return the translated offset.
1043 //
1044
1045 ULONG DacDbiInterfaceImpl::TranslateInstrumentedILOffsetToOriginal(ULONG                               ilOffset, 
1046                                                                    const InstrumentedILOffsetMapping * pMapping)
1047 {
1048     SIZE_T               cMap  = pMapping->GetCount();
1049     ARRAY_PTR_COR_IL_MAP rgMap = pMapping->GetOffsets();
1050
1051     _ASSERTE((cMap == 0) == (rgMap == NULL));
1052
1053     // Early out if there is no mapping, or if we are dealing with a special IL offset such as 
1054     // prolog, epilog, etc.
1055     if ((cMap == 0) || ((int)ilOffset < 0))
1056     {
1057         return ilOffset;
1058     }
1059
1060     SIZE_T i = 0;
1061     for (i = 1; i < cMap; i++)
1062     {
1063         if (ilOffset < rgMap[i].newOffset)
1064         {
1065             return rgMap[i - 1].oldOffset;
1066         }
1067     }
1068     return rgMap[i - 1].oldOffset;
1069 }
1070
1071 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
1072 // Function Data
1073 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
1074
1075
1076 // GetILCodeAndSig returns the function's ILCode and SigToken given
1077 // a module and a token. The info will come from a MethodDesc, if
1078 // one exists or from metadata.
1079 //
1080 void DacDbiInterfaceImpl::GetILCodeAndSig(VMPTR_DomainFile vmDomainFile, 
1081                                           mdToken          functionToken,
1082                                           TargetBuffer *   pCodeInfo, 
1083                                           mdToken *        pLocalSigToken)
1084 {
1085     DD_ENTER_MAY_THROW;
1086
1087     DomainFile * pDomainFile = vmDomainFile.GetDacPtr();
1088     Module *     pModule     = pDomainFile->GetCurrentModule();
1089     RVA          methodRVA   = 0;
1090     DWORD        implFlags;
1091     
1092     // preinitialize out params
1093     pCodeInfo->Clear();
1094     *pLocalSigToken = mdSignatureNil;
1095
1096     // Get the RVA and impl flags for this method.
1097     IfFailThrow(pModule->GetMDImport()->GetMethodImplProps(functionToken,
1098                                                            &methodRVA,
1099                                                            &implFlags));
1100
1101     MethodDesc* pMethodDesc =
1102         FindLoadedMethodRefOrDef(pModule, functionToken);
1103
1104     // If the RVA is 0 or it's native, then the method is not IL
1105     if (methodRVA == 0)
1106     {
1107         LOG((LF_CORDB,LL_INFO100000, "DDI::GICAS: Function is not IL - methodRVA == NULL!\n"));
1108         // return (CORDBG_E_FUNCTION_NOT_IL);
1109         // Sanity check this....
1110
1111         if(!pMethodDesc || !pMethodDesc->IsIL())
1112         {
1113             LOG((LF_CORDB,LL_INFO100000, "DDI::GICAS: And the MD agrees..\n"));
1114             ThrowHR(CORDBG_E_FUNCTION_NOT_IL);
1115         }
1116         else
1117         {
1118             LOG((LF_CORDB,LL_INFO100000, "DDI::GICAS: But the MD says it's IL..\n"));
1119         }
1120
1121         if (pMethodDesc != NULL && pMethodDesc->GetRVA() == 0)
1122         {
1123             LOG((LF_CORDB,LL_INFO100000, "DDI::GICAS: Actually, MD says RVA is 0 too - keep going...!\n"));
1124         }
1125     }
1126     if (IsMiNative(implFlags))
1127     {
1128         LOG((LF_CORDB,LL_INFO100000, "DDI::GICAS: Function is not IL - IsMiNative!\n"));
1129         ThrowHR(CORDBG_E_FUNCTION_NOT_IL);
1130     }
1131
1132     *pLocalSigToken = GetILCodeAndSigHelper(pModule, pMethodDesc, functionToken, methodRVA, pCodeInfo);
1133
1134 #ifdef LOGGING
1135     else
1136     {
1137         LOG((LF_CORDB,LL_INFO100000, "DDI::GICAS: GetMethodImplProps failed!\n"));
1138     }
1139 #endif
1140 } // GetILCodeAndSig
1141
1142 //---------------------------------------------------------------------------------------
1143 //
1144 // This is just a worker function for GetILCodeAndSig.  It returns the function's ILCode and SigToken 
1145 // given a module, a token, and the RVA.  If a MethodDesc is provided, it has to be consistent with 
1146 // the token and the RVA.
1147 //
1148 // Arguments:
1149 //    pModule       - the Module containing the specified method
1150 //    pMD           - the specified method; can be NULL
1151 //    mdMethodToken - the MethodDef token of the specified method
1152 //    methodRVA     - the RVA of the IL for the specified method
1153 //    pIL           - out parameter; return the target address and size of the IL of the specified method
1154 //
1155 // Return Value:
1156 //    Return the local variable signature token of the specified method.  Can be mdSignatureNil.
1157 //
1158
1159 mdSignature DacDbiInterfaceImpl::GetILCodeAndSigHelper(Module *       pModule,
1160                                                        MethodDesc *   pMD,
1161                                                        mdMethodDef    mdMethodToken,
1162                                                        RVA            methodRVA,
1163                                                        TargetBuffer * pIL)
1164 {
1165     _ASSERTE(pModule != NULL);
1166
1167     // If a MethodDesc is provided, it has to be consistent with the MethodDef token and the RVA.
1168     _ASSERTE((pMD == NULL) || ((pMD->GetMemberDef() == mdMethodToken) && (pMD->GetRVA() == methodRVA)));
1169
1170     TADDR pTargetIL; // target address of start of IL blob
1171
1172     // This works for methods in dynamic modules, and methods overriden by a profiler.
1173     pTargetIL = pModule->GetDynamicIL(mdMethodToken, TRUE);
1174
1175     // Method not overriden - get the original copy of the IL by going to the PE file/RVA
1176     // If this is in a dynamic module then don't even attempt this since ReflectionModule::GetIL isn't
1177     // implemend for DAC.
1178     if (pTargetIL == 0 && !pModule->IsReflection())
1179     {
1180         pTargetIL = (TADDR)pModule->GetIL(methodRVA);
1181     }
1182
1183     mdSignature mdSig = mdSignatureNil;
1184     if (pTargetIL == 0)
1185     {
1186         // Currently this should only happen for LCG methods (including IL stubs).
1187         // LCG methods have a 0 RVA, and so we don't currently have any way to get the IL here.
1188         _ASSERTE(pMD->IsDynamicMethod());
1189         _ASSERTE(pMD->AsDynamicMethodDesc()->IsLCGMethod()||
1190                  pMD->AsDynamicMethodDesc()->IsILStub());
1191
1192         // Clear the buffer.
1193         pIL->Clear();
1194     }
1195     else
1196     {
1197         // Now we have the target address of the IL blob, we need to bring it over to the host. 
1198         // DacGetILMethod will copy the COR_ILMETHOD information that we need
1199         COR_ILMETHOD * pHostIL = DacGetIlMethod(pTargetIL);     // host address of start of IL blob
1200         COR_ILMETHOD_DECODER header(pHostIL);                   // host address of header
1201
1202
1203         // Get the IL code info. We need the address of the IL itself, which will be beyond the header
1204         // at the beginning of the blob. We ultimately need the target address. To get this, we take 
1205         // target address of the target IL blob and add the offset from the beginning of the host IL blob 
1206         // (the header) to the beginning of the IL itself (we get this information from the header).
1207         pIL->pAddress = pTargetIL + ((SIZE_T)(header.Code) - (SIZE_T)pHostIL);
1208         pIL->cbSize = header.GetCodeSize();
1209
1210         // Now we get the signature token
1211         if (header.LocalVarSigTok != NULL)
1212         {
1213             mdSig = header.GetLocalVarSigTok();
1214         }
1215         else
1216         {
1217             mdSig = mdSignatureNil;
1218         }
1219     }
1220
1221     return mdSig;
1222 }
1223
1224
1225 bool DacDbiInterfaceImpl::GetMetaDataFileInfoFromPEFile(VMPTR_PEFile vmPEFile,
1226                                                         DWORD &dwTimeStamp,
1227                                                         DWORD &dwSize,
1228                                                         bool  &isNGEN,
1229                                                         IStringHolder* pStrFilename)
1230 {
1231 #if !defined(FEATURE_PREJIT)
1232
1233     return false;
1234
1235 #else // defined(FEATURE_PREJIT)
1236
1237     DD_ENTER_MAY_THROW;
1238
1239     DWORD dwDataSize;
1240     DWORD dwRvaHint;
1241     PEFile * pPEFile = vmPEFile.GetDacPtr();
1242     _ASSERTE(pPEFile != NULL);
1243     if (pPEFile == NULL)
1244         return false;
1245
1246     WCHAR wszFilePath[MAX_LONGPATH] = {0};
1247     DWORD cchFilePath = MAX_LONGPATH;
1248     bool ret = ClrDataAccess::GetMetaDataFileInfoFromPEFile(pPEFile,
1249                                                             dwTimeStamp,
1250                                                             dwSize,
1251                                                             dwDataSize,
1252                                                             dwRvaHint,
1253                                                             isNGEN,
1254                                                             wszFilePath,
1255                                                             cchFilePath);
1256
1257     pStrFilename->AssignCopy(wszFilePath);
1258     return ret;
1259 #endif // !defined(FEATURE_PREJIT)
1260 }
1261
1262
1263 bool DacDbiInterfaceImpl::GetILImageInfoFromNgenPEFile(VMPTR_PEFile vmPEFile,
1264                                                        DWORD &dwTimeStamp,
1265                                                        DWORD &dwSize,
1266                                                        IStringHolder* pStrFilename)
1267 {
1268 #if !defined(FEATURE_PREJIT)
1269
1270     return false;
1271
1272 #else // defined(FEATURE_PREJIT)
1273
1274     DD_ENTER_MAY_THROW;
1275
1276     PEFile * pPEFile = vmPEFile.GetDacPtr();
1277     _ASSERTE(pPEFile != NULL);
1278     if (pPEFile == NULL)
1279     {
1280         return false;
1281     }
1282
1283     WCHAR wszFilePath[MAX_LONGPATH] = {0};
1284     DWORD cchFilePath = MAX_LONGPATH;
1285     bool ret = ClrDataAccess::GetILImageInfoFromNgenPEFile(pPEFile,
1286                                                            dwTimeStamp,
1287                                                            dwSize,
1288                                                            wszFilePath,
1289                                                            cchFilePath);
1290
1291     pStrFilename->AssignCopy(wszFilePath);
1292     return ret;
1293 #endif // !defined(FEATURE_PREJIT)
1294 }
1295
1296 // Get start addresses and sizes for hot and cold regions for a native code blob.
1297 // Arguments:
1298 //    Input: 
1299 //        pMethodDesc - method desc for the function we are inspecting
1300 //    Output (required):
1301 //        pCodeInfo   - initializes the m_rgCodeRegions field of this structure
1302 //                      if the native code is available. Otherwise, 
1303 //                      pCodeInfo->IsValid() is false.
1304
1305 void DacDbiInterfaceImpl::GetMethodRegionInfo(MethodDesc *             pMethodDesc,
1306                                               NativeCodeFunctionData * pCodeInfo)
1307 {
1308     CONTRACTL
1309     {
1310         SO_INTOLERANT;
1311         GC_NOTRIGGER;
1312         PRECONDITION(CheckPointer(pCodeInfo));
1313     }
1314     CONTRACTL_END;
1315
1316     IJitManager::MethodRegionInfo methodRegionInfo = {NULL, 0, NULL, 0};
1317     PCODE functionAddress = pMethodDesc->GetNativeCode();
1318
1319     // get the start address of the hot region and initialize the jit manager
1320     pCodeInfo->m_rgCodeRegions[kHot].pAddress = CORDB_ADDRESS(PCODEToPINSTR(functionAddress));
1321
1322     // if the start address is NULL, the code isn't available yet, so just return
1323     if (functionAddress != NULL)
1324     {
1325         EECodeInfo codeInfo(functionAddress);
1326         _ASSERTE(codeInfo.IsValid());
1327
1328         codeInfo.GetMethodRegionInfo(&methodRegionInfo);
1329
1330         // now get the rest of the region information
1331         pCodeInfo->m_rgCodeRegions[kHot].cbSize = (ULONG)methodRegionInfo.hotSize;
1332         pCodeInfo->m_rgCodeRegions[kCold].Init(PCODEToPINSTR(methodRegionInfo.coldStartAddress), 
1333                                                (ULONG)methodRegionInfo.coldSize);
1334         _ASSERTE(pCodeInfo->IsValid());
1335     }
1336     else
1337     {
1338         _ASSERTE(!pCodeInfo->IsValid());
1339     }
1340 } // GetMethodRegionInfo
1341
1342
1343 // Gets the following information about a native code blob: 
1344 //    - its method desc
1345 //    - whether it's an instantiated generic
1346 //    - its EnC version number 
1347 //    - hot and cold region information.
1348 // If the hot region start address is NULL at the end, it means the native code 
1349 // isn't currently available. In this case, all values in pCodeInfo will be
1350 // cleared. 
1351
1352 void DacDbiInterfaceImpl::GetNativeCodeInfo(VMPTR_DomainFile         vmDomainFile, 
1353                                             mdToken                  functionToken,
1354                                             NativeCodeFunctionData * pCodeInfo)
1355 {
1356     DD_ENTER_MAY_THROW;
1357     
1358     _ASSERTE(pCodeInfo != NULL); 
1359
1360     // pre-initialize:
1361     pCodeInfo->Clear();
1362
1363     DomainFile * pDomainFile = vmDomainFile.GetDacPtr();
1364     Module *     pModule     = pDomainFile->GetCurrentModule();
1365     
1366     MethodDesc* pMethodDesc = FindLoadedMethodRefOrDef(pModule, functionToken);
1367     pCodeInfo->vmNativeCodeMethodDescToken.SetHostPtr(pMethodDesc);
1368    
1369     // if we are loading a module and trying to bind a previously set breakpoint, we may not have 
1370     // a method desc yet, so check for that situation
1371     if(pMethodDesc != NULL) 
1372     {
1373         GetMethodRegionInfo(pMethodDesc, pCodeInfo);
1374         if (pCodeInfo->m_rgCodeRegions[kHot].pAddress != NULL)
1375         {
1376             pCodeInfo->isInstantiatedGeneric = pMethodDesc->HasClassOrMethodInstantiation();
1377             LookupEnCVersions(pModule, 
1378                               pCodeInfo->vmNativeCodeMethodDescToken, 
1379                               functionToken, 
1380                               pCodeInfo->m_rgCodeRegions[kHot].pAddress, 
1381                               &(pCodeInfo->encVersion));
1382         }
1383     }
1384 } // GetNativeCodeInfo
1385
1386 // Gets the following information about a native code blob: 
1387 //    - its method desc
1388 //    - whether it's an instantiated generic
1389 //    - its EnC version number 
1390 //    - hot and cold region information.
1391 void DacDbiInterfaceImpl::GetNativeCodeInfoForAddr(VMPTR_MethodDesc         vmMethodDesc,
1392                                                    CORDB_ADDRESS            hotCodeStartAddr,
1393                                                    NativeCodeFunctionData * pCodeInfo)
1394 {
1395     DD_ENTER_MAY_THROW;
1396     
1397     _ASSERTE(pCodeInfo != NULL); 
1398
1399     if (hotCodeStartAddr == NULL)
1400     {
1401         // if the start address is NULL, the code isn't available yet, so just return
1402         _ASSERTE(!pCodeInfo->IsValid());
1403         return;
1404     }
1405     
1406     IJitManager::MethodRegionInfo methodRegionInfo = {NULL, 0, NULL, 0};
1407     TADDR codeAddr = CORDB_ADDRESS_TO_TADDR(hotCodeStartAddr);
1408     
1409 #ifdef _TARGET_ARM_
1410     // TADDR should not have the thumb code bit set.
1411     _ASSERTE((codeAddr & THUMB_CODE) == 0);
1412     codeAddr &= ~THUMB_CODE;
1413 #endif
1414
1415     EECodeInfo codeInfo(codeAddr);
1416     _ASSERTE(codeInfo.IsValid());
1417
1418     // We may not have the memory for the cold code region in a minidump.
1419     // Do not fail stackwalking because of this.
1420     EX_TRY_ALLOW_DATATARGET_MISSING_MEMORY
1421     {
1422         codeInfo.GetMethodRegionInfo(&methodRegionInfo);
1423     }
1424     EX_END_CATCH_ALLOW_DATATARGET_MISSING_MEMORY;
1425
1426     // Even if GetMethodRegionInfo() fails to retrieve the cold code region info,
1427     // we should still be able to get the hot code region info.  We are counting on this for
1428     // stackwalking to work in dump debugging scenarios.
1429     _ASSERTE(methodRegionInfo.hotStartAddress == codeAddr);
1430
1431     // now get the rest of the region information
1432     pCodeInfo->m_rgCodeRegions[kHot].Init(PCODEToPINSTR(methodRegionInfo.hotStartAddress),
1433                                           (ULONG)methodRegionInfo.hotSize);
1434     pCodeInfo->m_rgCodeRegions[kCold].Init(PCODEToPINSTR(methodRegionInfo.coldStartAddress), 
1435                                                (ULONG)methodRegionInfo.coldSize);
1436     _ASSERTE(pCodeInfo->IsValid());
1437
1438     MethodDesc* pMethodDesc = vmMethodDesc.GetDacPtr();
1439     pCodeInfo->isInstantiatedGeneric = pMethodDesc->HasClassOrMethodInstantiation();
1440     pCodeInfo->vmNativeCodeMethodDescToken = vmMethodDesc;
1441
1442     SIZE_T unusedLatestEncVersion;
1443     Module * pModule = pMethodDesc->GetModule();
1444     _ASSERTE(pModule != NULL);
1445     LookupEnCVersions(pModule,
1446                       vmMethodDesc, 
1447                       pMethodDesc->GetMemberDef(), 
1448                       codeAddr, 
1449                       &unusedLatestEncVersion, //unused by caller
1450                       &(pCodeInfo->encVersion));
1451
1452 } // GetNativeCodeInfo
1453
1454
1455 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
1456 //
1457 // Functions to get Type and Class information
1458 // 
1459 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
1460 //-----------------------------------------------------------------------------
1461 //DacDbiInterfaceImpl::GetTypeHandles
1462 // Get the approximate and exact type handles for a type
1463 // Arguments:
1464 //     input: 
1465 //         vmThExact            - VMPTR of the exact type handle. If this method is called
1466 //                                to get information for a new generic instantiation, this will already
1467 //                                be initialized. If it's called to get type information for an arbitrary
1468 //                                 type (i.e., called to initialize an instance of CordbClass), it will be NULL
1469 //         vmThApprox           - VMPTR of the approximate type handle. If this method is called
1470 //                                to get information for a new generic instantiation, this will already
1471 //                                be initialized. If it's called to get type information for an arbitrary
1472 //                                type (i.e., called to initialize an instance of CordbClass), it will be NULL
1473 //     output:
1474 //         pThExact             - handle for exact type information for a generic instantiation 
1475 //         pThApprox            - handle for type information 
1476 // Notes: 
1477 //    pThExact and pTHApprox must be pointers to existing memory.  
1478 //-----------------------------------------------------------------------------
1479 void DacDbiInterfaceImpl::GetTypeHandles(VMPTR_TypeHandle  vmThExact,
1480                                          VMPTR_TypeHandle  vmThApprox,
1481                                          TypeHandle *      pThExact,
1482                                          TypeHandle *      pThApprox)
1483  {
1484      _ASSERTE((pThExact != NULL) && (pThApprox != NULL));
1485
1486      *pThExact = TypeHandle::FromPtr(vmThExact.GetDacPtr()); 
1487      *pThApprox = TypeHandle::FromPtr(vmThApprox.GetDacPtr());
1488
1489     // If we can't find the class, return the proper HR to the right side. Note: if the class is not a value class and
1490     // the class is also not restored, then we must pretend that the class is still not loaded. We are gonna let
1491     // unrestored value classes slide, though, and special case access to the class's parent below.
1492     if ((pThApprox->IsNull()) || ((!pThApprox->IsValueType()) && (!pThApprox->IsRestored())))
1493     {
1494         LOG((LF_CORDB, LL_INFO10000, "D::GASCI: class isn't loaded.\n"));
1495         ThrowHR(CORDBG_E_CLASS_NOT_LOADED);
1496     }
1497     // If the exact type handle is not restored ignore it.
1498     if (!pThExact->IsNull() && !pThExact->IsRestored())
1499     {
1500         *pThExact = TypeHandle();
1501     }
1502  }  // DacDbiInterfaceImpl::GetTypeHandles
1503     
1504 //-----------------------------------------------------------------------------
1505 // DacDbiInterfaceImpl::GetTotalFieldCount
1506 // Gets the total number of fields for a type. 
1507 // Input Argument: thApprox - type handle used to determine the number of fields
1508 // Return Value:   count of the total fields of the type.
1509 //-----------------------------------------------------------------------------
1510 unsigned int DacDbiInterfaceImpl::GetTotalFieldCount(TypeHandle thApprox)
1511 {
1512     MethodTable *pMT = thApprox.GetMethodTable();
1513
1514     // Count the instance and static fields for this class (not including parent).
1515     // This will not include any newly added EnC fields.
1516     unsigned int IFCount = pMT->GetNumIntroducedInstanceFields();
1517     unsigned int SFCount = pMT->GetNumStaticFields();
1518
1519 #ifdef EnC_SUPPORTED
1520     PTR_Module pModule = pMT->GetModule();
1521
1522     // Stats above don't include EnC fields. So add them now.
1523     if (pModule->IsEditAndContinueEnabled())
1524     {
1525         PTR_EnCEEClassData pEncData = 
1526             (dac_cast<PTR_EditAndContinueModule>(pModule))->GetEnCEEClassData(pMT, TRUE);
1527
1528         if (pEncData != NULL)
1529         {
1530             _ASSERTE(pEncData->GetMethodTable() == pMT);
1531
1532             // EnC only adds fields, never removes them.
1533             IFCount += pEncData->GetAddedInstanceFields();
1534             SFCount += pEncData->GetAddedStaticFields();
1535         }
1536     }
1537 #endif
1538     return IFCount + SFCount; 
1539 } // DacDbiInterfaceImpl::GetTotalFieldCount
1540
1541 //-----------------------------------------------------------------------------
1542 // DacDbiInterfaceImpl::InitClassData
1543 // initializes various values of the ClassInfo data structure, including the
1544 // field count, generic args count, size and value class flag
1545 // Arguments:
1546 //     input:  thApprox            - used to get access to all the necessary values 
1547 //             fIsInstantiatedType - used to determine how to compute the size
1548 //     output: pData               - contains fields to be initialized  
1549 //-----------------------------------------------------------------------------
1550 void DacDbiInterfaceImpl::InitClassData(TypeHandle  thApprox, 
1551                                         BOOL        fIsInstantiatedType, 
1552                                         ClassInfo * pData)
1553 {
1554     pData->m_fieldList.Alloc(GetTotalFieldCount(thApprox));
1555
1556     // For Generic classes you must get the object size via the type handle, which
1557     // will get you to the right information for the particular instantiation
1558     // you're working with...
1559     pData->m_objectSize = 0;
1560     if ((!thApprox.GetNumGenericArgs()) || fIsInstantiatedType)
1561     {
1562         pData->m_objectSize = thApprox.GetMethodTable()->GetNumInstanceFieldBytes();
1563     }
1564
1565 } // DacDbiInterfaceImpl::InitClassData
1566
1567 //-----------------------------------------------------------------------------
1568 // DacDbiInterfaceImpl::GetStaticsBases
1569 // Gets the base table addresses for both GC and non-GC statics
1570 // Arguments:
1571 //     input:  thExact            - exact type handle for the class
1572 //             pAppDomain         - AppDomain in which the class is loaded
1573 //     output: ppGCStaticsBase    - base pointer for GC statics
1574 //             ppNonGCStaticsBase - base pointer for non GC statics
1575 // Notes:
1576 // If this is a non-generic type, or an instantiated type, then we'll be able to get the static var bases
1577 // If the typeHandle represents a generic type constructor (i.e. an uninstantiated generic class), then
1578 // the static bases will be null (since statics are per-instantiation).
1579 //-----------------------------------------------------------------------------
1580 void DacDbiInterfaceImpl::GetStaticsBases(TypeHandle thExact, 
1581                                          AppDomain * pAppDomain,
1582                                          PTR_BYTE *  ppGCStaticsBase,
1583                                          PTR_BYTE *  ppNonGCStaticsBase)
1584  {
1585     MethodTable * pMT = thExact.GetMethodTable();
1586     Module * pModuleForStatics = pMT->GetModuleForStatics();
1587     if (pModuleForStatics != NULL)
1588     {
1589         PTR_DomainLocalModule pLocalModule = pModuleForStatics->GetDomainLocalModule(pAppDomain);
1590         if (pLocalModule != NULL)
1591         {
1592             *ppGCStaticsBase = pLocalModule->GetGCStaticsBasePointer(pMT);
1593             *ppNonGCStaticsBase = pLocalModule->GetNonGCStaticsBasePointer(pMT);
1594         }
1595     }
1596 } // DacDbiInterfaceImpl::GetStaticsBases
1597
1598 //-----------------------------------------------------------------------------
1599 // DacDbiInterfaceImpl::ComputeFieldData
1600 // Computes the field info for pFD and stores it in pcurrentFieldData
1601 // Arguments:
1602 //     input:  pFD               - FieldDesc used to get necessary information
1603 //             pGCStaticsBase    - base table address for GC statics
1604 //             pNonGCStaticsBase - base table address for non-GC statics
1605 //     output: pCurrentFieldData - contains fields to be initialized 
1606 //-----------------------------------------------------------------------------
1607 void DacDbiInterfaceImpl::ComputeFieldData(PTR_FieldDesc pFD,
1608                                            PTR_BYTE    pGCStaticsBase,
1609                                            PTR_BYTE    pNonGCStaticsBase,
1610                                            FieldData * pCurrentFieldData)
1611 {
1612     pCurrentFieldData->Initialize(pFD->IsStatic(), pFD->IsPrimitive(), pFD->GetMemberDef());
1613
1614 #ifdef EnC_SUPPORTED
1615     // If the field was newly introduced via EnC, and hasn't yet
1616     // been fixed up, then we'll send back a marker indicating
1617     // that it isn't yet available.
1618     if (pFD->IsEnCNew())
1619     {
1620         // @dbgtodo Microsoft inspection: eliminate the debugger token when ICDClass and ICDType are 
1621         // completely DACized
1622         pCurrentFieldData->m_vmFieldDesc.SetHostPtr(pFD);
1623         pCurrentFieldData->m_fFldStorageAvailable = FALSE;
1624         pCurrentFieldData->m_fFldIsTLS = FALSE;
1625         pCurrentFieldData->m_fFldIsContextStatic = FALSE;
1626         pCurrentFieldData->m_fFldIsRVA = FALSE;
1627         pCurrentFieldData->m_fFldIsCollectibleStatic = FALSE;
1628     }
1629     else
1630 #endif // EnC_SUPPORTED
1631     {
1632         // Otherwise, we'll compute the info & send it back.
1633         pCurrentFieldData->m_fFldStorageAvailable = TRUE;
1634         // @dbgtodo Microsoft inspection: eliminate the debugger token when ICDClass and ICDType are 
1635         // completely DACized
1636         pCurrentFieldData->m_vmFieldDesc.SetHostPtr(pFD);
1637         pCurrentFieldData->m_fFldIsTLS = (pFD->IsThreadStatic() == TRUE);
1638         pCurrentFieldData->m_fFldIsContextStatic = (pFD->IsContextStatic() == TRUE);
1639         pCurrentFieldData->m_fFldIsRVA = (pFD->IsRVA() == TRUE);
1640         pCurrentFieldData->m_fFldIsCollectibleStatic = (pFD->IsStatic() == TRUE &&
1641             pFD->GetEnclosingMethodTable()->Collectible());
1642
1643         // Compute the address of the field
1644         if (pFD->IsStatic())
1645         {
1646             // statics are addressed using an absolute address.
1647             if (pFD->IsRVA())
1648             {
1649                 // RVA statics are relative to a base module address
1650                 DWORD offset = pFD->GetOffset();
1651                 PTR_VOID addr = pFD->GetModule()->GetRvaField(offset, pFD->IsZapped());
1652                 if (pCurrentFieldData->OkToGetOrSetStaticAddress())
1653                 {
1654                     pCurrentFieldData->SetStaticAddress(PTR_TO_TADDR(addr));
1655                 }
1656             }
1657             else if (pFD->IsThreadStatic() || pFD->IsContextStatic() || 
1658                 pCurrentFieldData->m_fFldIsCollectibleStatic)
1659             {
1660                 // this is a special type of static that must be queried using DB_IPCE_GET_SPECIAL_STATIC
1661             }
1662             else
1663             {
1664                 // This is a normal static variable in the GC or Non-GC static base table
1665                 PTR_BYTE base = pFD->IsPrimitive() ? pNonGCStaticsBase : pGCStaticsBase;
1666                 if (base == NULL)
1667                 {
1668                     // static var not available.  This may be an open generic class (not an instantiated type),
1669                     // or we might only have approximate type information because the type hasn't been
1670                     // initialized yet.
1671                     
1672                     if (pCurrentFieldData->OkToGetOrSetStaticAddress())
1673                     {
1674                         pCurrentFieldData->SetStaticAddress(NULL);
1675                     }
1676                 }
1677                 else
1678                 {
1679                     if (pCurrentFieldData->OkToGetOrSetStaticAddress())
1680                     {
1681                         // calculate the absolute address using the base and the offset from the base
1682                         pCurrentFieldData->SetStaticAddress(PTR_TO_TADDR(base) + pFD->GetOffset());
1683                     }
1684                 }
1685             }
1686         }
1687         else
1688         {
1689             // instance variables are addressed using an offset within the instance
1690             if (pCurrentFieldData->OkToGetOrSetInstanceOffset())
1691             {
1692                 pCurrentFieldData->SetInstanceOffset(pFD->GetOffset());
1693             }
1694         }
1695     }
1696
1697 } // DacDbiInterfaceImpl::ComputeFieldData
1698
1699 //-----------------------------------------------------------------------------
1700 // DacDbiInterfaceImpl::CollectFields
1701 // Gets information for all the fields for a given type 
1702 // Arguments:
1703 //     input:  thExact         - used to determine whether we need to get statics base tables
1704 //             thApprox        - used to get the field desc iterator
1705 //             pAppDomain      - used to get statics base tables
1706 //     output: 
1707 //             pFieldList      - contains fields to be initialized 
1708 // Note: the caller must ensure that *ppFields is NULL (i.e., any previously allocated memory 
1709 // must have been deallocated.            
1710 //-----------------------------------------------------------------------------
1711 void DacDbiInterfaceImpl::CollectFields(TypeHandle                   thExact, 
1712                                         TypeHandle                   thApprox, 
1713                                         AppDomain *                  pAppDomain,
1714                                         DacDbiArrayList<FieldData> * pFieldList)
1715
1716     PTR_BYTE pGCStaticsBase = NULL;
1717     PTR_BYTE pNonGCStaticsBase = NULL;
1718     if (!thExact.IsNull() && !thExact.GetMethodTable()->Collectible())
1719     {
1720         // get base tables for static fields
1721         GetStaticsBases(thExact, pAppDomain, &pGCStaticsBase, &pNonGCStaticsBase);
1722     }
1723
1724     unsigned int fieldCount = 0;
1725
1726     // <TODO> we are losing exact type information for static fields in generic types. We have 
1727     // field desc iterators only for approximate types, but statics are per instantiation, so we 
1728     // need an exact type to be able to handle these correctly. We need to use 
1729     // FieldDesc::GetExactDeclaringType to get at the correct field. This requires the exact
1730     // TypeHandle. </TODO>
1731     EncApproxFieldDescIterator fdIterator(thApprox.GetMethodTable(),
1732                                           ApproxFieldDescIterator::ALL_FIELDS,
1733                                           FALSE);  // don't fixup EnC (we can't, we're stopped)
1734
1735     PTR_FieldDesc pCurrentFD;
1736     int index = 0;
1737     while (((pCurrentFD = fdIterator.Next()) != NULL) && (index < pFieldList->Count()))
1738     {
1739         // fill in the pCurrentEntry structure
1740         ComputeFieldData(pCurrentFD, pGCStaticsBase, pNonGCStaticsBase, &((*pFieldList)[index]));
1741
1742         // Bump our counts and pointers.
1743         fieldCount++;
1744         index++;
1745     }
1746     _ASSERTE(fieldCount == (unsigned int)pFieldList->Count());
1747
1748 } // DacDbiInterfaceImpl::CollectFields
1749
1750
1751 // Determine if a type is a ValueType
1752 BOOL DacDbiInterfaceImpl::IsValueType (VMPTR_TypeHandle vmTypeHandle)
1753 {
1754     DD_ENTER_MAY_THROW;
1755
1756     TypeHandle th = TypeHandle::FromPtr(vmTypeHandle.GetDacPtr()); 
1757     return th.IsValueType();
1758 }
1759
1760 // Determine if a type has generic parameters
1761 BOOL DacDbiInterfaceImpl::HasTypeParams (VMPTR_TypeHandle vmTypeHandle)
1762 {
1763     DD_ENTER_MAY_THROW;
1764
1765     TypeHandle th = TypeHandle::FromPtr(vmTypeHandle.GetDacPtr()); 
1766     return th.ContainsGenericVariables();
1767 }
1768
1769 // DacDbi API: Get type information for a class
1770 void DacDbiInterfaceImpl::GetClassInfo(VMPTR_AppDomain  vmAppDomain,
1771                                        VMPTR_TypeHandle vmThExact,
1772                                        ClassInfo *      pData)
1773 {
1774     DD_ENTER_MAY_THROW;
1775
1776     AppDomain * pAppDomain = vmAppDomain.GetDacPtr();
1777
1778     TypeHandle  thExact;
1779     TypeHandle  thApprox;
1780
1781     GetTypeHandles(vmThExact, vmThExact, &thExact, &thApprox);
1782
1783     // initialize field count, generic args count, size and value class flag
1784     InitClassData(thApprox, false, pData);
1785
1786     if (pAppDomain != NULL)
1787         CollectFields(thExact, thApprox, pAppDomain, &(pData->m_fieldList));
1788 } // DacDbiInterfaceImpl::GetClassInfo
1789
1790 // DacDbi API: Get field information and object size for an instantiated generic type
1791 void DacDbiInterfaceImpl::GetInstantiationFieldInfo (VMPTR_DomainFile             vmDomainFile,
1792                                                      VMPTR_TypeHandle             vmThExact,
1793                                                      VMPTR_TypeHandle             vmThApprox,
1794                                                      DacDbiArrayList<FieldData> * pFieldList,
1795                                                      SIZE_T *                     pObjectSize)
1796 {
1797     DD_ENTER_MAY_THROW;
1798
1799     DomainFile * pDomainFile = vmDomainFile.GetDacPtr();
1800     _ASSERTE(pDomainFile != NULL);
1801     AppDomain * pAppDomain = pDomainFile->GetAppDomain();
1802     TypeHandle  thExact;
1803     TypeHandle  thApprox;
1804
1805     GetTypeHandles(vmThExact, vmThApprox, &thExact, &thApprox);
1806
1807     *pObjectSize = thApprox.GetMethodTable()->GetNumInstanceFieldBytes();
1808
1809     pFieldList->Alloc(GetTotalFieldCount(thApprox));
1810
1811     CollectFields(thExact, thApprox, pAppDomain, pFieldList);
1812
1813 } // DacDbiInterfaceImpl::GetInstantiationFieldInfo
1814
1815 //-----------------------------------------------------------------------------------
1816 // DacDbiInterfaceImpl::TypeDataWalk member functions
1817 //-----------------------------------------------------------------------------------
1818
1819 //-----------------------------------------------------------------------------
1820 // TypeDataWalk constructor--initialize the buffer and number of remaining items from input data
1821 // Arguments: pData - pointer to a list of records containing information about type parameters for an
1822 //                    instantiated type
1823 //            nData - number of entries in pData        
1824 //-----------------------------------------------------------------------------
1825 DacDbiInterfaceImpl::TypeDataWalk::TypeDataWalk(DebuggerIPCE_TypeArgData * pData, unsigned int nData)
1826 {
1827     m_pCurrentData = pData;
1828     m_nRemaining = nData;
1829 } // DacDbiInterfaceImpl::TypeDataWalk::TypeDataWalk
1830
1831 //-----------------------------------------------------------------------------
1832 // DacDbiInterfaceImpl::TypeDataWalk::ReadOne
1833 // read and return a single node from the list of type parameters
1834 // Arguments: none (uses internal state)
1835 // Return value: information about the next type parameter in m_pCurrentData
1836 //-----------------------------------------------------------------------------
1837 DebuggerIPCE_TypeArgData * DacDbiInterfaceImpl::TypeDataWalk::ReadOne() 
1838
1839     LIMITED_METHOD_CONTRACT; 
1840     if (m_nRemaining) 
1841     { 
1842         m_nRemaining--; 
1843         return m_pCurrentData++; 
1844     } 
1845     else 
1846     {
1847         return NULL; 
1848     }
1849 } // DacDbiInterfaceImpl::TypeDataWalk::ReadOne
1850
1851 //-----------------------------------------------------------------------------
1852 // DacDbiInterfaceImpl::TypeDataWalk::Skip
1853 // Skip a single node from the list of type handles along with any children it might have
1854 // Arguments: none  (uses internal state)
1855 // Return value: none (updates internal state)
1856 //-----------------------------------------------------------------------------
1857 void DacDbiInterfaceImpl::TypeDataWalk::Skip()
1858 {
1859     LIMITED_METHOD_CONTRACT;
1860
1861     DebuggerIPCE_TypeArgData * pData = ReadOne();
1862     if (pData)
1863     {
1864         for (unsigned int i = 0; i < pData->numTypeArgs; i++)
1865         {
1866             Skip();
1867         }
1868     }
1869 } // DacDbiInterfaceImpl::TypeDataWalk::Skip
1870
1871 //-----------------------------------------------------------------------------
1872 // DacDbiInterfaceImpl::TypeDataWalk::ReadLoadedTypeArg
1873 // Read a type handle when it is used in the position of a generic argument or
1874 // argument of an array or address type.  Take into account generic code sharing if we
1875 // have been requested to find the canonical representation amongst a set of shared-
1876 // code generic types.  That is, if generics code sharing is enabled then return "Object"
1877 // for all reference types, and canonicalize underneath value types, e.g. V<string> --> V<object>.
1878 // Return TypeHandle() if any of the type handles are not loaded.
1879 // 
1880 // Arguments: retrieveWhich - indicates whether to retrieve a canonical representation or 
1881 //                            an exact representation
1882 // Return value: the type handle for the type parameter                            
1883 //-----------------------------------------------------------------------------
1884 TypeHandle DacDbiInterfaceImpl::TypeDataWalk::ReadLoadedTypeArg(TypeHandleReadType retrieveWhich)
1885 {
1886     CONTRACTL
1887     {
1888         NOTHROW;
1889         GC_NOTRIGGER;
1890     }
1891     CONTRACTL_END;
1892
1893 #if !defined(FEATURE_SHARE_GENERIC_CODE)
1894     return ReadLoadedTypeHandle(kGetExact);
1895 #else
1896
1897     if (retrieveWhich == kGetExact)
1898         return ReadLoadedTypeHandle(kGetExact);
1899
1900     // This nasty bit of code works out what the "canonicalization" of a
1901     // parameter to a generic is once we take into account generics code sharing.
1902     //
1903     // This logic is somewhat a duplication of logic in vm\typehandle.cpp, though
1904     // that logic operates on a TypeHandle format, i.e. assumes we're finding the
1905     // canonical form of a type that has already been loaded.  Here we are finding
1906     // the canonical form of a type that may not have been loaded (but where we expect
1907     // its canonical form to have been loaded).
1908     //
1909     // Ideally this logic would not be duplicated in this way, but it is difficult
1910     // to arrange for that.
1911     DebuggerIPCE_TypeArgData * pData = ReadOne();
1912     if (!pData)
1913         return TypeHandle();
1914
1915     // If we have code sharing then the process of canonicalizing is trickier.
1916     // unfortunately we have to include the exact specification of compatibility at
1917     // this point.
1918     CorElementType elementType = pData->data.elementType;
1919     
1920     switch (elementType)
1921     {
1922         case ELEMENT_TYPE_PTR:
1923             _ASSERTE(pData->numTypeArgs == 1);
1924             return PtrOrByRefTypeArg(pData, retrieveWhich);
1925             break;
1926             
1927         case ELEMENT_TYPE_CLASS:
1928         case ELEMENT_TYPE_VALUETYPE:
1929             return ClassTypeArg(pData, retrieveWhich);
1930             break;
1931             
1932         case ELEMENT_TYPE_FNPTR:
1933             return FnPtrTypeArg(pData, retrieveWhich);
1934             break;
1935
1936         default:
1937             return ObjRefOrPrimitiveTypeArg(pData, elementType);
1938             break;
1939     }
1940
1941 #endif // FEATURE_SHARE_GENERIC_CODE
1942 } // DacDbiInterfaceImpl::TypeDataWalk::ReadLoadedTypeArg
1943
1944 //-----------------------------------------------------------------------------
1945 // DacDbiInterfaceImpl::TypeDataWalk::ReadLoadedTypeHandles
1946 // Iterate through the type argument data, creating type handles as we go.
1947 // 
1948 // Arguments: 
1949 //     input:  retrieveWhich - indicates whether we can return a canonical type handle
1950 //                             or we must return an exact type handle
1951 //             nTypeArgs     - number of type arguments to be read
1952 //     output: ppResults     - pointer to a list of TypeHandles that will hold the type handles 
1953 //                             for each type parameter 
1954 //                             
1955 // Return Value: FALSE iff any of the type handles are not loaded.
1956 //-----------------------------------------------------------------------------
1957 BOOL DacDbiInterfaceImpl::TypeDataWalk::ReadLoadedTypeHandles(TypeHandleReadType retrieveWhich, 
1958                                                               unsigned int       nTypeArgs, 
1959                                                               TypeHandle *       ppResults)
1960 {
1961     WRAPPER_NO_CONTRACT;
1962
1963     BOOL allOK = true;
1964     for (unsigned int i = 0; i < nTypeArgs; i++)
1965     {
1966         ppResults[i] = ReadLoadedTypeArg(retrieveWhich);
1967         allOK &= !ppResults[i].IsNull();
1968     }
1969     return allOK;
1970 } // DacDbiInterfaceImpl::TypeDataWalk::ReadLoadedTypeHandles
1971
1972 //-----------------------------------------------------------------------------
1973 // DacDbiInterfaceImpl::TypeDataWalk::ReadLoadedInstantiation
1974 // Read an instantiation of a generic type if it has already been created.
1975 // 
1976 // Arguments:
1977 //     input:  retrieveWhich - indicates whether we can return a canonical type handle
1978 //                             or we must return an exact type handle
1979 //             pModule       - module in which the instantiated type is loaded
1980 //             mdToken       - metadata token for the type
1981 //             nTypeArgs     - number of type arguments to be read 
1982 // Return value: the type handle for the instantiated type
1983 //-----------------------------------------------------------------------------
1984 TypeHandle DacDbiInterfaceImpl::TypeDataWalk::ReadLoadedInstantiation(TypeHandleReadType retrieveWhich, 
1985                                                                       Module *           pModule, 
1986                                                                       mdTypeDef          mdToken, 
1987                                                                       unsigned int       nTypeArgs)
1988 {
1989     WRAPPER_NO_CONTRACT;
1990
1991     NewHolder<TypeHandle> pInst(new TypeHandle[nTypeArgs]);
1992
1993     // get the type handle for each of the type parameters
1994     if (!ReadLoadedTypeHandles(retrieveWhich, nTypeArgs, pInst))
1995     {
1996         return TypeHandle();
1997     }
1998
1999     // get the type handle for the particular instantiation that corresponds to 
2000     // the given type parameters
2001     return FindLoadedInstantiation(pModule, mdToken, nTypeArgs, pInst);
2002
2003 } // DacDbiInterfaceImpl::TypeDataWalk::ReadLoadedInstantiation
2004
2005
2006 //-----------------------------------------------------------------------------
2007 // DacDbiInterfaceImpl::TypeDataWalk::ReadLoadedTypeHandle
2008 // 
2009 // Compute the type handle for a given type. 
2010 // This is the top-level function that will return the type handle  for an
2011 // arbitrary type. It uses mutual recursion with ReadLoadedTypeArg to get
2012 // the type handle for a (possibly parameterized) type. Note that the referent of 
2013 // address types or the element type of an array type are viewed as type parameters.
2014 // 
2015 // For example, assume that we are retrieving only exact types, and we have as our
2016 // top level type an array defined as int [][].
2017 // We start by noting that the type is an array type, so we call ReadLoadedTypeArg to
2018 // get the element type. We find that the element type is also an array:int [].
2019 // ReadLoadedTypeArg will call ReadLoadedTypeHandle with this type information. 
2020 // Again, we determine that the top-level type is an array, so we call ReadLoadedTypeArg 
2021 // to get the element type, int. ReadLoadedTypeArg will again call ReadLoadedTypeHandle
2022 // which will find that this time, the top-level type is a primitive type. It will request
2023 // the loaded type handle from the loader and return it. On return, we get the type handle 
2024 // for an array of int from the loader. We return again and request the type handle for an
2025 // array of arrays of int. This is the type handle we will return. 
2026 // 
2027 // Arguments:
2028 //      input: retrieveWhich - determines whether we can return the type handle for 
2029 //                             a canonical type or only for an exact type
2030 //             we use the list of type data stored in the TypeDataWalk data members
2031 //             for other input information
2032 // Return value:  type handle for the current type.
2033 //-----------------------------------------------------------------------------
2034 TypeHandle DacDbiInterfaceImpl::TypeDataWalk::ReadLoadedTypeHandle(TypeHandleReadType retrieveWhich)
2035 {
2036     CONTRACTL
2037     {
2038         NOTHROW;
2039         GC_NOTRIGGER;
2040     }
2041     CONTRACTL_END;
2042
2043     // get the type information at the head of the list m_pCurrentData
2044     DebuggerIPCE_TypeArgData * pData = ReadOne();
2045     if (!pData)
2046       return TypeHandle();
2047
2048     // get the type handle that corresponds to its elementType
2049     TypeHandle typeHandle;
2050     switch (pData->data.elementType)
2051     {
2052         case ELEMENT_TYPE_ARRAY:
2053         case ELEMENT_TYPE_SZARRAY:
2054             typeHandle = ArrayTypeArg(pData, retrieveWhich);
2055             break;
2056
2057         case ELEMENT_TYPE_PTR:
2058         case ELEMENT_TYPE_BYREF:
2059             typeHandle = PtrOrByRefTypeArg(pData, retrieveWhich);
2060             break;
2061         case ELEMENT_TYPE_CLASS:
2062         case ELEMENT_TYPE_VALUETYPE:
2063             {
2064                 Module *     pModule = pData->data.ClassTypeData.vmModule.GetDacPtr();
2065                 typeHandle = ReadLoadedInstantiation(retrieveWhich, 
2066                                                      pModule, 
2067                                                      pData->data.ClassTypeData.metadataToken, 
2068                                                      pData->numTypeArgs);
2069             }
2070             break;
2071
2072         case ELEMENT_TYPE_FNPTR:
2073             {
2074                 typeHandle = FnPtrTypeArg(pData, retrieveWhich);
2075             }
2076             break;
2077
2078     default:
2079             typeHandle = FindLoadedElementType(pData->data.elementType);
2080         break;
2081     }
2082     return typeHandle;
2083 } // DacDbiInterfaceImpl::TypeDataWalk::ReadLoadedTypeHandle
2084
2085 //-----------------------------------------------------------------------------
2086 // DacDbiInterfaceImpl::TypeDataWalk::ArrayTypeArg
2087 // get a loaded type handle for an array type (E_T_ARRAY or E_T_SZARRAY)
2088 // 
2089 // Arguments:
2090 //     input: pArrayTypeInfo - type information for an array type
2091 //                             Although this is in fact a pointer (in)to a list, we treat it here 
2092 //                             simply as a pointer to a single instance of DebuggerIPCE_TypeArgData
2093 //                             which holds type information for an array. 
2094 //                             This is the most recent type node (for an array type) retrieved 
2095 //                             by TypeDataWalk::ReadOne(). The call to ReadLoadedTypeArg will
2096 //                             result in call(s) to ReadOne to retrieve one or more type nodes
2097 //                             that are needed to compute the type handle for the
2098 //                             element type of the array. When we return from that call, we pass 
2099 //                             pArrayTypeInfo along with arrayElementTypeArg to FindLoadedArrayType
2100 //                             to get the type handle for this particular array type.
2101 //                             Note:
2102 //                             On entry, we know that pArrayTypeInfo is the same as m_pCurrentData - 1,
2103 //                             but by the time we need to use it, this is no longer true. Because
2104 //                             we can't predict how many nodes will be consumed by the call to 
2105 //                             ReadLoadedTypeArg, we can't compute this value from the member fields
2106 //                             of TypeDataWalk and therefore pass it as a parameter.                   
2107 //            retrieveWhich -  determines whether we can return the type handle for 
2108 //                             a canonical type or only for an exact type
2109 // Return value: the type handle corresponding to the array type
2110 //-----------------------------------------------------------------------------
2111
2112 TypeHandle DacDbiInterfaceImpl::TypeDataWalk::ArrayTypeArg(DebuggerIPCE_TypeArgData * pArrayTypeInfo, 
2113                                                            TypeHandleReadType         retrieveWhich)
2114 {
2115     TypeHandle arrayElementTypeArg = ReadLoadedTypeArg(retrieveWhich);
2116     if (!arrayElementTypeArg.IsNull())
2117     {
2118         return FindLoadedArrayType(pArrayTypeInfo->data.elementType, 
2119                                    arrayElementTypeArg, 
2120                                    pArrayTypeInfo->data.ArrayTypeData.arrayRank);
2121     }
2122     return TypeHandle();
2123 } // DacDbiInterfaceImpl::TypeDataWalk::ArrayTypeArg
2124
2125
2126 //-----------------------------------------------------------------------------
2127 // DacDbiInterfaceImpl::TypeDataWalk::PtrOrByRefTypeArg
2128 // get a loaded type handle for an address type (E_T_PTR or E_T_BYREF)
2129 // 
2130 // Arguments:
2131 //     input: pPtrOrByRefTypeInfo - type information for a pointer or byref type
2132 //                             Although this is in fact a pointer (in)to a list, we treat it here 
2133 //                             simply as a pointer to a single instance of DebuggerIPCE_TypeArgData
2134 //                             which holds type information for a pointer or byref type. 
2135 //                             This is the most recent type node (for a pointer or byref type) retrieved 
2136 //                             by TypeDataWalk::ReadOne(). The call to ReadLoadedTypeArg will
2137 //                             result in call(s) to ReadOne to retrieve one or more type nodes
2138 //                             that are needed to compute the type handle for the
2139 //                             referent type of the pointer. When we return from that call, we pass 
2140 //                             pPtrOrByRefTypeInfo along with referentTypeArg to FindLoadedPointerOrByrefType
2141 //                             to get the type handle for this particular pointer or byref type.
2142 //                             Note:
2143 //                             On entry, we know that pPtrOrByRefTypeInfo is the same as m_pCurrentData - 1,
2144 //                             but by the time we need to use it, this is no longer true. Because
2145 //                             we can't predict how many nodes will be consumed by the call to 
2146 //                             ReadLoadedTypeArg, we can't compute this value from the member fields
2147 //                             of TypeDataWalk and therefore pass it as a parameter.                   
2148 //            retrieveWhich - determines whether we can return the type handle for 
2149 //                            a canonical type or only for an exact type
2150 // Return value: the type handle corresponding to the address type
2151 //-----------------------------------------------------------------------------
2152 TypeHandle DacDbiInterfaceImpl::TypeDataWalk::PtrOrByRefTypeArg(DebuggerIPCE_TypeArgData * pPtrOrByRefTypeInfo, 
2153                                                                 TypeHandleReadType         retrieveWhich)
2154 {
2155     TypeHandle referentTypeArg = ReadLoadedTypeArg(retrieveWhich);
2156     if (!referentTypeArg.IsNull())
2157     {
2158         return FindLoadedPointerOrByrefType(pPtrOrByRefTypeInfo->data.elementType, referentTypeArg);
2159     }
2160
2161     return TypeHandle();
2162     
2163 } // DacDbiInterfaceImpl::TypeDataWalk::PtrOrByRefTypeArg
2164
2165 //-----------------------------------------------------------------------------
2166 // DacDbiInterfaceImpl::TypeDataWalk::ClassTypeArg
2167 // get a loaded type handle for a class type (E_T_CLASS or E_T_VALUETYPE)
2168 // 
2169 // Arguments:
2170 //     input: pClassTypeInfo - type information for a class type
2171 //                             Although this is in fact a pointer (in)to a list, we treat it here 
2172 //                             simply as a pointer to a single instance of DebuggerIPCE_TypeArgData
2173 //                             which holds type information for a pointer or byref type. 
2174 //                             This is the most recent type node (for a pointer or byref type) retrieved 
2175 //                             by TypeDataWalk::ReadOne(). The call to ReadLoadedInstantiation will
2176 //                             result in call(s) to ReadOne to retrieve one or more type nodes
2177 //                             that are needed to compute the type handle for the type parameters
2178 //                             for the class. If we can't find an exact loaded type for the class, we will 
2179 //                             instead return a canonical method table. In this case, we need to skip 
2180 //                             the type parameter information for each actual parameter to the class. 
2181 //                             This is necessary because we may be getting a type handle for a class which is
2182 //                             in turn an argument to a parent type. If the parent type has more arguments, we
2183 //                             need to be at the right place in the list when we return. We use 
2184 //                             pClassTypeInfo to get the number of type arguments that we need to skip.
2185 //            retrieveWhich - determines whether we can return the type handle for 
2186 //                            a canonical type or only for an exact type
2187 // Return value: the type handle corresponding to the class type
2188 //-----------------------------------------------------------------------------
2189 TypeHandle DacDbiInterfaceImpl::TypeDataWalk::ClassTypeArg(DebuggerIPCE_TypeArgData * pClassTypeInfo, 
2190                                                            TypeHandleReadType         retrieveWhich)
2191 {
2192     Module *     pModule = pClassTypeInfo->data.ClassTypeData.vmModule.GetDacPtr();
2193     TypeHandle   typeDef = ClassLoader::LookupTypeDefOrRefInModule(pModule, 
2194                                                                    pClassTypeInfo->data.ClassTypeData.metadataToken);
2195     
2196     if ((!typeDef.IsNull() && typeDef.IsValueType()) || (pClassTypeInfo->data.elementType == ELEMENT_TYPE_VALUETYPE))
2197     {
2198         return ReadLoadedInstantiation(retrieveWhich,
2199                                        pModule, 
2200                                        pClassTypeInfo->data.ClassTypeData.metadataToken, 
2201                                        pClassTypeInfo->numTypeArgs);
2202     }
2203     else
2204     {
2205         _ASSERTE(retrieveWhich == kGetCanonical);
2206         // skip the instantiation - no need to look at it since the type canonicalizes to "Object"
2207         for (unsigned int i = 0; i < pClassTypeInfo->numTypeArgs; i++)
2208         {
2209             Skip();
2210         }
2211         return TypeHandle(g_pCanonMethodTableClass);
2212     }
2213 }// DacDbiInterfaceImpl::TypeDataWalk::ClassTypeArg
2214
2215 //-----------------------------------------------------------------------------
2216 // DacDbiInterfaceImpl::TypeDataWalk::FnPtrTypeArg
2217 // get a loaded type handle for a function pointer type (E_T_FNPTR)
2218 // 
2219 // Arguments:
2220 //     input: pFnPtrTypeInfo - type information for a pointer or byref type
2221 //                             Although this is in fact a pointer (in)to a list, we treat it here 
2222 //                             simply as a pointer to a single instance of DebuggerIPCE_TypeArgData
2223 //                             which holds type information for a function pointer type. 
2224 //                             This is the most recent type node (for a function pointer type) retrieved 
2225 //                             by TypeDataWalk::ReadOne(). The call to ReadLoadedTypeHandles will
2226 //                             result in call(s) to ReadOne to retrieve one or more type nodes
2227 //                             that are needed to compute the type handle for the return type and 
2228 //                             parameter types of the function. When we return from that call, we pass 
2229 //                             pFnPtrTypeInfo along with pInst to FindLoadedFnptrType
2230 //                             to get the type handle for this particular function pointer type.
2231 //            retrieveWhich - determines whether we can return the type handle for 
2232 //                            a canonical type or only for an exact type
2233 // Return value: the type handle corresponding to the function pointer type
2234 //-----------------------------------------------------------------------------
2235 TypeHandle DacDbiInterfaceImpl::TypeDataWalk::FnPtrTypeArg(DebuggerIPCE_TypeArgData * pFnPtrTypeInfo, 
2236                                                            TypeHandleReadType         retrieveWhich)
2237 {
2238     // allocate space to store a list of type handles, one for the return type and one for each
2239     // of the parameter types of the function to which the FnPtr type refers. 
2240     NewHolder<TypeHandle> pInst(new TypeHandle[sizeof(TypeHandle) * pFnPtrTypeInfo->numTypeArgs]);
2241     
2242     if (ReadLoadedTypeHandles(retrieveWhich, pFnPtrTypeInfo->numTypeArgs, pInst))
2243     {
2244         return FindLoadedFnptrType(pFnPtrTypeInfo->numTypeArgs, pInst);
2245     }
2246
2247     return TypeHandle();
2248     
2249 } // DacDbiInterfaceImpl::TypeDataWalk::FnPtrTypeArg
2250
2251 //-----------------------------------------------------------------------------
2252 // DacDbiInterfaceImpl::TypeDataWalk::ObjRefOrPrimitiveTypeArg
2253 // get a loaded type handle for a primitive type or ObjRef
2254 // 
2255 // Arguments:
2256 //     input: pArgInfo      - type information for an objref or primitive type.
2257 //                            This is called only when the objref or primitive type
2258 //                            is a type argument for a parent type. In this case,
2259 //                            we treat all objrefs the same, that is, we don't care 
2260 //                            about type parameters for the referent. Instead, we will
2261 //                            simply return the canonical object type handle as the type 
2262 //                            of the referent. <@dbgtodo Microsoft: why is this?> 
2263 //                            If this is a primitive type, we'll simply get the 
2264 //                            type handle for that type.  
2265 //            elementType   - type of the argument
2266 // Return value: the type handle corresponding to the elementType
2267 //-----------------------------------------------------------------------------
2268 TypeHandle DacDbiInterfaceImpl::TypeDataWalk::ObjRefOrPrimitiveTypeArg(DebuggerIPCE_TypeArgData * pArgInfo, 
2269                                                                        CorElementType             elementType)
2270 {
2271     // If there are any type args (e.g. for arrays) they can be skipped.  The thing
2272     // is a reference type anyway.
2273     for (unsigned int i = 0; i < pArgInfo->numTypeArgs; i++)
2274     {
2275         Skip();
2276     }
2277      
2278     // for an ObjRef, just return the CLASS____CANON type handle
2279     if (CorTypeInfo::IsObjRef_NoThrow(elementType))
2280     {
2281         return TypeHandle(g_pCanonMethodTableClass);
2282     }
2283     else
2284     {
2285         return FindLoadedElementType(elementType);
2286     }
2287 } // DacDbiInterfaceImpl::TypeDataWalk::ObjRefOrPrimitiveTypeArg
2288
2289
2290 //-------------------------------------------------------------------------
2291 // end of TypeDataWalk implementations
2292 //-------------------------------------------------------------------------
2293 //-------------------------------------------------------------------------
2294 // functions to use loader to get type handles
2295 // ------------------------------------------------------------------------
2296
2297 // Note, in these functions, the use of ClassLoader::DontLoadTypes was chosen
2298 // instead of FailIfNotLoaded because, although we may want to debug unrestored 
2299 // VCs, we can't do it because the debug API is not set up to handle them.
2300 // 
2301 //-----------------------------------------------------------------------------
2302 // DacDbiInterfaceImpl::FindLoadedArrayType
2303 // Use ClassLoader to find a loaded type handle for an array type (E_T_ARRAY or E_T_SZARRAY)
2304 // Arguments: 
2305 //     input: arrayType - type of the array 
2306 //            TypeArg   - type handle for the base type
2307 //            rank      - array rank
2308 // Return Value: type handle for the array type
2309 //-----------------------------------------------------------------------------
2310 // static
2311 TypeHandle DacDbiInterfaceImpl::FindLoadedArrayType(CorElementType arrayType, 
2312                                                     TypeHandle     typeArg, 
2313                                                     unsigned       rank)
2314 {
2315     // Lookup operations run the class loader in non-load mode.
2316     ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE();
2317
2318     if (typeArg.IsNull())
2319     {
2320         return TypeHandle();
2321     }
2322     else
2323     {
2324         return ClassLoader::LoadArrayTypeThrowing(typeArg, 
2325                                                   arrayType, 
2326                                                   rank,                                                  
2327                                                   ClassLoader::DontLoadTypes );
2328     }
2329 } // DacDbiInterfaceImpl::FindLoadedArrayType;
2330
2331 //-----------------------------------------------------------------------------
2332 // DacDbiInterfaceImpl::FindLoadedPointerOrByrefType
2333 // Use ClassLoader to find a loaded type handle for an address type (E_T_PTR or E_T_BYREF)
2334 // Arguments: 
2335 //     input: addressType - type of the address type 
2336 //            TypeArg     - type handle for the base type
2337 // Return Value: type handle for the address type
2338 //-----------------------------------------------------------------------------
2339 // static
2340 TypeHandle DacDbiInterfaceImpl::FindLoadedPointerOrByrefType(CorElementType addressType, TypeHandle typeArg)
2341 {
2342     // Lookup operations run the class loader in non-load mode.
2343     ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE();
2344
2345     return ClassLoader::LoadPointerOrByrefTypeThrowing(addressType, 
2346                                                        typeArg, 
2347                                                        ClassLoader::DontLoadTypes);
2348 } // DacDbiInterfaceImpl::FindLoadedPointerOrByrefType
2349
2350 //-----------------------------------------------------------------------------
2351 // DacDbiInterfaceImpl::FindLoadedFnptrType
2352 // Use ClassLoader to find a loaded type handle for a function pointer type (E_T_FNPTR)
2353 // Arguments: 
2354 //     input: pInst       - type handles of the function's return value and arguments 
2355 //            numTypeArgs - number of type handles in pInst
2356 // Return Value: type handle for the function pointer type
2357 //-----------------------------------------------------------------------------
2358 // static
2359 TypeHandle DacDbiInterfaceImpl::FindLoadedFnptrType(DWORD numTypeArgs, TypeHandle * pInst)
2360 {
2361     // Lookup operations run the class loader in non-load mode.
2362     ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE();
2363
2364     // @dbgtodo : Do we need to worry about calling convention here?
2365     // LoadFnptrTypeThrowing expects the count of arguments, not
2366     // including return value, so we subtract 1 from numTypeArgs.
2367     return  ClassLoader::LoadFnptrTypeThrowing(0,
2368                                                numTypeArgs - 1,
2369                                                pInst,
2370                                                ClassLoader::DontLoadTypes);
2371 } // DacDbiInterfaceImpl::FindLoadedFnptrType
2372
2373 //-----------------------------------------------------------------------------
2374 // DacDbiInterfaceImpl::FindLoadedInstantiation
2375 // Use ClassLoader to find a loaded type handle for a particular instantiation of a 
2376 // class type (E_T_CLASS or E_T_VALUECLASS)
2377 // 
2378 // Arguments:
2379 //     input: pModule   - module in which the type is loaded
2380 //            mdToken   - metadata token for the type
2381 //            nTypeArgs - number of type arguments in pInst
2382 //            pInst     - list of type handles for the type parameters
2383 // Return value: type handle for the instantiated class type           
2384 //-----------------------------------------------------------------------------
2385 // static
2386 TypeHandle DacDbiInterfaceImpl::FindLoadedInstantiation(Module *     pModule, 
2387                                                         mdTypeDef    mdToken, 
2388                                                         DWORD        nTypeArgs, 
2389                                                         TypeHandle * pInst)
2390 {
2391     // Lookup operations run the class loader in non-load mode.
2392     ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE();
2393
2394     return ClassLoader::LoadGenericInstantiationThrowing(pModule, 
2395                                                          mdToken, 
2396                                                          Instantiation(pInst,nTypeArgs),
2397                                                          ClassLoader::DontLoadTypes);
2398
2399 } // DacDbiInterfaceImpl::FindLoadedInstantiation
2400
2401 //-----------------------------------------------------------------------------
2402 // DacDbiInterfaceImpl::FindLoadedElementType 
2403 // Get the type handle for a primitive type
2404 // Arguments:
2405 //     input: elementType - type of the primitive type
2406 // Return Value: Type handle for the primitive type
2407 //-----------------------------------------------------------------------------
2408 // static
2409 TypeHandle DacDbiInterfaceImpl::FindLoadedElementType(CorElementType elementType) 
2410 {
2411     // Lookup operations run the class loader in non-load mode.
2412     ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE();
2413
2414     MethodTable * pMethodTable = (&g_Mscorlib)->GetElementType(elementType);
2415
2416     return TypeHandle(pMethodTable);
2417 } // DacDbiInterfaceImpl::FindLoadedElementType
2418
2419
2420 //-----------------------------------------------------------------------------
2421 // DacDbiInterfaceImpl::GetArrayTypeInfo
2422 // Gets additional information to convert a type handle to an instance of CordbType if the type is E_T_ARRAY.
2423 // Specifically, we get the rank and the type of the array elements
2424 // 
2425 // Arguments: 
2426 //     input:  typeHandle - type handle for the array type
2427 //             pAppDomain - AppDomain into which the type is loaded
2428 //     output: pTypeInfo  - information for the array rank and element type
2429 //     
2430 //-----------------------------------------------------------------------------
2431 void DacDbiInterfaceImpl::GetArrayTypeInfo(TypeHandle                      typeHandle,
2432                                            DebuggerIPCE_ExpandedTypeData * pTypeInfo,
2433                                            AppDomain *                     pAppDomain)
2434 {
2435     _ASSERTE(typeHandle.IsArray());
2436     pTypeInfo->ArrayTypeData.arrayRank = typeHandle.AsArray()->GetRank();
2437     TypeHandleToBasicTypeInfo(typeHandle.AsArray()->GetArrayElementTypeHandle(), 
2438                               &(pTypeInfo->ArrayTypeData.arrayTypeArg),
2439                               pAppDomain);
2440 } // DacDbiInterfaceImpl::GetArrayTypeInfo
2441
2442 //-----------------------------------------------------------------------------
2443 // DacDbiInterfaceImpl::GetPtrTypeInfo
2444 // Gets additional information to convert a type handle to an instance of CordbType if the type is
2445 // E_T_PTR or E_T_BYREF. Specifically, we get the type for the referent of the address type
2446 // 
2447 // Arguments: 
2448 //     input:  boxed      - indicates what, if anything, is boxed (see code:AreValueTypesBoxed for 
2449 //                          more specific information)
2450 //             typeHandle - type handle for the address type
2451 //             pAppDomain - AppDomain into which the type is loaded
2452 //     output: pTypeInfo  - information for the referent type
2453 //     
2454 //-----------------------------------------------------------------------------
2455 void DacDbiInterfaceImpl::GetPtrTypeInfo(AreValueTypesBoxed              boxed, 
2456                                          TypeHandle                      typeHandle, 
2457                                          DebuggerIPCE_ExpandedTypeData * pTypeInfo,
2458                                          AppDomain *                     pAppDomain)
2459 {
2460     if (boxed == AllBoxed)
2461     {
2462         GetClassTypeInfo(typeHandle, pTypeInfo, pAppDomain);
2463     }
2464     else
2465     {
2466         _ASSERTE(typeHandle.IsTypeDesc());
2467         TypeHandleToBasicTypeInfo(typeHandle.AsTypeDesc()->GetTypeParam(), 
2468                                   &(pTypeInfo->UnaryTypeData.unaryTypeArg),
2469                                   pAppDomain);
2470     }
2471 } // DacDbiInterfaceImpl::GetPtrTypeInfo
2472
2473 //-----------------------------------------------------------------------------
2474 // DacDbiInterfaceImpl::GetFnPtrTypeInfo
2475 // Gets additional information to convert a type handle to an instance of CordbType if the type is
2476 // E_T_FNPTR, specifically the typehandle for the referent. 
2477 // 
2478 // Arguments
2479 //     input:  boxed      - indicates what, if anything, is boxed (see code:AreValueTypesBoxed for 
2480 //                          more specific information)
2481 //             typeHandle - type handle for the address type
2482 //             pAppDomain - AppDomain into which the type is loaded
2483 //     output: pTypeInfo  - information for the referent type
2484 //  
2485 //-----------------------------------------------------------------------------
2486 void DacDbiInterfaceImpl::GetFnPtrTypeInfo(AreValueTypesBoxed              boxed,
2487                                            TypeHandle                      typeHandle,
2488                                            DebuggerIPCE_ExpandedTypeData * pTypeInfo, 
2489                                            AppDomain *                     pAppDomain)
2490 {
2491     if (boxed == AllBoxed)
2492     {
2493         GetClassTypeInfo(typeHandle, pTypeInfo, pAppDomain);
2494     }
2495     else
2496     {
2497         pTypeInfo->NaryTypeData.typeHandle.SetDacTargetPtr(typeHandle.AsTAddr());
2498     }
2499 } // DacDbiInterfaceImpl::GetFnPtrTypeInfo
2500
2501
2502 //-----------------------------------------------------------------------------
2503 // DacDbiInterfaceImpl::GetClassTypeInfo
2504 // Gets additional information to convert a type handle to an instance of CordbType if the type is
2505 // E_T_CLASS or E_T_VALUETYPE
2506 // 
2507 // Arguments
2508 //     input:  typeHandle - type handle for the address type
2509 //             pAppDomain - AppDomain into which the type is loaded
2510 //     output: pTypeInfo  - information for the referent type
2511 //  
2512 //-----------------------------------------------------------------------------
2513 void DacDbiInterfaceImpl::GetClassTypeInfo(TypeHandle                      typeHandle,
2514                                            DebuggerIPCE_ExpandedTypeData * pTypeInfo,
2515                                            AppDomain *                     pAppDomain)
2516 {
2517     Module * pModule = typeHandle.GetModule();
2518
2519     if (typeHandle.HasInstantiation()) // the type handle represents a generic instantiation
2520     {
2521         pTypeInfo->ClassTypeData.typeHandle.SetDacTargetPtr(typeHandle.AsTAddr());
2522     }
2523     else // non-generic
2524     {
2525         pTypeInfo->ClassTypeData.typeHandle = VMPTR_TypeHandle::NullPtr();
2526     }
2527
2528     pTypeInfo->ClassTypeData.metadataToken = typeHandle.GetCl();
2529     
2530     _ASSERTE(pModule);
2531     pTypeInfo->ClassTypeData.vmModule.SetDacTargetPtr(PTR_HOST_TO_TADDR(pModule));
2532     if (pAppDomain)
2533     {
2534         pTypeInfo->ClassTypeData.vmDomainFile.SetDacTargetPtr(PTR_HOST_TO_TADDR(pModule->GetDomainFile(pAppDomain)));
2535     }
2536     else
2537     {
2538         pTypeInfo->ClassTypeData.vmDomainFile = VMPTR_DomainFile::NullPtr();
2539     }
2540 } // DacDbiInterfaceImpl::GetClassTypeInfo
2541
2542 //-----------------------------------------------------------------------------
2543 // DacDbiInterfaceImpl::GetElementType
2544 // Gets the correct CorElementType value from a type handle
2545 // 
2546 // Arguments
2547 //     input:  typeHandle - type handle for the address type
2548 // Return Value: the CorElementType enum value for the type handle
2549 //-----------------------------------------------------------------------------
2550 CorElementType DacDbiInterfaceImpl::GetElementType (TypeHandle typeHandle)
2551 {
2552     if (typeHandle.IsNull())
2553     {
2554         return ELEMENT_TYPE_VOID;
2555     }
2556     else if (typeHandle.GetMethodTable() == g_pObjectClass)
2557     {
2558        return ELEMENT_TYPE_OBJECT;
2559     }
2560     else if (typeHandle.GetMethodTable() == g_pStringClass)
2561     {
2562         return ELEMENT_TYPE_STRING;
2563     }
2564     else
2565     {
2566         // GetSignatureCorElementType returns E_T_CLASS for E_T_STRING... :-(
2567         return typeHandle.GetSignatureCorElementType();
2568     }
2569
2570 } // DacDbiInterfaceImpl::GetElementType
2571
2572 //-----------------------------------------------------------------------------
2573 // DacDbiInterfaceImpl::TypeHandleToBasicTypeInfo
2574 // Gets additional information to convert a type handle to an instance of CordbType for the referent of an 
2575 // E_T_BYREF or E_T_PTR or for the element type of an E_T_ARRAY or E_T_SZARRAY
2576 // 
2577 // Arguments: 
2578 //     input:  typeHandle - type handle for the address type
2579 //             pAppDomain - AppDomain into which the type is loaded
2580 //     output: pTypeInfo  - information for the referent type
2581 //  
2582 //-----------------------------------------------------------------------------
2583 void DacDbiInterfaceImpl::TypeHandleToBasicTypeInfo(TypeHandle                   typeHandle, 
2584                                                     DebuggerIPCE_BasicTypeData * pTypeInfo,
2585                                                     AppDomain *                  pAppDomain)
2586 {
2587     pTypeInfo->elementType = GetElementType(typeHandle);
2588
2589     switch (pTypeInfo->elementType)
2590     {
2591         case ELEMENT_TYPE_ARRAY:
2592         case ELEMENT_TYPE_SZARRAY:
2593         case ELEMENT_TYPE_FNPTR:
2594         case ELEMENT_TYPE_PTR:
2595         case ELEMENT_TYPE_BYREF:
2596             pTypeInfo->vmTypeHandle.SetDacTargetPtr(typeHandle.AsTAddr());
2597             pTypeInfo->metadataToken = mdTokenNil;
2598             pTypeInfo->vmDomainFile = VMPTR_DomainFile::NullPtr();
2599             break;
2600
2601         case ELEMENT_TYPE_CLASS:
2602         case ELEMENT_TYPE_VALUETYPE:
2603         {
2604             Module * pModule = typeHandle.GetModule();
2605
2606             if (typeHandle.HasInstantiation())   // only set if instantiated
2607             {
2608                 pTypeInfo->vmTypeHandle.SetDacTargetPtr(typeHandle.AsTAddr()); 
2609             }
2610             else
2611             {
2612                 pTypeInfo->vmTypeHandle = VMPTR_TypeHandle::NullPtr(); 
2613             }
2614                                                                              
2615             pTypeInfo->metadataToken = typeHandle.GetCl();
2616             _ASSERTE(pModule);
2617             
2618             pTypeInfo->vmModule.SetDacTargetPtr(PTR_HOST_TO_TADDR(pModule)); 
2619             if (pAppDomain)
2620             {
2621                 pTypeInfo->vmDomainFile.SetDacTargetPtr(PTR_HOST_TO_TADDR(pModule->GetDomainFile(pAppDomain)));
2622             }
2623             else
2624             {
2625                 pTypeInfo->vmDomainFile = VMPTR_DomainFile::NullPtr();
2626             }
2627             break;
2628         }
2629
2630         default:
2631             pTypeInfo->vmTypeHandle = VMPTR_TypeHandle::NullPtr();
2632             pTypeInfo->metadataToken = mdTokenNil;
2633             pTypeInfo->vmDomainFile = VMPTR_DomainFile::NullPtr();
2634             break;
2635     }
2636     return;
2637 } // DacDbiInterfaceImpl::TypeHandleToBasicTypeInfo
2638
2639
2640 void DacDbiInterfaceImpl::GetObjectExpandedTypeInfoFromID(AreValueTypesBoxed boxed,
2641                                        VMPTR_AppDomain vmAppDomain,
2642                                        COR_TYPEID id,
2643                                        DebuggerIPCE_ExpandedTypeData *pTypeInfo)
2644 {
2645     DD_ENTER_MAY_THROW;
2646     
2647     PTR_MethodTable pMT(TO_TADDR(id.token1));
2648     
2649     if (pMT->IsArray())
2650     {
2651         // ArrayBase::GetTypeHandle() may return a NULL handle in corner case scenarios.  This check prevents
2652         // us from an AV but doesn't actually fix the problem.  See DevDiv 653441 for more info.
2653         TypeHandle arrayHandle = ArrayBase::GetTypeHandle(pMT);
2654         if (arrayHandle.IsNull())
2655         {
2656             ThrowHR(CORDBG_E_CLASS_NOT_LOADED);
2657         }
2658
2659         TypeHandleToExpandedTypeInfoImpl(boxed, vmAppDomain, arrayHandle, pTypeInfo);
2660     }
2661     else
2662     {
2663         TypeHandleToExpandedTypeInfoImpl(boxed, vmAppDomain, TypeHandle::FromPtr(TO_TADDR(id.token1)), pTypeInfo);
2664     }
2665 }
2666
2667 void DacDbiInterfaceImpl::GetObjectExpandedTypeInfo(AreValueTypesBoxed boxed,
2668                                        VMPTR_AppDomain vmAppDomain,
2669                                        CORDB_ADDRESS addr,
2670                                        DebuggerIPCE_ExpandedTypeData *pTypeInfo)
2671 {
2672     DD_ENTER_MAY_THROW;
2673     
2674     PTR_Object obj(TO_TADDR(addr));
2675     TypeHandleToExpandedTypeInfoImpl(boxed, vmAppDomain, obj->GetGCSafeTypeHandle(), pTypeInfo);
2676 }
2677
2678 // DacDbi API: use a type handle to get the information needed to create the corresponding RS CordbType instance
2679 void DacDbiInterfaceImpl::TypeHandleToExpandedTypeInfo(AreValueTypesBoxed              boxed,
2680                                                        VMPTR_AppDomain                 vmAppDomain,
2681                                                        VMPTR_TypeHandle                vmTypeHandle,
2682                                                        DebuggerIPCE_ExpandedTypeData * pTypeInfo)
2683 {
2684     DD_ENTER_MAY_THROW;
2685     
2686     
2687     TypeHandle typeHandle = TypeHandle::FromPtr(vmTypeHandle.GetDacPtr());
2688     TypeHandleToExpandedTypeInfoImpl(boxed, vmAppDomain, typeHandle, pTypeInfo);
2689 }
2690
2691
2692 void DacDbiInterfaceImpl::TypeHandleToExpandedTypeInfoImpl(AreValueTypesBoxed              boxed,
2693                                                        VMPTR_AppDomain                 vmAppDomain,
2694                                                        TypeHandle                      typeHandle,
2695                                                        DebuggerIPCE_ExpandedTypeData * pTypeInfo)
2696 {
2697     AppDomain * pAppDomain = vmAppDomain.GetDacPtr();
2698     pTypeInfo->elementType = GetElementType(typeHandle);
2699
2700     switch (pTypeInfo->elementType)
2701     {
2702         case ELEMENT_TYPE_ARRAY:
2703         case ELEMENT_TYPE_SZARRAY:
2704             GetArrayTypeInfo(typeHandle, pTypeInfo, pAppDomain);
2705             break;
2706
2707         case ELEMENT_TYPE_PTR:
2708         case ELEMENT_TYPE_BYREF:
2709             GetPtrTypeInfo(boxed, typeHandle, pTypeInfo, pAppDomain);
2710             break;
2711
2712         case ELEMENT_TYPE_VALUETYPE:
2713             if (boxed == OnlyPrimitivesUnboxed || boxed == AllBoxed)
2714             {
2715                 pTypeInfo->elementType = ELEMENT_TYPE_CLASS;
2716             }
2717             GetClassTypeInfo(typeHandle, pTypeInfo, pAppDomain);
2718            break;
2719
2720         case ELEMENT_TYPE_CLASS:
2721             GetClassTypeInfo(typeHandle, pTypeInfo, pAppDomain);
2722             break;
2723
2724         case ELEMENT_TYPE_FNPTR:
2725                 GetFnPtrTypeInfo(boxed, typeHandle, pTypeInfo, pAppDomain);
2726                 break;
2727         default:
2728             if (boxed == AllBoxed)
2729             {
2730                 pTypeInfo->elementType = ELEMENT_TYPE_CLASS;
2731                 GetClassTypeInfo(typeHandle, pTypeInfo, pAppDomain);
2732             }
2733             // else the element type is sufficient
2734             break;
2735     }
2736     LOG((LF_CORDB, LL_INFO10000, "D::THTETI: converted left-side type handle to expanded right-side type info, pTypeInfo->ClassTypeData.typeHandle = 0x%08x.\n", pTypeInfo->ClassTypeData.typeHandle.GetRawPtr()));
2737     return;
2738 } // DacDbiInterfaceImpl::TypeHandleToExpandedTypeInfo
2739
2740 // Get type handle for a TypeDef token, if one exists. For generics this returns the open type.
2741 VMPTR_TypeHandle DacDbiInterfaceImpl::GetTypeHandle(VMPTR_Module vmModule,
2742                                                     mdTypeDef metadataToken)
2743 {
2744     DD_ENTER_MAY_THROW;
2745     Module* pModule = vmModule.GetDacPtr();
2746     VMPTR_TypeHandle vmTypeHandle = VMPTR_TypeHandle::NullPtr();
2747
2748     TypeHandle th = ClassLoader::LookupTypeDefOrRefInModule(pModule, metadataToken);
2749     if (th.IsNull())
2750     {
2751         LOG((LF_CORDB, LL_INFO10000, "D::GTH: class isn't loaded.\n"));
2752         ThrowHR(CORDBG_E_CLASS_NOT_LOADED);
2753     }
2754
2755     vmTypeHandle.SetDacTargetPtr(th.AsTAddr());
2756     return vmTypeHandle;
2757 }
2758
2759 // DacDbi API: GetAndSendApproxTypeHandle finds the type handle for the layout of the instance fields of an
2760 // instantiated type if it is available.
2761 VMPTR_TypeHandle DacDbiInterfaceImpl::GetApproxTypeHandle(TypeInfoList * pTypeData)
2762 {
2763     DD_ENTER_MAY_THROW;
2764
2765     LOG((LF_CORDB, LL_INFO10000, "D::GATH: getting info.\n"));
2766
2767
2768     TypeDataWalk walk(&((*pTypeData)[0]), pTypeData->Count());
2769     TypeHandle typeHandle = walk.ReadLoadedTypeHandle(TypeDataWalk::kGetCanonical);
2770     VMPTR_TypeHandle vmTypeHandle = VMPTR_TypeHandle::NullPtr();
2771
2772     vmTypeHandle.SetDacTargetPtr(typeHandle.AsTAddr());
2773     if (!typeHandle.IsNull())
2774     {
2775         vmTypeHandle.SetDacTargetPtr(typeHandle.AsTAddr());
2776     }
2777     else
2778     {
2779         ThrowHR(CORDBG_E_CLASS_NOT_LOADED);
2780     }
2781
2782     LOG((LF_CORDB, LL_INFO10000, 
2783         "D::GATH: sending result, result = 0x%0x8\n", 
2784         typeHandle));
2785     return vmTypeHandle;
2786 } // DacDbiInterfaceImpl::GetApproxTypeHandle
2787
2788 // DacDbiInterface API: Get the exact type handle from type data
2789 HRESULT DacDbiInterfaceImpl::GetExactTypeHandle(DebuggerIPCE_ExpandedTypeData * pTypeData,
2790                                                 ArgInfoList *   pArgInfo,
2791                                                 VMPTR_TypeHandle& vmTypeHandle)
2792 {
2793     DD_ENTER_MAY_THROW;
2794
2795     LOG((LF_CORDB, LL_INFO10000, "D::GETH: getting info.\n"));
2796
2797     HRESULT hr = S_OK;
2798
2799     EX_TRY
2800     {
2801         vmTypeHandle = vmTypeHandle.NullPtr();
2802
2803         // convert the type information to a type handle
2804         TypeHandle typeHandle = ExpandedTypeInfoToTypeHandle(pTypeData, pArgInfo);
2805         _ASSERTE(!typeHandle.IsNull());
2806         vmTypeHandle.SetDacTargetPtr(typeHandle.AsTAddr());
2807     }
2808     EX_CATCH_HRESULT(hr);
2809
2810     return hr;
2811 } // DacDbiInterfaceImpl::GetExactTypeHandle
2812
2813 // Retrieve the generic type params for a given MethodDesc.  This function is specifically 
2814 // for stackwalking because it requires the generic type token on the stack.
2815 void DacDbiInterfaceImpl::GetMethodDescParams(
2816     VMPTR_AppDomain     vmAppDomain,
2817     VMPTR_MethodDesc    vmMethodDesc,
2818     GENERICS_TYPE_TOKEN genericsToken,
2819     UINT32 *            pcGenericClassTypeParams,
2820     TypeParamsList *    pGenericTypeParams)
2821 {
2822     DD_ENTER_MAY_THROW;
2823
2824     if (vmAppDomain.IsNull() || vmMethodDesc.IsNull())
2825     {
2826         ThrowHR(E_INVALIDARG);
2827     }
2828
2829     _ASSERTE((pcGenericClassTypeParams != NULL) && (pGenericTypeParams != NULL));
2830
2831     MethodDesc * pMD = vmMethodDesc.GetDacPtr();
2832
2833     // Retrieve the number of type parameters for the class and 
2834     // the number of type parameters for the method itself.
2835     // For example, the method Foo<T, U>::Bar<V>() has 2 class type parameters and 1 method type parameters.
2836     UINT32 cGenericClassTypeParams  = pMD->GetNumGenericClassArgs();
2837     UINT32 cGenericMethodTypeParams = pMD->GetNumGenericMethodArgs();
2838     UINT32 cTotalGenericTypeParams  = cGenericClassTypeParams + cGenericMethodTypeParams;
2839
2840     // Set the out parameter.
2841     *pcGenericClassTypeParams = cGenericClassTypeParams;
2842
2843     TypeHandle   thSpecificClass;
2844     MethodDesc * pSpecificMethod;
2845
2846     // Try to retrieve a more specific MethodDesc and TypeHandle via the generics type token.
2847     // The generics token is not always guaranteed to be available.  
2848     // For example, it may be unavailable in prologs and epilogs.
2849     // In dumps, not available can also mean a thrown exception for missing memory.
2850     BOOL fExact = FALSE;
2851     ALLOW_DATATARGET_MISSING_MEMORY(
2852         fExact = Generics::GetExactInstantiationsOfMethodAndItsClassFromCallInformation(
2853             pMD,
2854             PTR_VOID((TADDR)genericsToken),
2855             &thSpecificClass,
2856             &pSpecificMethod);
2857             );
2858     if (!fExact ||
2859         !thSpecificClass.GetMethodTable()->SanityCheck() || 
2860         !pSpecificMethod->GetMethodTable()->SanityCheck())
2861     {
2862         // Use the canonical MethodTable and MethodDesc if the exact generics token is not available.
2863         thSpecificClass = TypeHandle(pMD->GetMethodTable());
2864         pSpecificMethod = pMD;
2865     }
2866
2867     // Retrieve the array of class type parameters and the array of method type parameters.
2868     Instantiation classInst  = pSpecificMethod->GetExactClassInstantiation(thSpecificClass);
2869     Instantiation methodInst = pSpecificMethod->GetMethodInstantiation();
2870
2871     _ASSERTE((classInst.IsEmpty())  == (cGenericClassTypeParams  == 0));
2872     _ASSERTE((methodInst.IsEmpty()) == (cGenericMethodTypeParams == 0));
2873
2874     // allocate memory for the return array
2875     pGenericTypeParams->Alloc(cTotalGenericTypeParams);
2876
2877     for (UINT32 i = 0; i < cTotalGenericTypeParams; i++)
2878     {
2879         // Retrieve the current type parameter depending on the index.
2880         TypeHandle thCurrent;
2881         if (i < cGenericClassTypeParams)
2882         {
2883             thCurrent = classInst[i];
2884         }
2885         else
2886         {
2887             thCurrent = methodInst[i - cGenericClassTypeParams];
2888         }
2889
2890         // There is the possiblity that we'll get this far with a dump and not fail, but still
2891         // not be able to get full info for a particular param.
2892         EX_TRY_ALLOW_DATATARGET_MISSING_MEMORY_WITH_HANDLER
2893         {
2894             // Fill in the struct using the TypeHandle of the current type parameter if we can.
2895             VMPTR_TypeHandle vmTypeHandle = VMPTR_TypeHandle::NullPtr();
2896             vmTypeHandle.SetDacTargetPtr(thCurrent.AsTAddr());
2897             TypeHandleToExpandedTypeInfo(NoValueTypeBoxing,
2898                                          vmAppDomain,
2899                                          vmTypeHandle,
2900                                          &((*pGenericTypeParams)[i]));
2901         }
2902         EX_CATCH_ALLOW_DATATARGET_MISSING_MEMORY_WITH_HANDLER
2903         {
2904             // On failure for a particular type, default it back to System.__Canon.
2905             VMPTR_TypeHandle vmTHCanon = VMPTR_TypeHandle::NullPtr();
2906             TypeHandle thCanon = TypeHandle(g_pCanonMethodTableClass);
2907             vmTHCanon.SetDacTargetPtr(thCanon.AsTAddr());
2908             TypeHandleToExpandedTypeInfo(NoValueTypeBoxing,
2909                                          vmAppDomain,
2910                                          vmTHCanon,
2911                                          &((*pGenericTypeParams)[i]));
2912         }
2913         EX_END_CATCH_ALLOW_DATATARGET_MISSING_MEMORY_WITH_HANDLER
2914     }
2915 }
2916
2917 //-----------------------------------------------------------------------------
2918 // DacDbiInterfaceImpl::GetClassOrValueTypeHandle
2919 // get a typehandle for a class or valuetype from basic type data (metadata token
2920 // and domain file).
2921 // Arguments: 
2922 //     input: pData - contains the metadata token and domain file
2923 // Return value: the type handle for the corresponding type
2924 //-----------------------------------------------------------------------------
2925 TypeHandle DacDbiInterfaceImpl::GetClassOrValueTypeHandle(DebuggerIPCE_BasicTypeData * pData)
2926 {
2927     TypeHandle typeHandle;
2928
2929     // if we already have a type handle, just return it
2930     if (!pData->vmTypeHandle.IsNull())
2931     {
2932         typeHandle = TypeHandle::FromPtr(pData->vmTypeHandle.GetDacPtr());
2933     }
2934     // otherwise, have the loader look it up using the metadata token and domain file
2935     else
2936     {
2937         DomainFile * pDomainFile = pData->vmDomainFile.GetDacPtr();
2938         Module *     pModule = pDomainFile->GetModule();
2939         
2940         typeHandle = ClassLoader::LookupTypeDefOrRefInModule(pModule, pData->metadataToken);
2941         if (typeHandle.IsNull())
2942         {
2943             LOG((LF_CORDB, LL_INFO10000, "D::BTITTH: class isn't loaded.\n"));
2944             ThrowHR(CORDBG_E_CLASS_NOT_LOADED);
2945         }
2946
2947         _ASSERTE(typeHandle.GetNumGenericArgs() == 0);
2948     }
2949
2950     return typeHandle;
2951
2952 } // DacDbiInterfaceImpl::GetClassOrValueTypeHandle
2953
2954 //-----------------------------------------------------------------------------
2955 // DacDbiInterfaceImpl::GetExactArrayTypeHandle
2956 // get an exact type handle for an array type
2957 // Arguments:
2958 //     input: pTopLevelTypeData - type information for a top-level array type
2959 //            pArgInfo           - contains the following information:
2960 //                 m_genericArgsCount  - number of generic parameters for the element type--this should be 1
2961 //                 m_pGenericArgs      - pointer to the generic parameter for the element type--this is
2962 //                                       effectively a one-element list. These are the actual parameters
2963 // Return Value: the exact type handle for the type           
2964 //-----------------------------------------------------------------------------
2965 TypeHandle DacDbiInterfaceImpl::GetExactArrayTypeHandle(DebuggerIPCE_ExpandedTypeData * pTopLevelTypeData,
2966                                                         ArgInfoList *                   pArgInfo)
2967 {
2968     TypeHandle typeArg;
2969
2970     _ASSERTE(pArgInfo->Count() == 1);
2971
2972     // get the type handle for the element type
2973     typeArg = BasicTypeInfoToTypeHandle(&((*pArgInfo)[0]));
2974
2975     // get the exact type handle for the array type
2976     return FindLoadedArrayType(pTopLevelTypeData->elementType, 
2977                                typeArg, 
2978                                pTopLevelTypeData->ArrayTypeData.arrayRank);
2979
2980 } // DacDbiInterfaceImpl::GetExactArrayTypeHandle
2981
2982 //-----------------------------------------------------------------------------
2983 // DacDbiInterfaceImpl::GetExactPtrOrByRefTypeHandle
2984 // get an exact type handle for a PTR or BYREF type
2985 // Arguments:
2986 //     input: pTopLevelTypeData - type information for the PTR or BYREF type
2987 //            pArgInfo           - contains the following information:
2988 //                 m_genericArgsCount  - number of generic parameters for the element type--this should be 1
2989 //                 m_pGenericArgs      - pointer to the generic parameter for the element type--this is
2990 //                                       effectively a one-element list. These are the actual parameters
2991 // Return Value: the exact type handle for the type           
2992 //-----------------------------------------------------------------------------
2993 TypeHandle DacDbiInterfaceImpl::GetExactPtrOrByRefTypeHandle(DebuggerIPCE_ExpandedTypeData * pTopLevelTypeData,
2994                                                              ArgInfoList *                   pArgInfo)
2995 {
2996     TypeHandle typeArg;
2997     _ASSERTE(pArgInfo->Count() == 1);
2998
2999     // get the type handle for the referent
3000     typeArg = BasicTypeInfoToTypeHandle(&((*pArgInfo)[0]));
3001
3002     // get the exact type handle for the PTR or BYREF type
3003     return FindLoadedPointerOrByrefType(pTopLevelTypeData->elementType, typeArg);
3004
3005 } // DacDbiInterfaceImpl::GetExactPtrOrByRefTypeHandle
3006
3007 //-----------------------------------------------------------------------------
3008 // DacDbiInterfaceImpl::GetExactClassTypeHandle
3009 // get an exact type handle for a CLASS or VALUETYPE type
3010 // Arguments:
3011 //     input: pTopLevelTypeData - type information for the CLASS or VALUETYPE type
3012 //            pArgInfo           - contains the following information:
3013 //                 m_genericArgsCount  - number of generic parameters for the class
3014 //                 m_pGenericArgs      - list of generic parameters for the class--these
3015 //                                       are the actual parameters
3016 // Return Value: the exact type handle for the type           
3017 //-----------------------------------------------------------------------------
3018 TypeHandle DacDbiInterfaceImpl::GetExactClassTypeHandle(DebuggerIPCE_ExpandedTypeData * pTopLevelTypeData,
3019                                                         ArgInfoList *                   pArgInfo)
3020 {
3021     Module *     pModule = pTopLevelTypeData->ClassTypeData.vmModule.GetDacPtr();
3022     int          argCount = pArgInfo->Count();
3023
3024     TypeHandle typeConstructor =
3025         ClassLoader::LookupTypeDefOrRefInModule(pModule, pTopLevelTypeData->ClassTypeData.metadataToken);
3026
3027     // If we can't find the class, throw the appropriate HR. Note: if the class is not a value class and
3028     // the class is also not restored, then we must pretend that the class is still not loaded. We are gonna let
3029     // unrestored value classes slide, though, and special case access to the class's parent below.
3030     if (typeConstructor.IsNull())
3031     {
3032         LOG((LF_CORDB, LL_INFO10000, "D::ETITTH: class isn't loaded.\n"));
3033         ThrowHR(CORDBG_E_CLASS_NOT_LOADED);
3034     }
3035
3036     // if there are no generic parameters, we already have the correct type handle
3037     if (argCount == 0)
3038     {
3039         return typeConstructor;
3040     }
3041
3042     // we have generic parameters--first validate we have a number consistent with the list
3043     // of parameters we received
3044     if ((unsigned int)argCount != typeConstructor.GetNumGenericArgs())
3045     {
3046         LOG((LF_CORDB, LL_INFO10000, 
3047             "D::ETITTH: wrong number of type parameters, %d given, %d expected\n", 
3048             argCount, typeConstructor.GetNumGenericArgs()));
3049         _ASSERTE((unsigned int)argCount == typeConstructor.GetNumGenericArgs());
3050         ThrowHR(E_FAIL);
3051     }
3052
3053     // now we allocate a list to store the type handles for each parameter
3054     S_UINT32 allocSize = S_UINT32(argCount) * S_UINT32(sizeof(TypeHandle));
3055     if (allocSize.IsOverflow())
3056     {
3057         ThrowHR(E_OUTOFMEMORY);
3058     }
3059
3060     NewHolder<TypeHandle> pInst(new TypeHandle[allocSize.Value()]);
3061
3062     // convert the type information for each parameter to its corresponding type handle
3063     // and store it in the list
3064     for (unsigned int i = 0; i < (unsigned int)argCount; i++)
3065     {
3066         pInst[i] = BasicTypeInfoToTypeHandle(&((*pArgInfo)[i]));
3067     }
3068
3069     // Finally, we find the type handle corresponding to this particular instantiation
3070     return FindLoadedInstantiation(typeConstructor.GetModule(), 
3071                                    typeConstructor.GetCl(), 
3072                                    argCount, 
3073                                    pInst);
3074
3075 } // DacDbiInterfaceImpl::GetExactClassTypeHandle
3076
3077 //-----------------------------------------------------------------------------
3078 // DacDbiInterfaceImpl::GetExactFnPtrTypeHandle
3079 // get an exact type handle for a FNPTR type
3080 // Arguments:
3081 //     input: pArgInfo - Contains the following information:
3082 //                 m_genericArgsCount  - number of generic parameters for the referent
3083 //                 m_pGenericArgs      - list of generic parameters for the referent--these
3084 //                                       are the actual parameters for the function signature
3085 // Return Value: the exact type handle for the type           
3086 //-----------------------------------------------------------------------------
3087 TypeHandle DacDbiInterfaceImpl::GetExactFnPtrTypeHandle(ArgInfoList * pArgInfo)
3088 {
3089     // allocate a list to store the type handles for each parameter
3090     S_UINT32 allocSize = S_UINT32(pArgInfo->Count()) * S_UINT32(sizeof(TypeHandle));
3091     if( allocSize.IsOverflow() )
3092     {
3093         ThrowHR(E_OUTOFMEMORY);
3094     }
3095     NewHolder<TypeHandle> pInst(new TypeHandle[allocSize.Value()]);
3096
3097     // convert the type information for each parameter to its corresponding type handle
3098     // and store it in the list
3099     for (int i = 0; i < pArgInfo->Count(); i++)
3100     {
3101         pInst[i] = BasicTypeInfoToTypeHandle(&((*pArgInfo)[i]));
3102     }
3103
3104     // find the type handle corresponding to this particular FNPTR
3105     return FindLoadedFnptrType(pArgInfo->Count(), pInst);
3106 } // DacDbiInterfaceImpl::GetExactFnPtrTypeHandle
3107
3108 //-----------------------------------------------------------------------------
3109 // DacDbiInterfaceImpl::BasicTypeInfoToTypeHandle
3110 // Convert basic type info for a type parameter that came from a top-level type to
3111 // the corresponding type handle. If the type parameter is an array or pointer
3112 // type, we simply extract the LS type handle from the VMPTR_TypeHandle that is
3113 // part of the type information. If the type parameter is a class or value type, 
3114 // we use the metadata token and domain file in the type info to look up the 
3115 // appropriate type handle. If the type parameter is any other types, we get the 
3116 // type handle by having the loader look up the type handle for the element type. 
3117 // Arguments: 
3118 //     input: pArgTypeData - basic type information for the type.
3119 // Return Value: the type handle for the type.
3120 //-----------------------------------------------------------------------------
3121 TypeHandle DacDbiInterfaceImpl::BasicTypeInfoToTypeHandle(DebuggerIPCE_BasicTypeData * pArgTypeData)
3122 {
3123     LOG((LF_CORDB, LL_INFO10000, 
3124         "D::BTITTH: expanding basic right-side type to left-side type, ELEMENT_TYPE: %d.\n", 
3125         pArgTypeData->elementType));
3126     TypeHandle typeHandle = TypeHandle();
3127
3128     switch (pArgTypeData->elementType)
3129     {
3130         case ELEMENT_TYPE_ARRAY:
3131         case ELEMENT_TYPE_SZARRAY:
3132         case ELEMENT_TYPE_PTR:
3133         case ELEMENT_TYPE_BYREF:
3134         case ELEMENT_TYPE_FNPTR:
3135             _ASSERTE(!pArgTypeData->vmTypeHandle.IsNull());
3136             typeHandle = TypeHandle::FromPtr(pArgTypeData->vmTypeHandle.GetDacPtr());
3137             break;
3138
3139         case ELEMENT_TYPE_CLASS:
3140         case ELEMENT_TYPE_VALUETYPE:
3141             typeHandle = GetClassOrValueTypeHandle(pArgTypeData);
3142             break;
3143         
3144         default:
3145             typeHandle = FindLoadedElementType(pArgTypeData->elementType);
3146             break;
3147     }
3148     if (typeHandle.IsNull())
3149     {
3150         ThrowHR(CORDBG_E_CLASS_NOT_LOADED);
3151     }
3152     return typeHandle;
3153 } // DacDbiInterfaceImpl::BasicTypeInfoToTypeHandle
3154
3155
3156 //-----------------------------------------------------------------------------
3157 // DacDbiInterfaceImpl::ExpandedTypeInfoToTypeHandle
3158 // Convert type information for a top-level type to an exact type handle. This
3159 // information includes information about the element type if the top-level type is
3160 // an array type, the referent if the top-level type is a pointer type, or actual
3161 // parameters if the top-level type is a generic class or value type.
3162 // Arguments: 
3163 //     input: pTopLevelTypeData - type information for the top-level type
3164 //            pArgInfo           - contains the following information:
3165 //                 m_genericArtsCount  - number of parameters 
3166 //                 m_pGenericArgs      - list of actual parameters
3167 // Return Value: the exact type handle corresponding to the type represented by 
3168 //            pTopLevelTypeData
3169 //-----------------------------------------------------------------------------
3170 TypeHandle DacDbiInterfaceImpl::ExpandedTypeInfoToTypeHandle(DebuggerIPCE_ExpandedTypeData * pTopLevelTypeData,
3171                                                              ArgInfoList *                   pArgInfo) 
3172 {
3173     WRAPPER_NO_CONTRACT;
3174
3175     LOG((LF_CORDB, LL_INFO10000, 
3176         "D::ETITTH: expanding right-side type to left-side type, ELEMENT_TYPE: %d.\n", 
3177         pData->elementType));
3178
3179     TypeHandle typeHandle = TypeHandle();
3180     // depending on the top-level type, get the type handle incorporating information about any type arguments
3181     switch (pTopLevelTypeData->elementType)
3182     {
3183         case ELEMENT_TYPE_ARRAY:
3184         case ELEMENT_TYPE_SZARRAY:
3185             typeHandle = GetExactArrayTypeHandle(pTopLevelTypeData, pArgInfo);
3186             break;
3187
3188         case ELEMENT_TYPE_PTR:
3189         case ELEMENT_TYPE_BYREF:
3190             typeHandle = GetExactPtrOrByRefTypeHandle(pTopLevelTypeData, pArgInfo);
3191             break;
3192
3193         case ELEMENT_TYPE_CLASS:
3194         case ELEMENT_TYPE_VALUETYPE:
3195             typeHandle = GetExactClassTypeHandle(pTopLevelTypeData, pArgInfo);
3196             break;
3197         case ELEMENT_TYPE_FNPTR:
3198             typeHandle = GetExactFnPtrTypeHandle(pArgInfo);
3199             break;
3200         default:
3201             typeHandle = FindLoadedElementType(pTopLevelTypeData->elementType);
3202             break;
3203     } // end switch (pData->elementType)
3204
3205     if (typeHandle.IsNull())
3206     {
3207         // This may fail because there are cases when a type can be used (and so visible to the 
3208         // debugger), but not yet loaded to the point of being available in the EETypeHashTable.  
3209         // For example, generic value types (without explicit constructors) may not need their 
3210         // exact instantiation type to be loaded in order to be used as a field of an object 
3211         // created on the heap 
3212         LOG((LF_CORDB, LL_INFO10000, "D::ETITTH: type isn't loaded.\n"));
3213         ThrowHR(CORDBG_E_CLASS_NOT_LOADED);
3214     }
3215     return typeHandle;
3216 } // DacDbiInterfaceImpl::ExpandedTypeInfoToTypeHandle
3217
3218 // ----------------------------------------------------------------------------
3219 // DacDbi API: GetThreadOrContextStaticAddress
3220 // Get the target field address of a context or thread local static. 
3221 // 
3222 // Notes: 
3223 // The address is  constant and could be cached.
3224 // 
3225 // If this is a context-static, the function uses the thread's current context.  
3226 // [This is important because it means that you can't lookup a context static 
3227 // unless you have a thread in that context. If anybody actually cared about contexts, 
3228 // we might have to revise this in the future] 
3229 // 
3230 // This can commonly fail, in which case, it will return NULL.
3231 // ----------------------------------------------------------------------------
3232 CORDB_ADDRESS DacDbiInterfaceImpl::GetThreadOrContextStaticAddress(VMPTR_FieldDesc vmField,
3233                                                                     VMPTR_Thread    vmRuntimeThread)
3234 {
3235     DD_ENTER_MAY_THROW;
3236
3237     Thread * pRuntimeThread = vmRuntimeThread.GetDacPtr();
3238     PTR_FieldDesc pFieldDesc = vmField.GetDacPtr();
3239     TADDR fieldAddress = NULL;
3240
3241     _ASSERTE(pRuntimeThread != NULL);
3242
3243     // Find out whether the field is thread local or context local and get its
3244     // address. 
3245     if (pFieldDesc->IsThreadStatic())
3246     {
3247         fieldAddress = pRuntimeThread->GetStaticFieldAddrNoCreate(pFieldDesc, NULL);
3248     }
3249 #ifdef FEATURE_REMOTING
3250     else if (pFieldDesc->IsContextStatic())
3251     {
3252         fieldAddress = PTR_TO_TADDR(pRuntimeThread->GetContext()->GetStaticFieldAddrNoCreate(pFieldDesc));
3253     }
3254 #endif
3255     else
3256     {
3257         // In case we have more special cases added later, this will allow us to notice the need to
3258         // update this function.
3259         ThrowHR(E_NOTIMPL);
3260     }
3261     return fieldAddress;
3262
3263 } // DacDbiInterfaceImpl::GetThreadOrContextStaticAddress
3264
3265     // Get the target field address of a collectible types static. 
3266 CORDB_ADDRESS DacDbiInterfaceImpl::GetCollectibleTypeStaticAddress(VMPTR_FieldDesc vmField,
3267                                                                    VMPTR_AppDomain vmAppDomain)
3268 {
3269     DD_ENTER_MAY_THROW;
3270
3271     AppDomain * pAppDomain = vmAppDomain.GetDacPtr();
3272     PTR_FieldDesc pFieldDesc = vmField.GetDacPtr();
3273     _ASSERTE(pAppDomain != NULL);
3274
3275     //
3276     // Verify this field is of the right type
3277     //
3278     if(!pFieldDesc->IsStatic() ||
3279        pFieldDesc->IsSpecialStatic())
3280     {
3281         _ASSERTE(!"BUG: Unsupported static field type for collectible types");
3282     }
3283
3284     //
3285     // Check that the data is available
3286     //
3287     /* TODO: Ideally we should be checking if the class is allocated first, however
3288              we don't appear to be doing this even for non-collectible statics and
3289              we have never seen an issue. 
3290     */
3291
3292     //
3293     // Get the address
3294     //
3295     PTR_VOID base = pFieldDesc->GetBaseInDomain(pAppDomain);
3296     if (base == PTR_NULL)
3297     {
3298         return PTR_HOST_TO_TADDR(NULL);
3299     }
3300
3301     //
3302     // Store the result and return
3303     //
3304     PTR_VOID addr = pFieldDesc->GetStaticAddressHandle(base);
3305     return PTR_TO_TADDR(addr);
3306
3307 } // DacDbiInterfaceImpl::GetCollectibleTypeStaticAddress
3308
3309 // DacDbi API: GetTypeHandleParams 
3310 // - gets the necessary data for a type handle, i.e. its type parameters, e.g. "String" and "List<int>" from the type handle
3311 //   for "Dict<String,List<int>>", and sends it back to the right side.
3312 // - pParams is allocated and initialized by this function
3313 // - This should not fail except for OOM 
3314 void DacDbiInterfaceImpl::GetTypeHandleParams(VMPTR_AppDomain  vmAppDomain,
3315                                               VMPTR_TypeHandle vmTypeHandle,
3316                                               TypeParamsList * pParams)
3317 {
3318     DD_ENTER_MAY_THROW
3319
3320     TypeHandle typeHandle = TypeHandle::FromPtr(vmTypeHandle.GetDacPtr());
3321     LOG((LF_CORDB, LL_INFO10000, "D::GTHP: getting type parameters for 0x%08x 0x%0x8.\n",
3322          vmAppDomain.GetDacPtr(), typeHandle.AsPtr()));
3323
3324
3325     // Find the class given its type handle.
3326     _ASSERTE(pParams->IsEmpty());
3327     pParams->Alloc(typeHandle.GetNumGenericArgs());
3328     
3329     // collect type information for each type parameter
3330     for (int i = 0; i < pParams->Count(); ++i)
3331     {
3332         VMPTR_TypeHandle thInst = VMPTR_TypeHandle::NullPtr();
3333         thInst.SetDacTargetPtr(typeHandle.GetInstantiation()[i].AsTAddr());
3334
3335         TypeHandleToExpandedTypeInfo(NoValueTypeBoxing, 
3336                                      vmAppDomain, 
3337                                      thInst,
3338                                      &((*pParams)[i]));
3339     }
3340
3341     LOG((LF_CORDB, LL_INFO10000, "D::GTHP: sending  result"));
3342 } // DacDbiInterfaceImpl::GetTypeHandleParams
3343
3344 //-----------------------------------------------------------------------------
3345 // DacDbi API: GetSimpleType
3346 // gets the metadata token and domain file corresponding to a simple type
3347 //-----------------------------------------------------------------------------
3348 void DacDbiInterfaceImpl::GetSimpleType(VMPTR_AppDomain    vmAppDomain, 
3349                                         CorElementType     simpleType, 
3350                                         mdTypeDef         *pMetadataToken,
3351                                         VMPTR_Module      *pVmModule,
3352                                         VMPTR_DomainFile  *pVmDomainFile)
3353 {
3354     DD_ENTER_MAY_THROW;
3355
3356     AppDomain *pAppDomain = vmAppDomain.GetDacPtr();
3357
3358     // if we fail to get either a valid type handle or module, we will want to send back
3359     // a NULL domain file too, so we'll to preinitialize this here. 
3360     _ASSERTE(pVmDomainFile != NULL);
3361     *pVmDomainFile = VMPTR_DomainFile::NullPtr();
3362     // FindLoadedElementType will return NULL if the type hasn't been loaded yet. 
3363     TypeHandle typeHandle =  FindLoadedElementType(simpleType);
3364
3365     if (typeHandle.IsNull())
3366     {
3367         ThrowHR(CORDBG_E_CLASS_NOT_LOADED);
3368     }
3369     else
3370     {
3371         _ASSERTE(pMetadataToken != NULL);
3372         *pMetadataToken = typeHandle.GetCl();
3373
3374         Module * pModule = typeHandle.GetModule();
3375         if (pModule == NULL)
3376             ThrowHR(CORDBG_E_TARGET_INCONSISTENT);
3377         
3378         pVmModule->SetHostPtr(pModule);
3379  
3380         if (pAppDomain)
3381         {
3382             pVmDomainFile->SetHostPtr(pModule->GetDomainFile(pAppDomain));
3383             if (pVmDomainFile->IsNull())
3384                 ThrowHR(CORDBG_E_TARGET_INCONSISTENT);
3385         }
3386     }
3387
3388     LOG((LF_CORDB, LL_INFO10000, "D::STI: sending result.\n"));
3389 } // DacDbiInterfaceImpl::GetSimpleType
3390
3391 BOOL DacDbiInterfaceImpl::IsExceptionObject(VMPTR_Object vmObject)
3392 {
3393     DD_ENTER_MAY_THROW;
3394
3395     Object* objPtr = vmObject.GetDacPtr();
3396     MethodTable* pMT = objPtr->GetMethodTable();
3397
3398     return IsExceptionObject(pMT);
3399 }
3400
3401 BOOL DacDbiInterfaceImpl::IsExceptionObject(MethodTable* pMT)
3402 {
3403     PTR_MethodTable pExMT = g_pExceptionClass;
3404
3405     TADDR targetMT = dac_cast<TADDR>(pMT);
3406     TADDR exceptionMT = dac_cast<TADDR>(pExMT);
3407
3408     do
3409     {
3410         if (targetMT == exceptionMT)
3411             return TRUE;
3412
3413         pMT = pMT->GetParentMethodTable();
3414         targetMT = dac_cast<TADDR>(pMT);
3415     } while (pMT);
3416
3417     return FALSE;
3418 }
3419
3420 void DacDbiInterfaceImpl::GetStackFramesFromException(VMPTR_Object vmObject, DacDbiArrayList<DacExceptionCallStackData>& dacStackFrames)
3421 {
3422     DD_ENTER_MAY_THROW;
3423
3424     PTR_Object objPtr = vmObject.GetDacPtr();
3425
3426 #ifdef _DEBUG
3427     // ensure we have an Exception object
3428     MethodTable* pMT = objPtr->GetMethodTable();
3429     _ASSERTE(IsExceptionObject(pMT));
3430 #endif
3431
3432     OBJECTREF objRef = ObjectToOBJECTREF(objPtr);
3433
3434     DebugStackTrace::GetStackFramesData stackFramesData;
3435
3436     stackFramesData.pDomain = NULL;
3437     stackFramesData.skip = 0;
3438     stackFramesData.NumFramesRequested = 0;
3439
3440     DebugStackTrace::GetStackFramesFromException(&objRef, &stackFramesData);
3441
3442     INT32 dacStackFramesLength = stackFramesData.cElements;
3443
3444     if (dacStackFramesLength > 0)
3445     {
3446         dacStackFrames.Alloc(dacStackFramesLength);
3447
3448         for (INT32 index = 0; index < dacStackFramesLength; ++index)
3449         {
3450             DebugStackTrace::DebugStackTraceElement const& currentElement = stackFramesData.pElements[index];
3451             DacExceptionCallStackData& currentFrame = dacStackFrames[index];
3452
3453             Module* pModule = currentElement.pFunc->GetModule();
3454             BaseDomain* pBaseDomain = currentElement.pFunc->GetAssembly()->GetDomain();
3455
3456             AppDomain* pDomain = NULL;
3457             DomainFile* pDomainFile = NULL;
3458
3459             if (pBaseDomain->IsSharedDomain())
3460                 pDomain = SystemDomain::System()->DefaultDomain();
3461             else
3462                 pDomain = pBaseDomain->AsAppDomain();
3463
3464             _ASSERTE(pDomain != NULL);
3465
3466             pDomainFile = pModule->FindDomainFile(pDomain);
3467             _ASSERTE(pDomainFile != NULL);
3468
3469             currentFrame.vmAppDomain.SetHostPtr(pDomain);
3470             currentFrame.vmDomainFile.SetHostPtr(pDomainFile);
3471             currentFrame.ip = currentElement.ip;
3472             currentFrame.methodDef = currentElement.pFunc->GetMemberDef();
3473 #if defined(FEATURE_EXCEPTIONDISPATCHINFO)
3474             currentFrame.isLastForeignExceptionFrame = currentElement.fIsLastFrameFromForeignStackTrace;
3475 #else
3476             // for CLRs lacking exception dispatch info just set it to 0
3477             currentFrame.isLastForeignExceptionFrame = 0;
3478 #endif
3479         }
3480     }
3481 }
3482
3483 #ifdef FEATURE_COMINTEROP
3484
3485 PTR_RCW GetRcwFromVmptrObject(VMPTR_Object vmObject)
3486 {
3487     PTR_RCW pRCW = NULL;
3488
3489     Object* objPtr = vmObject.GetDacPtr();
3490
3491     PTR_SyncBlock pSyncBlock = NULL;
3492     pSyncBlock = objPtr->PassiveGetSyncBlock();
3493     if (pSyncBlock == NULL)
3494         return pRCW;
3495
3496     PTR_InteropSyncBlockInfo pInfo = NULL;
3497     pInfo = pSyncBlock->GetInteropInfoNoCreate();
3498     if (pInfo == NULL)
3499         return pRCW;
3500
3501     pRCW = dac_cast<PTR_RCW>(pInfo->DacGetRawRCW());
3502
3503     return pRCW;
3504 }
3505
3506 #endif
3507
3508 BOOL DacDbiInterfaceImpl::IsRcw(VMPTR_Object vmObject)
3509 {
3510 #ifdef FEATURE_COMINTEROP
3511     DD_ENTER_MAY_THROW;
3512     return GetRcwFromVmptrObject(vmObject) != NULL;
3513 #else
3514     return FALSE;
3515 #endif // FEATURE_COMINTEROP
3516
3517 }
3518
3519 void DacDbiInterfaceImpl::GetRcwCachedInterfaceTypes(
3520                         VMPTR_Object vmObject, 
3521                         VMPTR_AppDomain vmAppDomain, 
3522                         BOOL bIInspectableOnly,
3523                         DacDbiArrayList<DebuggerIPCE_ExpandedTypeData> * pDacInterfaces)
3524 {
3525 #ifdef FEATURE_COMINTEROP
3526
3527     DD_ENTER_MAY_THROW;
3528
3529     Object* objPtr = vmObject.GetDacPtr();
3530
3531     InlineSArray<PTR_MethodTable, INTERFACE_ENTRY_CACHE_SIZE> rgMT;
3532
3533     PTR_RCW pRCW = GetRcwFromVmptrObject(vmObject);
3534     if (pRCW != NULL)
3535     {
3536         pRCW->GetCachedInterfaceTypes(bIInspectableOnly,  &rgMT);
3537
3538         pDacInterfaces->Alloc(rgMT.GetCount());
3539
3540         for (COUNT_T i = 0; i < rgMT.GetCount(); ++i)
3541         {
3542             // There is the possiblity that we'll get this far with a dump and not fail, but still
3543             // not be able to get full info for a particular param.
3544             EX_TRY_ALLOW_DATATARGET_MISSING_MEMORY_WITH_HANDLER
3545             {
3546                 // Fill in the struct using the current TypeHandle
3547                 VMPTR_TypeHandle vmTypeHandle = VMPTR_TypeHandle::NullPtr();
3548                 TypeHandle th = TypeHandle::FromTAddr(dac_cast<TADDR>(rgMT[i]));
3549                 vmTypeHandle.SetDacTargetPtr(th.AsTAddr());
3550                 TypeHandleToExpandedTypeInfo(NoValueTypeBoxing,
3551                                              vmAppDomain,
3552                                              vmTypeHandle,
3553                                              &((*pDacInterfaces)[i]));
3554             }
3555             EX_CATCH_ALLOW_DATATARGET_MISSING_MEMORY_WITH_HANDLER
3556             {
3557                 // On failure for a particular type, default it to NULL.
3558                 (*pDacInterfaces)[i].elementType = ELEMENT_TYPE_END;
3559             }
3560             EX_END_CATCH_ALLOW_DATATARGET_MISSING_MEMORY_WITH_HANDLER
3561
3562         }
3563
3564     }
3565     else
3566 #endif // FEATURE_COMINTEROP
3567     {
3568         pDacInterfaces->Alloc(0);
3569     }
3570 }
3571
3572 void DacDbiInterfaceImpl::GetRcwCachedInterfacePointers(
3573                     VMPTR_Object vmObject, 
3574                     BOOL bIInspectableOnly,
3575                     DacDbiArrayList<CORDB_ADDRESS> * pDacItfPtrs)
3576 {
3577 #ifdef FEATURE_COMINTEROP
3578
3579     DD_ENTER_MAY_THROW;
3580
3581     Object* objPtr = vmObject.GetDacPtr();
3582
3583     InlineSArray<TADDR, INTERFACE_ENTRY_CACHE_SIZE> rgUnks;
3584
3585     PTR_RCW pRCW = GetRcwFromVmptrObject(vmObject);
3586     if (pRCW != NULL)
3587     {
3588         pRCW->GetCachedInterfacePointers(bIInspectableOnly, &rgUnks);
3589
3590         pDacItfPtrs->Alloc(rgUnks.GetCount());
3591
3592         for (COUNT_T i = 0; i < rgUnks.GetCount(); ++i)
3593         {
3594             (*pDacItfPtrs)[i] = (CORDB_ADDRESS)(rgUnks[i]);
3595         }
3596
3597     }
3598     else
3599 #endif // FEATURE_COMINTEROP
3600     {
3601         pDacItfPtrs->Alloc(0);
3602     }
3603 }
3604
3605 void DacDbiInterfaceImpl::GetCachedWinRTTypesForIIDs(
3606                     VMPTR_AppDomain vmAppDomain, 
3607                                         DacDbiArrayList<GUID> & iids,
3608                                 OUT DacDbiArrayList<DebuggerIPCE_ExpandedTypeData> * pTypes)
3609 {
3610 #ifdef FEATURE_COMINTEROP
3611
3612     DD_ENTER_MAY_THROW;
3613
3614     AppDomain * pAppDomain = vmAppDomain.GetDacPtr();
3615     if (pAppDomain->IsUnloading())
3616     {
3617         return;
3618     }
3619
3620     {
3621         pTypes->Alloc(iids.Count());
3622
3623         for (int i = 0; i < iids.Count(); ++i)
3624         {
3625             // There is the possiblity that we'll get this far with a dump and not fail, but still
3626             // not be able to get full info for a particular param.
3627             EX_TRY_ALLOW_DATATARGET_MISSING_MEMORY_WITH_HANDLER
3628             {
3629                 PTR_MethodTable pMT = pAppDomain->LookupTypeByGuid(iids[i]);
3630
3631                 // Fill in the struct using the current TypeHandle
3632                 VMPTR_TypeHandle vmTypeHandle = VMPTR_TypeHandle::NullPtr();
3633                 TypeHandle th = TypeHandle::FromTAddr(dac_cast<TADDR>(pMT));
3634                 vmTypeHandle.SetDacTargetPtr(th.AsTAddr());
3635                 TypeHandleToExpandedTypeInfo(NoValueTypeBoxing,
3636                                              vmAppDomain,
3637                                              vmTypeHandle,
3638                                              &((*pTypes)[i]));
3639             }
3640             EX_CATCH_ALLOW_DATATARGET_MISSING_MEMORY_WITH_HANDLER
3641             {
3642                 // On failure for a particular type, default it to NULL.
3643                 (*pTypes)[i].elementType = ELEMENT_TYPE_END;
3644             }
3645             EX_END_CATCH_ALLOW_DATATARGET_MISSING_MEMORY_WITH_HANDLER
3646         }
3647     }
3648 #else // FEATURE_COMINTEROP
3649     {
3650         pTypes->Alloc(0);
3651     }
3652 #endif // FEATURE_COMINTEROP
3653 }
3654
3655 void DacDbiInterfaceImpl::GetCachedWinRTTypes(
3656                     VMPTR_AppDomain vmAppDomain, 
3657                     OUT DacDbiArrayList<GUID> * pGuids,
3658                     OUT DacDbiArrayList<DebuggerIPCE_ExpandedTypeData> * pTypes)
3659 {
3660 #ifdef FEATURE_COMINTEROP
3661
3662     DD_ENTER_MAY_THROW;
3663
3664     AppDomain * pAppDomain = vmAppDomain.GetDacPtr();
3665     if (pAppDomain->IsUnloading())
3666     {
3667         return;
3668     }
3669
3670     InlineSArray<PTR_MethodTable, 32> rgMT;
3671     InlineSArray<GUID, 32> rgGuid;
3672
3673     {
3674         pAppDomain->GetCachedWinRTTypes(&rgMT, &rgGuid, 0, NULL);
3675
3676         pTypes->Alloc(rgMT.GetCount());
3677         pGuids->Alloc(rgGuid.GetCount());
3678
3679         for (COUNT_T i = 0; i < rgMT.GetCount(); ++i)
3680         {
3681             // There is the possiblity that we'll get this far with a dump and not fail, but still
3682             // not be able to get full info for a particular param.
3683             EX_TRY_ALLOW_DATATARGET_MISSING_MEMORY_WITH_HANDLER
3684             {
3685                 // Fill in the struct using the current TypeHandle
3686                 VMPTR_TypeHandle vmTypeHandle = VMPTR_TypeHandle::NullPtr();
3687                 TypeHandle th = TypeHandle::FromTAddr(dac_cast<TADDR>(rgMT[i]));
3688                 vmTypeHandle.SetDacTargetPtr(th.AsTAddr());
3689                 TypeHandleToExpandedTypeInfo(NoValueTypeBoxing,
3690                                              vmAppDomain,
3691                                              vmTypeHandle,
3692                                              &((*pTypes)[i]));
3693             }
3694             EX_CATCH_ALLOW_DATATARGET_MISSING_MEMORY_WITH_HANDLER
3695             {
3696                 // On failure for a particular type, default it to NULL.
3697                 (*pTypes)[i].elementType = ELEMENT_TYPE_END;
3698             }
3699             EX_END_CATCH_ALLOW_DATATARGET_MISSING_MEMORY_WITH_HANDLER
3700             (*pGuids)[i] = rgGuid[i];
3701
3702         }
3703
3704     }
3705 #else // FEATURE_COMINTEROP
3706     {
3707         pTypes->Alloc(0);
3708     }
3709 #endif // FEATURE_COMINTEROP
3710 }
3711
3712 //-----------------------------------------------------------------------------
3713 // DacDbiInterfaceImpl::FindField
3714 // Finds information for a particular class field
3715 // Arguments:
3716 //     input: thApprox - type handle for the type to which the field belongs
3717 //            fldToken - metadata token for the field
3718 // Return Value: FieldDesc containing information for the field if found or NULL otherwise    
3719 //-----------------------------------------------------------------------------
3720 PTR_FieldDesc  DacDbiInterfaceImpl::FindField(TypeHandle thApprox, mdFieldDef fldToken)
3721 {
3722     EncApproxFieldDescIterator fdIterator(thApprox.GetMethodTable(),
3723                                           ApproxFieldDescIterator::ALL_FIELDS,
3724                                           FALSE);  // don't fixup EnC (we can't, we're stopped)
3725
3726     PTR_FieldDesc pCurrentFD;
3727
3728     while ((pCurrentFD = fdIterator.Next()) != NULL)
3729     {
3730         // We're looking for a specific fieldDesc, see if we got it.
3731         if (pCurrentFD->GetMemberDef() == fldToken)
3732         {
3733             return pCurrentFD;
3734         }
3735     }
3736
3737     // we never found it...
3738     return NULL;
3739 } // DacDbiInterfaceImpl::FindField
3740
3741 //-----------------------------------------------------------------------------
3742 // DacDbiInterfaceImpl::GetEnCFieldDesc
3743 // Get the FieldDesc corresponding to a particular EnC field token
3744 // Arguments: 
3745 //     input:  pEnCFieldInfo
3746 // Return Value: pointer to the FieldDesc that corresponds to the EnC field
3747 // Note: this function may throw
3748 //-----------------------------------------------------------------------------
3749 FieldDesc * DacDbiInterfaceImpl::GetEnCFieldDesc(const EnCHangingFieldInfo * pEnCFieldInfo)
3750 {
3751         FieldDesc * pFD = NULL;
3752
3753         DomainFile * pDomainFile = pEnCFieldInfo->GetObjectTypeData().vmDomainFile.GetDacPtr();
3754         Module     * pModule     = pDomainFile->GetModule();
3755
3756         // get the type handle for the object 
3757         TypeHandle typeHandle = ClassLoader::LookupTypeDefOrRefInModule(pModule, 
3758                                              pEnCFieldInfo->GetObjectTypeData().metadataToken);
3759         if (typeHandle == NULL)
3760         {
3761             ThrowHR(CORDBG_E_CLASS_NOT_LOADED);
3762         }
3763         // and find the field desc
3764         pFD = FindField(typeHandle, pEnCFieldInfo->GetFieldToken());
3765         if (pFD == NULL)
3766         {
3767             // FieldDesc is not yet available, so can't get EnC field info
3768             ThrowHR(CORDBG_E_ENC_HANGING_FIELD);
3769         }
3770         return pFD;
3771
3772 } // DacDbiInterfaceImpl::GetEnCFieldDesc
3773
3774 //-----------------------------------------------------------------------------
3775 // DacDbiInterfaceImpl::GetPtrToEnCField
3776 // Get the address of a field added with EnC.
3777 // Arguments:
3778 //     input: pFD           - field desc for the added field
3779 //            pEnCFieldInfo - information about the new field
3780 // Return Value: The field address if the field is available (i.e., it has been accessed)
3781 //               or NULL otherwise
3782 // Note: this function may throw
3783 //-----------------------------------------------------------------------------
3784 PTR_CBYTE DacDbiInterfaceImpl::GetPtrToEnCField(FieldDesc * pFD, const EnCHangingFieldInfo * pEnCFieldInfo)
3785 {
3786 #ifndef EnC_SUPPORTED
3787     _ASSERTE(!"Trying to get the address of an EnC field where EnC is not supported! ");
3788     return NULL;
3789 #else
3790
3791     PTR_EditAndContinueModule pEnCModule;
3792     DomainFile * pDomainFile = pEnCFieldInfo->GetObjectTypeData().vmDomainFile.GetDacPtr();
3793     Module     * pModule     = pDomainFile->GetModule();
3794
3795     // make sure we actually have an EditAndContinueModule
3796     _ASSERTE(pModule->IsEditAndContinueCapable());
3797     pEnCModule = dac_cast<PTR_EditAndContinueModule>(pModule);
3798
3799     // we should also have an EnCFieldDesc
3800     _ASSERTE(pFD->IsEnCNew());
3801     EnCFieldDesc * pEnCFieldDesc;
3802     pEnCFieldDesc = dac_cast<PTR_EnCFieldDesc>(pFD);
3803
3804     // If it hasn't been fixed up yet, then we can't return the pointer.
3805     if (pEnCFieldDesc->NeedsFixup())
3806     {
3807         ThrowHR(CORDBG_E_ENC_HANGING_FIELD);
3808     }
3809     // Get a pointer to the field
3810     PTR_CBYTE pORField = NULL;
3811
3812     PTR_Object pObject = pEnCFieldInfo->GetVmObject().GetDacPtr();
3813     pORField = pEnCModule->ResolveField(ObjectToOBJECTREF(pObject), 
3814                                         pEnCFieldDesc);   
3815
3816     // The field could be absent because the code hasn't accessed it yet. If so, we're not going to add it
3817     // since we can't allocate anyway.
3818     if (pORField == NULL)
3819     {
3820         ThrowHR(CORDBG_E_ENC_HANGING_FIELD);
3821     }
3822     return pORField;
3823 #endif // EnC_SUPPORTED
3824 } // DacDbiInterfaceImpl::GetPtrToEnCField
3825
3826 //-----------------------------------------------------------------------------
3827 // DacDbiInterfaceImpl::InitFieldData
3828 // Initialize information about a field added with EnC 
3829 // Arguments :
3830 //     input:  
3831 //             pFD           - provides information about whether the field is static,
3832 //                             the metadata token, etc.
3833 //             pORField      - provides the field address or offset
3834 //             pEnCFieldData - provides the offset to the fields of the object
3835 //     output: pFieldData    - initialized in accordance with the input information
3836 //-----------------------------------------------------------------------------
3837 void DacDbiInterfaceImpl::InitFieldData(const FieldDesc *           pFD, 
3838                                         const PTR_CBYTE             pORField, 
3839                                         const EnCHangingFieldInfo * pEnCFieldData, 
3840                                         FieldData *           pFieldData)
3841 {
3842
3843     pFieldData->ClearFields();
3844
3845     pFieldData->m_fFldIsStatic = (pFD->IsStatic() != 0);
3846     pFieldData->m_vmFieldDesc.SetHostPtr(pFD);
3847     pFieldData->m_fFldIsTLS = (pFD->IsThreadStatic() == TRUE);
3848     pFieldData->m_fldMetadataToken = pFD->GetMemberDef();
3849     pFieldData->m_fFldIsRVA = (pFD->IsRVA() == TRUE);
3850     pFieldData->m_fFldIsContextStatic = (pFD->IsContextStatic() == TRUE);
3851     pFieldData->m_fFldIsCollectibleStatic = FALSE;
3852     pFieldData->m_fFldStorageAvailable = true;
3853
3854     if (pFieldData->m_fFldIsStatic)
3855     {
3856         //EnC is only supported on regular static fields
3857         _ASSERTE(!pFieldData->m_fFldIsContextStatic);
3858         _ASSERTE(!pFieldData->m_fFldIsTLS);
3859         _ASSERTE(!pFieldData->m_fFldIsRVA);
3860
3861         // pORField contains the absolute address
3862         pFieldData->SetStaticAddress(PTR_TO_TADDR(pORField));
3863     }
3864     else
3865     {
3866         // fldInstanceOffset is computed to work correctly with GetFieldValue
3867         // which computes:
3868         // addr of pORField = object + pEnCFieldInfo->m_offsetToVars + offsetToFld
3869         pFieldData->SetInstanceOffset(PTR_TO_TADDR(pORField) - 
3870                                       (PTR_TO_TADDR(pEnCFieldData->GetVmObject().GetDacPtr()) + 
3871                                                    pEnCFieldData->GetOffsetToVars()));
3872     }
3873 } // DacDbiInterfaceImpl::InitFieldData
3874
3875
3876 // ----------------------------------------------------------------------------
3877 // DacDbi API: GetEnCHangingFieldInfo
3878 // After a class has been loaded, if a field has been added via EnC we'll have to jump through
3879 // some hoops to get at it (it hangs off the sync block or FieldDesc).
3880 //
3881 // GENERICS: TODO: this method will need to be modified if we ever support EnC on
3882 // generic classes.
3883 //-----------------------------------------------------------------------------
3884 void DacDbiInterfaceImpl::GetEnCHangingFieldInfo(const EnCHangingFieldInfo * pEnCFieldInfo,
3885                                                  FieldData *           pFieldData,
3886                                                  BOOL *                pfStatic)
3887 {
3888     DD_ENTER_MAY_THROW;
3889
3890     LOG((LF_CORDB, LL_INFO100000, "DDI::IEnCHFI: Obj:0x%x, objType"
3891         ":0x%x, offset:0x%x\n", pEnCFieldInfo->m_pObject, pEnCFieldInfo->m_objectTypeData.elementType,
3892         pEnCFieldInfo->m_offsetToVars));
3893
3894     FieldDesc *  pFD      = NULL;
3895     PTR_CBYTE    pORField = NULL;
3896
3897     pFD = GetEnCFieldDesc(pEnCFieldInfo);
3898     _ASSERTE(pFD->IsEnCNew()); // We shouldn't be here if it wasn't added to an
3899                                // already loaded class.
3900
3901 #ifdef EnC_SUPPORTED
3902     pORField = GetPtrToEnCField(pFD, pEnCFieldInfo);
3903 #else
3904     _ASSERTE(!"We shouldn't be here: EnC not supported");
3905 #endif // EnC_SUPPORTED
3906
3907     InitFieldData(pFD, pORField, pEnCFieldInfo, pFieldData);
3908     *pfStatic = (pFD->IsStatic() != 0);
3909
3910 } // DacDbiInterfaceImpl::GetEnCHangingFieldInfo
3911
3912 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
3913
3914
3915 void DacDbiInterfaceImpl::GetAssemblyFromDomainAssembly(VMPTR_DomainAssembly vmDomainAssembly, VMPTR_Assembly *vmAssembly)
3916 {
3917     DD_ENTER_MAY_THROW;
3918     
3919     _ASSERTE(vmAssembly != NULL);
3920
3921     DomainAssembly * pDomainAssembly = vmDomainAssembly.GetDacPtr();
3922     vmAssembly->SetHostPtr(pDomainAssembly->GetAssembly());
3923 }
3924
3925 // Determines whether the runtime security system has assigned full-trust to this assembly.
3926 BOOL DacDbiInterfaceImpl::IsAssemblyFullyTrusted(VMPTR_DomainAssembly vmDomainAssembly)
3927 {
3928     DD_ENTER_MAY_THROW;
3929
3930     DomainAssembly * pAssembly = vmDomainAssembly.GetDacPtr();
3931     IAssemblySecurityDescriptor * pSecDisc = pAssembly->GetSecurityDescriptor();
3932     return pSecDisc->IsFullyTrusted();
3933 }
3934
3935 // Get the full path and file name to the assembly's manifest module.
3936 BOOL DacDbiInterfaceImpl::GetAssemblyPath(
3937     VMPTR_Assembly  vmAssembly, 
3938     IStringHolder * pStrFilename)
3939 {    
3940     DD_ENTER_MAY_THROW;
3941
3942     // Get the manifest module for this assembly
3943     Assembly * pAssembly = vmAssembly.GetDacPtr();
3944     Module * pManifestModule = pAssembly->GetManifestModule();
3945
3946     // Get the path for the manifest module.
3947     // since we no longer support Win9x, we assume all paths will be in unicode format already
3948     const WCHAR * szPath = pManifestModule->GetPath().DacGetRawUnicode();
3949     HRESULT hrStatus = pStrFilename->AssignCopy(szPath);
3950     IfFailThrow(hrStatus);
3951      
3952     if(szPath == NULL || *szPath=='\0')
3953     {
3954         // The asembly has no (and will never have a) file name, but we didn't really fail
3955         return FALSE;
3956     }
3957
3958     return TRUE;
3959 }
3960
3961 // DAC/DBI API
3962 // Get a resolved type def from a type ref. The type ref may come from a module other than the 
3963 // referencing module. 
3964 void DacDbiInterfaceImpl::ResolveTypeReference(const TypeRefData * pTypeRefInfo,
3965                                                TypeRefData *       pTargetRefInfo)
3966 {   
3967     DD_ENTER_MAY_THROW;
3968     DomainFile * pDomainFile        = pTypeRefInfo->vmDomainFile.GetDacPtr();
3969     Module *     pReferencingModule = pDomainFile->GetCurrentModule();
3970     BOOL         fSuccess = FALSE;
3971
3972     // Resolve the type ref
3973     // g_pEEInterface->FindLoadedClass is almost what we want, but it isn't guaranteed to work if
3974     // the typeRef was originally loaded from a different assembly.  Also, we need to ensure that
3975     // we can resolve even unloaded types in fully loaded assemblies, so APIs such as 
3976     // LoadTypeDefOrRefThrowing aren't acceptable.
3977
3978     Module * pTargetModule = NULL;
3979     mdTypeDef targetTypeDef = mdTokenNil;
3980
3981     // The loader won't need to trigger a GC or throw because we've told it not to load anything
3982     ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE();
3983
3984     fSuccess = ClassLoader::ResolveTokenToTypeDefThrowing(pReferencingModule,
3985                                                           pTypeRefInfo->typeToken,
3986                                                           &pTargetModule,
3987                                                           &targetTypeDef,
3988                                                           Loader::SafeLookup   //don't load, no locks/allocations
3989                                                           );
3990     if (fSuccess)
3991     {
3992         _ASSERTE(pTargetModule != NULL);
3993         _ASSERTE( TypeFromToken(targetTypeDef) == mdtTypeDef );
3994
3995         AppDomain * pAppDomain = pDomainFile->GetAppDomain();
3996
3997         pTargetRefInfo->vmDomainFile.SetDacTargetPtr(PTR_HOST_TO_TADDR(pTargetModule->GetDomainFile(pAppDomain)));
3998         pTargetRefInfo->typeToken = targetTypeDef;
3999     }
4000     else
4001     {
4002         // failed - presumably because the target assembly isn't loaded                        
4003         ThrowHR(CORDBG_E_CLASS_NOT_LOADED);
4004     }
4005 } // DacDbiInterfaceImpl::ResolveTypeReference
4006
4007
4008 // Get the full path and file name to the module (if any).
4009 BOOL DacDbiInterfaceImpl::GetModulePath(VMPTR_Module vmModule, 
4010                                         IStringHolder *  pStrFilename)
4011 {
4012     DD_ENTER_MAY_THROW;
4013
4014     Module * pModule = vmModule.GetDacPtr();
4015     PEFile * pFile = pModule->GetFile();
4016     if (pFile != NULL)
4017     {
4018         if( !pFile->GetPath().IsEmpty() )
4019         {
4020             // Module has an on-disk path
4021             const WCHAR * szPath = pFile->GetPath().DacGetRawUnicode();
4022             if (szPath == NULL)
4023             {
4024                 szPath = pFile->GetModuleFileNameHint().DacGetRawUnicode();
4025                 if (szPath == NULL)
4026                 {
4027                     goto NoFileName;
4028                 }
4029             }
4030             IfFailThrow(pStrFilename->AssignCopy(szPath));
4031             return TRUE;
4032         }
4033     }
4034
4035 NoFileName:
4036     // no filename
4037     IfFailThrow(pStrFilename->AssignCopy(W("")));
4038     return FALSE;
4039 }
4040
4041 // Get the full path and file name to the ngen image for the module (if any).
4042 BOOL DacDbiInterfaceImpl::GetModuleNGenPath(VMPTR_Module vmModule, 
4043                                             IStringHolder *  pStrFilename)
4044 {
4045     DD_ENTER_MAY_THROW;
4046 #ifdef FEATURE_PREJIT
4047     Module * pModule = vmModule.GetDacPtr();
4048     PEFile * pFile = pModule->GetFile();
4049     if (pFile != NULL && pFile->HasNativeImage())
4050     {
4051         PEImage * pImage = pFile->GetPersistentNativeImage();
4052         if (pImage != NULL && pImage->IsFile())
4053         {
4054             // We have an on-disk ngen image.  Return the path.
4055             // since we no longer support Win9x, we assume all paths will be in unicode format already
4056             const WCHAR * szPath = pImage->GetPath().DacGetRawUnicode();
4057             if (szPath == NULL)
4058             {
4059                 szPath = pFile->GetModuleFileNameHint().DacGetRawUnicode();
4060                 if (szPath == NULL)
4061                 {
4062                     goto NoFileName;
4063                 }
4064             }
4065             IfFailThrow(pStrFilename->AssignCopy(szPath));
4066             return TRUE;
4067         }
4068     }
4069 #endif // FEATURE_PREJIT
4070
4071 NoFileName:
4072     // no ngen filename
4073     IfFailThrow(pStrFilename->AssignCopy(W("")));
4074     return FALSE;
4075 }
4076
4077 // Implementation of IDacDbiInterface::GetModuleSimpleName
4078 void DacDbiInterfaceImpl::GetModuleSimpleName(VMPTR_Module vmModule, IStringHolder * pStrFilename)
4079 {
4080     DD_ENTER_MAY_THROW;
4081
4082     _ASSERTE(pStrFilename != NULL);
4083     
4084     Module * pModule = vmModule.GetDacPtr();
4085     LPCUTF8 szNameUtf8 = pModule->GetSimpleName();
4086
4087     SString convert(SString::Utf8, szNameUtf8);
4088     IfFailThrow(pStrFilename->AssignCopy(convert.GetUnicode()));
4089 }
4090
4091 // Helper to intialize a TargetBuffer from a MemoryRange
4092 // 
4093 // Arguments:
4094 //    memoryRange - memory range.
4095 //    pTargetBuffer - required out parameter  to be initialized to value of memory range.
4096 //    
4097 // Notes:
4098 //    MemoryRange and TargetBuffer both conceptually describe a single contiguous buffer of memory in the
4099 //    target. MemoryRange is a VM structure, which can't bleed across the DacDbi boundary. TargetBuffer is 
4100 //    a DacDbi structure, which can cross the DacDbi boundary. 
4101 void InitTargetBufferFromMemoryRange(const MemoryRange memoryRange, TargetBuffer * pTargetBuffer)
4102 {
4103     SUPPORTS_DAC;
4104
4105     _ASSERTE(pTargetBuffer != NULL);
4106     PTR_CVOID p = memoryRange.StartAddress();
4107     CORDB_ADDRESS addr = PTR_TO_CORDB_ADDRESS(PTR_TO_TADDR(p));
4108
4109     _ASSERTE(memoryRange.Size() <= 0xffffffff);
4110     pTargetBuffer->Init(addr, (ULONG)memoryRange.Size());
4111 }
4112
4113 // Helper to intialize a TargetBuffer (host representation of target) from an SBuffer  (target)
4114 // 
4115 // Arguments:
4116 //   pBuffer - target pointer to a SBuffer structure. If pBuffer is NULL, then target buffer will be empty.
4117 //   pTargetBuffer - required out pointer to hold buffer description.
4118 //   
4119 // Notes:
4120 //   PTR_SBuffer and TargetBuffer are both semantically equivalent structures. They both are a pointer and length
4121 //   describing a buffer in the target address space. (SBufer also has ownership semantics, but for DAC's
4122 //   read-only nature, that doesn't matter).
4123 //   Neither of these will actually copy the target buffer into the host without explicit action.  
4124 //   The important difference is that TargetBuffer is a host datastructure and so easier to manipulate. 
4125 //   
4126 void InitTargetBufferFromTargetSBuffer(PTR_SBuffer pBuffer, TargetBuffer * pTargetBuffer)
4127 {
4128     SUPPORTS_DAC;
4129
4130     _ASSERTE(pTargetBuffer != NULL);
4131
4132     SBuffer * pBufferHost = pBuffer;
4133     if (pBufferHost == NULL)
4134     {
4135         pTargetBuffer->Clear();
4136         return;
4137     }
4138
4139     MemoryRange m = pBufferHost->DacGetRawBuffer();
4140     InitTargetBufferFromMemoryRange(m, pTargetBuffer);
4141 }
4142
4143
4144 // Implementation of IDacDbiInterface::GetMetadata
4145 void DacDbiInterfaceImpl::GetMetadata(VMPTR_Module vmModule, TargetBuffer * pTargetBuffer)
4146 {
4147     DD_ENTER_MAY_THROW;
4148
4149     pTargetBuffer->Clear();
4150
4151     Module     * pModule = vmModule.GetDacPtr();
4152
4153     // Target should only be asking about modules that are visible to debugger.
4154     _ASSERTE(pModule->IsVisibleToDebugger());
4155
4156     // For dynamic modules, metadata is stored as an eagerly-serialized buffer hanging off the Reflection Module.
4157     if (pModule->IsReflection())
4158     {
4159         // Here is the fetch.
4160         ReflectionModule * pReflectionModule = pModule->GetReflectionModule();
4161         InitTargetBufferFromTargetSBuffer(pReflectionModule->GetDynamicMetadataBuffer(), pTargetBuffer);
4162     }
4163     else
4164     {
4165         PEFile * pFile = pModule->GetFile();
4166
4167         // For non-dynamic modules, metadata is in the pe-image.            
4168         COUNT_T size;
4169         CORDB_ADDRESS address = PTR_TO_CORDB_ADDRESS(dac_cast<TADDR>(pFile->GetLoadedMetadata(&size)));
4170
4171         pTargetBuffer->Init(address, (ULONG) size);
4172     }
4173
4174     if (pTargetBuffer->IsEmpty())
4175     {
4176         // We never expect this to happen in a well-behaved scenario. But just in case.
4177         ThrowHR(CORDBG_E_MISSING_METADATA);
4178     }
4179     
4180 }
4181
4182 // Implementation of IDacDbiInterface::GetSymbolsBuffer
4183 void DacDbiInterfaceImpl::GetSymbolsBuffer(VMPTR_Module vmModule, TargetBuffer * pTargetBuffer, SymbolFormat * pSymbolFormat)
4184 {
4185     DD_ENTER_MAY_THROW;
4186
4187     pTargetBuffer->Clear();
4188     *pSymbolFormat = kSymbolFormatNone;
4189     
4190     Module * pModule = vmModule.GetDacPtr();
4191
4192     // Target should only be asking about modules that are visible to debugger.
4193     _ASSERTE(pModule->IsVisibleToDebugger());
4194
4195     PTR_CGrowableStream pStream = pModule->GetInMemorySymbolStream();
4196     if (pStream == NULL)
4197     {
4198         // Common case is to not have PDBs in-memory.
4199         return;
4200     }
4201
4202     const MemoryRange m = pStream->GetRawBuffer();
4203     if (m.Size() == 0)
4204     {
4205         // We may be prepared to store symbols (in some particular format) but none are there yet.
4206         // We treat this the same as not having any symbols above.
4207         return;
4208     }
4209     InitTargetBufferFromMemoryRange(m, pTargetBuffer);
4210
4211     // Set the symbol format appropriately
4212     ESymbolFormat symFormat = pModule->GetInMemorySymbolStreamFormat();
4213     switch (symFormat)
4214     {
4215     case eSymbolFormatPDB:
4216         *pSymbolFormat = kSymbolFormatPDB;
4217         break;
4218
4219     case eSymbolFormatILDB:
4220         *pSymbolFormat = kSymbolFormatILDB;
4221         break;
4222
4223     default:
4224         CONSISTENCY_CHECK_MSGF(false, "Unexpected symbol format");
4225         pTargetBuffer->Clear();
4226         ThrowHR(E_UNEXPECTED);
4227     }
4228 }
4229
4230
4231     
4232 void DacDbiInterfaceImpl::GetModuleForDomainFile(VMPTR_DomainFile vmDomainFile, OUT VMPTR_Module * pModule)
4233 {
4234     DD_ENTER_MAY_THROW;
4235     
4236     _ASSERTE(pModule != NULL);
4237     
4238     DomainFile * pDomainFile = vmDomainFile.GetDacPtr();
4239     pModule->SetHostPtr(pDomainFile->GetModule());
4240 }
4241
4242
4243 // Implement IDacDbiInterface::GetDomainFileData
4244 void DacDbiInterfaceImpl::GetDomainFileData(VMPTR_DomainFile vmDomainFile, DomainFileInfo * pData)
4245 {
4246     DD_ENTER_MAY_THROW;
4247
4248     _ASSERTE(pData != NULL);
4249
4250     ZeroMemory(pData, sizeof(*pData));
4251
4252     DomainFile * pDomainFile  = vmDomainFile.GetDacPtr();
4253     AppDomain  * pAppDomain   = pDomainFile->GetAppDomain();
4254     
4255     // @dbgtodo - is this efficient DAC usage (perhaps a dac-cop rule)? Are we round-tripping the pointer?
4256     // Should we have a GetDomainAssembly() that returns a PTR_DomainAssembly?
4257     pData->vmDomainAssembly.SetHostPtr(pDomainFile->GetDomainAssembly()); 
4258     pData->vmAppDomain.SetHostPtr(pAppDomain);
4259 }
4260
4261 // Implement IDacDbiInterface::GetModuleData
4262 void DacDbiInterfaceImpl::GetModuleData(VMPTR_Module vmModule, ModuleInfo * pData)
4263 {
4264     DD_ENTER_MAY_THROW;
4265
4266     _ASSERTE(pData != NULL);
4267
4268     ZeroMemory(pData, sizeof(*pData));
4269     
4270     Module     * pModule      = vmModule.GetDacPtr();
4271     PEFile     * pFile        = pModule->GetFile();
4272
4273     pData->vmPEFile.SetHostPtr(pFile);
4274     pData->vmAssembly.SetHostPtr(pModule->GetAssembly());
4275
4276     // Is it dynamic?
4277     BOOL fIsDynamic = pModule->IsReflection();
4278     pData->fIsDynamic = fIsDynamic;
4279    
4280     // Get PE BaseAddress and Size
4281     // For dynamic modules, these are 0. Else, 
4282     pData->pPEBaseAddress = NULL;
4283     pData->nPESize = 0;
4284     
4285     if (!fIsDynamic)
4286     {
4287         COUNT_T size = 0;
4288         pData->pPEBaseAddress = PTR_TO_TADDR(pFile->GetDebuggerContents(&size));    
4289         pData->nPESize = (ULONG) size;
4290     }
4291    
4292     // In-memory is determined by whether the module has a filename.    
4293     pData->fInMemory = FALSE;
4294     if (pFile != NULL)
4295     {
4296         pData->fInMemory = pFile->GetPath().IsEmpty();
4297     }
4298 }
4299
4300
4301 // Enumerate all AppDomains in the process.
4302 void DacDbiInterfaceImpl::EnumerateAppDomains(
4303     FP_APPDOMAIN_ENUMERATION_CALLBACK fpCallback, 
4304     void * pUserData)
4305 {
4306     DD_ENTER_MAY_THROW;
4307     
4308     _ASSERTE(fpCallback != NULL);
4309
4310     // Only include active appdomains in the enumeration. 
4311     // This includes appdomains sent before the AD load event, 
4312     // and does not include appdomains that are in shutdown after the AD exit event.
4313     const BOOL bOnlyActive = TRUE;
4314     AppDomainIterator iterator(bOnlyActive); 
4315
4316     while(iterator.Next())
4317     {
4318         // It's critical that we don't yield appdomains after the unload event has been sent.
4319         // See code:IDacDbiInterface#Enumeration for details.
4320         AppDomain * pAppDomain = iterator.GetDomain(); 
4321         if (pAppDomain->IsUnloading())
4322         {
4323             continue;
4324         }
4325         
4326         VMPTR_AppDomain vmAppDomain = VMPTR_AppDomain::NullPtr();
4327         vmAppDomain.SetHostPtr(pAppDomain);
4328
4329         fpCallback(vmAppDomain, pUserData);
4330     }
4331 }
4332
4333 // Enumerate all Assemblies in an appdomain. 
4334 void  DacDbiInterfaceImpl::EnumerateAssembliesInAppDomain(
4335     VMPTR_AppDomain vmAppDomain,
4336     FP_ASSEMBLY_ENUMERATION_CALLBACK fpCallback,
4337     void * pUserData
4338 )
4339 {
4340     DD_ENTER_MAY_THROW;
4341     
4342     _ASSERTE(fpCallback != NULL);
4343     
4344     // Iterate through all Assemblies (including shared) in the appdomain.
4345     AppDomain::AssemblyIterator iterator;
4346
4347     // If the containing appdomain is unloading, then don't enumerate any assemblies
4348     // in the domain. This is to enforce rules at code:IDacDbiInterface#Enumeration.
4349     // See comment in code:DacDbiInterfaceImpl::EnumerateModulesInAssembly code for details.
4350     AppDomain * pAppDomain = vmAppDomain.GetDacPtr();
4351     if (pAppDomain->IsUnloading())
4352     {
4353         return;
4354     }
4355
4356     // Pass the magical flags to the loader enumerator to get all Execution-only assemblies.
4357     iterator = pAppDomain->IterateAssembliesEx((AssemblyIterationFlags)(kIncludeLoading | kIncludeLoaded | kIncludeExecution));
4358     CollectibleAssemblyHolder<DomainAssembly *> pDomainAssembly;
4359     
4360     while (iterator.Next(pDomainAssembly.This()))
4361     {
4362         if (!pDomainAssembly->IsVisibleToDebugger())
4363         {
4364             continue;
4365         }
4366
4367         VMPTR_DomainAssembly vmDomainAssembly = VMPTR_DomainAssembly::NullPtr();
4368         vmDomainAssembly.SetHostPtr(pDomainAssembly);
4369
4370         fpCallback(vmDomainAssembly, pUserData);
4371     }
4372 }
4373
4374 // Implementation of IDacDbiInterface::EnumerateModulesInAssembly,
4375 // Enumerate all the modules (non-resource) in an assembly.
4376 void DacDbiInterfaceImpl::EnumerateModulesInAssembly(
4377     VMPTR_DomainAssembly vmAssembly,
4378     FP_MODULE_ENUMERATION_CALLBACK fpCallback,
4379     void * pUserData)
4380 {
4381     DD_ENTER_MAY_THROW;
4382
4383     _ASSERTE(fpCallback != NULL);
4384
4385     DomainAssembly * pDomainAssembly = vmAssembly.GetDacPtr();
4386
4387     // If the appdomain or assembly containing this module is unloading, then don't enumerate any modules.
4388     // in the domain. This is to enforce rules at code:IDacDbiInterface#Enumeration, specifically
4389     // that new objects are not available after the unload event is sent. 
4390     // This is a very large hammer, but since modules only unload with appdomains or assemblies, we're 
4391     // erring on the side of safety. If the debugger happens to have VMPTR_DomainFiles (CordbModules) already
4392     // cached, it can still use those until the unload event. 
4393     if (pDomainAssembly->IsUnloading())
4394     {
4395         return;
4396     }
4397     
4398
4399     // If the domain is not yet fully-loaded, don't advertise it yet.
4400     // It's not ready to be inspected. 
4401     DomainModuleIterator iterator =  pDomainAssembly->IterateModules(kModIterIncludeLoaded);
4402     
4403     while (iterator.Next())
4404     {
4405         DomainFile * pDomainFile = iterator.GetDomainFile();
4406
4407         // Debugger isn't notified of Resource / Inspection-only modules.
4408         if (!pDomainFile->GetModule()->IsVisibleToDebugger())
4409         {
4410             continue;
4411         }
4412
4413         _ASSERTE(pDomainFile->IsLoaded());        
4414         
4415         VMPTR_DomainFile vmDomainFile = VMPTR_DomainFile::NullPtr();
4416         vmDomainFile.SetHostPtr(pDomainFile);
4417
4418         fpCallback(vmDomainFile, pUserData);
4419     }
4420 }
4421
4422 // Implementation of IDacDbiInterface::ResolveAssembly
4423 // Returns NULL if not found.
4424 VMPTR_DomainAssembly DacDbiInterfaceImpl::ResolveAssembly(
4425     VMPTR_DomainFile vmScope, 
4426     mdToken tkAssemblyRef)
4427 {
4428     DD_ENTER_MAY_THROW;
4429
4430
4431     DomainFile * pDomainFile  = vmScope.GetDacPtr();
4432     AppDomain  * pAppDomain   = pDomainFile->GetAppDomain();
4433     Module     * pModule      = pDomainFile->GetCurrentModule();
4434
4435     VMPTR_DomainAssembly vmDomainAssembly = VMPTR_DomainAssembly::NullPtr();
4436
4437     Assembly * pAssembly = pModule->LookupAssemblyRef(tkAssemblyRef);
4438     if (pAssembly != NULL)
4439     {
4440         DomainAssembly * pDomainAssembly = pAssembly->FindDomainAssembly(pAppDomain);
4441         vmDomainAssembly.SetHostPtr(pDomainAssembly);
4442     }
4443     return vmDomainAssembly;
4444 }
4445
4446 // When stopped at an event, request a synchronization. 
4447 // See DacDbiInterface.h for full comments
4448 void DacDbiInterfaceImpl::RequestSyncAtEvent()
4449 {
4450     DD_ENTER_MAY_THROW;
4451
4452     // To request a sync, we just need to set g_pDebugger->m_RSRequestedSync high. 
4453     if (g_pDebugger != NULL)
4454     {        
4455         TADDR addr = PTR_HOST_MEMBER_TADDR(Debugger, g_pDebugger, m_RSRequestedSync);
4456         
4457         BOOL fTrue = TRUE;
4458         SafeWriteStructOrThrow<BOOL>(addr, &fTrue);
4459
4460     }    
4461 }
4462
4463 HRESULT DacDbiInterfaceImpl::SetSendExceptionsOutsideOfJMC(BOOL sendExceptionsOutsideOfJMC)
4464 {
4465     DD_ENTER_MAY_THROW
4466
4467     HRESULT hr = S_OK;
4468     EX_TRY
4469     {
4470         if (g_pDebugger != NULL)
4471         {
4472             TADDR addr = PTR_HOST_MEMBER_TADDR(Debugger, g_pDebugger, m_sendExceptionsOutsideOfJMC);
4473             SafeWriteStructOrThrow<BOOL>(addr, &sendExceptionsOutsideOfJMC);
4474         }
4475     }
4476     EX_CATCH_HRESULT(hr);
4477     return hr;
4478 }
4479
4480 // Notify the debuggee that a debugger attach is pending.
4481 // See DacDbiInterface.h for full comments
4482 void DacDbiInterfaceImpl::MarkDebuggerAttachPending()
4483 {
4484     DD_ENTER_MAY_THROW;
4485
4486     if (g_pDebugger != NULL)
4487     {
4488         DWORD flags = g_CORDebuggerControlFlags;
4489         flags |= DBCF_PENDING_ATTACH;
4490
4491         // Uses special DAC writing. PTR_TO_TADDR doesn't fetch for globals.
4492         // @dbgtodo  dac support - the exact mechanism of writing to the target needs to be flushed out,
4493         // especially as it relates to DAC cop and enforcing undac-ized writes.
4494         g_CORDebuggerControlFlags = flags;
4495     }
4496     else
4497     {
4498         // Caller should have gauranteed that the LS is loaded.
4499         // If we're detaching, then don't throw because we don't care.
4500         ThrowHR(CORDBG_E_NOTREADY);
4501     }
4502 }
4503
4504
4505 // Notify the debuggee that a debugger is attached.
4506 // See DacDbiInterface.h for full comments
4507 void DacDbiInterfaceImpl::MarkDebuggerAttached(BOOL fAttached)
4508 {
4509     DD_ENTER_MAY_THROW;
4510
4511     if (g_pDebugger != NULL)
4512     {
4513         // To be attached, we need to set the following
4514         //   g_CORDebuggerControlFlags |= DBCF_ATTACHED;
4515         // To detach (if !fAttached), we need to do the opposite.
4516
4517         DWORD flags = g_CORDebuggerControlFlags;
4518         if (fAttached) 
4519         {
4520             flags |= DBCF_ATTACHED;
4521         }
4522         else
4523         {
4524             flags &= ~ (DBCF_ATTACHED | DBCF_PENDING_ATTACH);
4525         }
4526
4527         // Uses special DAC writing. PTR_TO_TADDR doesn't fetch for globals.
4528         // @dbgtodo  dac support - the exact mechanism of writing to the target needs to be flushed out,
4529         // especially as it relates to DAC cop and enforcing undac-ized writes.
4530         g_CORDebuggerControlFlags = flags;
4531     }
4532     else if (fAttached)
4533     {
4534         // Caller should have gauranteed that the LS is loaded.
4535         // If we're detaching, then don't throw because we don't care.
4536         ThrowHR(CORDBG_E_NOTREADY);
4537     }
4538
4539 }
4540
4541 #ifdef FEATURE_INCLUDE_ALL_INTERFACES
4542 // Enumerate all the Connections in the process.
4543 void DacDbiInterfaceImpl::EnumerateConnections(FP_CONNECTION_CALLBACK fpCallback, void * pUserData)
4544 {
4545     DD_ENTER_MAY_THROW;
4546
4547     ConnectionNameHashEntry * pConnection;
4548     
4549     HASHFIND hashfind;
4550
4551     pConnection = CCLRDebugManager::FindFirst(&hashfind);
4552     while (pConnection)
4553     {    
4554         DWORD id = pConnection->m_dwConnectionId;
4555         LPCWSTR pName = pConnection->m_pwzName;
4556         
4557         fpCallback(id, pName, pUserData);
4558
4559         // now get the next connection record
4560         pConnection = CCLRDebugManager::FindNext(&hashfind);
4561     }
4562 }
4563 #endif
4564
4565
4566 // Enumerate all threads in the process. 
4567 void DacDbiInterfaceImpl::EnumerateThreads(FP_THREAD_ENUMERATION_CALLBACK fpCallback, void * pUserData)
4568 {
4569     DD_ENTER_MAY_THROW;
4570     
4571     if (ThreadStore::s_pThreadStore == NULL)
4572     {
4573         return;
4574     }
4575
4576     Thread *pThread = ThreadStore::GetThreadList(NULL);
4577     
4578     while (pThread != NULL)
4579     {
4580
4581         // Don't want to publish threads via enumeration before they're ready to be inspected.
4582         // Use the same window that we used in whidbey.
4583         Thread::ThreadState threadState = pThread->GetSnapshotState();
4584         if (!((IsThreadMarkedDeadWorker(pThread)) || (threadState & Thread::TS_Unstarted)))
4585         {
4586             VMPTR_Thread vmThread = VMPTR_Thread::NullPtr();
4587             vmThread.SetHostPtr(pThread);
4588             fpCallback(vmThread, pUserData);
4589         }
4590
4591         pThread = ThreadStore::GetThreadList(pThread);
4592     }    
4593 }
4594
4595 // public implementation of IsThreadMarkedDead
4596 bool DacDbiInterfaceImpl::IsThreadMarkedDead(VMPTR_Thread vmThread)
4597 {
4598     DD_ENTER_MAY_THROW;
4599     Thread * pThread = vmThread.GetDacPtr();
4600     return IsThreadMarkedDeadWorker(pThread);
4601 }
4602
4603 // Private worker for IsThreadMarkedDead
4604 // 
4605 // Arguments:
4606 //    pThread - valid thread to check if dead
4607 //    
4608 // Returns: 
4609 //    true iff thread is marked as dead.
4610 //    
4611 // Notes:
4612 //    This is an internal method that skips public validation.
4613 //    See code:IDacDbiInterface::#IsThreadMarkedDead for purpose.
4614 bool DacDbiInterfaceImpl::IsThreadMarkedDeadWorker(Thread * pThread)
4615 {
4616     _ASSERTE(pThread != NULL);
4617
4618     Thread::ThreadState threadState = pThread->GetSnapshotState();
4619
4620     bool fIsDead = (threadState & Thread::TS_Dead) != 0;
4621
4622     return fIsDead;
4623 }
4624
4625
4626 // Return the handle of the specified thread.
4627 HANDLE DacDbiInterfaceImpl::GetThreadHandle(VMPTR_Thread vmThread)
4628 {
4629     DD_ENTER_MAY_THROW;
4630
4631     Thread * pThread = vmThread.GetDacPtr();
4632     return pThread->GetThreadHandle();
4633 }
4634
4635 // Return the object handle for the managed Thread object corresponding to the specified thread.
4636 VMPTR_OBJECTHANDLE DacDbiInterfaceImpl::GetThreadObject(VMPTR_Thread vmThread)
4637 {
4638     DD_ENTER_MAY_THROW;
4639
4640     Thread * pThread = vmThread.GetDacPtr();
4641     Thread::ThreadState threadState = pThread->GetSnapshotState();
4642
4643     if ( (threadState & Thread::TS_Dead) ||
4644          (threadState & Thread::TS_Unstarted) ||
4645          (threadState & Thread::TS_Detached) ||
4646          g_fProcessDetach )
4647     {
4648         ThrowHR(CORDBG_E_BAD_THREAD_STATE);
4649     }
4650     else
4651     {
4652         VMPTR_OBJECTHANDLE vmObjHandle = VMPTR_OBJECTHANDLE::NullPtr();
4653         vmObjHandle.SetDacTargetPtr(pThread->GetExposedObjectHandleForDebugger());
4654         return vmObjHandle;
4655     }
4656 }
4657
4658 // Set and reset the TSNC_DebuggerUserSuspend bit on the state of the specified thread
4659 // according to the CorDebugThreadState.
4660 void DacDbiInterfaceImpl::SetDebugState(VMPTR_Thread        vmThread,
4661                                         CorDebugThreadState debugState)
4662 {
4663     DD_ENTER_MAY_THROW;
4664
4665     Thread * pThread = vmThread.GetDacPtr();
4666
4667     // update the field on the host copy
4668     if (debugState == THREAD_SUSPEND)
4669     {
4670         pThread->SetThreadStateNC(Thread::TSNC_DebuggerUserSuspend);
4671     }
4672     else if (debugState == THREAD_RUN)
4673     {
4674         pThread->ResetThreadStateNC(Thread::TSNC_DebuggerUserSuspend);
4675     }
4676     else
4677     {
4678         ThrowHR(E_INVALIDARG);
4679     }
4680
4681     // update the field on the target copy
4682     TADDR taThreadState = PTR_HOST_MEMBER_TADDR(Thread, pThread, m_StateNC);
4683     SafeWriteStructOrThrow<Thread::ThreadStateNoConcurrency>(taThreadState, &(pThread->m_StateNC));
4684 }
4685
4686 // Gets the debugger unhandled exception threadstate flag
4687 BOOL DacDbiInterfaceImpl::HasUnhandledException(VMPTR_Thread vmThread)
4688 {
4689     DD_ENTER_MAY_THROW;
4690
4691     Thread * pThread = vmThread.GetDacPtr();
4692
4693     // some managed exceptions don't have any underlying
4694     // native exception processing going on. They just consist
4695     // of a managed throwable that we have stashed away followed
4696     // by a debugger notification and some form of failfast.
4697     // Everything that comes through EEFatalError is in this category
4698     if(pThread->IsLastThrownObjectUnhandled())
4699     {
4700         return TRUE;
4701     }
4702
4703     // most managed exceptions are just a throwable bound to a
4704     // native exception. In that case this handle will be non-null
4705     OBJECTHANDLE ohException = pThread->GetThrowableAsHandle();
4706     if (ohException != NULL)
4707     {
4708         // during the UEF we set the unhandled bit, if it is set the exception
4709         // was unhandled
4710         // however if the exception has intercept info then we consider it handled
4711         // again
4712         return pThread->GetExceptionState()->GetFlags()->IsUnhandled() &&
4713             !(pThread->GetExceptionState()->GetFlags()->DebuggerInterceptInfo());
4714     }
4715
4716     return FALSE;
4717 }
4718
4719 // Return the user state of the specified thread.
4720 CorDebugUserState DacDbiInterfaceImpl::GetUserState(VMPTR_Thread vmThread)
4721 {
4722     DD_ENTER_MAY_THROW;
4723
4724     UINT result = 0;
4725     result = GetPartialUserState(vmThread);
4726
4727     if (!IsThreadAtGCSafePlace(vmThread))
4728     {
4729         result |= USER_UNSAFE_POINT;
4730     }
4731
4732     return (CorDebugUserState)result;
4733 }
4734
4735
4736 // Return the connection ID of the specified thread.
4737 CONNID DacDbiInterfaceImpl::GetConnectionID(VMPTR_Thread vmThread)
4738 {
4739     DD_ENTER_MAY_THROW;
4740
4741     Thread * pThread = vmThread.GetDacPtr();
4742     return pThread->GetConnectionId();
4743 }
4744
4745 // Return the task ID of the specified thread.
4746 TASKID DacDbiInterfaceImpl::GetTaskID(VMPTR_Thread vmThread)
4747 {
4748     DD_ENTER_MAY_THROW;
4749
4750     Thread * pThread = vmThread.GetDacPtr();
4751     return pThread->GetTaskId();
4752 }
4753
4754 // Return the OS thread ID of the specified thread
4755 DWORD DacDbiInterfaceImpl::TryGetVolatileOSThreadID(VMPTR_Thread vmThread)
4756 {
4757     DD_ENTER_MAY_THROW;
4758
4759     Thread * pThread = vmThread.GetDacPtr();
4760     _ASSERTE(pThread != NULL);
4761
4762     DWORD dwThreadId = pThread->GetOSThreadIdForDebugger();
4763
4764     // If the thread ID is a the magical cookie value, then this is really
4765     // a switched out thread and doesn't have an OS tid. In that case, the
4766     // DD contract is to return 0 (a much more sane value)
4767     const DWORD dwSwitchedOutThreadId = SWITCHED_OUT_FIBER_OSID;
4768     if (dwThreadId == dwSwitchedOutThreadId)
4769     {
4770         return 0;
4771     }
4772     return dwThreadId;
4773 }
4774
4775 // Return the unique thread ID of the specified thread.
4776 DWORD DacDbiInterfaceImpl::GetUniqueThreadID(VMPTR_Thread vmThread)
4777 {
4778     DD_ENTER_MAY_THROW;
4779
4780     Thread * pThread = vmThread.GetDacPtr();
4781     _ASSERTE(pThread != NULL);
4782
4783     if (CLRTaskHosted())
4784     {
4785         return pThread->GetThreadId();
4786     }
4787     else
4788     {
4789         return pThread->GetOSThreadId();
4790     }
4791 }
4792
4793 // Return the object handle to the managed Exception object of the current exception
4794 // on the specified thread.  The return value could be NULL if there is no current exception.
4795 VMPTR_OBJECTHANDLE DacDbiInterfaceImpl::GetCurrentException(VMPTR_Thread vmThread)
4796 {
4797     DD_ENTER_MAY_THROW;
4798
4799     Thread * pThread = vmThread.GetDacPtr();
4800
4801     // OBJECTHANDLEs are really just TADDRs.
4802     OBJECTHANDLE ohException = pThread->GetThrowableAsHandle();        // ohException can be NULL
4803
4804     if (ohException == NULL)
4805     {
4806         if (pThread->IsLastThrownObjectUnhandled())
4807         {
4808             ohException = pThread->LastThrownObjectHandle();
4809         }
4810     }
4811
4812     VMPTR_OBJECTHANDLE vmObjHandle;
4813     vmObjHandle.SetDacTargetPtr(ohException);
4814     return vmObjHandle;
4815 }
4816
4817 // Return the object handle to the managed object for a given CCW pointer.
4818 VMPTR_OBJECTHANDLE DacDbiInterfaceImpl::GetObjectForCCW(CORDB_ADDRESS ccwPtr)
4819 {
4820     DD_ENTER_MAY_THROW;
4821
4822     OBJECTHANDLE ohCCW = NULL;
4823
4824 #ifdef FEATURE_COMINTEROP
4825     ComCallWrapper *pCCW = DACGetCCWFromAddress(ccwPtr);
4826     if (pCCW)
4827     {
4828         ohCCW = pCCW->GetObjectHandle();
4829     }
4830 #endif
4831
4832     VMPTR_OBJECTHANDLE vmObjHandle;
4833     vmObjHandle.SetDacTargetPtr(ohCCW);
4834     return vmObjHandle;
4835 }
4836
4837 // Return the object handle to the managed CustomNotification object of the current notification
4838 // on the specified thread.  The return value could be NULL if there is no current notification.
4839 // Arguments:
4840 //     input: vmThread - the thread on which the notification occurred
4841 // Return value: object handle for the current notification (if any) on the thread. This will return non-null
4842 // if and only if we are currently inside a CustomNotification Callback (or a dump was generated while in this 
4843 // callback)
4844 // 
4845 VMPTR_OBJECTHANDLE DacDbiInterfaceImpl::GetCurrentCustomDebuggerNotification(VMPTR_Thread vmThread)
4846 {
4847     DD_ENTER_MAY_THROW;
4848
4849     Thread * pThread = vmThread.GetDacPtr();
4850
4851     // OBJECTHANDLEs are really just TADDRs.
4852     OBJECTHANDLE ohNotification = pThread->GetThreadCurrNotification();        // ohNotification can be NULL
4853
4854     VMPTR_OBJECTHANDLE vmObjHandle;
4855     vmObjHandle.SetDacTargetPtr(ohNotification);
4856     return vmObjHandle;
4857 }
4858
4859 // Return the current appdomain the specified thread is in.
4860 VMPTR_AppDomain DacDbiInterfaceImpl::GetCurrentAppDomain(VMPTR_Thread vmThread)
4861 {
4862     DD_ENTER_MAY_THROW;
4863
4864     Thread *    pThread    = vmThread.GetDacPtr();
4865     AppDomain * pAppDomain = pThread->GetDomain();
4866
4867     if (pAppDomain == NULL)
4868     {
4869         ThrowHR(E_FAIL);
4870     }
4871
4872     VMPTR_AppDomain vmAppDomain = VMPTR_AppDomain::NullPtr();
4873     vmAppDomain.SetDacTargetPtr(PTR_HOST_TO_TADDR(pAppDomain));
4874     return vmAppDomain;
4875 }
4876
4877
4878 // Returns a bitfield reflecting the managed debugging state at the time of
4879 // the jit attach.
4880 CLR_DEBUGGING_PROCESS_FLAGS DacDbiInterfaceImpl::GetAttachStateFlags()
4881 {
4882     DD_ENTER_MAY_THROW;
4883
4884     CLR_DEBUGGING_PROCESS_FLAGS res = (CLR_DEBUGGING_PROCESS_FLAGS)0;
4885     if (g_pDebugger != NULL)
4886     {
4887         res = g_pDebugger->GetAttachStateFlags();
4888     }
4889     else
4890     {
4891         // When launching the process under a managed debugger we
4892         // request these flags when CLR is loaded (before g_pDebugger
4893         // had a chance to be initialized). In these cases simply 
4894         // return 0
4895     }
4896     return res;
4897 }
4898
4899 //---------------------------------------------------------------------------------------
4900 // Helper to get the address of the 2nd-chance hijack function Or throw
4901 //
4902 // Returns:
4903 //     Non-null Target Address of hijack function.
4904 TADDR DacDbiInterfaceImpl::GetHijackAddress()
4905 {
4906     TADDR addr = NULL; 
4907     if (g_pDebugger != NULL)
4908     {
4909         // Get the start address of the redirect function for unhandled exceptions.
4910         addr = dac_cast<TADDR>(g_pDebugger->m_rgHijackFunction[Debugger::kUnhandledException].StartAddress());
4911     }
4912     if (addr == NULL)
4913     {
4914         ThrowHR(CORDBG_E_NOTREADY);
4915     }
4916     return addr;
4917 }
4918
4919 //---------------------------------------------------------------------------------------
4920 // Helper to determine whether a control PC is in any native stub which the runtime knows how to unwind.
4921 //
4922 // Arguments:
4923 //    taControlPC - control PC to be checked
4924 //
4925 // Returns:
4926 //    Returns true if the control PC is in a runtime unwindable stub.
4927 //
4928 // Notes:
4929 //    Currently this function only recognizes the ExceptionHijack() stub,
4930 //    which is used for unhandled exceptions.
4931 //   
4932
4933 bool DacDbiInterfaceImpl::IsRuntimeUnwindableStub(PCODE targetControlPC)
4934 {
4935
4936     TADDR controlPC = PCODEToPINSTR(targetControlPC);
4937     // we call this function a lot while walking the stack and the values here will never change
4938     // Getting the g_pDebugger and each entry in the m_rgHijackFunction is potentially ~7 DAC
4939     // accesses per frame. Caching the data into a single local array is much faster. This optimization
4940     // recovered a few % of DAC stackwalking time
4941     if(!m_isCachedHijackFunctionValid)
4942     {
4943         Debugger* pDebugger = g_pDebugger;
4944         if ((pDebugger == NULL) || (pDebugger->m_rgHijackFunction == NULL))
4945         {
4946             // The in-process debugging infrastructure hasn't been fully initialized, which means that we could 
4947             // NOT have hijacked anything yet.
4948             return false;
4949         }
4950
4951         // PERF NOTE: if needed this array copy could probably be made more efficient
4952         // hitting the DAC only once for a single memory block, or even better
4953         // put the array inline in the Debugger object so that we only do 1 DAC
4954         // access for this entire thing
4955         for (int i = 0; i < Debugger::kMaxHijackFunctions; i++)
4956         {
4957             InitTargetBufferFromMemoryRange(pDebugger->m_rgHijackFunction[i], &m_pCachedHijackFunction[i] );
4958         }
4959         m_isCachedHijackFunctionValid = TRUE;
4960     }
4961
4962     // Check whether the control PC is in any of the thread redirection functions.
4963     for (int i = 0; i < Debugger::kMaxHijackFunctions; i++)
4964     {
4965         CORDB_ADDRESS start = m_pCachedHijackFunction[i].pAddress;
4966         CORDB_ADDRESS end = start + m_pCachedHijackFunction[i].cbSize;
4967         if ((start <= controlPC) && (controlPC < end))
4968         {
4969             return true;
4970         }
4971     }
4972     return false;
4973 }
4974
4975 //---------------------------------------------------------------------------------------
4976 // Align a stack pointer for the given architecture
4977 // 
4978 // Arguments:
4979 //    pEsp - in/out: pointer to stack pointer. 
4980 //
4981 void DacDbiInterfaceImpl::AlignStackPointer(CORDB_ADDRESS * pEsp)
4982 {
4983     SUPPORTS_DAC;
4984
4985     // Nop on x86.
4986 #if defined(_WIN64)
4987     // on 64-bit, stack pointer must be 16-byte aligned. 
4988     // Stacks grown down, so round down to nearest 0xF bits.
4989     *pEsp &= ~((CORDB_ADDRESS) 0xF);
4990 #endif
4991 }
4992
4993 //---------------------------------------------------------------------------------------
4994 // Emulate pushing something on a thread's stack.
4995 // 
4996 // Arguments:
4997 //     pEsp - in/out: pointer to stack pointer to push object at. On output, 
4998 //            updated stack pointer. 
4999 //     pData  - object to push on the stack.
5000 //     fAlignStack - whether to align the stack pointer before and after the push.
5001 //                   Callers which specify FALSE must be very careful and know exactly 
5002 //                   what they are doing.
5003 //
5004 // Return:
5005 //     address of pushed object. Throws on error.
5006 template <class T>
5007 CORDB_ADDRESS DacDbiInterfaceImpl::PushHelper(CORDB_ADDRESS * pEsp, 
5008                                               const T * pData, 
5009                                               BOOL fAlignStack)
5010 {    
5011     SUPPORTS_DAC;
5012
5013     if (fAlignStack == TRUE)
5014     {
5015         AlignStackPointer(pEsp);
5016     }
5017     *pEsp -= sizeof(T);
5018     if (fAlignStack == TRUE)
5019     {
5020         AlignStackPointer(pEsp);
5021     }
5022     SafeWriteStructOrThrow(*pEsp, pData);
5023     return *pEsp;
5024 }
5025
5026 //---------------------------------------------------------------------------------------
5027 // Write an EXCEPTION_RECORD structure to the remote target at the specified address while taking 
5028 // into account the number of exception parameters.  On 64-bit OS and on the WOW64, the OS always 
5029 // pushes the entire EXCEPTION_RECORD onto the stack.  However, on native x86 OS, the OS only pushes
5030 // enough of the EXCEPTION_RECORD to cover the specified number of exception parameters.  Thus we
5031 // need to be extra careful when we overwrite an EXCEPTION_RECORD on the stack.
5032 //
5033 // Arguments:
5034 //    pRemotePtr   - address of the EXCEPTION_RECORD in the remote target 
5035 //    pExcepRecord - EXCEPTION_RECORD to be written
5036 //
5037 // Notes:
5038 //    This function is only used by the code which hijacks a therad when there's an unhandled exception.
5039 //    It only works when we are actually debugging a live process, not a dump.
5040 //
5041
5042 void DacDbiInterfaceImpl::WriteExceptionRecordHelper(CORDB_ADDRESS pRemotePtr, 
5043                                                      const EXCEPTION_RECORD * pExcepRecord)
5044 {
5045     // Calculate the correct size to push onto the stack.
5046     ULONG32 cbSize = offsetof(EXCEPTION_RECORD, ExceptionInformation);
5047     cbSize += pExcepRecord->NumberParameters * sizeof(pExcepRecord->ExceptionInformation[0]);
5048
5049     // Use the data target to write to the remote target.  Here we are assuming that we are debugging a 
5050     // live process, since this function is only called by the hijacking code for unhandled exceptions.
5051     HRESULT hr = m_pMutableTarget->WriteVirtual(pRemotePtr, 
5052                                                 reinterpret_cast<const BYTE *>(pExcepRecord), 
5053                                                 cbSize);
5054
5055     if (FAILED(hr))
5056     {
5057         ThrowHR(hr);
5058     }
5059 }
5060
5061 // Implement IDacDbiInterface::Hijack
5062 void DacDbiInterfaceImpl::Hijack(
5063     VMPTR_Thread                 vmThread,
5064     ULONG32                      dwThreadId,
5065     const EXCEPTION_RECORD *     pRecord,  
5066     T_CONTEXT *                  pOriginalContext, 
5067     ULONG32                      cbSizeContext,
5068     EHijackReason::EHijackReason reason, 
5069     void *                       pUserData,
5070     CORDB_ADDRESS *              pRemoteContextAddr)
5071 {
5072     DD_ENTER_MAY_THROW;
5073
5074     //
5075     // Validate parameters
5076     //
5077
5078     // pRecord may be NULL if we're not hijacking at an exception
5079     // pOriginalContext may be NULL if caller doesn't want a copy of the context.
5080     // (The hijack function already has the context)
5081     _ASSERTE((pOriginalContext == NULL) == (cbSizeContext == 0));
5082     _ASSERTE(EHijackReason::IsValid(reason));
5083 #ifdef PLATFORM_UNIX
5084     _ASSERTE(!"Not supported on this platform");
5085 #endif
5086
5087     //
5088     // If we hijack a thread which might not be managed we can set vmThread = NULL
5089     // The only side-effect in this case is that we can't reuse CONTEXT and
5090     // EXCEPTION_RECORD space on the stack by an already underway in-process exception
5091     // filter. If you depend on those being used and updated you must provide the vmThread
5092     //
5093     Thread* pThread = NULL;
5094     if(!vmThread.IsNull())
5095     {
5096         pThread = vmThread.GetDacPtr();
5097         _ASSERTE(pThread->GetOSThreadIdForDebugger() == dwThreadId);
5098     }
5099
5100     TADDR pfnHijackFunction = GetHijackAddress();
5101
5102     //
5103     // Setup context for hijack
5104     // 
5105     T_CONTEXT ctx;
5106     HRESULT hr = m_pTarget->GetThreadContext(
5107         dwThreadId, 
5108         CONTEXT_FULL, 
5109         sizeof(ctx), 
5110         (BYTE*) &ctx);
5111     IfFailThrow(hr);
5112
5113     // If caller requested, copy back the original context that we're hijacking from.
5114     if (pOriginalContext != NULL)
5115     {
5116         // Since Dac + DBI are tightly coupled, context sizes should be the same.
5117         if (cbSizeContext != sizeof(T_CONTEXT))
5118         {
5119             ThrowHR(E_INVALIDARG);
5120         }
5121
5122         memcpy(pOriginalContext, &ctx, cbSizeContext);
5123     }
5124
5125     // Make sure the trace flag isn't on. This can happen if we were single stepping the thread when we faulted. This
5126     // will ensure that we don't try to single step through the OS's exception logic, which greatly confuses our second
5127     // chance hijack logic. This also mimics what the OS does for us automaically when single stepping in process, i.e.,
5128     // when you turn the trace flag on in-process and go, if there is a fault, the fault is reported and the trace flag
5129     // is automatically turned off.
5130     //
5131     // The debugger could always re-enable the single-step flag if it wants to.    
5132 #ifndef _TARGET_ARM_
5133     UnsetSSFlag(reinterpret_cast<DT_CONTEXT *>(&ctx)); 
5134 #endif
5135
5136     // Push pointers
5137     void* espContext = NULL;
5138     void* espRecord = NULL;
5139     const void* pData = pUserData;
5140
5141     // @dbgtodo  cross-plat - this is not cross plat
5142     CORDB_ADDRESS esp = GetSP(&ctx);
5143     
5144     //
5145     // Find out where the OS exception dispatcher has pushed the EXCEPTION_RECORD and CONTEXT. The ExInfo and
5146     // ExceptionTracker have pointers to these data structures, but when we get the unhandled exception
5147     // notification, the OS exception dispatcher is no longer on the stack, so these pointers are no longer
5148     // valid.  We need to either update these pointers in the ExInfo/ExcepionTracker, or reuse the stack
5149     // space used by the OS exception dispatcher.  We are using the latter approach here.
5150     // 
5151
5152     CORDB_ADDRESS espOSContext = NULL;
5153     CORDB_ADDRESS espOSRecord  = NULL;
5154     if (pThread != NULL && pThread->IsExceptionInProgress())
5155     {
5156         espOSContext = (CORDB_ADDRESS)PTR_TO_TADDR(pThread->GetExceptionState()->GetContextRecord());
5157         espOSRecord  = (CORDB_ADDRESS)PTR_TO_TADDR(pThread->GetExceptionState()->GetExceptionRecord());
5158
5159         // The managed exception may not be related to the unhandled exception for which we are trying to 
5160         // hijack.  An example would be when a thread hits a managed exception, VS tries to do func eval on 
5161         // the thread, but the func eval causes an unhandled exception (e.g. AV in mscorwks.dll).  In this
5162         // case, the pointers stored on the ExInfo/ExceptionTracker are closer to the root than the current
5163         // SP of the thread.  The check below makes sure we don't reuse the pointers in this case.
5164         if (espOSContext < esp)
5165         {
5166             SafeWriteStructOrThrow(espOSContext, &ctx);
5167             espContext = CORDB_ADDRESS_TO_PTR(espOSContext);
5168
5169             // We should have an EXCEPTION_RECORD if we are hijacked at an exception.
5170             // We need to be careful when we overwrite the exception record.  On x86, the OS doesn't 
5171             // always push the full record onto the stack, and so we can't blindly use sizeof(EXCEPTION_RECORD).  
5172             // Instead, we have to look at the number of exception parameters and calculate the size.
5173             _ASSERTE(pRecord != NULL);
5174             WriteExceptionRecordHelper(espOSRecord, pRecord);
5175             espRecord  = CORDB_ADDRESS_TO_PTR(espOSRecord);
5176
5177             esp = min(espOSContext, espOSRecord);
5178         }
5179     }
5180
5181     // If we haven't reused the pointers, then push everything at the leaf of the stack.
5182     if (espContext == NULL)
5183     {
5184         _ASSERTE(espRecord == NULL);
5185
5186         // Push on full Context and ExceptionRecord structures. We'll then push pointers to these,
5187         // and those pointers will serve as the actual args to the function.
5188         espContext = CORDB_ADDRESS_TO_PTR(PushHelper(&esp, &ctx, TRUE));
5189
5190         // If caller didn't pass an exception-record, then we're not being hijacked at an exception.
5191         // We'll just pass NULL for the exception-record to the Hijack function.
5192         if (pRecord != NULL)
5193         {
5194             espRecord  = CORDB_ADDRESS_TO_PTR(PushHelper(&esp, pRecord, TRUE));
5195         }
5196     }
5197
5198     if(pRemoteContextAddr != NULL)
5199     {
5200         *pRemoteContextAddr = PTR_TO_CORDB_ADDRESS(espContext);
5201     }
5202
5203     //
5204     // Push args onto the stack to be able to call the hijack function
5205     //
5206
5207     // Prototype of hijack is:
5208     //     void __stdcall ExceptionHijackWorker(CONTEXT * pContext, EXCEPTION_RECORD * pRecord, EHijackReason, void * pData)
5209     // Set up everything so that the hijack stub can just do a "call" instruction.
5210     //
5211     // Regarding stack overflow: We could do an explicit check against the thread's stack base limit.
5212     // However, we don't need an explicit overflow check because if the stack does overflow, 
5213     // the hijack will just hit a regular stack-overflow exception.
5214 #if defined(_TARGET_X86_)  // TARGET 
5215     // X86 calling convention is to push args on the stack in reverse order.
5216     // If we fail here, the stack is written, but esp hasn't been committed yet so it shouldn't matter.
5217     PushHelper(&esp, &pData, TRUE);
5218     PushHelper(&esp, &reason, TRUE);
5219     PushHelper(&esp, &espRecord, TRUE);
5220     PushHelper(&esp, &espContext, TRUE);
5221 #elif defined (_TARGET_AMD64_) // TARGET 
5222     // AMD64 calling convention is to place first 4 parameters in: rcx, rdx, r8 and r9
5223     ctx.Rcx = (DWORD64) espContext;
5224     ctx.Rdx = (DWORD64) espRecord;
5225     ctx.R8  = (DWORD64) reason;
5226     ctx.R9  = (DWORD64) pData;
5227
5228     // Caller must allocate stack space to spill for args.
5229     // Push the arguments onto the outgoing argument homes.  
5230     // Make sure we push pointer-sized values to keep the stack aligned.
5231     PushHelper(&esp, reinterpret_cast<SIZE_T *>(&(ctx.R9)), FALSE);
5232     PushHelper(&esp, reinterpret_cast<SIZE_T *>(&(ctx.R8)), FALSE);
5233     PushHelper(&esp, reinterpret_cast<SIZE_T *>(&(ctx.Rdx)), FALSE);
5234     PushHelper(&esp, reinterpret_cast<SIZE_T *>(&(ctx.Rcx)), FALSE);
5235 #elif defined(_TARGET_ARM_)
5236     ctx.R0 = (DWORD)espContext;
5237     ctx.R1 = (DWORD)espRecord;
5238     ctx.R2 = (DWORD)reason;
5239     ctx.R3 = (DWORD)pData;
5240 #elif defined(_TARGET_ARM64_)
5241     ctx.X0 = (DWORD64)espContext;
5242     ctx.X1 = (DWORD64)espRecord;
5243     ctx.X2 = (DWORD64)reason;
5244     ctx.X3 = (DWORD64)pData;
5245 #else
5246     PORTABILITY_ASSERT("CordbThread::HijackForUnhandledException is not implemented on this platform.");
5247 #endif
5248     SetSP(&ctx, CORDB_ADDRESS_TO_TADDR(esp));
5249
5250     // @dbgtodo  cross-plat - not cross-platform safe
5251     SetIP(&ctx, pfnHijackFunction);
5252
5253     //
5254     // Commit the context. 
5255     //
5256     hr = m_pMutableTarget->SetThreadContext(dwThreadId, sizeof(ctx), reinterpret_cast<BYTE*> (&ctx));
5257     IfFailThrow(hr);
5258 }
5259
5260 // Return the filter CONTEXT on the LS.
5261 VMPTR_CONTEXT DacDbiInterfaceImpl::GetManagedStoppedContext(VMPTR_Thread vmThread)
5262 {
5263     DD_ENTER_MAY_THROW;
5264
5265     VMPTR_CONTEXT vmContext = VMPTR_CONTEXT::NullPtr();
5266
5267     Thread * pThread = vmThread.GetDacPtr();
5268     if (pThread->GetInteropDebuggingHijacked())
5269     {
5270         _ASSERTE(!ISREDIRECTEDTHREAD(pThread));
5271         vmContext = VMPTR_CONTEXT::NullPtr();
5272     }
5273     else
5274     {
5275         DT_CONTEXT * pLSContext = reinterpret_cast<DT_CONTEXT *>(pThread->GetFilterContext());
5276         if (pLSContext != NULL)
5277         {
5278             _ASSERTE(!ISREDIRECTEDTHREAD(pThread));
5279             vmContext.SetHostPtr(pLSContext);
5280         }
5281         else if (ISREDIRECTEDTHREAD(pThread))
5282         {
5283             pLSContext = reinterpret_cast<DT_CONTEXT *>(GETREDIRECTEDCONTEXT(pThread));
5284             _ASSERTE(pLSContext != NULL);
5285
5286             if (pLSContext != NULL)
5287             {
5288                 vmContext.SetHostPtr(pLSContext);
5289             }
5290         }
5291     }
5292
5293     return vmContext;
5294 }
5295
5296 // Return a TargetBuffer for the raw vararg signature.
5297 TargetBuffer DacDbiInterfaceImpl::GetVarArgSig(CORDB_ADDRESS   VASigCookieAddr,
5298                                                CORDB_ADDRESS * pArgBase)
5299 {
5300     DD_ENTER_MAY_THROW;
5301
5302     _ASSERTE(pArgBase != NULL);
5303     *pArgBase = NULL;
5304
5305     // First, read the VASigCookie pointer.
5306     TADDR taVASigCookie = NULL;
5307     SafeReadStructOrThrow(VASigCookieAddr, &taVASigCookie);
5308
5309     // Now create a DAC copy of VASigCookie.
5310     VASigCookie * pVACookie = PTR_VASigCookie(taVASigCookie);
5311
5312     // Figure out where the first argument is.
5313 #if defined(_TARGET_X86_) // (STACK_GROWS_DOWN_ON_ARGS_WALK)
5314     *pArgBase = VASigCookieAddr + pVACookie->sizeOfArgs;
5315 #else  // !_TARGET_X86_ (STACK_GROWS_UP_ON_ARGS_WALK)
5316     *pArgBase = VASigCookieAddr + sizeof(VASigCookie *);
5317 #endif // !_TARGET_X86_ (STACK_GROWS_UP_ON_ARGS_WALK)
5318
5319     return TargetBuffer(PTR_TO_CORDB_ADDRESS(pVACookie->signature.GetRawSig()), 
5320                         pVACookie->signature.GetRawSigLen());
5321 }
5322
5323 // returns TRUE if the type requires 8-byte alignment
5324 BOOL DacDbiInterfaceImpl::RequiresAlign8(VMPTR_TypeHandle thExact)
5325 {
5326     DD_ENTER_MAY_THROW;
5327
5328 #ifdef FEATURE_64BIT_ALIGNMENT
5329     TypeHandle th = TypeHandle::FromPtr(thExact.GetDacPtr()); 
5330     PTR_MethodTable mt = th.AsMethodTable();
5331
5332     return mt->RequiresAlign8();
5333 #else
5334     ThrowHR(E_NOTIMPL);
5335 #endif
5336 }
5337
5338 // Resolve the raw generics token to the real generics type token.  The resolution is based on the
5339 // given index.
5340 GENERICS_TYPE_TOKEN DacDbiInterfaceImpl::ResolveExactGenericArgsToken(DWORD               dwExactGenericArgsTokenIndex,
5341                                                                       GENERICS_TYPE_TOKEN rawToken)
5342 {
5343     DD_ENTER_MAY_THROW;
5344
5345     if (dwExactGenericArgsTokenIndex == 0)
5346     {
5347         // In this case the real generics type token is the MethodTable of the "this" object.
5348         // Note that we want the target address here.        
5349         
5350         // Incoming rawToken is actually a PTR_Object for the 'this' pointer. 
5351         // Need to do some casting to convert GENERICS_TYPE_TOKEN --> PTR_Object
5352         TADDR addrObjThis = CORDB_ADDRESS_TO_TADDR(rawToken);
5353         PTR_Object pObjThis = dac_cast<PTR_Object>(addrObjThis);
5354
5355         
5356         PTR_MethodTable pMT = pObjThis->GetMethodTable();
5357         
5358         // Now package up the PTR_MethodTable back into a GENERICS_TYPE_TOKEN
5359         TADDR addrMT = dac_cast<TADDR>(pMT);
5360         GENERICS_TYPE_TOKEN realToken = (GENERICS_TYPE_TOKEN) addrMT;
5361         return realToken;
5362     }
5363     else if (dwExactGenericArgsTokenIndex == (DWORD)ICorDebugInfo::TYPECTXT_ILNUM)
5364     {
5365         // rawToken is already initialized correctly.  Nothing to do here.
5366         return  rawToken;
5367     }
5368     
5369     // The index of the generics type token should not be anything else.
5370     // This is indeed an error condition, and so we throw here.
5371     _ASSERTE(!"DDII::REGAT - Unexpected generics type token index.");
5372     ThrowHR(CORDBG_E_TARGET_INCONSISTENT);
5373 }
5374
5375 // Check if the given method is an IL stub or an LCD method.
5376 IDacDbiInterface::DynamicMethodType DacDbiInterfaceImpl::IsILStubOrLCGMethod(VMPTR_MethodDesc vmMethodDesc)
5377 {
5378     DD_ENTER_MAY_THROW;
5379
5380     MethodDesc * pMD = vmMethodDesc.GetDacPtr();
5381
5382     if (pMD->IsILStub())
5383     {
5384         return kILStub;
5385     }
5386     else if (pMD->IsLCGMethod())
5387     {
5388         return kLCGMethod;
5389     }
5390     else
5391     {
5392         return kNone;
5393     }
5394 }
5395
5396 //---------------------------------------------------------------------------------------
5397 //
5398 // Determine whether the specified thread is at a GC safe place.
5399 //
5400 // Arguments:
5401 //    vmThread - the thread to be examined
5402 //
5403 // Return Value:
5404 //    Return TRUE if the thread is at a GC safe place.
5405 //    and under what conditions
5406 //
5407 // Notes:
5408 //    This function basically does a one-frame stackwalk.
5409 //    The logic is adopted from Debugger::IsThreadAtSafePlace().
5410 //
5411
5412 BOOL DacDbiInterfaceImpl::IsThreadAtGCSafePlace(VMPTR_Thread vmThread)
5413 {
5414     DD_ENTER_MAY_THROW;
5415
5416     BOOL fIsGCSafe = FALSE;
5417     Thread * pThread = vmThread.GetDacPtr();
5418
5419     // Check if the runtime has entered "Shutdown for Finalizer" mode.
5420     if ((g_fEEShutDown & ShutDown_Finalize2) != 0)
5421     {
5422         fIsGCSafe = TRUE;
5423     }
5424     else
5425     {
5426         T_CONTEXT ctx;
5427         REGDISPLAY rd;
5428         SetUpRegdisplayForStackWalk(pThread, &ctx, &rd);
5429
5430         ULONG32 flags = (QUICKUNWIND | HANDLESKIPPEDFRAMES | DISABLE_MISSING_FRAME_DETECTION);
5431
5432         StackFrameIterator iter;
5433         iter.Init(pThread, pThread->GetFrame(), &rd, flags);
5434
5435         CrawlFrame * pCF = &(iter.m_crawl);
5436         if (pCF->IsFrameless() && pCF->IsActiveFunc())
5437         {
5438             if (pCF->IsGcSafe())
5439             {
5440                 fIsGCSafe = TRUE;
5441             }
5442         }
5443     }
5444               
5445     return fIsGCSafe;
5446 }
5447
5448 //---------------------------------------------------------------------------------------
5449 //
5450 // Return a partial user state of the specified thread.  The returned user state doesn't contain
5451 // information about USER_UNSAFE_POINT.  The caller needs to call IsThreadAtGCSafePlace() to get
5452 // the full user state.
5453 //
5454 // Arguments:
5455 //    vmThread - the specified thread
5456 //
5457 // Return Value:
5458 //    Return the partial user state except for USER_UNSAFE_POINT
5459 //
5460
5461 CorDebugUserState DacDbiInterfaceImpl::GetPartialUserState(VMPTR_Thread vmThread)
5462 {
5463     DD_ENTER_MAY_THROW;
5464
5465     Thread * pThread = vmThread.GetDacPtr();
5466     Thread::ThreadState ts = pThread->GetSnapshotState();
5467
5468     UINT result = 0;
5469     if (ts & Thread::TS_Background)
5470     {
5471         result |= USER_BACKGROUND;
5472     }
5473
5474     if (ts & Thread::TS_Unstarted)
5475     {
5476         result |= USER_UNSTARTED;            
5477     }
5478
5479     // Don't report a StopRequested if the thread has actually stopped.
5480     if (ts & Thread::TS_Dead)
5481     {
5482         result |= USER_STOPPED;           
5483     }
5484
5485     // The interruptible flag is unreliable (see issue 699245)
5486     // The Debugger_SleepWaitJoin is always accurate when it is present, but it is still
5487     // just a band-aid fix to cover some of the race conditions interruptible has.
5488
5489     if (ts & Thread::TS_Interruptible || pThread->HasThreadStateNC(Thread::TSNC_DebuggerSleepWaitJoin))
5490     {
5491         result |= USER_WAIT_SLEEP_JOIN;          
5492     }
5493
5494     // Don't report a SuspendRequested if the thread has actually Suspended.
5495     if ((ts & Thread::TS_UserSuspendPending) && (ts & Thread::TS_SyncSuspended))
5496     {
5497         result |= USER_SUSPENDED;
5498     }
5499     else if (ts & Thread::TS_UserSuspendPending)
5500     {
5501         result |= USER_SUSPEND_REQUESTED;
5502     }
5503
5504     if (pThread->IsThreadPoolThread())
5505     {
5506         result |= USER_THREADPOOL;
5507     }
5508
5509     return (CorDebugUserState)result;
5510 }
5511
5512 //---------------------------------------------------------------------------------------
5513 //
5514 // Look up the EnC version number of a particular jitted instance of a managed method.
5515 //
5516 // Arguments:
5517 //    pModule             - the module containing the managed method
5518 //    vmMethodDesc        - the MethodDesc of the managed method
5519 //    mdMethod            - the MethodDef metadata token of the managed method
5520 //    pNativeStartAddress - the native start address of the jitted code
5521 //    pJittedInstanceEnCVersion - out parameter; the version number of the version 
5522 //                                corresponding to the specified native start address
5523 //    pLatestEnCVersion         - out parameter; the version number of the latest version
5524 //
5525 // Assumptions:
5526 //    vmMethodDesc and mdMethod must match (see below).
5527 //
5528 // Notes:
5529 //    mdMethod is not strictly necessary, since we can always get that from vmMethodDesc.
5530 //    It is just a perf optimization since the caller has the metadata token around already.
5531 //
5532 //    Today, there is no way to retrieve the EnC version number from the RS data structures.
5533 //    This primitive uses DAC to retrieve it from the LS data structures.  This function may
5534 //    very well be ripped out in the future if we DACize this information, but the current 
5535 //    thinking is that some of the RS data structures will remain, most likely in a reduced form.
5536 //
5537
5538 void DacDbiInterfaceImpl::LookupEnCVersions(Module*          pModule,
5539                                             VMPTR_MethodDesc vmMethodDesc,
5540                                             mdMethodDef      mdMethod,
5541                                             CORDB_ADDRESS    pNativeStartAddress,
5542                                             SIZE_T *         pLatestEnCVersion,
5543                                             SIZE_T *         pJittedInstanceEnCVersion /* = NULL */)
5544 {
5545     MethodDesc * pMD     = vmMethodDesc.GetDacPtr();
5546
5547     // make sure the vmMethodDesc and mdMethod match
5548     _ASSERTE(pMD->GetMemberDef() == mdMethod);
5549
5550     _ASSERTE(pLatestEnCVersion != NULL);
5551
5552     // @dbgtodo  inspection - once we do EnC, stop using DMIs.
5553     // If the method wasn't EnCed, DMIs may not exist. And since this is DAC, we can't create them.
5554
5555     // We may not have the memory for the DebuggerMethodInfos in a minidump.
5556     // When dump debugging EnC information isn't very useful so just fallback
5557     // to default version.
5558     DebuggerMethodInfo * pDMI = NULL;
5559     DebuggerJitInfo * pDJI = NULL;
5560     EX_TRY_ALLOW_DATATARGET_MISSING_MEMORY
5561     {
5562         pDMI = g_pDebugger->GetOrCreateMethodInfo(pModule, mdMethod);
5563         if (pDMI != NULL)
5564         {
5565             pDJI = pDMI->FindJitInfo(pMD, CORDB_ADDRESS_TO_TADDR(pNativeStartAddress));
5566         }
5567     }
5568     EX_END_CATCH_ALLOW_DATATARGET_MISSING_MEMORY;
5569     if (pDJI != NULL)
5570     {
5571         if (pJittedInstanceEnCVersion != NULL)
5572         {
5573             *pJittedInstanceEnCVersion = pDJI->m_encVersion;
5574         }
5575         *pLatestEnCVersion = pDMI->GetCurrentEnCVersion();
5576     }
5577     else
5578     {
5579         // If we have no DMI/DJI, then we must never have EnCed. So we can use default EnC info        
5580         // Several cases where we don't have a DMI/DJI:
5581         // - LCG methods
5582         // - method was never "touched" by debugger. (DJIs are created lazily).         
5583         if (pJittedInstanceEnCVersion != NULL)
5584         {
5585             *pJittedInstanceEnCVersion = CorDB_DEFAULT_ENC_FUNCTION_VERSION;
5586         }
5587         *pLatestEnCVersion = CorDB_DEFAULT_ENC_FUNCTION_VERSION;
5588     }
5589 }
5590
5591 // Get the address of the Debugger control block on the helper thread
5592 // Arguments: none
5593 // Return Value: The remote address of the Debugger control block allocated on the helper thread 
5594 //               if it has been successfully allocated or NULL otherwise.
5595 CORDB_ADDRESS DacDbiInterfaceImpl::GetDebuggerControlBlockAddress()
5596 {
5597     DD_ENTER_MAY_THROW;
5598
5599     if ((g_pDebugger != NULL) &&
5600         (g_pDebugger->m_pRCThread != NULL))
5601     {
5602     return CORDB_ADDRESS(dac_cast<TADDR>(g_pDebugger->m_pRCThread->GetDCB()));
5603     }
5604
5605     return NULL;
5606 }
5607
5608 // DacDbi API: Get the context for a particular thread of the target process
5609 void DacDbiInterfaceImpl::GetContext(VMPTR_Thread vmThread, DT_CONTEXT * pContextBuffer)
5610 {
5611     DD_ENTER_MAY_THROW
5612
5613     _ASSERTE(pContextBuffer != NULL);
5614
5615     Thread *  pThread  = vmThread.GetDacPtr();
5616
5617     // @dbgtodo  Once the filter context is removed, then we should always 
5618     // start with the leaf CONTEXT.
5619     DT_CONTEXT * pFilterContext = reinterpret_cast<DT_CONTEXT *>(pThread->GetFilterContext());
5620
5621     if (pFilterContext == NULL)
5622     {
5623         // If the filter context is NULL, then we use the true context of the thread.
5624         pContextBuffer->ContextFlags = CONTEXT_ALL;
5625         HRESULT hr = m_pTarget->GetThreadContext(pThread->GetOSThreadId(), 
5626                                                 pContextBuffer->ContextFlags, 
5627                                                 sizeof(*pContextBuffer),
5628                                                 reinterpret_cast<BYTE *>(pContextBuffer));
5629         if (hr == E_NOTIMPL)
5630         {
5631             // GetThreadContext is not implemented on this data target.
5632             // That's why we have to make do with context we can obtain from Frames explicitly stored in Thread object. 
5633             // It suffices for managed debugging stackwalk. 
5634             REGDISPLAY tmpRd = {};
5635             T_CONTEXT tmpContext = {};
5636             FillRegDisplay(&tmpRd, &tmpContext);
5637             
5638             // Going through thread Frames and looking for first (deepest one) one that 
5639             // that has context available for stackwalking (SP and PC)
5640             // For example: RedirectedThreadFrame, InlinedCallFrame, HelperMethodFrame, ComPlusMethodFrame
5641             Frame *frame = pThread->GetFrame();
5642             while (frame != NULL && frame != FRAME_TOP)
5643             {
5644                 frame->UpdateRegDisplay(&tmpRd);
5645                 if (GetRegdisplaySP(&tmpRd) != 0 && GetControlPC(&tmpRd) != 0)
5646                 {
5647                     UpdateContextFromRegDisp(&tmpRd, &tmpContext);
5648                     CopyMemory(pContextBuffer, &tmpContext, sizeof(*pContextBuffer));
5649                     pContextBuffer->ContextFlags = DT_CONTEXT_CONTROL;
5650                     return;
5651                 }
5652                 frame = frame->Next();
5653             }
5654
5655             // It looks like this thread is not running managed code. 
5656             ZeroMemory(pContextBuffer, sizeof(*pContextBuffer));   
5657         }
5658         else 
5659         {
5660             IfFailThrow(hr);
5661         }
5662     }
5663     else
5664     {
5665         *pContextBuffer = *pFilterContext;
5666     }
5667     
5668 } // DacDbiInterfaceImpl::GetContext
5669
5670 // Create a VMPTR_Object from a target object address
5671 // @dbgtodo validate the VMPTR_Object is in fact a object, possibly by DACizing
5672 //          Object::Validate
5673 VMPTR_Object DacDbiInterfaceImpl::GetObject(CORDB_ADDRESS ptr) 
5674 {
5675     DD_ENTER_MAY_THROW;
5676
5677     VMPTR_Object vmObj = VMPTR_Object::NullPtr();
5678     vmObj.SetDacTargetPtr(CORDB_ADDRESS_TO_TADDR(ptr));
5679     return vmObj;
5680 }
5681
5682 HRESULT DacDbiInterfaceImpl::EnableNGENPolicy(CorDebugNGENPolicy ePolicy)
5683 {
5684     return E_NOTIMPL;
5685 }
5686
5687 HRESULT DacDbiInterfaceImpl::SetNGENCompilerFlags(DWORD dwFlags)
5688 {
5689     DD_ENTER_MAY_THROW;
5690
5691 #ifndef FEATURE_PREJIT
5692     return CORDBG_E_NGEN_NOT_SUPPORTED;
5693 #else
5694     // verify that we are still early enough in runtime lifecycle to mutate these
5695     // flags. Typically this is done in the CreateProcess event though it is possible
5696     // to do it even earlier
5697     if(!Debugger::s_fCanChangeNgenFlags)
5698         return CORDBG_E_MUST_BE_IN_CREATE_PROCESS;
5699
5700     BOOL fAllowOpt =
5701         ((dwFlags & CORDEBUG_JIT_DISABLE_OPTIMIZATION) != CORDEBUG_JIT_DISABLE_OPTIMIZATION);
5702     PEFile::SetNGENDebugFlags(fAllowOpt);
5703     return S_OK;
5704 #endif
5705 }
5706
5707 HRESULT DacDbiInterfaceImpl::GetNGENCompilerFlags(DWORD *pdwFlags)
5708 {
5709     DD_ENTER_MAY_THROW;
5710
5711 #ifndef FEATURE_PREJIT
5712     return CORDBG_E_NGEN_NOT_SUPPORTED;
5713 #else
5714     BOOL fAllowOpt = TRUE;
5715     PEFile::GetNGENDebugFlags(&fAllowOpt);
5716     if(!fAllowOpt)
5717     {
5718         *pdwFlags = CORDEBUG_JIT_DISABLE_OPTIMIZATION;
5719     }
5720     else
5721     {
5722         *pdwFlags = CORDEBUG_JIT_DEFAULT;
5723     }
5724
5725     return S_OK;
5726 #endif
5727 }
5728
5729 typedef DPTR(OBJECTREF) PTR_ObjectRef;
5730
5731 // Create a VMPTR_Object from an address which points to a reference to an object
5732 // @dbgtodo validate the VMPTR_Object is in fact a object, possibly by DACizing
5733 //          Object::Validate
5734 VMPTR_Object DacDbiInterfaceImpl::GetObjectFromRefPtr(CORDB_ADDRESS ptr) 
5735 {
5736     DD_ENTER_MAY_THROW;
5737
5738     VMPTR_Object vmObj = VMPTR_Object::NullPtr();
5739     PTR_ObjectRef objRef = PTR_ObjectRef(CORDB_ADDRESS_TO_TADDR(ptr));
5740     vmObj.SetDacTargetPtr(PTR_TO_TADDR(*objRef));
5741
5742     return vmObj;
5743 }
5744
5745 // Create a VMPTR_OBJECTHANDLE from a handle 
5746 VMPTR_OBJECTHANDLE DacDbiInterfaceImpl::GetVmObjectHandle(CORDB_ADDRESS handleAddress)
5747 {
5748     DD_ENTER_MAY_THROW;
5749
5750     VMPTR_OBJECTHANDLE vmObjHandle = VMPTR_OBJECTHANDLE::NullPtr();
5751     vmObjHandle.SetDacTargetPtr(CORDB_ADDRESS_TO_TADDR(handleAddress));
5752
5753     return vmObjHandle;
5754 }
5755
5756
5757 // Validate that the VMPTR_OBJECTHANDLE refers to a legitimate managed object
5758 BOOL DacDbiInterfaceImpl::IsVmObjectHandleValid(VMPTR_OBJECTHANDLE vmHandle)
5759 {
5760     DD_ENTER_MAY_THROW;
5761
5762     BOOL ret = FALSE;
5763     // this may cause unallocated debuggee memory to be read
5764     // SEH exceptions will be caught
5765     EX_TRY
5766     {
5767         OBJECTREF objRef = ObjectFromHandle((OBJECTHANDLE)vmHandle.GetDacPtr());
5768
5769         // NULL is certinally valid...
5770         if (objRef != NULL)
5771         {
5772             if (objRef->ValidateObjectWithPossibleAV())
5773             {
5774                 ret = TRUE;
5775             }
5776         }
5777     }
5778     EX_CATCH
5779     {
5780     }
5781     EX_END_CATCH(SwallowAllExceptions);
5782
5783     return ret;
5784 }
5785
5786 // determines if the specified module is a WinRT module
5787 HRESULT DacDbiInterfaceImpl::IsWinRTModule(VMPTR_Module vmModule, BOOL& isWinRT)
5788 {
5789     DD_ENTER_MAY_THROW;
5790
5791     HRESULT hr = S_OK;
5792     isWinRT = FALSE;
5793
5794     EX_TRY
5795     {
5796         Module* pModule = vmModule.GetDacPtr();
5797         isWinRT = pModule->GetFile()->GetAssembly()->IsWindowsRuntime();
5798     }
5799     EX_CATCH_HRESULT(hr);
5800
5801     return hr;
5802 }
5803
5804 // Determines the app domain id for the object refered to by a given VMPTR_OBJECTHANDLE
5805 ULONG DacDbiInterfaceImpl::GetAppDomainIdFromVmObjectHandle(VMPTR_OBJECTHANDLE vmHandle)
5806 {
5807     DD_ENTER_MAY_THROW;
5808
5809     OBJECTHANDLE handle = (OBJECTHANDLE) vmHandle.GetDacPtr();
5810     return HndGetHandleADIndex(handle).m_dwIndex;
5811 }
5812
5813 // Get the target address from a VMPTR_OBJECTHANDLE, i.e., the handle address
5814 CORDB_ADDRESS DacDbiInterfaceImpl::GetHandleAddressFromVmHandle(VMPTR_OBJECTHANDLE vmHandle)
5815 {
5816     DD_ENTER_MAY_THROW;
5817
5818     CORDB_ADDRESS handle = vmHandle.GetDacPtr();
5819
5820     return handle;
5821 }
5822
5823 // Create a TargetBuffer which describes the location of the object
5824 TargetBuffer DacDbiInterfaceImpl::GetObjectContents(VMPTR_Object vmObj) 
5825 {
5826     DD_ENTER_MAY_THROW;
5827     PTR_Object objPtr = vmObj.GetDacPtr();
5828
5829     _ASSERTE(objPtr->GetSize() <= 0xffffffff);
5830     return TargetBuffer(PTR_TO_TADDR(objPtr), (ULONG)objPtr->GetSize());
5831 }
5832
5833 // ============================================================================
5834 // functions to get information about objects referenced via an instance of CordbReferenceValue or 
5835 // CordbHandleValue
5836 // ============================================================================
5837
5838 // DacDbiInterfaceImpl::FastSanityCheckObject
5839 // Helper function for CheckRef. Sanity check an object. 
5840 // We use a fast and easy check to improve confidence that objPtr points to a valid object. 
5841 // We can't tell cheaply if this is really a valid object (that would require walking the GC heap), but at
5842 // least we can check if we get an EEClass from the supposed method table and then get the method table from
5843 // the class. If we can, we have improved the probability that the object is valid. 
5844 // Arguments:
5845 //     input: objPtr - address of the object we are checking
5846 // Return Value: E_INVALIDARG or S_OK.
5847 HRESULT DacDbiInterfaceImpl::FastSanityCheckObject(PTR_Object objPtr)
5848 {
5849     CONTRACTL
5850     {
5851         SO_NOT_MAINLINE;
5852         NOTHROW;
5853         GC_NOTRIGGER;
5854     }
5855     CONTRACTL_END;
5856
5857     HRESULT hr = S_OK;
5858
5859     EX_TRY
5860     {
5861         // NULL is certainly valid...
5862         if (objPtr != NULL)
5863         {
5864             if (!objPtr->ValidateObjectWithPossibleAV())
5865             {
5866                 LOG((LF_CORDB, LL_INFO10000, "GOI: object methodtable-class invariant doesn't hold.\n"));
5867                 hr = E_INVALIDARG;
5868             }
5869         }
5870     }
5871     EX_CATCH
5872     {
5873         LOG((LF_CORDB, LL_INFO10000, "GOI: exception indicated ref is bad.\n"));
5874         hr = E_INVALIDARG;
5875     }
5876     EX_END_CATCH(SwallowAllExceptions);
5877
5878     return hr;
5879 }   // DacDbiInterfaceImpl::FastSanityCheckObject
5880
5881 // Perform a sanity check on an object address to determine if this _could be_ a valid object. 
5882 // We can't tell this for certain without walking the GC heap, but we do some fast tests to rule
5883 // out clearly invalid object addresses. See code:DacDbiInterfaceImpl::FastSanityCheckObject for more
5884 // details.
5885 // Arguments: 
5886 //     input:  objPtr    - address of the object we are checking
5887 // Return Value: 
5888 //             objRefBad - true iff we have determined the address cannot be pointing to a valid object.
5889 //                         Note that a value of false doesn't necessarily guarantee the object is really
5890 //                         valid                      
5891 bool DacDbiInterfaceImpl::CheckRef(PTR_Object objPtr)
5892 {
5893     bool objRefBad = false;
5894
5895     // Shortcut null references now...
5896     if (objPtr == NULL)
5897     {
5898         LOG((LF_CORDB, LL_INFO10000, "D::GOI: ref is NULL.\n"));
5899
5900         objRefBad = true;
5901     }
5902     else
5903     {
5904         // Try to verify the integrity of the object. This is not fool proof.
5905         // @todo - this whole idea of expecting AVs is broken, but it does rule
5906         // out a fair bit of rubbish. Find another
5907         // way to test if the object is valid?
5908         if (FAILED(FastSanityCheckObject(objPtr)))
5909         {
5910             LOG((LF_CORDB, LL_INFO10000, "D::GOI: address is not a valid object.\n"));
5911
5912             objRefBad = true;
5913         }
5914     }
5915
5916     return objRefBad;
5917 } // DacDbiInterfaceImpl::CheckRef
5918
5919 // DacDbiInterfaceImpl::InitObjectData 
5920 // Initialize basic object information: type handle, object size, offset to fields and expanded type
5921 // information.
5922 // Arguments:
5923 //     input:  objPtr      - address of object of interest
5924 //             vmAppDomain - AppDomain for the type f the object
5925 //     output: pObjectData - object information
5926 // Note: It is assumed that pObjectData is non-null. 
5927 void DacDbiInterfaceImpl::InitObjectData(PTR_Object                objPtr, 
5928                                          VMPTR_AppDomain           vmAppDomain, 
5929                                          DebuggerIPCE_ObjectData * pObjectData)
5930 {
5931     _ASSERTE(pObjectData != NULL);
5932     // @todo - this is still dangerous because the object may still be invalid.
5933     VMPTR_TypeHandle vmTypeHandle = VMPTR_TypeHandle::NullPtr();
5934     vmTypeHandle.SetDacTargetPtr(objPtr->GetGCSafeTypeHandle().AsTAddr());
5935
5936     // Save basic object info.
5937     pObjectData->objSize = objPtr->GetSize();
5938     pObjectData->objOffsetToVars = dac_cast<TADDR>((objPtr)->GetData()) - dac_cast<TADDR>(objPtr);
5939
5940     TypeHandleToExpandedTypeInfo(AllBoxed, vmAppDomain, vmTypeHandle, &(pObjectData->objTypeData));
5941
5942     // If this is a string object, set the type to ELEMENT_TYPE_STRING.
5943     if (objPtr->GetGCSafeMethodTable() == g_pStringClass)
5944     {
5945         pObjectData->objTypeData.elementType = ELEMENT_TYPE_STRING;
5946         if(pObjectData->objSize < MIN_OBJECT_SIZE)
5947         {
5948             pObjectData->objSize = PtrAlign(pObjectData->objSize);
5949         }
5950     }
5951 } // DacDbiInterfaceImpl::InitObjectData
5952
5953 // DAC/DBI API
5954
5955 // Get object information for a TypedByRef object (System.TypedReference). 
5956
5957 // These are objects that contain a managed pointer to a location and the type of the value at that location.
5958 // They are most commonly used for varargs but also may be used for parameters and locals. They are
5959 // stack-allocated. They provide a means for adding dynamic type information to a value type, whereas boxing
5960 // provides only static type information. This means they can be passed as reference parameters to
5961 // polymorphic methods that don't statically restrict the type of arguments they can receive.
5962
5963 // Although they are represented simply as an address, unlike other object references, they don't point
5964 // directly to the object. Instead, there is an extra level of indirection. The reference points to a struct
5965 // that contains the address of the object, so we need to treat them differently. They have their own
5966 // CorElementType (ELEMENT_TYPE_TYPEDBYREF) which makes it possible to identify this special case.
5967
5968 // Example:
5969 // static int AddABunchOfInts (__arglist)
5970 // {
5971 //     int result = 0;
5972 //
5973 //     System.ArgIterator iter = new System.ArgIterator (__arglist);
5974 //     int argCount = iter.GetRemainingCount();
5975 //
5976 //     for (int i = 0; i < argCount; i++) 
5977 //     {
5978 //         System.TypedReference typedRef = iter.GetNextArg();
5979 //         result += (int)TypedReference.ToObject(typedRef);
5980 //     }
5981 // 
5982 //     return result;
5983 // }
5984 //
5985 // static int Main (string[] args)
5986 // {
5987 //     int result = AddABunchOfInts (__arglist (2, 3, 4));
5988 //     Console.WriteLine ("Answer: {0}", result);
5989 //
5990 //     if (result != 9)
5991 //         return 1;
5992 //
5993 //     return 0;
5994 // }
5995
5996 // Initializes the objRef and typedByRefType fields of pObjectData (type info for the referent).
5997 void DacDbiInterfaceImpl::GetTypedByRefInfo(CORDB_ADDRESS             pTypedByRef, 
5998                                             VMPTR_AppDomain           vmAppDomain,
5999                                             DebuggerIPCE_ObjectData * pObjectData)
6000 {
6001      DD_ENTER_MAY_THROW;
6002
6003     // pTypedByRef is really the address of a TypedByRef struct rather than of a normal object.
6004     // The data field of the TypedByRef struct is the actual object ref.
6005     PTR_TypedByRef refAddr = PTR_TypedByRef(TADDR(pTypedByRef));
6006
6007     _ASSERTE(refAddr != NULL);
6008     _ASSERTE(pObjectData != NULL);
6009
6010     // The type of the referent is in the type field of the TypedByRef. We need to initialize the object
6011     // data type information. 
6012     TypeHandleToBasicTypeInfo(refAddr->type, 
6013                               &(pObjectData->typedByrefInfo.typedByrefType), 
6014                               vmAppDomain.GetDacPtr());
6015
6016     // The reference to the object is in the data field of the TypedByRef.
6017     CORDB_ADDRESS tempRef = dac_cast<TADDR>(refAddr->data);
6018     pObjectData->objRef = CORDB_ADDRESS_TO_PTR(tempRef);
6019
6020     LOG((LF_CORDB, LL_INFO10000, "D::GASOI: sending REFANY result: "
6021          "ref=0x%08x, cls=0x%08x, mod=0x%p\n",
6022          pObjectData->objRef,
6023          pObjectData->typedByrefType.metadataToken,
6024          pObjectData->typedByrefType.vmDomainFile.GetDacPtr()));
6025 } // DacDbiInterfaceImpl::GetTypedByRefInfo
6026
6027 // Get the string data associated withn obj and put it into the pointers
6028 // DAC/DBI API
6029 // Get the string length and offset to string base for a string object
6030 void DacDbiInterfaceImpl::GetStringData(CORDB_ADDRESS objectAddress, DebuggerIPCE_ObjectData * pObjectData)
6031 {
6032     DD_ENTER_MAY_THROW;
6033
6034     PTR_Object objPtr = PTR_Object(TADDR(objectAddress));
6035     LOG((LF_CORDB, LL_INFO10000, "D::GOI: The referent is a string.\n"));
6036
6037     if (objPtr->GetGCSafeMethodTable() != g_pStringClass) 
6038     {
6039         ThrowHR(CORDBG_E_TARGET_INCONSISTENT);
6040     }
6041
6042     PTR_StringObject pStrObj = dac_cast<PTR_StringObject>(objPtr);
6043     
6044     _ASSERTE(pStrObj != NULL);
6045     pObjectData->stringInfo.length = pStrObj->GetStringLength();
6046     pObjectData->stringInfo.offsetToStringBase = (UINT_PTR) pStrObj->GetBufferOffset();
6047
6048 } // DacDbiInterfaceImpl::GetStringData
6049
6050
6051 // DAC/DBI API
6052 // Get information for an array type referent of an objRef, including rank, upper and lower
6053 // bounds, element size and type, and the number of elements.
6054 void DacDbiInterfaceImpl::GetArrayData(CORDB_ADDRESS objectAddress, DebuggerIPCE_ObjectData * pObjectData)
6055 {
6056     DD_ENTER_MAY_THROW;
6057
6058     PTR_Object objPtr = PTR_Object(TADDR(objectAddress));
6059     PTR_MethodTable pMT = objPtr->GetGCSafeMethodTable();
6060
6061     if (!objPtr->GetGCSafeTypeHandle().IsArray())
6062     {
6063         LOG((LF_CORDB, LL_INFO10000,
6064              "D::GASOI: object should be an array.\n"));
6065
6066         pObjectData->objRefBad = true;
6067     }
6068     else
6069     {
6070         PTR_ArrayBase arrPtr = dac_cast<PTR_ArrayBase>(objPtr);
6071
6072         // this is also returned in the type information for the array - we return both for sanity checking...
6073         pObjectData->arrayInfo.rank = arrPtr->GetRank();      
6074         pObjectData->arrayInfo.componentCount = arrPtr->GetNumComponents();
6075         pObjectData->arrayInfo.offsetToArrayBase = arrPtr->GetDataPtrOffset(pMT);
6076
6077         if (arrPtr->IsMultiDimArray())
6078         {
6079             pObjectData->arrayInfo.offsetToUpperBounds = SIZE_T(arrPtr->GetBoundsOffset(pMT));
6080
6081             pObjectData->arrayInfo.offsetToLowerBounds = SIZE_T(arrPtr->GetLowerBoundsOffset(pMT));
6082         }
6083         else
6084         {
6085             pObjectData->arrayInfo.offsetToUpperBounds = 0;
6086             pObjectData->arrayInfo.offsetToLowerBounds = 0;
6087         }
6088
6089         pObjectData->arrayInfo.elementSize = arrPtr->GetComponentSize();
6090
6091         LOG((LF_CORDB, LL_INFO10000, "D::GOI: array info: "
6092             "baseOff=%d, lowerOff=%d, upperOff=%d, cnt=%d, rank=%d, rank (2) = %d,"
6093              "eleSize=%d, eleType=0x%02x\n",
6094              pObjectData->arrayInfo.offsetToArrayBase,
6095              pObjectData->arrayInfo.offsetToLowerBounds,
6096              pObjectData->arrayInfo.offsetToUpperBounds,
6097              pObjectData->arrayInfo.componentCount,
6098              pObjectData->arrayInfo.rank,
6099              pObjectData->objTypeData.ArrayTypeData.arrayRank,
6100              pObjectData->arrayInfo.elementSize,
6101              pObjectData->objTypeData.ArrayTypeData.arrayTypeArg.elementType));
6102     }
6103 } // DacDbiInterfaceImpl::GetArrayData
6104
6105 // DAC/DBI API: Get information about an object for which we have a reference, including the object size and
6106 // type information.
6107 void DacDbiInterfaceImpl::GetBasicObjectInfo(CORDB_ADDRESS             objectAddress, 
6108                                              CorElementType            type, 
6109                                              VMPTR_AppDomain           vmAppDomain, 
6110                                              DebuggerIPCE_ObjectData * pObjectData)
6111 {
6112     DD_ENTER_MAY_THROW;
6113
6114     PTR_Object objPtr = PTR_Object(TADDR(objectAddress));
6115     pObjectData->objRefBad = CheckRef(objPtr);
6116     if (pObjectData->objRefBad != true)
6117     {
6118         // initialize object type, size, offset information. Note: We may have a different element type
6119         // after this. For example, we may start with E_T_CLASS but return with something more specific. 
6120         InitObjectData (objPtr, vmAppDomain, pObjectData);
6121     }
6122 } // DacDbiInterfaceImpl::GetBasicObjectInfo
6123
6124 // This is the data passed to EnumerateBlockingObjectsCallback below
6125 struct BlockingObjectUserDataWrapper
6126 {
6127     CALLBACK_DATA pUserData;
6128     IDacDbiInterface::FP_BLOCKINGOBJECT_ENUMERATION_CALLBACK fpCallback;
6129 };
6130
6131 // The callback helper used by EnumerateBlockingObjects below, this
6132 // callback in turn invokes the user's callback with the right arguments
6133 void EnumerateBlockingObjectsCallback(PTR_DebugBlockingItem obj, VOID* pUserData)
6134 {
6135     BlockingObjectUserDataWrapper* wrapper = (BlockingObjectUserDataWrapper*)pUserData;
6136     DacBlockingObject dacObj;
6137
6138     // init to an arbitrary value to avoid mac compiler error about unintialized use
6139     // it will be correctly set in the switch and is never used with only this init here
6140     dacObj.blockingReason = DacBlockReason_MonitorCriticalSection;
6141     
6142     dacObj.vmBlockingObject.SetDacTargetPtr(dac_cast<TADDR>(OBJECTREFToObject(obj->pMonitor->GetOwningObject())));
6143     dacObj.dwTimeout = obj->dwTimeout;
6144     dacObj.vmAppDomain.SetDacTargetPtr(dac_cast<TADDR>(obj->pAppDomain));
6145     switch(obj->type)
6146     {
6147         case DebugBlock_MonitorCriticalSection:
6148             dacObj.blockingReason = DacBlockReason_MonitorCriticalSection;
6149             break;
6150         case DebugBlock_MonitorEvent:
6151             dacObj.blockingReason = DacBlockReason_MonitorEvent;
6152             break;
6153         default:
6154             _ASSERTE(!"obj->type has an invalid value");
6155             return;
6156     }
6157
6158     wrapper->fpCallback(dacObj, wrapper->pUserData);
6159 }
6160
6161 // DAC/DBI API:
6162 // Enumerate all monitors blocking a thread
6163 void DacDbiInterfaceImpl::EnumerateBlockingObjects(VMPTR_Thread                           vmThread,
6164                                                    FP_BLOCKINGOBJECT_ENUMERATION_CALLBACK fpCallback,
6165                                                    CALLBACK_DATA                          pUserData)
6166 {
6167     DD_ENTER_MAY_THROW;
6168
6169     Thread * pThread = vmThread.GetDacPtr();
6170     _ASSERTE(pThread != NULL);
6171
6172     BlockingObjectUserDataWrapper wrapper;
6173     wrapper.fpCallback = fpCallback;
6174     wrapper.pUserData = pUserData;
6175
6176     pThread->DebugBlockingInfo.VisitBlockingItems((DebugBlockingItemVisitor)EnumerateBlockingObjectsCallback,
6177         (VOID*)&wrapper);
6178 }
6179
6180 // DAC/DBI API:
6181 // Returns the thread which owns the monitor lock on an object and the acquisition count
6182 MonitorLockInfo DacDbiInterfaceImpl::GetThreadOwningMonitorLock(VMPTR_Object vmObject)
6183 {
6184     DD_ENTER_MAY_THROW;
6185     MonitorLockInfo info;
6186     info.lockOwner = VMPTR_Thread::NullPtr();
6187     info.acquisitionCount = 0;
6188
6189     Object* pObj = vmObject.GetDacPtr();
6190     DWORD threadId;
6191     DWORD acquisitionCount;
6192     if(!pObj->GetHeader()->GetThreadOwningMonitorLock(&threadId, &acquisitionCount))
6193     {
6194         return info;
6195     }
6196
6197     Thread *pThread = ThreadStore::GetThreadList(NULL);
6198     while (pThread != NULL)
6199     {
6200         if(pThread->GetThreadId() == threadId)
6201         {
6202             info.lockOwner.SetDacTargetPtr(PTR_HOST_TO_TADDR(pThread));
6203             info.acquisitionCount = acquisitionCount;
6204             return info;
6205         }
6206         pThread = ThreadStore::GetThreadList(pThread);
6207     } 
6208     _ASSERTE(!"A thread should have been found");
6209     return info;
6210 }
6211
6212 // The data passed to EnumerateThreadsCallback below
6213 struct ThreadUserDataWrapper
6214 {
6215     CALLBACK_DATA pUserData;
6216     IDacDbiInterface::FP_THREAD_ENUMERATION_CALLBACK fpCallback;
6217 };
6218
6219 // The callback helper used for EnumerateMonitorEventWaitList below. This callback
6220 // invokes the user's callback with the correct arguments.
6221 void EnumerateThreadsCallback(PTR_Thread pThread, VOID* pUserData)
6222 {
6223     ThreadUserDataWrapper* wrapper = (ThreadUserDataWrapper*)pUserData;
6224     VMPTR_Thread vmThread = VMPTR_Thread::NullPtr();
6225     vmThread.SetDacTargetPtr(dac_cast<TADDR>(pThread));
6226     wrapper->fpCallback(vmThread, wrapper->pUserData);
6227 }
6228
6229 // DAC/DBI API:
6230 // Enumerate all threads waiting on the monitor event for an object
6231 void DacDbiInterfaceImpl::EnumerateMonitorEventWaitList(VMPTR_Object                   vmObject,
6232                                                         FP_THREAD_ENUMERATION_CALLBACK fpCallback,
6233                                                         CALLBACK_DATA                  pUserData)
6234 {
6235     DD_ENTER_MAY_THROW;
6236
6237     Object* pObj = vmObject.GetDacPtr();
6238     SyncBlock* psb = pObj->PassiveGetSyncBlock();
6239     
6240     // no sync block means no wait list
6241     if(psb == NULL)
6242         return;
6243
6244     ThreadUserDataWrapper wrapper;
6245     wrapper.fpCallback = fpCallback;
6246     wrapper.pUserData = pUserData;
6247     ThreadQueue::EnumerateThreads(psb, (FP_TQ_THREAD_ENUMERATION_CALLBACK)EnumerateThreadsCallback, (VOID*) &wrapper);
6248 }
6249
6250
6251 bool DacDbiInterfaceImpl::AreGCStructuresValid()
6252 {
6253     return true;
6254 }
6255
6256 HeapData::HeapData()
6257     : YoungestGenPtr(0), YoungestGenLimit(0), Gen0Start(0), Gen0End(0), SegmentCount(0), Segments(0)
6258 {
6259 }
6260
6261 HeapData::~HeapData()
6262 {
6263     if (Segments)
6264         delete [] Segments;
6265 }
6266
6267 LinearReadCache::LinearReadCache()
6268     : mCurrPageStart(0), mPageSize(0), mCurrPageSize(0), mPage(0)
6269 {
6270     SYSTEM_INFO si;
6271         GetSystemInfo(&si);
6272
6273     mPageSize = si.dwPageSize;
6274     mPage = new (nothrow) BYTE[mPageSize];
6275 }
6276
6277 LinearReadCache::~LinearReadCache()
6278 {
6279     if (mPage)
6280         delete [] mPage;
6281 }
6282
6283 bool LinearReadCache::MoveToPage(CORDB_ADDRESS addr)
6284 {
6285     mCurrPageStart = addr - (addr % mPageSize);
6286     HRESULT hr = g_dacImpl->m_pTarget->ReadVirtual(mCurrPageStart, mPage, mPageSize, &mCurrPageSize);
6287
6288     if (hr != S_OK)
6289     {
6290         mCurrPageStart = 0;
6291         mCurrPageSize = 0;
6292         return false;
6293     }
6294
6295     return true;
6296 }
6297
6298
6299 CORDB_ADDRESS DacHeapWalker::HeapStart = 0;
6300 CORDB_ADDRESS DacHeapWalker::HeapEnd = ~0;
6301
6302 DacHeapWalker::DacHeapWalker()
6303     : mThreadCount(0), mAllocInfo(0), mHeapCount(0), mHeaps(0),
6304         mCurrObj(0), mCurrSize(0), mCurrMT(0),
6305         mCurrHeap(0), mCurrSeg(0), mStart((TADDR)HeapStart), mEnd((TADDR)HeapEnd)
6306 {
6307 }
6308
6309 DacHeapWalker::~DacHeapWalker()
6310 {
6311     if (mAllocInfo)
6312         delete [] mAllocInfo;
6313
6314     if (mHeaps)
6315         delete [] mHeaps;
6316 }
6317
6318 SegmentData *DacHeapWalker::FindSegment(CORDB_ADDRESS obj)
6319 {
6320     for (size_t i = 0; i < mHeapCount; ++i)
6321         for (size_t j = 0; j < mHeaps[i].SegmentCount; ++j)
6322             if (mHeaps[i].Segments[j].Start <= obj && obj <= mHeaps[i].Segments[j].End)
6323                 return &mHeaps[i].Segments[j];
6324
6325     return NULL;
6326 }
6327
6328 HRESULT DacHeapWalker::Next(CORDB_ADDRESS *pValue, CORDB_ADDRESS *pMT, ULONG64 *pSize)
6329 {
6330     if (!HasMoreObjects())
6331         return E_FAIL;
6332
6333     if (pValue)
6334         *pValue = mCurrObj;
6335
6336     if (pMT)
6337         *pMT = (CORDB_ADDRESS)mCurrMT;
6338
6339     if (pSize)
6340         *pSize = (ULONG64)mCurrSize;
6341
6342     HRESULT hr = MoveToNextObject();
6343     return FAILED(hr) ? hr : S_OK;
6344 }
6345
6346
6347
6348 HRESULT DacHeapWalker::MoveToNextObject()
6349 {
6350     do
6351     {
6352         // Move to the next object
6353         mCurrObj += mCurrSize;
6354
6355         // Check to see if we are in the correct bounds.
6356         if (mHeaps[mCurrHeap].Gen0Start <= mCurrObj && mHeaps[mCurrHeap].Gen0End > mCurrObj)
6357             CheckAllocAndSegmentRange();
6358
6359         // Check to see if we've moved off the end of a segment
6360         if (mCurrObj >= mHeaps[mCurrHeap].Segments[mCurrSeg].End || mCurrObj > mEnd)
6361         {
6362             HRESULT hr = NextSegment();
6363             if (FAILED(hr) || hr == S_FALSE)
6364                 return hr;
6365         }
6366
6367         // Get the method table pointer
6368         if (!mCache.ReadMT(mCurrObj, &mCurrMT))
6369             return E_FAIL;
6370
6371         if (!GetSize(mCurrMT, mCurrSize))
6372             return E_FAIL;
6373     } while (mCurrObj < mStart);
6374
6375     _ASSERTE(mStart <= mCurrObj && mCurrObj <= mEnd);
6376     return S_OK;
6377 }
6378
6379 bool DacHeapWalker::GetSize(TADDR tMT, size_t &size)
6380 {
6381     // With heap corruption, it's entierly possible that the MethodTable
6382     // we get is bad.  This could cause exceptions, which we will catch
6383     // and return false.  This causes the heapwalker to move to the next
6384     // segment.
6385     bool ret = true;
6386     EX_TRY
6387     {
6388         MethodTable *mt = PTR_MethodTable(tMT);
6389         size_t cs = mt->GetComponentSize();
6390
6391         if (cs)
6392         {
6393             DWORD tmp = 0;
6394             if (mCache.Read(mCurrObj+sizeof(TADDR), &tmp))
6395                 cs *= tmp;
6396             else
6397                 ret = false;
6398         }
6399
6400         size = mt->GetBaseSize() + cs;
6401
6402         // The size is not guaranteed to be aligned, we have to
6403         // do that ourself.
6404         if (mHeaps[mCurrHeap].Segments[mCurrSeg].Generation == 3)
6405             size = AlignLarge(size);
6406         else
6407             size = Align(size);
6408     }
6409     EX_CATCH
6410     {
6411         ret = false;
6412     }
6413     EX_END_CATCH(SwallowAllExceptions)
6414
6415     return ret;
6416 }
6417
6418
6419 HRESULT DacHeapWalker::NextSegment()
6420 {
6421     mCurrObj = 0;
6422     mCurrMT = 0;
6423     mCurrSize = 0;
6424
6425     do
6426     {
6427         mCurrSeg++;
6428         while (mCurrSeg >= mHeaps[mCurrHeap].SegmentCount)
6429         {
6430             mCurrSeg = 0;
6431             mCurrHeap++;
6432
6433             if (mCurrHeap >= mHeapCount)
6434             {
6435                 return S_FALSE;
6436             }
6437         }
6438
6439         mCurrObj = mHeaps[mCurrHeap].Segments[mCurrSeg].Start;
6440         
6441         if (mHeaps[mCurrHeap].Gen0Start <= mCurrObj && mHeaps[mCurrHeap].Gen0End > mCurrObj)
6442             CheckAllocAndSegmentRange();
6443     
6444         if (!mCache.ReadMT(mCurrObj, &mCurrMT))
6445         {
6446             return E_FAIL;
6447         }
6448     
6449         if (!GetSize(mCurrMT, mCurrSize))
6450         {
6451             return E_FAIL;
6452         }
6453     } while((mHeaps[mCurrHeap].Segments[mCurrSeg].Start > mEnd) || (mHeaps[mCurrHeap].Segments[mCurrSeg].End < mStart));
6454
6455     return S_OK;
6456 }
6457
6458 void DacHeapWalker::CheckAllocAndSegmentRange()
6459 {
6460     const size_t MinObjSize = sizeof(TADDR)*3;
6461
6462     for (int i = 0; i < mThreadCount; ++i)
6463         if (mCurrObj == mAllocInfo[i].Ptr)
6464         {
6465             mCurrObj = mAllocInfo[i].Limit + Align(MinObjSize);
6466             break;
6467         }
6468
6469     if (mCurrObj == mHeaps[mCurrHeap].YoungestGenPtr)
6470     {
6471         mCurrObj = mHeaps[mCurrHeap].YoungestGenLimit + Align(MinObjSize);
6472     }
6473 }
6474
6475 HRESULT DacHeapWalker::Init(CORDB_ADDRESS start, CORDB_ADDRESS end)
6476 {
6477     // Collect information about the allocation contexts in the process.
6478     ThreadStore* threadStore = ThreadStore::s_pThreadStore;
6479     if (threadStore != NULL)
6480     {
6481         int count = (int)threadStore->ThreadCountInEE();
6482         mAllocInfo = new (nothrow) AllocInfo[count];
6483         if (mAllocInfo == NULL)
6484             return E_OUTOFMEMORY;
6485
6486         Thread *thread = NULL;
6487         int j = 0;
6488         for (int i = 0; i < count; ++i)
6489         {
6490             // The thread or allocation context being null is troubling, but not fatal.
6491             // We may have stopped the process where the thread list or thread's alloc
6492             // context was in an inconsistent state.  We will simply skip over affected
6493             // segments during the heap walk if we encounter problems due to this.
6494             thread = ThreadStore::GetThreadList(thread);
6495             if (thread == NULL)
6496                 continue;
6497
6498             gc_alloc_context *ctx = thread->GetAllocContext();
6499             if (ctx == NULL)
6500                 continue;
6501
6502             if ((CORDB_ADDRESS)ctx->alloc_ptr != NULL)
6503             {
6504                 mAllocInfo[j].Ptr = (CORDB_ADDRESS)ctx->alloc_ptr;
6505                 mAllocInfo[j].Limit = (CORDB_ADDRESS)ctx->alloc_limit;
6506                 j++;
6507             }
6508         }
6509
6510         mThreadCount = j;
6511     }
6512
6513 #ifdef FEATURE_SVR_GC
6514     HRESULT hr = GCHeapUtilities::IsServerHeap() ? InitHeapDataSvr(mHeaps, mHeapCount) : InitHeapDataWks(mHeaps, mHeapCount);
6515 #else
6516     HRESULT hr = InitHeapDataWks(mHeaps, mHeapCount);
6517 #endif
6518
6519     // Set up mCurrObj/mCurrMT.
6520     if (SUCCEEDED(hr))
6521         hr = Reset(start, end);
6522     
6523     // Collect information about GC heaps
6524     return hr;
6525 }
6526
6527 HRESULT DacHeapWalker::Reset(CORDB_ADDRESS start, CORDB_ADDRESS end)
6528 {
6529     _ASSERTE(mHeaps);
6530     _ASSERTE(mHeapCount > 0);
6531     _ASSERTE(mHeaps[0].Segments);
6532     _ASSERTE(mHeaps[0].SegmentCount > 0);
6533
6534     mStart = start;
6535     mEnd = end;
6536
6537     // Set up first object
6538     mCurrObj = mHeaps[0].Segments[0].Start;
6539     mCurrMT = 0;
6540     mCurrSize = 0;
6541     mCurrHeap = 0;
6542     mCurrSeg = 0;
6543
6544     if (!mCache.ReadMT(mCurrObj, &mCurrMT))
6545         return E_FAIL;
6546
6547     if (!GetSize(mCurrMT, mCurrSize))
6548         return E_FAIL;
6549
6550     if (mCurrObj < mStart || mCurrObj > mEnd)
6551         MoveToNextObject();
6552
6553     return S_OK;
6554 }
6555
6556 HRESULT DacHeapWalker::ListNearObjects(CORDB_ADDRESS obj, CORDB_ADDRESS *pPrev, CORDB_ADDRESS *pContaining, CORDB_ADDRESS *pNext)
6557 {
6558     SegmentData *seg = FindSegment(obj);
6559
6560     if (seg == NULL)
6561         return E_FAIL;
6562     
6563     HRESULT hr = Reset(seg->Start, seg->End);
6564     if (SUCCEEDED(hr))
6565     {
6566         CORDB_ADDRESS prev = 0;
6567         CORDB_ADDRESS curr = 0;
6568         ULONG64 size = 0;
6569         bool found = false;
6570
6571         while (!found && HasMoreObjects())
6572         {
6573             prev = curr;
6574             hr = Next(&curr, NULL, &size);
6575             if (FAILED(hr))
6576                 break;
6577
6578             if (obj >= curr && obj < curr + size)
6579                 found = true;
6580         }
6581         
6582         if (found)
6583         {
6584             if (pPrev)
6585                 *pPrev = prev;
6586
6587             if (pContaining)
6588                 *pContaining = curr;
6589
6590             if (pNext)
6591             {
6592                 if (HasMoreObjects())
6593                 {
6594                     hr = Next(&curr, NULL, NULL);
6595                     if (SUCCEEDED(hr))
6596                         *pNext = curr;
6597                 }
6598                 else
6599                 {
6600                     *pNext = 0;
6601                 }
6602             }
6603
6604             hr = S_OK;
6605         }
6606         else if (SUCCEEDED(hr))
6607         {
6608             hr = E_FAIL;
6609         }
6610     }
6611     
6612     return hr;
6613 }
6614
6615 #include "gceewks.cpp"
6616 HRESULT DacHeapWalker::InitHeapDataWks(HeapData *&pHeaps, size_t &pCount)
6617 {
6618     // Scrape basic heap details
6619     pCount = 1;
6620     pHeaps = new (nothrow) HeapData[1];
6621     if (pHeaps == NULL)
6622         return E_OUTOFMEMORY;
6623
6624     pHeaps[0].YoungestGenPtr = (CORDB_ADDRESS)WKS::generation_table[0].allocation_context.alloc_ptr;
6625     pHeaps[0].YoungestGenLimit = (CORDB_ADDRESS)WKS::generation_table[0].allocation_context.alloc_limit;
6626
6627     pHeaps[0].Gen0Start = (CORDB_ADDRESS)WKS::generation_table[0].allocation_start;
6628     pHeaps[0].Gen0End = (CORDB_ADDRESS)WKS::gc_heap::alloc_allocated.GetAddr();
6629     pHeaps[0].Gen1Start = (CORDB_ADDRESS)WKS::generation_table[1].allocation_start;
6630     
6631     // Segments
6632     int count = GetSegmentCount(WKS::generation_table[NUMBERGENERATIONS-1].start_segment);
6633     count += GetSegmentCount(WKS::generation_table[NUMBERGENERATIONS-2].start_segment);
6634
6635     pHeaps[0].SegmentCount = count;
6636     pHeaps[0].Segments = new (nothrow) SegmentData[count];
6637     if (pHeaps[0].Segments == NULL)
6638         return E_OUTOFMEMORY;
6639     
6640     // Small object heap segments
6641     WKS::heap_segment *seg = WKS::generation_table[NUMBERGENERATIONS-2].start_segment;
6642     int i = 0;
6643     for (; seg && (i < count); ++i)
6644     {
6645         pHeaps[0].Segments[i].Start = (CORDB_ADDRESS)seg->mem;
6646         if (seg == WKS::gc_heap::ephemeral_heap_segment)
6647         {
6648             pHeaps[0].Segments[i].End = (CORDB_ADDRESS)WKS::gc_heap::alloc_allocated.GetAddr();
6649             pHeaps[0].Segments[i].Generation = 1;
6650             pHeaps[0].EphemeralSegment = i;
6651         }
6652         else
6653         {
6654             pHeaps[0].Segments[i].End = (CORDB_ADDRESS)seg->allocated;
6655             pHeaps[0].Segments[i].Generation = 2;
6656         }
6657         
6658         seg = seg->next;
6659     }
6660
6661     // Large object heap segments
6662     seg = WKS::generation_table[NUMBERGENERATIONS-1].start_segment;
6663     for (; seg && (i < count); ++i)
6664     {
6665         pHeaps[0].Segments[i].Generation = 3;
6666         pHeaps[0].Segments[i].Start = (CORDB_ADDRESS)seg->mem;
6667         pHeaps[0].Segments[i].End = (CORDB_ADDRESS)seg->allocated;
6668         
6669         seg = seg->next;
6670     }
6671
6672     return S_OK;
6673 }
6674
6675  HRESULT DacDbiInterfaceImpl::CreateHeapWalk(IDacDbiInterface::HeapWalkHandle *pHandle)
6676 {
6677     DD_ENTER_MAY_THROW;
6678     
6679     DacHeapWalker *data = new (nothrow) DacHeapWalker;
6680     if (data == NULL)
6681         return E_OUTOFMEMORY;
6682
6683     HRESULT hr = data->Init();
6684     if (SUCCEEDED(hr))
6685         *pHandle = reinterpret_cast<HeapWalkHandle>(data);
6686     else
6687         delete data;
6688
6689     return hr;
6690 }
6691
6692 void DacDbiInterfaceImpl::DeleteHeapWalk(HeapWalkHandle handle)
6693 {
6694     DD_ENTER_MAY_THROW;
6695     
6696     DacHeapWalker *data = reinterpret_cast<DacHeapWalker*>(handle);
6697     if (data)
6698         delete data;
6699 }
6700
6701 HRESULT DacDbiInterfaceImpl::WalkHeap(HeapWalkHandle handle,
6702                     ULONG count,
6703                     OUT COR_HEAPOBJECT * objects,
6704                     OUT ULONG *fetched)
6705 {
6706     DD_ENTER_MAY_THROW;
6707     if (fetched == NULL)
6708         return E_INVALIDARG;
6709     
6710     DacHeapWalker *walk = reinterpret_cast<DacHeapWalker*>(handle);
6711     *fetched = 0;
6712
6713     if (!walk->HasMoreObjects())
6714         return S_FALSE;
6715     
6716     CORDB_ADDRESS freeMT = (CORDB_ADDRESS)g_pFreeObjectMethodTable.GetAddr();
6717
6718     HRESULT hr = S_OK;
6719     CORDB_ADDRESS addr, mt;
6720     ULONG64 size;
6721     
6722     ULONG i = 0;
6723     while (i < count && walk->HasMoreObjects())
6724     {
6725         hr = walk->Next(&addr, &mt, &size);
6726
6727         if (FAILED(hr))
6728             break;
6729
6730         if (mt != freeMT)
6731         {
6732             objects[i].address = addr;
6733             objects[i].type.token1 = mt;
6734             objects[i].type.token2 = NULL;
6735             objects[i].size = size;
6736             i++;
6737         }
6738     }
6739
6740     if (SUCCEEDED(hr))
6741         hr = (i < count) ? S_FALSE : S_OK;
6742     
6743     *fetched = i;
6744     return hr;
6745 }
6746
6747
6748     
6749 HRESULT DacDbiInterfaceImpl::GetHeapSegments(OUT DacDbiArrayList<COR_SEGMENT> *pSegments)
6750 {
6751     DD_ENTER_MAY_THROW;
6752     
6753     
6754     size_t heapCount = 0;
6755     HeapData *heaps = 0;
6756     
6757 #ifdef FEATURE_SVR_GC
6758     HRESULT hr = GCHeapUtilities::IsServerHeap() ? DacHeapWalker::InitHeapDataSvr(heaps, heapCount) : DacHeapWalker::InitHeapDataWks(heaps, heapCount);
6759 #else
6760     HRESULT hr = DacHeapWalker::InitHeapDataWks(heaps, heapCount);
6761 #endif
6762
6763     NewArrayHolder<HeapData> _heapHolder = heaps;
6764     
6765     // Count the number of segments to know how much to allocate.
6766     int total = 0;
6767     for (size_t i = 0; i < heapCount; ++i)
6768     {
6769         // SegmentCount is +1 due to the ephemeral segment containing more than one
6770         // generation (Gen1 + Gen0, and sometimes part of Gen2).
6771         total += (int)heaps[i].SegmentCount + 1;
6772         
6773         // It's possible that part of Gen2 lives on the ephemeral segment.  If so,
6774         // we need to add one more to the output.
6775         const size_t eph = heaps[i].EphemeralSegment;
6776         _ASSERTE(eph < heaps[i].SegmentCount);
6777         if (heaps[i].Segments[eph].Start != heaps[i].Gen1Start)
6778             total++;
6779     }
6780     
6781     pSegments->Alloc(total);
6782     
6783     // Now walk all segments and write them to the array.
6784     int curr = 0;
6785     for (size_t i = 0; i < heapCount; ++i)
6786     {
6787         // Generation 0 is not in the segment list.
6788         _ASSERTE(curr < total);
6789         {
6790             COR_SEGMENT &seg = (*pSegments)[curr++];
6791             seg.start = heaps[i].Gen0Start;
6792             seg.end = heaps[i].Gen0End;
6793             seg.type = CorDebug_Gen0;
6794             seg.heap = (ULONG)i;
6795         }
6796         
6797         for (size_t j = 0; j < heaps[i].SegmentCount; ++j)
6798         {
6799             if (heaps[i].Segments[j].Generation == 1)
6800             {
6801                 // This is the ephemeral segment.  We have already written Gen0,
6802                 // now write Gen1.
6803                 _ASSERTE(heaps[i].Segments[j].Start <= heaps[i].Gen1Start);
6804                 _ASSERTE(heaps[i].Segments[j].End > heaps[i].Gen1Start);
6805                 
6806                 {
6807                     _ASSERTE(curr < total);
6808                     COR_SEGMENT &seg = (*pSegments)[curr++];
6809                     seg.start = heaps[i].Gen1Start;
6810                     seg.end = heaps[i].Gen0Start;
6811                     seg.type = CorDebug_Gen1;
6812                     seg.heap = (ULONG)i;
6813                 }
6814                 
6815                 // It's possible for Gen2 to take up a portion of the ephemeral segment.
6816                 // We test for that here.
6817                 if (heaps[i].Segments[j].Start != heaps[i].Gen1Start)
6818                 {
6819                     _ASSERTE(curr < total);
6820                     COR_SEGMENT &seg = (*pSegments)[curr++];
6821                     seg.start = heaps[i].Segments[j].Start;
6822                     seg.end = heaps[i].Gen1Start;
6823                     seg.type = CorDebug_Gen2;
6824                     seg.heap = (ULONG)i;
6825                 }
6826             }
6827             else
6828             {
6829                 // Otherwise, we have a gen2 or gen3 (LOH) segment
6830                 _ASSERTE(curr < total);
6831                 COR_SEGMENT &seg = (*pSegments)[curr++];
6832                 seg.start = heaps[i].Segments[j].Start;
6833                 seg.end = heaps[i].Segments[j].End;
6834                 
6835                 _ASSERTE(heaps[i].Segments[j].Generation <= CorDebug_LOH);
6836                 seg.type = (CorDebugGenerationTypes)heaps[i].Segments[j].Generation;
6837                 seg.heap = (ULONG)i;
6838             }
6839         }
6840     }
6841     
6842     _ASSERTE(total == curr);
6843     return hr;
6844 }
6845
6846 bool DacDbiInterfaceImpl::IsValidObject(CORDB_ADDRESS addr)
6847 {
6848     DD_ENTER_MAY_THROW;
6849     
6850     bool isValid = false;
6851     EX_TRY
6852     {
6853         PTR_Object obj(TO_TADDR(addr));
6854         
6855         PTR_MethodTable mt = obj->GetMethodTable();
6856         PTR_EEClass cls = mt->GetClass();
6857         
6858         if (mt == cls->GetMethodTable())
6859             isValid = true;
6860         else if (!mt->IsCanonicalMethodTable())
6861             isValid = cls->GetMethodTable()->GetClass() == cls;
6862     }
6863     EX_CATCH
6864     {
6865         isValid = false;
6866     }
6867     EX_END_CATCH(SwallowAllExceptions)
6868     
6869     return isValid;
6870 }
6871
6872 bool DacDbiInterfaceImpl::GetAppDomainForObject(CORDB_ADDRESS addr, OUT VMPTR_AppDomain * pAppDomain,
6873                                                 OUT VMPTR_Module *pModule, OUT VMPTR_DomainFile *pDomainFile)
6874 {
6875     DD_ENTER_MAY_THROW;
6876     
6877     PTR_Object obj(TO_TADDR(addr));
6878     MethodTable *mt = obj->GetMethodTable();
6879
6880     PTR_Module module = mt->GetModule();
6881     PTR_Assembly assembly = module->GetAssembly();
6882     BaseDomain *baseDomain = assembly->GetDomain();
6883     
6884     if (baseDomain->IsSharedDomain())
6885     {
6886         pModule->SetDacTargetPtr(PTR_HOST_TO_TADDR(module));
6887         *pAppDomain = VMPTR_AppDomain::NullPtr();
6888         *pDomainFile = VMPTR_DomainFile::NullPtr();
6889     }
6890     else if (baseDomain->IsAppDomain())
6891     {
6892         pAppDomain->SetDacTargetPtr(PTR_HOST_TO_TADDR(baseDomain->AsAppDomain()));
6893         pModule->SetDacTargetPtr(PTR_HOST_TO_TADDR(module));
6894         pDomainFile->SetDacTargetPtr(PTR_HOST_TO_TADDR(module->GetDomainFile(baseDomain->AsAppDomain())));
6895     }
6896     else
6897     {
6898         return false;
6899     }
6900
6901     return true;
6902 }
6903
6904 HRESULT DacDbiInterfaceImpl::CreateRefWalk(OUT RefWalkHandle * pHandle, BOOL walkStacks, BOOL walkFQ, UINT32 handleWalkMask)
6905 {
6906     DD_ENTER_MAY_THROW;
6907     
6908     DacRefWalker *walker = new (nothrow) DacRefWalker(this, walkStacks, walkFQ, handleWalkMask);
6909     
6910     if (walker == NULL)
6911         return E_OUTOFMEMORY;
6912     
6913     HRESULT hr = walker->Init();
6914     if (FAILED(hr))
6915     {
6916         delete walker;
6917     }
6918     else
6919     {
6920         *pHandle = reinterpret_cast<RefWalkHandle>(walker);
6921     }
6922     
6923     return hr;
6924 }
6925
6926
6927 void DacDbiInterfaceImpl::DeleteRefWalk(IN RefWalkHandle handle)
6928 {
6929     DD_ENTER_MAY_THROW;
6930     
6931     DacRefWalker *walker = reinterpret_cast<DacRefWalker*>(handle);
6932     
6933     if (walker)
6934         delete walker;
6935 }
6936
6937
6938 HRESULT DacDbiInterfaceImpl::WalkRefs(RefWalkHandle handle, ULONG count, OUT DacGcReference * objects, OUT ULONG *pFetched)
6939 {
6940     if (objects == NULL || pFetched == NULL)
6941         return E_POINTER;
6942
6943     DD_ENTER_MAY_THROW;
6944     
6945     DacRefWalker *walker = reinterpret_cast<DacRefWalker*>(handle);
6946     if (!walker)
6947         return E_INVALIDARG;
6948    
6949    return walker->Next(count, objects, pFetched);
6950 }
6951
6952 HRESULT DacDbiInterfaceImpl::GetTypeID(CORDB_ADDRESS dbgObj, COR_TYPEID *pID)
6953 {
6954     DD_ENTER_MAY_THROW;
6955
6956     TADDR obj[3];
6957     ULONG32 read = 0;
6958     HRESULT hr = g_dacImpl->m_pTarget->ReadVirtual(dbgObj, (BYTE*)obj, sizeof(obj), &read);
6959     if (FAILED(hr))
6960         return hr;
6961
6962     pID->token1 = (UINT64)(obj[0] & ~1);
6963     pID->token2 = 0;
6964
6965     return hr;
6966 }
6967
6968 HRESULT DacDbiInterfaceImpl::GetTypeIDForType(VMPTR_TypeHandle vmTypeHandle, COR_TYPEID *pID)
6969 {
6970     DD_ENTER_MAY_THROW;
6971
6972     _ASSERTE(pID != NULL);
6973     _ASSERTE(!vmTypeHandle.IsNull());
6974
6975     TypeHandle th = TypeHandle::FromPtr(vmTypeHandle.GetDacPtr());
6976     PTR_MethodTable pMT = th.GetMethodTable();
6977     pID->token1 = pMT.GetAddr();
6978     _ASSERTE(pID->token1 != 0);
6979     pID->token2 = 0;
6980     return S_OK;
6981 }
6982
6983 HRESULT DacDbiInterfaceImpl::GetObjectFields(COR_TYPEID id, ULONG32 celt, COR_FIELD *layout, ULONG32 *pceltFetched)
6984 {
6985     if (layout == NULL || pceltFetched == NULL)
6986         return E_POINTER;
6987         
6988     if (id.token1 == 0)
6989         return CORDBG_E_CLASS_NOT_LOADED;
6990
6991     DD_ENTER_MAY_THROW;
6992     
6993     HRESULT hr = S_OK;
6994     
6995     TypeHandle typeHandle = TypeHandle::FromPtr(TO_TADDR(id.token1));
6996
6997     if (typeHandle.IsTypeDesc())
6998         return E_INVALIDARG;
6999     
7000     ApproxFieldDescIterator fieldDescIterator(typeHandle.AsMethodTable(), ApproxFieldDescIterator::INSTANCE_FIELDS);
7001     
7002     ULONG32 cFields = fieldDescIterator.Count();
7003
7004     // Handle case where user only wanted to know the number of fields.
7005     if (layout == NULL)
7006     {
7007         *pceltFetched = cFields;
7008         return S_FALSE;
7009     }
7010
7011     if (celt < cFields)
7012     {
7013         cFields = celt;
7014     
7015         // we are returning less than the total
7016         hr = S_FALSE;
7017     }
7018
7019     // This must be non-null due to check at beginning of function.
7020     *pceltFetched = celt;
7021     
7022     CorElementType componentType = typeHandle.AsMethodTable()->GetInternalCorElementType();
7023     BOOL fReferenceType = CorTypeInfo::IsObjRef_NoThrow(componentType);
7024     for (ULONG32 i = 0; i < cFields; ++i)
7025     {
7026         FieldDesc *pField = fieldDescIterator.Next();
7027         layout[i].token = pField->GetMemberDef();
7028         layout[i].offset = (ULONG32)pField->GetOffset() + (fReferenceType ? Object::GetOffsetOfFirstField() : 0);
7029         
7030         TypeHandle fieldHandle = pField->LookupFieldTypeHandle();
7031         
7032         if (fieldHandle.IsNull())
7033         {
7034             layout[i].id.token1 = 0;
7035             layout[i].id.token2 = 0;
7036             layout[i].fieldType = (CorElementType)0;
7037         }
7038         else
7039         {
7040             PTR_MethodTable mt = fieldHandle.GetMethodTable();
7041             layout[i].fieldType = mt->GetInternalCorElementType();
7042             layout[i].id.token1 = (ULONG64)mt.GetAddr();
7043             
7044             if (!mt->IsArray())
7045             {
7046                 layout[i].id.token2 = 0;
7047             }
7048             else
7049             {
7050                 TypeHandle hnd = mt->GetApproxArrayElementTypeHandle();
7051                 PTR_MethodTable cmt = hnd.GetMethodTable();
7052                 layout[i].id.token2 = (ULONG64)cmt.GetAddr();
7053             }
7054         }
7055     }
7056     
7057     return hr;
7058 }
7059
7060
7061 HRESULT DacDbiInterfaceImpl::GetTypeLayout(COR_TYPEID id, COR_TYPE_LAYOUT *pLayout)
7062 {
7063     if (pLayout == NULL)
7064         return E_POINTER;
7065         
7066     if (id.token1 == 0)
7067         return CORDBG_E_CLASS_NOT_LOADED;
7068
7069     DD_ENTER_MAY_THROW;
7070
7071     PTR_MethodTable mt = PTR_MethodTable(TO_TADDR(id.token1));
7072     PTR_MethodTable parentMT = mt->GetParentMethodTable();
7073     
7074     COR_TYPEID parent = {parentMT.GetAddr(), 0};
7075     pLayout->parentID = parent;
7076
7077     DWORD size = mt->GetBaseSize();
7078     ApproxFieldDescIterator fieldDescIterator(mt, ApproxFieldDescIterator::INSTANCE_FIELDS);
7079
7080     pLayout->objectSize = size;
7081     pLayout->numFields = fieldDescIterator.Count();
7082     
7083     // Get type
7084     CorElementType componentType = mt->IsString() ? ELEMENT_TYPE_STRING : mt->GetInternalCorElementType();
7085     pLayout->type = componentType;
7086     pLayout->boxOffset = CorTypeInfo::IsObjRef_NoThrow(componentType) ? 0 : sizeof(TADDR);
7087     
7088     return S_OK;
7089 }
7090
7091 HRESULT DacDbiInterfaceImpl::GetArrayLayout(COR_TYPEID id, COR_ARRAY_LAYOUT *pLayout)
7092 {
7093     if (pLayout == NULL)
7094         return E_POINTER;
7095         
7096     if (id.token1 == 0)
7097         return CORDBG_E_CLASS_NOT_LOADED;
7098
7099     DD_ENTER_MAY_THROW;
7100
7101     PTR_MethodTable mt = PTR_MethodTable(TO_TADDR(id.token1));
7102
7103     if (!mt->IsStringOrArray())
7104         return E_INVALIDARG;
7105     
7106     if (mt->IsString())
7107     {
7108         COR_TYPEID token;
7109         token.token1 = MscorlibBinder::GetElementType(ELEMENT_TYPE_CHAR).GetAddr();
7110         token.token2 = 0;
7111         
7112         pLayout->componentID = token;
7113         
7114         pLayout->rankSize = 4;
7115         pLayout->numRanks = 1;
7116         pLayout->rankOffset = sizeof(TADDR);
7117         pLayout->firstElementOffset = sizeof(TADDR) + 4;
7118         pLayout->countOffset = sizeof(TADDR);
7119         pLayout->componentType = ELEMENT_TYPE_CHAR;
7120         pLayout->elementSize = 2;
7121     }
7122     else
7123     {
7124         DWORD ranks = mt->GetRank();
7125         pLayout->rankSize = 4;
7126         pLayout->numRanks = ranks;
7127         bool multiDim = (ranks > 1);
7128
7129         pLayout->rankOffset = multiDim ? sizeof(TADDR)*2 : sizeof(TADDR);
7130         pLayout->countOffset = sizeof(TADDR);
7131         pLayout->firstElementOffset = ArrayBase::GetDataPtrOffset(mt);
7132     
7133  
7134         TypeHandle hnd = mt->GetApproxArrayElementTypeHandle();
7135         PTR_MethodTable cmt = hnd.GetMethodTable();
7136
7137         CorElementType componentType = cmt->GetInternalCorElementType();
7138         if ((UINT64)cmt.GetAddr() == (UINT64)g_pStringClass.GetAddr())
7139             componentType = ELEMENT_TYPE_STRING;
7140
7141         COR_TYPEID token;
7142         token.token1 = cmt.GetAddr();  // This could be type handle
7143         token.token2 = 0;
7144         pLayout->componentID = token;
7145         pLayout->componentType = componentType;
7146             
7147         if (CorTypeInfo::IsObjRef_NoThrow(componentType))
7148             pLayout->elementSize = sizeof(TADDR);
7149         else if (CorIsPrimitiveType(componentType))
7150             pLayout->elementSize = gElementTypeInfo[componentType].m_cbSize;
7151         else
7152             pLayout->elementSize = cmt->GetNumInstanceFieldBytes();
7153     }
7154     
7155     return S_OK;
7156 }
7157
7158
7159 void DacDbiInterfaceImpl::GetGCHeapInformation(COR_HEAPINFO * pHeapInfo)
7160 {
7161     DD_ENTER_MAY_THROW;
7162     
7163     size_t heapCount = 0;
7164     pHeapInfo->areGCStructuresValid = GCScan::GetGcRuntimeStructuresValid();
7165     
7166 #ifdef FEATURE_SVR_GC
7167     if (GCHeapUtilities::IsServerHeap())
7168     {
7169         pHeapInfo->gcType = CorDebugServerGC;
7170         pHeapInfo->numHeaps = DacGetNumHeaps();
7171     }
7172     else
7173 #endif
7174     {
7175         pHeapInfo->gcType = CorDebugWorkstationGC;
7176         pHeapInfo->numHeaps = 1;
7177     }
7178     
7179     pHeapInfo->pointerSize = sizeof(TADDR);
7180     pHeapInfo->concurrent = g_pConfig->GetGCconcurrent() ? TRUE : FALSE;
7181 }
7182
7183
7184 HRESULT DacDbiInterfaceImpl::GetPEFileMDInternalRW(VMPTR_PEFile vmPEFile, OUT TADDR* pAddrMDInternalRW)
7185 {
7186     DD_ENTER_MAY_THROW;
7187     if (pAddrMDInternalRW == NULL)
7188         return E_INVALIDARG;
7189     PEFile * pPEFile = vmPEFile.GetDacPtr();
7190     *pAddrMDInternalRW = pPEFile->GetMDInternalRWAddress();
7191     return S_OK;
7192 }
7193
7194 HRESULT DacDbiInterfaceImpl::GetReJitInfo(VMPTR_Module vmModule, mdMethodDef methodTk, OUT VMPTR_ReJitInfo* pvmReJitInfo)
7195 {
7196     DD_ENTER_MAY_THROW;
7197     if (pvmReJitInfo == NULL)
7198         return E_INVALIDARG;
7199 #ifdef FEATURE_REJIT
7200     PTR_Module pModule = vmModule.GetDacPtr();
7201     ReJitManager * pReJitMgr = pModule->GetReJitManager();
7202     PTR_ReJitInfo pReJitInfoCurrent = pReJitMgr->FindNonRevertedReJitInfo(pModule, methodTk);
7203     // if the token lookup failed, we need to search again by method desc
7204     // The rejit manager will index by token if the method isn't loaded when RequestReJIT runs
7205     // and by methoddesc if it was loaded
7206     if (pReJitInfoCurrent == NULL)
7207     {
7208         MethodDesc* pMD = pModule->LookupMethodDef(methodTk);
7209         if (pMD != NULL)
7210         {
7211             pReJitInfoCurrent = pReJitMgr->FindNonRevertedReJitInfo(dac_cast<PTR_MethodDesc>(pMD));
7212         }
7213     }
7214     pvmReJitInfo->SetDacTargetPtr(PTR_TO_TADDR(pReJitInfoCurrent));
7215 #else
7216     pvmReJitInfo->SetDacTargetPtr(0);
7217 #endif
7218     return S_OK;
7219 }
7220
7221 HRESULT DacDbiInterfaceImpl::GetReJitInfo(VMPTR_MethodDesc vmMethod, CORDB_ADDRESS codeStartAddress, OUT VMPTR_ReJitInfo* pvmReJitInfo)
7222 {
7223     DD_ENTER_MAY_THROW;
7224     if (pvmReJitInfo == NULL)
7225         return E_INVALIDARG;
7226 #ifdef FEATURE_REJIT
7227     PTR_MethodDesc pMD = vmMethod.GetDacPtr();
7228     ReJitManager * pReJitMgr = pMD->GetReJitManager();
7229     PTR_ReJitInfo pReJitInfoCurrent = pReJitMgr->FindReJitInfo(pMD, (PCODE)codeStartAddress, 0);
7230     pvmReJitInfo->SetDacTargetPtr(PTR_TO_TADDR(pReJitInfoCurrent));
7231 #else
7232     pvmReJitInfo->SetDacTargetPtr(0);
7233 #endif
7234     return S_OK;
7235 }
7236
7237 HRESULT DacDbiInterfaceImpl::GetSharedReJitInfo(VMPTR_ReJitInfo vmReJitInfo, OUT VMPTR_SharedReJitInfo* pvmSharedReJitInfo)
7238 {
7239     DD_ENTER_MAY_THROW;
7240     if (pvmSharedReJitInfo == NULL)
7241         return E_INVALIDARG;
7242 #ifdef FEATURE_REJIT
7243     ReJitInfo* pReJitInfo = vmReJitInfo.GetDacPtr();
7244     pvmSharedReJitInfo->SetDacTargetPtr(PTR_TO_TADDR(pReJitInfo->m_pShared));
7245 #else
7246     _ASSERTE(!"You shouldn't be calling this - how did you get a ReJitInfo?");
7247     pvmSharedReJitInfo->SetDacTargetPtr(0);
7248 #endif
7249     return S_OK;
7250 }
7251
7252 HRESULT DacDbiInterfaceImpl::GetSharedReJitInfoData(VMPTR_SharedReJitInfo vmSharedReJitInfo, DacSharedReJitInfo* pData)
7253 {
7254     DD_ENTER_MAY_THROW;
7255 #ifdef FEATURE_REJIT
7256     SharedReJitInfo* pSharedReJitInfo = vmSharedReJitInfo.GetDacPtr();
7257     pData->m_state = pSharedReJitInfo->GetState();
7258     pData->m_pbIL = PTR_TO_CORDB_ADDRESS(pSharedReJitInfo->m_pbIL);
7259     pData->m_dwCodegenFlags = pSharedReJitInfo->m_dwCodegenFlags;
7260     pData->m_cInstrumentedMapEntries = (ULONG)pSharedReJitInfo->m_instrumentedILMap.GetCount();
7261     pData->m_rgInstrumentedMapEntries = PTR_TO_CORDB_ADDRESS(dac_cast<ULONG_PTR>(pSharedReJitInfo->m_instrumentedILMap.GetOffsets()));
7262 #else
7263     _ASSERTE(!"You shouldn't be calling this - how did you get a SharedReJitInfo?");
7264 #endif
7265     return S_OK;
7266 }
7267
7268 HRESULT DacDbiInterfaceImpl::GetDefinesBitField(ULONG32 *pDefines)
7269 {
7270     DD_ENTER_MAY_THROW;
7271     if (pDefines == NULL)
7272         return E_INVALIDARG;
7273     *pDefines = g_pDebugger->m_defines;
7274     return S_OK;
7275 }
7276
7277 HRESULT DacDbiInterfaceImpl::GetMDStructuresVersion(ULONG32* pMDStructuresVersion)
7278 {
7279     DD_ENTER_MAY_THROW;
7280     if (pMDStructuresVersion == NULL)
7281         return E_INVALIDARG;
7282     *pMDStructuresVersion = g_pDebugger->m_mdDataStructureVersion;
7283     return S_OK;
7284 }
7285
7286
7287 DacRefWalker::DacRefWalker(ClrDataAccess *dac, BOOL walkStacks, BOOL walkFQ, UINT32 handleMask)
7288     : mDac(dac), mWalkStacks(walkStacks), mWalkFQ(walkFQ), mHandleMask(handleMask), mStackWalker(NULL),
7289       mHandleWalker(NULL), mFQStart(PTR_NULL), mFQEnd(PTR_NULL), mFQCurr(PTR_NULL)
7290 {
7291 }
7292
7293 DacRefWalker::~DacRefWalker()
7294 {
7295     Clear();
7296 }
7297
7298 HRESULT DacRefWalker::Init()
7299 {
7300     HRESULT hr = S_OK;
7301     if (mHandleMask)
7302     {
7303         // Will throw on OOM, which is fine.
7304         mHandleWalker = new DacHandleWalker();
7305         
7306         hr = mHandleWalker->Init(GetHandleWalkerMask());
7307     }
7308     
7309     if (mWalkStacks && SUCCEEDED(hr))
7310     {
7311         hr = NextThread();
7312     }
7313     
7314     return hr;
7315 }
7316
7317 void DacRefWalker::Clear()
7318 {
7319     if (mHandleWalker)
7320     {
7321         delete mHandleWalker;
7322         mHandleWalker = NULL;
7323     }
7324     
7325     if (mStackWalker)
7326     {
7327         delete mStackWalker;
7328         mStackWalker = NULL;
7329     }
7330 }
7331
7332
7333
7334 UINT32 DacRefWalker::GetHandleWalkerMask()
7335 {
7336     UINT32 result = 0;
7337     if (mHandleMask & CorHandleStrong)
7338         result |= (1 << HNDTYPE_STRONG);
7339         
7340     if (mHandleMask & CorHandleStrongPinning)
7341         result |= (1 << HNDTYPE_PINNED);
7342
7343     if (mHandleMask & CorHandleWeakShort)
7344         result |= (1 << HNDTYPE_WEAK_SHORT);
7345     
7346     if (mHandleMask & CorHandleWeakLong)
7347         result |= (1 << HNDTYPE_WEAK_LONG);
7348     
7349 #ifdef FEATURE_COMINTEROP
7350     if ((mHandleMask & CorHandleWeakRefCount) || (mHandleMask & CorHandleStrongRefCount))
7351         result |= (1 << HNDTYPE_REFCOUNTED);
7352
7353     if (mHandleMask & CorHandleWeakWinRT)
7354         result |= (1 << HNDTYPE_WEAK_WINRT);
7355 #endif // FEATURE_COMINTEROP
7356
7357     if (mHandleMask & CorHandleStrongDependent)
7358         result |= (1 << HNDTYPE_DEPENDENT);
7359         
7360     if (mHandleMask & CorHandleStrongAsyncPinned)
7361         result |= (1 << HNDTYPE_ASYNCPINNED);
7362         
7363     if (mHandleMask & CorHandleStrongSizedByref)
7364         result |= (1 << HNDTYPE_SIZEDREF);
7365     
7366     return result;
7367 }
7368
7369
7370     
7371 HRESULT DacRefWalker::Next(ULONG celt, DacGcReference roots[], ULONG *pceltFetched)
7372 {
7373     if (roots == NULL || pceltFetched == NULL)
7374         return E_POINTER;
7375         
7376     ULONG total = 0;
7377     HRESULT hr = S_OK;
7378     
7379     if (mHandleWalker)
7380     {
7381         hr = mHandleWalker->Next(celt, roots, &total);
7382         
7383         if (hr == S_FALSE || FAILED(hr))
7384         {
7385             delete mHandleWalker;
7386             mHandleWalker = NULL;
7387             
7388             if (FAILED(hr))
7389                 return hr;
7390         }
7391     }
7392     
7393     if (total < celt)
7394     {
7395         while (total < celt && mFQCurr < mFQEnd)
7396         {
7397             DacGcReference &ref = roots[total++];
7398             
7399             ref.vmDomain = VMPTR_AppDomain::NullPtr();
7400             ref.objHnd.SetDacTargetPtr(mFQCurr.GetAddr());
7401             ref.dwType = (DWORD)CorReferenceFinalizer;
7402             ref.i64ExtraData = 0;
7403             
7404             mFQCurr++;
7405         }
7406     }
7407     
7408     while (total < celt && mStackWalker)
7409     {
7410         ULONG fetched = 0;
7411         hr = mStackWalker->Next(celt-total, roots+total, &fetched);
7412
7413         if (FAILED(hr))
7414             return hr;
7415             
7416         if (hr == S_FALSE)
7417         {
7418             hr = NextThread();
7419             
7420             if (FAILED(hr))
7421                 return hr;
7422         }
7423         
7424         total += fetched;
7425     }
7426     
7427     *pceltFetched = total;
7428     
7429     return total < celt ? S_FALSE : S_OK;
7430 }
7431
7432 HRESULT DacRefWalker::NextThread()
7433 {
7434     Thread *pThread = NULL;
7435     if (mStackWalker)
7436     {
7437         pThread = mStackWalker->GetThread();
7438         delete mStackWalker;
7439         mStackWalker = NULL;
7440     }
7441     
7442     pThread = ThreadStore::GetThreadList(pThread);
7443     
7444     if (!pThread)
7445         return S_FALSE;
7446     
7447     mStackWalker = new DacStackReferenceWalker(mDac, pThread->GetOSThreadId());
7448     return mStackWalker->Init();
7449 }
7450
7451 HRESULT DacHandleWalker::Next(ULONG celt, DacGcReference roots[], ULONG *pceltFetched)
7452 {
7453     SUPPORTS_DAC;
7454     
7455     if (roots == NULL || pceltFetched == NULL)
7456         return E_POINTER;
7457       
7458     return DoHandleWalk<DacGcReference, ULONG, DacHandleWalker::EnumCallbackDac>(celt, roots, pceltFetched);
7459 }
7460
7461
7462 void CALLBACK DacHandleWalker::EnumCallbackDac(PTR_UNCHECKED_OBJECTREF handle, uintptr_t *pExtraInfo, uintptr_t param1, uintptr_t param2)
7463 {
7464     SUPPORTS_DAC;
7465     
7466     DacHandleWalkerParam *param = (DacHandleWalkerParam *)param1;
7467     HandleChunkHead *curr = param->Curr;
7468     
7469     // If we failed on a previous call (OOM) don't keep trying to allocate, it's not going to work.
7470     if (FAILED(param->Result))
7471         return;
7472     
7473     // We've moved past the size of the current chunk.  We'll allocate a new chunk
7474     // and stuff the handles there.  These are cleaned up by the destructor 
7475     if (curr->Count >= (curr->Size/sizeof(DacGcReference)))
7476     {
7477         if (curr->Next == NULL)
7478         {
7479             HandleChunk *next = new (nothrow) HandleChunk;
7480             if (next != NULL)
7481             {
7482                 curr->Next = next;
7483             }
7484             else
7485             {
7486                 param->Result = E_OUTOFMEMORY;
7487                 return;
7488             }
7489         }
7490         
7491         curr = param->Curr = param->Curr->Next;
7492     }
7493     
7494     // Fill the current handle.
7495     DacGcReference *dataArray = (DacGcReference*)curr->pData;
7496     DacGcReference &data = dataArray[curr->Count++];
7497     
7498     data.objHnd.SetDacTargetPtr(handle.GetAddr());
7499     data.vmDomain.SetDacTargetPtr(TO_TADDR(param->AppDomain));
7500     
7501     data.i64ExtraData = 0;
7502     unsigned int refCnt = 0;
7503     
7504     switch (param->Type)
7505     {
7506         case HNDTYPE_STRONG:
7507             data.dwType = (DWORD)CorHandleStrong;
7508             break;
7509             
7510         case HNDTYPE_PINNED:
7511             data.dwType = (DWORD)CorHandleStrongPinning;
7512             break;
7513             
7514         case HNDTYPE_WEAK_SHORT:
7515             data.dwType = (DWORD)CorHandleWeakShort;
7516             break;
7517             
7518         case HNDTYPE_WEAK_LONG:
7519             data.dwType = (DWORD)CorHandleWeakLong;
7520             break;
7521             
7522 #ifdef FEATURE_COMINTEROP
7523         case HNDTYPE_REFCOUNTED:
7524             data.dwType = (DWORD)(data.i64ExtraData ? CorHandleStrongRefCount : CorHandleWeakRefCount);
7525             GetRefCountedHandleInfo((OBJECTREF)*handle, param->Type, &refCnt, NULL, NULL, NULL);
7526             data.i64ExtraData = refCnt;
7527             break;
7528
7529         case HNDTYPE_WEAK_WINRT:
7530             data.dwType = (DWORD)CorHandleWeakWinRT;
7531             break;
7532 #endif
7533
7534         case HNDTYPE_DEPENDENT:
7535             data.dwType = (DWORD)CorHandleStrongDependent;
7536             data.i64ExtraData = GetDependentHandleSecondary(handle.GetAddr()).GetAddr();
7537             break;
7538             
7539         case HNDTYPE_ASYNCPINNED:
7540             data.dwType = (DWORD)CorHandleStrongAsyncPinned;
7541             break;
7542             
7543         case HNDTYPE_SIZEDREF:
7544             data.dwType = (DWORD)CorHandleStrongSizedByref;
7545             break;
7546     }
7547 }
7548
7549
7550 void DacStackReferenceWalker::GCEnumCallbackDac(LPVOID hCallback, OBJECTREF *pObject, uint32_t flags, DacSlotLocation loc)
7551 {
7552     GCCONTEXT *gcctx = (GCCONTEXT *)hCallback;
7553     DacScanContext *dsc = (DacScanContext*)gcctx->sc;
7554     
7555     CORDB_ADDRESS obj = 0;
7556     
7557     if (flags & GC_CALL_INTERIOR)
7558     {
7559         if (loc.targetPtr)
7560             obj = (CORDB_ADDRESS)(*PTR_PTR_Object((TADDR)pObject)).GetAddr();
7561         else
7562             obj = (CORDB_ADDRESS)TO_TADDR(pObject);
7563         
7564         HRESULT hr = dsc->pWalker->mHeap.ListNearObjects(obj, NULL, &obj, NULL);
7565         
7566         // If we failed don't add this instance to the list.  ICorDebug doesn't handle invalid pointers
7567         // very well, and the only way the heap walker's ListNearObjects will fail is if we have heap
7568         // corruption...which ICorDebug doesn't deal with anyway.
7569         if (FAILED(hr))
7570             return;
7571     }
7572     
7573     DacGcReference *data = dsc->pWalker->GetNextObject<DacGcReference>(dsc);
7574     if (data != NULL)
7575     {
7576         data->vmDomain.SetDacTargetPtr(dac_cast<PTR_AppDomain>(dsc->pCurrentDomain).GetAddr());
7577         if (obj)
7578             data->pObject = obj | 1;
7579         else if (loc.targetPtr)
7580             data->objHnd.SetDacTargetPtr(TO_TADDR(pObject));
7581         else
7582             data->pObject = pObject->GetAddr() | 1;
7583         
7584         data->dwType = CorReferenceStack;
7585         data->i64ExtraData = 0;
7586     }
7587 }
7588
7589
7590 void DacStackReferenceWalker::GCReportCallbackDac(PTR_PTR_Object ppObj, ScanContext *sc, uint32_t flags)
7591 {
7592     DacScanContext *dsc = (DacScanContext*)sc;
7593     
7594     TADDR obj = ppObj.GetAddr();
7595     if (flags & GC_CALL_INTERIOR)
7596     {
7597         CORDB_ADDRESS fixed_addr = 0;
7598         HRESULT hr = dsc->pWalker->mHeap.ListNearObjects((CORDB_ADDRESS)obj, NULL, &fixed_addr, NULL);
7599         
7600         // If we failed don't add this instance to the list.  ICorDebug doesn't handle invalid pointers
7601         // very well, and the only way the heap walker's ListNearObjects will fail is if we have heap
7602         // corruption...which ICorDebug doesn't deal with anyway.
7603         if (FAILED(hr))
7604             return;
7605             
7606         obj = TO_TADDR(fixed_addr);
7607     }
7608     
7609     DacGcReference *data = dsc->pWalker->GetNextObject<DacGcReference>(dsc);
7610     if (data != NULL)
7611     {
7612         data->vmDomain.SetDacTargetPtr(dac_cast<PTR_AppDomain>(dsc->pCurrentDomain).GetAddr());
7613         data->objHnd.SetDacTargetPtr(obj);
7614         data->dwType = CorReferenceStack;
7615         data->i64ExtraData = 0;
7616     }
7617 }
7618
7619
7620
7621 HRESULT DacStackReferenceWalker::Next(ULONG count, DacGcReference stackRefs[], ULONG *pFetched)
7622 {
7623     if (stackRefs == NULL || pFetched == NULL)
7624         return E_POINTER;
7625     
7626     HRESULT hr = DoStackWalk<ULONG, DacGcReference, 
7627                              DacStackReferenceWalker::GCReportCallbackDac,
7628                              DacStackReferenceWalker::GCEnumCallbackDac>
7629                                 (count, stackRefs, pFetched);
7630     
7631     return hr;
7632 }