{
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();
/// <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];
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.IO;
using System.Reflection.PortableExecutable;
using System.Text;
}
}
- 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>
}
/// <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:
if ((Flags & CorExceptionFlag.COR_ILEXCEPTION_CLAUSE_DUPLICATED) != (CorExceptionFlag)0)
{
- stringBuilder.Append(" DUPLICATED");
+ writer.Write(" DUPLICATED");
}
}
}
/// <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();
}
}
}
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 = "";
{
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();
}
}
internal override void DumpRuntimeFunction(RuntimeFunction rtf, XmlNode parentNode = null)
{
_writer.WriteLine(rtf.Method.SignatureString);
- _writer.Write($"{rtf}");
+ rtf.WriteTo(_writer, _options);
if (_options.Disasm)
{