Files

206 lines
6.4 KiB
C

#define _CRT_SECURE_NO_WARNINGS
#include "Pdb.h"
#include <conio.h>
#include <Strsafe.h>
#include <Dbghelp.h>
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#define RSDS_SIGNATURE 'SDSR'
#define PDB_MAX_SYMBOL_SIZE 1000
//Only for PDB2.0 format!
struct CV_INFO_PDB20{
DWORD CvSignature;
DWORD Offset;
DWORD Signature;
DWORD Age;
BYTE PdbFileName[MAX_PATH];
};
//Only for PDB7.0 format!
typedef struct _CV_INFO_PDB70{
DWORD CvSignature;
GUID Signature;
DWORD Age;
BYTE PdbFileName[MAX_PATH];
} CV_INFO_PDB70;
typedef struct _PdbCtxt_T{
HANDLE hProcess;
void* pModuleBase;
ULONG ModuleSize;
}PdbCtxt_T;
//------------------------------------------------------------------------------
BOOL WINAPI GetModulePdbInfo(HANDLE hProcess, VOID* pModuleBase, CV_INFO_PDB70* pPdb70Info)
{
UCHAR* pBase = (UCHAR*)pModuleBase;
IMAGE_DOS_HEADER ImageDosHeader;
IMAGE_NT_HEADERS ImageNtHeaders;
IMAGE_DEBUG_DIRECTORY ImageDebugDirectory;
BOOL bResult = FALSE;
#ifdef _WIN64
BOOL bWow64;
IMAGE_NT_HEADERS32 ImageNtHeaders32;
if (hProcess==NULL) hProcess = GetCurrentProcess();
if (!IsWow64Process(hProcess, &bWow64)) goto End;
if (bWow64==TRUE)
{
if (!ReadProcessMemory(hProcess, pModuleBase, &ImageDosHeader, sizeof(ImageDosHeader), NULL)) goto End;
if (!ReadProcessMemory(hProcess, pBase + ImageDosHeader.e_lfanew, &ImageNtHeaders32, sizeof(ImageNtHeaders32), NULL)) goto End;
if (!ReadProcessMemory(hProcess, pBase + ImageNtHeaders32.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress, &ImageDebugDirectory, sizeof(ImageDebugDirectory), NULL)) goto End;
if (!ReadProcessMemory(hProcess, pBase + ImageDebugDirectory.AddressOfRawData, pPdb70Info, sizeof(*pPdb70Info), NULL)) goto End;
}
else
#endif
{
if (!ReadProcessMemory(hProcess, pModuleBase, &ImageDosHeader, sizeof(ImageDosHeader), NULL)) goto End;
if (!ReadProcessMemory(hProcess, pBase + ImageDosHeader.e_lfanew, &ImageNtHeaders, sizeof(ImageNtHeaders), NULL)) goto End;
if (!ReadProcessMemory(hProcess, pBase + ImageNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress, &ImageDebugDirectory, sizeof(ImageDebugDirectory), NULL)) goto End;
if (!ReadProcessMemory(hProcess, pBase + ImageDebugDirectory.AddressOfRawData, pPdb70Info, sizeof(*pPdb70Info), NULL)) goto End;
}
if (pPdb70Info->CvSignature != RSDS_SIGNATURE )
{
_cprintf("Invalid CvSignature");
goto End;
}
bResult = TRUE;
End:
return (bResult);
}
//------------------------------------------------------------------------------
BOOL WINAPI GetPdbFilePath(HANDLE hProcess, VOID* pModuleBase, UCHAR* pPdbPath, UINT PdbPathSize)
{
CV_INFO_PDB70 Pdb70Info;
CHAR SymbolPath[MAX_PATH] = { 0 };
CHAR NtSymbolPath[MAX_PATH] = { 0 };
BOOL bResult = FALSE;
if (!GetModulePdbInfo(hProcess, pModuleBase, &Pdb70Info)) goto End;
/*
if (!SymFindFileInPath(hProcess, "c:\\symbols\\", Pdb70Info.PdbFileName, &Pdb70Info.Signature, Pdb70Info.Age, 0, SSRVOPT_GUIDPTR, pPdbPath, NULL, NULL))
{
printf("SymFindFileInPath failed %u\n", GetLastError());
goto End;
}
*/
if (strchr((char*)Pdb70Info.PdbFileName, '\\') != NULL)
{
StringCbPrintfA((STRSAFE_LPSTR)pPdbPath, PdbPathSize, "%hs", Pdb70Info.PdbFileName);
}
else
{
int iResult;
char* pStar = NULL;
if (GetEnvironmentVariableA("RpcViewSymbolPath", NtSymbolPath, sizeof(NtSymbolPath)) == 0)
{
if (GetEnvironmentVariableA("_NT_SYMBOL_PATH", NtSymbolPath, sizeof(NtSymbolPath)) == 0) goto End;
}
iResult = sscanf(NtSymbolPath, "srv*%259s", SymbolPath);
if (iResult == 0) goto End;
pStar = strchr(SymbolPath+4, '*');
if (pStar != NULL) *pStar = 0;
StringCbPrintfA((STRSAFE_LPSTR)pPdbPath, PdbPathSize, "%s\\%s\\%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X%X\\%s",
SymbolPath,
Pdb70Info.PdbFileName,
Pdb70Info.Signature.Data1,
Pdb70Info.Signature.Data2,
Pdb70Info.Signature.Data3,
Pdb70Info.Signature.Data4[0],
Pdb70Info.Signature.Data4[1],
Pdb70Info.Signature.Data4[2],
Pdb70Info.Signature.Data4[3],
Pdb70Info.Signature.Data4[4],
Pdb70Info.Signature.Data4[5],
Pdb70Info.Signature.Data4[6],
Pdb70Info.Signature.Data4[7],
Pdb70Info.Age,
Pdb70Info.PdbFileName
);
}
bResult = TRUE;
End:
return (bResult);
}
//------------------------------------------------------------------------------
__checkReturn void* WINAPI PdbInit(__in HANDLE hProcess, __in VOID* pModuleBase, __in UINT ModuleSize)
{
UCHAR PdbPath[MAX_PATH];
PdbCtxt_T* pPdbCtxt = NULL;
if (!SymInitialize(hProcess, NULL, FALSE)) goto End;
if (!GetPdbFilePath(hProcess, pModuleBase, PdbPath, sizeof(PdbPath))) goto End;
if (!SymLoadModule64(hProcess, NULL, (STRSAFE_LPCSTR)PdbPath, NULL,(DWORD64) pModuleBase, ModuleSize))
{
printf("SymLoadModule64 failed\n");
SymCleanup(hProcess);
goto End;
}
//
// All is ok, so we can allocate and init the PDB private context
//
pPdbCtxt = (PdbCtxt_T*)malloc(sizeof(PdbCtxt_T));
if (pPdbCtxt!=NULL)
{
ZeroMemory(pPdbCtxt, sizeof(PdbCtxt_T));
pPdbCtxt->hProcess = hProcess;
pPdbCtxt->ModuleSize = ModuleSize;
pPdbCtxt->pModuleBase = pModuleBase;
}
End:
return (pPdbCtxt);
}
//------------------------------------------------------------------------------
__checkReturn BOOL WINAPI PdbGetSymbolName(__in void* hCtxt, __in VOID* pSymbol, __out WCHAR* pName, __in UINT NameLength)
{
BOOL bResult = FALSE;
IMAGEHLP_SYMBOL64* pSymbolInfo = NULL;
DWORD64 dwDisp = 0;
PdbCtxt_T* pPdbCtxt = (PdbCtxt_T*)hCtxt;
if (pPdbCtxt==NULL) goto End;
pSymbolInfo=(IMAGEHLP_SYMBOL64*)malloc( PDB_MAX_SYMBOL_SIZE );
if (pSymbolInfo==NULL) goto End;
ZeroMemory(pSymbolInfo, PDB_MAX_SYMBOL_SIZE);
pSymbolInfo->MaxNameLength = NameLength;
pSymbolInfo->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
bResult = SymGetSymFromAddr64( pPdbCtxt->hProcess, (DWORD64)pSymbol, &dwDisp, pSymbolInfo);
if (!bResult) goto End;
if (dwDisp!=0) goto End;
StringCbPrintfW(pName,NameLength,L"%S",pSymbolInfo->Name);
End:
if (pSymbolInfo!=NULL) free(pSymbolInfo);
return (bResult);
}
//------------------------------------------------------------------------------
void WINAPI PdbUninit(__in void* hCtxt)
{
PdbCtxt_T* pPdbCtxt = (PdbCtxt_T*)hCtxt;
if (pPdbCtxt==NULL) goto End;
SymUnloadModule64(pPdbCtxt->hProcess,(DWORD64)pPdbCtxt->pModuleBase);
free(pPdbCtxt);
End:
return;
}