[release/6.0] Fix enum memory code paths (#58076)
authorgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Wed, 25 Aug 2021 15:26:12 +0000 (08:26 -0700)
committerGitHub <noreply@github.com>
Wed, 25 Aug 2021 15:26:12 +0000 (08:26 -0700)
* Fix enum memory code paths

* Fix wks enumeration

Co-authored-by: Andrew Au <andrewau@microsoft.com>
src/coreclr/debug/daccess/request.cpp
src/coreclr/debug/daccess/request_common.h
src/coreclr/debug/daccess/request_svr.cpp

index 6ffcc76..71a7528 100644 (file)
@@ -3780,24 +3780,24 @@ ClrDataAccess::EnumWksGlobalMemoryRegions(CLRDataEnumMemoryFlags flags)
     Dereference(g_gcDacGlobals->finalize_queue).EnumMem();
 
     // Enumerate the entire generation table, which has variable size
-    size_t gen_table_size = g_gcDacGlobals->generation_size * (*g_gcDacGlobals->max_gen + 2);
-    DacEnumMemoryRegion(dac_cast<TADDR>(g_gcDacGlobals->generation_table), gen_table_size);
+    EnumGenerationTable(dac_cast<TADDR>(g_gcDacGlobals->generation_table));
 
     if (g_gcDacGlobals->generation_table.IsValid())
     {
-            // enumerating the generations from max (which is normally gen2) to max+1 gives you
-            // the segment list for all the normal segements plus the large heap segment (max+1)
-            // this is the convention in the GC so it is repeated here
-            for (ULONG i = *g_gcDacGlobals->max_gen; i <= *g_gcDacGlobals->max_gen +1; i++)
+        ULONG first = IsRegion() ? 0 : (*g_gcDacGlobals->max_gen);
+        // enumerating the first to max + 2 gives you
+        // the segment list for all the normal segments plus the pinned heap segment (max + 2)
+        // this is the convention in the GC so it is repeated here
+        for (ULONG i = first; i <= *g_gcDacGlobals->max_gen + 2; i++)
+        {
+            dac_generation gen = GenerationTableIndex(g_gcDacGlobals->generation_table, i);
+            __DPtr<dac_heap_segment> seg = dac_cast<TADDR>(gen.start_segment);
+            while (seg)
             {
-                dac_generation gen = GenerationTableIndex(g_gcDacGlobals->generation_table, i);
-                __DPtr<dac_heap_segment> seg = dac_cast<TADDR>(gen.start_segment);
-                while (seg)
-                {
-                    DacEnumMemoryRegion(dac_cast<TADDR>(seg), sizeof(dac_heap_segment));
-                    seg = seg->next;
-                }
+                DacEnumMemoryRegion(dac_cast<TADDR>(seg), sizeof(dac_heap_segment));
+                seg = seg->next;
             }
+        }
     }
 }
 
index e6c976f..742d24f 100644 (file)
@@ -63,6 +63,15 @@ HeapTableIndex(DPTR(unused_gc_heap**) heaps, size_t index)
     }
 
 // if (field_offset != -1)
+//    p_field.EnumMem();
+#define ENUM(field_name, field_type)                                                         \
+    LOAD_BASE(field_name, field_type)                                                        \
+    if (field_name##_offset != -1)                                                           \
+    {                                                                                        \
+        p_##field_name.EnumMem();                                                            \
+    }
+
+// if (field_offset != -1)
 //    result.field = DPTR(field_type)field_name
 #define LOAD_DPTR(field_name, field_type)                                                    \
     LOAD_BASE(field_name, field_type*)                                                       \
@@ -87,6 +96,13 @@ HeapTableIndex(DPTR(unused_gc_heap**) heaps, size_t index)
         }                                                                                    \
     }
 
+#define ENUM_ARRAY(field_name, field_type, array_length)                                     \
+    LOAD_BASE(field_name, field_type)                                                        \
+    if (field_name##_offset != -1)                                                           \
+    {                                                                                        \
+        DacEnumMemoryRegion(p_##field_name.GetAddr(), sizeof(field_type) * array_length);    \
+    }
+
 inline bool IsRegion()
 {
     return (g_gcDacGlobals->minor_version_number & 1) != 0;
@@ -121,6 +137,26 @@ LoadGcHeapData(TADDR heap)
     return result;
 }
 
+inline void EnumGcHeap(TADDR heap)
+{
+    DPTR(int) field_offsets = g_gcDacGlobals->gc_heap_field_offsets;
+    int field_index = 0;
+
+#define BASE heap
+#define ALL_FIELDS
+#define DEFINE_FIELD(field_name, field_type) ENUM(field_name, field_type)
+#define DEFINE_DPTR_FIELD(field_name, field_type) ENUM(field_name, field_type)
+#define DEFINE_ARRAY_FIELD(field_name, field_type, array_length) ENUM_ARRAY(field_name, field_type, array_length)
+
+#include "../../gc/dac_gcheap_fields.h"
+
+#undef DEFINE_ARRAY_FIELD
+#undef DEFINE_DPTR_FIELD
+#undef DEFINE_FIELD
+#undef ALL_FIELDS
+#undef BASE
+}
+
 // Load an instance of dac_generation for the generation pointed by generation.
 // Fields that does not exist in the current generation instance is zero initialized.
 // Return the dac_generation object.
@@ -148,6 +184,26 @@ LoadGeneration(TADDR generation)
     return result;
 }
 
+inline void EnumGeneration(TADDR generation)
+{
+    DPTR(int) field_offsets = g_gcDacGlobals->generation_field_offsets;
+    int field_index = 0;
+
+#define BASE generation
+#define ALL_FIELDS
+#define DEFINE_FIELD(field_name, field_type) ENUM(field_name, field_type)
+#define DEFINE_DPTR_FIELD(field_name, field_type) ENUM(field_name, field_type)
+#define DEFINE_ARRAY_FIELD(field_name, field_type, array_length) ENUM_ARRAY(field_name, field_type, array_length)
+
+#include "../../gc/dac_generation_fields.h"
+
+#undef DEFINE_ARRAY_FIELD
+#undef DEFINE_DPTR_FIELD
+#undef DEFINE_FIELD
+#undef ALL_FIELDS
+#undef BASE
+}
+
 // Indexes into a given generation table, returning a dac_generation
 inline dac_generation
 GenerationTableIndex(DPTR(unused_generation) base, size_t index)
@@ -155,10 +211,7 @@ GenerationTableIndex(DPTR(unused_generation) base, size_t index)
     return LoadGeneration(TableIndex(base, index, g_gcDacGlobals->generation_size).GetAddr());
 }
 
-// Indexes into a heap's generation table, given the heap instance
-// and the desired index. Returns a dac_generation
-inline dac_generation
-ServerGenerationTableIndex(TADDR heap, size_t index)
+inline TADDR ServerGenerationTableAddress(TADDR heap)
 {
     DPTR(int) field_offsets = g_gcDacGlobals->gc_heap_field_offsets;
     int field_index = GENERATION_TABLE_FIELD_INDEX;
@@ -166,9 +219,27 @@ ServerGenerationTableIndex(TADDR heap, size_t index)
     LOAD_BASE (generation_table, unused_generation);
     #undef BASE
     assert (generation_table_offset != -1);
+    return p_generation_table.GetAddr();
+}
+
+// Indexes into a heap's generation table, given the heap instance
+// and the desired index. Returns a dac_generation
+inline dac_generation
+ServerGenerationTableIndex(TADDR heap, size_t index)
+{
+    DPTR(unused_generation) p_generation_table = ServerGenerationTableAddress(heap);
     return LoadGeneration(TableIndex(p_generation_table, index, g_gcDacGlobals->generation_size).GetAddr());
 }
 
+inline void EnumGenerationTable(TADDR generation_table)
+{
+    DPTR(unused_generation) p_generation_table = generation_table;
+    for (unsigned int i = 0; i < *g_gcDacGlobals->max_gen + 2; i++)
+    {
+        EnumGeneration(TableIndex(p_generation_table, i, g_gcDacGlobals->generation_size).GetAddr());
+    }
+}
+
 #undef LOAD_ARRAY
 #undef LOAD_DPTR
 #undef LOAD
index 5ff14b0..afe3e9d 100644 (file)
@@ -252,21 +252,19 @@ ClrDataAccess::EnumSvrGlobalMemoryRegions(CLRDataEnumMemoryFlags flags)
 
     for (int i = 0; i < heaps; i++)
     {
-        TADDR heapAddress = HeapTableIndex(g_gcDacGlobals->g_heaps, i);    
+        TADDR heapAddress = HeapTableIndex(g_gcDacGlobals->g_heaps, i);
         dac_gc_heap heap = LoadGcHeapData(heapAddress);
         dac_gc_heap* pHeap = &heap;
-
-        size_t gen_table_size = g_gcDacGlobals->generation_size * (*g_gcDacGlobals->max_gen + 2);
-        DacEnumMemoryRegion(dac_cast<TADDR>(pHeap), sizeof(dac_gc_heap));
+        EnumGcHeap(heapAddress);
+        TADDR generationTable = ServerGenerationTableAddress(heapAddress);
+        EnumGenerationTable(generationTable);
         DacEnumMemoryRegion(dac_cast<TADDR>(pHeap->finalize_queue), sizeof(dac_finalize_queue));
 
-        TADDR taddrTable = dac_cast<TADDR>(pHeap) + offsetof(dac_gc_heap, generation_table);
-        DacEnumMemoryRegion(taddrTable, gen_table_size);
-
-        // enumerating the generations from max (which is normally gen2) to max+1 gives you
-        // the segment list for all the normal segements plus the large heap segment (max+1)
+        ULONG first = IsRegion() ? 0 : (*g_gcDacGlobals->max_gen);
+        // enumerating the first to max + 2 gives you
+        // the segment list for all the normal segments plus the pinned heap segment (max + 2)
         // this is the convention in the GC so it is repeated here
-        for (ULONG i = *g_gcDacGlobals->max_gen; i <= *g_gcDacGlobals->max_gen +1; i++)
+        for (ULONG i = first; i <= *g_gcDacGlobals->max_gen + 2; i++)
         {
             dac_generation generation = ServerGenerationTableIndex(heapAddress, i);
             DPTR(dac_heap_segment) seg = generation.start_segment;