R2RDump fixes for parsing composite images (#34429)
authorTomáš Rylek <trylek@microsoft.com>
Thu, 2 Apr 2020 12:52:48 +0000 (14:52 +0200)
committerGitHub <noreply@github.com>
Thu, 2 Apr 2020 12:52:48 +0000 (14:52 +0200)
1. Fixed several inconsistencies w.r.t. signature context in
recursive descent into generic signatures based on offline
investigation with JanV.

2. Don't crash the dump upon invalid UTF8 characters.

Thanks

Tomas

src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/ReadyToRunReader.cs
src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/ReadyToRunSignature.cs
src/coreclr/src/tools/r2rdump/R2RDump.cs

index fd60500..3683fe9 100644 (file)
@@ -703,8 +703,8 @@ namespace ILCompiler.Reflection.ReadyToRun
             NativeParser curParser = allEntriesEnum.GetNext();
             while (!curParser.IsNull())
             {
-                SignatureDecoder decoder = new SignatureDecoder(_assemblyResolver, this, (int)curParser.Offset);
                 MetadataReader mdReader = _composite ? null : _assemblyCache[0];
+                SignatureDecoder decoder = new SignatureDecoder(_assemblyResolver, mdReader, this, (int)curParser.Offset);
 
                 string owningType = null;
 
index b1425ba..a59bda4 100644 (file)
@@ -41,7 +41,7 @@ namespace ILCompiler.Reflection.ReadyToRun
 
         public static string FormatSignature(IAssemblyResolver assemblyResolver, ReadyToRunReader r2rReader, int imageOffset)
         {
-            SignatureDecoder decoder = new SignatureDecoder(assemblyResolver, r2rReader, imageOffset);
+            SignatureDecoder decoder = new SignatureDecoder(assemblyResolver, r2rReader.GetGlobalMetadataReader(), r2rReader, imageOffset);
             string result = decoder.ReadR2RSignature();
             return result;
         }
@@ -351,7 +351,12 @@ namespace ILCompiler.Reflection.ReadyToRun
         private readonly MetadataReader _metadataReader;
 
         /// <summary>
-        /// ECMA reader representing the top-level signature context.
+        /// Outer ECMA reader is used as the default context for generic parameters.
+        /// </summary>
+        private readonly MetadataReader _outerReader;
+
+        /// <summary>
+        /// ECMA reader representing the reference module of the signature being decoded.
         /// </summary>
         private readonly ReadyToRunReader _contextReader;
 
@@ -381,9 +386,10 @@ namespace ILCompiler.Reflection.ReadyToRun
         /// <param name="options">Dump options and paths</param>
         /// <param name="r2rReader">R2RReader object representing the PE file containing the ECMA metadata</param>
         /// <param name="offset">Signature offset within the PE file byte array</param>
-        public SignatureDecoder(IAssemblyResolver options, ReadyToRunReader r2rReader, int offset)
+        public SignatureDecoder(IAssemblyResolver options, MetadataReader metadataReader, ReadyToRunReader r2rReader, int offset)
         {
-            _metadataReader = r2rReader.GetGlobalMetadataReader();
+            _metadataReader = metadataReader;
+            _outerReader = metadataReader;
             _options = options;
             _image = r2rReader.Image;
             _offset = offset;
@@ -397,30 +403,15 @@ namespace ILCompiler.Reflection.ReadyToRun
         /// <param name="metadataReader">Metadata reader for the R2R image</param>
         /// <param name="signature">Signature to parse</param>
         /// <param name="offset">Signature offset within the signature byte array</param>
+        /// <param name="outerReader">Metadata reader representing the outer signature context</param>
         /// <param name="contextReader">Top-level signature context reader</param>
-        private SignatureDecoder(IAssemblyResolver options, MetadataReader metadataReader, byte[] signature, int offset, ReadyToRunReader contextReader)
+        private SignatureDecoder(IAssemblyResolver options, MetadataReader metadataReader, byte[] signature, int offset, MetadataReader outerReader, ReadyToRunReader contextReader)
         {
-            _metadataReader = metadataReader;
-            _options = options;
-            _image = signature;
-            _offset = offset;
-            _contextReader = contextReader;
-        }
-
-        /// <summary>
-        /// Construct the signature decoder by storing the image byte array and offset within the array.
-        /// This variant uses the outer global metadata reader
-        /// </summary>
-        /// <param name="options">Dump options and paths</param>
-        /// <param name="signature">Signature to parse</param>
-        /// <param name="offset">Signature offset within the signature byte array</param>
-        /// <param name="contextReader">Top-level signature context reader</param>
-        private SignatureDecoder(IAssemblyResolver options, byte[] signature, int offset, ReadyToRunReader contextReader)
-        {
-            _metadataReader = contextReader.GetGlobalMetadataReader();
             _options = options;
+            _metadataReader = metadataReader;
             _image = signature;
             _offset = offset;
+            _outerReader = outerReader;
             _contextReader = contextReader;
         }
 
@@ -656,7 +647,7 @@ namespace ILCompiler.Reflection.ReadyToRun
                 fixupType &= ~(uint)ReadyToRunFixupKind.ModuleOverride;
                 int moduleIndex = (int)ReadUIntAndEmitInlineSignatureBinary(builder);
                 MetadataReader refAsmEcmaReader = _contextReader.OpenReferenceAssembly(moduleIndex);
-                moduleDecoder = new SignatureDecoder(_options, refAsmEcmaReader, _image, _offset, _contextReader);
+                moduleDecoder = new SignatureDecoder(_options, refAsmEcmaReader, _image, _offset, refAsmEcmaReader, _contextReader);
             }
 
             moduleDecoder.ParseSignature((ReadyToRunFixupKind)fixupType, builder);
@@ -1013,9 +1004,7 @@ namespace ILCompiler.Reflection.ReadyToRun
                     break;
 
                 case CorElementType.ELEMENT_TYPE_GENERICINST:
-                    SignatureDecoder outerTypeDecoder = new SignatureDecoder(_options, _image, _offset, _contextReader);
-                    outerTypeDecoder.ParseGenericTypeInstance(builder);
-                    _offset = outerTypeDecoder._offset;
+                    ParseGenericTypeInstance(builder);
                     break;
 
                 case CorElementType.ELEMENT_TYPE_TYPEDBYREF:
@@ -1085,7 +1074,7 @@ namespace ILCompiler.Reflection.ReadyToRun
                     {
                         int moduleIndex = (int)ReadUIntAndEmitInlineSignatureBinary(builder);
                         MetadataReader refAsmReader = _contextReader.OpenReferenceAssembly(moduleIndex);
-                        SignatureDecoder refAsmDecoder = new SignatureDecoder(_options, refAsmReader, _image, _offset, _contextReader);
+                        SignatureDecoder refAsmDecoder = new SignatureDecoder(_options, refAsmReader, _image, _offset, _outerReader, _contextReader);
                         refAsmDecoder.ParseType(builder);
                         _offset = refAsmDecoder.Offset;
                     }
@@ -1117,6 +1106,7 @@ namespace ILCompiler.Reflection.ReadyToRun
         {
             ParseType(builder);
             uint typeArgCount = ReadUIntAndEmitInlineSignatureBinary(builder);
+            SignatureDecoder outerDecoder = new SignatureDecoder(_options, _outerReader, _image, _offset, _outerReader, _contextReader);
             builder.Append("<");
             for (uint paramIndex = 0; paramIndex < typeArgCount; paramIndex++)
             {
@@ -1124,9 +1114,10 @@ namespace ILCompiler.Reflection.ReadyToRun
                 {
                     builder.Append(", ");
                 }
-                ParseType(builder);
+                outerDecoder.ParseType(builder);
             }
             builder.Append(">");
+            _offset = outerDecoder.Offset;
         }
 
         private void ParseTypeToken(StringBuilder builder)
@@ -1160,9 +1151,7 @@ namespace ILCompiler.Reflection.ReadyToRun
             string owningTypeOverride = null;
             if ((methodFlags & (uint)ReadyToRunMethodSigFlags.READYTORUN_METHOD_SIG_OwnerType) != 0)
             {
-                SignatureDecoder owningTypeDecoder = new SignatureDecoder(_options, _metadataReader, _image, _offset, _contextReader);
-                owningTypeOverride = owningTypeDecoder.ReadTypeSignatureNoEmit();
-                _offset = owningTypeDecoder._offset;
+                owningTypeOverride = ReadTypeSignatureNoEmit();
             }
             if ((methodFlags & (uint)ReadyToRunMethodSigFlags.READYTORUN_METHOD_SIG_SlotInsteadOfToken) != 0)
             {
index b874fa6..5e4360d 100644 (file)
@@ -12,6 +12,7 @@ using System.Reflection.Metadata;
 using System.Reflection.Metadata.Ecma335;
 using System.Reflection.PortableExecutable;
 using System.Runtime.CompilerServices;
+using System.Text;
 using System.Threading.Tasks;
 using ILCompiler.Reflection.ReadyToRun;
 
@@ -215,7 +216,7 @@ namespace R2RDump
 
             if (_options.Out != null)
             {
-                _writer = new StreamWriter(_options.Out.FullName);
+                _writer = new StreamWriter(_options.Out.FullName, append: false, encoding: new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: false));
             }
             else
             {