提交 7f1a3414 编写于 作者: C Charles Stoner

EE: Use intrinsic method assembly

上级 999b647f
......@@ -355,11 +355,6 @@ public static SyntaxTree ParseWithRoundTripCheck(string text, CSharpParseOptions
CSharpCompilationOptions options = null,
bool appendDefaultHeader = true)
{
if (string.IsNullOrEmpty(ilSource))
{
return CreateCompilationWithMscorlib(source, references, options);
}
IEnumerable<MetadataReference> metadataReferences = new[] { CompileIL(ilSource, appendDefaultHeader) };
if (references != null)
{
......
......@@ -116,17 +116,18 @@ private PlaceholderLocalSymbol LookupPlaceholder(string name)
switch (kind)
{
case PseudoVariableKind.Exception:
case PseudoVariableKind.StowedException:
return new ExceptionLocalSymbol(_containingMethod, id, type);
case PseudoVariableKind.ReturnValue:
return new ReturnValueLocalSymbol(_containingMethod, id, type, index);
case PseudoVariableKind.ObjectId:
return new ObjectIdLocalSymbol(_containingMethod, type, id, isWritable: false);
case PseudoVariableKind.DeclaredLocal:
return new ObjectIdLocalSymbol(_containingMethod, type, id, isWritable: true);
default:
throw ExceptionUtilities.UnexpectedValue(kind);
case PseudoVariableKind.Exception:
return new ExceptionLocalSymbol(_containingMethod, id, type, ExpressionCompilerConstants.GetExceptionMethodName);
case PseudoVariableKind.StowedException:
return new ExceptionLocalSymbol(_containingMethod, id, type, ExpressionCompilerConstants.GetStowedExceptionMethodName);
case PseudoVariableKind.ReturnValue:
return new ReturnValueLocalSymbol(_containingMethod, id, type, index);
case PseudoVariableKind.ObjectId:
return new ObjectIdLocalSymbol(_containingMethod, type, id, isWritable: false);
case PseudoVariableKind.DeclaredLocal:
return new ObjectIdLocalSymbol(_containingMethod, type, id, isWritable: true);
default:
throw ExceptionUtilities.UnexpectedValue(kind);
}
}
}
......
......@@ -57,22 +57,11 @@ internal static BoundNode Rewrite(CSharpCompilation compilation, EENamedTypeSymb
declaredLocals.Add(local);
var voidType = compilation.GetSpecialType(SpecialType.System_Void);
var objectType = compilation.GetSpecialType(SpecialType.System_Object);
var typeType = compilation.GetWellKnownType(WellKnownType.System_Type);
var stringType = compilation.GetSpecialType(SpecialType.System_String);
// <>CreateVariable(Type type, string name)
var method = container.GetOrAddSynthesizedMethod(
ExpressionCompilerConstants.CreateVariableMethodName,
(c, n, s) => new PlaceholderMethodSymbol(
c,
s,
n,
voidType,
m => ImmutableArray.Create<ParameterSymbol>(
new SynthesizedParameterSymbol(m, typeType, ordinal: 0, refKind: RefKind.None),
new SynthesizedParameterSymbol(m, stringType, ordinal: 1, refKind: RefKind.None))));
// CreateVariable(Type type, string name)
var method = PlaceholderLocalSymbol.GetIntrinsicMethod(compilation, ExpressionCompilerConstants.CreateVariableMethodName);
var type = new BoundTypeOfOperator(syntax, new BoundTypeExpression(syntax, aliasOpt: null, type: local.Type), null, typeType);
var name = new BoundLiteral(syntax, ConstantValue.Create(local.Name), stringType);
var call = BoundCall.Synthesized(
......
......@@ -346,6 +346,7 @@ internal override bool IsInterface
internal delegate PlaceholderMethodSymbol CreateSynthesizedMethod(EENamedTypeSymbol container, string methodName, CSharpSyntaxNode syntax);
// Not thread-safe.
// TODO: Simplify for the one remaining caller.
internal PlaceholderMethodSymbol GetOrAddSynthesizedMethod(string methodName, CreateSynthesizedMethod factory)
{
#if DEBUG
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Immutable;
using System.Diagnostics;
using Microsoft.CodeAnalysis.CSharp.Symbols;
namespace Microsoft.CodeAnalysis.CSharp.ExpressionEvaluator
{
internal sealed class ExceptionLocalSymbol : PlaceholderLocalSymbol
{
internal ExceptionLocalSymbol(MethodSymbol method, string name, TypeSymbol type) :
private readonly string getExceptionMethodName;
internal ExceptionLocalSymbol(MethodSymbol method, string name, TypeSymbol type, string getExceptionMethodName) :
base(method, name, type)
{
this.getExceptionMethodName = getExceptionMethodName;
}
internal override bool IsWritable
......@@ -20,19 +21,7 @@ internal override bool IsWritable
internal override BoundExpression RewriteLocal(CSharpCompilation compilation, EENamedTypeSymbol container, CSharpSyntaxNode syntax)
{
Debug.Assert(this.Name == this.Name.ToLowerInvariant());
var method = container.GetOrAddSynthesizedMethod(
this.Name,
(c, n, s) =>
{
var returnType = compilation.GetWellKnownType(WellKnownType.System_Exception);
return new PlaceholderMethodSymbol(
c,
s,
n,
returnType,
m => ImmutableArray<ParameterSymbol>.Empty);
});
var method = GetIntrinsicMethod(compilation, this.getExceptionMethodName);
var call = BoundCall.Synthesized(syntax, receiverOpt: null, method: method);
return ConvertToLocalType(compilation, call, this.Type);
}
......
......@@ -26,18 +26,7 @@ internal override bool IsWritable
internal override BoundExpression RewriteLocal(CSharpCompilation compilation, EENamedTypeSymbol container, CSharpSyntaxNode syntax)
{
var method = container.GetOrAddSynthesizedMethod(
ExpressionCompilerConstants.GetObjectAtAddressMethodName,
(c, n, s) =>
{
var parameterType = compilation.GetSpecialType(SpecialType.System_UInt64);
return new PlaceholderMethodSymbol(
c,
s,
n,
this.Type,
m => ImmutableArray.Create<ParameterSymbol>(new SynthesizedParameterSymbol(m, parameterType, ordinal: 0, refKind: RefKind.None)));
});
var method = GetIntrinsicMethod(compilation, ExpressionCompilerConstants.GetObjectAtAddressMethodName);
var argument = new BoundLiteral(
syntax,
Microsoft.CodeAnalysis.ConstantValue.Create(_address),
......
......@@ -35,63 +35,35 @@ internal static BoundExpression RewriteLocal(CSharpCompilation compilation, EENa
private static BoundExpression RewriteLocalInternal(CSharpCompilation compilation, EENamedTypeSymbol container, CSharpSyntaxNode syntax, LocalSymbol local)
{
var parameterType = compilation.GetSpecialType(SpecialType.System_String);
var getValueMethod = container.GetOrAddSynthesizedMethod(
ExpressionCompilerConstants.GetVariableValueMethodName,
(c, n, s) =>
{
var returnType = compilation.GetSpecialType(SpecialType.System_Object);
return new PlaceholderMethodSymbol(
c,
s,
n,
returnType,
m => ImmutableArray.Create<ParameterSymbol>(new SynthesizedParameterSymbol(m, parameterType, ordinal: 0, refKind: RefKind.None)));
});
var getAddressMethod = container.GetOrAddSynthesizedMethod(
ExpressionCompilerConstants.GetVariableAddressMethodName,
(c, n, s) =>
{
return new PlaceholderMethodSymbol(
c,
s,
n,
m => ImmutableArray.Create<TypeParameterSymbol>(new SimpleTypeParameterSymbol(m, 0, "<>T")),
m => m.TypeParameters[0], // return type is <>T&
m => ImmutableArray.Create<ParameterSymbol>(new SynthesizedParameterSymbol(m, parameterType, ordinal: 0, refKind: RefKind.None)),
returnValueIsByRef: true);
});
return new BoundPseudoVariable(
syntax,
local,
new ObjectIdExpressions(compilation, getValueMethod, getAddressMethod),
new ObjectIdExpressions(compilation),
local.Type);
}
private sealed class ObjectIdExpressions : PseudoVariableExpressions
{
private readonly CSharpCompilation _compilation;
private readonly MethodSymbol _getValueMethod;
private readonly MethodSymbol _getAddressMethod;
internal ObjectIdExpressions(CSharpCompilation compilation, MethodSymbol getValueMethod, MethodSymbol getAddressMethod)
internal ObjectIdExpressions(CSharpCompilation compilation)
{
_compilation = compilation;
_getValueMethod = getValueMethod;
_getAddressMethod = getAddressMethod;
}
internal override BoundExpression GetValue(BoundPseudoVariable variable)
{
var getValueMethod = GetIntrinsicMethod(this._compilation, ExpressionCompilerConstants.GetVariableValueMethodName);
var local = variable.LocalSymbol;
var expr = InvokeGetMethod(_getValueMethod, variable.Syntax, local.Name);
var expr = InvokeGetMethod(getValueMethod, variable.Syntax, local.Name);
return ConvertToLocalType(_compilation, expr, local.Type);
}
internal override BoundExpression GetAddress(BoundPseudoVariable variable)
{
var getAddressMethod = GetIntrinsicMethod(this._compilation, ExpressionCompilerConstants.GetVariableAddressMethodName);
var local = variable.LocalSymbol;
return InvokeGetMethod(_getAddressMethod.Construct(local.Type), variable.Syntax, local.Name);
return InvokeGetMethod(getAddressMethod.Construct(local.Type), variable.Syntax, local.Name);
}
private static BoundExpression InvokeGetMethod(MethodSymbol method, CSharpSyntaxNode syntax, string name)
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.ExpressionEvaluator;
using Roslyn.Utilities;
using System.Collections.Generic;
using System.Collections.Immutable;
......@@ -102,5 +103,13 @@ internal static BoundExpression ConvertToLocalType(CSharpCompilation compilation
constantValueOpt: null,
type: type);
}
internal static MethodSymbol GetIntrinsicMethod(CSharpCompilation compilation, string methodName)
{
var type = compilation.GetTypeByMetadataName(ExpressionCompilerConstants.IntrinsicAssemblyTypeMetadataName);
var members = type.GetMembers(methodName);
Debug.Assert(members.Length == 1);
return (MethodSymbol)members[0];
}
}
}
......@@ -23,19 +23,7 @@ internal override bool IsWritable
internal override BoundExpression RewriteLocal(CSharpCompilation compilation, EENamedTypeSymbol container, CSharpSyntaxNode syntax)
{
var method = container.GetOrAddSynthesizedMethod(
ExpressionCompilerConstants.GetReturnValueMethodName,
(c, n, s) =>
{
var parameterType = compilation.GetSpecialType(SpecialType.System_Int32);
var returnType = compilation.GetSpecialType(SpecialType.System_Object);
return new PlaceholderMethodSymbol(
c,
s,
n,
returnType,
m => ImmutableArray.Create<ParameterSymbol>(new SynthesizedParameterSymbol(m, parameterType, ordinal: 0, refKind: RefKind.None)));
});
var method = GetIntrinsicMethod(compilation, ExpressionCompilerConstants.GetReturnValueMethodName);
var argument = new BoundLiteral(
syntax,
Microsoft.CodeAnalysis.ConstantValue.Create(_index),
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.CodeAnalysis.CodeGen;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.ExpressionEvaluator;
using Microsoft.CodeAnalysis.Test.Utilities;
......@@ -65,51 +64,21 @@ .maxstack 2
IL_0000: ldtoken ""int""
IL_0005: call ""System.Type System.Type.GetTypeFromHandle(System.RuntimeTypeHandle)""
IL_000a: ldstr ""z""
IL_000f: call ""void <>x.<>CreateVariable(System.Type, string)""
IL_000f: call ""void Microsoft.VisualStudio.Debugger.Clr.IntrinsicMethods.CreateVariable(System.Type, string)""
IL_0014: ldstr ""z""
IL_0019: call ""int <>x.<>GetVariableAddress<int>(string)""
IL_0019: call ""Int32 Microsoft.VisualStudio.Debugger.Clr.IntrinsicMethods.GetVariableAddress<int>(string)""
IL_001e: ldc.i4.1
IL_001f: stind.i4
IL_0020: ldtoken ""int""
IL_0025: call ""System.Type System.Type.GetTypeFromHandle(System.RuntimeTypeHandle)""
IL_002a: ldstr ""F""
IL_002f: call ""void <>x.<>CreateVariable(System.Type, string)""
IL_002f: call ""void Microsoft.VisualStudio.Debugger.Clr.IntrinsicMethods.CreateVariable(System.Type, string)""
IL_0034: ldstr ""F""
IL_0039: call ""int <>x.<>GetVariableAddress<int>(string)""
IL_0039: call ""Int32 Microsoft.VisualStudio.Debugger.Clr.IntrinsicMethods.GetVariableAddress<int>(string)""
IL_003e: ldc.i4.2
IL_003f: stind.i4
IL_0040: ret
}");
var assembly = ImmutableArray.CreateRange(result.Assembly);
assembly.VerifyIL("<>x.<>CreateVariable",
@"{
// Code size 2 (0x2)
.maxstack 8
IL_0000: ldnull
IL_0001: throw
}");
assembly.VerifyIL("<>x.<>GetVariableAddress",
@"{
// Code size 2 (0x2)
.maxstack 8
IL_0000: ldnull
IL_0001: throw
}");
// Verify <>CreateVariable is not generic and <>GetVariableAddress is.
using (var metadata = ModuleMetadata.CreateFromImage(ImmutableArray.CreateRange(assembly)))
{
var reader = metadata.MetadataReader;
var typeDef = reader.GetTypeDef("<>x");
reader.CheckTypeParameters(typeDef.GetGenericParameters());
var methodDef = reader.GetMethodDef(typeDef, "<>CreateVariable");
reader.CheckTypeParameters(methodDef.GetGenericParameters());
var method = (MethodSymbol)testData.GetMethodData("<>x.<>CreateVariable").Method;
Assert.Equal(method.CallingConvention, Cci.CallingConvention.Default);
methodDef = reader.GetMethodDef(typeDef, "<>GetVariableAddress");
reader.CheckTypeParameters(methodDef.GetGenericParameters(), "<>T");
method = (MethodSymbol)testData.GetMethodData("<>x.<>GetVariableAddress<<>T>").Method;
Assert.Equal(method.CallingConvention, Cci.CallingConvention.Generic);
}
}
[Fact]
......@@ -191,6 +160,65 @@ .maxstack 2
}");
}
[Fact]
public void Address()
{
var source =
@"class C
{
static void M()
{
}
}";
var compilation0 = CreateCompilationWithMscorlib(
source,
options: TestOptions.DebugDll,
assemblyName: ExpressionCompilerUtilities.GenerateUniqueName());
var runtime = CreateRuntimeInstance(compilation0);
var context = CreateMethodContext(
runtime,
methodName: "C.M");
ResultProperties resultProperties;
string error;
ImmutableArray<AssemblyIdentity> missingAssemblyIdentities;
var testData = new CompilationTestData();
var result = context.CompileExpression(
InspectionContextFactory.Empty.Add("c", typeof(char)),
"*(&c) = 'A'",
DkmEvaluationFlags.None,
DiagnosticFormatter.Instance,
out resultProperties,
out error,
out missingAssemblyIdentities,
EnsureEnglishUICulture.PreferredOrNull,
testData);
testData.GetMethodData("<>x.<>m0").VerifyIL(
@"{
// Code size 65 (0x41)
.maxstack 2
.locals init (object V_0, //y
bool V_1,
object V_2)
IL_0000: ldtoken ""int""
IL_0005: call ""System.Type System.Type.GetTypeFromHandle(System.RuntimeTypeHandle)""
IL_000a: ldstr ""z""
IL_000f: call ""void Microsoft.VisualStudio.Debugger.Clr.IntrinsicMethods.CreateVariable(System.Type, string)""
IL_0014: ldstr ""z""
IL_0019: call ""Int32 Microsoft.VisualStudio.Debugger.Clr.IntrinsicMethods.GetVariableAddress<int>(string)""
IL_001e: ldc.i4.1
IL_001f: stind.i4
IL_0020: ldtoken ""int""
IL_0025: call ""System.Type System.Type.GetTypeFromHandle(System.RuntimeTypeHandle)""
IL_002a: ldstr ""F""
IL_002f: call ""void Microsoft.VisualStudio.Debugger.Clr.IntrinsicMethods.CreateVariable(System.Type, string)""
IL_0034: ldstr ""F""
IL_0039: call ""Int32 Microsoft.VisualStudio.Debugger.Clr.IntrinsicMethods.GetVariableAddress<int>(string)""
IL_003e: ldc.i4.2
IL_003f: stind.i4
IL_0040: ret
}");
}
[Fact]
public void TreatAsExpression()
{
......
......@@ -43,6 +43,12 @@ public override void Dispose()
byte[] pdbBytes;
ImmutableArray<MetadataReference> references;
compilation.EmitAndGetReferences(out exeBytes, out pdbBytes, out references);
var builder = ArrayBuilder<MetadataReference>.GetInstance();
builder.AddRange(references);
builder.Add(ExpressionCompilerTestHelpers.InstrinsicAssembly);
references = builder.ToImmutableAndFree();
return CreateRuntimeInstance(
Guid.NewGuid().ToString("D"),
references,
......
......@@ -1959,52 +1959,34 @@ static void M()
var result = context.CompileExpression(
"@0x123 ?? @0xa1b2c3 ?? (object)$exception ?? @0XA1B2C3.GetHashCode()",
out error, testData);
Assert.Equal(testData.Methods.Count, 3);
var assembly = ImmutableArray.CreateRange(result.Assembly);
Assert.Equal(testData.Methods.Count, 1);
testData.GetMethodData("<>x.<>m0").VerifyIL(
@"{
// Code size 61 (0x3d)
.maxstack 2
IL_0000: ldc.i4 0x123
IL_0005: conv.i8
IL_0006: call ""object <>x.<>GetObjectAtAddress(ulong)""
IL_0006: call ""object Microsoft.VisualStudio.Debugger.Clr.IntrinsicMethods.GetObjectAtAddress(ulong)""
IL_000b: dup
IL_000c: brtrue.s IL_003c
IL_000e: pop
IL_000f: ldc.i4 0xa1b2c3
IL_0014: conv.i8
IL_0015: call ""object <>x.<>GetObjectAtAddress(ulong)""
IL_0015: call ""object Microsoft.VisualStudio.Debugger.Clr.IntrinsicMethods.GetObjectAtAddress(ulong)""
IL_001a: dup
IL_001b: brtrue.s IL_003c
IL_001d: pop
IL_001e: call ""System.Exception <>x.$exception()""
IL_001e: call ""System.Exception Microsoft.VisualStudio.Debugger.Clr.IntrinsicMethods.GetException()""
IL_0023: dup
IL_0024: brtrue.s IL_003c
IL_0026: pop
IL_0027: ldc.i4 0xa1b2c3
IL_002c: conv.i8
IL_002d: call ""object <>x.<>GetObjectAtAddress(ulong)""
IL_002d: call ""object Microsoft.VisualStudio.Debugger.Clr.IntrinsicMethods.GetObjectAtAddress(ulong)""
IL_0032: callvirt ""int object.GetHashCode()""
IL_0037: box ""int""
IL_003c: ret
}");
assembly.VerifyIL("<>x.$exception",
@"{
// Code size 2 (0x2)
.maxstack 8
IL_0000: ldnull
IL_0001: throw
}");
assembly.VerifyIL("<>x.<>GetObjectAtAddress",
@"{
// Code size 2 (0x2)
.maxstack 8
IL_0000: ldnull
IL_0001: throw
}");
testData = new CompilationTestData();
// Report overflow, even though native EE does not.
result = context.CompileExpression(
......
......@@ -4,7 +4,6 @@
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.ExpressionEvaluator;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.VisualStudio.Debugger.Evaluation.ClrCompilation;
using Roslyn.Test.Utilities;
using System;
using System.Collections.Immutable;
......
......@@ -117,35 +117,19 @@ static void M()
EnsureEnglishUICulture.PreferredOrNull,
testData);
Assert.Empty(missingAssemblyIdentities);
Assert.Equal(testData.Methods.Count, 3);
var assembly = ImmutableArray.CreateRange(result.Assembly);
Assert.Equal(testData.Methods.Count, 1);
testData.GetMethodData("<>x.<>m0").VerifyIL(
@"{
// Code size 25 (0x19)
.maxstack 2
IL_0000: call ""System.Exception <>x.$exception()""
IL_0000: call ""System.Exception Microsoft.VisualStudio.Debugger.Clr.IntrinsicMethods.GetException()""
IL_0005: castclass ""System.IO.IOException""
IL_000a: dup
IL_000b: brtrue.s IL_0018
IL_000d: pop
IL_000e: call ""System.Exception <>x.$stowedexception()""
IL_000e: call ""System.Exception Microsoft.VisualStudio.Debugger.Clr.IntrinsicMethods.GetStowedException()""
IL_0013: castclass ""System.InvalidOperationException""
IL_0018: ret
}");
assembly.VerifyIL("<>x.$exception",
@"{
// Code size 2 (0x2)
.maxstack 8
IL_0000: ldnull
IL_0001: throw
}");
assembly.VerifyIL("<>x.$stowedexception",
@"{
// Code size 2 (0x2)
.maxstack 8
IL_0000: ldnull
IL_0001: throw
}");
}
......@@ -182,29 +166,21 @@ static void M()
EnsureEnglishUICulture.PreferredOrNull,
testData);
Assert.Empty(missingAssemblyIdentities);
Assert.Equal(testData.Methods.Count, 2);
Assert.Equal(testData.Methods.Count, 1);
testData.GetMethodData("<>x.<>m0").VerifyIL(
@"{
// Code size 22 (0x16)
.maxstack 2
IL_0000: ldc.i4.0
IL_0001: call ""object <>x.<>GetReturnValue(int)""
IL_0001: call ""object Microsoft.VisualStudio.Debugger.Clr.IntrinsicMethods.GetReturnValue(int)""
IL_0006: dup
IL_0007: brtrue.s IL_0015
IL_0009: pop
IL_000a: ldc.i4.2
IL_000b: call ""object <>x.<>GetReturnValue(int)""
IL_000b: call ""object Microsoft.VisualStudio.Debugger.Clr.IntrinsicMethods.GetReturnValue(int)""
IL_0010: castclass ""string""
IL_0015: ret
}");
testData.GetMethodData("<>x.<>GetReturnValue").VerifyIL(
@"{
// Code size 2 (0x2)
.maxstack 1
IL_0000: ldnull
IL_0001: throw
}");
// Value type $ReturnValue.
testData = new CompilationTestData();
result = context.CompileExpression(
......@@ -224,7 +200,7 @@ .maxstack 1
.maxstack 1
.locals init (int? V_0)
IL_0000: ldc.i4.0
IL_0001: call ""object <>x.<>GetReturnValue(int)""
IL_0001: call ""object Microsoft.VisualStudio.Debugger.Clr.IntrinsicMethods.GetReturnValue(int)""
IL_0006: unbox.any ""int?""
IL_000b: stloc.0
IL_000c: ldloca.s V_0
......
......@@ -7,7 +7,6 @@
using System.Diagnostics;
using System.Linq;
using System.Reflection.Metadata;
using Microsoft.VisualStudio.Debugger;
using Microsoft.VisualStudio.Debugger.Clr;
using Microsoft.VisualStudio.Debugger.Evaluation;
using Microsoft.VisualStudio.Debugger.Evaluation.ClrCompilation;
......@@ -21,57 +20,67 @@ internal static class DkmUtilities
internal unsafe delegate IntPtr GetMetadataBytesPtrFunction(AssemblyIdentity assemblyIdentity, out uint uSize);
private static IEnumerable<DkmClrModuleInstance> GetModulesInAppDomain(this DkmProcess process, DkmClrAppDomain appDomain)
private static IEnumerable<DkmClrModuleInstance> GetModulesInAppDomain(this DkmClrRuntimeInstance runtime, DkmClrAppDomain appDomain)
{
var appDomainId = appDomain.Id;
return process.GetRuntimeInstances().
OfType<DkmClrRuntimeInstance>().
SelectMany(runtime => runtime.GetModuleInstances()).
return runtime.GetModuleInstances().
Cast<DkmClrModuleInstance>().
Where(module => module.AppDomain.Id == appDomainId);
}
internal unsafe static ImmutableArray<MetadataBlock> GetMetadataBlocks(this DkmProcess process, DkmClrAppDomain appDomain)
internal unsafe static ImmutableArray<MetadataBlock> GetMetadataBlocks(this DkmClrRuntimeInstance runtime, DkmClrAppDomain appDomain)
{
var builder = ArrayBuilder<MetadataBlock>.GetInstance();
foreach (DkmClrModuleInstance module in process.GetModulesInAppDomain(appDomain))
IntPtr ptr;
uint size;
foreach (DkmClrModuleInstance module in runtime.GetModulesInAppDomain(appDomain))
{
int size;
IntPtr ptr;
MetadataReader reader;
if (module.TryGetMetadataReader(out ptr, out size, out reader))
MetadataBlock block;
try
{
var moduleDef = reader.GetModuleDefinition();
var moduleVersionId = reader.GetGuid(moduleDef.Mvid);
var generationId = reader.GetGuid(moduleDef.GenerationId);
Debug.Assert(moduleVersionId == module.Mvid);
builder.Add(new MetadataBlock(moduleVersionId, generationId, ptr, size));
ptr = module.GetMetaDataBytesPtr(out size);
block = GetMetadataBlock(ptr, size);
}
catch (Exception e) when (MetadataUtilities.IsBadOrMissingMetadataException(e, module.FullName))
{
continue;
}
Debug.Assert(block.ModuleVersionId == module.Mvid);
builder.Add(block);
}
// Include "intrinsic method" assembly.
ptr = runtime.GetIntrinsicAssemblyMetaDataBytesPtr(out size);
builder.Add(GetMetadataBlock(ptr, size));
return builder.ToImmutableAndFree();
}
private static IntPtr GetIntrinsicAssemblyMetaDataBytesPtr(this DkmClrRuntimeInstance runtime, out uint size)
{
throw new NotImplementedException();
}
internal static ImmutableArray<MetadataBlock> GetMetadataBlocks(GetMetadataBytesPtrFunction getMetaDataBytesPtrFunction, ImmutableArray<AssemblyIdentity> missingAssemblyIdentities)
{
ArrayBuilder<MetadataBlock> builder = null;
foreach (AssemblyIdentity missingAssemblyIdentity in missingAssemblyIdentities)
{
int size;
IntPtr ptr;
MetadataReader reader;
if (TryGetMetadataReader(getMetaDataBytesPtrFunction, missingAssemblyIdentity, out ptr, out size, out reader))
MetadataBlock block;
try
{
var moduleDef = reader.GetModuleDefinition();
var moduleVersionId = reader.GetGuid(moduleDef.Mvid);
var generationId = reader.GetGuid(moduleDef.GenerationId);
if (builder == null)
{
builder = ArrayBuilder<MetadataBlock>.GetInstance();
}
builder.Add(new MetadataBlock(moduleVersionId, generationId, ptr, size));
uint size;
IntPtr ptr;
ptr = getMetaDataBytesPtrFunction(missingAssemblyIdentity, out size);
block = GetMetadataBlock(ptr, size);
}
catch (Exception e) when (MetadataUtilities.IsBadOrMissingMetadataException(e, missingAssemblyIdentity.GetDisplayName()))
{
continue;
}
if (builder == null)
{
builder = ArrayBuilder<MetadataBlock>.GetInstance();
}
builder.Add(block);
}
return builder == null ? ImmutableArray<MetadataBlock>.Empty : builder.ToImmutableAndFree();
}
......@@ -79,77 +88,40 @@ internal static ImmutableArray<MetadataBlock> GetMetadataBlocks(GetMetadataBytes
internal static ImmutableArray<AssemblyReaders> MakeAssemblyReaders(this DkmClrInstructionAddress instructionAddress)
{
var builder = ArrayBuilder<AssemblyReaders>.GetInstance();
foreach (DkmClrModuleInstance module in instructionAddress.Process.GetModulesInAppDomain(instructionAddress.ModuleInstance.AppDomain))
foreach (DkmClrModuleInstance module in instructionAddress.RuntimeInstance.GetModulesInAppDomain(instructionAddress.ModuleInstance.AppDomain))
{
MetadataReader metadataReader;
if (module.TryGetMetadataReader(out metadataReader))
var symReader = module.GetSymReader();
if (symReader == null)
{
continue;
}
MetadataReader reader;
unsafe
{
var symReader = module.GetSymReader();
if (symReader != null)
try
{
uint size;
IntPtr ptr;
ptr = module.GetMetaDataBytesPtr(out size);
reader = new MetadataReader((byte*)ptr, (int)size);
}
catch (Exception e) when (MetadataUtilities.IsBadOrMissingMetadataException(e, module.FullName))
{
builder.Add(new AssemblyReaders(metadataReader, symReader));
continue;
}
}
builder.Add(new AssemblyReaders(reader, symReader));
}
return builder.ToImmutableAndFree();
}
/// <summary>
/// Attempt to construct a <see cref="MetadataReader"/> instance for this module.
/// </summary>
/// <returns>Returns 'false' for modules with "bad" or missing metadata.</returns>
private static bool TryGetMetadataReader(this DkmClrModuleInstance module, out MetadataReader reader)
{
int size;
IntPtr ptr;
return module.TryGetMetadataReader(out ptr, out size, out reader);
}
/// <summary>
/// Attempt to construct a <see cref="MetadataReader"/> instance for this module.
/// </summary>
/// <returns>Returns 'false' for modules with "bad" or missing metadata.</returns>
private unsafe static bool TryGetMetadataReader(this DkmClrModuleInstance module, out IntPtr ptr, out int size, out MetadataReader reader)
{
try
{
uint uSize;
ptr = module.GetMetaDataBytesPtr(out uSize);
size = (int)uSize;
reader = new MetadataReader((byte*)ptr, size);
return true;
}
catch (Exception e) when (MetadataUtilities.IsBadOrMissingMetadataException(e, module.FullName))
{
ptr = IntPtr.Zero;
size = 0;
reader = null;
return false;
}
}
/// <summary>
/// Attempt to construct a <see cref="MetadataReader"/> instance for this module.
/// </summary>
/// <returns>Returns 'false' for modules with "bad" or missing metadata.</returns>
private unsafe static bool TryGetMetadataReader(GetMetadataBytesPtrFunction getMetaDataBytesPtrFunction, AssemblyIdentity assemblyIdentity, out IntPtr ptr, out int size, out MetadataReader reader)
private unsafe static MetadataBlock GetMetadataBlock(IntPtr ptr, uint size)
{
var assemblyName = assemblyIdentity.GetDisplayName();
try
{
uint uSize;
ptr = getMetaDataBytesPtrFunction(assemblyIdentity, out uSize);
size = (int)uSize;
reader = new MetadataReader((byte*)ptr, size);
return true;
}
catch (Exception e) when (MetadataUtilities.IsBadOrMissingMetadataException(e, assemblyName))
{
ptr = IntPtr.Zero;
size = 0;
reader = null;
return false;
}
var reader = new MetadataReader((byte*)ptr, (int)size);
var moduleDef = reader.GetModuleDefinition();
var moduleVersionId = reader.GetGuid(moduleDef.Mvid);
var generationId = reader.GetGuid(moduleDef.GenerationId);
return new MetadataBlock(moduleVersionId, generationId, ptr, (int)size);
}
internal static object GetSymReader(this DkmClrModuleInstance clrModule)
......
......@@ -32,7 +32,7 @@ static ExpressionCompiler()
{
try
{
var references = instructionAddress.Process.GetMetadataBlocks(instructionAddress.ModuleInstance.AppDomain);
var references = instructionAddress.RuntimeInstance.GetMetadataBlocks(instructionAddress.ModuleInstance.AppDomain);
var context = this.CreateMethodContext(instructionAddress, references);
var builder = ArrayBuilder<LocalAndMethod>.GetInstance();
string typeName;
......@@ -62,7 +62,7 @@ static ExpressionCompiler()
try
{
var appDomain = instructionAddress.ModuleInstance.AppDomain;
var references = instructionAddress.Process.GetMetadataBlocks(appDomain);
var references = instructionAddress.RuntimeInstance.GetMetadataBlocks(appDomain);
ImmutableArray<AssemblyIdentity> missingAssemblyIdentities;
ResultProperties resultProperties;
......@@ -100,7 +100,7 @@ static ExpressionCompiler()
try
{
var appDomain = instructionAddress.ModuleInstance.AppDomain;
var references = instructionAddress.Process.GetMetadataBlocks(appDomain);
var references = instructionAddress.RuntimeInstance.GetMetadataBlocks(appDomain);
ResultProperties resultProperties;
ImmutableArray<AssemblyIdentity> missingAssemblyIdentities;
......@@ -139,7 +139,7 @@ static ExpressionCompiler()
try
{
var appDomain = moduleInstance.AppDomain;
var references = moduleInstance.Process.GetMetadataBlocks(appDomain);
var references = moduleInstance.RuntimeInstance.GetMetadataBlocks(appDomain);
ResultProperties unusedResultProperties;
ImmutableArray<AssemblyIdentity> missingAssemblyIdentities;
......
......@@ -6,10 +6,13 @@ internal static class ExpressionCompilerConstants
{
internal const string TypeVariablesLocalName = "<>TypeVariables";
internal const string TypeVariablesClassName = "<>c__TypeVariables";
internal const string GetObjectAtAddressMethodName = "<>GetObjectAtAddress";
internal const string GetReturnValueMethodName = "<>GetReturnValue";
internal const string CreateVariableMethodName = "<>CreateVariable";
internal const string GetVariableValueMethodName = "<>GetObjectByAlias";
internal const string GetVariableAddressMethodName = "<>GetVariableAddress";
internal const string IntrinsicAssemblyTypeMetadataName = "Microsoft.VisualStudio.Debugger.Clr.IntrinsicMethods";
internal const string GetExceptionMethodName = "GetException";
internal const string GetStowedExceptionMethodName = "GetStowedException";
internal const string GetObjectAtAddressMethodName = "GetObjectAtAddress";
internal const string GetReturnValueMethodName = "GetReturnValue";
internal const string CreateVariableMethodName = "CreateVariable";
internal const string GetVariableValueMethodName = "GetVariableValue";
internal const string GetVariableAddressMethodName = "GetVariableAddress";
}
}
......@@ -51,9 +51,9 @@ internal static ImmutableArray<MetadataReference> MakeAssemblyReferences(this Im
metadataBuilder.Add(metadata);
}
}
catch (Exception e) when (MetadataUtilities.IsBadOrMissingMetadataException(e))
catch (Exception e) when (IsBadMetadataException(e))
{
// Ignore modules with "bad" or missing metadata.
// Ignore modules with "bad" metadata.
}
}
......@@ -140,9 +140,9 @@ private static PortableExecutableReference MakeAssemblyMetadata(ModuleMetadata m
}
}
}
catch (Exception e) when (MetadataUtilities.IsBadOrMissingMetadataException(e))
catch (Exception e) when (IsBadMetadataException(e))
{
// Ignore modules with "bad" or missing metadata.
// Ignore modules with "bad" metadata.
}
}
......@@ -385,23 +385,30 @@ private static ConstantValue GetConstantValue(byte[] signature, object value)
return ConstantValue.Create(value, SpecialTypeExtensions.FromRuntimeTypeOfLiteralValue(value));
}
internal static bool IsBadOrMissingMetadataException(Exception e, string moduleName = null)
private static bool IsBadMetadataException(Exception e)
{
switch (unchecked((uint)e.HResult))
return GetHResult(e) == COR_E_BADIMAGEFORMAT;
}
internal static bool IsBadOrMissingMetadataException(Exception e, string moduleName)
{
Debug.Assert(moduleName != null);
switch (GetHResult(e))
{
case COR_E_BADIMAGEFORMAT:
// Some callers may not be able to provide a module name (the name may need to be read from
// metadata, and this Exception indicates that we cannot construct a MetadataReader).
Debug.WriteLine("Module '{0}' contains corrupt metadata.", new string[] { moduleName ?? "<unspecified>" });
return true;
case CORDBG_E_MISSING_METADATA:
// All callers that pass this Exception should also have a module name available (from the DkmClrModuleInstance).
Debug.Assert(moduleName != null);
Debug.WriteLine("Module '{0}' is missing metadata.", moduleName);
return true;
default:
return false;
case COR_E_BADIMAGEFORMAT:
Debug.WriteLine("Module '{0}' contains corrupt metadata.", moduleName);
return true;
case CORDBG_E_MISSING_METADATA:
Debug.WriteLine("Module '{0}' is missing metadata.", moduleName);
return true;
default:
return false;
}
}
private static uint GetHResult(Exception e)
{
return unchecked((uint)e.HResult);
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
extern alias PDB;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
......@@ -91,19 +91,6 @@ internal static Guid GetModuleVersionId(this byte[] exeBytes)
}
}
/// <summary>
/// Helper method to write the bytes to a file.
/// </summary>
[Conditional("DEBUG")]
internal static void WriteBytes(this ImmutableArray<byte> bytes, string path = null)
{
if (path == null)
{
path = Path.Combine(Path.GetTempPath(), "__ee_temp.dll");
}
File.WriteAllBytes(path, bytes.ToArray());
}
internal static ImmutableArray<string> GetLocalNames(this ISymUnmanagedReader symReader, int methodToken, int methodVersion = 1)
{
var method = symReader.GetMethodByVersion(methodToken, methodVersion);
......@@ -348,6 +335,53 @@ internal static ISymUnmanagedReader ConstructSymReaderWithImports(byte[] exeByte
}
}
internal static readonly MetadataReference InstrinsicAssembly = GetIntrinsicAssembly();
private static MetadataReference GetIntrinsicAssembly()
{
var source =
@".assembly extern mscorlib { }
.class public Microsoft.VisualStudio.Debugger.Clr.IntrinsicMethods
{
.method public static object GetObjectAtAddress(uint64 address)
{
ldnull
throw
}
.method public static class [mscorlib]System.Exception GetException()
{
ldnull
throw
}
.method public static class [mscorlib]System.Exception GetStowedException()
{
ldnull
throw
}
.method public static object GetReturnValue(int32 index)
{
ldnull
throw
}
.method public static void CreateVariable(class [mscorlib]System.Type 'type', string name)
{
ldnull
throw
}
.method public static object GetObjectByAlias(string name)
{
ldnull
throw
}
.method public static !!T& GetVariableAddress<T>(string name)
{
ldnull
throw
}
}";
return CommonTestBase.CompileIL(source, appendDefaultHeader: true);
}
/// <summary>
/// Return MetadataReferences to the .winmd assemblies
/// for the given namespaces.
......
......@@ -33,8 +33,8 @@ End Class"
Dim missingAssemblyIdentities As ImmutableArray(Of AssemblyIdentity) = Nothing
Dim testData = New CompilationTestData()
Dim result = context.CompileExpression(
InspectionContextFactory.Empty.Add("3", GetType(Integer)),
"z = $3",
InspectionContextFactory.Empty.Add("c", GetType(Char)),
"c = ""B""c",
DkmEvaluationFlags.None,
DiagnosticFormatter.Instance,
resultProperties,
......
Imports Microsoft.CodeAnalysis.CodeGen
Imports Microsoft.CodeAnalysis.ExpressionEvaluator
Imports Microsoft.CodeAnalysis.Test.Utilities
Imports Microsoft.VisualStudio.Debugger.Evaluation.ClrCompilation
Imports Xunit
Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册