Do not show out-of-scope local variables
authorIgor Kulaychuk <i.kulaychuk@samsung.com>
Tue, 11 Jul 2017 14:46:50 +0000 (17:46 +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/debugger/modules.cpp
src/debug/debugger/symbolreader.cpp
src/debug/debugger/symbolreader.h
src/debug/debugger/valueprint.cpp
src/debug/debugger/valuewalk.cpp
src/debug/debugger/varobj.cpp

index ca8a701..f62f4ab 100644 (file)
@@ -391,6 +391,65 @@ namespace SOS
             return false;
         }
 
+        internal static bool GetLocalVariableNameAndScope(IntPtr symbolReaderHandle, int methodToken, int localIndex, out IntPtr localVarName, out int ilStartOffset, out int ilEndOffset)
+        {
+            localVarName = IntPtr.Zero;
+            ilStartOffset = 0;
+            ilEndOffset = 0;
+
+            string localVar = null;
+            if (!GetLocalVariableAndScopeByIndex(symbolReaderHandle, methodToken, localIndex, out localVar, out ilStartOffset, out ilEndOffset))
+                return false;
+
+            localVarName = Marshal.StringToBSTR(localVar);
+            localVar = null;
+            return true;
+        }
+
+        internal static bool GetLocalVariableAndScopeByIndex(IntPtr symbolReaderHandle, int methodToken, int localIndex, out string localVarName, out int ilStartOffset, out int ilEndOffset)
+        {
+            Debug.Assert(symbolReaderHandle != IntPtr.Zero);
+            localVarName = null;
+            ilStartOffset = 0;
+            ilEndOffset = 0;
+
+            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();
+                LocalScopeHandleCollection localScopes = reader.GetLocalScopes(methodDebugHandle);
+                foreach (LocalScopeHandle scopeHandle in localScopes)
+                {
+                    LocalScope scope = reader.GetLocalScope(scopeHandle);
+                    LocalVariableHandleCollection localVars = scope.GetLocalVariables();
+                    foreach (LocalVariableHandle varHandle in localVars)
+                    {
+                        LocalVariable localVar = reader.GetLocalVariable(varHandle);
+                        if (localVar.Index == localIndex)
+                        {
+                            if (localVar.Attributes == LocalVariableAttributes.DebuggerHidden)
+                                return false;
+
+                            localVarName = reader.GetString(localVar.Name);
+                            ilStartOffset = scope.StartOffset;
+                            ilEndOffset = scope.EndOffset;
+                            return true;
+                        }
+                    }
+                }
+            }
+            catch
+            {
+            }
+            return false;
+        }
+
         /// <summary>
         /// Returns local variable name for given local index and IL offset.
         /// </summary>
index c7854da..53d6536 100644 (file)
@@ -204,7 +204,9 @@ HRESULT GetFrameNamedLocalVariable(
     mdMethodDef methodToken,
     ULONG localIndex,
     std::string &paramName,
-    ICorDebugValue** ppValue)
+    ICorDebugValue** ppValue,
+    ULONG32 *pIlStart,
+    ULONG32 *pIlEnd)
 {
     HRESULT Status;
 
@@ -218,7 +220,7 @@ HRESULT GetFrameNamedLocalVariable(
             return E_FAIL;
         }
 
-        IfFailRet(info_pair->second.symbols->GetNamedLocalVariable(pILFrame, methodToken, localIndex, wParamName, _countof(wParamName), ppValue));
+        IfFailRet(info_pair->second.symbols->GetNamedLocalVariableAndScope(pILFrame, methodToken, localIndex, wParamName, _countof(wParamName), ppValue, pIlStart, pIlEnd));
     }
 
     paramName = to_utf8(wParamName);
index ed894ec..e82cf1d 100644 (file)
@@ -24,7 +24,7 @@ std::string SymbolReader::coreClrPath;
 LoadSymbolsForModuleDelegate SymbolReader::loadSymbolsForModuleDelegate;
 DisposeDelegate SymbolReader::disposeDelegate;
 ResolveSequencePointDelegate SymbolReader::resolveSequencePointDelegate;
-GetLocalVariableName SymbolReader::getLocalVariableNameDelegate;
+GetLocalVariableNameAndScope SymbolReader::getLocalVariableNameAndScopeDelegate;
 GetLineByILOffsetDelegate SymbolReader::getLineByILOffsetDelegate;
 GetStepRangesFromIPDelegate SymbolReader::getStepRangesFromIPDelegate;
 
@@ -230,7 +230,7 @@ HRESULT SymbolReader::PrepareSymbolReader()
     IfFailRet(createDelegate(hostHandle, domainId, SymbolReaderDllName, SymbolReaderClassName, "LoadSymbolsForModule", (void **)&loadSymbolsForModuleDelegate));
     IfFailRet(createDelegate(hostHandle, domainId, SymbolReaderDllName, SymbolReaderClassName, "Dispose", (void **)&disposeDelegate));
     IfFailRet(createDelegate(hostHandle, domainId, SymbolReaderDllName, SymbolReaderClassName, "ResolveSequencePoint", (void **)&resolveSequencePointDelegate));
-    IfFailRet(createDelegate(hostHandle, domainId, SymbolReaderDllName, SymbolReaderClassName, "GetLocalVariableName", (void **)&getLocalVariableNameDelegate));
+    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));
 
@@ -311,15 +311,22 @@ HRESULT SymbolReader::GetStepRangesFromIP(ULONG64 ip, mdMethodDef MethodToken, U
     return E_FAIL;
 }
 
-HRESULT SymbolReader::GetNamedLocalVariable(ICorDebugILFrame * pILFrame, mdMethodDef methodToken,
-    ULONG localIndex, WCHAR* paramName, ULONG paramNameLen, ICorDebugValue** ppValue)
+HRESULT SymbolReader::GetNamedLocalVariableAndScope(
+    ICorDebugILFrame * pILFrame,
+    mdMethodDef methodToken,
+    ULONG localIndex,
+    WCHAR* paramName,
+    ULONG paramNameLen,
+    ICorDebugValue** ppValue,
+    ULONG32* pIlStart,
+    ULONG32* pIlEnd)
 {
     HRESULT Status = S_OK;
 
     if (!m_symbolReaderHandle)
         return E_FAIL;
 
-    _ASSERTE(getLocalVariableNameDelegate != nullptr);
+    _ASSERTE(getLocalVariableNameAndScopeDelegate != nullptr);
 
     BSTR wszParamName = SysAllocStringLen(0, mdNameLen);
     if (wszParamName == NULL)
@@ -327,7 +334,7 @@ HRESULT SymbolReader::GetNamedLocalVariable(ICorDebugILFrame * pILFrame, mdMetho
         return E_OUTOFMEMORY;
     }
 
-    if (getLocalVariableNameDelegate(m_symbolReaderHandle, methodToken, localIndex, &wszParamName) == FALSE)
+    if (getLocalVariableNameAndScopeDelegate(m_symbolReaderHandle, methodToken, localIndex, &wszParamName, pIlStart, pIlEnd) == FALSE)
     {
         SysFreeString(wszParamName);
         return E_FAIL;
index 88cfe89..10d7fc4 100644 (file)
@@ -5,7 +5,7 @@ typedef  int (*ReadMemoryDelegate)(ULONG64, char *, int);
 typedef  PVOID (*LoadSymbolsForModuleDelegate)(const char*, BOOL, ULONG64, int, ULONG64, int, ReadMemoryDelegate);
 typedef  void (*DisposeDelegate)(PVOID);
 typedef  BOOL (*ResolveSequencePointDelegate)(PVOID, const char*, unsigned int, unsigned int*, unsigned int*);
-typedef  BOOL (*GetLocalVariableName)(PVOID, int, int, BSTR*);
+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*);
 
@@ -21,7 +21,7 @@ private:
     static LoadSymbolsForModuleDelegate loadSymbolsForModuleDelegate;
     static DisposeDelegate disposeDelegate;
     static ResolveSequencePointDelegate resolveSequencePointDelegate;
-    static GetLocalVariableName getLocalVariableNameDelegate;
+    static GetLocalVariableNameAndScope getLocalVariableNameAndScopeDelegate;
     static GetLineByILOffsetDelegate getLineByILOffsetDelegate;
     static GetStepRangesFromIPDelegate getStepRangesFromIPDelegate;
 
@@ -55,7 +55,7 @@ public:
 
     HRESULT LoadSymbols(IMetaDataImport* pMD, ICorDebugModule* pModule);
     HRESULT GetLineByILOffset(mdMethodDef MethodToken, ULONG64 IlOffset, ULONG *pLinenum, WCHAR* pwszFileName, ULONG cchFileName);
-    HRESULT GetNamedLocalVariable(ICorDebugILFrame * pILFrame, mdMethodDef methodToken, ULONG localIndex, WCHAR* paramName, ULONG paramNameLen, ICorDebugValue **ppValue);
+    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);
 };
index 8cd3a5d..ffe8d53 100644 (file)
 #include "torelease.h"
 #include "arrayholder.h"
 #include "cputil.h"
-
-// Modules
-HRESULT GetFrameNamedLocalVariable(
-    ICorDebugModule *pModule,
-    ICorDebugILFrame *pILFrame,
-    mdMethodDef methodToken,
-    ULONG localIndex,
-    std::string &paramName,
-    ICorDebugValue** ppValue);
-
 #include "typeprinter.h"
 
 // From strike.cpp
index f6d9d93..34534ac 100644 (file)
@@ -26,7 +26,9 @@ HRESULT GetFrameNamedLocalVariable(
     mdMethodDef methodToken,
     ULONG localIndex,
     std::string &paramName,
-    ICorDebugValue** ppValue);
+    ICorDebugValue** ppValue,
+    ULONG32 *pIlStart,
+    ULONG32 *pIlEnd);
 
 #include "typeprinter.h"
 
@@ -354,6 +356,10 @@ HRESULT WalkStackVars(ICorDebugFrame *pFrame, WalkStackVarsCallback cb)
     ULONG cLocals = 0;
     ToRelease<ICorDebugValueEnum> pLocalsEnum;
 
+    ULONG32 currentIlOffset;
+    CorDebugMappingResult mappingResult;
+    IfFailRet(pILFrame->GetIP(&currentIlOffset, &mappingResult));
+
     IfFailRet(pILFrame->EnumerateLocalVariables(&pLocalsEnum));
     IfFailRet(pLocalsEnum->GetCount(&cLocals));
     if (cLocals > 0)
@@ -363,11 +369,16 @@ HRESULT WalkStackVars(ICorDebugFrame *pFrame, WalkStackVarsCallback cb)
             std::string paramName;
 
             ToRelease<ICorDebugValue> pValue;
-            Status = GetFrameNamedLocalVariable(pModule, pILFrame, methodDef, i, paramName, &pValue);
+            ULONG32 ilStart;
+            ULONG32 ilEnd;
+            Status = GetFrameNamedLocalVariable(pModule, pILFrame, methodDef, i, paramName, &pValue, &ilStart, &ilEnd);
 
             if (FAILED(Status))
                 continue;
 
+            if (currentIlOffset < ilStart || currentIlOffset >= ilEnd)
+                continue;
+
             if (Status == S_FALSE)
                 break;
 
index 32929e6..7633f8e 100644 (file)
 
 #include "torelease.h"
 #include "arrayholder.h"
-
-// Modules
-HRESULT GetFrameNamedLocalVariable(
-    ICorDebugModule *pModule,
-    ICorDebugILFrame *pILFrame,
-    mdMethodDef methodToken,
-    ULONG localIndex,
-    std::string &paramName,
-    ICorDebugValue** ppValue);
-
 #include "typeprinter.h"
 
 // Valuewalk