Debugging Assemblies that weren’t built with debug information

Posted in: , , by . No comments


introduction

Using this great dotPeek feature we can debug any third party managed assembly we want (it gets even better when we prevent JIT optimizations), unless it was built without debug information. This can be seen during debug in the Modules window:image
Such assemblies were created without a PDB file using that setting:image
The debugger sees that the assembly was created without a PDB file, so it will refuse loading the “fake” PDB that dotPeek creates.

Note that there is no reason to build assemblies with this setting, the fact that the assembly points to a PDB file is mostly relevant during debug time and has no impact on performance. Thus it’s rare to find such assemblies (all Microsoft’s .NET Framework assemblies and even Windows’ native DLLs were built with PDBs for example) but they exist.

Where is that information stored?

This information is stored in the PE header, and can be viewed with dumbin /headers:

C:\> dumpbin /headers Test.dll
...
Debug Directories

Time Type Size RVA Pointer
-------- ------ -------- -------- --------
55324F94 cv 24 00125D90 123F90 Format: RSDS, {C2B3677B-EE83-4
1DA-8CA2-C16D74BB6C87}, 1, Test.pdb
...

The output above contains the GUID that is matched by the debugger in the loaded PDB file along with few other things. When Debug Info is set to none no Debug directories are emitted and thus no PDB file can be matched.


What can we do?

Theoretically it is possible to directly add Debug Directories to the assembly but no common tool does it, so we’ll use ildasm and ilasm:

C:\> ildasm NoDebugInfo.dll /out=Test.il
C:\> ilasm /dll /pdb /Out:Test.dll Test.il


Those pair of commands create an assembly with a PDB file, thus the assembly has Debug Directories that point to the PDB. You now may be asking the following:


  1. What if the assembly is strong name signed?
    This will break the signature, but for some cases it isn’t validated and when it is you can disable validation for this assembly using sn –Vr <AssemblyFile> (don’t forget to restore the setting later using sn –Vu or sn -Vx). Note that you must run the correct edition (32 bit or 64 bit) for the program you are running, the Visual Studio Developer Command Prompt on my machine references the 32 bit one so for 64 bit application I must run the one located in C:\Program Files (x86)\Microsoft SDKs\Windows\v8.1A\bin\NETFX 4.5.1 Tools\x64 on my machine.

  2. What does the created PDB contain?
    .NET PDBs point between IL offsets and source code lines, in this case instead of C# our source is IL, which isn’t really useful because the same IL instructions are embedded in the assembly, However for our purpose it doesn’t matter, we just wanted to add Debug Directories and we’ll use the dotPeek provided PDB that is “faking” the PDB signature to actually debug C# code.

Posted in: , , by . No comments

The permalink

Leave a Reply