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); }
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); } } } } }
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; } }