Interweave gcslot liveness with disasm
authorAmy Yu <amycmyu@gmail.com>
Sat, 16 Jun 2018 00:07:41 +0000 (17:07 -0700)
committerAmy Yu <amycmyu@gmail.com>
Sat, 16 Jun 2018 00:20:47 +0000 (17:20 -0700)
Commit migrated from https://github.com/dotnet/coreclr/commit/c77c97e4d08ad8cafdae00128496b214dc2a2098

src/coreclr/src/tools/r2rdump/CoreDisTools.cs
src/coreclr/src/tools/r2rdump/GCInfo.cs
src/coreclr/src/tools/r2rdump/R2RDump.cs
src/coreclr/src/tools/r2rdump/R2RMethod.cs
src/coreclr/src/tools/r2rdump/R2RReader.cs

index 16fef7e..ad3b7b4 100644 (file)
@@ -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)
index e924d40..0442286 100644 (file)
@@ -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;
         }
     }
 }
index be5c893..2e2c27c 100644 (file)
@@ -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:");
index 356d1eb..78e90af 100644 (file)
@@ -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;
         }
 
index 566928c..f0f43fc 100644 (file)
@@ -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]);
             }