Где Visual Studio получает хэш для моей DLL для поиска символов? - PullRequest
0 голосов
/ 21 ноября 2018

Я настраиваю наш частный сервер символов.Все отлично работает.Обратите внимание на следующий журнал Resharper, когда я отлаживаю в одном из наших пакетов Nuget с помощью сервера символов:

Поиск источников типа 'ClassLibrary1.Class1' в C: \ SNIPPED \ SymbolCache \ ClassLibrary1.pdb \ 91180103b9def6ca85f41230aaf9a4611ClassLibrary1.pdb
Загрузчик: https: //LOCAL_SYMBOL_SVR/app/sources/builds/id-1641/sources/files/ClassLibrary1/Class1.cs -> хорошо, 268 байт

См.хэш, 91180103b9def6ca85f41230aaf9a4611?Обратите внимание, что это 33 цифры.

Я полагал, что это может быть сохранено в PE-заголовке, но dumpbin.exe /all DLL не содержит хеш-код в своих выходных данных.

Откуда взялся этот хеш?Хранится ли в DLL где-нибудь?Если да, то как и где он хранится?

1 Ответ

0 голосов
/ 21 ноября 2018

если PE построить с отладочной информацией - должно существовать IMAGE_DEBUG_DIRECTORY в нем с IMAGE_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 и age as %08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X%x

dwSig должен равняться 'SDSR' и szPdb, хранящимся как пример строкового кода utf8:

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");
}
...