Skip to content

Commit

Permalink
Translate [rip +- offset] to absolute RVA's in R2RDump (dotnet#19219)
Browse files Browse the repository at this point in the history
* Translate [rip +- offset] to absoluate RVA's in R2RDump

The existing logic for displaying rip-relative addressed on X64
make it very hard to calculate the final addresses. I have added
a horrendous hack using textual analysis of the disassembled
instruction to translate this notation to absolute RVA's.

As part of this effort I have also encapsulated the CorDisTools
helper in a new class Disassembler that also contains customizable
provisions for handling special assembly cases on the individual
architectures.

Thanks

Tomas

* Temporarily block out disassembly to make tests pass

In my initial commit I removed the line blocking out disassembly
however this ends up failing several lab tests so I'm putting the
line back.

Thanks

Tomas
  • Loading branch information
trylek committed Aug 14, 2018
1 parent c509903 commit 66b3197
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 19 deletions.
87 changes: 87 additions & 0 deletions src/tools/r2rdump/CoreDisTools.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,91 @@ public static IntPtr GetDisasm(Machine machine)
return InitBufferedDisasm(target);
}
}

public class Disassembler : IDisposable
{
private readonly IntPtr _disasm;

private readonly byte[] _image;

private readonly Machine _machine;

public Disassembler(byte[] image, Machine machine)
{
_disasm = CoreDisTools.GetDisasm(machine);
_image = image;
_machine = machine;
}

public void Dispose()
{
if (_disasm != IntPtr.Zero)
{
CoreDisTools.FinishDisasm(_disasm);
}
}

public int GetInstruction(RuntimeFunction rtf, int imageOffset, int rtfOffset, out string instruction)
{
int instrSize = CoreDisTools.GetInstruction(_disasm, rtf, imageOffset, rtfOffset, _image, out instruction);

switch (_machine)
{
case Machine.Amd64:
case Machine.IA64:
ProbeX64Quirks(rtf, imageOffset, rtfOffset, instrSize, ref instruction);
break;

case Machine.I386:
break;

case Machine.ArmThumb2:
case Machine.Thumb:
break;

case Machine.Arm64:
break;

default:
throw new NotImplementedException();
}

return instrSize;
}

const string RelIPTag = "[rip ";

private void ProbeX64Quirks(RuntimeFunction rtf, int imageOffset, int rtfOffset, int instrSize, ref string instruction)
{
int relip = instruction.IndexOf(RelIPTag);
if (relip >= 0 && instruction.Length >= relip + RelIPTag.Length + 3)
{
int start = relip;
relip += RelIPTag.Length;
char sign = instruction[relip];
if (sign == '+' || sign == '-' &&
instruction[relip + 1] == ' ' &&
Char.IsDigit(instruction[relip + 2]))
{
relip += 2;
int offset = 0;
do
{
offset = 10 * offset + (int)(instruction[relip] - '0');
}
while (++relip < instruction.Length && Char.IsDigit(instruction[relip]));
if (relip < instruction.Length && instruction[relip] == ']')
{
relip++;
if (sign == '-')
{
offset = -offset;
}
int target = rtf.StartAddress + rtfOffset + instrSize + offset;
instruction = instruction.Substring(0, start) + $@"[0x{target:x4}]" + instruction.Substring(relip);
}
}
}
}
}
}
22 changes: 11 additions & 11 deletions src/tools/r2rdump/R2RDump.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public abstract class Dumper
internal bool _raw;
internal bool _header;
internal bool _disasm;
internal IntPtr _disassembler;
internal Disassembler _disassembler;
internal bool _unwind;
internal bool _gc;
internal bool _sectionContents;
Expand All @@ -34,7 +34,7 @@ public abstract class Dumper
abstract internal void DumpAllMethods();
abstract internal void DumpMethod(R2RMethod method, XmlNode parentNode = null);
abstract internal void DumpRuntimeFunction(RuntimeFunction rtf, XmlNode parentNode = null);
abstract internal unsafe void DumpDisasm(IntPtr Disasm, RuntimeFunction rtf, int imageOffset, byte[] image, XmlNode parentNode = null);
abstract internal void DumpDisasm(RuntimeFunction rtf, int imageOffset, XmlNode parentNode = null);
abstract internal void DumpBytes(int rva, uint size, XmlNode parentNode = null, string name = "Raw", bool convertToOffset = true);
abstract internal void DumpSectionContents(R2RSection section, XmlNode parentNode = null);
abstract internal XmlNode DumpQueryCount(string q, string title, int count);
Expand All @@ -54,7 +54,6 @@ class R2RDump
private IReadOnlyList<int> _runtimeFunctions = Array.Empty<int>();
private IReadOnlyList<string> _sections = Array.Empty<string>();
private bool _diff;
private IntPtr _disassembler;
private bool _unwind;
private bool _gc;
private bool _sectionContents;
Expand Down Expand Up @@ -371,6 +370,8 @@ private int Run(string[] args)
return 0;
}

Disassembler disassembler = null;

try
{
if (_inputFilenames.Count == 0)
Expand All @@ -382,24 +383,19 @@ private int Run(string[] args)

if (_disasm)
{
_disassembler = CoreDisTools.GetDisasm(r2r.Machine);
disassembler = new Disassembler(r2r.Image, r2r.Machine);
}

if (_xml)
{
_dumper = new XmlDumper(_ignoreSensitive, r2r, _writer, _raw, _header, _disasm, _disassembler, _unwind, _gc, _sectionContents);
_dumper = new XmlDumper(_ignoreSensitive, r2r, _writer, _raw, _header, _disasm, disassembler, _unwind, _gc, _sectionContents);
}
else
{
_dumper = new TextDumper(r2r, _writer, _raw, _header, _disasm, _disassembler, _unwind, _gc, _sectionContents);
_dumper = new TextDumper(r2r, _writer, _raw, _header, _disasm, disassembler, _unwind, _gc, _sectionContents);
}

Dump(r2r);

if (_disasm)
{
CoreDisTools.FinishDisasm(_disassembler);
}
}
}
catch (Exception e)
Expand All @@ -425,6 +421,10 @@ private int Run(string[] args)
}
finally
{
if (disassembler != null)
{
disassembler.Dispose();
}
// close output stream
_writer.Close();
}
Expand Down
8 changes: 4 additions & 4 deletions src/tools/r2rdump/TextDumper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace R2RDump
{
class TextDumper : Dumper
{
public TextDumper(R2RReader r2r, TextWriter writer, bool raw, bool header, bool disasm, IntPtr disassembler, bool unwind, bool gc, bool sectionContents)
public TextDumper(R2RReader r2r, TextWriter writer, bool raw, bool header, bool disasm, Disassembler disassembler, bool unwind, bool gc, bool sectionContents)
{
_r2r = r2r;
_writer = writer;
Expand Down Expand Up @@ -147,7 +147,7 @@ internal override void DumpRuntimeFunction(RuntimeFunction rtf, XmlNode parentNo

if (_disasm)
{
DumpDisasm(_disassembler, rtf, _r2r.GetOffset(rtf.StartAddress), _r2r.Image);
DumpDisasm(rtf, _r2r.GetOffset(rtf.StartAddress));
}

if (_raw)
Expand All @@ -167,14 +167,14 @@ internal override void DumpRuntimeFunction(RuntimeFunction rtf, XmlNode parentNo
SkipLine();
}

internal unsafe override void DumpDisasm(IntPtr Disasm, RuntimeFunction rtf, int imageOffset, byte[] image, XmlNode parentNode = null)
internal override void DumpDisasm(RuntimeFunction rtf, int imageOffset, XmlNode parentNode = null)
{
int rtfOffset = 0;
int codeOffset = rtf.CodeOffset;
while (rtfOffset < rtf.Size)
{
string instr;
int instrSize = CoreDisTools.GetInstruction(Disasm, rtf, imageOffset, rtfOffset, image, out instr);
int instrSize = _disassembler.GetInstruction(rtf, imageOffset, rtfOffset, out instr);

_writer.Write(instr);
if (rtf.Method.GcInfo != null && rtf.Method.GcInfo.Transitions.ContainsKey(codeOffset))
Expand Down
8 changes: 4 additions & 4 deletions src/tools/r2rdump/XmlDumper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class XmlDumper : Dumper
private bool _ignoreSensitive;
private XmlAttributeOverrides _ignoredProperties;

public XmlDumper(bool ignoreSensitive, R2RReader r2r, TextWriter writer, bool raw, bool header, bool disasm, IntPtr disassembler, bool unwind, bool gc, bool sectionContents)
public XmlDumper(bool ignoreSensitive, R2RReader r2r, TextWriter writer, bool raw, bool header, bool disasm, Disassembler disassembler, bool unwind, bool gc, bool sectionContents)
{
_ignoreSensitive = ignoreSensitive;
_r2r = r2r;
Expand Down Expand Up @@ -190,7 +190,7 @@ internal override void DumpRuntimeFunction(RuntimeFunction rtf, XmlNode parentNo

if (_disasm)
{
DumpDisasm(_disassembler, rtf, _r2r.GetOffset(rtf.StartAddress), _r2r.Image, rtfNode);
DumpDisasm(rtf, _r2r.GetOffset(rtf.StartAddress), rtfNode);
}

if (_raw)
Expand All @@ -211,7 +211,7 @@ internal override void DumpRuntimeFunction(RuntimeFunction rtf, XmlNode parentNo
}
}

internal unsafe override void DumpDisasm(IntPtr Disasm, RuntimeFunction rtf, int imageOffset, byte[] image, XmlNode parentNode)
internal override void DumpDisasm(RuntimeFunction rtf, int imageOffset, XmlNode parentNode)
{
int rtfOffset = 0;
int codeOffset = rtf.CodeOffset;
Expand All @@ -220,7 +220,7 @@ internal unsafe override void DumpDisasm(IntPtr Disasm, RuntimeFunction rtf, int
while (rtfOffset < rtf.Size)
{
string instr;
int instrSize = CoreDisTools.GetInstruction(Disasm, rtf, imageOffset, rtfOffset, image, out instr);
int instrSize = _disassembler.GetInstruction(rtf, imageOffset, rtfOffset, out instr);

AddXMLNode("offset"+codeOffset, instr, parentNode, $"{codeOffset}");
if (transitions.ContainsKey(codeOffset))
Expand Down

0 comments on commit 66b3197

Please sign in to comment.