Should I be concerned about PDB files ?

I still can remember, the first time I encountered PDB files. “Should I be concerned about PDB files ?” and was quickly replied as “it’s just another file used in the debugging process”, by a colleague. Till yesterday, I had the same definition with me. Let me share with you what I found more about it.

A PDB(Program Data Base) file generated by Visual Studio, is used by a debugger and it contains mapping information. It maps the identifier and the statements in the source code to the ones present in the generated executable or dll. Out of this mapping information it concludes two pieces of information: the source file name and the line number that are displayed in the Visual Studio IDE; and  the location in the executable to stop at when you set a breakpoint. (If you want to programmatically  inspect the PDF file take a look at Marc‘s article.)

The debugger in order to find the matching PDB file, looks for PDB file having the same name as executable/dll. If dll is named as “Web.dll”, the debugger looks for “Web.pdb”. Another piece of information that makes the PDB file as  the exact match for the binary, is by the use of a GUID that’s embedded in both the PDB file and the binary. The process of compilation puts the GUID into the binary and PDB. The debugger loads only a PDB file for an executable that exactly matches the PDB file that was created when the executable was built. Now if we loose the PDB files for some build, then we won’t be able to debug that build. For this we can setup a Symbol Server, that stores the PDBs and binaries.

In order to find the correct PDB file the debugger searches for it at these locations :

  1. The debugger first checks inside the location that is specified inside the DLL or the executable file. This happens at the time of  built when the linker places the full path and file name of the associated PDB file inside the DLL or the executable file.
  2. Then it searches inside the directory where the DLL or executable file, is present.
  3. If it is not found in the above two locations it checks for the presence any symbol sever setup for the machine. If yes, it looks inside the symbol server cache directory.
  4. If the PDB is not found in the cache it then looks inside the symbol server.

After getting the correct PDB file, now debugger searches for the source file, it looks for it at these locations in the following order :

  1. Any files that are opened in the Visual Studio instance that launched the debugger.
  2. Inside the solution folder that is opened in the Visual Studio instance that launched the debugger.
  3. Directories that are specified in the Common Properties / Debug Source Files page in the properties of the solution.
  4. The matched PDB file also contains the original location of the source file or it can be a command to a source server from where it can be retrieved from.
Build Settings

Build Settings

A PDB file gets generated both in case of “Debug” and “Release” builds. Yes, for “Release” builds also it gets generated by default. However, there’s less information in a “Release” build than in a “Debug” build anyway. But we can also control its generation from “Project Properties -> Build -> Advanced…-> Output -> Debug Info”.  Three options are available “none”, “full” and “pdb-only”.  One difference between “full” and “pdb-only” is that with “pdb-only” selected, the compiler emits the DebuggableAttribute ( which tells the JIT compiler that debug information is available) and the generated PDB file allows viewing of information such as source file names and line numbers in the application’s stacktrace. One thing to keep in mind while using “full” option is that, you will get an error if your code contains the “DebuggableAttribute” set to false and we select the “full” option. ( John Robbins has shared some different views, about the differences I will hold to the MSDN info, till I get some new updates. Surely you can share with me your findings). Also the generation of PDB’s have zero performance impact.

Another benefit that PDB’s give is a detail stack trace report for a crash. In order to better understand, lets create an ASP.NET empty web application, named as “PDBDemo”. To this project add an aspx page, named as “TestPage.aspx” and to the “Page_Load()” event handler add a line of code to throw an exception.

namespace PDBDemo
{
 public partial class TestPage : System.Web.UI.Page
 {
 protected void Page_Load(object sender, EventArgs e)
 {
 throw new ApplicationException();
 }
 }
}

And this is the result we got with and without the presence of a PDB file.

With PDB

With PDB

Without PDB

Without PDB

Certainly we wont be showing the ASP.NET yellow page of death to the end user. But the log files will be missing the line number and the source path, which can help us to zero in and fix the issue.

In my opinion, its always good to generate PDB’s for the “Release” builds. It is not that we need to have PDBs along with binaries deployed to get that extra information about the exception. The same can also be achieved using Symbol Server and Source Indexing. To conclude, for me, the PDB’s are as much valuable as the source code.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s