Support for dumping GC info in R2RDump (dotnet/coreclr#22216)
authorTomáš Rylek <trylek@microsoft.com>
Thu, 31 Jan 2019 23:10:58 +0000 (00:10 +0100)
committerGitHub <noreply@github.com>
Thu, 31 Jan 2019 23:10:58 +0000 (00:10 +0100)
Thanks to tons of help from Jan Vorlicek I found out that a huge
failure bucket in the CoreCLR Pridotnet/coreclr#1 tests is caused by incorrect
GC info for generic methods causing failures in catch clauses
where the exception type is a generic referring to a generic
parameter of the method.

As part of investigation of this issue I'm adding provisions for
dumping the GC info alongside methods to make the differences
between CPAOT and Crossgen easier to analyze.

For now I have only implemented the AMD64 variant of the GC info.
Thankfully it turns out that the same GC info is used by both ARM32
and ARM64 so that the only remaining debt is supplying a variant
of the new code for X86.

Thanks

Tomas

Commit migrated from https://github.com/dotnet/coreclr/commit/d59e2b71b85c4b52eede67d41d31617dbd51bc90

src/coreclr/src/tools/r2rdump/R2RMethod.cs

index 27f2185..36f3dd0 100644 (file)
@@ -199,6 +199,49 @@ namespace R2RDump
             }
             writer.WriteLine();
 
+            if (Method.GcInfo is Amd64.GcInfo gcInfo)
+            {
+                writer.WriteLine("GC info:");
+                writer.WriteLine($@"    Version:                           {gcInfo.Version}");
+                writer.WriteLine($@"    ReturnKind:                        {gcInfo.ReturnKind}");
+                writer.WriteLine($@"    ValidRangeStart:                   0x{gcInfo.ValidRangeStart:X4}");
+                writer.WriteLine($@"    ValidRangeEnd:                     0x{gcInfo.ValidRangeEnd:X4}");
+                writer.WriteLine($@"    SecurityObjectStackSlot:           0x{gcInfo.SecurityObjectStackSlot:X4}");
+                writer.WriteLine($@"    GSCookieStackSlot:                 0x{gcInfo.GSCookieStackSlot:X4}");
+                writer.WriteLine($@"    PSPSymStackSlot:                   0x{gcInfo.PSPSymStackSlot:X4}");
+                writer.WriteLine($@"    GenericsInstContextStackSlot:      0x{gcInfo.GenericsInstContextStackSlot:X4}");
+                writer.WriteLine($@"    StackBaseRegister:                 {gcInfo.StackBaseRegister}");
+                writer.WriteLine($@"    SizeOfENCPreservedArea:            0x{gcInfo.SizeOfEditAndContinuePreservedArea:X4}");
+                writer.WriteLine($@"    ReversePInvokeFrameStackSlot:      0x{gcInfo.ReversePInvokeFrameStackSlot:X4}");
+                writer.WriteLine($@"    SizeOfStackOutgoingAndScratchArea: 0x{gcInfo.SizeOfStackOutgoingAndScratchArea:X4}");
+                writer.WriteLine($@"    NumSafePoints:                     {gcInfo.NumSafePoints}");
+                writer.WriteLine($@"    NumInterruptibleRanges:            {gcInfo.NumInterruptibleRanges}");
+
+                writer.WriteLine($@"    SafePointOffsets: {gcInfo.SafePointOffsets.Count}");
+                foreach (Amd64.GcInfo.SafePointOffset safePoint in gcInfo.SafePointOffsets)
+                {
+                    writer.WriteLine($@"        Index: {safePoint.Index,2}; Value: 0x{safePoint.Value:X4}");
+                }
+
+                writer.WriteLine($@"    InterruptibleRanges: {gcInfo.InterruptibleRanges.Count}");
+                foreach (Amd64.InterruptibleRange range in gcInfo.InterruptibleRanges)
+                {
+                    writer.WriteLine($@"        Index: {range.Index,2}; StartOffset: 0x{range.StartOffset:X4}; StopOffset: 0x{range.StopOffset:X4}");
+                }
+
+                writer.WriteLine("    SlotTable:");
+                writer.WriteLine($@"        NumRegisters:  {gcInfo.SlotTable.NumRegisters}");
+                writer.WriteLine($@"        NumStackSlots: {gcInfo.SlotTable.NumStackSlots}");
+                writer.WriteLine($@"        NumUntracked:  {gcInfo.SlotTable.NumUntracked}");
+                writer.WriteLine($@"        NumSlots:      {gcInfo.SlotTable.NumSlots}");
+                writer.WriteLine($@"        GcSlots:       {gcInfo.SlotTable.GcSlots.Count}");
+                foreach (Amd64.GcSlotTable.GcSlot slot in gcInfo.SlotTable.GcSlots)
+                {
+                    writer.WriteLine($@"            Index: {slot.Index,2}; RegisterNumber: {slot.RegisterNumber,2}; Flags: {slot.Flags}");
+                }
+                writer.WriteLine();
+            }
+
             if (EHInfo != null)
             {
                 writer.WriteLine($@"EH info @ {EHInfo.EHInfoRVA:X4}, #clauses = {EHInfo.EHClauses.Length}");
@@ -403,7 +446,7 @@ namespace R2RDump
                     writer.Write("    ");
                     if (!options.Naked)
                     {
-                        writer.WriteLine($"TableIndex {cell.TableIndex}, Offset {cell.CellOffset:X4}: ");
+                        writer.Write($"TableIndex {cell.TableIndex}, Offset {cell.CellOffset:X4}: ");
                     }
                     writer.WriteLine(cell.Signature);
                 }