From 0c557e5a94d3e91f6695c62179354f8025e4c73a Mon Sep 17 00:00:00 2001 From: Jan Vorlicek Date: Sun, 27 Oct 2019 14:50:56 -0700 Subject: [PATCH] Fix GCRefMap generation in crossgen2 (dotnet/coreclr#27484) 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 --- .../DependencyAnalysis/ReadyToRun/GCRefMapNode.cs | 12 ++++++------ src/coreclr/src/tools/r2rdump/R2RImportSection.cs | 21 +++++++++++++++++---- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/GCRefMapNode.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/GCRefMapNode.cs index 496f5df..156f6fc 100644 --- a/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/GCRefMapNode.cs +++ b/src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/GCRefMapNode.cs @@ -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); diff --git a/src/coreclr/src/tools/r2rdump/R2RImportSection.cs b/src/coreclr/src/tools/r2rdump/R2RImportSection.cs index b0ebcf0..8b2ab0d 100644 --- a/src/coreclr/src/tools/r2rdump/R2RImportSection.cs +++ b/src/coreclr/src/tools/r2rdump/R2RImportSection.cs @@ -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; } } -- 2.7.4