wiki

Codit Wiki

Loading information... Please wait.

Codit Blog

How to debug through external code ?

 

Posted on Thursday, May 17, 2018 12:00 AM

Frederik Gheysels by Frederik Gheysels

This article will guide you through the process of exposing the debug-information for your project using a symbol server on VSTS with private build agents.

We'll focus on exposing the symbols using IIS while pointing out some caveats along the way.

Introduction

I believe that we've all experienced the situation where you're debugging an application and would like to step into the code of a dependent assembly that has been written by you or another team in your company but is not part of the current code repository.
Exposing the debug-information of that assembly via a symbol server allows you to do that.

While setting up a symbol-server and indexing pdb files was quite a hassle 10 years ago, it currently is a piece of cake when you use VSTS for your automated builds.

Build definition

To enable the possibility of stepping into the code of your project, the debug-symbols of that assembly must be exposed to the public.

This is done by adding the Index sources & Publish symbols task to your VSTS build definition:
This task will in fact add some extra information to the pdb files that are created during the build process. 

Additional information, such as where the source files can be found and what version of the sources were used during the build will be added to the pdb files.

After that, the pdb files will be published via a Symbol Server.

Once this task has been added, it still needs some simple configuration:

Since VSTS is now also a symbol server, the easiest way to publish your symbols is to select Symbol Server in this account/collection.  
When this option is selected, you should be good to go and don't have to worry about the remainder of this article.

However, since some projects are configured with private build agents, I want to explore the File share Symbol Server type in this article.

Select File Share as the Symbol Server type and specify the path to the location where the debug-symbols must be stored.

See the image below for an example:

When selecting this option, you'll publish the symbols to a File share which means that you'll need to have access to the build-server.  This implies that a Private Build Agent must be used that runs on a server that is under your (or your organizations) control.
Note that the path must be an UNC path and may not end with a backslash, otherwise the task will fail.
This means that the folder that will ultimately contain the symbol-files must be shared and needs the correct permissions.
Make sure that the user under which the build runs, has sufficient rights to write and modify files on that share. Granting the VSTS_AgentService group or the Network Service group Modify rights on that directory should suffice.

At this point, you can trigger the build and verify if the Index sources & Publish symbols task succeeded.

If it succeeded, you should see that some directories are created in the location where the symbols should be stored and you should find pdb files inside those directories.

If nothing has been added to the folder, you should inspect the logs and see what went wrong.

Maybe no *.pdb files have been found, possibly because the path to the build-output folder is incorrect.

It's also possible that *.pdb files have been found but cannot be indexed. This is common when publishing symbols projects that target .NET Core or .NET Standard. In those cases, you might find a warning in the log of the Index & Publish task that looks like this:
Skipping: somefile.pdb because it is a Portable PDB

It seems that the Index sources & Publish symbols task does not support Portable pdb files. To expose debug information for these assemblies, SourceLink  must be used, but this is beyond the scope of this article.

There is a quick workaround however: change the build settings of your project and specify that the debug information should not be portable but must be Full or Pdb only. This can be specified in the Advanced Build settings of your project in Visual Studio.

This workaround enables that the symbols can be indexed but using them while debugging will only be possible on Windows platforms which defeats a bit the purpose of having a .NET core assembly.

Exposing the debug symbols via HTTP

Now that the debug symbols are there, they should be exposed so that users of your assembly / package can make use of them.

One way to do this, is serving the symbols via a webserver.

To do this, install and configure IIS on the server where your build agent runs.

Create a Virtual Directory

This step is fairly simple: In IIS Manager, just create a virtual directory for the folder that contains the debug symbols:

Configure MIME type for the pdb files

IIS will refuse to serve files with an unknown MIME - type. Therefore, you'll have to specify the MIME type for the *.pdb files. If you fail to do so, IIS will return a HTTP 404 status code (NotFound) when a pdb file is requested.

To configure the MIME type for *.pdb files, open IIS Manager and click open the MIME types section and specify a new MIME type for the .pdb extension:

Authentication

Depending on who should have access to the debug-symbols, the correct authentication method has to be setup.

If anyone may download the debug symbols, then IIS must be configured to use Anonymous Authentication.

To enable Anonymous Authentication, open the Authentication pane in IIS and enable Anonymous Authentication. If the Anonymous Authentication option is not listed, then use Turn Windows feature on and off to enable it.

Having access to the debugging information does not imply that everybody also has access to the source code, as we'll see later in the article.

Configure Visual Studio to access the symbol server

Now that the debug information is available, the only thing left to do is enable Visual Studio to use those symbols.

To do this, open the Debug Options in Visual Studio and check the Enable source server support option in the General section.
You might also want to uncheck the Enable Just My Code option to avoid that you'll have initiate the loading of the symbol files manually via the 
Modules window in Visual Studio:
Next to that, Visual Studio also needs to know where the symbols that are exposed can be found. This is done by adding the URL that exposes your symbols as a symbol location in Visual Studio:

Now, everything should be in place to be able to debug through the source of an external library, as we'll see in the next section.

In Action

When everything is setup correctly, you should now be able to step through the code of an external library.

As an example, I have a little program called AgeCalculator that uses a simple NuGet package AgeUtils.Lib for which I have exposed its symbols:

While debugging the program, you can see in the Modules window of Visual Studio that symbols for the external dll AgeUtils.Lib have been loaded.  This means that Visual Studio has found the pdb file that matches the version of the AgeUtils.Lib assembly that is currently in use.

When a line of code is encountered where functionality from the NuGet package is called, you can just step into it.
As can be seen in the Output Window, Visual Studio attempts to download the correct version of the Age.cs source code file from the source-repository. 

The debugger knows how this file is named, which version is required and where it can be found since all information is present in the pdb file that it has downloaded from the symbol server!

When the debugger attempts to retrieve the correct code-file, you'll need to enter some credentials.  Once this is done, the source-file is downloaded and you'll be able to step through it:

Now, you'll be able to find out why that external library isn't working as expected! :)

Happy debugging!

Frederik
Categories: Technology
Tags: Debugging
written by: Frederik Gheysels