diff --git a/src/coreclr/tools/Common/Compiler/CompilerTypeSystemContext.cs b/src/coreclr/tools/Common/Compiler/CompilerTypeSystemContext.cs index 029949cda38468c599525f2da427551b47c8b7f5..e903005084bae657cb2c36438d59005c73fe6fb1 100644 --- a/src/coreclr/tools/Common/Compiler/CompilerTypeSystemContext.cs +++ b/src/coreclr/tools/Common/Compiler/CompilerTypeSystemContext.cs @@ -315,39 +315,39 @@ public MetadataStringDecoder GetMetadataStringDecoder() private PdbSymbolReader OpenAssociatedSymbolFile(string peFilePath, PEReader peReader) { - // Assume that the .pdb file is next to the binary - var pdbFilename = Path.ChangeExtension(peFilePath, ".pdb"); - string searchPath = ""; + string pdbFileName = null; + BlobContentId pdbContentId = default; - if (!File.Exists(pdbFilename)) + foreach (DebugDirectoryEntry debugEntry in peReader.ReadDebugDirectory()) { - pdbFilename = null; + if (debugEntry.Type != DebugDirectoryEntryType.CodeView) + continue; - // If the file doesn't exist, try the path specified in the CodeView section of the image - foreach (DebugDirectoryEntry debugEntry in peReader.ReadDebugDirectory()) + CodeViewDebugDirectoryData debugDirectoryData = peReader.ReadCodeViewDebugDirectoryData(debugEntry); + + string candidatePath = debugDirectoryData.Path; + if (!Path.IsPathRooted(candidatePath) || !File.Exists(candidatePath)) { - if (debugEntry.Type != DebugDirectoryEntryType.CodeView) + // Also check next to the PE file + candidatePath = Path.Combine(Path.GetDirectoryName(peFilePath), Path.GetFileName(candidatePath)); + if (!File.Exists(candidatePath)) continue; - - string candidateFileName = peReader.ReadCodeViewDebugDirectoryData(debugEntry).Path; - if (Path.IsPathRooted(candidateFileName) && File.Exists(candidateFileName)) - { - pdbFilename = candidateFileName; - searchPath = Path.GetDirectoryName(pdbFilename); - break; - } } - - if (pdbFilename == null) - return null; + + 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()); + PdbSymbolReader reader = PortablePdbSymbolReader.TryOpen(pdbFileName, GetMetadataStringDecoder(), pdbContentId); if (reader == null) { // Fallback to the diasymreader for non-portable pdbs - reader = UnmanagedPdbSymbolReader.TryOpenSymbolReaderForMetadataFile(peFilePath, searchPath); + reader = UnmanagedPdbSymbolReader.TryOpenSymbolReaderForMetadataFile(peFilePath, Path.GetDirectoryName(pdbFileName)); } return reader; diff --git a/src/coreclr/tools/Common/TypeSystem/Ecma/SymbolReader/PortablePdbSymbolReader.cs b/src/coreclr/tools/Common/TypeSystem/Ecma/SymbolReader/PortablePdbSymbolReader.cs index b270b73ab8d90b45707ae0c3457e30c0741703c7..553f5a94fedcebcb0f17e397b2990fe065ece9ed 100644 --- a/src/coreclr/tools/Common/TypeSystem/Ecma/SymbolReader/PortablePdbSymbolReader.cs +++ b/src/coreclr/tools/Common/TypeSystem/Ecma/SymbolReader/PortablePdbSymbolReader.cs @@ -62,13 +62,20 @@ private static unsafe MetadataReader TryOpenMetadataFile(string filePath, Metada } } - public static PdbSymbolReader TryOpen(string pdbFilename, MetadataStringDecoder stringDecoder) + public static PdbSymbolReader TryOpen(string pdbFilename, MetadataStringDecoder stringDecoder, BlobContentId expectedContentId) { MemoryMappedViewAccessor mappedViewAccessor; MetadataReader reader = TryOpenMetadataFile(pdbFilename, stringDecoder, out mappedViewAccessor); if (reader == null) return null; + var foundContentId = new BlobContentId(reader.DebugMetadataHeader.Id); + if (foundContentId != expectedContentId) + { + mappedViewAccessor.Dispose(); + return null; + } + return new PortablePdbSymbolReader(reader, mappedViewAccessor); } diff --git a/src/coreclr/tools/dotnet-pgo/TraceTypeSystemContext.cs b/src/coreclr/tools/dotnet-pgo/TraceTypeSystemContext.cs index afdb148089b266851ed9b4d5553f6d104330b1f6..6377988bbb21177f3d6920e594068a8cc24c6dfa 100644 --- a/src/coreclr/tools/dotnet-pgo/TraceTypeSystemContext.cs +++ b/src/coreclr/tools/dotnet-pgo/TraceTypeSystemContext.cs @@ -356,33 +356,35 @@ private EcmaModule AddModule(string filePath, string expectedSimpleName, byte[] private PdbSymbolReader OpenAssociatedSymbolFile(string peFilePath, PEReader peReader) { - // Assume that the .pdb file is next to the binary - var pdbFilename = Path.ChangeExtension(peFilePath, ".pdb"); + string pdbFileName = null; + BlobContentId pdbContentId = default; - if (!File.Exists(pdbFilename)) + foreach (DebugDirectoryEntry debugEntry in peReader.ReadDebugDirectory()) { - pdbFilename = null; + if (debugEntry.Type != DebugDirectoryEntryType.CodeView) + continue; - // If the file doesn't exist, try the path specified in the CodeView section of the image - foreach (DebugDirectoryEntry debugEntry in peReader.ReadDebugDirectory()) + CodeViewDebugDirectoryData debugDirectoryData = peReader.ReadCodeViewDebugDirectoryData(debugEntry); + + string candidatePath = debugDirectoryData.Path; + if (!Path.IsPathRooted(candidatePath) || !File.Exists(candidatePath)) { - if (debugEntry.Type != DebugDirectoryEntryType.CodeView) + // Also check next to the PE file + candidatePath = Path.Combine(Path.GetDirectoryName(peFilePath), Path.GetFileName(candidatePath)); + if (!File.Exists(candidatePath)) continue; - - string candidateFileName = peReader.ReadCodeViewDebugDirectoryData(debugEntry).Path; - if (Path.IsPathRooted(candidateFileName) && File.Exists(candidateFileName)) - { - pdbFilename = candidateFileName; - break; - } } - if (pdbFilename == null) - return null; + 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()); + PdbSymbolReader reader = PortablePdbSymbolReader.TryOpen(pdbFileName, GetMetadataStringDecoder(), pdbContentId); return reader; }