Skip to content

Commit

Permalink
Avoid decompressing/compressing unresolved embedded source information (
Browse files Browse the repository at this point in the history
  • Loading branch information
jbevain authored Jun 30, 2021
1 parent fbb3c44 commit 96c159d
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 28 deletions.
57 changes: 53 additions & 4 deletions Mono.Cecil.Cil/Symbols.cs
Original file line number Diff line number Diff line change
Expand Up @@ -619,17 +619,36 @@ public StateMachineScopeDebugInformation ()

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 {
Expand All @@ -638,12 +657,42 @@ public override CustomDebugInformationKind Kind {

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 {
Expand Down
50 changes: 28 additions & 22 deletions Mono.Cecil/AssemblyReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3223,28 +3223,7 @@ public Collection<CustomDebugInformation> GetCustomDebugInformation (ICustomDebu

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 {
Expand All @@ -3256,6 +3235,33 @@ public Collection<CustomDebugInformation> GetCustomDebugInformation (ICustomDebu

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 {
Expand Down
7 changes: 7 additions & 0 deletions Mono.Cecil/AssemblyWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2422,6 +2422,13 @@ void AddAsyncMethodBodyDebugInformation (ICustomDebugInformationProvider provide
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);
Expand Down
7 changes: 5 additions & 2 deletions Test/Mono.Cecil.Tests/PortablePdbTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -490,10 +490,13 @@ public void SourceLink ()
[Test]
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;
Expand Down Expand Up @@ -533,7 +536,7 @@ static void Main()

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
{
Expand Down

0 comments on commit 96c159d

Please sign in to comment.