Fix GCRefMap generation in crossgen2 (dotnet/coreclr#27484)
authorJan Vorlicek <janvorli@microsoft.com>
Sun, 27 Oct 2019 21:50:56 +0000 (14:50 -0700)
committerGitHub <noreply@github.com>
Sun, 27 Oct 2019 21:50:56 +0000 (14:50 -0700)
There was a bug in the index table - it was pointing to the last
GCRefMap in the previous stride instead of the first one in the new
stride.

I've modified R2RDump too to use the index table when loading GCRefMaps.
While it was not incorrect, the fact that it was not using the index
table has hidden this issue. Now it uses the same algorithm as the
runtime.

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

src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/GCRefMapNode.cs
src/coreclr/src/tools/r2rdump/R2RImportSection.cs

index 496f5df..156f6fc 100644 (file)
@@ -78,12 +78,6 @@ namespace ILCompiler.DependencyAnalysis.ReadyToRun
             int nextMethodIndex = GCREFMAP_LOOKUP_STRIDE - 1;
             for (int methodIndex = 0; methodIndex < _methods.Count; methodIndex++)
             {
-                if (methodIndex >= nextMethodIndex)
-                {
-                    builder.Builder.EmitInt(offsets[nextOffsetIndex], builder.Builder.CountBytes);
-                    nextOffsetIndex++;
-                    nextMethodIndex += GCREFMAP_LOOKUP_STRIDE;
-                }
                 IMethodNode methodNode = _methods[methodIndex];
                 if (methodNode == null || (methodNode is MethodWithGCInfo methodWithGCInfo && methodWithGCInfo.IsEmpty))
                 {
@@ -95,6 +89,12 @@ namespace ILCompiler.DependencyAnalysis.ReadyToRun
                 {
                     builder.GetCallRefMap(methodNode.Method);
                 }
+                if (methodIndex >= nextMethodIndex)
+                {
+                    builder.Builder.EmitInt(offsets[nextOffsetIndex], builder.Builder.CountBytes);
+                    nextOffsetIndex++;
+                    nextMethodIndex += GCREFMAP_LOOKUP_STRIDE;
+                }
             }
             Debug.Assert(nextOffsetIndex == offsets.Length);
 
index b0ebcf0..8b2ab0d 100644 (file)
@@ -126,16 +126,29 @@ namespace R2RDump
             AuxiliaryDataSize = 0;
             if (AuxiliaryDataRVA != 0)
             {
-                int startOffset = auxDataOffset + BitConverter.ToInt32(reader.Image, auxDataOffset);
+                int endOffset = auxDataOffset + BitConverter.ToInt32(reader.Image, auxDataOffset);
 
                 for (int i = 0; i < Entries.Count; i++)
                 {
-                    GCRefMapDecoder decoder = new GCRefMapDecoder(reader, startOffset);
+                    int entryStartOffset = auxDataOffset + BitConverter.ToInt32(reader.Image, auxDataOffset + sizeof(int) * (Entries[i].Index / GCRefMap.GCREFMAP_LOOKUP_STRIDE));
+                    int remaining = Entries[i].Index % GCRefMap.GCREFMAP_LOOKUP_STRIDE;
+                    while (remaining != 0)
+                    {
+                        while ((reader.Image[entryStartOffset] & 0x80) != 0)
+                        {
+                            entryStartOffset++;
+                        }
+
+                        entryStartOffset++;
+                        remaining--;
+                    }
+
+                    GCRefMapDecoder decoder = new GCRefMapDecoder(reader, entryStartOffset);
                     Entries[i].GCRefMap = decoder.ReadMap();
-                    startOffset = decoder.GetOffset();
+                    endOffset = decoder.GetOffset();
                 }
 
-                AuxiliaryDataSize = startOffset - auxDataOffset;
+                AuxiliaryDataSize = endOffset - auxDataOffset;
             }
         }