首页 > 解决方案 > Visual Studio 在哪里获取用于查找符号的 DLL 的哈希?

问题描述

我正在设置我们的私有符号服务器。一切都很好。当我使用符号服务器调试我们的 Nuget 包之一时,请观察以下 Resharper 日志:

在 C:\SNIPPED\SymbolCache\ClassLibrary1.pdb\91180103b9def6ca85f41230aaf9a4611\ClassLibrary1.pdb 中搜索“ClassLibrary1.Class1”类型源
下载器:https://LOCAL_SYMBOL_SVR/app/sources/builds/id-1641/sources/files/ClassLibrary1/ Class1.cs -> 好的,268 字节

看到哈希,91180103b9def6ca85f41230aaf9a4611?请注意,它是 33 位数字。

我认为它可能存储在 PE 标头中,但dumpbin.exe /all DLL在其输出中不包含散列。

那个哈希是从哪里来的?它是否存储DLL 中的某个地方?如果是这样,它是如何以及在哪里存储的?

标签: visual-studiodebuggingdebug-symbolssymbol-server

解决方案


如果PE构建带有调试信息 - 必须IMAGE_DEBUG_DIRECTORYIMAGE_DEBUG_TYPE_CODEVIEW. 所以首先调试器搜索IMAGE_DEBUG_DIRECTORY元素数组(它可以是多个)。该数组位于IMAGE_DIRECTORY_ENTRY_DEBUG数据目录中。调试信息IMAGE_DEBUG_TYPE_CODEVIEW现在位于格式RSDS

struct RSDSI                       // RSDS debug info
{
    DWORD   dwSig;                 // RSDSI
    GUID    guidSig;
    DWORD   age;
    char    szPdb[];
};

你所谓的“哈希”这实际上不是从guidSig年龄形成的哈希%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X%x

dwSig必须等于'SDSR'并存储为szPdbutf8 字符串代码示例:

ULONG FormatPdbPath(PWSTR* ppdbPath, PCWSTR SymbolsPath, PCSTR PdbFileName, LPGUID Signature, DWORD Age)
{
    ULONG UTF8StringByteCount = (ULONG)strlen(PdbFileName) + 1;

    ULONG UnicodeStringLen = MultiByteToWideChar(CP_UTF8, 0, PdbFileName, UTF8StringByteCount, 0, 0);

    if (!UnicodeStringLen)
    {
        return ERROR_GEN_FAILURE;
    }

    if (UnicodeStringLen >= MAXSHORT)
    {
        return ERROR_FILENAME_EXCED_RANGE;
    }

    PWSTR FileName = (PWSTR)alloca(UnicodeStringLen * sizeof(WCHAR));

    UnicodeStringLen = MultiByteToWideChar(CP_UTF8, 0, PdbFileName, UTF8StringByteCount, FileName, UnicodeStringLen);

    if (!UnicodeStringLen)
    {
        return ERROR_GEN_FAILURE;
    }

    if (PWSTR pdbPath = new WCHAR[2 * UnicodeStringLen + wcslen(SymbolsPath) + 42])
    {
        *ppdbPath = pdbPath;

        swprintf(pdbPath, L"%s\\%s\\%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X%x\\%s", 
            SymbolsPath, FileName, 
            Signature->Data1, Signature->Data2, Signature->Data3,
            Signature->Data4[0], Signature->Data4[1], Signature->Data4[2], Signature->Data4[3], 
            Signature->Data4[4], Signature->Data4[5], Signature->Data4[6], Signature->Data4[7], 
            Age, FileName);

        return NOERROR;
    }

    return ERROR_NO_SYSTEM_RESOURCES;
}

ULONG FormatPdbPath(PWSTR* ppdbPath, PCWSTR SymbolsPath, PCWSTR lpszName)
{
    HMODULE hmod = LoadLibraryExW(lpszName, 0, LOAD_LIBRARY_AS_DATAFILE);

    if (!hmod) return GetLastError();

    ULONG status = ERROR_NOT_FOUND;

    DWORD cb;
    BOOLEAN bMappedAsImage = !((DWORD_PTR)hmod & (PAGE_SIZE - 1));

    PIMAGE_DEBUG_DIRECTORY pidd = (PIMAGE_DEBUG_DIRECTORY)RtlImageDirectoryEntryToData(hmod, bMappedAsImage, IMAGE_DIRECTORY_ENTRY_DEBUG, &cb);

    if (pidd && cb && !(cb % sizeof(IMAGE_DEBUG_DIRECTORY)))
    {
        do 
        {
            struct RSDSI                       // RSDS debug info
            {
                DWORD   dwSig;                 // RSDSI
                GUID    guidSig;
                DWORD   age;
                char    szPdb[];
            };

            if (pidd->Type == IMAGE_DEBUG_TYPE_CODEVIEW && pidd->SizeOfData > sizeof(RSDSI))
            {
                if (DWORD PointerToRawData = bMappedAsImage ? pidd->AddressOfRawData : pidd->PointerToRawData)
                {
                    RSDSI* lpcvh = (RSDSI*)RtlOffsetToPointer(PAGE_ALIGN(hmod), PointerToRawData);

                    if (lpcvh->dwSig == 'SDSR')
                    {
                        PCSTR szPdb = lpcvh->szPdb, c = strrchr(szPdb, L'\\');

                        if (c)
                        {
                            szPdb = c + 1;
                        }

                        status = FormatPdbPath(ppdbPath, SymbolsPath, szPdb, &lpcvh->guidSig, lpcvh->age);

                        break;
                    }
                }
            }

        } while (pidd++, cb -= sizeof(IMAGE_DEBUG_DIRECTORY));
    }

    FreeLibrary(hmod);

    return status;
}

void test(PCWSTR SymbolsPath, PCWSTR lpszName)
{
    PWSTR pdbPath;
    if (!FormatPdbPath(&pdbPath, SymbolsPath, lpszName))
    {
        DbgPrint("%S\n", pdbPath);
        delete [] pdbPath;
    }
}

void test2(PCWSTR SymbolsPath = L"C:\\SNIPPED\\SymbolCache")
{
    WCHAR myExe[MAX_PATH];
    GetModuleFileNameW(0, myExe, RTL_NUMBER_OF(myExe));
    test(SymbolsPath, myExe);
    test(SymbolsPath, L"hal.dll");
    test(SymbolsPath, L"drivers/ntfs.sys");
    test(SymbolsPath, L"kernel32.dll");
}

推荐阅读