если 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");
}