Skip to content

Commit

Permalink
Refactor PDB data loading via IStream, explicit file access.
Browse files Browse the repository at this point in the history
  • Loading branch information
ZehMatt authored and mrexodia committed Jul 1, 2018
1 parent c8af1f9 commit cad8aed
Show file tree
Hide file tree
Showing 2 changed files with 183 additions and 8 deletions.
190 changes: 182 additions & 8 deletions src/dbg/pdbdiafile.cpp
Expand Up @@ -3,6 +3,7 @@
#include <windows.h>
#include <thread>
#include <atomic>
#include <mutex>
#include <algorithm>

#include "msdia/dia2.h"
Expand Down Expand Up @@ -86,6 +87,116 @@ class DiaLoadCallback : public IDiaLoadCallback2
}
};

class DiaFileStream : public IStream
{
private:
HANDLE _hFile;

public:
DiaFileStream(HANDLE hFile)
{
_hFile = hFile;
}

~DiaFileStream()
{
if(_hFile != INVALID_HANDLE_VALUE)
{
::CloseHandle(_hFile);
}
}

public:
HRESULT static OpenFile(LPCWSTR pName, IStream** ppStream)
{
HANDLE hFile = ::CreateFileW(pName, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

if(hFile == INVALID_HANDLE_VALUE)
return HRESULT_FROM_WIN32(GetLastError());

DiaFileStream* out = new DiaFileStream(hFile);
*ppStream = out;

if(*ppStream == NULL)
CloseHandle(hFile);

return S_OK;
}

virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject)
{
if(iid == __uuidof(IUnknown)
|| iid == __uuidof(IStream)
|| iid == __uuidof(ISequentialStream))
{
*ppvObject = static_cast<IStream*>(this);
return S_OK;
}
else
return E_NOINTERFACE;
}

virtual ULONG STDMETHODCALLTYPE AddRef(void)
{
return 1;
}

virtual ULONG STDMETHODCALLTYPE Release(void)
{
return 1;
}

virtual HRESULT STDMETHODCALLTYPE Read(void* pv, ULONG cb, ULONG* pcbRead)
{
BOOL rc = ReadFile(_hFile, pv, cb, pcbRead, NULL);
return (rc) ? S_OK : HRESULT_FROM_WIN32(GetLastError());
}

virtual HRESULT STDMETHODCALLTYPE Seek(LARGE_INTEGER liDistanceToMove, DWORD dwOrigin,
ULARGE_INTEGER* lpNewFilePointer)
{
DWORD dwMoveMethod;

switch(dwOrigin)
{
case STREAM_SEEK_SET:
dwMoveMethod = FILE_BEGIN;
break;
case STREAM_SEEK_CUR:
dwMoveMethod = FILE_CURRENT;
break;
case STREAM_SEEK_END:
dwMoveMethod = FILE_END;
break;
default:
return STG_E_INVALIDFUNCTION;
break;
}

if(SetFilePointerEx(_hFile, liDistanceToMove, (PLARGE_INTEGER)lpNewFilePointer,
dwMoveMethod) == 0)
return HRESULT_FROM_WIN32(GetLastError());
return S_OK;
}

virtual HRESULT STDMETHODCALLTYPE Stat(STATSTG* pStatstg, DWORD grfStatFlag)
{
if(GetFileSizeEx(_hFile, (PLARGE_INTEGER)&pStatstg->cbSize) == 0)
return HRESULT_FROM_WIN32(GetLastError());
return S_OK;
}

virtual HRESULT STDMETHODCALLTYPE Write(void const* pv, ULONG cb, ULONG* pcbWritten) {return E_NOTIMPL;}
virtual HRESULT STDMETHODCALLTYPE SetSize(ULARGE_INTEGER) { return E_NOTIMPL; }
virtual HRESULT STDMETHODCALLTYPE CopyTo(IStream*, ULARGE_INTEGER, ULARGE_INTEGER*, ULARGE_INTEGER*) { return E_NOTIMPL; }
virtual HRESULT STDMETHODCALLTYPE Commit(DWORD) { return E_NOTIMPL; }
virtual HRESULT STDMETHODCALLTYPE Revert(void) { return E_NOTIMPL; }
virtual HRESULT STDMETHODCALLTYPE LockRegion(ULARGE_INTEGER, ULARGE_INTEGER, DWORD) { return E_NOTIMPL; }
virtual HRESULT STDMETHODCALLTYPE UnlockRegion(ULARGE_INTEGER, ULARGE_INTEGER, DWORD) { return E_NOTIMPL; }
virtual HRESULT STDMETHODCALLTYPE Clone(IStream**) { return E_NOTIMPL; }
};

volatile LONG PDBDiaFile::m_sbInitialized = 0;

template<typename T>
Expand Down Expand Up @@ -118,6 +229,7 @@ typedef ScopedDiaType<IDiaSymbol> ScopedDiaSymbol;
typedef ScopedDiaType<IDiaEnumSymbols> ScopedDiaEnumSymbols;

PDBDiaFile::PDBDiaFile() :
m_stream(nullptr),
m_dataSource(nullptr),
m_session(nullptr)
{
Expand Down Expand Up @@ -162,6 +274,14 @@ bool PDBDiaFile::open(const char* file, uint64_t loadAddress, DiaValidationData_

bool PDBDiaFile::open(const wchar_t* file, uint64_t loadAddress, DiaValidationData_t* validationData)
{
if(isOpen())
{
#if 1 // Enable for validation purpose.
__debugbreak();
#endif
return false;
}

wchar_t fileExt[MAX_PATH] = { 0 };
wchar_t fileDir[MAX_PATH] = { 0 };

Expand Down Expand Up @@ -194,27 +314,30 @@ bool PDBDiaFile::open(const wchar_t* file, uint64_t loadAddress, DiaValidationDa

if(_wcsicmp(fileExt, L".pdb") == 0)
{
hr = DiaFileStream::OpenFile(file, &m_stream);
if(testError(hr))
{
GuiSymbolLogAdd("Unable to open PDB file.\n");
return false;
}

if(validationData != nullptr)
{
hr = m_dataSource->loadAndValidateDataFromPdb(file, &validationData->guid, validationData->signature, validationData->age);
if((hr == E_PDB_INVALID_SIG) || (hr == E_PDB_INVALID_AGE))
{
GuiSymbolLogAdd("PDB is not matching.\n");
return false;
}
else if(hr == E_PDB_FORMAT)
hr = m_dataSource->loadDataFromIStream(m_stream);
if(hr == E_PDB_FORMAT)
{
GuiSymbolLogAdd("PDB uses an obsolete format.\n");
return false;
}
}
else
{
hr = m_dataSource->loadDataFromPdb(file);
hr = m_dataSource->loadDataFromIStream(m_stream);
}
}
else
{
// NOTE: Unsupported use with IStream.
DiaLoadCallback callback;
hr = m_dataSource->loadDataForExe(file, fileDir, &callback);
}
Expand All @@ -235,6 +358,51 @@ bool PDBDiaFile::open(const wchar_t* file, uint64_t loadAddress, DiaValidationDa
return false;
}

if(validationData != nullptr)
{
ScopedDiaType<IDiaSymbol> globalSym;
hr = m_session->get_globalScope(globalSym.ref());
if(testError(hr))
{
//??
}
else
{
DWORD age = 0;
hr = globalSym->get_age(&age);
if(!testError(hr) && validationData->age != age)
{
close();

GuiSymbolLogAdd("PDB age is not matching.\n");
return false;
}

// NOTE: For some reason this never matches, commented for now.
/*
DWORD signature = 0;
hr = globalSym->get_signature(&signature);
if (!testError(hr) && validationData->signature != signature)
{
close();
GuiSymbolLogAdd("PDB is not matching.\n");
return false;
}
*/

GUID guid = {0};
hr = globalSym->get_guid(&guid);
if(!testError(hr) && memcmp(&guid, &validationData->guid, sizeof(GUID)) != 0)
{
close();

GuiSymbolLogAdd("PDB guid is not matching.\n");
return false;
}
}
}

if(loadAddress != 0)
{
m_session->put_loadAddress(loadAddress);
Expand All @@ -255,6 +423,12 @@ bool PDBDiaFile::close()
if(m_session == nullptr)
return false;

if(m_stream != nullptr)
{
delete(DiaFileStream*)m_stream;
m_stream = nullptr;
}

m_session->Release();
m_dataSource->Release();
m_session = nullptr;
Expand Down
1 change: 1 addition & 0 deletions src/dbg/pdbdiafile.h
Expand Up @@ -33,6 +33,7 @@ class PDBDiaFile
static volatile long m_sbInitialized;

private:
IStream* m_stream;
IDiaDataSource* m_dataSource;
IDiaSession* m_session;

Expand Down

0 comments on commit cad8aed

Please sign in to comment.