Skip to content

Commit

Permalink
Minor R2RDump facelift w.r.t. diffing dump (#2184)
Browse files Browse the repository at this point in the history
Based on offline chat with JanV I added initial provisions to simplify
diffing Crossgen1- and 2-compiled SPC. In essence, the --diff option
newly ends up emitting two extra files with the ".r2rdump" extension
representing the methods common to the left and right R2R file. This
is formerly untrodden territory, I'm pioneering R2RDump usability for
this purpose.

Thanks

Tomas
  • Loading branch information
trylek committed Jan 27, 2020
1 parent 96c79db commit e7ce09d
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 31 deletions.
56 changes: 40 additions & 16 deletions src/coreclr/src/tools/r2rdump/R2RDiff.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,30 +18,30 @@ namespace R2RDump
class R2RDiff
{
/// <summary>
/// Left R2R image for the diff.
/// Left dumper to use for the diff
/// </summary>
private readonly ReadyToRunReader _leftFile;
private readonly Dumper _leftDumper;

/// <summary>
/// Right R2R image for the diff.
/// Right dumper to use for the diff
/// </summary>
private readonly ReadyToRunReader _rightFile;
private readonly Dumper _rightDumper;

/// <summary>
/// Text writer to receive diff output.
/// Text writer to use for common output
/// </summary>
private readonly TextWriter _writer;

/// <summary>
/// Store the left and right file and output writer.
/// </summary>
/// <param name="leftFile">Left R2R file</param>
/// <param name="rightFile">Right R2R file</param>
/// <param name="writer">Output writer to receive the diff</param>
public R2RDiff(ReadyToRunReader leftFile, ReadyToRunReader rightFile, TextWriter writer)
/// <param name="leftDumper">Dumper to use for the left diff output</param>
/// <param name="rightDumper">Dumper to use for the right diff output</param>
/// <param name="writer">Writer to use for output common to left / right side</param>
public R2RDiff(Dumper leftDumper, Dumper rightDumper, TextWriter writer)
{
_leftFile = leftFile;
_rightFile = rightFile;
_leftDumper = leftDumper;
_rightDumper = rightDumper;
_writer = writer;
}

Expand All @@ -54,15 +54,20 @@ public void Run()
DiffPESections();
DiffR2RSections();
DiffR2RMethods();

HashSet<string> commonMethods = new HashSet<string>(_leftDumper.Reader.Methods.Select(method => method.SignatureString)
.Intersect(_rightDumper.Reader.Methods.Select(method => method.SignatureString)));
DumpCommonMethods(_leftDumper, commonMethods);
DumpCommonMethods(_rightDumper, commonMethods);
}

/// <summary>
/// Diff title shows the names of the files being compared and their lengths.
/// </summary>
private void DiffTitle()
{
_writer.WriteLine($@"Left file: {_leftFile.Filename} ({_leftFile.Image.Length} B)");
_writer.WriteLine($@"Right file: {_rightFile.Filename} ({_rightFile.Image.Length} B)");
_writer.WriteLine($@"Left file: {_leftDumper.Reader.Filename} ({_leftDumper.Reader.Image.Length} B)");
_writer.WriteLine($@"Right file: {_rightDumper.Reader.Filename} ({_rightDumper.Reader.Image.Length} B)");
_writer.WriteLine();
}

Expand All @@ -71,23 +76,23 @@ private void DiffTitle()
/// </summary>
private void DiffPESections()
{
ShowDiff(GetPESectionMap(_leftFile), GetPESectionMap(_rightFile), "PE sections");
ShowDiff(GetPESectionMap(_leftDumper.Reader), GetPESectionMap(_rightDumper.Reader), "PE sections");
}

/// <summary>
/// Diff R2R header sections.
/// </summary>
private void DiffR2RSections()
{
ShowDiff(GetR2RSectionMap(_leftFile), GetR2RSectionMap(_rightFile), "R2R sections");
ShowDiff(GetR2RSectionMap(_leftDumper.Reader), GetR2RSectionMap(_rightDumper.Reader), "R2R sections");
}

/// <summary>
/// Diff the R2R method maps.
/// </summary>
private void DiffR2RMethods()
{
ShowDiff(GetR2RMethodMap(_leftFile), GetR2RMethodMap(_rightFile), "R2R methods");
ShowDiff(GetR2RMethodMap(_leftDumper.Reader), GetR2RMethodMap(_rightDumper.Reader), "R2R methods");
}

/// <summary>
Expand Down Expand Up @@ -204,5 +209,24 @@ private Dictionary<string, int> GetR2RMethodMap(ReadyToRunReader reader)

return methodMap;
}

/// <summary>
/// Dump the subset of methods common to both sides of the diff to the given dumper.
/// </summary>
/// <param name="dumper">Output dumper to use</param>
/// <param name="signatureFilter">Set of common signatures of methods to dump</param>
private void DumpCommonMethods(Dumper dumper, HashSet<string> signatureFilter)
{
IEnumerable<ReadyToRunMethod> filteredMethods = dumper
.Reader
.Methods
.Where(method => signatureFilter.Contains(method.SignatureString))
.OrderBy(method => method.SignatureString);

foreach (ReadyToRunMethod method in filteredMethods)
{
dumper.DumpMethod(method);
}
}
}
}
40 changes: 25 additions & 15 deletions src/coreclr/src/tools/r2rdump/R2RDump.cs
Original file line number Diff line number Diff line change
Expand Up @@ -161,13 +161,19 @@ public IEnumerable<ReadyToRunMethod> NormalizedMethods()
abstract internal void DumpBytes(int rva, uint size, string name = "Raw", bool convertToOffset = true);
abstract internal void DumpSectionContents(ReadyToRunSection section);
abstract internal void DumpQueryCount(string q, string title, int count);

public TextWriter Writer => _writer;

public DumpOptions Options => _options;

public ReadyToRunReader Reader => _r2r;
}

class R2RDump
{
private readonly DumpOptions _options;
private readonly TextWriter _writer;
private readonly Dictionary<ReadyToRunSection.SectionType, bool> _selectedSections = new Dictionary<ReadyToRunSection.SectionType, bool>();
private TextWriter _writer;
private Dumper _dumper;

private R2RDump(DumpOptions options)
Expand All @@ -181,16 +187,6 @@ private R2RDump(DumpOptions options)
_options.GC = true;
_options.SectionContents = true;
}

// open output stream
if (_options.Out != null)
{
_writer = new StreamWriter(_options.Out.FullName, append: false, encoding: Encoding.ASCII);
}
else
{
_writer = Console.Out;
}
}

private static int ArgStringToInt(string arg)
Expand Down Expand Up @@ -478,7 +474,12 @@ private int Run()
throw new ArgumentException("The option '--naked' is incompatible with '--raw'");
}

ReadyToRunReader previousReader = null;
Dumper previousDumper = null;
TextWriter globalWriter = null;
if (_options.Out != null)
{
globalWriter = new StreamWriter(_options.Out.FullName);
}

foreach (FileInfo filename in _options.In)
{
Expand All @@ -497,19 +498,28 @@ private int Run()
}
}

if (!_options.Diff && globalWriter != null)
{
_writer = globalWriter;
}
else
{
string outFile = r2r.Filename + ".r2rdump";
_writer = new StreamWriter(outFile, append: false, encoding: Encoding.ASCII);
}
_dumper = new TextDumper(r2r, _writer, disassembler, _options);

if (!_options.Diff)
{
// output the ReadyToRun info
Dump(r2r);
}
else if (previousReader != null)
else if (previousDumper != null)
{
new R2RDiff(previousReader, r2r, _writer).Run();
new R2RDiff(previousDumper, _dumper, globalWriter).Run();
}

previousReader = r2r;
previousDumper = _dumper;
}
}
catch (Exception e)
Expand Down

0 comments on commit e7ce09d

Please sign in to comment.