diff --git a/Mono.Cecil.Cil/PortablePdb.cs b/Mono.Cecil.Cil/PortablePdb.cs index 6664bee32..0ffa1815d 100644 --- a/Mono.Cecil.Cil/PortablePdb.cs +++ b/Mono.Cecil.Cil/PortablePdb.cs @@ -319,6 +319,20 @@ public void Write () } } + string GetPdbPath () + { + var debugHeader = module.Image.DebugHeader; + foreach (var entry in debugHeader.Entries) { + var data = entry.Data; + // Pdb path is NUL-terminated path at offset 24. + // https://github.com/dotnet/runtime/blob/main/docs/design/specs/PE-COFF.md#codeview-debug-directory-entry-type-2 + if (entry.Directory.Type == ImageDebugType.CodeView && data.Length >= 25) + return System.Text.Encoding.UTF8.GetString (data, 24, data.Length - 25); + } + + return string.Empty; + } + public ImageDebugHeader GetDebugHeader () { if (IsEmbedded) @@ -341,7 +355,10 @@ public ImageDebugHeader GetDebugHeader () // PDB Age buffer.WriteUInt32 (1); // PDB Path - var fileName = writer.BaseStream.GetFileName (); + var fileName = GetPdbPath (); + if (string.IsNullOrEmpty (fileName)) { + fileName = writer.BaseStream.GetFileName (); + } if (string.IsNullOrEmpty (fileName)) { fileName = module.Assembly.Name.Name + ".pdb"; } diff --git a/Test/Mono.Cecil.Tests/PortablePdbTests.cs b/Test/Mono.Cecil.Tests/PortablePdbTests.cs index a89f79d83..617f4b608 100644 --- a/Test/Mono.Cecil.Tests/PortablePdbTests.cs +++ b/Test/Mono.Cecil.Tests/PortablePdbTests.cs @@ -1148,5 +1148,33 @@ static void GetCodeViewPdbId (ModuleDefinition module, out byte[] pdbId) buffer.WriteInt32 (cv.Directory.TimeDateStamp); pdbId = buffer.buffer; } + + [Test] + public void WritePortablePdbPath () + { + const string resource = "PdbPathLib.dll"; + string destination = Path.GetTempFileName (); + + using (var module = GetResourceModule (resource, new ReaderParameters { ReadSymbols = true })) { + module.Write (destination, new WriterParameters { WriteSymbols = true }); + } + + using (var module = ModuleDefinition.ReadModule (destination, new ReaderParameters { ReadSymbols = true })) { + GetCodeViewPdbPath (module, out string pdbPath); + + Assert.AreEqual ("/_/artifacts/obj/PdbPathLib/release/PdbPathLib.pdb", pdbPath); + } + } + + static void GetCodeViewPdbPath (ModuleDefinition module, out string pdbPath) + { + var header = module.GetDebugHeader (); + var cv = Mixin.GetCodeViewEntry (header); + Assert.IsNotNull (cv); + + CollectionAssert.AreEqual (new byte [] { 0x52, 0x53, 0x44, 0x53 }, cv.Data.Take (4)); + + pdbPath = Encoding.UTF8.GetString (cv.Data, 24, cv.Data.Length - 25); + } } } diff --git a/Test/Resources/assemblies/PdbPathLib.dll b/Test/Resources/assemblies/PdbPathLib.dll new file mode 100644 index 000000000..8c176d76c Binary files /dev/null and b/Test/Resources/assemblies/PdbPathLib.dll differ diff --git a/Test/Resources/assemblies/PdbPathLib.pdb b/Test/Resources/assemblies/PdbPathLib.pdb new file mode 100644 index 000000000..37b9925c1 Binary files /dev/null and b/Test/Resources/assemblies/PdbPathLib.pdb differ