From f4b205e030d429d9ea36ca2671bc414a84ab3e39 Mon Sep 17 00:00:00 2001 From: Amy Yu Date: Fri, 15 Jun 2018 17:07:41 -0700 Subject: [PATCH] Interweave gcslot liveness with disasm Commit migrated from https://github.com/dotnet/coreclr/commit/c77c97e4d08ad8cafdae00128496b214dc2a2098 --- src/coreclr/src/tools/r2rdump/CoreDisTools.cs | 38 ++++++++++++++++++++------- src/coreclr/src/tools/r2rdump/GCInfo.cs | 34 +++++++++++++++++++----- src/coreclr/src/tools/r2rdump/R2RDump.cs | 9 +++---- src/coreclr/src/tools/r2rdump/R2RMethod.cs | 5 +++- src/coreclr/src/tools/r2rdump/R2RReader.cs | 5 +++- 5 files changed, 67 insertions(+), 24 deletions(-) diff --git a/src/coreclr/src/tools/r2rdump/CoreDisTools.cs b/src/coreclr/src/tools/r2rdump/CoreDisTools.cs index 16fef7e..ad3b7b4 100644 --- a/src/coreclr/src/tools/r2rdump/CoreDisTools.cs +++ b/src/coreclr/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 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/coreclr/src/tools/r2rdump/GCInfo.cs b/src/coreclr/src/tools/r2rdump/GCInfo.cs index e924d40..0442286 100644 --- a/src/coreclr/src/tools/r2rdump/GCInfo.cs +++ b/src/coreclr/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 Transitions { get; } + public Dictionary 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 GetTranstions(byte[] image, ref int bitOffset) + public Dictionary 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(); + return new Dictionary(); } 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 transitions) + private Dictionary UpdateTransitionCodeOffset(List transitions) { + Dictionary updatedTransitions = new Dictionary(); int cumInterruptibleLength = 0; using (IEnumerator 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/coreclr/src/tools/r2rdump/R2RDump.cs b/src/coreclr/src/tools/r2rdump/R2RDump.cs index be5c893..2e2c27c 100644 --- a/src/coreclr/src/tools/r2rdump/R2RDump.cs +++ b/src/coreclr/src/tools/r2rdump/R2RDump.cs @@ -178,15 +178,12 @@ namespace R2RDump /// 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/coreclr/src/tools/r2rdump/R2RMethod.cs b/src/coreclr/src/tools/r2rdump/R2RMethod.cs index 356d1eb..78e90af 100644 --- a/src/coreclr/src/tools/r2rdump/R2RMethod.cs +++ b/src/coreclr/src/tools/r2rdump/R2RMethod.cs @@ -38,6 +38,8 @@ namespace R2RDump /// public int UnwindRVA { get; } + public int CodeOffset { get; set; } + /// /// The method that this runtime function belongs to /// @@ -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/coreclr/src/tools/r2rdump/R2RReader.cs b/src/coreclr/src/tools/r2rdump/R2RReader.cs index 566928c..f0f43fc 100644 --- a/src/coreclr/src/tools/r2rdump/R2RReader.cs +++ b/src/coreclr/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]); } -- 2.7.4