summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/tools/r2rdump/CoreDisTools.cs38
-rw-r--r--src/tools/r2rdump/GCInfo.cs34
-rw-r--r--src/tools/r2rdump/R2RDump.cs9
-rw-r--r--src/tools/r2rdump/R2RMethod.cs5
-rw-r--r--src/tools/r2rdump/R2RReader.cs5
5 files changed, 67 insertions, 24 deletions
diff --git a/src/tools/r2rdump/CoreDisTools.cs b/src/tools/r2rdump/CoreDisTools.cs
index 16fef7e848..ad3b7b45e4 100644
--- a/src/tools/r2rdump/CoreDisTools.cs
+++ b/src/tools/r2rdump/CoreDisTools.cs
@@ -3,8 +3,10 @@
// See the LICENSE file in the project root for more information.
using System;
+using System.Collections.Generic;
using System.Reflection.PortableExecutable;
using System.Runtime.InteropServices;
+using System.Text;
namespace R2RDump
{
@@ -38,18 +40,36 @@ namespace R2RDump
[DllImport("coredistools.dll")]
public static extern void FinishDisasm(IntPtr Disasm);
- public unsafe static string GetCodeBlock(IntPtr Disasm, int Address, int Offset, byte[] image, int Size)
+ public unsafe static string GetCodeBlock(IntPtr Disasm, RuntimeFunction rtf, int imageOffset, byte[] image)
{
- int len;
- fixed (byte* p = image)
+ StringBuilder sb = new StringBuilder();
+
+ int rtfOffset = 0;
+ int codeOffset = rtf.CodeOffset;
+ Dictionary<int, GcInfo.GcTransition> transitions = rtf.Method.GcInfo.Transitions;
+ GcSlotTable slotTable = rtf.Method.GcInfo.SlotTable;
+ while (rtfOffset < rtf.Size)
{
- IntPtr ptr = (IntPtr)(p + Offset);
- len = DumpInstruction(Disasm, (ulong)Address, ptr, Size); //DumpCodeBlock(Disasm, (ulong)Address, ptr, Size);
+ int instrSize = 1;
+ fixed (byte* p = image)
+ {
+ IntPtr ptr = (IntPtr)(p + imageOffset + rtfOffset);
+ instrSize = DumpInstruction(Disasm, (ulong)(rtf.StartAddress + rtfOffset), ptr, rtf.Size);
+ }
+ IntPtr pBuffer = GetOutputBuffer();
+ string instr = Marshal.PtrToStringAnsi(pBuffer);
+
+ sb.Append(instr);
+ if (transitions.ContainsKey(codeOffset))
+ {
+ sb.AppendLine($"\t\t\t\t{transitions[codeOffset].GetSlotState(slotTable)}");
+ }
+
+ ClearOutputBuffer();
+ rtfOffset += instrSize;
+ codeOffset += instrSize;
}
- IntPtr pBuffer = GetOutputBuffer();
- string buffer = Marshal.PtrToStringAnsi(pBuffer);
- ClearOutputBuffer();
- return buffer;
+ return sb.ToString();
}
public static IntPtr GetDisasm(Machine machine)
diff --git a/src/tools/r2rdump/GCInfo.cs b/src/tools/r2rdump/GCInfo.cs
index e924d408c7..04422862e3 100644
--- a/src/tools/r2rdump/GCInfo.cs
+++ b/src/tools/r2rdump/GCInfo.cs
@@ -48,6 +48,7 @@ namespace R2RDump
public int SlotId { get; }
public bool IsLive { get; }
public int ChunkId { get; }
+
public GcTransition(int codeOffset, int slotId, bool isLive, int chunkId)
{
CodeOffset = codeOffset;
@@ -68,6 +69,23 @@ namespace R2RDump
return sb.ToString();
}
+ public string GetSlotState(GcSlotTable slotTable)
+ {
+ GcSlotTable.GcSlot slot = slotTable.GcSlots[SlotId];
+ string slotStr = "";
+ if (slot.StackSlot == null)
+ {
+ slotStr = Enum.GetName(typeof(Amd64Registers), slot.RegisterNumber);
+ }
+ else
+ {
+ slotStr = $"sp{slot.StackSlot.SpOffset:+#;-#;+0}";
+ }
+ string isLiveStr = "live";
+ if (!IsLive)
+ isLiveStr = "dead";
+ return $"{slotStr} is {isLiveStr}";
+ }
}
private const int GCINFO_VERSION = 2;
@@ -107,7 +125,7 @@ namespace R2RDump
public GcSlotTable SlotTable { get; }
public int Size { get; }
public int Offset { get; }
- public IList<GcTransition> Transitions { get; }
+ public Dictionary<int, GcTransition> Transitions { get; }
public GcInfo(byte[] image, int offset, Machine machine, ushort majorVersion)
{
@@ -283,7 +301,7 @@ namespace R2RDump
sb.AppendLine($"{tab}SlotTable:");
sb.Append(SlotTable.ToString());
sb.AppendLine($"{tab}Transitions:");
- foreach (GcTransition trans in Transitions)
+ foreach (GcTransition trans in Transitions.Values)
{
sb.AppendLine(trans.ToString());
}
@@ -359,7 +377,7 @@ namespace R2RDump
return (readyToRunMajorVersion == 1) ? 1 : GCINFO_VERSION;
}
- public IList<GcTransition> GetTranstions(byte[] image, ref int bitOffset)
+ public Dictionary<int, GcTransition> GetTranstions(byte[] image, ref int bitOffset)
{
int totalInterruptibleLength = 0;
if (NumInterruptibleRanges == 0)
@@ -378,7 +396,7 @@ namespace R2RDump
int numBitsPerPointer = (int)NativeReader.DecodeVarLengthUnsigned(image, _gcInfoTypes.POINTER_SIZE_ENCBASE, ref bitOffset);
if (numBitsPerPointer == 0)
{
- return new List<GcTransition>();
+ return new Dictionary<int, GcTransition>();
}
int[] chunkPointers = new int[numChunks];
@@ -437,9 +455,8 @@ namespace R2RDump
}
transitions.Sort((s1, s2) => s1.CodeOffset.CompareTo(s2.CodeOffset));
- UpdateTransitionCodeOffset(transitions);
- return transitions;
+ return UpdateTransitionCodeOffset(transitions);
}
private uint GetNumCouldBeLiveSlots(byte[] image, ref int bitOffset)
@@ -507,8 +524,9 @@ namespace R2RDump
return slotId;
}
- private void UpdateTransitionCodeOffset(List<GcTransition> transitions)
+ private Dictionary<int, GcTransition> UpdateTransitionCodeOffset(List<GcTransition> transitions)
{
+ Dictionary<int, GcTransition> updatedTransitions = new Dictionary<int, GcTransition>();
int cumInterruptibleLength = 0;
using (IEnumerator<InterruptibleRange> interruptibleRangesIter = InterruptibleRanges.GetEnumerator())
{
@@ -527,8 +545,10 @@ namespace R2RDump
codeOffset = transition.CodeOffset + (int)currentRange.StartOffset - cumInterruptibleLength;
}
transition.CodeOffset = codeOffset;
+ updatedTransitions[codeOffset] = transition;
}
}
+ return updatedTransitions;
}
}
}
diff --git a/src/tools/r2rdump/R2RDump.cs b/src/tools/r2rdump/R2RDump.cs
index be5c893196..2e2c27cdf2 100644
--- a/src/tools/r2rdump/R2RDump.cs
+++ b/src/tools/r2rdump/R2RDump.cs
@@ -178,15 +178,12 @@ namespace R2RDump
/// </summary>
private void DumpRuntimeFunction(R2RReader r2r, RuntimeFunction rtf)
{
+ _writer.Write($"{rtf}");
if (_disasm)
{
- _writer.WriteLine($"Id: {rtf.Id}");
- _writer.Write(CoreDisTools.GetCodeBlock(_disassembler, rtf.StartAddress, r2r.GetOffset(rtf.StartAddress), r2r.Image, rtf.Size));
- }
- else
- {
- _writer.Write($"{rtf}");
+ _writer.Write(CoreDisTools.GetCodeBlock(_disassembler, rtf, r2r.GetOffset(rtf.StartAddress), r2r.Image));
}
+
if (_raw)
{
_writer.WriteLine("Raw Bytes:");
diff --git a/src/tools/r2rdump/R2RMethod.cs b/src/tools/r2rdump/R2RMethod.cs
index 356d1eb98d..78e90af9c3 100644
--- a/src/tools/r2rdump/R2RMethod.cs
+++ b/src/tools/r2rdump/R2RMethod.cs
@@ -38,6 +38,8 @@ namespace R2RDump
/// </summary>
public int UnwindRVA { get; }
+ public int CodeOffset { get; set; }
+
/// <summary>
/// The method that this runtime function belongs to
/// </summary>
@@ -45,7 +47,7 @@ namespace R2RDump
public UnwindInfo UnwindInfo { get; }
- public RuntimeFunction(int id, int startRva, int endRva, int unwindRva, R2RMethod method, UnwindInfo unwindInfo, GcInfo gcInfo)
+ public RuntimeFunction(int id, int startRva, int endRva, int unwindRva, int codeOffset, R2RMethod method, UnwindInfo unwindInfo, GcInfo gcInfo)
{
Id = id;
StartAddress = startRva;
@@ -60,6 +62,7 @@ namespace R2RDump
{
Size = gcInfo.CodeLength;
}
+ CodeOffset = codeOffset;
method.GcInfo = gcInfo;
}
diff --git a/src/tools/r2rdump/R2RReader.cs b/src/tools/r2rdump/R2RReader.cs
index 566928c5de..f0f43fcca7 100644
--- a/src/tools/r2rdump/R2RReader.cs
+++ b/src/tools/r2rdump/R2RReader.cs
@@ -208,6 +208,7 @@ namespace R2RDump
continue;
curOffset = runtimeFunctionOffset + runtimeFunctionId * runtimeFunctionSize;
GcInfo gcInfo = null;
+ int codeOffset = 0;
do
{
int startRva = NativeReader.ReadInt32(Image, ref curOffset);
@@ -225,8 +226,10 @@ namespace R2RDump
gcInfo = new GcInfo(Image, unwindOffset + unwindInfo.Size, Machine, R2RHeader.MajorVersion);
}
- method.RuntimeFunctions.Add(new RuntimeFunction(runtimeFunctionId, startRva, endRva, unwindRva, method, unwindInfo, gcInfo));
+ RuntimeFunction rtf = new RuntimeFunction(runtimeFunctionId, startRva, endRva, unwindRva, codeOffset, method, unwindInfo, gcInfo);
+ method.RuntimeFunctions.Add(rtf);
runtimeFunctionId++;
+ codeOffset += rtf.Size;
}
while (runtimeFunctionId < isEntryPoint.Length && !isEntryPoint[runtimeFunctionId]);
}