|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable disable
extern alias PDB;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Collections.ObjectModel;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Reflection.PortableExecutable;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading;
using Microsoft.Cci;
using Microsoft.CodeAnalysis.CodeGen;
using Microsoft.CodeAnalysis.Emit;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Symbols;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.DiaSymReader;
using Microsoft.Metadata.Tools;
using Microsoft.VisualStudio.Debugger.Evaluation;
using Microsoft.VisualStudio.Debugger.Evaluation.ClrCompilation;
using Roslyn.Test.Utilities;
using Xunit;
using PDB::Roslyn.Test.Utilities;
using PDB::Roslyn.Test.PdbUtilities;
namespace Microsoft.CodeAnalysis.ExpressionEvaluator.UnitTests
{
internal sealed class Scope
{
internal readonly int StartOffset;
internal readonly int EndOffset;
internal readonly ImmutableArray<string> Locals;
internal Scope(int startOffset, int endOffset, ImmutableArray<string> locals, bool isEndInclusive)
{
this.StartOffset = startOffset;
this.EndOffset = endOffset + (isEndInclusive ? 1 : 0);
this.Locals = locals;
}
internal int Length
{
get { return this.EndOffset - this.StartOffset + 1; }
}
internal bool Contains(int offset)
{
return (offset >= this.StartOffset) && (offset < this.EndOffset);
}
}
internal static class ExpressionCompilerTestHelpers
{
internal static CompileResult CompileAssignment(
this EvaluationContextBase context,
string target,
string expr,
out string error,
CompilationTestData testData = null,
DiagnosticFormatter formatter = null)
{
ResultProperties resultProperties;
ImmutableArray<AssemblyIdentity> missingAssemblyIdentities;
var result = context.CompileAssignment(
target,
expr,
ImmutableArray<Alias>.Empty,
formatter ?? DebuggerDiagnosticFormatter.Instance,
out resultProperties,
out error,
out missingAssemblyIdentities,
EnsureEnglishUICulture.PreferredOrNull,
testData);
Assert.Empty(missingAssemblyIdentities);
// This is a crude way to test the language, but it's convenient to share this test helper.
var isCSharp = context.GetType().Namespace.IndexOf("csharp", StringComparison.OrdinalIgnoreCase) >= 0;
var expectedFlags = error != null
? DkmClrCompilationResultFlags.None
: isCSharp
? DkmClrCompilationResultFlags.PotentialSideEffect
: DkmClrCompilationResultFlags.PotentialSideEffect | DkmClrCompilationResultFlags.ReadOnlyResult;
Assert.Equal(expectedFlags, resultProperties.Flags);
Assert.Equal(default(DkmEvaluationResultCategory), resultProperties.Category);
Assert.Equal(default(DkmEvaluationResultAccessType), resultProperties.AccessType);
Assert.Equal(default(DkmEvaluationResultStorageType), resultProperties.StorageType);
Assert.Equal(default(DkmEvaluationResultTypeModifierFlags), resultProperties.ModifierFlags);
return result;
}
internal static CompileResult CompileAssignment(
this EvaluationContextBase context,
string target,
string expr,
ImmutableArray<Alias> aliases,
DiagnosticFormatter formatter,
out ResultProperties resultProperties,
out string error,
out ImmutableArray<AssemblyIdentity> missingAssemblyIdentities,
CultureInfo preferredUICulture,
CompilationTestData testData)
{
var diagnostics = DiagnosticBag.GetInstance();
var result = context.CompileAssignment(target, expr, aliases, diagnostics, out resultProperties, testData);
if (diagnostics.HasAnyErrors())
{
bool useReferencedModulesOnly;
error = context.GetErrorMessageAndMissingAssemblyIdentities(diagnostics, formatter, preferredUICulture, EvaluationContextBase.SystemCoreIdentity, out useReferencedModulesOnly, out missingAssemblyIdentities);
}
else
{
error = null;
missingAssemblyIdentities = ImmutableArray<AssemblyIdentity>.Empty;
}
diagnostics.Free();
return result;
}
internal static ReadOnlyCollection<byte> CompileGetLocals(
this EvaluationContextBase context,
ArrayBuilder<LocalAndMethod> locals,
bool argumentsOnly,
out string typeName,
CompilationTestData testData,
DiagnosticDescription[] expectedDiagnostics = null)
{
var diagnostics = DiagnosticBag.GetInstance();
var result = context.CompileGetLocals(
locals,
argumentsOnly,
ImmutableArray<Alias>.Empty,
diagnostics,
out typeName,
testData);
diagnostics.Verify(expectedDiagnostics ?? DiagnosticDescription.None);
diagnostics.Free();
return result;
}
internal static CompileResult CompileExpression(
this EvaluationContextBase context,
string expr,
out string error,
CompilationTestData testData = null,
DiagnosticFormatter formatter = null)
{
ResultProperties resultProperties;
return CompileExpression(context, expr, out resultProperties, out error, testData, formatter);
}
internal static CompileResult CompileExpression(
this EvaluationContextBase context,
string expr,
out ResultProperties resultProperties,
out string error,
CompilationTestData testData = null,
DiagnosticFormatter formatter = null)
{
ImmutableArray<AssemblyIdentity> missingAssemblyIdentities;
var result = context.CompileExpression(
expr,
DkmEvaluationFlags.TreatAsExpression,
ImmutableArray<Alias>.Empty,
formatter ?? DebuggerDiagnosticFormatter.Instance,
out resultProperties,
out error,
out missingAssemblyIdentities,
EnsureEnglishUICulture.PreferredOrNull,
testData);
Assert.Empty(missingAssemblyIdentities);
return result;
}
internal static CompileResult CompileExpression(
this EvaluationContextBase evaluationContext,
string expr,
DkmEvaluationFlags compilationFlags,
ImmutableArray<Alias> aliases,
out string error,
CompilationTestData testData = null,
DiagnosticFormatter formatter = null)
{
ResultProperties resultProperties;
ImmutableArray<AssemblyIdentity> missingAssemblyIdentities;
var result = evaluationContext.CompileExpression(
expr,
compilationFlags,
aliases,
formatter ?? DebuggerDiagnosticFormatter.Instance,
out resultProperties,
out error,
out missingAssemblyIdentities,
EnsureEnglishUICulture.PreferredOrNull,
testData);
Assert.Empty(missingAssemblyIdentities);
return result;
}
/// <summary>
/// Compile C# expression and emit assembly with evaluation method.
/// </summary>
/// <returns>
/// Result containing generated assembly, type and method names, and any format specifiers.
/// </returns>
internal static CompileResult CompileExpression(
this EvaluationContextBase evaluationContext,
string expr,
DkmEvaluationFlags compilationFlags,
ImmutableArray<Alias> aliases,
DiagnosticFormatter formatter,
out ResultProperties resultProperties,
out string error,
out ImmutableArray<AssemblyIdentity> missingAssemblyIdentities,
CultureInfo preferredUICulture,
CompilationTestData testData)
{
var diagnostics = DiagnosticBag.GetInstance();
var result = evaluationContext.CompileExpression(expr, compilationFlags, aliases, diagnostics, out resultProperties, testData);
if (diagnostics.HasAnyErrors())
{
bool useReferencedModulesOnly;
error = evaluationContext.GetErrorMessageAndMissingAssemblyIdentities(diagnostics, formatter, preferredUICulture, EvaluationContextBase.SystemCoreIdentity, out useReferencedModulesOnly, out missingAssemblyIdentities);
}
else
{
error = null;
missingAssemblyIdentities = ImmutableArray<AssemblyIdentity>.Empty;
}
diagnostics.Free();
return result;
}
internal static CompileResult CompileExpressionWithRetry(
ImmutableArray<MetadataBlock> metadataBlocks,
EvaluationContextBase context,
ExpressionCompiler.CompileDelegate<CompileResult> compile,
DkmUtilities.GetMetadataBytesPtrFunction getMetaDataBytesPtr,
out string errorMessage)
{
return ExpressionCompiler.CompileWithRetry(
metadataBlocks,
DebuggerDiagnosticFormatter.Instance,
(blocks, useReferencedModulesOnly) => context,
compile,
getMetaDataBytesPtr,
out errorMessage);
}
internal static CompileResult CompileExpressionWithRetry(
ImmutableArray<MetadataBlock> metadataBlocks,
string expr,
ImmutableArray<Alias> aliases,
ExpressionCompiler.CreateContextDelegate createContext,
DkmUtilities.GetMetadataBytesPtrFunction getMetaDataBytesPtr,
out string errorMessage,
out CompilationTestData testData)
{
var r = ExpressionCompiler.CompileWithRetry(
metadataBlocks,
DebuggerDiagnosticFormatter.Instance,
createContext,
(context, diagnostics) =>
{
var td = new CompilationTestData();
ResultProperties resultProperties;
var compileResult = context.CompileExpression(
expr,
DkmEvaluationFlags.TreatAsExpression,
aliases,
diagnostics,
out resultProperties,
td);
return new CompileExpressionResult(compileResult, td);
},
getMetaDataBytesPtr,
out errorMessage);
testData = r.TestData;
return r.CompileResult;
}
private readonly struct CompileExpressionResult
{
internal readonly CompileResult CompileResult;
internal readonly CompilationTestData TestData;
internal CompileExpressionResult(CompileResult compileResult, CompilationTestData testData)
{
this.CompileResult = compileResult;
this.TestData = testData;
}
}
internal static TypeDefinition GetTypeDef(this MetadataReader reader, string typeName)
{
return reader.TypeDefinitions.Select(reader.GetTypeDefinition).First(t => reader.StringComparer.Equals(t.Name, typeName));
}
internal static MethodDefinition GetMethodDef(this MetadataReader reader, TypeDefinition typeDef, string methodName)
{
return typeDef.GetMethods().Select(reader.GetMethodDefinition).First(m => reader.StringComparer.Equals(m.Name, methodName));
}
internal static MethodDefinitionHandle GetMethodDefHandle(this MetadataReader reader, TypeDefinition typeDef, string methodName)
{
return typeDef.GetMethods().First(h => reader.StringComparer.Equals(reader.GetMethodDefinition(h).Name, methodName));
}
internal static void CheckTypeParameters(this MetadataReader reader, GenericParameterHandleCollection genericParameters, params string[] expectedNames)
{
var actualNames = genericParameters.Select(reader.GetGenericParameter).Select(tp => reader.GetString(tp.Name)).ToArray();
Assert.True(expectedNames.SequenceEqual(actualNames));
}
internal static AssemblyName GetAssemblyName(this byte[] exeBytes)
{
using (var reader = new PEReader(ImmutableArray.CreateRange(exeBytes)))
{
var metadataReader = reader.GetMetadataReader();
var def = metadataReader.GetAssemblyDefinition();
var name = metadataReader.GetString(def.Name);
return new AssemblyName() { Name = name, Version = def.Version };
}
}
internal static Guid GetModuleVersionId(this byte[] exeBytes)
{
using (var reader = new PEReader(ImmutableArray.CreateRange(exeBytes)))
{
return reader.GetMetadataReader().GetModuleVersionId();
}
}
internal static ImmutableArray<string> GetLocalNames(this ISymUnmanagedReader symReader, int methodToken, int methodVersion = 1)
{
var method = symReader.GetMethodByVersion(methodToken, methodVersion);
if (method == null)
{
return ImmutableArray<string>.Empty;
}
var scopes = ArrayBuilder<ISymUnmanagedScope>.GetInstance();
method.GetAllScopes(scopes);
var names = ArrayBuilder<string>.GetInstance();
foreach (var scope in scopes)
{
foreach (var local in scope.GetLocals())
{
var name = local.GetName();
int slot;
local.GetAddressField1(out slot);
while (names.Count <= slot)
{
names.Add(null);
}
names[slot] = name;
}
}
scopes.Free();
return names.ToImmutableAndFree();
}
internal static void VerifyIL(
this byte[] assembly,
int methodToken,
string qualifiedName,
string expectedIL,
[CallerLineNumber] int expectedValueSourceLine = 0,
[CallerFilePath] string expectedValueSourcePath = null)
{
var parts = qualifiedName.Split('.');
if (parts.Length != 2)
{
throw new NotImplementedException();
}
using (var metadata = ModuleMetadata.CreateFromImage(assembly))
{
var module = metadata.Module;
var reader = module.MetadataReader;
var methodHandle = (MethodDefinitionHandle)MetadataTokens.Handle(methodToken);
var methodDef = reader.GetMethodDefinition(methodHandle);
var typeDef = reader.GetTypeDefinition(methodDef.GetDeclaringType());
Assert.True(reader.StringComparer.Equals(typeDef.Name, parts[0]));
Assert.True(reader.StringComparer.Equals(methodDef.Name, parts[1]));
var methodBody = module.GetMethodBodyOrThrow(methodHandle);
var pooled = PooledStringBuilder.GetInstance();
var builder = pooled.Builder;
if (!methodBody.LocalSignature.IsNil)
{
var visualizer = new MetadataVisualizer(reader, new StringWriter(), MetadataVisualizerOptions.NoHeapReferences);
var signature = reader.GetStandaloneSignature(methodBody.LocalSignature);
builder.AppendFormat("Locals: {0}", visualizer.StandaloneSignature(signature.Signature));
builder.AppendLine();
}
ILVisualizer.Default.DumpMethod(
builder,
methodBody.MaxStack,
methodBody.GetILContent(),
ImmutableArray.Create<ILVisualizer.LocalInfo>(),
ImmutableArray.Create<ILVisualizer.HandlerSpan>());
var actualIL = pooled.ToStringAndFree();
AssertEx.AssertEqualToleratingWhitespaceDifferences(expectedIL, actualIL, escapeQuotes: true, expectedValueSourcePath: expectedValueSourcePath, expectedValueSourceLine: expectedValueSourceLine);
}
}
internal static ImmutableArray<MetadataReference> GetEmittedReferences(Compilation compilation, MetadataReader mdReader)
{
// Determine the set of references that were actually used
// and ignore any references that were dropped in emit.
var referenceNames = new HashSet<string>(mdReader.AssemblyReferences.Select(h => GetAssemblyReferenceName(mdReader, h)));
return ImmutableArray.CreateRange(compilation.References.Where(r => IsReferenced(r, referenceNames)));
}
internal static ImmutableArray<Scope> GetScopes(this ISymUnmanagedReader symReader, int methodToken, int methodVersion, bool isEndInclusive)
{
var method = symReader.GetMethodByVersion(methodToken, methodVersion);
if (method == null)
{
return ImmutableArray<Scope>.Empty;
}
var scopes = ArrayBuilder<ISymUnmanagedScope>.GetInstance();
method.GetAllScopes(scopes);
var result = scopes.SelectAsArray(s => new Scope(s.GetStartOffset(), s.GetEndOffset(), ImmutableArray.CreateRange(s.GetLocals().Select(l => l.GetName())), isEndInclusive));
scopes.Free();
return result;
}
internal static Scope GetInnermostScope(this ImmutableArray<Scope> scopes, int offset)
{
Scope result = null;
foreach (var scope in scopes)
{
if (scope.Contains(offset))
{
if ((result == null) || (result.Length > scope.Length))
{
result = scope;
}
}
}
return result;
}
private static string GetAssemblyReferenceName(MetadataReader reader, AssemblyReferenceHandle handle)
{
var reference = reader.GetAssemblyReference(handle);
return reader.GetString(reference.Name);
}
private static bool IsReferenced(MetadataReference reference, HashSet<string> referenceNames)
{
var assemblyMetadata = ((PortableExecutableReference)reference).GetMetadataNoCopy() as AssemblyMetadata;
if (assemblyMetadata == null)
{
// Netmodule. Assume it is referenced.
return true;
}
var name = assemblyMetadata.GetAssembly().Identity.Name;
return referenceNames.Contains(name);
}
internal static ModuleInstance ToModuleInstance(this MetadataReference reference)
{
return ModuleInstance.Create((PortableExecutableReference)reference);
}
internal static ModuleInstance ToModuleInstance(
this Compilation compilation,
DebugInformationFormat debugFormat = DebugInformationFormat.Pdb,
bool includeLocalSignatures = true)
{
var pdbStream = (debugFormat != 0) ? new MemoryStream() : null;
var peImage = compilation.EmitToArray(new EmitOptions(debugInformationFormat: debugFormat), pdbStream: pdbStream);
var symReader = (debugFormat != 0) ? SymReaderFactory.CreateReader(pdbStream, new PEReader(peImage)) : null;
return ModuleInstance.Create(peImage, symReader, includeLocalSignatures);
}
internal static ModuleInstance GetModuleInstanceForIL(string ilSource)
{
ImmutableArray<byte> peBytes;
ImmutableArray<byte> pdbBytes;
CommonTestBase.EmitILToArray(ilSource, appendDefaultHeader: true, includePdb: true, assemblyBytes: out peBytes, pdbBytes: out pdbBytes);
return ModuleInstance.Create(peBytes, SymReaderFactory.CreateReader(pdbBytes), includeLocalSignatures: true);
}
internal static void VerifyLocal<TMethodSymbol>(
this CompilationTestData testData,
string typeName,
LocalAndMethod localAndMethod,
string expectedMethodName,
string expectedLocalName,
string expectedLocalDisplayName,
DkmClrCompilationResultFlags expectedFlags,
Action<TMethodSymbol> verifyTypeParameters,
string expectedILOpt,
bool expectedGeneric,
string expectedValueSourcePath,
int expectedValueSourceLine)
where TMethodSymbol : IMethodSymbolInternal
{
Assert.Equal(expectedLocalName, localAndMethod.LocalName);
Assert.Equal(expectedLocalDisplayName, localAndMethod.LocalDisplayName);
Assert.True(expectedMethodName.StartsWith(localAndMethod.MethodName, StringComparison.Ordinal), expectedMethodName + " does not start with " + localAndMethod.MethodName); // Expected name may include type arguments and parameters.
Assert.Equal(expectedFlags, localAndMethod.Flags);
var methodData = testData.GetMethodData(typeName + "." + expectedMethodName);
verifyTypeParameters((TMethodSymbol)methodData.Method);
if (expectedILOpt != null)
{
string actualIL = methodData.GetMethodIL();
AssertEx.AssertEqualToleratingWhitespaceDifferences(
expectedILOpt,
actualIL,
escapeQuotes: true,
expectedValueSourcePath: expectedValueSourcePath,
expectedValueSourceLine: expectedValueSourceLine);
}
Assert.Equal(((Cci.IMethodDefinition)methodData.Method.GetCciAdapter()).CallingConvention, expectedGeneric ? Cci.CallingConvention.Generic : Cci.CallingConvention.Default);
}
internal static void VerifyResolutionRequests(EEMetadataReferenceResolver resolver, (AssemblyIdentity, AssemblyIdentity, int)[] expectedRequests)
{
#if DEBUG
var expected = ArrayBuilder<(AssemblyIdentity, AssemblyIdentity, int)>.GetInstance();
var actual = ArrayBuilder<(AssemblyIdentity, AssemblyIdentity, int)>.GetInstance();
expected.AddRange(expectedRequests);
sort(expected);
actual.AddRange(resolver.Requests.Select(pair => (pair.Key, pair.Value.Identity, pair.Value.Count)));
sort(actual);
AssertEx.Equal(expected, actual);
actual.Free();
expected.Free();
void sort(ArrayBuilder<(AssemblyIdentity, AssemblyIdentity, int)> builder)
{
builder.Sort((x, y) => AssemblyIdentityComparer.SimpleNameComparer.Compare(x.Item1.GetDisplayName(), y.Item1.GetDisplayName()));
}
#endif
}
internal static void VerifyAppDomainMetadataContext<TAssemblyContext>(MetadataContext<TAssemblyContext> metadataContext, Guid[] moduleVersionIds)
where TAssemblyContext : struct
{
var actualIds = metadataContext.AssemblyContexts.Keys.Select(key => key.ModuleVersionId.ToString()).ToArray();
Array.Sort(actualIds);
var expectedIds = moduleVersionIds.Select(mvid => mvid.ToString()).ToArray();
Array.Sort(expectedIds);
AssertEx.Equal(expectedIds, actualIds);
}
internal static ISymUnmanagedReader ConstructSymReaderWithImports(ImmutableArray<byte> peImage, string methodName, params string[] importStrings)
{
using (var peReader = new PEReader(peImage))
{
var metadataReader = peReader.GetMetadataReader();
var methodHandle = metadataReader.MethodDefinitions.Single(h => metadataReader.StringComparer.Equals(metadataReader.GetMethodDefinition(h).Name, methodName));
var methodToken = metadataReader.GetToken(methodHandle);
return new MockSymUnmanagedReader(new Dictionary<int, MethodDebugInfoBytes>
{
{ methodToken, new MethodDebugInfoBytes.Builder(new [] { importStrings }).Build() },
}.ToImmutableDictionary());
}
}
internal const uint NoILOffset = 0xffffffff;
internal static readonly MetadataReference IntrinsicAssemblyReference = GetIntrinsicAssemblyReference();
internal static ImmutableArray<MetadataReference> AddIntrinsicAssembly(this ImmutableArray<MetadataReference> references)
{
var builder = ArrayBuilder<MetadataReference>.GetInstance();
builder.AddRange(references);
builder.Add(IntrinsicAssemblyReference);
return builder.ToImmutableAndFree();
}
private static MetadataReference GetIntrinsicAssemblyReference()
{
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, valuetype [mscorlib]System.Guid customTypeInfoPayloadTypeId, uint8[] customTypeInfoPayload)
{
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);
}
/// <summary>
/// Return MetadataReferences to the .winmd assemblies
/// for the given namespaces.
/// </summary>
internal static ImmutableArray<MetadataReference> GetRuntimeWinMds(params string[] namespaces)
{
var paths = new HashSet<string>();
foreach (var @namespace in namespaces)
{
foreach (var path in WindowsRuntimeMetadata.ResolveNamespace(@namespace, null))
{
paths.Add(path);
}
}
return ImmutableArray.CreateRange(paths.Select(GetAssembly));
}
private const string Version1_3CLRString = "WindowsRuntime 1.3;CLR v4.0.30319";
private const string Version1_3String = "WindowsRuntime 1.3";
private const string Version1_4String = "WindowsRuntime 1.4";
private static readonly int s_versionStringLength = Version1_3CLRString.Length;
private static readonly byte[] s_version1_3CLRBytes = ToByteArray(Version1_3CLRString, s_versionStringLength);
private static readonly byte[] s_version1_3Bytes = ToByteArray(Version1_3String, s_versionStringLength);
private static readonly byte[] s_version1_4Bytes = ToByteArray(Version1_4String, s_versionStringLength);
private static byte[] ToByteArray(string str, int length)
{
var bytes = new byte[length];
for (int i = 0; i < str.Length; i++)
{
bytes[i] = (byte)str[i];
}
return bytes;
}
internal static byte[] ToVersion1_3(byte[] bytes)
{
return ToVersion(bytes, s_version1_3CLRBytes, s_version1_3Bytes);
}
internal static byte[] ToVersion1_4(byte[] bytes)
{
return ToVersion(bytes, s_version1_3CLRBytes, s_version1_4Bytes);
}
private static byte[] ToVersion(byte[] bytes, byte[] from, byte[] to)
{
int n = bytes.Length;
var copy = new byte[n];
Array.Copy(bytes, copy, n);
int index = IndexOf(copy, from);
Array.Copy(to, 0, copy, index, to.Length);
return copy;
}
private static int IndexOf(byte[] a, byte[] b)
{
int m = b.Length;
int n = a.Length - m;
for (int x = 0; x < n; x++)
{
var matches = true;
for (int y = 0; y < m; y++)
{
if (a[x + y] != b[y])
{
matches = false;
break;
}
}
if (matches)
{
return x;
}
}
return -1;
}
private static MetadataReference GetAssembly(string path)
{
var bytes = File.ReadAllBytes(path);
var metadata = ModuleMetadata.CreateFromImage(bytes);
return metadata.GetReference(filePath: path);
}
internal static uint GetOffset(int methodToken, ISymUnmanagedReader symReader, int atLineNumber = -1)
{
int ilOffset;
if (symReader == null)
{
ilOffset = 0;
}
else
{
var symMethod = symReader.GetMethod(methodToken);
if (symMethod == null)
{
ilOffset = 0;
}
else
{
var sequencePoints = symMethod.GetSequencePoints();
ilOffset = atLineNumber < 0
? sequencePoints.Where(sp => sp.StartLine != Cci.SequencePoint.HiddenLine).Select(sp => sp.Offset).FirstOrDefault()
: sequencePoints.First(sp => sp.StartLine == atLineNumber).Offset;
}
}
Assert.InRange(ilOffset, 0, int.MaxValue);
return (uint)ilOffset;
}
internal static string GetMethodOrTypeSignatureParts(string signature, out string[] parameterTypeNames)
{
var parameterListStart = signature.IndexOf('(');
if (parameterListStart < 0)
{
parameterTypeNames = null;
return signature;
}
var parameters = signature.Substring(parameterListStart + 1, signature.Length - parameterListStart - 2);
var methodName = signature.Substring(0, parameterListStart);
parameterTypeNames = (parameters.Length == 0)
? new string[0]
: parameters.Split(',');
return methodName;
}
internal static unsafe ModuleMetadata ToModuleMetadata(this PEMemoryBlock metadata, bool ignoreAssemblyRefs)
{
return ModuleMetadata.CreateFromMetadata(
(IntPtr)metadata.Pointer,
metadata.Length,
includeEmbeddedInteropTypes: false,
ignoreAssemblyRefs: ignoreAssemblyRefs);
}
internal static unsafe MetadataReader ToMetadataReader(this PEMemoryBlock metadata)
{
return new MetadataReader(metadata.Pointer, metadata.Length, MetadataReaderOptions.None);
}
internal static void EmitCorLibWithAssemblyReferences(
Compilation comp,
string pdbPath,
Func<CommonPEModuleBuilder, EmitOptions, CommonPEModuleBuilder> getModuleBuilder,
out ImmutableArray<byte> peBytes,
out ImmutableArray<byte> pdbBytes)
{
var diagnostics = DiagnosticBag.GetInstance();
var emitOptions = EmitOptions.Default.WithRuntimeMetadataVersion("0.0.0.0").WithDebugInformationFormat(DebugInformationFormat.PortablePdb);
var moduleBuilder = comp.CheckOptionsAndCreateModuleBuilder(
diagnostics,
null,
emitOptions,
null,
null,
null,
null,
default(CancellationToken));
// Wrap the module builder in a module builder that
// reports the "System.Object" type as having no base type.
moduleBuilder = getModuleBuilder(moduleBuilder, emitOptions);
bool result = comp.Compile(
moduleBuilder,
emittingPdb: pdbPath != null,
diagnostics: diagnostics,
filterOpt: null,
cancellationToken: default(CancellationToken));
using (var peStream = new MemoryStream())
{
using (var pdbStream = new MemoryStream())
{
PeWriter.WritePeToStream(
new EmitContext(moduleBuilder, null, diagnostics, metadataOnly: false, includePrivateMembers: true),
comp.MessageProvider,
() => peStream,
() => pdbStream,
nativePdbWriterOpt: null,
pdbPathOpt: null,
metadataOnly: true,
isDeterministic: false,
emitTestCoverageData: false,
privateKeyOpt: null,
cancellationToken: default(CancellationToken));
peBytes = peStream.ToImmutable();
pdbBytes = pdbStream.ToImmutable();
}
}
diagnostics.Verify();
diagnostics.Free();
}
}
}
|