/// <summary> /// Read the pdb file name and assembly version information from the PE file. /// </summary> /// <param name="assemblyPath">PE file path</param> /// <param name="loadedPeAddress">loaded PE image address or zero</param> /// <param name="loadedPeSize">loaded PE image size</param> /// <param name="age">age</param> /// <param name="guid">assembly guid</param> /// <param name="stamp">time stamp</param> /// <returns>pdb name or null</returns> /// <remarks> /// loadedPeAddress and loadedPeSize will be used here when/if the PEReader /// support runtime loaded images instead of just file images. /// </remarks> private static unsafe string GetPdbPathFromPeStream(string assemblyPath, IntPtr loadedPeAddress, int loadedPeSize, out int age, out Guid guid, out uint stamp) { if (File.Exists(assemblyPath)) { Stream peStream = File.OpenRead(assemblyPath); using (PEReader peReader = new PEReader(peStream)) { foreach (DebugDirectoryEntry entry in peReader.ReadDebugDirectory()) { if (entry.Type == DebugDirectoryEntryType.CodeView) { CodeViewDebugDirectoryData codeViewData = peReader.ReadCodeViewDebugDirectoryData(entry); stamp = entry.Stamp; age = codeViewData.Age; guid = codeViewData.Guid; string peDirectory = Path.GetDirectoryName(assemblyPath); return(Path.Combine(peDirectory, Path.GetFileName(codeViewData.Path))); } } } } stamp = 0; age = 0; guid = new Guid(); return(null); }
private bool TryReadCodeViewData(string peFilePath, out CodeViewDebugDirectoryData codeViewData, out uint stamp) { try { var peStream = PortableShim.FileStream.CreateReadShareDelete(peFilePath); using (var peReader = new PEReader(peStream)) { foreach (var entry in peReader.ReadDebugDirectory()) { if (entry.Type == DebugDirectoryEntryType.CodeView) { codeViewData = peReader.ReadCodeViewDebugDirectoryData(entry); stamp = entry.Stamp; return(true); } } } } catch { } codeViewData = default(CodeViewDebugDirectoryData); stamp = 0; return(false); }
private static void PrintAssemblyInfo(string dll) { var debugDirectory = PdbInfo.ReadDebugDirectoryEntries(dll); foreach (var debugDirectoryEntry in debugDirectory) { PrintNameValue("Debug directory entry", debugDirectoryEntry.entry.Type.ToString()); if (debugDirectoryEntry.entry.Type == DebugDirectoryEntryType.CodeView) { CodeViewDebugDirectoryData data = (CodeViewDebugDirectoryData)debugDirectoryEntry.data; PrintNameValue("Guid", data.Guid.ToString()); PrintNameValue("Age", data.Age.ToString()); PrintNameValue("Pdb path", data.Path.ToString()); PrintNameValue("Stamp", debugDirectoryEntry.entry.Stamp.ToString("X8")); } Console.WriteLine(); } var pdb = Path.ChangeExtension(dll, ".pdb"); if (File.Exists(pdb)) { Console.WriteLine("Found " + Path.GetFileName(pdb) + ":"); CheckMatch(dll, pdb); } }
private bool TryReadCodeViewData(string peFilePath, out CodeViewDebugDirectoryData codeViewData, out uint stamp) { try { var peStream = PortableShim.File.OpenRead(peFilePath); using (var peReader = new PEReader(peStream)) { foreach (var entry in PEUtilities.ReadDebugDirectory(peReader, peStream)) { if (entry.EntryType == DebugDirectoryEntryType.CodeView) { codeViewData = PEUtilities.ReadCodeViewDebugDirectoryData(peStream, entry); stamp = entry.Stamp; return(true); } } } } catch { } codeViewData = default(CodeViewDebugDirectoryData); stamp = 0; return(false); }
private static OpenedReader TryOpenReaderFromCodeView(PEReader peReader, DebugDirectoryEntry codeViewEntry, string assemblyPath) { OpenedReader result = null; MetadataReaderProvider provider = null; try { CodeViewDebugDirectoryData data = peReader.ReadCodeViewDebugDirectoryData(codeViewEntry); string pdbPath = data.Path; Stream pdbStream = null; if (assemblyPath != null) { try { pdbPath = Path.Combine(Path.GetDirectoryName(assemblyPath), GetFileName(pdbPath)); } catch { // invalid characters in CodeView path return(null); } pdbStream = TryOpenFile(pdbPath); } if (pdbStream == null) { if (s_symbolStore == null) { return(null); } Debug.Assert(codeViewEntry.MinorVersion == ImageDebugDirectory.PortablePDBMinorVersion); SymbolStoreKey key = PortablePDBFileKeyGenerator.GetKey(pdbPath, data.Guid); pdbStream = GetSymbolStoreFile(key)?.Stream; } provider = MetadataReaderProvider.FromPortablePdbStream(pdbStream); MetadataReader reader = provider.GetMetadataReader(); // Validate that the PDB matches the assembly version if (data.Age == 1 && new BlobContentId(reader.DebugMetadataHeader.Id) == new BlobContentId(data.Guid, codeViewEntry.Stamp)) { result = new OpenedReader(provider, reader); } } catch (Exception e) when(e is BadImageFormatException || e is IOException) { return(null); } finally { if (result == null) { provider?.Dispose(); } } return(result); }
public async Task <PdbFilePathResult?> GetPdbFilePathAsync(string dllPath, PEReader peReader, bool useDefaultSymbolServers, CancellationToken cancellationToken) { var hasCodeViewEntry = false; uint timeStamp = 0; CodeViewDebugDirectoryData codeViewEntry = default; using var _ = ArrayBuilder <PdbChecksum> .GetInstance(out var checksums); foreach (var entry in peReader.ReadDebugDirectory()) { if (entry.Type == DebugDirectoryEntryType.PdbChecksum) { var checksum = peReader.ReadPdbChecksumDebugDirectoryData(entry); checksums.Add(new PdbChecksum(checksum.AlgorithmName, checksum.Checksum)); } else if (entry.Type == DebugDirectoryEntryType.CodeView && entry.IsPortableCodeView) { hasCodeViewEntry = true; timeStamp = entry.Stamp; codeViewEntry = peReader.ReadCodeViewDebugDirectoryData(entry); } } if (!hasCodeViewEntry) { return(null); } var pdbInfo = new SymbolLocatorPdbInfo( Path.GetFileName(codeViewEntry.Path), codeViewEntry.Guid, (uint)codeViewEntry.Age, timeStamp, checksums.ToImmutable(), dllPath, codeViewEntry.Path); var flags = useDefaultSymbolServers ? SymbolLocatorSearchFlags.ForceNuGetSymbolServer | SymbolLocatorSearchFlags.ForceMsftSymbolServer : SymbolLocatorSearchFlags.None; var result = await _debuggerSymbolLocatorService.LocateSymbolFileAsync(pdbInfo, flags, progress : null, cancellationToken).ConfigureAwait(false); if (result.Found && result.SymbolFilePath is not null) { return(new PdbFilePathResult(result.SymbolFilePath)); } else if (_logger is not null) { // We log specific info from the debugger if there is a failure, but the caller will log general failure // information otherwise _logger.Log(result.Status); _logger.Log(result.Log); } return(null); }
// // Symbols // private PdbSymbolReader OpenAssociatedSymbolFile(string peFilePath, PEReader peReader) { string pdbFileName = null; BlobContentId pdbContentId = default; foreach (DebugDirectoryEntry debugEntry in peReader.ReadDebugDirectory()) { if (debugEntry.Type != DebugDirectoryEntryType.CodeView) { continue; } CodeViewDebugDirectoryData debugDirectoryData = peReader.ReadCodeViewDebugDirectoryData(debugEntry); string candidatePath = debugDirectoryData.Path; if (!Path.IsPathRooted(candidatePath) || !File.Exists(candidatePath)) { // Also check next to the PE file candidatePath = Path.Combine(Path.GetDirectoryName(peFilePath), Path.GetFileName(candidatePath)); if (!File.Exists(candidatePath)) { continue; } } pdbFileName = candidatePath; pdbContentId = new BlobContentId(debugDirectoryData.Guid, debugEntry.Stamp); break; } if (pdbFileName == null) { return(null); } // Try to open the symbol file as portable pdb first PdbSymbolReader reader = PortablePdbSymbolReader.TryOpen(pdbFileName, GetMetadataStringDecoder(), pdbContentId); if (reader == null) { // Fallback to the diasymreader for non-portable pdbs reader = UnmanagedPdbSymbolReader.TryOpenSymbolReaderForMetadataFile(peFilePath, Path.GetDirectoryName(pdbFileName)); } return(reader); }
public unsafe AssemblyInfo(MonoProxy monoProxy, SessionId sessionId, string url, byte[] assembly, byte[] pdb, CancellationToken token) { debugId = -1; this.id = Interlocked.Increment(ref next_id); using var asmStream = new MemoryStream(assembly); peReader = new PEReader(asmStream); var entries = peReader.ReadDebugDirectory(); if (entries.Length > 0) { var codeView = entries[0]; CodeViewDebugDirectoryData codeViewData = peReader.ReadCodeViewDebugDirectoryData(codeView); PdbAge = codeViewData.Age; PdbGuid = codeViewData.Guid; PdbName = codeViewData.Path; PdbInformationAvailable = true; } asmMetadataReader = PEReaderExtensions.GetMetadataReader(peReader); var asmDef = asmMetadataReader.GetAssemblyDefinition(); Name = asmDef.GetAssemblyName().Name + ".dll"; if (pdb != null) { var pdbStream = new MemoryStream(pdb); try { // MetadataReaderProvider.FromPortablePdbStream takes ownership of the stream pdbMetadataReader = MetadataReaderProvider.FromPortablePdbStream(pdbStream).GetMetadataReader(); } catch (BadImageFormatException) { monoProxy.SendLog(sessionId, $"Warning: Unable to read debug information of: {Name} (use DebugType=Portable/Embedded)", token); } } else { var embeddedPdbEntry = entries.FirstOrDefault(e => e.Type == DebugDirectoryEntryType.EmbeddedPortablePdb); if (embeddedPdbEntry.DataSize != 0) { pdbMetadataReader = peReader.ReadEmbeddedPortablePdbDebugDirectoryData(embeddedPdbEntry).GetMetadataReader(); } } Populate(); }
/// <summary> /// Returns metadata readers for assembly PE file and portable PDB. /// </summary> /// <param name="assemblyFileName">file name of the assembly</param> /// <param name="peReader">PE metadata reader return</param> /// <param name="pdbReader">PDB metadata reader return</param> /// <returns>true if debugging information is available</returns> private static bool GetReaders(string assemblyFileName, out MetadataReader peReader, out MetadataReader pdbReader) { peReader = null; pdbReader = null; if (!File.Exists(assemblyFileName)) { return(false); } Stream peStream = File.OpenRead(assemblyFileName); PEReader reader = new PEReader(peStream); string pdbPath = null; foreach (DebugDirectoryEntry entry in reader.ReadDebugDirectory()) { if (entry.Type == DebugDirectoryEntryType.CodeView) { CodeViewDebugDirectoryData codeViewData = reader.ReadCodeViewDebugDirectoryData(entry); pdbPath = codeViewData.Path; break; } } if (pdbPath == null) { return(false); } if (!File.Exists(pdbPath)) { pdbPath = Path.GetFileName(pdbPath); if (!File.Exists(pdbPath)) { return(false); } } peReader = reader.GetMetadataReader(); Stream pdbStream = File.OpenRead(pdbPath); MetadataReaderProvider provider = MetadataReaderProvider.FromPortablePdbStream(pdbStream); pdbReader = provider.GetMetadataReader(); return(true); }
internal PeParser(byte[] dllBytes) { using (var peReader = new PEReader(new MemoryStream(dllBytes))) { DebugData = peReader.ReadCodeViewDebugDirectoryData(peReader.ReadDebugDirectory()[0]); PeHeaders = peReader.PEHeaders; } var peBufferHandle = GCHandle.Alloc(dllBytes, GCHandleType.Pinned); _peBuffer = peBufferHandle.AddrOfPinnedObject(); BaseRelocations = GetBaseRelocations(); ExportedFunctions = GetExportedFunctions(); ImportedFunctions = GetImportedFunctions(); TlsCallbacks = GetTlsCallbacks(); peBufferHandle.Free(); }
public PdbChecksumDebugDirectoryDataEntry(CodeViewDebugDirectoryData entry) { this.entry = entry; }
public CodeViewTreeNode(CodeViewDebugDirectoryData entry) { this.entry = entry; }