}
}
+void HeapTraverser::PrintLoaderAllocator(size_t memberValue)
+{
+ if (m_format == FORMAT_XML)
+ {
+ fprintf(m_file,
+ " <loaderallocator address=\"0x%p\"/>\n",
+ (PBYTE)memberValue);
+ }
+ else if (m_format == FORMAT_CLRPROFILER)
+ {
+ fprintf(m_file,
+ " 0x%p",
+ (PBYTE)memberValue);
+ }
+}
+
void HeapTraverser::PrintObjectMember(size_t memberValue, bool dependentHandle)
{
if (m_format==FORMAT_XML)
MethodTableInfo* info = g_special_mtCache.Lookup((DWORD_PTR)methodTable);
_ASSERTE(info->IsInitialized()); // This is the second pass, so we should be initialized
- if (!info->bContainsPointers)
+ if (!info->bContainsPointers && !info->bCollectible)
return;
- // Fetch the GCInfo from the other process
- CGCDesc *map = info->GCInfo;
- if (map == NULL)
+ if (info->bContainsPointers)
{
- INT_PTR nEntries;
- move_xp (nEntries, dwAddr-sizeof(PVOID));
- bool arrayOfVC = false;
- if (nEntries<0)
- {
- arrayOfVC = true;
- nEntries = -nEntries;
- }
-
- size_t nSlots = 1+nEntries*sizeof(CGCDescSeries)/sizeof(DWORD_PTR);
- info->GCInfoBuffer = new DWORD_PTR[nSlots];
- if (info->GCInfoBuffer == NULL)
+ // Fetch the GCInfo from the other process
+ CGCDesc *map = info->GCInfo;
+ if (map == NULL)
{
- ReportOOM();
- return;
- }
+ INT_PTR nEntries;
+ move_xp (nEntries, dwAddr-sizeof(PVOID));
+ bool arrayOfVC = false;
+ if (nEntries<0)
+ {
+ arrayOfVC = true;
+ nEntries = -nEntries;
+ }
- if (FAILED(rvCache->Read(TO_CDADDR(dwAddr - nSlots*sizeof(DWORD_PTR)),
- info->GCInfoBuffer, (ULONG) (nSlots*sizeof(DWORD_PTR)), NULL)))
- return;
-
- map = info->GCInfo = (CGCDesc*)(info->GCInfoBuffer+nSlots);
- info->ArrayOfVC = arrayOfVC;
+ size_t nSlots = 1+nEntries*sizeof(CGCDescSeries)/sizeof(DWORD_PTR);
+ info->GCInfoBuffer = new DWORD_PTR[nSlots];
+ if (info->GCInfoBuffer == NULL)
+ {
+ ReportOOM();
+ return;
+ }
+
+ if (FAILED(rvCache->Read(TO_CDADDR(dwAddr - nSlots*sizeof(DWORD_PTR)),
+ info->GCInfoBuffer, (ULONG) (nSlots*sizeof(DWORD_PTR)), NULL)))
+ return;
+
+ map = info->GCInfo = (CGCDesc*)(info->GCInfoBuffer+nSlots);
+ info->ArrayOfVC = arrayOfVC;
+ }
}
mCache.EnsureRangeInCache((TADDR)obj, (unsigned int)size);
for (sos::RefIterator itr(obj, info->GCInfo, info->ArrayOfVC, &mCache); itr; ++itr)
{
if (*itr && (!m_verify || sos::IsObject(*itr)))
- PrintObjectMember(*itr, false);
+ {
+ if (itr.IsLoaderAllocator())
+ {
+ PrintLoaderAllocator(*itr);
+ }
+ else
+ {
+ PrintObjectMember(*itr, false);
+ }
+ }
}
std::unordered_map<TADDR, std::list<TADDR>>::iterator itr = mDependentHandleMap.find((TADDR)obj);
return Status;
}
+ DacpMethodTableCollectibleData vMethTableCollectible;
+ vMethTableCollectible.Request(g_sos, TO_CDADDR(dwStartAddr));
+
table.WriteRow("EEClass:", EEClassPtr(vMethTable.Class));
table.WriteRow("Module:", ModulePtr(vMethTable.Module));
table.WriteRow("mdToken:", Pointer(vMethTable.cl));
table.WriteRow("File:", fileName[0] ? fileName : W("Unknown Module"));
+ if (vMethTableCollectible.LoaderAllocatorObjectHandle != NULL)
+ {
+ TADDR loaderAllocator;
+ if (SUCCEEDED(MOVE(loaderAllocator, vMethTableCollectible.LoaderAllocatorObjectHandle)))
+ {
+ table.WriteRow("LoaderAllocator:", ObjectPtr(loaderAllocator));
+ }
+ }
+
table.WriteRow("BaseSize:", PrefixHex(vMethTable.BaseSize));
table.WriteRow("ComponentSize:", PrefixHex(vMethTable.ComponentSize));
table.WriteRow("Slots in VTable:", Decimal(vMethTable.wNumMethods));