skip to Main Content

I want to validate if there is source code difference occurred between two builds with help of .pdb files generated from Build1 and Build2.

Little Background :

I am using Visual Studio 2019 and My solution has a mix of .NET Framework, .NET Core projects summing up to 50 projects. I want a mechanism to validate if the source code has changed between two builds by comparing the .dll’s and/or .pdb’s from build1 and build2.

Note : The environment under which the source codes are built is the same.

What I want to achieve :

Whenever source code changes from versionX to versionY, Computer 1 builds the whole solution result of which is 50 dll’s and 50 pdb’s.
I want to skip the building process and copy only the changed dll’s and pdb’s and port it to Computer 2 after of checking out the source code to versionY to save time.

So, the tool I’m looking for should be capable of doing the following operations :

Compare two pdb’s output ‘true’ if the source code matches, ‘false’ is there seems to difference in source code. Plus: The tool can make use of the dll’s also.

2

Answers


  1. You can use the Debug Interface Access SDK to achieve what you require.

    Specifcally MS provide an example using IDiaDataSource::loadAndValidateDataFromPdb

    Quote from MS site: "A .pdb file contains both signature and age values. These values are replicated in the .exe or .dll file that matches the .pdb file. Before preparing the data source, this method verifies that the named .pdb file’s signature and age match the values provided."

    Login or Signup to reply.
  2. As the official document says:

    How symbol files work

    The pdb file contains the below information:

    The source file name and line number to display in the Visual Studio
    IDE.

    Where in the app to stop for a breakpoint.

    So I think the pdb will not be able to compare whether the source file of them are same. Because the content of it doesn’t have enough information.

    But you can still get an approximate result (based on line number and offset).

    Below is a console app sample for you to achieve your requirement(I am based on System.Reflection.Metadata):

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Reflection.Metadata;
    using System.Reflection.Metadata.Ecma335;
    
    class Program
    {
        static void Main(string[] args)
        {
            var pdbFile1 = "C:\Users\Administrator\source\repos\Blazor-WebAssembly-by-Example\Chapter09\ConsoleApp1\ConsoleApp1.pdb";
            var pdbFile2 = "C:\Users\Administrator\source\repos\Blazor-WebAssembly-by-Example\Chapter09\ConsoleApp1\test\ConsoleApp1.pdb";
            var diff_pdb = "C:\Users\Administrator\source\repos\Blazor-WebAssembly-by-Example\Chapter09\ConsoleApp1\bin\Debug\net6.0\ConsoleApp1.pdb";
    
            var sequencePoints1 = GetSequencePoints(pdbFile1);
            var sequencePoints2 = GetSequencePoints(diff_pdb);
    
            var areEqual = CompareSequencePoints(sequencePoints1, sequencePoints2);
            Console.WriteLine($"Are sequence points equal: {areEqual}");
        }
    
        static List<SequencePoint> GetSequencePoints(string pdbFilePath)
        {
            var sequencePoints = new List<SequencePoint>();
    
            using (var stream = File.OpenRead(pdbFilePath))
            {
                var pdbReaderProvider = MetadataReaderProvider.FromPortablePdbStream(stream);
                var pdbReader = pdbReaderProvider.GetMetadataReader();
                foreach (var methodDebugHandle in pdbReader.MethodDebugInformation)
                {
                    var methodDebugInformation = pdbReader.GetMethodDebugInformation(methodDebugHandle);
                    var sequencePointsForMethod = methodDebugInformation.GetSequencePoints();
                    sequencePoints.AddRange(sequencePointsForMethod);
                }
            }
    
            return sequencePoints;
        }
    
        static bool CompareSequencePoints(List<SequencePoint> sequencePoints1, List<SequencePoint> sequencePoints2)
        {
            if (sequencePoints1.Count != sequencePoints2.Count)
            {
                return false;
            }
    
            for (int i = 0; i < sequencePoints1.Count; i++)
            {
                if (sequencePoints1[i].StartLine != sequencePoints2[i].StartLine ||
                    sequencePoints1[i].EndLine != sequencePoints2[i].EndLine ||
                    sequencePoints1[i].Offset != sequencePoints2[i].Offset)
                {
                    return false;
                }
            }
    
            return true;
        }
    }
    

    The above code should be able to run directly.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search