0

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.

PoomaniGP
  • 80
  • 1
  • 1
  • 11
  • You can write a program to query your pdb files against the source files, here's a link to an example of the [Debug Interface Access SDK](https://learn.microsoft.com/en-us/visualstudio/debugger/debug-interface-access/idiasourcefile?view=vs-2022). You can compare `IDiaSourceFile::get_checksum` with a checksum of each of your source files. – user20716902 Jul 14 '23 at 10:06
  • Wrong approach. To do better than msbuild you have to inspect the dependencies, focusing on public types exposed by an assembly. Reading them is made easy with Roslyn. – Hans Passant Jul 14 '23 at 13:08
  • You can take a look of my answer, I write code based on System.Reflection.Metadata. As I understand, if you only use pdb, it should be not enough to compare and 100% sure the source file are same. – Bowman Zhu-MSFT Jul 18 '23 at 08:32
  • Hi, any update of this case? :) – Bowman Zhu-MSFT Jul 25 '23 at 06:48

2 Answers2

0

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."

user20716902
  • 861
  • 1
  • 14
0

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.

Bowman Zhu-MSFT
  • 4,776
  • 1
  • 9
  • 10