summaryrefslogtreecommitdiff
path: root/src/tools
diff options
context:
space:
mode:
authorTomáš Rylek <trylek@microsoft.com>2018-12-03 20:33:49 +0100
committerGitHub <noreply@github.com>2018-12-03 20:33:49 +0100
commit940ed217fd424f645227acd3d9fac0caf28ec47b (patch)
tree30010d7763cf6ca0103f51b9052d78fb5267dc17 /src/tools
parentcb8557de0c07126473172483aee08cabcb6d67a7 (diff)
downloadcoreclr-940ed217fd424f645227acd3d9fac0caf28ec47b.tar.gz
coreclr-940ed217fd424f645227acd3d9fac0caf28ec47b.tar.bz2
coreclr-940ed217fd424f645227acd3d9fac0caf28ec47b.zip
Improvements for naked R2RDump output (#21317)
The initial impulse for this change was removing native offsets from debug info that caused noise in naked R2R comparisons. Fixing this required propagation of DumpOptions to some more call sites prompting me to unify dumping logic to always use TextWriter as the output medium. I have also fixed some minor bugs I noticed around the naked disassembly. Thanks Tomas
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/r2rdump/CoreDisTools.cs11
-rw-r--r--src/tools/r2rdump/DebugInfo.cs62
-rw-r--r--src/tools/r2rdump/EHInfo.cs34
-rw-r--r--src/tools/r2rdump/R2RMethod.cs52
-rw-r--r--src/tools/r2rdump/TextDumper.cs2
5 files changed, 78 insertions, 83 deletions
diff --git a/src/tools/r2rdump/CoreDisTools.cs b/src/tools/r2rdump/CoreDisTools.cs
index 19117f76c4..d6a82f1b63 100644
--- a/src/tools/r2rdump/CoreDisTools.cs
+++ b/src/tools/r2rdump/CoreDisTools.cs
@@ -157,11 +157,13 @@ namespace R2RDump
{
colon += 3;
}
- nakedInstruction.AppendLine(new string(' ', 32) + line.Substring(colon).TrimStart());
+ nakedInstruction.Append(new string(' ', 32) + line.Substring(colon).TrimStart());
+ nakedInstruction.Append('\n');
}
else
{
- nakedInstruction.AppendLine(line);
+ nakedInstruction.Append(line);
+ nakedInstruction.Append('\n');
}
}
instruction = nakedInstruction.ToString();
@@ -306,11 +308,6 @@ namespace R2RDump
/// <param name="instruction">Textual representation of the instruction</param>
private void ProbeCommonIntelQuirks(RuntimeFunction rtf, int imageOffset, int rtfOffset, int instrSize, ref string instruction)
{
- if (_options.Naked)
- {
- // Don't relocate relative offsets in naked mode
- return;
- }
if (instrSize == 2 && IsIntelJumpInstructionWithByteOffset(imageOffset + rtfOffset))
{
sbyte offset = (sbyte)_reader.Image[imageOffset + rtfOffset + 1];
diff --git a/src/tools/r2rdump/DebugInfo.cs b/src/tools/r2rdump/DebugInfo.cs
index eacc84856f..f4d8f5c882 100644
--- a/src/tools/r2rdump/DebugInfo.cs
+++ b/src/tools/r2rdump/DebugInfo.cs
@@ -5,6 +5,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.IO;
using System.Reflection.PortableExecutable;
using System.Text;
@@ -52,76 +53,77 @@ namespace R2RDump
}
}
- public override string ToString()
+ public void WriteTo(TextWriter writer, DumpOptions dumpOptions)
{
- StringBuilder sb = new StringBuilder();
-
if (_boundsList.Count > 0)
- sb.AppendLine("Debug Info");
+ writer.WriteLine("Debug Info");
- sb.AppendLine("\tBounds:");
+ writer.WriteLine("\tBounds:");
for (int i = 0; i < _boundsList.Count; ++i)
{
- sb.AppendLine($"\tNative Offset: 0x{_boundsList[i].NativeOffset:X}, IL Offset: 0x{_boundsList[i].ILOffset:X}, Source Types: {_boundsList[i].SourceTypes}");
+ writer.Write('\t');
+ if (!dumpOptions.Naked)
+ {
+ writer.Write($"Native Offset: 0x{_boundsList[i].NativeOffset:X}, ");
+ }
+ writer.WriteLine($"IL Offset: 0x{_boundsList[i].ILOffset:X}, Source Types: {_boundsList[i].SourceTypes}");
}
- sb.AppendLine("");
+ writer.WriteLine("");
if (_variablesList.Count > 0)
- sb.AppendLine("\tVariable Locations:");
+ writer.WriteLine("\tVariable Locations:");
for (int i = 0; i < _variablesList.Count; ++i)
{
var varLoc = _variablesList[i];
- sb.AppendLine($"\tVariable Number: {varLoc.VariableNumber}");
- sb.AppendLine($"\tStart Offset: 0x{varLoc.StartOffset:X}");
- sb.AppendLine($"\tEnd Offset: 0x{varLoc.EndOffset:X}");
- sb.AppendLine($"\tLoc Type: {varLoc.VariableLocation.VarLocType}");
+ writer.WriteLine($"\tVariable Number: {varLoc.VariableNumber}");
+ writer.WriteLine($"\tStart Offset: 0x{varLoc.StartOffset:X}");
+ writer.WriteLine($"\tEnd Offset: 0x{varLoc.EndOffset:X}");
+ writer.WriteLine($"\tLoc Type: {varLoc.VariableLocation.VarLocType}");
switch (varLoc.VariableLocation.VarLocType)
{
case VarLocType.VLT_REG:
case VarLocType.VLT_REG_FP:
case VarLocType.VLT_REG_BYREF:
- sb.AppendLine($"\tRegister: {GetPlatformSpecificRegister(_machine, varLoc.VariableLocation.Data1)}");
+ writer.WriteLine($"\tRegister: {GetPlatformSpecificRegister(_machine, varLoc.VariableLocation.Data1)}");
break;
case VarLocType.VLT_STK:
case VarLocType.VLT_STK_BYREF:
- sb.AppendLine($"\tBase Register: {GetPlatformSpecificRegister(_machine, varLoc.VariableLocation.Data1)}");
- sb.AppendLine($"\tStack Offset: {varLoc.VariableLocation.Data2}");
+ writer.WriteLine($"\tBase Register: {GetPlatformSpecificRegister(_machine, varLoc.VariableLocation.Data1)}");
+ writer.WriteLine($"\tStack Offset: {varLoc.VariableLocation.Data2}");
break;
case VarLocType.VLT_REG_REG:
- sb.AppendLine($"\tRegister 1: {GetPlatformSpecificRegister(_machine, varLoc.VariableLocation.Data1)}");
- sb.AppendLine($"\tRegister 2: {GetPlatformSpecificRegister(_machine, varLoc.VariableLocation.Data2)}");
+ writer.WriteLine($"\tRegister 1: {GetPlatformSpecificRegister(_machine, varLoc.VariableLocation.Data1)}");
+ writer.WriteLine($"\tRegister 2: {GetPlatformSpecificRegister(_machine, varLoc.VariableLocation.Data2)}");
break;
case VarLocType.VLT_REG_STK:
- sb.AppendLine($"\tRegister: {GetPlatformSpecificRegister(_machine, varLoc.VariableLocation.Data1)}");
- sb.AppendLine($"\tBase Register: {GetPlatformSpecificRegister(_machine, varLoc.VariableLocation.Data2)}");
- sb.AppendLine($"\tStack Offset: {varLoc.VariableLocation.Data3}");
+ writer.WriteLine($"\tRegister: {GetPlatformSpecificRegister(_machine, varLoc.VariableLocation.Data1)}");
+ writer.WriteLine($"\tBase Register: {GetPlatformSpecificRegister(_machine, varLoc.VariableLocation.Data2)}");
+ writer.WriteLine($"\tStack Offset: {varLoc.VariableLocation.Data3}");
break;
case VarLocType.VLT_STK_REG:
- sb.AppendLine($"\tStack Offset: {varLoc.VariableLocation.Data1}");
- sb.AppendLine($"\tBase Register: {GetPlatformSpecificRegister(_machine, varLoc.VariableLocation.Data2)}");
- sb.AppendLine($"\tRegister: {GetPlatformSpecificRegister(_machine, varLoc.VariableLocation.Data3)}");
+ writer.WriteLine($"\tStack Offset: {varLoc.VariableLocation.Data1}");
+ writer.WriteLine($"\tBase Register: {GetPlatformSpecificRegister(_machine, varLoc.VariableLocation.Data2)}");
+ writer.WriteLine($"\tRegister: {GetPlatformSpecificRegister(_machine, varLoc.VariableLocation.Data3)}");
break;
case VarLocType.VLT_STK2:
- sb.AppendLine($"\tBase Register: {GetPlatformSpecificRegister(_machine, varLoc.VariableLocation.Data1)}");
- sb.AppendLine($"\tStack Offset: {varLoc.VariableLocation.Data2}");
+ writer.WriteLine($"\tBase Register: {GetPlatformSpecificRegister(_machine, varLoc.VariableLocation.Data1)}");
+ writer.WriteLine($"\tStack Offset: {varLoc.VariableLocation.Data2}");
break;
case VarLocType.VLT_FPSTK:
- sb.AppendLine($"\tOffset: {GetPlatformSpecificRegister(_machine, varLoc.VariableLocation.Data1)}");
+ writer.WriteLine($"\tOffset: {GetPlatformSpecificRegister(_machine, varLoc.VariableLocation.Data1)}");
break;
case VarLocType.VLT_FIXED_VA:
- sb.AppendLine($"\tOffset: {GetPlatformSpecificRegister(_machine, varLoc.VariableLocation.Data1)}");
+ writer.WriteLine($"\tOffset: {GetPlatformSpecificRegister(_machine, varLoc.VariableLocation.Data1)}");
break;
default:
throw new BadImageFormatException("Unexpected var loc type");
}
- sb.AppendLine("");
+ writer.WriteLine("");
}
-
- return sb.ToString();
}
/// <summary>
diff --git a/src/tools/r2rdump/EHInfo.cs b/src/tools/r2rdump/EHInfo.cs
index 818b343482..4d1ce25163 100644
--- a/src/tools/r2rdump/EHInfo.cs
+++ b/src/tools/r2rdump/EHInfo.cs
@@ -100,35 +100,35 @@ namespace R2RDump
}
/// <summary>
- /// Emit a textual representation of the EH info to a given string builder.
+ /// Emit a textual representation of the EH info to a given text writer.
/// </summary>
- /// <param name="stringBuilder">Output builder for the textual representation</param>
+ /// <param name="writer">Output writer for the textual representation</param>
/// <param name="methodRva">Starting RVA of the runtime function is used to display the try / handler info as RVA intervals</param>
- public void WriteTo(StringBuilder stringBuilder, int methodRva)
+ public void WriteTo(TextWriter writer, int methodRva)
{
- stringBuilder.Append($@"Flags {(uint)Flags:X2} ");
- stringBuilder.Append($@"TryOff {TryOffset:X4} (RVA {(TryOffset + methodRva):X4}) ");
- stringBuilder.Append($@"TryEnd {TryEnd:X4} (RVA {(TryEnd + methodRva):X4}) ");
- stringBuilder.Append($@"HndOff {HandlerOffset:X4} (RVA {(HandlerOffset + methodRva):X4}) ");
- stringBuilder.Append($@"HndEnd {HandlerEnd:X4} (RVA {(HandlerEnd + methodRva):X4}) ");
- stringBuilder.Append($@"ClsFlt {ClassTokenOrFilterOffset:X4}");
+ writer.Write($@"Flags {(uint)Flags:X2} ");
+ writer.Write($@"TryOff {TryOffset:X4} (RVA {(TryOffset + methodRva):X4}) ");
+ writer.Write($@"TryEnd {TryEnd:X4} (RVA {(TryEnd + methodRva):X4}) ");
+ writer.Write($@"HndOff {HandlerOffset:X4} (RVA {(HandlerOffset + methodRva):X4}) ");
+ writer.Write($@"HndEnd {HandlerEnd:X4} (RVA {(HandlerEnd + methodRva):X4}) ");
+ writer.Write($@"ClsFlt {ClassTokenOrFilterOffset:X4}");
switch (Flags & CorExceptionFlag.COR_ILEXCEPTION_CLAUSE_KIND_MASK)
{
case CorExceptionFlag.COR_ILEXCEPTION_CLAUSE_NONE:
- stringBuilder.AppendFormat(" CATCH: {0}", ClassName ?? "null");
+ writer.Write($" CATCH: {0}", ClassName ?? "null");
break;
case CorExceptionFlag.COR_ILEXCEPTION_CLAUSE_FILTER:
- stringBuilder.AppendFormat(" FILTER (RVA {0:X4})", ClassTokenOrFilterOffset + methodRva);
+ writer.Write($" FILTER (RVA {0:X4})", ClassTokenOrFilterOffset + methodRva);
break;
case CorExceptionFlag.COR_ILEXCEPTION_CLAUSE_FINALLY:
- stringBuilder.AppendFormat(" FINALLY");
+ writer.Write(" FINALLY");
break;
case CorExceptionFlag.COR_ILEXCEPTION_CLAUSE_FAULT:
- stringBuilder.AppendFormat(" FAULT");
+ writer.Write(" FAULT");
break;
default:
@@ -137,7 +137,7 @@ namespace R2RDump
if ((Flags & CorExceptionFlag.COR_ILEXCEPTION_CLAUSE_DUPLICATED) != (CorExceptionFlag)0)
{
- stringBuilder.Append(" DUPLICATED");
+ writer.Write(" DUPLICATED");
}
}
}
@@ -189,12 +189,12 @@ namespace R2RDump
/// <summary>
/// Emit the textual representation of the EH info into a given writer.
/// </summary>
- public void WriteTo(StringBuilder stringBuilder)
+ public void WriteTo(TextWriter writer)
{
foreach (EHClause ehClause in EHClauses)
{
- ehClause.WriteTo(stringBuilder, MethodRVA);
- stringBuilder.AppendLine();
+ ehClause.WriteTo(writer, MethodRVA);
+ writer.WriteLine();
}
}
}
diff --git a/src/tools/r2rdump/R2RMethod.cs b/src/tools/r2rdump/R2RMethod.cs
index 592f123822..6078e6f6bc 100644
--- a/src/tools/r2rdump/R2RMethod.cs
+++ b/src/tools/r2rdump/R2RMethod.cs
@@ -137,21 +137,19 @@ namespace R2RDump
EHInfo = ehInfo;
}
- public override string ToString()
+ public void WriteTo(TextWriter writer, DumpOptions options)
{
- StringBuilder sb = new StringBuilder();
-
- sb.AppendLine($"Id: {Id}");
- sb.AppendLine($"StartAddress: 0x{StartAddress:X8}");
+ writer.WriteLine($"Id: {Id}");
+ writer.WriteLine($"StartAddress: 0x{StartAddress:X8}");
if (Size == -1)
{
- sb.AppendLine("Size: Unavailable");
+ writer.WriteLine("Size: Unavailable");
}
else
{
- sb.AppendLine($"Size: {Size} bytes");
+ writer.WriteLine($"Size: {Size} bytes");
}
- sb.AppendLine($"UnwindRVA: 0x{UnwindRVA:X8}");
+ writer.WriteLine($"UnwindRVA: 0x{UnwindRVA:X8}");
if (UnwindInfo is Amd64.UnwindInfo amd64UnwindInfo)
{
string parsedFlags = "";
@@ -171,40 +169,38 @@ namespace R2RDump
{
parsedFlags = " NHANDLER";
}
- sb.AppendLine($"Version: {amd64UnwindInfo.Version}");
- sb.AppendLine($"Flags: 0x{amd64UnwindInfo.Flags:X2}{parsedFlags}");
- sb.AppendLine($"SizeOfProlog: 0x{amd64UnwindInfo.SizeOfProlog:X4}");
- sb.AppendLine($"CountOfUnwindCodes: {amd64UnwindInfo.CountOfUnwindCodes}");
- sb.AppendLine($"FrameRegister: {amd64UnwindInfo.FrameRegister}");
- sb.AppendLine($"FrameOffset: 0x{amd64UnwindInfo.FrameOffset}");
- sb.AppendLine($"PersonalityRVA: 0x{amd64UnwindInfo.PersonalityRoutineRVA:X4}");
+ writer.WriteLine($"Version: {amd64UnwindInfo.Version}");
+ writer.WriteLine($"Flags: 0x{amd64UnwindInfo.Flags:X2}{parsedFlags}");
+ writer.WriteLine($"SizeOfProlog: 0x{amd64UnwindInfo.SizeOfProlog:X4}");
+ writer.WriteLine($"CountOfUnwindCodes: {amd64UnwindInfo.CountOfUnwindCodes}");
+ writer.WriteLine($"FrameRegister: {amd64UnwindInfo.FrameRegister}");
+ writer.WriteLine($"FrameOffset: 0x{amd64UnwindInfo.FrameOffset}");
+ writer.WriteLine($"PersonalityRVA: 0x{amd64UnwindInfo.PersonalityRoutineRVA:X4}");
for (int unwindCodeIndex = 0; unwindCodeIndex < amd64UnwindInfo.CountOfUnwindCodes; unwindCodeIndex++)
{
Amd64.UnwindCode unwindCode = amd64UnwindInfo.UnwindCodeArray[unwindCodeIndex];
- sb.Append($"UnwindCode[{unwindCode.Index}]: ");
- sb.Append($"CodeOffset 0x{unwindCode.CodeOffset:X4} ");
- sb.Append($"FrameOffset 0x{unwindCode.FrameOffset:X4} ");
- sb.Append($"NextOffset 0x{unwindCode.NextFrameOffset} ");
- sb.Append($"Op {unwindCode.OpInfoStr}");
- sb.AppendLine();
+ writer.Write($"UnwindCode[{unwindCode.Index}]: ");
+ writer.Write($"CodeOffset 0x{unwindCode.CodeOffset:X4} ");
+ writer.Write($"FrameOffset 0x{unwindCode.FrameOffset:X4} ");
+ writer.Write($"NextOffset 0x{unwindCode.NextFrameOffset} ");
+ writer.Write($"Op {unwindCode.OpInfoStr}");
+ writer.WriteLine();
}
}
- sb.AppendLine();
+ writer.WriteLine();
if (EHInfo != null)
{
- sb.AppendLine($@"EH info @ {EHInfo.EHInfoRVA:X4}, #clauses = {EHInfo.EHClauses.Length}");
- EHInfo.WriteTo(sb);
- sb.AppendLine();
+ writer.WriteLine($@"EH info @ {EHInfo.EHInfoRVA:X4}, #clauses = {EHInfo.EHClauses.Length}");
+ EHInfo.WriteTo(writer);
+ writer.WriteLine();
}
if (DebugInfo != null)
{
- sb.AppendLine(DebugInfo.ToString());
+ DebugInfo.WriteTo(writer, options);
}
-
- return sb.ToString();
}
}
diff --git a/src/tools/r2rdump/TextDumper.cs b/src/tools/r2rdump/TextDumper.cs
index df1bef547d..da45a71757 100644
--- a/src/tools/r2rdump/TextDumper.cs
+++ b/src/tools/r2rdump/TextDumper.cs
@@ -149,7 +149,7 @@ namespace R2RDump
internal override void DumpRuntimeFunction(RuntimeFunction rtf, XmlNode parentNode = null)
{
_writer.WriteLine(rtf.Method.SignatureString);
- _writer.Write($"{rtf}");
+ rtf.WriteTo(_writer, _options);
if (_options.Disasm)
{