Fix FieldRVA handling of Field tokens (#35557)
authorSimon Nattress <nattress@gmail.com>
Wed, 29 Apr 2020 03:41:42 +0000 (20:41 -0700)
committerGitHub <noreply@github.com>
Wed, 29 Apr 2020 03:41:42 +0000 (20:41 -0700)
FieldRefs in the metadata tables are variable sized. We assumed the common 2 byte encoding, but if there are at least 0x10000 fields in the assembly 4 bytes are used in all tables with FieldRefs, including the FieldRva table we walk and patch.

Use row size to make sure we adjust based on the encoding, and preserve it when rewriting the metadata.

src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedFieldRvaNode.cs
src/coreclr/src/tools/crossgen2/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedMetadataBlobNode.cs

index ca3ca21..7c5240f 100644 (file)
@@ -60,11 +60,20 @@ namespace ILCompiler.DependencyAnalysis.ReadyToRun
             MetadataReader metadataReader = _module.MetadataReader;
             BlobReader metadataBlob = new BlobReader(_module.PEReader.GetMetadata().Pointer, _module.PEReader.GetMetadata().Length);
             metadataBlob.Offset = metadataReader.GetTableMetadataOffset(TableIndex.FieldRva);
-
+            bool compressedFieldRef = 6 == metadataReader.GetTableRowSize(TableIndex.FieldRva);
+            
             for (int i = 1; i <= metadataReader.GetTableRowCount(TableIndex.FieldRva); i++)
             {
                 int currentFieldRva = metadataBlob.ReadInt32();
-                short currentFieldRid = metadataBlob.ReadInt16();
+                int currentFieldRid;
+                if (compressedFieldRef)
+                {
+                    currentFieldRid = metadataBlob.ReadInt16();
+                }
+                else
+                {
+                    currentFieldRid = metadataBlob.ReadInt32();
+                }
                 if (currentFieldRva != _rva)
                     continue;
 
index 4160a9e..aedf303 100644 (file)
@@ -73,7 +73,8 @@ namespace ILCompiler.DependencyAnalysis.ReadyToRun
             MetadataReader metadataReader = _sourceModule.MetadataReader;
             var tableIndex = TableIndex.FieldRva;
             int rowCount = metadataReader.GetTableRowCount(tableIndex);
-
+            bool compressedFieldRef = 6 == metadataReader.GetTableRowSize(TableIndex.FieldRva);
+            
             for (int i = 1; i <= rowCount; i++)
             {
                 Debug.Assert(builder.CountBytes == reader.Offset);
@@ -81,13 +82,28 @@ namespace ILCompiler.DependencyAnalysis.ReadyToRun
                 // Rva
                 reader.ReadInt32();
 
-                short fieldToken = reader.ReadInt16();
+                int fieldToken;
+                if (compressedFieldRef)
+                {
+                    fieldToken = reader.ReadInt16();
+                }
+                else
+                {
+                    fieldToken = reader.ReadInt32();
+                }
                 EntityHandle fieldHandle = MetadataTokens.EntityHandle(TableIndex.Field, fieldToken);
                 EcmaField fieldDesc = (EcmaField)_sourceModule.GetField(fieldHandle);
                 Debug.Assert(fieldDesc.HasRva);
 
                 builder.EmitReloc(factory.CopiedFieldRva(fieldDesc), RelocType.IMAGE_REL_BASED_ADDR32NB);
-                builder.EmitShort(fieldToken);
+                if (compressedFieldRef)
+                {
+                    builder.EmitUShort((ushort)fieldToken);
+                }
+                else
+                {
+                    builder.EmitUInt((uint)fieldToken);
+                }
             }
         }