Пример #1
0
        private static string GetFirstSourceFileInPDB(string binaryPath)
        {
            try
            {
                using (PdbSymbolProvider provider = PdbSymbolProvider.TryBuildProvider(binaryPath))
                {
                    if (provider != null)
                    {
                        string firstDocumentUrl = provider.FirstDocumentUrl();

                        if (firstDocumentUrl.StartsWith("http", StringComparison.OrdinalIgnoreCase))
                        {
                            firstDocumentUrl = provider.CacheLocation(firstDocumentUrl);
                        }

                        return(firstDocumentUrl);
                    }
                }
            }
            catch (ArgumentException)
            {
                // ... Couldn't load PDB - different platform target?
            }

            return(null);
        }
Пример #2
0
        public void Walk(string binaryPath, MutableSymbol parent)
        {
            if (!FileIO.IsManagedBinary(binaryPath))
            {
                throw new ArgumentException(String.Format("SrmCrawler doesn't know how to walk file with extension '{0}'", Path.GetExtension(binaryPath)));
            }

            FileStream stream = new FileStream(binaryPath, FileMode.Open, FileAccess.Read);

            // NOTE: Need to keep PEReader alive through crawl to avoid AV in looking up signatures
            using (PEReader peReader = new PEReader(stream))
            {
                if (peReader.HasMetadata == false)
                {
                    return;
                }

                Trace.WriteLine("\t" + binaryPath);

                using (PdbSymbolProvider pdbProvider = PdbSymbolProvider.TryBuildProvider(binaryPath))
                {
                    PDB = pdbProvider;

                    MutableSymbol assemblyRoot = parent.AddChild(new MutableSymbol(Path.GetFileName(binaryPath), SymbolType.Assembly));

                    // Walk all non-nested types. Namespaces are derived as found. Nested types will be found during crawl of containing type.
                    MetadataReader mdReader = peReader.GetMetadataReader();
                    foreach (TypeDefinitionHandle typeHandle in mdReader.TypeDefinitions)
                    {
                        TypeDefinition type            = mdReader.GetTypeDefinition(typeHandle);
                        string         namespaceString = mdReader.GetString(type.Namespace);

                        if (!type.Attributes.IsNested())
                        {
                            MutableSymbol ns = assemblyRoot.FindOrAddPath(namespaceString, '.', SymbolType.Namespace);
                            WalkType(mdReader, typeHandle, ns);
                        }
                    }
                }
            }
        }
Пример #3
0
        public static PdbSymbolProvider TryBuildProvider(string binaryFilePath)
        {
            string pdbFilePath = Path.ChangeExtension(binaryFilePath, ".pdb");

            // If there's no PDB next to the binary, look in the symbol cache
            if (!File.Exists(pdbFilePath))
            {
                if (String.IsNullOrEmpty(SymbolCache.Path))
                {
                    return(null);
                }

                RsDsSignature signature = Assembly.ReadRsDsSignature(binaryFilePath);
                if (signature == null)
                {
                    Trace.WriteLine(String.Format("Unable to read PDB signature from '{0}'", binaryFilePath));
                    return(null);
                }

                string pdbFileName = Path.ChangeExtension(Path.GetFileName(binaryFilePath), ".pdb");
                pdbFilePath = Path.Combine(SymbolCache.Path, pdbFileName, signature.ToString(), pdbFileName);

                // If there was no PDB in the SymbolCache either, return no provider
                if (!File.Exists(pdbFilePath))
                {
                    return(null);
                }
            }

            try
            {
                PdbSymbolProvider provider = new PdbSymbolProvider(binaryFilePath, pdbFilePath);
                return(provider);
            }
            catch (Exception ex)
            {
                Trace.WriteLine(String.Format("Unable to build PDB provider for '{0}'. Error: {1}", binaryFilePath, ex.Message));
                return(null);
            }
        }
Пример #4
0
        private void WalkBinary(string binaryPath, MutableSymbol parent, string encodedFrameworkNames)
        {
            // Add the binary as a reference to resolve symbols in it
            MetadataReference reference = MetadataReference.CreateFromFile(binaryPath);

            CSharpCompilationOptions compilationOptions = new CSharpCompilationOptions(
                outputKind: OutputKind.ConsoleApplication,
                reportSuppressedDiagnostics: false);

            compilationOptions.SetMetadataImportOptions(MetadataImportOptions.All);

            // Create an empty binary to 'host' the reference
            CSharpCompilation emptyCompilation = CSharpCompilation.Create("Empty.exe", references: new[] { reference }, options: compilationOptions);

            // Get the root of the reference specifically
            ISymbol referenceRootSymbol = emptyCompilation.GetAssemblyOrModuleSymbol(reference);

            // If this wasn't a managed assembly, don't add anything
            if (referenceRootSymbol == null)
            {
                return;
            }

            string           assemblyName    = null;
            INamespaceSymbol globalNamespace = null;

            if (referenceRootSymbol is IAssemblySymbol)
            {
                // NOTE: Use the Assembly.Identity.Name specifically as the root to allow VS to identify binaries (potentially) already referenced safely.
                assemblyName    = ((IAssemblySymbol)referenceRootSymbol).Identity.Name;
                globalNamespace = ((IAssemblySymbol)referenceRootSymbol).GlobalNamespace;
            }
            else if (referenceRootSymbol is IModuleSymbol)
            {
                assemblyName    = Path.GetFileName(binaryPath);
                globalNamespace = ((IModuleSymbol)referenceRootSymbol).GlobalNamespace;
            }
            else
            {
                // Unable to crawl if we didn't find an assembly or module
                Trace.WriteLine(String.Format("ERROR: Unable to crawl binary with root symbol type '{0}'", referenceRootSymbol.GetType().Name));
                return;
            }

            // Walk the binary
            MutableSymbol addUnderRoot = parent.AddChild(new MutableSymbol(assemblyName, SymbolType.Assembly));

            // Add the target framework [if requested and identifiable]
            if (this.IncludeFrameworkTargets)
            {
                if (!String.IsNullOrEmpty(encodedFrameworkNames))
                {
                    addUnderRoot = addUnderRoot.AddChild(new MutableSymbol(encodedFrameworkNames, SymbolType.FrameworkTarget));
                }
            }

            // PRIVATE ROSLYN: Attempt to build a PDB reader for the binary
            using (PdbSymbolProvider pdbProvider = PdbSymbolProvider.TryBuildProvider(binaryPath))
            {
                PDB = pdbProvider;

                WalkNamespace(globalNamespace, addUnderRoot);

                // Remove the PdbSymbolProvider
                PDB = null;
            }
        }