summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomáš Rylek <trylek@microsoft.com>2018-08-14 12:37:19 +0200
committerGitHub <noreply@github.com>2018-08-14 12:37:19 +0200
commit66b3197f69cf4669ba04a7a8121d33d9aa5d3c9d (patch)
tree79cff94a7c5454bd909287713f8f8f2dd340dd71
parentc509903171fedf0a4a6f9fffeb6e2b9820f537c2 (diff)
downloadcoreclr-66b3197f69cf4669ba04a7a8121d33d9aa5d3c9d.tar.gz
coreclr-66b3197f69cf4669ba04a7a8121d33d9aa5d3c9d.tar.bz2
coreclr-66b3197f69cf4669ba04a7a8121d33d9aa5d3c9d.zip
Translate [rip +- offset] to absolute RVA's in R2RDump (#19219)
* 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
-rw-r--r--src/tools/r2rdump/CoreDisTools.cs87
-rw-r--r--src/tools/r2rdump/R2RDump.cs22
-rw-r--r--src/tools/r2rdump/TextDumper.cs8
-rw-r--r--src/tools/r2rdump/XmlDumper.cs8
4 files changed, 106 insertions, 19 deletions
diff --git a/src/tools/r2rdump/CoreDisTools.cs b/src/tools/r2rdump/CoreDisTools.cs
index 194b449adb..214be53d04 100644
--- a/src/tools/r2rdump/CoreDisTools.cs
+++ b/src/tools/r2rdump/CoreDisTools.cs
@@ -76,4 +76,91 @@ namespace R2RDump
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);
+ }
+ }
+ }
+ }
+ }
}
diff --git a/src/tools/r2rdump/R2RDump.cs b/src/tools/r2rdump/R2RDump.cs
index 2391de0a0b..9341c44164 100644
--- a/src/tools/r2rdump/R2RDump.cs
+++ b/src/tools/r2rdump/R2RDump.cs
@@ -18,7 +18,7 @@ namespace R2RDump
internal bool _raw;
internal bool _header;
internal bool _disasm;
- internal IntPtr _disassembler;
+ internal Disassembler _disassembler;
internal bool _unwind;
internal bool _gc;
internal bool _sectionContents;
@@ -34,7 +34,7 @@ namespace R2RDump
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);
@@ -54,7 +54,6 @@ namespace 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;
@@ -371,6 +370,8 @@ namespace R2RDump
return 0;
}
+ Disassembler disassembler = null;
+
try
{
if (_inputFilenames.Count == 0)
@@ -382,24 +383,19 @@ namespace R2RDump
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)
@@ -425,6 +421,10 @@ namespace R2RDump
}
finally
{
+ if (disassembler != null)
+ {
+ disassembler.Dispose();
+ }
// close output stream
_writer.Close();
}
diff --git a/src/tools/r2rdump/TextDumper.cs b/src/tools/r2rdump/TextDumper.cs
index a1c6905f3e..41bd9fae80 100644
--- a/src/tools/r2rdump/TextDumper.cs
+++ b/src/tools/r2rdump/TextDumper.cs
@@ -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;
@@ -147,7 +147,7 @@ namespace R2RDump
if (_disasm)
{
- DumpDisasm(_disassembler, rtf, _r2r.GetOffset(rtf.StartAddress), _r2r.Image);
+ DumpDisasm(rtf, _r2r.GetOffset(rtf.StartAddress));
}
if (_raw)
@@ -167,14 +167,14 @@ namespace R2RDump
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))
diff --git a/src/tools/r2rdump/XmlDumper.cs b/src/tools/r2rdump/XmlDumper.cs
index f724d7bb2d..3676baad2f 100644
--- a/src/tools/r2rdump/XmlDumper.cs
+++ b/src/tools/r2rdump/XmlDumper.cs
@@ -14,7 +14,7 @@ namespace R2RDump
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;
@@ -190,7 +190,7 @@ namespace R2RDump
if (_disasm)
{
- DumpDisasm(_disassembler, rtf, _r2r.GetOffset(rtf.StartAddress), _r2r.Image, rtfNode);
+ DumpDisasm(rtf, _r2r.GetOffset(rtf.StartAddress), rtfNode);
}
if (_raw)
@@ -211,7 +211,7 @@ namespace R2RDump
}
}
- 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;
@@ -220,7 +220,7 @@ namespace R2RDump
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))