Flush Crossgen2 R2R output stream before generating native PDB - #131607
Flush Crossgen2 R2R output stream before generating native PDB#131607elinor-fung with Copilot wants to merge 8 commits into
Conversation
|
Azure Pipelines: 16 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
The FileStream that ReadyToRunObjectWriter writes the R2R image into was kept open (via a method-scoped `using`) while SymbolFileBuilder.SavePdb read the image back from disk to generate the native PDB. Because the FileStream buffers writes until disposed, the PDB writer could observe an incomplete image with a zeroed CodeView/RSDS GUID, producing native PDBs whose PDB-info GUID did not match the DLL. Close the stream (capturing the file size for the map builder) before generating symbol files. Co-authored-by: elinor-fung <47805090+elinor-fung@users.noreply.github.com>
|
Azure Pipelines: Successfully started running 3 pipeline(s). 13 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
@copilot We already have |
Extend PdbChecker to optionally take the crossgen2 output image via a new `--image <file>` argument. When supplied, it reads the image's CodeView/RSDS debug record and verifies the DIA-reported PDB-info GUID/age is nonzero and matches the image identity, regressing the zero-GUID native PDB bug. Wire the crossgen2 R2R test PDB check to pass the output image. Co-authored-by: elinor-fung <47805090+elinor-fung@users.noreply.github.com>
Avoid silently skipping validation and returning success when a PDB file argument is omitted but --image is supplied. Co-authored-by: elinor-fung <47805090+elinor-fung@users.noreply.github.com>
Done. Note This comment was generated by GitHub Copilot. |
| } | ||
| MSDiaSymbolReader reader = new MSDiaSymbolReader(args[0]); | ||
|
|
||
| string? pdbFile = null; |
There was a problem hiding this comment.
@copilot We can still require the pdb file to be args[0] (like it did before)
There was a problem hiding this comment.
Done — the PDB file is back to args[0], with --image and symbol names parsed from the remaining args.
Note
This comment was generated by GitHub Copilot.
| /// match the CodeView / RSDS debug record embedded in the output image. This guards | ||
| /// against native PDBs whose identity does not satisfy the image's symbol-server lookup key. | ||
| /// </summary> | ||
| private static void ValidatePdbMatchesImage(MSDiaSymbolReader reader, string imageFile) |
There was a problem hiding this comment.
@copilot can we just make MSDiaSymbol reader use loadAndValidateDataFromPdb if we have an image?
There was a problem hiding this comment.
Done. MSDiaSymbolReader now reads the image's CodeView/RSDS GUID+age and calls loadAndValidateDataFromPdb when an image is provided, so DIA performs the identity match (and rejects the all-zero-GUID PDB) instead of comparing manually in Program.cs.
Note
This comment was generated by GitHub Copilot.
…taFromPdb Keep the PDB file as the first positional argument. When --image is supplied, MSDiaSymbolReader reads the image's CodeView/RSDS identity and loads the PDB via DIA's loadAndValidateDataFromPdb, which throws when the PDB-info GUID/age don't match the image (including the all-zero GUID regression), instead of comparing identities manually in Program.cs. Co-authored-by: elinor-fung <47805090+elinor-fung@users.noreply.github.com>
Co-authored-by: elinor-fung <47805090+elinor-fung@users.noreply.github.com>
| /// <summary> | ||
| /// PDB-info identity GUID as reported by DIA for the PDB file. | ||
| /// </summary> | ||
| public Guid PdbGuid { get; } | ||
|
|
||
| /// <summary> | ||
| /// PDB-info age as reported by DIA for the PDB file. | ||
| /// </summary> | ||
| public uint PdbAge { get; } | ||
|
|
||
| public MSDiaSymbolReader(string pdbFile, string? imageFile = null) |
There was a problem hiding this comment.
@copilot remove these properties. All we do is print out the GUID and age in the constructor.
There was a problem hiding this comment.
Removed the PdbGuid/PdbAge properties; the GUID and age are now local variables printed in the constructor (809f5c6).
Note
This comment was generated by GitHub Copilot.
Co-authored-by: elinor-fung <47805090+elinor-fung@users.noreply.github.com>
Co-authored-by: Elinor Fung <elfung@microsoft.com>
| Console.WriteLine("PDB file: {0}", pdbFile); | ||
| Console.WriteLine("PDB GUID: {0}", pdbGuid); | ||
| IDiaSymbol globalScope = _diaSession.globalScope; | ||
| Console.WriteLine("PDB file: {0}", pdbFile); | ||
| Console.WriteLine("PDB GUID: {0}", globalScope.guid); | ||
| Console.WriteLine("PDB age: {0}", globalScope.age); | ||
| Console.WriteLine("Total symbols: {0}", symbolsTotal); | ||
| Console.WriteLine("Public symbols: {0}", _pdbSymbols.Count); |
Crossgen2-generated native PDBs (
*.ni.pdb) had an all-zero PDB-info GUID after the migration fromR2RPEBuildertoPEObjectWriter, so the PDB could not satisfy the DLL's symbol-server lookup key andmsdlsymbol lookup failed for .NET 11 preview SDK R2R symbols.Root cause
In
ReadyToRunObjectWriter.EmitReadyToRunObjects, the outputFileStreamwas declared with a method-scopedusing, so it stayed open whileSymbolFileBuilder.SavePdbran.SavePdb→PdbWriter.WritePDBDataHelperreads the finished image back from disk (File.Copy(dllPath, ...)) to feed DIA. SinceFileStreambuffers writes until disposed, DIA read an incomplete on-disk image with a zeroed CodeView/RSDS GUID, producing a PDB whose identity didn't match the DLL.Changes
ReadyToRunObjectWriter.cs: Scope the object emission in a nestedusingblock so the stream is flushed and closed before any symbol file (PDB/PerfMap) reads the image from disk. Capturestream.Lengthinside the block for the map builder, which was the only remaining consumer of the open stream.Notes
No regression test is added here: native PDB generation goes through DIA, which is Windows-only, and there is no cross-platform crossgen2 PDB test infrastructure to extend.