Что означают имена каталогов, такие как D0C3BDDD4ADD4E87B2B5E803303B8D772 в кеше символов Visual Studio?

У меня есть каталог кеша символа, установленный в D:\symbols в параметрах Visual Studio:

Options

В этом каталоге Visual Studio создает иерархию с каталогами верхнего уровня, соответствующими именам файлов PDB (например, ole32.pdb), на следующем уровне находятся один или несколько каталогов, таких как D0C3BDDD4ADD4E87B2B5E803303B8D772 (выглядящие как 33-значные шестнадцатеричные числа) и внутри них сами файлы PDB, по-видимому, загружаются с серверов Microsoft Symbol.

Я предполагаю, что эти шестнадцатеричные числа представляют версии файлов PDB. Интересно, имеют ли эти цифры какую-либо структуру или значение, и как их можно извлечь из файлов PDB (в идеале, используя С#)?

Учитывая файл PDB в другой папке, можно ли найти каталог в кеше символов, в котором отладчик Visual Studio будет искать его?

Ответы

Ответ 1

Первые 32 цифры - это всего лишь GUID, который выпекается как в файл PE (DLL, EXE,...), так и соответствующий PDB, следующие цифры - это так называемый возраст в шестнадцатеричном представлении без начальных нулей (он может быть увеличен во время процесса сборки путем связывания, подписания и т.д.). В большинстве случаев возраст вписывается в одну шестую цифру, поэтому всего 33 цифры, иногда называемые сигнатурой. Вы можете извлечь подпись из файла PDB с помощью SDK для доступа к интерфейсу отладки. Пример в С#:

using System;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;

static class Program
{
    // Pass a PDB file name as a command-line parameter
    static void Main(string[] args)
    {
        var pdbFile = args.FirstOrDefault();
        if (!File.Exists(pdbFile))
            return;

        try
        {
            var dataSource = (IDiaDataSource)Activator.CreateInstance(Marshal.GetTypeFromCLSID(new Guid("83AB22C8-993A-4D14-A0E0-37BC0AAEA793")));
            dataSource.LoadDataFromPdb(pdbFile);

            IDiaSession session;
            dataSource.OpenSession(out session);

            var globalScope = session.GlobalScope;
            Console.WriteLine(globalScope.Guid.ToString("N").ToUpperInvariant() + globalScope.Age.ToString("X"));
        }
        catch (COMException) { } // May happen for corrupted PDB files
    }
}


[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("79F1BB5F-B66E-48E5-B6A9-1545C323CA3D")]
interface IDiaDataSource
{
    void _VtblGap_1();
    void LoadDataFromPdb(string pdbFile);
    void _VtblGap_3();
    void OpenSession(out IDiaSession session);
}

[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("6FC5D63F-011E-40C2-8DD2-E6486E9D6B68")]
interface IDiaSession
{
    void _VtblGap_2();
    IDiaSymbol GlobalScope { get; }
}

[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("CB787B2F-BD6C-4635-BA52-933126BD2DCD")]
interface IDiaSymbol
{
    void _VtblGap_43();
    Guid Guid { get; }
    void _VtblGap_28();
    uint Age { get; }
}

Ответ 2

Это значение является идентификатором GUID, который встроен в сборку и файл символов, чтобы их можно было синхронизировать.

http://www.wintellect.com/blogs/jrobbins/pdb-files-what-every-developer-must-know

Вы можете запустить dumpbin /headers на своей сборке, чтобы увидеть встроенный GUID.