diff options
author | Jb Evain <jb@evain.net> | 2021-06-30 07:57:53 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-06-30 07:57:53 +0300 |
commit | 96c159d4687ea7493893011f3bd4a6e098dab163 (patch) | |
tree | cf9dc331833604d7d650b3b55d46a8662bc5bf7e | |
parent | fbb3c444bba3086f26c03bca8928307dd4ac6883 (diff) |
Avoid decompressing/compressing unresolved embedded source information (#771)
-rw-r--r-- | Mono.Cecil.Cil/Symbols.cs | 57 | ||||
-rw-r--r-- | Mono.Cecil/AssemblyReader.cs | 50 | ||||
-rw-r--r-- | Mono.Cecil/AssemblyWriter.cs | 7 | ||||
-rw-r--r-- | Test/Mono.Cecil.Tests/PortablePdbTests.cs | 7 |
4 files changed, 93 insertions, 28 deletions
diff --git a/Mono.Cecil.Cil/Symbols.cs b/Mono.Cecil.Cil/Symbols.cs index 4cf435d..5e92b67 100644 --- a/Mono.Cecil.Cil/Symbols.cs +++ b/Mono.Cecil.Cil/Symbols.cs @@ -619,17 +619,36 @@ namespace Mono.Cecil.Cil { public sealed class EmbeddedSourceDebugInformation : CustomDebugInformation { + internal uint index; + internal MetadataReader debug_reader; + internal bool resolved; internal byte [] content; internal bool compress; public byte [] Content { - get { return content; } - set { content = value; } + get { + if (!resolved) + Resolve (); + + return content; + } + set { + content = value; + resolved = true; + } } public bool Compress { - get { return compress; } - set { compress = value; } + get { + if (!resolved) + Resolve (); + + return compress; + } + set { + compress = value; + resolved = true; + } } public override CustomDebugInformationKind Kind { @@ -638,12 +657,42 @@ namespace Mono.Cecil.Cil { public static Guid KindIdentifier = new Guid ("{0E8A571B-6926-466E-B4AD-8AB04611F5FE}"); + internal EmbeddedSourceDebugInformation (uint index, MetadataReader debug_reader) + : base (KindIdentifier) + { + this.index = index; + this.debug_reader = debug_reader; + } + public EmbeddedSourceDebugInformation (byte [] content, bool compress) : base (KindIdentifier) { + this.resolved = true; this.content = content; this.compress = compress; } + + internal byte [] ReadRawEmbeddedSourceDebugInformation () + { + if (debug_reader == null) + throw new InvalidOperationException (); + + return debug_reader.ReadRawEmbeddedSourceDebugInformation (index); + } + + void Resolve () + { + if (resolved) + return; + + if (debug_reader == null) + throw new InvalidOperationException (); + + var row = debug_reader.ReadEmbeddedSourceDebugInformation (index); + content = row.Col1; + compress = row.Col2; + resolved = true; + } } public sealed class SourceLinkDebugInformation : CustomDebugInformation { diff --git a/Mono.Cecil/AssemblyReader.cs b/Mono.Cecil/AssemblyReader.cs index d5b34b7..9fdcf68 100644 --- a/Mono.Cecil/AssemblyReader.cs +++ b/Mono.Cecil/AssemblyReader.cs @@ -3223,28 +3223,7 @@ namespace Mono.Cecil { infos.Add (async_body); } else if (rows [i].Col1 == EmbeddedSourceDebugInformation.KindIdentifier) { - var signature = ReadSignature (rows [i].Col2); - var format = signature.ReadInt32 (); - var length = signature.sig_length - 4; - - var info = null as CustomDebugInformation; - - if (format == 0) { - info = new EmbeddedSourceDebugInformation (signature.ReadBytes ((int) length), compress: false); - } else if (format > 0) { - var compressed_stream = new MemoryStream (signature.ReadBytes ((int) length)); - var decompressed_document = new byte [format]; // if positive, format is the decompressed length of the document - var decompressed_stream = new MemoryStream (decompressed_document); - - using (var deflate_stream = new DeflateStream (compressed_stream, CompressionMode.Decompress, leaveOpen: true)) - deflate_stream.CopyTo (decompressed_stream); - - info = new EmbeddedSourceDebugInformation (decompressed_document, compress: true); - } else if (format < 0) { - info = new BinaryCustomDebugInformation (rows [i].Col1, ReadBlob (rows [i].Col2)); - } - - infos.Add (info); + infos.Add (new EmbeddedSourceDebugInformation (rows [i].Col2, this)); } else if (rows [i].Col1 == SourceLinkDebugInformation.KindIdentifier) { infos.Add (new SourceLinkDebugInformation (Encoding.UTF8.GetString (ReadBlob (rows [i].Col2)))); } else { @@ -3256,6 +3235,33 @@ namespace Mono.Cecil { return infos; } + + public byte [] ReadRawEmbeddedSourceDebugInformation (uint index) + { + var signature = ReadSignature (index); + return signature.ReadBytes ((int) signature.sig_length); + } + + public Row<byte [], bool> ReadEmbeddedSourceDebugInformation (uint index) + { + var signature = ReadSignature (index); + var format = signature.ReadInt32 (); + var length = signature.sig_length - 4; + + if (format == 0) { + return new Row<byte [], bool> (signature.ReadBytes ((int) length), false); + } else if (format > 0) { + var compressed_stream = new MemoryStream (signature.ReadBytes ((int) length)); + var decompressed_document = new byte [format]; // if positive, format is the decompressed length of the document + var decompressed_stream = new MemoryStream (decompressed_document); + + using (var deflate_stream = new DeflateStream (compressed_stream, CompressionMode.Decompress, leaveOpen: true)) + deflate_stream.CopyTo (decompressed_stream); + + return new Row<byte [], bool> (decompressed_document, true); + } else + throw new NotSupportedException (); + } } sealed class SignatureReader : ByteBuffer { diff --git a/Mono.Cecil/AssemblyWriter.cs b/Mono.Cecil/AssemblyWriter.cs index 200410e..3f17a82 100644 --- a/Mono.Cecil/AssemblyWriter.cs +++ b/Mono.Cecil/AssemblyWriter.cs @@ -2422,6 +2422,13 @@ namespace Mono.Cecil { void AddEmbeddedSourceDebugInformation (ICustomDebugInformationProvider provider, EmbeddedSourceDebugInformation embedded_source) { var signature = CreateSignatureWriter (); + + if (!embedded_source.resolved) { + signature.WriteBytes (embedded_source.ReadRawEmbeddedSourceDebugInformation ()); + AddCustomDebugInformation (provider, embedded_source, signature); + return; + } + var content = embedded_source.content ?? Empty<byte>.Array; if (embedded_source.compress) { signature.WriteInt32 (content.Length); diff --git a/Test/Mono.Cecil.Tests/PortablePdbTests.cs b/Test/Mono.Cecil.Tests/PortablePdbTests.cs index b0c1f32..43b8cfe 100644 --- a/Test/Mono.Cecil.Tests/PortablePdbTests.cs +++ b/Test/Mono.Cecil.Tests/PortablePdbTests.cs @@ -491,9 +491,12 @@ namespace Mono.Cecil.Tests { public void EmbeddedSource () { TestModule ("embedcs.exe", module => { + }, symbolReaderProvider: typeof (PortablePdbReaderProvider), symbolWriterProvider: typeof (PortablePdbWriterProvider)); + + TestModule ("embedcs.exe", module => { var program = GetDocument (module.GetType ("Program")); var program_src = GetSourceDebugInfo (program); - Assert.IsTrue (program_src.compress); + Assert.IsTrue (program_src.Compress); var program_src_content = Encoding.UTF8.GetString (program_src.Content); Assert.AreEqual (Normalize (@"using System; @@ -533,7 +536,7 @@ class Program var a = GetDocument (module.GetType ("A")); var a_src = GetSourceDebugInfo (a); - Assert.IsFalse (a_src.compress); + Assert.IsFalse (a_src.Compress); var a_src_content = Encoding.UTF8.GetString (a_src.Content); Assert.AreEqual (Normalize (@"class A { |