Enable SymbolReader to get SequencePoints for method
authorIgor Kulaychuk <i.kulaychuk@samsung.com>
Sat, 22 Jul 2017 17:09:51 +0000 (20:09 +0300)
committerIgor Kulaychuk <i.kulaychuk@samsung.com>
Mon, 13 Nov 2017 19:22:40 +0000 (22:22 +0300)
src/ToolBox/SOS/NETCore/SymbolReader.cs
src/debug/netcoredbg/symbolreader.cpp
src/debug/netcoredbg/symbolreader.h

index 93c977e..c7b71e9 100644 (file)
@@ -41,6 +41,16 @@ namespace SOS
 
         }
 
+        [StructLayout(LayoutKind.Sequential)]
+        internal struct DbgSequencePoint
+        {
+            public int startLine;
+            public int startColumn;
+            public int endLine;
+            public int endColumn;
+            public int offset;
+        }
+
         /// <summary>
         /// Read memory callback
         /// </summary>
@@ -337,6 +347,65 @@ namespace SOS
             return false;
         }
 
+        internal static bool GetSequencePoints(IntPtr symbolReaderHandle, int methodToken, out IntPtr points, out int pointsCount)
+        {
+            Debug.Assert(symbolReaderHandle != IntPtr.Zero);
+            pointsCount = 0;
+            points = IntPtr.Zero;
+
+            Debug.Assert(symbolReaderHandle != IntPtr.Zero);
+
+            GCHandle gch = GCHandle.FromIntPtr(symbolReaderHandle);
+            MetadataReader reader = ((OpenedReader)gch.Target).Reader;
+
+            try
+            {
+                Handle handle = MetadataTokens.Handle(methodToken);
+                if (handle.Kind != HandleKind.MethodDefinition)
+                    return false;
+
+                MethodDebugInformationHandle methodDebugHandle = ((MethodDefinitionHandle)handle).ToDebugInformationHandle();
+                if (methodDebugHandle.IsNil)
+                    return false;
+
+                MethodDebugInformation methodDebugInfo = reader.GetMethodDebugInformation(methodDebugHandle);
+                SequencePointCollection sequencePoints = methodDebugInfo.GetSequencePoints();
+
+                var list = new List<DbgSequencePoint>();
+                foreach (SequencePoint p in sequencePoints)
+                {
+                    list.Add(new DbgSequencePoint() {
+                        startLine = p.StartLine,
+                        endLine = p.EndLine,
+                        startColumn = p.StartColumn,
+                        endColumn = p.EndColumn,
+                        offset = p.Offset
+                    });
+                }
+
+                if (list.Count == 0)
+                    return true;
+
+                var structSize = Marshal.SizeOf<DbgSequencePoint>();
+                IntPtr allPoints = Marshal.AllocCoTaskMem(list.Count * structSize);
+                var currentPtr = allPoints;
+
+                foreach (var p in list)
+                {
+                    Marshal.StructureToPtr(p, currentPtr, false);
+                    currentPtr = (IntPtr)(currentPtr.ToInt64() + structSize);
+                }
+
+                points = allPoints;
+                pointsCount = list.Count;
+                return true;
+            }
+            catch
+            {
+            }
+            return false;
+        }
+
         internal static bool GetStepRangesFromIP(IntPtr symbolReaderHandle, int ip, int methodToken, out uint ilStartOffset, out uint ilEndOffset)
         {
             Debug.Assert(symbolReaderHandle != IntPtr.Zero);
index 1bb7040..a06cb20 100644 (file)
@@ -1,6 +1,7 @@
 #include "common.h"
 
 #include <string>
+#include <vector>
 
 #include "symbolreader.h"
 
@@ -13,6 +14,9 @@ ResolveSequencePointDelegate SymbolReader::resolveSequencePointDelegate;
 GetLocalVariableNameAndScope SymbolReader::getLocalVariableNameAndScopeDelegate;
 GetLineByILOffsetDelegate SymbolReader::getLineByILOffsetDelegate;
 GetStepRangesFromIPDelegate SymbolReader::getStepRangesFromIPDelegate;
+GetSequencePointsDelegate SymbolReader::getSequencePointsDelegate;
+
+const int SymbolReader::HiddenLine = 0xfeefee;
 
 HRESULT SymbolReader::LoadSymbols(IMetaDataImport* pMD, ICorDebugModule* pModule)
 {
@@ -183,6 +187,7 @@ HRESULT SymbolReader::PrepareSymbolReader()
     IfFailRet(createDelegate(hostHandle, domainId, SymbolReaderDllName, SymbolReaderClassName, "GetLocalVariableNameAndScope", (void **)&getLocalVariableNameAndScopeDelegate));
     IfFailRet(createDelegate(hostHandle, domainId, SymbolReaderDllName, SymbolReaderClassName, "GetLineByILOffset", (void **)&getLineByILOffsetDelegate));
     IfFailRet(createDelegate(hostHandle, domainId, SymbolReaderDllName, SymbolReaderClassName, "GetStepRangesFromIP", (void **)&getStepRangesFromIPDelegate));
+    IfFailRet(createDelegate(hostHandle, domainId, SymbolReaderDllName, SymbolReaderClassName, "GetSequencePoints", (void **)&getSequencePointsDelegate));
 
     return Status;
 }
@@ -300,3 +305,29 @@ HRESULT SymbolReader::GetNamedLocalVariableAndScope(
     }
     return S_OK;
 }
+
+HRESULT SymbolReader::GetSequencePoints(mdMethodDef methodToken, std::vector<SequencePoint> &points)
+{
+    HRESULT Status = S_OK;
+
+    if (m_symbolReaderHandle != 0)
+    {
+        _ASSERTE(getSequencePointsDelegate != nullptr);
+
+        SequencePoint *allocatedPoints = nullptr;
+        int pointsCount = 0;
+
+        if (getSequencePointsDelegate(m_symbolReaderHandle, methodToken, (PVOID*)&allocatedPoints, &pointsCount) == FALSE)
+        {
+            return E_FAIL;
+        }
+
+        points.assign(allocatedPoints, allocatedPoints + pointsCount);
+
+        CoTaskMemFree(allocatedPoints);
+
+        return S_OK;
+    }
+
+    return E_FAIL;
+}
\ No newline at end of file
index 9b9d8f9..a375c6e 100644 (file)
@@ -8,6 +8,7 @@ typedef  BOOL (*ResolveSequencePointDelegate)(PVOID, const char*, unsigned int,
 typedef  BOOL (*GetLocalVariableNameAndScope)(PVOID, int, int, BSTR*, unsigned int*, unsigned int*);
 typedef  BOOL (*GetLineByILOffsetDelegate)(PVOID, mdMethodDef, ULONG64, ULONG *, BSTR*);
 typedef  BOOL (*GetStepRangesFromIPDelegate)(PVOID, int, mdMethodDef, unsigned int*, unsigned int*);
+typedef  BOOL (*GetSequencePointsDelegate)(PVOID, mdMethodDef, PVOID*, int*);
 
 BOOL SafeReadMemory (TADDR offset, PVOID lpBuffer, ULONG cb,
                      PULONG lpcbBytesRead);
@@ -24,6 +25,7 @@ private:
     static GetLocalVariableNameAndScope getLocalVariableNameAndScopeDelegate;
     static GetLineByILOffsetDelegate getLineByILOffsetDelegate;
     static GetStepRangesFromIPDelegate getStepRangesFromIPDelegate;
+    static GetSequencePointsDelegate getSequencePointsDelegate;
 
     static HRESULT PrepareSymbolReader();
 
@@ -37,6 +39,15 @@ private:
         ULONG64 inMemoryPdbSize);
 
 public:
+    static const int HiddenLine;
+    struct __attribute__((packed)) SequencePoint {
+        int32_t startLine;
+        int32_t startColumn;
+        int32_t endLine;
+        int32_t endColumn;
+        int32_t offset;
+    };
+
     SymbolReader()
     {
         m_symbolReaderHandle = 0;
@@ -60,4 +71,5 @@ public:
     HRESULT GetNamedLocalVariableAndScope(ICorDebugILFrame * pILFrame, mdMethodDef methodToken, ULONG localIndex, WCHAR* paramName, ULONG paramNameLen, ICorDebugValue **ppValue, ULONG32* pIlStart, ULONG32* pIlEnd);
     HRESULT ResolveSequencePoint(WCHAR* pFilename, ULONG32 lineNumber, TADDR mod, mdMethodDef* pToken, ULONG32* pIlOffset);
     HRESULT GetStepRangesFromIP(ULONG64 ip, mdMethodDef MethodToken, ULONG32 *ilStartOffset, ULONG32 *ilEndOffset);
+    HRESULT GetSequencePoints(mdMethodDef methodToken, std::vector<SequencePoint> &points);
 };