ILSpy
ILSpy copied to clipboard
Add tests for PDBGen
We need tests for PDBGen:
These could be similar to existing IL pretty tests:
- Take IL and fixed list of sequence points
- Decompile + Generate PDB
- Compare output + list of sequence points
Hi, I'm looking into whether I am capable of adding these tests and was contemplating the most effective ways of ensuring the tests provide the best possible coverage. My initial thought is that the tests should take existing DLLs of various open-source projects (such as Json.NET, Cecil, etc, used in the round-trip tests), decompile them, generate sequence points, and then compare the generated sequence points with the ones in the original PDB.
Because I understand that the generated sequence points are only an approximation, I think I won't be able to compare them directly, as that would likely yield way too many false positives. I was wondering if, instead, I could use some high-level heuristics to detect that something is wrong and may negatively effect the stepping experience, such as:
- If two
call
/callvirt
instructions were in the same sequence point in the original pdb, but aren't in the same sequence point in the generated PDB - If there is are two (or more) sequence points in the original PDB which are wholly contained inside a single generate sequence point
Before I attempt to go on this endeavor, I would love to get your feedback both on the general approach and on the heuristics listed above. Thanks for listening!
/cc @dgrunwald
The sequence points original PDB are a mapping between IL-Offsets and the original source code. The sequence points in the ILSpy-generated PDB is a mapping between IL-Offsets and the decompiled source code. Because the source code isn't identical (different line numbers; potentially different arrangement of control flow (e.g. early-return vs. else-block)), the sequence points won't be identical either.
The other option is to decompile a DLL, then recompile it with the C# compiler. Now you have two PDBs referring to the same source code, but to different assemblies. The IL offsets won't be the same, so you also won't get comparable sequence points.
Even the checks you suggest don't work. Consider the original source code:
int i = FirstCall();
Console.WriteLine(i);
The C# compiler may optimize out the local variable i
, the the decompiled code now looks like this:
Console.WriteLine(FirstCall());
So for the decompiled PDB both calls are in the same sequence point, whereas they aren't in the original PDB.
I guess your approach can work if you compare two PDBs that both apply to the same source code (ILSpy-generated PDB and PDB generated when recompiling the decompiled code) -- you can match sequence points based on their line numbers. They will have different IL offsets associated with them, but you could look into the associated IL code and check that the set of call instructions matches. There will probably still be some differences; especially if the original assembly was compiled by a different Roslyn version than the recompiled assembly (e.g. different implementations of string concatenation). But maybe at least the simple case where the same compiler was used for the original compilation and the recompilation can be made to work.
Still, this is only a sanity check (like our RoundtripTests are for the decompiler), we definitely also need unit tests where we can check specific problematic code constructs.
Regarding constructs and feature status please also see #1422 and #1901
I added another test in https://github.com/icsharpcode/ILSpy/pull/3032, currently disabled