From 1882b7f35e607bf785eca25c6979d50a1db82728 Mon Sep 17 00:00:00 2001 From: Charles Stoner Date: Fri, 25 Sep 2015 11:42:53 -0700 Subject: [PATCH] Fix function pointer representation --- .../ResultProvider/FunctionPointerTests.cs | 75 +++++++++++++------ .../Debugger/Engine/DkmClrValue.cs | 27 ++++--- 2 files changed, 70 insertions(+), 32 deletions(-) diff --git a/src/ExpressionEvaluator/CSharp/Test/ResultProvider/FunctionPointerTests.cs b/src/ExpressionEvaluator/CSharp/Test/ResultProvider/FunctionPointerTests.cs index c9df0accc30..7df62f7f8ca 100644 --- a/src/ExpressionEvaluator/CSharp/Test/ResultProvider/FunctionPointerTests.cs +++ b/src/ExpressionEvaluator/CSharp/Test/ResultProvider/FunctionPointerTests.cs @@ -3,6 +3,8 @@ using Microsoft.CodeAnalysis.ExpressionEvaluator; using Microsoft.VisualStudio.Debugger.Clr; using Microsoft.VisualStudio.Debugger.Evaluation; +using Microsoft.VisualStudio.Debugger.Evaluation.ClrCompilation; +using Microsoft.VisualStudio.Debugger.Metadata; using System; using System.Diagnostics; using Xunit; @@ -12,40 +14,71 @@ namespace Microsoft.CodeAnalysis.CSharp.UnitTests { public class FunctionPointerTests : CSharpResultProviderTestBase { - [Fact(Skip = "Tests are failing in Jenkins queues")] + [Fact] public void Root() { - const int ptr = 0x1234; - var value = CreateDkmClrValue(ptr, type: new DkmClrType(FunctionPointerType.Instance)); - var evalResult = FormatResult("pfn", value); - Verify(evalResult, - EvalResult("pfn", PointerToString(new IntPtr(ptr)), "System.Object*", "pfn", DkmEvaluationResultFlags.None, DkmEvaluationResultCategory.Other)); + var source = +@"unsafe class C +{ + internal C(long p) + { + this.pfn = (int*)p; + } + int* pfn; +}"; + var assembly = GetUnsafeAssembly(source); + unsafe + { + int i = 0x1234; + long ptr = (long)&i; + var type = assembly.GetType("C"); + var value = GetFunctionPointerField(CreateDkmClrValue(type.Instantiate(ptr)), "pfn"); + var evalResult = FormatResult("pfn", value); + Verify(evalResult, + EvalResult("pfn", PointerToString(new IntPtr(ptr)), "System.Object*", "pfn", DkmEvaluationResultFlags.None, DkmEvaluationResultCategory.Other)); + } } - [Fact(Skip = "Tests are failing in Jenkins queues")] + [Fact] public void Member() { var source = -@"class C +@"unsafe class C { - object pfn; + internal C(long p) + { + this.pfn = (int*)p; + } + int* pfn; }"; - const int ptr = 0x0; - GetMemberValueDelegate getMemberValue = (v, m) => (m == "pfn") ? CreateDkmClrValue(ptr, type: new DkmClrType(FunctionPointerType.Instance)) : null; - var runtime = new DkmClrRuntimeInstance(ReflectionUtilities.GetMscorlibAndSystemCore(GetAssembly(source)), getMemberValue: getMemberValue); - using (runtime.Load()) + var assembly = GetUnsafeAssembly(source); + unsafe { - var type = runtime.GetType("C"); - var value = CreateDkmClrValue(type.Instantiate(), type: type); - var evalResult = FormatResult("o", value); - Verify(evalResult, - EvalResult("o", "{C}", "C", "o", DkmEvaluationResultFlags.Expandable, DkmEvaluationResultCategory.Other)); - var children = GetChildren(evalResult); - Verify(children, - EvalResult("pfn", PointerToString(new IntPtr(ptr)), "object {System.Object*}", "o.pfn", DkmEvaluationResultFlags.None, DkmEvaluationResultCategory.Other)); + const long ptr = 0x0; + GetMemberValueDelegate getMemberValue = (v, m) => (m == "pfn") ? GetFunctionPointerField(v, m) : null; + var runtime = new DkmClrRuntimeInstance(ReflectionUtilities.GetMscorlibAndSystemCore(assembly), getMemberValue: getMemberValue); + using (runtime.Load()) + { + var type = runtime.GetType("C"); + var value = CreateDkmClrValue(type.Instantiate(ptr), type); + var evalResult = FormatResult("o", value); + Verify(evalResult, + EvalResult("o", "{C}", "C", "o", DkmEvaluationResultFlags.Expandable, DkmEvaluationResultCategory.Other)); + var children = GetChildren(evalResult); + Verify(children, + EvalResult("pfn", PointerToString(new IntPtr(ptr)), "int*", "o.pfn", DkmEvaluationResultFlags.None, DkmEvaluationResultCategory.Other)); + } } } + private DkmClrValue GetFunctionPointerField(DkmClrValue value, string fieldName) + { + var valueType = value.Type.GetLmrType(); + var fieldInfo = valueType.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); + var fieldValue = fieldInfo.GetValue(value.RawValue); + return CreateDkmClrValue(DkmClrValue.UnboxPointer(fieldValue), new DkmClrType(FunctionPointerType.Instance)); + } + // Function pointer type has IsPointer == true and GetElementType() == null. private sealed class FunctionPointerType : TypeImpl { diff --git a/src/ExpressionEvaluator/Core/Test/ResultProvider/Debugger/Engine/DkmClrValue.cs b/src/ExpressionEvaluator/Core/Test/ResultProvider/Debugger/Engine/DkmClrValue.cs index 3290a7db209..7c0f4919c23 100644 --- a/src/ExpressionEvaluator/Core/Test/ResultProvider/Debugger/Engine/DkmClrValue.cs +++ b/src/ExpressionEvaluator/Core/Test/ResultProvider/Debugger/Engine/DkmClrValue.cs @@ -501,17 +501,7 @@ public DkmClrValue GetMemberValue(string MemberName, int MemberType, string Pare Type type; if (value is System.Reflection.Pointer) { - unsafe - { - if (Environment.Is64BitProcess) - { - value = (long)System.Reflection.Pointer.Unbox(value); - } - else - { - value = (int)System.Reflection.Pointer.Unbox(value); - } - } + value = UnboxPointer(value); type = declaredType; } else if (value == null || declaredType.IsNullable()) @@ -535,6 +525,21 @@ public DkmClrValue GetMemberValue(string MemberName, int MemberType, string Pare access: access); } + internal static unsafe object UnboxPointer(object value) + { + unsafe + { + if (Environment.Is64BitProcess) + { + return (long)System.Reflection.Pointer.Unbox(value); + } + else + { + return (int)System.Reflection.Pointer.Unbox(value); + } + } + } + public DkmClrValue GetArrayElement(int[] indices, DkmInspectionContext inspectionContext) { if (inspectionContext == null) -- GitLab