Click here to Skip to main content
15,867,756 members
Articles / .NET

Know Program Database File (PDB)

Rate me:
Please Sign up or sign in to vote.
4.47/5 (23 votes)
25 May 2018CPOL6 min read 73.5K   53   6
What is the use of PDB file?

Introduction

This article helps developers who are at a beginner or intermediate level but don't have much understanding about the importance of PDBs and why they are required.

What is PDB

PDB is an acronym for Program database file.

A PDB file is typically created from source files during compilation. It stores a list of all symbols in a module with their addresses and possibly the name of the file and the line on which the symbol was declared. (from wiki)

Why PDB as a Separate File?

These symbols can be very well embedded in the binary, but it in turn results in the file size growing significantly larger (sometimes by several megabytes). To avoid this extra size, modern compilers and early mainframe debugging systems output the symbolic information into a separate file; for Microsoft compilers, this file is called a PDB file.

What Does the PDB File Contain

Following is some of the important information stored by PDB file:

  1. Local variable name - To prove that pdb contains local variable name, we will make use of Reflector to decompile the assembly with its PDB present in the same folder as that of assembly. Reflector has a option called "Show PDB symbols" as shown in the screenshot which when checked also loads corresponding PDB for that assembly. When you check the option, you can see the decompiled code has the same variable name as that of your actual code but in the absence of that PDB or when this option is unchecked, your local variables in your decompiled code would get replaced with names like "str" for string variable and "num" for decimal, etc.

    Image 1

  2. Source file name
  3. Line number of the source
  4. Source Indexing (explained in later section)

To show that PDB contains source file name and line number of source (point 2 and 3), run the following console application first with PDB present in the same folder and second by deleting the PDB file.

C#
namespace UnderstandingPDBs
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                int sum = Add(5, 10);
                decimal value = Divide(10, 0);
            }
 
            catch
            {
            }
        }
 
        private static int Add(int i, int j)
        {
            return i + j;
        }
 
        private static decimal Divide(int i, int j)
        {
            try
            {
                return i / j;
            }
            catch (Exception ex)
            {
                LogError(ex);
                throw ex;
            }
        }
 
        private static void LogError(Exception ex)
        {
            using (var txtWriter = new StreamWriter(@"dump.txt",true))
            {
                string error = "Exception:" + ex.Message + 
                Environment.NewLine + "StackTrace:" + ex.StackTrace
                if(ex.InnerException!=null)
                    error=error+"INNER EXCEPTION:"+ex.InnerException;
                txtWriter.WriteLine(error);
            }
        }
    }
}  

With PDB, this is the exception thrown by the application:

Exception:Attempted to divide by zero.
StackTrace: at UnderstandingPDBs.Program.Divide(Int32 i, Int32 j) in 
C:\Users\Rishi\Documents\Visual Studio 2010\Projects\UnderstandingPDBs\Program.cs:line 33

Without PDB, exception shows the following message:

Exception:Attempted to divide by zero.
StackTrace: at UnderstandingPDBs.Program.Divide(Int32 i, Int32 j)
---------

Clearly, the one with PDB shows line number and file name of the class where exception is thrown.

How PDB is Loaded by Debugger?

The Visual Studio debugger expects the PDB file to be under the same folder as the DLL or EXE. PDB files generated for the assembly are unique for each build, that means you can't use the PDB created in previous build with the assembly created in any other build even if there are no code changes. Debugger finds out if the PDB is for that binary by comparing a specific GUID in PDB with that of the binary. This Guid is embedded during compilation in both binary and PDB which tightly links PDB with its binary.

Different Build Settings in Visual Studio

Visual Studio has 3 different Build Options which control the debug symbols generation:

  1. none: PDB files will not be generated.
  2. pdb-only: The debug symbols will be only in PDB files and not in Binary
  3. Full: Along with symbols in PDB binary will also contain some debug symbols

Full is the default option set in Visual Studio.

According to MSDN:

"If you use /debug:full, be aware that there is some impact on the speed and size of JIT optimized code and a small impact on code quality with /debug:full. We recommend /debug:pdbonly or no PDB for generating release code."

Image 2

Should We Deploy PDBs Along with Binaries?

If the size of deliverables are not a concern, it's good to have PDB deployed along with other binaries as it helps provide more information about exceptions as we saw in the above example. These PDBs can be very helpful during certain crashes occuring intermittently for some user which without PDB will make life difficult.

It is not that you must have PDBs along with Binary deployed to get that extra information about the exception. The same can be achieved using Symbol Server and Source Indexing which I will discuss in the below topic.

Security Risk with PDB?

Anyone having access to DLL/EXE can easily do reverse engineering to generate the source code with or without PDB using tools like reflector. So not providing PDB will not be of much help in this case.

If PDB is deployed and the user doesn't have access to binaries, it's not a good idea to show them the stack trace information and let them know the internals of the application.

Symbol Server

Symbol server is used to store pdb files which are known to the debugger and can be used to find more descriptive call stack information.

We can set up our own Symbol server using the symstore.exe, which allows debugger to find the actual PDB associated with binary in question. symstore.exe is included in the Debugging tools for Window package.

Microsoft also maintains Symbol server which we can use by loading the PDBs from Microsoft's Symbol server.

How and Why to load Microsoft Symbol Store

When you stop execution at debug point and open Modules Window (as shown below), you will find all the DLLs(external or internal) loaded until that breakpoint but the Symbol status by default will show "Cannot find or open pdb file" except for your PDB. These are the Microsoft BCL binaries which are not loaded because our debugger can't find the related PDBs.

Image 3

To load these symbols, go to Debugging->Symbols and check Microsoft Symbol Servers and give the Cache symbols in this directory as any shared folders so that it can be used by all the developers.

Since these binaries are external to your application, you also need to uncheck "Enable just my Code" in Debugging->General menu.

In the below screenshot, you can see that I have loaded the Symbol and now the status of the symbols shows "Symbols loaded".

Image 4

So how can this be useful?
You can put breakpoint in your code and see the call stack with and without the symbols loaded.
The below figure shows the call stack without the Symbols loaded and it just displays my methods and the BCL's method as just [External Code] .

Image 5

With the symbols loaded, the call stacks display all the method calls prior to the breakpoint (see below figure). It certainly can be helpful when we want to know what are the external methods called so that it can be analyzed using Reflector or by debugging Disassembly, while sorting out any particular issue in our application related to some behaviour change due to external code.

Call stack after Symbols are loaded

Like Symbol server, there is also something called Source Server which are used to retrieve the exact version of source file used to build any particular application. Binaries can be source indexed when it is build and this information is stored in PDB file which helps source server to find the exact source file.

You can check MSDN to know more about Symbol and Source Store.

Points of Interest

PDB files are Microsoft proprietary files and are least documented. I will be happy to learn more with your feedback, and will explore and publish more about it in the future.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Technical Lead Microlise
India India
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionUnable to see all images Pin
Suchi Banerjee, Pune26-Mar-12 2:31
Suchi Banerjee, Pune26-Mar-12 2:31 
AnswerRe: Unable to see all images Pin
Rishikesh_Singh26-Mar-12 2:44
Rishikesh_Singh26-Mar-12 2:44 
Seems some issue with IE. Please try in firefox
GeneralRe: Unable to see all images Pin
Blake Miller26-Mar-12 8:09
Blake Miller26-Mar-12 8:09 
GeneralRe: Unable to see all images Pin
Rishikesh_Singh26-Mar-12 20:27
Rishikesh_Singh26-Mar-12 20:27 
GeneralRe: Unable to see all images Pin
Corvus Corax26-Mar-12 18:44
Corvus Corax26-Mar-12 18:44 
GeneralRe: Unable to see all images Pin
Rishikesh_Singh26-Mar-12 20:15
Rishikesh_Singh26-Mar-12 20:15 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.