예제 #1
0
        private static TimeSpan RunCustomAssemblyLoder()
        {
            Stopwatch stopwatch = new Stopwatch();

            stopwatch.Start();
            try
            {
                using (var loader = new InteractiveAssemblyLoader())
                {
                    if (AssemblyIdentity.TryParseDisplayName("CSScriptConsole, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", out AssemblyIdentity cccassemblyid))
                    {
                        loader.RegisterDependency(cccassemblyid, Path.Combine(AppContext.BaseDirectory, "CSScriptConsole.dll"));
                    }
                    var option = ScriptOptions.Default
                                 .WithFilePath(Path.Combine(scriptrootpath, "CustomizeAssemblyLoading", "main.csx"))
                                 .WithFileEncoding(Encoding.UTF8);
                    String code   = "#load \"main.csx\"";
                    var    script = CSharpScript.Create(code, options: option, assemblyLoader: loader);
                    var    c      = script.Compile();
                    var    state  = script.RunAsync(null).Result;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"{ex.Message}{Environment.NewLine}{ex.StackTrace}");
            }
            finally
            {
                stopwatch.Stop();
            }
            return(stopwatch.Elapsed);
        }
예제 #2
0
            /// <summary>
            /// Attempts to find and load an <see cref="Assembly"/> when the requesting <see cref="Assembly"/>
            /// is unknown.
            /// </summary>
            /// <remarks>
            /// In this case we simply look next to all the assemblies we have previously loaded for one with the
            /// correct name and a matching <see cref="AssemblyIdentity"/>.
            /// </remarks>
            private static Assembly ResolveForUnknownRequestor(string requestedAssemblyName)
            {
                lock (s_guard)
                {
                    string requestedNameWithPolicyApplied = AppDomain.CurrentDomain.ApplyPolicy(requestedAssemblyName);

                    Assembly assembly;
                    if (s_assembliesFromNames.TryGetValue(requestedNameWithPolicyApplied, out assembly))
                    {
                        // We've already loaded an assembly by this name; use that.
                        return(assembly);
                    }

                    AssemblyIdentity requestedAssemblyIdentity;
                    if (!AssemblyIdentity.TryParseDisplayName(requestedNameWithPolicyApplied, out requestedAssemblyIdentity))
                    {
                        return(null);
                    }

                    foreach (string loadedAssemblyFullPath in s_assembliesFromFiles.Keys)
                    {
                        string directoryPath             = Path.GetDirectoryName(loadedAssemblyFullPath);
                        string candidateAssemblyFullPath = Path.Combine(directoryPath, requestedAssemblyIdentity.Name + ".dll");

                        AssemblyIdentity candidateAssemblyIdentity = TryGetAssemblyIdentity(candidateAssemblyFullPath);

                        if (requestedAssemblyIdentity.Equals(candidateAssemblyIdentity))
                        {
                            return(LoadCore(candidateAssemblyFullPath));
                        }
                    }

                    return(null);
                }
            }
        internal Assembly ResolveAssembly(string assemblyDisplayName, Assembly requestingAssemblyOpt)
        {
            AssemblyIdentity identity;

            if (!AssemblyIdentity.TryParseDisplayName(assemblyDisplayName, out identity))
            {
                return(null);
            }

            string loadDirectoryOpt;

            lock (_referencesLock)
            {
                LoadedAssembly loadedAssembly;
                if (requestingAssemblyOpt != null &&
                    _assembliesLoadedFromLocation.TryGetValue(requestingAssemblyOpt, out loadedAssembly))
                {
                    loadDirectoryOpt = Path.GetDirectoryName(loadedAssembly.OriginalPath);
                }
                else
                {
                    loadDirectoryOpt = null;
                }
            }

            return(ResolveAssembly(identity, loadDirectoryOpt));
        }
        private async Task <string> GetAssemblyNameFromInternalsVisibleToAttributeAsync(
            Document document,
            SyntaxNode node,
            CancellationToken cancellationToken
            )
        {
            var constructorArgument = GetConstructorArgumentOfInternalsVisibleToAttribute(node);

            if (constructorArgument == null)
            {
                return(string.Empty);
            }

            var semanticModel = await document
                                .ReuseExistingSpeculativeModelAsync(constructorArgument, cancellationToken)
                                .ConfigureAwait(false);

            var constantCandidate = semanticModel.GetConstantValue(
                constructorArgument,
                cancellationToken
                );

            if (constantCandidate.HasValue && constantCandidate.Value is string argument)
            {
                if (AssemblyIdentity.TryParseDisplayName(argument, out var assemblyIdentity))
                {
                    return(assemblyIdentity.Name);
                }
            }

            return(string.Empty);
        }
예제 #5
0
            private (Project project, ISymbol symbol) TryResolveSymbolInCurrentSolution(
                Workspace workspace, string symbolKey)
            {
                if (!this.Properties.TryGetValue(MetadataAssemblyIdentityDisplayName, out var identityDisplayName) ||
                    !AssemblyIdentity.TryParseDisplayName(identityDisplayName, out var identity))
                {
                    return(null, null);
                }

                var project = workspace.CurrentSolution
                              .ProjectsWithReferenceToAssembly(identity)
                              .FirstOrDefault();

                if (project == null)
                {
                    return(null, null);
                }

                var compilation = project.GetCompilationAsync(CancellationToken.None)
                                  .WaitAndGetResult(CancellationToken.None);

                var symbol = SymbolKey.Resolve(symbolKey, compilation).Symbol;

                return(project, symbol);
            }
예제 #6
0
        private static async Task <ISet <AssemblyIdentity> > GetUniqueIdentitiesAsync(
            CodeFixContext context
            )
        {
            var cancellationToken = context.CancellationToken;
            var compilation       = await context.Document.Project
                                    .GetCompilationAsync(cancellationToken)
                                    .ConfigureAwait(false);

            var uniqueIdentities = new HashSet <AssemblyIdentity>();

            foreach (var diagnostic in context.Diagnostics)
            {
                var assemblyIds = compilation.GetUnreferencedAssemblyIdentities(diagnostic);
                uniqueIdentities.AddRange(assemblyIds);

                var properties = diagnostic.Properties;
                if (
                    properties.TryGetValue(
                        DiagnosticPropertyConstants.UnreferencedAssemblyIdentity,
                        out var displayName
                        ) &&
                    AssemblyIdentity.TryParseDisplayName(displayName, out var serializedIdentity)
                    )
                {
                    uniqueIdentities.Add(serializedIdentity);
                }
            }

            uniqueIdentities.Remove(compilation.Assembly.Identity);
            return(uniqueIdentities);
        }
예제 #7
0
        private void TestParseDisplayName(
            string displayName,
            AssemblyIdentity expected,
            AssemblyIdentityParts expectedParts,
            AssemblyIdentity expectedFusion
            )
        {
            var fusion = FusionAssemblyIdentity.ToAssemblyIdentity(
                FusionAssemblyIdentity.ToAssemblyNameObject(displayName)
                );

            Assert.Equal(expectedFusion, fusion);

            AssemblyIdentity      id = null;
            AssemblyIdentityParts actualParts;
            bool success = AssemblyIdentity.TryParseDisplayName(
                displayName,
                out id,
                out actualParts
                );

            Assert.Equal(expected, id);
            Assert.Equal(success, id != null);
            Assert.Equal(expectedParts, actualParts);
        }
예제 #8
0
        private Assembly AssemblyResolve(object sender, ResolveEventArgs args)
        {
            AssemblyIdentity identity;

            if (!AssemblyIdentity.TryParseDisplayName(args.Name, out identity))
            {
                return(null);
            }

            if (args.RequestingAssembly != null)
            {
                string originalDllPath = null, originalExePath = null;

                string originalPath = null;
                lock (ReferencesLock)
                {
                    LoadedAssembly loadedAssembly;
                    if (_loadedAssemblies.TryGetValue(args.RequestingAssembly, out loadedAssembly))
                    {
                        originalPath = loadedAssembly.OriginalPath;

                        string pathWithoutExtension = Path.Combine(Path.GetDirectoryName(originalPath), identity.Name);
                        originalDllPath = pathWithoutExtension + ".dll";
                        originalExePath = pathWithoutExtension + ".exe";

                        Assembly assembly;
                        if (_loadedAssembliesByPath.TryGetValue(originalDllPath, out assembly) || _loadedAssembliesByPath.TryGetValue(originalExePath, out assembly))
                        {
                            return(assembly);
                        }
                    }
                }

                // if the referring assembly is already loaded by our loader, load from its directory:
                if (originalPath != null)
                {
                    // Copy & load both .dll and .exe, this is not a common scenario we would need to optimize for.
                    // Remember both loaded assemblies for the next time, even though their versions might not match the current request
                    // they might match the next one and we don't want to load them again.
                    Assembly dll = ShadowCopyAndLoadDependency(originalDllPath);
                    Assembly exe = ShadowCopyAndLoadDependency(originalExePath);

                    if (dll == null ^ exe == null)
                    {
                        return(dll ?? exe);
                    }

                    if (dll != null && exe != null)
                    {
                        // .dll and an .exe of the same name might have different versions,
                        // one of which might match the requested version.
                        // Prefer .dll if they are both the same.
                        return(FindHighestVersionOrFirstMatchingIdentity(identity, new[] { dll, exe }));
                    }
                }
            }

            return(GetOrLoadKnownAssembly(identity));
        }
 public static bool InternalsVisibleToProxyGenerator(this ISymbol typeSymbol)
 {
     return(typeSymbol.ContainingAssembly != null &&
            typeSymbol.ContainingAssembly.GetAttributes()
            .Any(att => att.AttributeClass.ToString() == MetadataNames.InternalsVisibleToAttributeFullTypeName &&
                 att.ConstructorArguments.Any(arg => arg.Value != null && AssemblyIdentity.TryParseDisplayName(arg.Value.ToString(), out var identity) &&
                                              identity.Name == MetadataNames.CastleDynamicProxyGenAssembly2Name)));
 }
예제 #10
0
        public void ValidAnalyzerReference_Id()
        {
            AnalyzerFileReference reference = CreateAnalyzerFileReference(_testFixture.Alpha.Path);

            AssemblyIdentity.TryParseDisplayName("Alpha, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", out var expectedIdentity);

            Assert.Equal(expected: expectedIdentity, actual: reference.Id);
        }
예제 #11
0
        public void AssemblyIdentity_EmptyName()
        {
            var identity = new AssemblyIdentity(noThrow: true, name: "");
            var name     = identity.GetDisplayName();

            Assert.Equal(", Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", name);
            Assert.False(AssemblyIdentity.TryParseDisplayName(name, out _));
        }
        private void TestMatch(
            string displayName1,
            string displayName2,
            AssemblyIdentityComparer.ComparisonResult match,
            AssemblyIdentityComparer.ComparisonResult?fusionMatch = null,
            bool ignoreVersion            = false,
            bool partial                  = false,
            bool unificationApplied       = false,
            bool?fusionUnificationApplied = null,
            string policyPath             = null)
        {
            if (fusionMatch == null)
            {
                fusionMatch = match;
            }

            using (var fusionPolicy = policyPath != null ? FusionAssemblyPortabilityPolicy.LoadFromFile(policyPath) : null)
            {
                var comparer = DesktopAssemblyIdentityComparer.Default;

                var policy = default(AssemblyPortabilityPolicy);
                if (policyPath != null)
                {
                    using (var policyStream = new FileStream(policyPath, FileMode.Open, FileAccess.Read))
                    {
                        policy   = AssemblyPortabilityPolicy.LoadFromXml(policyStream);
                        comparer = new DesktopAssemblyIdentityComparer(policy);
                    }
                }

                bool fusionUnificationApplied1;
                var  fusionResult1 = FusionAssemblyIdentityComparer.CompareAssemblyIdentity(displayName1, displayName2, ignoreVersion, policy: fusionPolicy, unificationApplied: out fusionUnificationApplied1);
                Assert.Equal(fusionMatch, fusionResult1);
                Assert.Equal(fusionUnificationApplied ?? unificationApplied, fusionUnificationApplied1);

                AssemblyIdentity      id1, id2;
                AssemblyIdentityParts parts1, parts2;

                Assert.True(AssemblyIdentity.TryParseDisplayName(displayName1, out id1, out parts1));
                Assert.Equal(partial, !AssemblyIdentity.IsFullName(parts1));

                Assert.True(AssemblyIdentity.TryParseDisplayName(displayName2, out id2, out parts2));
                Assert.True(AssemblyIdentity.IsFullName(parts2), "Expected full name");

                bool unificationApplied1;
                var  actual1 = comparer.Compare(null, displayName1, id2, out unificationApplied1, ignoreVersion);
                Assert.Equal(match, actual1);
                Assert.Equal(unificationApplied, unificationApplied1);

                if (!partial && id1 != null)
                {
                    bool unificationApplied2;
                    var  actual2 = comparer.Compare(id1, null, id2, out unificationApplied2, ignoreVersion);
                    Assert.Equal(match, actual2);
                    Assert.Equal(unificationApplied, unificationApplied2);
                }
            }
        }
예제 #13
0
        public static string DumpAssemblyData(IEnumerable <ModuleData> modules, out string dumpDirectory)
        {
            dumpDirectory = null;

            StringBuilder sb = new StringBuilder();

            foreach (var module in modules)
            {
                if (module.InMemoryModule)
                {
                    if (dumpDirectory == null)
                    {
                        dumpDirectory = Path.Combine(Path.GetTempPath(), "RoslynTestFailureDump", Guid.NewGuid().ToString());
                        Directory.CreateDirectory(dumpDirectory);
                    }

                    string fileName;
                    if (module.Kind == OutputKind.NetModule)
                    {
                        fileName = module.FullName;
                    }
                    else
                    {
                        AssemblyIdentity identity;
                        AssemblyIdentity.TryParseDisplayName(module.FullName, out identity);
                        fileName = identity.Name;
                    }

                    string pePath  = Path.Combine(dumpDirectory, fileName + module.Kind.GetDefaultExtension());
                    string pdbPath = (module.Pdb != null) ? pdbPath = Path.Combine(dumpDirectory, fileName + ".pdb") : null;
                    try
                    {
                        module.Image.WriteToFile(pePath);
                        if (pdbPath != null)
                        {
                            module.Pdb.WriteToFile(pdbPath);
                        }
                    }
                    catch (IOException)
                    {
                        pePath = "<unable to write file>";
                        if (pdbPath != null)
                        {
                            pdbPath = "<unable to write file>";
                        }
                    }
                    sb.Append("PE(" + module.Kind + "): ");
                    sb.AppendLine(pePath);
                    if (pdbPath != null)
                    {
                        sb.Append("PDB: ");
                        sb.AppendLine(pdbPath);
                    }
                }
            }
            return(sb.ToString());
        }
예제 #14
0
        private static void AddAssemblyIdentity(List <AssemblyIdentity> list, string dllName)
        {
            if (!AssemblyIdentity.TryParseDisplayName(dllName, out var identity))
            {
                return;
            }

            list.Add(identity);
        }
예제 #15
0
        public void ValidAnalyzerReference_Id()
        {
            var directory = Temp.CreateDirectory();
            var alphaDll  = directory.CreateFile("Alpha.dll").WriteAllBytes(TestResources.AssemblyLoadTests.Alpha);
            AnalyzerFileReference reference = CreateAnalyzerFileReference(alphaDll.Path);

            AssemblyIdentity.TryParseDisplayName("Alpha, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", out var expectedIdentity);

            Assert.Equal(expected: expectedIdentity, actual: reference.Id);
        }
예제 #16
0
        private Assembly AssemblyResolve(string assemblyDisplayName, Assembly requestingAssemblyOpt)
        {
            AssemblyIdentity identity;

            if (!AssemblyIdentity.TryParseDisplayName(assemblyDisplayName, out identity))
            {
                return(null);
            }

            return(AssemblyResolve(identity, requestingAssemblyOpt));
        }
예제 #17
0
            public AssemblyIdentity ApplyBindingRedirects(AssemblyIdentity originalIdentity)
            {
                var redirectedAssemblyName = AppDomain.CurrentDomain.ApplyPolicy(originalIdentity.ToString());

                if (AssemblyIdentity.TryParseDisplayName(redirectedAssemblyName, out var redirectedAssemblyIdentity))
                {
                    return(redirectedAssemblyIdentity);
                }

                return(originalIdentity);
            }
        private void TestParseSimpleName(string displayName, string expected, string expectedFusion)
        {
            var fusionName = FusionAssemblyIdentity.ToAssemblyNameObject(displayName);
            var actual     = (fusionName != null) ? FusionAssemblyIdentity.GetName(fusionName) : null;

            Assert.Equal(expectedFusion, actual);

            AssemblyIdentity id;

            actual = AssemblyIdentity.TryParseDisplayName(displayName, out id) ? id.Name : null;
            Assert.Equal(expected, actual);
        }
        private void TestParseVersion(string value)
        {
            string displayName = "Foo, Version=" + value;
            var    fusion      = FusionAssemblyIdentity.ToAssemblyIdentity(FusionAssemblyIdentity.ToAssemblyNameObject(displayName));

            AssemblyIdentity id      = null;
            bool             success = AssemblyIdentity.TryParseDisplayName(displayName, out id);

            Assert.Equal(fusion != null, success);

            if (success)
            {
                Assert.Equal(fusion.Version, id.Version);
            }
        }
        public void TryParseDisplayName()
        {
            string V = "\\u" + ((int)'V').ToString("X4") + ";";

            TestParseDisplayName("  \"fo'o\"  , " + V + "ersion=1.0.0.0\t, \rCulture=zz-ZZ\n, PublicKeyToken=" + StrPublicKeyToken1,
                                 new AssemblyIdentity("fo'o", new Version(1, 0, 0, 0), "zz-ZZ", RoPublicKeyToken1, hasPublicKey: false, isRetargetable: false, contentType: AssemblyContentType.Default),
                                 NVCT);

            // invalid:
            AssemblyIdentity id;

            Assert.Throws <ArgumentNullException>(() => AssemblyIdentity.TryParseDisplayName(null, out id));

            TestParseDisplayName("", null);
            TestParseDisplayName("fo=o, Culture=neutral, Version=1.0.0.0", null);
            TestParseDisplayName("foo, Culture=neutral, Version,1.0.0.0", null);

            // custom properties:
            TestParseDisplayName("foo, A=B",
                                 new AssemblyIdentity("foo"), N | AssemblyIdentityParts.Unknown);

            // we don't allow CT=WinRT + Retargetable, fusion does.
            Assert.False(
                AssemblyIdentity.TryParseDisplayName("foo, Version=1.0.0.0, Culture=en-US, Retargetable=Yes, ContentType=WindowsRuntime, PublicKeyToken=" + StrPublicKeyToken1, out id));

            // order
            TestParseDisplayName("foo, Culture=neutral, Version=1.0.0.0",
                                 new AssemblyIdentity("foo", new Version(1, 0, 0, 0)), NVC);

            TestParseDisplayName("foo, Version=1.0.0.0, Culture=en-US, Retargetable=Yes, PublicKeyToken=" + StrPublicKeyToken1,
                                 new AssemblyIdentity("foo", new Version(1, 0, 0, 0), "en-US", RoPublicKeyToken1, hasPublicKey: false, isRetargetable: true),
                                 NVCT | AssemblyIdentityParts.Retargetability);

            TestParseDisplayName("foo, PublicKey=" + StrPublicKey1 + ", Version=1.0.0.1",
                                 new AssemblyIdentity("foo", new Version(1, 0, 0, 1), publicKeyOrToken: RoPublicKey1, hasPublicKey: true),
                                 NVK);

            TestParseDisplayName(@"Foo, Version=0.0.0.0, Culture=""  \'\t\r\n\\\=\,  "", PublicKeyToken=null",
                                 new AssemblyIdentity("Foo", cultureName: "  '\t\r\n\\=,  "),
                                 NVCT);

            // duplicates
            TestParseDisplayName("foo, Version=1.0.0.0, Version=1.0.0.0", null);
            TestParseDisplayName("foo, Version=1.0.0.0, Version=2.0.0.0", null);
            TestParseDisplayName("foo, Culture=neutral, Version=1.0.0.0, Culture=en-US", null);
        }
            /// <summary>
            /// Handles the <see cref="AppDomain.AssemblyResolve"/> event when the requesting
            /// assembly is one that we've loaded.
            ///
            /// We assume that an assembly's dependencies can be found next to it in the file
            /// system.
            /// </summary>
            private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
            {
                if (args.RequestingAssembly == null)
                {
                    // We don't know who is requesting the load; don't try to satisfy the request.
                    return(null);
                }

                lock (s_guard)
                {
                    string requestingAssemblyName = args.RequestingAssembly.FullName;

                    string requestingAssemblyFullPath;
                    if (!s_filesFromAssemblyNames.TryGetValue(requestingAssemblyName, out requestingAssemblyFullPath))
                    {
                        // The requesting assembly is not one of ours; don't try to satisfy the request.
                        return(null);
                    }

                    string nameWithPolicyApplied = AppDomain.CurrentDomain.ApplyPolicy(args.Name);

                    Assembly assembly;
                    if (s_assembliesFromNames.TryGetValue(nameWithPolicyApplied, out assembly))
                    {
                        // We've already loaded an assembly by this name; use that.
                        return(assembly);
                    }

                    AssemblyIdentity assemblyIdentity;
                    if (!AssemblyIdentity.TryParseDisplayName(nameWithPolicyApplied, out assemblyIdentity))
                    {
                        return(null);
                    }

                    string directoryPath    = Path.GetDirectoryName(requestingAssemblyFullPath);
                    string assemblyFullPath = Path.Combine(directoryPath, assemblyIdentity.Name + ".dll");

                    assembly = LoadCore(assemblyFullPath);

                    s_requestingFilesFromFiles[assemblyFullPath] = requestingAssemblyFullPath;

                    return(assembly);
                }
            }
예제 #22
0
            /// <summary>
            /// Attempts to find and load an <see cref="Assembly"/> when the requesting <see cref="Assembly"/>
            /// is known.
            /// </summary>
            /// <remarks>
            /// This method differs from <see cref="ResolveForUnknownRequestor(string)"/> in a couple of ways.
            /// First, we only attempt to handle the load if the requesting assembly is one we've loaded.
            /// If it isn't one of ours, then presumably some other component is hooking <see cref="AppDomain.AssemblyResolve"/>
            /// and will have a better idea of how to load the assembly.
            /// Second, we only look immediately next to the requesting assembly, instead of next to all the assemblies
            /// we've previously loaded. An analyzer needs to ship with all of its dependencies, and if it doesn't we don't
            /// want to mask the problem.
            /// </remarks>
            private static Assembly ResolveForKnownRequestor(string requestedAssemblyName, Assembly requestingAssembly)
            {
                lock (s_guard)
                {
                    string requestingAssemblyName = requestingAssembly.FullName;

                    string requestingAssemblyFullPath;
                    if (!s_filesFromAssemblyNames.TryGetValue(requestingAssemblyName, out requestingAssemblyFullPath))
                    {
                        // The requesting assembly is not one of ours; don't try to satisfy the request.
                        return(null);
                    }

                    string nameWithPolicyApplied = AppDomain.CurrentDomain.ApplyPolicy(requestedAssemblyName);

                    Assembly assembly;
                    if (s_assembliesFromNames.TryGetValue(nameWithPolicyApplied, out assembly))
                    {
                        // We've already loaded an assembly by this name; use that.
                        return(assembly);
                    }

                    AssemblyIdentity assemblyIdentity;
                    if (!AssemblyIdentity.TryParseDisplayName(nameWithPolicyApplied, out assemblyIdentity))
                    {
                        return(null);
                    }

                    string directoryPath    = Path.GetDirectoryName(requestingAssemblyFullPath);
                    string assemblyFullPath = Path.Combine(directoryPath, assemblyIdentity.Name + ".dll");
                    if (!File.Exists(assemblyFullPath))
                    {
                        return(null);
                    }

                    assembly = LoadCore(assemblyFullPath);

                    s_requestingFilesFromFiles[assemblyFullPath] = requestingAssemblyFullPath;

                    return(assembly);
                }
            }
예제 #23
0
        public Assembly Load(string displayName)
        {
            if (!AssemblyIdentity.TryParseDisplayName(displayName, out var requestedIdentity))
            {
                return(null);
            }

            ImmutableArray <string> candidatePaths;

            lock (_guard)
            {
                // First, check if this loader already loaded the requested assembly:
                if (_loadedAssembliesByIdentity.TryGetValue(requestedIdentity, out var existingAssembly))
                {
                    return(existingAssembly);
                }
                // Second, check if an assembly file of the same simple name was registered with the loader:
                if (!_knownAssemblyPathsBySimpleName.TryGetValue(requestedIdentity.Name, out var pathList))
                {
                    return(null);
                }

                Debug.Assert(pathList.Count > 0);
                candidatePaths = pathList.ToImmutableArray();
            }

            // Multiple assemblies of the same simple name but different identities might have been registered.
            // Load the one that matches the requested identity (if any).
            foreach (var candidatePath in candidatePaths)
            {
                var candidateIdentity = GetOrAddAssemblyIdentity(candidatePath);

                if (requestedIdentity.Equals(candidateIdentity))
                {
                    return(LoadFromPathUncheckedCore(candidatePath, candidateIdentity));
                }
            }

            return(null);
        }
        private static ImmutableDictionary <IAssemblySymbol, ImmutableSortedSet <string> > GetRestrictedInternalsVisibleToMap(Compilation compilation)
        {
            var restrictedInternalsVisibleToAttribute = compilation.GetTypeByMetadataName("System.Runtime.CompilerServices.RestrictedInternalsVisibleToAttribute");

            if (restrictedInternalsVisibleToAttribute == null)
            {
                return(ImmutableDictionary <IAssemblySymbol, ImmutableSortedSet <string> > .Empty);
            }

            var builder = ImmutableDictionary.CreateBuilder <IAssemblySymbol, ImmutableSortedSet <string> >();

            foreach (var referencedAssemblySymbol in compilation.References.Select(compilation.GetAssemblyOrModuleSymbol).OfType <IAssemblySymbol>())
            {
                // Check IVT
                if (!referencedAssemblySymbol.GivesAccessTo(compilation.Assembly))
                {
                    continue;
                }

                var namespaceNameComparer = compilation.IsCaseSensitive ? StringComparer.Ordinal : StringComparer.OrdinalIgnoreCase;
                var namespaceBuilder      = ImmutableSortedSet.CreateBuilder(namespaceNameComparer);
                foreach (var assemblyAttribute in referencedAssemblySymbol.GetAttributes())
                {
                    // Look for ctor: "RestrictedInternalsVisibleToAttribute(string assemblyName, params string[] namespaces)"
                    if (!Equals(assemblyAttribute.AttributeClass, restrictedInternalsVisibleToAttribute) ||
                        assemblyAttribute.AttributeConstructor.Parameters.Length != 2 ||
                        assemblyAttribute.AttributeConstructor.Parameters[0].Type.SpecialType != SpecialType.System_String ||
                        !(assemblyAttribute.AttributeConstructor.Parameters[1].Type is IArrayTypeSymbol arrayType) ||
                        arrayType.Rank != 1 ||
                        arrayType.ElementType.SpecialType != SpecialType.System_String ||
                        !assemblyAttribute.AttributeConstructor.Parameters[1].IsParams)
                    {
                        continue;
                    }

                    // Ensure the Restricted IVT is for the current compilation's assembly.
                    if (assemblyAttribute.ConstructorArguments.Length != 2 ||
                        assemblyAttribute.ConstructorArguments[0].Kind != TypedConstantKind.Primitive ||
                        !(assemblyAttribute.ConstructorArguments[0].Value is string assemblyName) ||
                        !AssemblyIdentity.TryParseDisplayName(assemblyName, out var assemblyIdentity) ||
                        AssemblyIdentityComparer.Default.Compare(assemblyIdentity, compilation.Assembly.Identity) == AssemblyIdentityComparer.ComparisonResult.NotEquivalent)
                    {
                        continue;
                    }

                    // Ensure second constructor argument is string array.
                    if (assemblyAttribute.ConstructorArguments[1].Kind != TypedConstantKind.Array ||
                        !(assemblyAttribute.ConstructorArguments[1].Values is var namespaceConstants))
                    {
                        continue;
                    }

                    // Add namespaces specified in the second constructor argument.
                    foreach (TypedConstant namespaceConstant in namespaceConstants)
                    {
                        if (namespaceConstant.Kind == TypedConstantKind.Primitive &&
                            namespaceConstant.Value is string namespaceName)
                        {
                            namespaceBuilder.Add(namespaceName);
                        }
                    }
                }

                if (namespaceBuilder.Count > 0)
                {
                    builder.Add(referencedAssemblySymbol, namespaceBuilder.ToImmutable());
                }
            }

            return(builder.ToImmutable());
        }
예제 #25
0
        public static MethodDebugInfo GetMethodDebugInfo(
            this ISymUnmanagedReader reader,
            int methodToken,
            int methodVersion,
            ArrayBuilder <ISymUnmanagedScope> scopes)
        {
            ImmutableArray <string> externAliasStrings;
            var importStringGroups = reader.GetCSharpGroupedImportStrings(methodToken, methodVersion, out externAliasStrings);

            Debug.Assert(importStringGroups.IsDefault == externAliasStrings.IsDefault);

            ArrayBuilder <ImmutableArray <ImportRecord> > importRecordGroupBuilder = null;
            ArrayBuilder <ExternAliasRecord> externAliasRecordBuilder = null;

            if (!importStringGroups.IsDefault)
            {
                importRecordGroupBuilder = ArrayBuilder <ImmutableArray <ImportRecord> > .GetInstance(importStringGroups.Length);

                foreach (var importStringGroup in importStringGroups)
                {
                    var groupBuilder = ArrayBuilder <ImportRecord> .GetInstance(importStringGroup.Length);

                    foreach (var importString in importStringGroup)
                    {
                        ImportRecord record;
                        if (NativeImportRecord.TryCreateFromCSharpImportString(importString, out record))
                        {
                            groupBuilder.Add(record);
                        }
                        else
                        {
                            Debug.WriteLine($"Failed to parse import string {importString}");
                        }
                    }
                    importRecordGroupBuilder.Add(groupBuilder.ToImmutableAndFree());
                }

                if (!externAliasStrings.IsDefault)
                {
                    externAliasRecordBuilder = ArrayBuilder <ExternAliasRecord> .GetInstance(externAliasStrings.Length);

                    foreach (string externAliasString in externAliasStrings)
                    {
                        string           alias;
                        string           externAlias;
                        string           target;
                        ImportTargetKind kind;
                        if (!CustomDebugInfoReader.TryParseCSharpImportString(externAliasString, out alias, out externAlias, out target, out kind))
                        {
                            Debug.WriteLine($"Unable to parse extern alias '{externAliasString}'");
                            continue;
                        }

                        Debug.Assert(kind == ImportTargetKind.Assembly, "Programmer error: How did a non-assembly get in the extern alias list?");
                        Debug.Assert(alias != null);       // Name of the extern alias.
                        Debug.Assert(externAlias == null); // Not used.
                        Debug.Assert(target != null);      // Name of the target assembly.

                        AssemblyIdentity targetIdentity;
                        if (!AssemblyIdentity.TryParseDisplayName(target, out targetIdentity))
                        {
                            Debug.WriteLine($"Unable to parse target of extern alias '{externAliasString}'");
                            continue;
                        }

                        externAliasRecordBuilder.Add(new NativeExternAliasRecord <AssemblySymbol>(alias, targetIdentity));
                    }
                }
            }

            var hoistedLocalScopeRecords = ImmutableArray <HoistedLocalScopeRecord> .Empty;
            var dynamicLocalMap          = ImmutableDictionary <int, ImmutableArray <bool> > .Empty;
            var dynamicLocalConstantMap  = ImmutableDictionary <string, ImmutableArray <bool> > .Empty;

            byte[] customDebugInfoBytes = reader.GetCustomDebugInfoBytes(methodToken, methodVersion);

            if (customDebugInfoBytes != null)
            {
                var customDebugInfoRecord = CustomDebugInfoReader.TryGetCustomDebugInfoRecord(customDebugInfoBytes, CustomDebugInfoKind.StateMachineHoistedLocalScopes);
                if (!customDebugInfoRecord.IsDefault)
                {
                    hoistedLocalScopeRecords = CustomDebugInfoReader.DecodeStateMachineHoistedLocalScopesRecord(customDebugInfoRecord)
                                               .SelectAsArray(s => HoistedLocalScopeRecord.FromNative(s.StartOffset, s.EndOffset));
                }

                CustomDebugInfoReader.GetCSharpDynamicLocalInfo(
                    customDebugInfoBytes,
                    methodToken,
                    methodVersion,
                    scopes,
                    out dynamicLocalMap,
                    out dynamicLocalConstantMap);
            }

            return(new MethodDebugInfo(
                       hoistedLocalScopeRecords,
                       importRecordGroupBuilder?.ToImmutableAndFree() ?? ImmutableArray <ImmutableArray <ImportRecord> > .Empty,
                       externAliasRecordBuilder?.ToImmutableAndFree() ?? ImmutableArray <ExternAliasRecord> .Empty,
                       dynamicLocalMap,
                       dynamicLocalConstantMap,
                       defaultNamespaceName: "")); // Unused in C#.
        }
예제 #26
0
        public static MethodDebugInfo GetMethodDebugInfo(
            this ISymUnmanagedReader reader,
            int methodToken,
            int methodVersion)
        {
            ImmutableArray <string> externAliasStrings;
            var importStringGroups = reader.GetCSharpGroupedImportStrings(methodToken, methodVersion, out externAliasStrings);

            Debug.Assert(importStringGroups.IsDefault == externAliasStrings.IsDefault);

            if (importStringGroups.IsDefault)
            {
                return(default(MethodDebugInfo));
            }

            var importRecordGroupBuilder = ArrayBuilder <ImmutableArray <ImportRecord> > .GetInstance(importStringGroups.Length);

            foreach (var importStringGroup in importStringGroups)
            {
                var groupBuilder = ArrayBuilder <ImportRecord> .GetInstance(importStringGroup.Length);

                foreach (var importString in importStringGroup)
                {
                    ImportRecord record;
                    if (NativeImportRecord.TryCreateFromCSharpImportString(importString, out record))
                    {
                        groupBuilder.Add(record);
                    }
                    else
                    {
                        Debug.WriteLine($"Failed to parse import string {importString}");
                    }
                }
                importRecordGroupBuilder.Add(groupBuilder.ToImmutableAndFree());
            }

            var externAliasRecordBuilder = ArrayBuilder <ExternAliasRecord> .GetInstance(externAliasStrings.Length);

            foreach (string externAliasString in externAliasStrings)
            {
                string           alias;
                string           externAlias;
                string           target;
                ImportTargetKind kind;
                if (!CustomDebugInfoReader.TryParseCSharpImportString(externAliasString, out alias, out externAlias, out target, out kind))
                {
                    Debug.WriteLine($"Unable to parse extern alias '{externAliasString}'");
                    continue;
                }

                Debug.Assert(kind == ImportTargetKind.Assembly, "Programmer error: How did a non-assembly get in the extern alias list?");
                Debug.Assert(alias != null);       // Name of the extern alias.
                Debug.Assert(externAlias == null); // Not used.
                Debug.Assert(target != null);      // Name of the target assembly.

                AssemblyIdentity targetIdentity;
                if (!AssemblyIdentity.TryParseDisplayName(target, out targetIdentity))
                {
                    Debug.WriteLine($"Unable to parse target of extern alias '{externAliasString}'");
                    continue;
                }

                externAliasRecordBuilder.Add(new NativeExternAliasRecord <AssemblySymbol>(alias, targetIdentity));
            }

            return(new MethodDebugInfo(
                       importRecordGroupBuilder.ToImmutableAndFree(),
                       externAliasRecordBuilder.ToImmutableAndFree(),
                       defaultNamespaceName: "")); // Unused in C#.
        }
예제 #27
0
        public static string DumpAssemblyData(IEnumerable <ModuleData> modules, out string dumpDirectory)
        {
            dumpDirectory = null;

            StringBuilder sb = new StringBuilder();

            foreach (var module in modules)
            {
                // Limit the number of dumps to 10.  After 10 we're likely in a bad state and are
                // dumping lots of unnecessary data.
                if (s_dumpCount > 10)
                {
                    break;
                }

                if (module.InMemoryModule)
                {
                    Interlocked.Increment(ref s_dumpCount);

                    if (dumpDirectory == null)
                    {
                        dumpDirectory = Path.GetTempPath();
                        try
                        {
                            Directory.CreateDirectory(dumpDirectory);
                        }
                        catch
                        {
                            // Okay if directory already exists
                        }
                    }

                    string fileName;
                    if (module.Kind == OutputKind.NetModule)
                    {
                        fileName = module.FullName;
                    }
                    else
                    {
                        AssemblyIdentity.TryParseDisplayName(module.FullName, out var identity);
                        fileName = identity.Name;
                    }

                    string pePath  = Path.Combine(dumpDirectory, fileName + module.Kind.GetDefaultExtension());
                    string pdbPath = (module.Pdb != null) ? pdbPath = Path.Combine(dumpDirectory, fileName + ".pdb") : null;
                    try
                    {
                        module.Image.WriteToFile(pePath);
                        if (pdbPath != null)
                        {
                            module.Pdb.WriteToFile(pdbPath);
                        }
                    }
                    catch (IOException)
                    {
                        pePath = "<unable to write file>";
                        if (pdbPath != null)
                        {
                            pdbPath = "<unable to write file>";
                        }
                    }
                    sb.Append("PE(" + module.Kind + "): ");
                    sb.AppendLine(pePath);
                    if (pdbPath != null)
                    {
                        sb.Append("PDB: ");
                        sb.AppendLine(pdbPath);
                    }
                }
            }
            return(sb.ToString());
        }
예제 #28
0
        private static List <RazorEngineAssembly> GetRazorCustomizationAssemblies(Compilation compilation)
        {
            // The goal here is to find the set of assemblies + paths that have some kind of
            // Razor extensibility.
            //
            // We do that by making a compilation and then looking through the set of assembly names
            // (AssemblyIdentity) and references to dlls on disk (PortableExecutableReference) to find
            // uses of RazorEngineCustomizationAttribute and RazorEngineDependencyAttribute.
            //
            // We're limited to supporting files on disk because we will need to shadow copy them
            // and manually load them.
            //
            // Also note that we're not doing anything here to explicitly uniquify this list, since
            // we're limiting the set of candidates to the set of assemblies used for compilation, which
            // has already been processed by Roslyn.
            var results = new List <RazorEngineAssembly>();

            // The RazorEngineDependencyAttribute also allows specifying an assembly name to go along
            // with a piece of extensibility. We'll collect these on the first pass through the assemblies
            // and then look those up by name.
            var unresolvedIdentities = new List <AssemblyIdentity>();

            foreach (var reference in compilation.References)
            {
                var peReference = reference as PortableExecutableReference;
                if (peReference == null || peReference.FilePath == null)
                {
                    // No path, can't load it.
                    continue;
                }

                var assemblySymbol = compilation.GetAssemblyOrModuleSymbol(reference) as IAssemblySymbol;
                if (assemblySymbol == null)
                {
                    // It's unlikely, but possible that a reference might be a module instead of an assembly.
                    // We can't load that, so just skip it.
                    continue;
                }

                var identity = assemblySymbol.Identity;
                if (identity.Name == RazorAssemblyName)
                {
                    // This is the main Razor assembly.
                    results.Add(new RazorEngineAssembly(identity, peReference.FilePath));
                }

                // Now we're looking for the Razor exensibility attributes.
                var attributes = assemblySymbol.GetAttributes();
                for (var i = 0; i < attributes.Length; i++)
                {
                    var attribute = attributes[i];
                    var name      = attribute.AttributeClass.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
                    if (string.Equals(
                            CustomizationAttribute,
                            name,
                            StringComparison.Ordinal))
                    {
                        results.Add(new RazorEngineAssembly(identity, peReference.FilePath));
                    }

                    if (string.Equals(
                            DependencyAttribute,
                            name,
                            StringComparison.Ordinal))
                    {
                        // This attribute refers to a separate assembly for which we will need to resolve a path.
                        //
                        // Ignore parsing failures here.
                        AssemblyIdentity dependency;
                        if (AssemblyIdentity.TryParseDisplayName((string)attribute.ConstructorArguments[0].Value, out dependency))
                        {
                            unresolvedIdentities.Add(dependency);
                        }
                    }
                }
            }

            // Now we need to do another pass to resolve all the unresolved names.
            if (unresolvedIdentities.Count > 0)
            {
                //while (identities.MoveNext() && references.MoveNext())
                //{
                //    var peReference = references.Current as PortableExecutableReference;
                //    if (peReference == null || peReference.FilePath == null)
                //    {
                //        // No path, can't load it.
                //        continue;
                //    }

                //    var assemblySymbol = compilation.GetAssemblyOrModuleSymbol(peReference) as IAssemblySymbol;
                //    if (assemblySymbol == null)
                //    {
                //        // It's unlikely, but possible that a reference might be a module instead of an assembly.
                //        // We can't load that, so just skip it.
                //        continue;
                //    }

                //    for (var i = 0; i < unresolvedIdentities.Count; i++)
                //    {
                //        // Note: argument ordering here is significant. We expect that the attribute will often refer to a
                //        // partial name and omit details like the version and public-key, therefore the value from the
                //        // attribute must be the first argument.
                //        if (AssemblyIdentityComparer.Default.ReferenceMatchesDefinition(
                //            unresolvedIdentities[i],
                //            identities.Current))
                //        {
                //            results.Add(new RazorEngineAssembly(identities.Current, peReference.FilePath));
                //            break;
                //        }
                //    }
                //}
            }

            return(results);
        }
        private static void ReadCSharpNativeImportsInfo(
            ISymUnmanagedReader3 reader,
            EESymbolProvider <TTypeSymbol, TLocalSymbol> symbolProvider,
            int methodToken,
            int methodVersion,
            out ImmutableArray <ImmutableArray <ImportRecord> > importRecordGroups,
            out ImmutableArray <ExternAliasRecord> externAliasRecords)
        {
            ImmutableArray <string> externAliasStrings;

            var importStringGroups = CustomDebugInfoReader.GetCSharpGroupedImportStrings(
                methodToken,
                KeyValuePair.Create(reader, methodVersion),
                getMethodCustomDebugInfo: (token, arg) => GetCustomDebugInfoBytes(arg.Key, token, arg.Value),
                getMethodImportStrings: (token, arg) => GetImportStrings(arg.Key, token, arg.Value),
                externAliasStrings: out externAliasStrings);

            Debug.Assert(importStringGroups.IsDefault == externAliasStrings.IsDefault);

            ArrayBuilder <ImmutableArray <ImportRecord> > importRecordGroupBuilder = null;
            ArrayBuilder <ExternAliasRecord> externAliasRecordBuilder = null;

            if (!importStringGroups.IsDefault)
            {
                importRecordGroupBuilder = ArrayBuilder <ImmutableArray <ImportRecord> > .GetInstance(importStringGroups.Length);

                foreach (var importStringGroup in importStringGroups)
                {
                    var groupBuilder = ArrayBuilder <ImportRecord> .GetInstance(importStringGroup.Length);

                    foreach (var importString in importStringGroup)
                    {
                        ImportRecord record;
                        if (TryCreateImportRecordFromCSharpImportString(symbolProvider, importString, out record))
                        {
                            groupBuilder.Add(record);
                        }
                        else
                        {
                            Debug.WriteLine($"Failed to parse import string {importString}");
                        }
                    }
                    importRecordGroupBuilder.Add(groupBuilder.ToImmutableAndFree());
                }

                if (!externAliasStrings.IsDefault)
                {
                    externAliasRecordBuilder = ArrayBuilder <ExternAliasRecord> .GetInstance(externAliasStrings.Length);

                    foreach (string externAliasString in externAliasStrings)
                    {
                        string           alias;
                        string           externAlias;
                        string           target;
                        ImportTargetKind kind;
                        if (!CustomDebugInfoReader.TryParseCSharpImportString(externAliasString, out alias, out externAlias, out target, out kind))
                        {
                            Debug.WriteLine($"Unable to parse extern alias '{externAliasString}'");
                            continue;
                        }

                        Debug.Assert(kind == ImportTargetKind.Assembly, "Programmer error: How did a non-assembly get in the extern alias list?");
                        Debug.Assert(alias != null);       // Name of the extern alias.
                        Debug.Assert(externAlias == null); // Not used.
                        Debug.Assert(target != null);      // Name of the target assembly.

                        AssemblyIdentity targetIdentity;
                        if (!AssemblyIdentity.TryParseDisplayName(target, out targetIdentity))
                        {
                            Debug.WriteLine($"Unable to parse target of extern alias '{externAliasString}'");
                            continue;
                        }

                        externAliasRecordBuilder.Add(new ExternAliasRecord(alias, targetIdentity));
                    }
                }
            }

            importRecordGroups = importRecordGroupBuilder?.ToImmutableAndFree() ?? ImmutableArray <ImmutableArray <ImportRecord> > .Empty;
            externAliasRecords = externAliasRecordBuilder?.ToImmutableAndFree() ?? ImmutableArray <ExternAliasRecord> .Empty;
        }
예제 #30
0
        private static string GetReferenceString(Reference reference)
        {
            if (!reference.StrongName)
            {
                return(reference.Path);
            }

            string name = reference.Name;

            if (name == "mscorlib")
            {
                // mscorlib is always loaded
                return(null);
            }

            // TODO: This shouldn't directly depend on GAC, rather we should have some kind of "reference simplifier".
            var possibleGacNames = GlobalAssemblyCache.GetAssemblyIdentities(name).ToArray();

            if (possibleGacNames.Length == 0)
            {
                // no assembly with simple "name" found in GAC, use path to identify the reference:
                return(reference.Path);
            }

            string version        = reference.Version;
            string culture        = reference.Culture;
            string publicKeyToken = reference.PublicKeyToken;

            var fullName = string.Concat(
                name,
                ", Version=",
                version,
                ", Culture=",
                (culture == "") ? "neutral" : culture,
                ", PublicKeyToken=",
                publicKeyToken.ToLowerInvariant());

            AssemblyIdentity identity;

            if (!AssemblyIdentity.TryParseDisplayName(fullName, out identity))
            {
                // ignore invalid names:
                return(null);
            }

            var foundEquivalent    = false;
            var foundNonEquivalent = false;

            foreach (var possibleGacName in possibleGacNames)
            {
                if (DesktopAssemblyIdentityComparer.Default.ReferenceMatchesDefinition(identity, possibleGacName))
                {
                    foundEquivalent = true;
                }
                else
                {
                    foundNonEquivalent = true;
                }

                if (foundEquivalent && foundNonEquivalent)
                {
                    break;
                }
            }

            if (!foundEquivalent)
            {
                // The reference name isn't equivalent to any GAC name.
                // The assembly is strong named but not GAC'd, so we need to load it from path:
                return(reference.Path);
            }

            if (foundNonEquivalent)
            {
                // We found some equivalent assemblies but also some non-equivalent.
                // So simple name doesn't identify the reference uniquely.
                return(fullName);
            }

            // We found a single simple name match that is equivalent to the given reference.
            // We can use the simple name to load the GAC'd assembly.
            return(name);
        }