mirror of
https://github.com/ivellioscolin/pykd.git
synced 2025-04-20 03:23:23 +08:00
[0.2.x] added facade for retrieving symbol information
git-svn-id: https://pykd.svn.codeplex.com/svn@78409 9b283d60-5439-405e-af05-b73fd8c4d996
This commit is contained in:
parent
73478dc355
commit
9cbbbb7ea6
@ -13,9 +13,12 @@ void debugGo();
|
||||
ULONG64 findModuleBase( const std::string &moduleName );
|
||||
ULONG64 findModuleBase( ULONG64 offset );
|
||||
std::string getModuleName( ULONG64 baseOffset );
|
||||
std::string getModuleSymbolFileName( ULONG64 baseOffset );
|
||||
|
||||
//manage access to target memory
|
||||
ULONG64 addr64( ULONG64 offset );
|
||||
|
||||
void readMemory( ULONG64 offset, PVOID buffer, ULONG length, bool phyAddr = FALSE );
|
||||
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include "stdafx.h"
|
||||
#include "dbgexcept.h"
|
||||
#include "diawrapper.h"
|
||||
//#include "diawrapper.h"
|
||||
|
||||
namespace pykd {
|
||||
|
||||
@ -11,7 +11,7 @@ python::handle<> exceptPyType<DbgException>::pyExceptType;
|
||||
python::handle<> exceptPyType<MemoryException>::pyExceptType;
|
||||
python::handle<> exceptPyType<WaitEventException>::pyExceptType;
|
||||
python::handle<> exceptPyType<SymbolException>::pyExceptType;
|
||||
python::handle<> exceptPyType<pyDia::Exception>::pyExceptType;
|
||||
//python::handle<> exceptPyType<pyDia::Exception>::pyExceptType;
|
||||
python::handle<> exceptPyType<TypeException>::pyExceptType;
|
||||
python::handle<> exceptPyType<AddSyntheticSymbolException>::pyExceptType;
|
||||
python::handle<> exceptPyType<ImplementException>::pyExceptType;
|
||||
|
@ -7,19 +7,14 @@
|
||||
|
||||
namespace pykd {
|
||||
|
||||
|
||||
template< class TExcept >
|
||||
struct exceptPyType{
|
||||
|
||||
static python::handle<> pyExceptType;
|
||||
|
||||
static python::handle<> pyExceptType;
|
||||
};
|
||||
|
||||
|
||||
template< class TExcept, class TBaseExcept = python::detail::not_specified >
|
||||
class exception {
|
||||
|
||||
|
||||
public:
|
||||
|
||||
exception( const std::string& className, const std::string& classDesc )
|
||||
|
1433
pykd/dbgmem.cpp
1433
pykd/dbgmem.cpp
File diff suppressed because it is too large
Load Diff
226
pykd/dbgmem.h
226
pykd/dbgmem.h
@ -4,104 +4,154 @@ namespace pykd {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ULONG64
|
||||
addr64( ULONG64 addr );
|
||||
|
||||
bool
|
||||
isVaValid( ULONG64 addr );
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
HRESULT readVirtual(
|
||||
IDebugDataSpaces4 *dbgDataSpace,
|
||||
ULONG64 address,
|
||||
PVOID buffer,
|
||||
ULONG length,
|
||||
PULONG readed
|
||||
);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void
|
||||
readMemory( IDebugDataSpaces4* dbgDataSpace, ULONG64 address, PVOID buffer, ULONG length, bool phyAddr = FALSE );
|
||||
|
||||
void
|
||||
readMemoryPtr( IDebugDataSpaces4* dbgDataSpace, ULONG64 address, PULONG64 ptrValue );
|
||||
|
||||
void
|
||||
writeMemory( IDebugDataSpaces4* dbgDataSpace, ULONG64 address, PVOID buffer, ULONG length, bool phyAddr = FALSE );
|
||||
|
||||
bool
|
||||
compareMemoryRange( IDebugDataSpaces4* dbgDataSpace, ULONG64 addr1, ULONG64 addr2, ULONG length, bool phyAddr = FALSE );
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string loadChars( ULONG64 address, ULONG number, bool phyAddr = FALSE );
|
||||
|
||||
std::wstring loadWChars( ULONG64 address, ULONG number, bool phyAddr = FALSE );
|
||||
|
||||
std::string loadCStr( ULONG64 offset );
|
||||
|
||||
std::wstring loadWStr( ULONG64 offset );
|
||||
|
||||
python::list loadBytes( ULONG64 offset, ULONG count, bool phyAddr = FALSE );
|
||||
|
||||
python::list loadWords( ULONG64 offset, ULONG count, bool phyAddr = FALSE );
|
||||
|
||||
python::list loadDWords( ULONG64 offset, ULONG count, bool phyAddr = FALSE );
|
||||
|
||||
python::list loadQWords( ULONG64 offset, ULONG count, bool phyAddr = FALSE );
|
||||
|
||||
python::list loadSignBytes( ULONG64 offset, ULONG count, bool phyAddr = FALSE );
|
||||
|
||||
python::list loadSignWords( ULONG64 offset, ULONG count, bool phyAddr = FALSE );
|
||||
|
||||
python::list loadSignDWords( ULONG64 offset, ULONG count, bool phyAddr = FALSE );
|
||||
|
||||
python::list loadSignQWords( ULONG64 offset, ULONG count, bool phyAddr = FALSE );
|
||||
|
||||
ULONG64 ptrByte( ULONG64 offset );
|
||||
|
||||
ULONG64 ptrWord( ULONG64 offset );
|
||||
|
||||
ULONG64 ptrDWord( ULONG64 offset );
|
||||
|
||||
ULONG64 ptrDWord( ULONG64 offset, IDebugDataSpaces4* dbgDataSpace );
|
||||
|
||||
ULONG64 ptrQWord( ULONG64 offset );
|
||||
|
||||
ULONG64 ptrQWord( ULONG64 offset, IDebugDataSpaces4* dbgDataSpace );
|
||||
|
||||
ULONG64 ptrMWord( ULONG64 offset );
|
||||
|
||||
ULONG64 ptrMWord( ULONG64 offset, IDebugDataSpaces4* dbgDataSpace );
|
||||
|
||||
LONG64 ptrSignByte( ULONG64 offset );
|
||||
|
||||
LONG64 ptrSignWord( ULONG64 offset );
|
||||
|
||||
LONG64 ptrSignDWord( ULONG64 offset );
|
||||
|
||||
LONG64 ptrSignQWord( ULONG64 offset );
|
||||
|
||||
LONG64 ptrSignMWord( ULONG64 offset );
|
||||
|
||||
ULONG64 ptrPtr( ULONG64 offset );
|
||||
|
||||
ULONG64 ptrPtr( ULONG64 offset, IDebugDataSpaces4* dbgDataSpace );
|
||||
|
||||
bool
|
||||
compareMemory( ULONG64 addr1, ULONG64 addr2, ULONG length, bool phyAddr = FALSE );
|
||||
|
||||
std::wstring loadUnicodeStr( ULONG64 address );
|
||||
|
||||
std::string loadAnsiStr( ULONG64 address );
|
||||
|
||||
python::list loadPtrList( ULONG64 address );
|
||||
|
||||
python::list loadPtrArray( ULONG64 address, ULONG number );
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
};
|
||||
}; // end pykd namespace
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//namespace pykd {
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//ULONG64
|
||||
//addr64( ULONG64 addr );
|
||||
//
|
||||
//bool
|
||||
//isVaValid( ULONG64 addr );
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//HRESULT readVirtual(
|
||||
// IDebugDataSpaces4 *dbgDataSpace,
|
||||
// ULONG64 address,
|
||||
// PVOID buffer,
|
||||
// ULONG length,
|
||||
// PULONG readed
|
||||
//);
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//void
|
||||
//readMemory( IDebugDataSpaces4* dbgDataSpace, ULONG64 address, PVOID buffer, ULONG length, bool phyAddr = FALSE );
|
||||
//
|
||||
//void
|
||||
//readMemoryPtr( IDebugDataSpaces4* dbgDataSpace, ULONG64 address, PULONG64 ptrValue );
|
||||
//
|
||||
//void
|
||||
//writeMemory( IDebugDataSpaces4* dbgDataSpace, ULONG64 address, PVOID buffer, ULONG length, bool phyAddr = FALSE );
|
||||
//
|
||||
//bool
|
||||
//compareMemoryRange( IDebugDataSpaces4* dbgDataSpace, ULONG64 addr1, ULONG64 addr2, ULONG length, bool phyAddr = FALSE );
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//std::string loadChars( ULONG64 address, ULONG number, bool phyAddr = FALSE );
|
||||
//
|
||||
//std::wstring loadWChars( ULONG64 address, ULONG number, bool phyAddr = FALSE );
|
||||
//
|
||||
//std::string loadCStr( ULONG64 offset );
|
||||
//
|
||||
//std::wstring loadWStr( ULONG64 offset );
|
||||
//
|
||||
//python::list loadBytes( ULONG64 offset, ULONG count, bool phyAddr = FALSE );
|
||||
//
|
||||
//python::list loadWords( ULONG64 offset, ULONG count, bool phyAddr = FALSE );
|
||||
//
|
||||
//python::list loadDWords( ULONG64 offset, ULONG count, bool phyAddr = FALSE );
|
||||
//
|
||||
//python::list loadQWords( ULONG64 offset, ULONG count, bool phyAddr = FALSE );
|
||||
//
|
||||
//python::list loadSignBytes( ULONG64 offset, ULONG count, bool phyAddr = FALSE );
|
||||
//
|
||||
//python::list loadSignWords( ULONG64 offset, ULONG count, bool phyAddr = FALSE );
|
||||
//
|
||||
//python::list loadSignDWords( ULONG64 offset, ULONG count, bool phyAddr = FALSE );
|
||||
//
|
||||
//python::list loadSignQWords( ULONG64 offset, ULONG count, bool phyAddr = FALSE );
|
||||
//
|
||||
//ULONG64 ptrByte( ULONG64 offset );
|
||||
//
|
||||
//ULONG64 ptrWord( ULONG64 offset );
|
||||
//
|
||||
//ULONG64 ptrDWord( ULONG64 offset );
|
||||
//
|
||||
//ULONG64 ptrDWord( ULONG64 offset, IDebugDataSpaces4* dbgDataSpace );
|
||||
//
|
||||
//ULONG64 ptrQWord( ULONG64 offset );
|
||||
//
|
||||
//ULONG64 ptrQWord( ULONG64 offset, IDebugDataSpaces4* dbgDataSpace );
|
||||
//
|
||||
//ULONG64 ptrMWord( ULONG64 offset );
|
||||
//
|
||||
//ULONG64 ptrMWord( ULONG64 offset, IDebugDataSpaces4* dbgDataSpace );
|
||||
//
|
||||
//LONG64 ptrSignByte( ULONG64 offset );
|
||||
//
|
||||
//LONG64 ptrSignWord( ULONG64 offset );
|
||||
//
|
||||
//LONG64 ptrSignDWord( ULONG64 offset );
|
||||
//
|
||||
//LONG64 ptrSignQWord( ULONG64 offset );
|
||||
//
|
||||
//LONG64 ptrSignMWord( ULONG64 offset );
|
||||
//
|
||||
//ULONG64 ptrPtr( ULONG64 offset );
|
||||
//
|
||||
//ULONG64 ptrPtr( ULONG64 offset, IDebugDataSpaces4* dbgDataSpace );
|
||||
//
|
||||
//bool
|
||||
//compareMemory( ULONG64 addr1, ULONG64 addr2, ULONG length, bool phyAddr = FALSE );
|
||||
//
|
||||
//std::wstring loadUnicodeStr( ULONG64 address );
|
||||
//
|
||||
//std::string loadAnsiStr( ULONG64 address );
|
||||
//
|
||||
//python::list loadPtrList( ULONG64 address );
|
||||
//
|
||||
//python::list loadPtrArray( ULONG64 address, ULONG number );
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//};
|
||||
|
||||
|
714
pykd/dia/diawrapper.cpp
Normal file
714
pykd/dia/diawrapper.cpp
Normal file
@ -0,0 +1,714 @@
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "dia/diawrapper.h"
|
||||
#include "win/utils.h"
|
||||
|
||||
namespace pykd {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const std::string DiaException::descPrefix("pyDia: ");
|
||||
|
||||
std::string DiaException::makeFullDesc(const std::string &desc, HRESULT hres)
|
||||
{
|
||||
std::stringstream sstream;
|
||||
sstream << descPrefix << desc << " failed" << std::endl;
|
||||
sstream << "Return value is 0x" << std::hex << hres;
|
||||
|
||||
PCHAR errMessage = NULL;
|
||||
FormatMessageA(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
NULL,
|
||||
hres,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(PCHAR)&errMessage,
|
||||
0,
|
||||
NULL);
|
||||
if (errMessage)
|
||||
{
|
||||
sstream << ": " << std::endl;
|
||||
sstream << errMessage;
|
||||
LocalFree(errMessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
sstream << std::endl;
|
||||
}
|
||||
|
||||
return sstream.str();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define callSymbol(method) \
|
||||
callSymbolT( &IDiaSymbol::##method, #method)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SymbolPtr loadSymbolFile(const std::string &filePath)
|
||||
{
|
||||
HRESULT hres;
|
||||
DiaDataSourcePtr dataSource;
|
||||
|
||||
hres = dataSource.CoCreateInstance(__uuidof(DiaSource), NULL, CLSCTX_INPROC_SERVER);
|
||||
|
||||
if ( S_OK != hres )
|
||||
throw DiaException("Call ::CoCreateInstance", hres);
|
||||
|
||||
hres = dataSource->loadDataFromPdb( toWStr(filePath) );
|
||||
if ( S_OK != hres )
|
||||
throw DiaException("Call IDiaDataSource::loadDataFromPdb", hres);
|
||||
|
||||
DiaSessionPtr _session;
|
||||
hres = dataSource->openSession(&_session);
|
||||
if ( S_OK != hres )
|
||||
throw DiaException("Call IDiaDataSource::openSession", hres);
|
||||
|
||||
DiaSymbolPtr _globalScope;
|
||||
hres = _session->get_globalScope(&_globalScope);
|
||||
if ( S_OK != hres )
|
||||
throw DiaException("Call IDiaSymbol::get_globalScope", hres);
|
||||
|
||||
return SymbolPtr( new DiaSymbol( _globalScope ) );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DiaSymbol::DiaSymbol(__inout DiaSymbolPtr &_symbol )
|
||||
{
|
||||
m_symbol = _symbol;
|
||||
m_symbol->get_machineType(&m_machineType);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SymbolPtr DiaSymbol::getChildByName(const std::string &_name)
|
||||
{
|
||||
DiaEnumSymbolsPtr symbols;
|
||||
HRESULT hres =
|
||||
m_symbol->findChildren(
|
||||
SymTagNull,
|
||||
toWStr(_name),
|
||||
nsCaseSensitive,
|
||||
&symbols);
|
||||
if (S_OK != hres)
|
||||
throw DiaException("Call IDiaSymbol::findChildren", hres);
|
||||
|
||||
LONG count;
|
||||
hres = symbols->get_Count(&count);
|
||||
if (S_OK != hres)
|
||||
throw DiaException("Call IDiaEnumSymbols::get_Count", hres);
|
||||
|
||||
if (!count)
|
||||
throw DiaException(_name + " not found");
|
||||
|
||||
if (count != 1)
|
||||
throw DiaException(_name + " is not unique");
|
||||
|
||||
DiaSymbolPtr child;
|
||||
hres = symbols->Item(0, &child);
|
||||
if (S_OK != hres)
|
||||
throw DiaException("Call IDiaEnumSymbols::Item", hres);
|
||||
|
||||
return SymbolPtr( new DiaSymbol(child) );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ULONG DiaSymbol::getRva()
|
||||
{
|
||||
return callSymbol(get_relativeVirtualAddress);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}; // pykd nemaspace end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
//#include "diawrapper.h"
|
||||
//#include "diacallback.h"
|
||||
//#include "utils.h"
|
||||
//
|
||||
//namespace pyDia {
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
////PyObject *Exception::diaExceptTypeObject = NULL;
|
||||
//
|
||||
//const std::string Exception::descPrefix("pyDia: ");
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//#define callSymbol(method) \
|
||||
// callSymbolT( &IDiaSymbol::##method, #method)
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//std::string Exception::makeFullDesc(const std::string &desc, HRESULT hres)
|
||||
//{
|
||||
// std::stringstream sstream;
|
||||
// sstream << descPrefix << desc << " failed" << std::endl;
|
||||
// sstream << "Return value is 0x" << std::hex << hres;
|
||||
//
|
||||
// PCHAR errMessage = NULL;
|
||||
// FormatMessageA(
|
||||
// FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
// NULL,
|
||||
// hres,
|
||||
// MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
// (PCHAR)&errMessage,
|
||||
// 0,
|
||||
// NULL);
|
||||
// if (errMessage)
|
||||
// {
|
||||
// sstream << ": " << std::endl;
|
||||
// sstream << errMessage;
|
||||
// LocalFree(errMessage);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// sstream << std::endl;
|
||||
// }
|
||||
//
|
||||
// return sstream.str();
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//SymbolPtrList Symbol::findChildrenImpl(
|
||||
// ULONG symTag,
|
||||
// const std::string &name,
|
||||
// DWORD nameCmpFlags
|
||||
//)
|
||||
//{
|
||||
// DiaEnumSymbolsPtr symbols;
|
||||
// HRESULT hres;
|
||||
//
|
||||
// if ( name.empty() )
|
||||
// {
|
||||
// hres = m_symbol->findChildren(
|
||||
// static_cast<enum SymTagEnum>(symTag),
|
||||
// NULL,
|
||||
// nameCmpFlags,
|
||||
// &symbols);
|
||||
//
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// hres = m_symbol->findChildren(
|
||||
// static_cast<enum SymTagEnum>(symTag),
|
||||
// toWStr(name),
|
||||
// nameCmpFlags,
|
||||
// &symbols);
|
||||
// }
|
||||
//
|
||||
// if (S_OK != hres)
|
||||
// throw Exception("Call IDiaSymbol::findChildren", hres);
|
||||
//
|
||||
// SymbolPtrList childList;
|
||||
//
|
||||
// DiaSymbolPtr child;
|
||||
// ULONG celt;
|
||||
// while ( SUCCEEDED(symbols->Next(1, &child, &celt)) && (celt == 1) )
|
||||
// childList.push_back( SymbolPtr( new Symbol(child, m_machineType) ) );
|
||||
//
|
||||
// return childList;
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//ULONGLONG Symbol::getSize()
|
||||
//{
|
||||
// return callSymbol(get_length);
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//std::string Symbol::getName()
|
||||
//{
|
||||
// autoBstr retValue( callSymbol(get_name) );
|
||||
// return retValue.asStr();
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//std::string Symbol::getUndecoratedName()
|
||||
//{
|
||||
// autoBstr retValue( callSymbol(get_undecoratedName) );
|
||||
// return retValue.asStr();
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//SymbolPtr Symbol::getType()
|
||||
//{
|
||||
// return SymbolPtr( new Symbol(callSymbol(get_type), m_machineType) );
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//SymbolPtr Symbol::getIndexType()
|
||||
//{
|
||||
// return SymbolPtr( new Symbol(callSymbol(get_arrayIndexType), m_machineType) );
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//ULONG Symbol::getSymTag()
|
||||
//{
|
||||
// return callSymbol(get_symTag);
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//ULONG Symbol::getRva()
|
||||
//{
|
||||
// return callSymbol(get_relativeVirtualAddress);
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//ULONGLONG Symbol::getVa()
|
||||
//{
|
||||
// return callSymbol(get_virtualAddress);
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//ULONG Symbol::getLocType()
|
||||
//{
|
||||
// return callSymbol(get_locationType);
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//LONG Symbol::getOffset()
|
||||
//{
|
||||
// return callSymbol(get_offset);
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//ULONG Symbol::getCount()
|
||||
//{
|
||||
// return callSymbol(get_count);
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//int Symbol::getVirtualBasePointerOffset()
|
||||
//{
|
||||
// return callSymbol(get_virtualBasePointerOffset);
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//ULONG Symbol::getVirtualBaseDispIndex()
|
||||
//{
|
||||
// return callSymbol(get_virtualBaseDispIndex);
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//ULONG Symbol::getVirtualBaseDispSize()
|
||||
//{
|
||||
// SymbolPtr baseTableType = SymbolPtr( new Symbol( callSymbol(get_virtualBaseTableType), m_machineType ) );
|
||||
//
|
||||
// return (ULONG)baseTableType->getType()->getSize();
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//ULONG Symbol::getSection()
|
||||
//{
|
||||
// return callSymbol(get_targetSection);
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//void Symbol::getValueImpl(IDiaSymbol *_symbol, VARIANT &vtValue)
|
||||
//{
|
||||
// HRESULT hres = _symbol->get_value(&vtValue);
|
||||
// if (S_OK != hres)
|
||||
// throw Exception("Call IDiaSymbol::get_value", hres);
|
||||
//}
|
||||
//
|
||||
//void Symbol::getValue( VARIANT &vtValue)
|
||||
//{
|
||||
// HRESULT hres = m_symbol->get_value(&vtValue);
|
||||
// if (S_OK != hres)
|
||||
// throw Exception("Call IDiaSymbol::get_value", hres);
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//python::object Symbol::getValue()
|
||||
//{
|
||||
// VARIANT vtValue = { VT_EMPTY };
|
||||
// getValueImpl(m_symbol, vtValue);
|
||||
// switch (vtValue.vt)
|
||||
// {
|
||||
// case VT_I1:
|
||||
// case VT_UI1:
|
||||
// return python::object( static_cast<ULONG>(vtValue.bVal) );
|
||||
//
|
||||
// case VT_BOOL:
|
||||
// return python::object( static_cast<bool>(!!vtValue.iVal) );
|
||||
//
|
||||
// case VT_I2:
|
||||
// case VT_UI2:
|
||||
// return python::object( static_cast<ULONG>(vtValue.iVal) );
|
||||
//
|
||||
// case VT_I4:
|
||||
// case VT_UI4:
|
||||
// case VT_INT:
|
||||
// case VT_UINT:
|
||||
// case VT_ERROR:
|
||||
// case VT_HRESULT:
|
||||
// return python::object( vtValue.lVal );
|
||||
//
|
||||
// case VT_I8:
|
||||
// case VT_UI8:
|
||||
// return python::object( vtValue.llVal );
|
||||
//
|
||||
// case VT_R4:
|
||||
// return python::object( double(vtValue.fltVal) );
|
||||
//
|
||||
// case VT_R8:
|
||||
// return python::object( vtValue.dblVal );
|
||||
//
|
||||
// case VT_BSTR:
|
||||
// return python::object( autoBstr::asStr(vtValue.bstrVal).c_str() );
|
||||
//
|
||||
// }
|
||||
// throw Exception("Unknown value type");
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//bool Symbol::isBasicType()
|
||||
//{
|
||||
// DWORD baseType = btNoType;
|
||||
// return
|
||||
// SUCCEEDED( m_symbol->get_baseType(&baseType) ) &&
|
||||
// (btNoType != baseType);
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//bool Symbol::isVirtualBaseClass()
|
||||
//{
|
||||
// return !!callSymbol(get_virtualBaseClass);
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//bool Symbol::isIndirectVirtualBaseClass()
|
||||
//{
|
||||
// return !!callSymbol(get_indirectVirtualBaseClass);
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//ULONG Symbol::getBaseType()
|
||||
//{
|
||||
// return callSymbol(get_baseType);
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//ULONG Symbol::getBitPosition()
|
||||
//{
|
||||
// return callSymbol(get_bitPosition);
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//ULONG Symbol::getIndexId()
|
||||
//{
|
||||
// return callSymbol(get_symIndexId);
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//ULONG Symbol::getUdtKind()
|
||||
//{
|
||||
// return callSymbol(get_udtKind);
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//ULONG Symbol::getDataKind()
|
||||
//{
|
||||
// return callSymbol(get_dataKind);
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//ULONG Symbol::getRegisterId()
|
||||
//{
|
||||
// return callSymbol(get_registerId);
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//bool Symbol::isConstant()
|
||||
//{
|
||||
// return !!callSymbol(get_constType);
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//SymbolPtr Symbol::getChildByName(const std::string &_name)
|
||||
//{
|
||||
// DiaEnumSymbolsPtr symbols;
|
||||
// HRESULT hres =
|
||||
// m_symbol->findChildren(
|
||||
// SymTagNull,
|
||||
// toWStr(_name),
|
||||
// nsCaseSensitive,
|
||||
// &symbols);
|
||||
// if (S_OK != hres)
|
||||
// throw Exception("Call IDiaSymbol::findChildren", hres);
|
||||
//
|
||||
// LONG count;
|
||||
// hres = symbols->get_Count(&count);
|
||||
// if (S_OK != hres)
|
||||
// throw Exception("Call IDiaEnumSymbols::get_Count", hres);
|
||||
//
|
||||
// if (!count)
|
||||
// throw Exception(_name + " not found");
|
||||
//
|
||||
// if (count != 1)
|
||||
// throw Exception(_name + " is not unique");
|
||||
//
|
||||
// DiaSymbolPtr child;
|
||||
// hres = symbols->Item(0, &child);
|
||||
// if (S_OK != hres)
|
||||
// throw Exception("Call IDiaEnumSymbols::Item", hres);
|
||||
//
|
||||
// return SymbolPtr( new Symbol(child, m_machineType) );
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//std::string Symbol::print()
|
||||
//{
|
||||
// return printImpl(m_symbol, m_machineType);
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//bool Symbol::eq(Symbol &rhs)
|
||||
//{
|
||||
// return getIndexId() == rhs.getIndexId();
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//GlobalScope::GlobalScope(
|
||||
// __inout DiaDataSourcePtr &dataSource,
|
||||
// __inout DiaSessionPtr &_session,
|
||||
// __inout DiaSymbolPtr &_globalScope
|
||||
//) : Symbol(_globalScope, CV_CFL_80386)
|
||||
// , m_dataSource( dataSource.Detach() )
|
||||
// , m_session( _session.Detach() )
|
||||
//{
|
||||
// m_symbol->get_machineType(&m_machineType);
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//GlobalScopePtr GlobalScope::loadPdb(const std::string &filePath)
|
||||
//{
|
||||
// class CLoaderFromPdb : public IScopeDataLoader {
|
||||
// public:
|
||||
// CLoaderFromPdb(const std::string &filePath) : m_filePath(filePath) {}
|
||||
//
|
||||
// virtual void loadData(IDiaDataSource *dataSource) override {
|
||||
// HRESULT hres = dataSource->loadDataFromPdb( toWStr(m_filePath) );
|
||||
// if ( S_OK != hres )
|
||||
// throw Exception("Call IDiaDataSource::loadDataFromPdb", hres);
|
||||
// }
|
||||
//
|
||||
// private:
|
||||
// const std::string &m_filePath;
|
||||
// } loaderFromPdb(filePath);
|
||||
//
|
||||
// return loadImpl(loaderFromPdb);
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//GlobalScopePtr GlobalScope::loadExe(const std::string &filePath, PCSTR searchPath /*= NULL*/)
|
||||
//{
|
||||
// if (!searchPath)
|
||||
// searchPath = "SRV**\\\\symbols\\symbols";
|
||||
//
|
||||
// class CLoaderForExe : public IScopeDataLoader {
|
||||
// public:
|
||||
// CLoaderForExe(const std::string &filePath, PCSTR searchPath)
|
||||
// : m_filePath(filePath), m_searchPath(searchPath)
|
||||
// {
|
||||
// }
|
||||
//
|
||||
// virtual void loadData(IDiaDataSource *dataSource) override {
|
||||
// LoadCallback loadCallback;
|
||||
// HRESULT hres =
|
||||
// dataSource->loadDataForExe( toWStr(m_filePath), toWStr(m_searchPath), &loadCallback );
|
||||
// if ( S_OK != hres )
|
||||
// throw Exception("Call IDiaDataSource::loadDataForExe", hres);
|
||||
// }
|
||||
//
|
||||
// private:
|
||||
// const std::string &m_filePath;
|
||||
// const std::string m_searchPath;
|
||||
// } loaderForExe(filePath, searchPath);
|
||||
//
|
||||
// return loadImpl(loaderForExe);
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//GlobalScopePtr GlobalScope::loadImpl(IScopeDataLoader &ScopeDataLoader)
|
||||
//{
|
||||
// DiaDataSourcePtr dataSource;
|
||||
//
|
||||
// HRESULT hres =
|
||||
// dataSource.CoCreateInstance(__uuidof(DiaSource), NULL, CLSCTX_INPROC_SERVER);
|
||||
// if ( S_OK != hres )
|
||||
// throw Exception("Call ::CoCreateInstance", hres);
|
||||
//
|
||||
// ScopeDataLoader.loadData(dataSource);
|
||||
//
|
||||
// DiaSessionPtr _session;
|
||||
// hres = dataSource->openSession(&_session);
|
||||
// if ( S_OK != hres )
|
||||
// throw Exception("Call IDiaDataSource::openSession", hres);
|
||||
//
|
||||
// DiaSymbolPtr _globalScope;
|
||||
// hres = _session->get_globalScope(&_globalScope);
|
||||
// if ( S_OK != hres )
|
||||
// throw Exception("Call IDiaSymbol::get_globalScope", hres);
|
||||
//
|
||||
// return GlobalScopePtr( new GlobalScope(dataSource, _session, _globalScope) );
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//SymbolPtr GlobalScope::findByRvaImpl(
|
||||
// __in ULONG rva,
|
||||
// __in ULONG symTag,
|
||||
// __out LONG &displacement
|
||||
//)
|
||||
//{
|
||||
// DiaSymbolPtr child;
|
||||
// HRESULT hres =
|
||||
// m_session->findSymbolByRVAEx(
|
||||
// rva,
|
||||
// static_cast<enum SymTagEnum>(symTag),
|
||||
// &child,
|
||||
// &displacement);
|
||||
// if (S_OK != hres)
|
||||
// throw Exception("Call IDiaSession::findSymbolByRVAEx", hres);
|
||||
// if (!child)
|
||||
// throw Exception("Call IDiaSession::findSymbolByRVAEx", E_UNEXPECTED);
|
||||
//
|
||||
// return SymbolPtr( new Symbol(child, m_machineType) );
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//SymbolPtr GlobalScope::findByVaImpl(
|
||||
// __in ULONGLONG va,
|
||||
// __in ULONG symTag,
|
||||
// __out LONG &displacement
|
||||
//)
|
||||
//{
|
||||
// DiaSymbolPtr child;
|
||||
// HRESULT hres =
|
||||
// m_session->findSymbolByVAEx(
|
||||
// va,
|
||||
// static_cast<enum SymTagEnum>(symTag),
|
||||
// &child,
|
||||
// &displacement);
|
||||
// if (S_OK != hres)
|
||||
// throw Exception("Call IDiaSession::findSymbolByVAEx", hres);
|
||||
// if (!child)
|
||||
// throw Exception("Call IDiaSession::findSymbolByVAEx", E_UNEXPECTED);
|
||||
//
|
||||
// return SymbolPtr( new Symbol(child, m_machineType) );
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//SymbolPtr GlobalScope::getSymbolById(ULONG symId)
|
||||
//{
|
||||
// DiaSymbolPtr _symbol;
|
||||
// HRESULT hres = m_session->symbolById(symId, &_symbol);
|
||||
// if (S_OK != hres)
|
||||
// throw Exception("Call IDiaSession::findSymbolByRVAEx", hres);
|
||||
// if (!_symbol)
|
||||
// throw Exception("Call IDiaSession::findSymbolByRVAEx", E_UNEXPECTED);
|
||||
//
|
||||
// return SymbolPtr( new Symbol(_symbol, m_machineType) );
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//ULONGLONG GlobalScope::getLoadAddress()
|
||||
//{
|
||||
// ULONGLONG loadAddress;
|
||||
// HRESULT hres = m_session->get_loadAddress(&loadAddress);
|
||||
// if (S_OK != hres)
|
||||
// throw Exception("Call IDiaSession::get_loadAddress", hres);
|
||||
// return loadAddress;
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//void GlobalScope::setLoadAddress(ULONGLONG loadAddress)
|
||||
//{
|
||||
// HRESULT hres = m_session->put_loadAddress(loadAddress);
|
||||
// if (S_OK != hres)
|
||||
// throw Exception("Call IDiaSession::put_loadAddress", hres);
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//}
|
635
pykd/dia/diawrapper.h
Normal file
635
pykd/dia/diawrapper.h
Normal file
@ -0,0 +1,635 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "symengine.h"
|
||||
#include "dbgexcept.h"
|
||||
|
||||
namespace pykd {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef CComPtr< IDiaSymbol > DiaSymbolPtr;
|
||||
typedef CComPtr< IDiaEnumSymbols > DiaEnumSymbolsPtr;
|
||||
typedef CComPtr< IDiaDataSource > DiaDataSourcePtr;
|
||||
typedef CComPtr< IDiaSession > DiaSessionPtr;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class DiaException : public SymbolException {
|
||||
public:
|
||||
DiaException(const std::string &desc, HRESULT hres)
|
||||
: SymbolException( makeFullDesc(desc, hres) )
|
||||
, m_hres(hres)
|
||||
{
|
||||
}
|
||||
|
||||
DiaException(const std::string &desc)
|
||||
: SymbolException(descPrefix + desc)
|
||||
, m_hres(S_FALSE)
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT getRes() const {
|
||||
return m_hres;
|
||||
}
|
||||
private:
|
||||
|
||||
static const std::string descPrefix;
|
||||
|
||||
static std::string makeFullDesc(const std::string &desc, HRESULT hres);
|
||||
|
||||
HRESULT m_hres;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class DiaSymbol : public Symbol {
|
||||
public:
|
||||
|
||||
DiaSymbol(__inout DiaSymbolPtr &_symbol );
|
||||
|
||||
SymbolPtr getChildByName(const std::string &_name);
|
||||
|
||||
ULONG getRva();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//SymbolPtrList findChildrenImpl(
|
||||
// ULONG symTag,
|
||||
// const std::string &name = "",
|
||||
// DWORD nameCmpFlags = 0
|
||||
//);
|
||||
|
||||
//python::list findChildrenEx(
|
||||
// ULONG symTag,
|
||||
// const std::string &name = "",
|
||||
// DWORD nameCmpFlags = 0
|
||||
//)
|
||||
//{
|
||||
// return toPyList( findChildrenImpl(symTag, name, nameCmpFlags) );
|
||||
//}
|
||||
|
||||
//python::list findChildren(
|
||||
// const std::string &name
|
||||
//)
|
||||
//{
|
||||
// return toPyList( findChildrenImpl(SymTagNull, name, nsfCaseSensitive) );
|
||||
//}
|
||||
|
||||
//ULONGLONG getSize();
|
||||
|
||||
//std::string getName();
|
||||
//std::string getUndecoratedName();
|
||||
|
||||
//SymbolPtr getType();
|
||||
|
||||
//SymbolPtr getIndexType();
|
||||
|
||||
//ULONG getSymTag();
|
||||
|
||||
//ULONG getRva();
|
||||
//ULONGLONG getVa();
|
||||
|
||||
//ULONG getLocType();
|
||||
|
||||
//LONG getOffset();
|
||||
|
||||
//ULONG getCount();
|
||||
|
||||
//static void getValueImpl(IDiaSymbol *_symbol, VARIANT &vtValue);
|
||||
//python::object getValue();
|
||||
//void getValue( VARIANT &vtValue);
|
||||
|
||||
//bool isBasicType();
|
||||
|
||||
//bool isVirtualBaseClass();
|
||||
|
||||
//bool isIndirectVirtualBaseClass();
|
||||
|
||||
//ULONG getBaseType();
|
||||
|
||||
//ULONG getBitPosition();
|
||||
|
||||
//ULONG getIndexId();
|
||||
|
||||
//ULONG getUdtKind();
|
||||
|
||||
//ULONG getDataKind();
|
||||
|
||||
//ULONG getRegisterId();
|
||||
|
||||
//ULONG getMachineType() const {
|
||||
// return m_machineType;
|
||||
//}
|
||||
|
||||
//SymbolPtr getChildByName(const std::string &_name);
|
||||
|
||||
//template<ULONG symTag>
|
||||
//ULONG getChildCount();
|
||||
|
||||
//ULONG getChildCount() {
|
||||
// return getChildCount<SymTagNull>();
|
||||
//}
|
||||
|
||||
//template<ULONG symTag>
|
||||
//SymbolPtr getChildByIndex(ULONG _index );
|
||||
|
||||
//SymbolPtr getChildByIndex(ULONG _index ) {
|
||||
// return getChildByIndex<SymTagNull>( _index );
|
||||
//}
|
||||
//
|
||||
//bool isConstant();
|
||||
|
||||
//std::string print();
|
||||
|
||||
//bool eq(Symbol &rhs);
|
||||
|
||||
//int getVirtualBasePointerOffset();
|
||||
|
||||
//ULONG getVirtualBaseDispIndex();
|
||||
|
||||
//ULONG getVirtualBaseDispSize();
|
||||
|
||||
//ULONG getSection();
|
||||
|
||||
public:
|
||||
//typedef std::pair<ULONG, const char *> ValueNameEntry;
|
||||
|
||||
//static const ValueNameEntry dataKindName[DataIsConstant + 1];
|
||||
|
||||
//static const ValueNameEntry symTagName[SymTagMax];
|
||||
|
||||
//static const ValueNameEntry locTypeName[LocTypeMax];
|
||||
|
||||
//static const ValueNameEntry basicTypeName[];
|
||||
//static const size_t cntBasicTypeName;
|
||||
|
||||
//static const ValueNameEntry udtKindName[];
|
||||
//static const size_t cntUdtKindName;
|
||||
|
||||
//static const ValueNameEntry i386RegName[];
|
||||
//static const size_t cntI386RegName;
|
||||
|
||||
//static const ValueNameEntry amd64RegName[];
|
||||
//static const size_t cntAmd64RegName;
|
||||
|
||||
//static std::string getBasicTypeName( ULONG basicType );
|
||||
|
||||
protected:
|
||||
|
||||
//// Check symbols loop
|
||||
//class checkSymLoop
|
||||
//{
|
||||
//public:
|
||||
// checkSymLoop(checkSymLoop *prev)
|
||||
// : m_symSetPtr( prev ? prev->m_symSetPtr : symSetPtr(new symSet) )
|
||||
// {
|
||||
// }
|
||||
|
||||
// bool check(IDiaSymbol *_symbol)
|
||||
// {
|
||||
// DWORD symIndexId = 0;
|
||||
// _symbol->get_symIndexId(&symIndexId);
|
||||
// return !m_symSetPtr->insert(symIndexId).second;
|
||||
// }
|
||||
|
||||
//private:
|
||||
// typedef std::set<DWORD> symSet;
|
||||
// typedef boost::shared_ptr<symSet> symSetPtr;
|
||||
// symSetPtr m_symSetPtr;
|
||||
//};
|
||||
|
||||
//static std::string printImpl(
|
||||
// IDiaSymbol *_symbol,
|
||||
// DWORD machineType,
|
||||
// ULONG indent = 0,
|
||||
// checkSymLoop *checkLoopPrev = NULL,
|
||||
// const char *prefix = NULL
|
||||
//);
|
||||
|
||||
template <typename TRet>
|
||||
TRet callSymbolT(
|
||||
HRESULT(STDMETHODCALLTYPE IDiaSymbol::*method)(TRet *),
|
||||
const char *methodName
|
||||
)
|
||||
{
|
||||
TRet retValue;
|
||||
HRESULT hres = (m_symbol->*method)(&retValue);
|
||||
if (S_OK != hres)
|
||||
throw DiaException(std::string("Call IDiaSymbol::") + methodName, hres);
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
DiaSymbolPtr m_symbol;
|
||||
|
||||
DWORD m_machineType;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
} // end pykd namespace
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//#include <set>
|
||||
//
|
||||
//#include <boost\smart_ptr\scoped_ptr.hpp>
|
||||
//
|
||||
//#include <cvconst.h>
|
||||
//
|
||||
//#include "utils.h"
|
||||
//#include "dbgexcept.h"
|
||||
//
|
||||
//namespace pyDia {
|
||||
//
|
||||
//typedef CComPtr< IDiaSymbol > DiaSymbolPtr;
|
||||
//typedef CComPtr< IDiaEnumSymbols > DiaEnumSymbolsPtr;
|
||||
//typedef CComPtr< IDiaDataSource > DiaDataSourcePtr;
|
||||
//typedef CComPtr< IDiaSession > DiaSessionPtr;
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//// DIA Exceptions
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//class Exception : public pykd::SymbolException {
|
||||
//public:
|
||||
// Exception(const std::string &desc, HRESULT hres)
|
||||
// : SymbolException( makeFullDesc(desc, hres) )
|
||||
// , m_hres(hres)
|
||||
// {
|
||||
// }
|
||||
//
|
||||
// Exception(const std::string &desc)
|
||||
// : SymbolException(descPrefix + desc)
|
||||
// , m_hres(S_FALSE)
|
||||
// {
|
||||
// }
|
||||
//
|
||||
// HRESULT getRes() const {
|
||||
// return m_hres;
|
||||
// }
|
||||
//private:
|
||||
//
|
||||
// static const std::string descPrefix;
|
||||
//
|
||||
// static std::string makeFullDesc(const std::string &desc, HRESULT hres);
|
||||
//
|
||||
// HRESULT m_hres;
|
||||
//};
|
||||
//
|
||||
//class Symbol;
|
||||
//typedef boost::shared_ptr< Symbol > SymbolPtr;
|
||||
//typedef std::list< SymbolPtr > SymbolPtrList;
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//// Symbol
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//class Symbol {
|
||||
//public:
|
||||
// Symbol()
|
||||
// {
|
||||
// throw Exception("DiaSymbol must be created over factory from DiaScope::...");
|
||||
// }
|
||||
// Symbol(__inout DiaSymbolPtr &_symbol, DWORD machineType)
|
||||
// : m_machineType(machineType)
|
||||
// {
|
||||
// m_symbol = _symbol.Detach();
|
||||
// }
|
||||
// Symbol(__in IDiaSymbol *_symbol, DWORD machineType)
|
||||
// : m_machineType(machineType)
|
||||
// {
|
||||
// m_symbol = _symbol;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// SymbolPtrList findChildrenImpl(
|
||||
// ULONG symTag,
|
||||
// const std::string &name = "",
|
||||
// DWORD nameCmpFlags = 0
|
||||
// );
|
||||
//
|
||||
// python::list findChildrenEx(
|
||||
// ULONG symTag,
|
||||
// const std::string &name = "",
|
||||
// DWORD nameCmpFlags = 0
|
||||
// )
|
||||
// {
|
||||
// return toPyList( findChildrenImpl(symTag, name, nameCmpFlags) );
|
||||
// }
|
||||
//
|
||||
// python::list findChildren(
|
||||
// const std::string &name
|
||||
// )
|
||||
// {
|
||||
// return toPyList( findChildrenImpl(SymTagNull, name, nsfCaseSensitive) );
|
||||
// }
|
||||
//
|
||||
// ULONGLONG getSize();
|
||||
//
|
||||
// std::string getName();
|
||||
// std::string getUndecoratedName();
|
||||
//
|
||||
// SymbolPtr getType();
|
||||
//
|
||||
// SymbolPtr getIndexType();
|
||||
//
|
||||
// ULONG getSymTag();
|
||||
//
|
||||
// ULONG getRva();
|
||||
// ULONGLONG getVa();
|
||||
//
|
||||
// ULONG getLocType();
|
||||
//
|
||||
// LONG getOffset();
|
||||
//
|
||||
// ULONG getCount();
|
||||
//
|
||||
// static void getValueImpl(IDiaSymbol *_symbol, VARIANT &vtValue);
|
||||
// python::object getValue();
|
||||
// void getValue( VARIANT &vtValue);
|
||||
//
|
||||
// bool isBasicType();
|
||||
//
|
||||
// bool isVirtualBaseClass();
|
||||
//
|
||||
// bool isIndirectVirtualBaseClass();
|
||||
//
|
||||
// ULONG getBaseType();
|
||||
//
|
||||
// ULONG getBitPosition();
|
||||
//
|
||||
// ULONG getIndexId();
|
||||
//
|
||||
// ULONG getUdtKind();
|
||||
//
|
||||
// ULONG getDataKind();
|
||||
//
|
||||
// ULONG getRegisterId();
|
||||
//
|
||||
// ULONG getMachineType() const {
|
||||
// return m_machineType;
|
||||
// }
|
||||
//
|
||||
// SymbolPtr getChildByName(const std::string &_name);
|
||||
//
|
||||
// template<ULONG symTag>
|
||||
// ULONG getChildCount();
|
||||
//
|
||||
// ULONG getChildCount() {
|
||||
// return getChildCount<SymTagNull>();
|
||||
// }
|
||||
//
|
||||
// template<ULONG symTag>
|
||||
// SymbolPtr getChildByIndex(ULONG _index );
|
||||
//
|
||||
// SymbolPtr getChildByIndex(ULONG _index ) {
|
||||
// return getChildByIndex<SymTagNull>( _index );
|
||||
// }
|
||||
//
|
||||
// bool isConstant();
|
||||
//
|
||||
// std::string print();
|
||||
//
|
||||
// bool eq(Symbol &rhs);
|
||||
//
|
||||
// int getVirtualBasePointerOffset();
|
||||
//
|
||||
// ULONG getVirtualBaseDispIndex();
|
||||
//
|
||||
// ULONG getVirtualBaseDispSize();
|
||||
//
|
||||
// ULONG getSection();
|
||||
//
|
||||
//public:
|
||||
// typedef std::pair<ULONG, const char *> ValueNameEntry;
|
||||
//
|
||||
// static const ValueNameEntry dataKindName[DataIsConstant + 1];
|
||||
//
|
||||
// static const ValueNameEntry symTagName[SymTagMax];
|
||||
//
|
||||
// static const ValueNameEntry locTypeName[LocTypeMax];
|
||||
//
|
||||
// static const ValueNameEntry basicTypeName[];
|
||||
// static const size_t cntBasicTypeName;
|
||||
//
|
||||
// static const ValueNameEntry udtKindName[];
|
||||
// static const size_t cntUdtKindName;
|
||||
//
|
||||
// static const ValueNameEntry i386RegName[];
|
||||
// static const size_t cntI386RegName;
|
||||
//
|
||||
// static const ValueNameEntry amd64RegName[];
|
||||
// static const size_t cntAmd64RegName;
|
||||
//
|
||||
// static std::string getBasicTypeName( ULONG basicType );
|
||||
//
|
||||
//protected:
|
||||
//
|
||||
// // Check symbols loop
|
||||
// class checkSymLoop
|
||||
// {
|
||||
// public:
|
||||
// checkSymLoop(checkSymLoop *prev)
|
||||
// : m_symSetPtr( prev ? prev->m_symSetPtr : symSetPtr(new symSet) )
|
||||
// {
|
||||
// }
|
||||
//
|
||||
// bool check(IDiaSymbol *_symbol)
|
||||
// {
|
||||
// DWORD symIndexId = 0;
|
||||
// _symbol->get_symIndexId(&symIndexId);
|
||||
// return !m_symSetPtr->insert(symIndexId).second;
|
||||
// }
|
||||
//
|
||||
// private:
|
||||
// typedef std::set<DWORD> symSet;
|
||||
// typedef boost::shared_ptr<symSet> symSetPtr;
|
||||
// symSetPtr m_symSetPtr;
|
||||
// };
|
||||
//
|
||||
// static std::string printImpl(
|
||||
// IDiaSymbol *_symbol,
|
||||
// DWORD machineType,
|
||||
// ULONG indent = 0,
|
||||
// checkSymLoop *checkLoopPrev = NULL,
|
||||
// const char *prefix = NULL
|
||||
// );
|
||||
//
|
||||
// template <typename TRet>
|
||||
// TRet callSymbolT(
|
||||
// HRESULT(STDMETHODCALLTYPE IDiaSymbol::*method)(TRet *),
|
||||
// const char *methodName
|
||||
// )
|
||||
// {
|
||||
// TRet retValue;
|
||||
// HRESULT hres = (m_symbol->*method)(&retValue);
|
||||
// if (S_OK != hres)
|
||||
// throw Exception(std::string("Call IDiaSymbol::") + methodName, hres);
|
||||
//
|
||||
// return retValue;
|
||||
// }
|
||||
//
|
||||
// DiaSymbolPtr m_symbol;
|
||||
// DWORD m_machineType;
|
||||
//};
|
||||
//
|
||||
//class GlobalScope;
|
||||
//typedef boost::shared_ptr< GlobalScope > GlobalScopePtr;
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//// Global scope: source + sessions
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//class GlobalScope : public Symbol {
|
||||
//public:
|
||||
// GlobalScope() {}
|
||||
//
|
||||
// // GlobalScope factory
|
||||
// static GlobalScopePtr loadPdb(const std::string &filePath);
|
||||
// static GlobalScopePtr loadExe(const std::string &filePath, PCSTR searchPath = NULL);
|
||||
//
|
||||
// // RVA -> Symbol
|
||||
// python::tuple findByRva(
|
||||
// ULONG rva,
|
||||
// ULONG symTag
|
||||
// )
|
||||
// {
|
||||
// LONG displacement;
|
||||
// SymbolPtr child = findByRvaImpl(rva, symTag, displacement);
|
||||
// return python::make_tuple(child, displacement);
|
||||
// }
|
||||
// SymbolPtr findByRvaImpl(
|
||||
// __in ULONG rva,
|
||||
// __in ULONG symTag,
|
||||
// __out LONG &displacement
|
||||
// );
|
||||
//
|
||||
// // VA -> Symbol
|
||||
// python::tuple findByVa(
|
||||
// ULONG va,
|
||||
// ULONG symTag
|
||||
// )
|
||||
// {
|
||||
// LONG displacement;
|
||||
// SymbolPtr child = findByVaImpl(va, symTag, displacement);
|
||||
// return python::make_tuple(child, displacement);
|
||||
// }
|
||||
// SymbolPtr findByVaImpl(
|
||||
// __in ULONGLONG va,
|
||||
// __in ULONG symTag,
|
||||
// __out LONG &displacement
|
||||
// );
|
||||
//
|
||||
// // get symbol by unique index
|
||||
// SymbolPtr getSymbolById(ULONG symId);
|
||||
//
|
||||
// // get/set load address
|
||||
// ULONGLONG getLoadAddress();
|
||||
// void setLoadAddress(ULONGLONG loadAddress);
|
||||
//
|
||||
//private:
|
||||
// interface IScopeDataLoader {
|
||||
// virtual ~IScopeDataLoader() {}
|
||||
// virtual void loadData(IDiaDataSource *dataSource) = 0;
|
||||
// };
|
||||
// static GlobalScopePtr loadImpl(IScopeDataLoader &ScopeDataLoader);
|
||||
//
|
||||
// GlobalScope(
|
||||
// __inout DiaDataSourcePtr &dataSource,
|
||||
// __inout DiaSessionPtr &_session,
|
||||
// __inout DiaSymbolPtr &_globalScope
|
||||
// );
|
||||
//
|
||||
// DiaDataSourcePtr m_dataSource;
|
||||
// DiaSessionPtr m_session;
|
||||
//};
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//template<ULONG symTag>
|
||||
//ULONG Symbol::getChildCount()
|
||||
//{
|
||||
// DiaEnumSymbolsPtr symbols;
|
||||
// HRESULT hres =
|
||||
// m_symbol->findChildren(
|
||||
// static_cast<enum SymTagEnum>(symTag),
|
||||
// NULL,
|
||||
// nsCaseSensitive,
|
||||
// &symbols);
|
||||
// if (S_OK != hres)
|
||||
// throw Exception("Call IDiaSymbol::findChildren", hres);
|
||||
//
|
||||
// LONG count;
|
||||
// hres = symbols->get_Count(&count);
|
||||
// if (S_OK != hres)
|
||||
// throw Exception("Call IDiaEnumSymbols::get_Count", hres);
|
||||
//
|
||||
// return count;
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//template<ULONG symTag>
|
||||
//SymbolPtr Symbol::getChildByIndex(ULONG _index )
|
||||
//{
|
||||
// DiaEnumSymbolsPtr symbols;
|
||||
// HRESULT hres =
|
||||
// m_symbol->findChildren(
|
||||
// static_cast<enum SymTagEnum>(symTag),
|
||||
// NULL,
|
||||
// nsCaseSensitive,
|
||||
// &symbols);
|
||||
// if (S_OK != hres)
|
||||
// throw Exception("Call IDiaSymbol::findChildren", hres);
|
||||
//
|
||||
// LONG count;
|
||||
// hres = symbols->get_Count(&count);
|
||||
// if (S_OK != hres)
|
||||
// throw Exception("Call IDiaEnumSymbols::get_Count", hres);
|
||||
//
|
||||
// if (LONG(_index) >= count)
|
||||
// {
|
||||
// PyErr_SetString(PyExc_IndexError, "Index out of range");
|
||||
// boost::python::throw_error_already_set();
|
||||
// }
|
||||
//
|
||||
// DiaSymbolPtr child;
|
||||
// hres = symbols->Item(_index, &child);
|
||||
// if (S_OK != hres)
|
||||
// throw Exception("Call IDiaEnumSymbols::Item", hres);
|
||||
//
|
||||
// return SymbolPtr( new Symbol(child, m_machineType) );
|
||||
//}
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
//};
|
@ -1,555 +0,0 @@
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "diawrapper.h"
|
||||
#include "diacallback.h"
|
||||
#include "utils.h"
|
||||
|
||||
namespace pyDia {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//PyObject *Exception::diaExceptTypeObject = NULL;
|
||||
|
||||
const std::string Exception::descPrefix("pyDia: ");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define callSymbol(method) \
|
||||
callSymbolT( &IDiaSymbol::##method, #method)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string Exception::makeFullDesc(const std::string &desc, HRESULT hres)
|
||||
{
|
||||
std::stringstream sstream;
|
||||
sstream << descPrefix << desc << " failed" << std::endl;
|
||||
sstream << "Return value is 0x" << std::hex << hres;
|
||||
|
||||
PCHAR errMessage = NULL;
|
||||
FormatMessageA(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
NULL,
|
||||
hres,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(PCHAR)&errMessage,
|
||||
0,
|
||||
NULL);
|
||||
if (errMessage)
|
||||
{
|
||||
sstream << ": " << std::endl;
|
||||
sstream << errMessage;
|
||||
LocalFree(errMessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
sstream << std::endl;
|
||||
}
|
||||
|
||||
return sstream.str();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SymbolPtrList Symbol::findChildrenImpl(
|
||||
ULONG symTag,
|
||||
const std::string &name,
|
||||
DWORD nameCmpFlags
|
||||
)
|
||||
{
|
||||
DiaEnumSymbolsPtr symbols;
|
||||
HRESULT hres;
|
||||
|
||||
if ( name.empty() )
|
||||
{
|
||||
hres = m_symbol->findChildren(
|
||||
static_cast<enum SymTagEnum>(symTag),
|
||||
NULL,
|
||||
nameCmpFlags,
|
||||
&symbols);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
hres = m_symbol->findChildren(
|
||||
static_cast<enum SymTagEnum>(symTag),
|
||||
toWStr(name),
|
||||
nameCmpFlags,
|
||||
&symbols);
|
||||
}
|
||||
|
||||
if (S_OK != hres)
|
||||
throw Exception("Call IDiaSymbol::findChildren", hres);
|
||||
|
||||
SymbolPtrList childList;
|
||||
|
||||
DiaSymbolPtr child;
|
||||
ULONG celt;
|
||||
while ( SUCCEEDED(symbols->Next(1, &child, &celt)) && (celt == 1) )
|
||||
childList.push_back( SymbolPtr( new Symbol(child, m_machineType) ) );
|
||||
|
||||
return childList;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ULONGLONG Symbol::getSize()
|
||||
{
|
||||
return callSymbol(get_length);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string Symbol::getName()
|
||||
{
|
||||
autoBstr retValue( callSymbol(get_name) );
|
||||
return retValue.asStr();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string Symbol::getUndecoratedName()
|
||||
{
|
||||
autoBstr retValue( callSymbol(get_undecoratedName) );
|
||||
return retValue.asStr();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SymbolPtr Symbol::getType()
|
||||
{
|
||||
return SymbolPtr( new Symbol(callSymbol(get_type), m_machineType) );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SymbolPtr Symbol::getIndexType()
|
||||
{
|
||||
return SymbolPtr( new Symbol(callSymbol(get_arrayIndexType), m_machineType) );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ULONG Symbol::getSymTag()
|
||||
{
|
||||
return callSymbol(get_symTag);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ULONG Symbol::getRva()
|
||||
{
|
||||
return callSymbol(get_relativeVirtualAddress);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ULONGLONG Symbol::getVa()
|
||||
{
|
||||
return callSymbol(get_virtualAddress);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ULONG Symbol::getLocType()
|
||||
{
|
||||
return callSymbol(get_locationType);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LONG Symbol::getOffset()
|
||||
{
|
||||
return callSymbol(get_offset);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ULONG Symbol::getCount()
|
||||
{
|
||||
return callSymbol(get_count);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int Symbol::getVirtualBasePointerOffset()
|
||||
{
|
||||
return callSymbol(get_virtualBasePointerOffset);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ULONG Symbol::getVirtualBaseDispIndex()
|
||||
{
|
||||
return callSymbol(get_virtualBaseDispIndex);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ULONG Symbol::getVirtualBaseDispSize()
|
||||
{
|
||||
SymbolPtr baseTableType = SymbolPtr( new Symbol( callSymbol(get_virtualBaseTableType), m_machineType ) );
|
||||
|
||||
return (ULONG)baseTableType->getType()->getSize();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ULONG Symbol::getSection()
|
||||
{
|
||||
return callSymbol(get_targetSection);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Symbol::getValueImpl(IDiaSymbol *_symbol, VARIANT &vtValue)
|
||||
{
|
||||
HRESULT hres = _symbol->get_value(&vtValue);
|
||||
if (S_OK != hres)
|
||||
throw Exception("Call IDiaSymbol::get_value", hres);
|
||||
}
|
||||
|
||||
void Symbol::getValue( VARIANT &vtValue)
|
||||
{
|
||||
HRESULT hres = m_symbol->get_value(&vtValue);
|
||||
if (S_OK != hres)
|
||||
throw Exception("Call IDiaSymbol::get_value", hres);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
python::object Symbol::getValue()
|
||||
{
|
||||
VARIANT vtValue = { VT_EMPTY };
|
||||
getValueImpl(m_symbol, vtValue);
|
||||
switch (vtValue.vt)
|
||||
{
|
||||
case VT_I1:
|
||||
case VT_UI1:
|
||||
return python::object( static_cast<ULONG>(vtValue.bVal) );
|
||||
|
||||
case VT_BOOL:
|
||||
return python::object( static_cast<bool>(!!vtValue.iVal) );
|
||||
|
||||
case VT_I2:
|
||||
case VT_UI2:
|
||||
return python::object( static_cast<ULONG>(vtValue.iVal) );
|
||||
|
||||
case VT_I4:
|
||||
case VT_UI4:
|
||||
case VT_INT:
|
||||
case VT_UINT:
|
||||
case VT_ERROR:
|
||||
case VT_HRESULT:
|
||||
return python::object( vtValue.lVal );
|
||||
|
||||
case VT_I8:
|
||||
case VT_UI8:
|
||||
return python::object( vtValue.llVal );
|
||||
|
||||
case VT_R4:
|
||||
return python::object( double(vtValue.fltVal) );
|
||||
|
||||
case VT_R8:
|
||||
return python::object( vtValue.dblVal );
|
||||
|
||||
case VT_BSTR:
|
||||
return python::object( autoBstr::asStr(vtValue.bstrVal).c_str() );
|
||||
|
||||
}
|
||||
throw Exception("Unknown value type");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool Symbol::isBasicType()
|
||||
{
|
||||
DWORD baseType = btNoType;
|
||||
return
|
||||
SUCCEEDED( m_symbol->get_baseType(&baseType) ) &&
|
||||
(btNoType != baseType);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool Symbol::isVirtualBaseClass()
|
||||
{
|
||||
return !!callSymbol(get_virtualBaseClass);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool Symbol::isIndirectVirtualBaseClass()
|
||||
{
|
||||
return !!callSymbol(get_indirectVirtualBaseClass);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ULONG Symbol::getBaseType()
|
||||
{
|
||||
return callSymbol(get_baseType);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ULONG Symbol::getBitPosition()
|
||||
{
|
||||
return callSymbol(get_bitPosition);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ULONG Symbol::getIndexId()
|
||||
{
|
||||
return callSymbol(get_symIndexId);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ULONG Symbol::getUdtKind()
|
||||
{
|
||||
return callSymbol(get_udtKind);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ULONG Symbol::getDataKind()
|
||||
{
|
||||
return callSymbol(get_dataKind);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ULONG Symbol::getRegisterId()
|
||||
{
|
||||
return callSymbol(get_registerId);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool Symbol::isConstant()
|
||||
{
|
||||
return !!callSymbol(get_constType);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SymbolPtr Symbol::getChildByName(const std::string &_name)
|
||||
{
|
||||
DiaEnumSymbolsPtr symbols;
|
||||
HRESULT hres =
|
||||
m_symbol->findChildren(
|
||||
SymTagNull,
|
||||
toWStr(_name),
|
||||
nsCaseSensitive,
|
||||
&symbols);
|
||||
if (S_OK != hres)
|
||||
throw Exception("Call IDiaSymbol::findChildren", hres);
|
||||
|
||||
LONG count;
|
||||
hres = symbols->get_Count(&count);
|
||||
if (S_OK != hres)
|
||||
throw Exception("Call IDiaEnumSymbols::get_Count", hres);
|
||||
|
||||
if (!count)
|
||||
throw Exception(_name + " not found");
|
||||
|
||||
if (count != 1)
|
||||
throw Exception(_name + " is not unique");
|
||||
|
||||
DiaSymbolPtr child;
|
||||
hres = symbols->Item(0, &child);
|
||||
if (S_OK != hres)
|
||||
throw Exception("Call IDiaEnumSymbols::Item", hres);
|
||||
|
||||
return SymbolPtr( new Symbol(child, m_machineType) );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string Symbol::print()
|
||||
{
|
||||
return printImpl(m_symbol, m_machineType);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool Symbol::eq(Symbol &rhs)
|
||||
{
|
||||
return getIndexId() == rhs.getIndexId();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GlobalScope::GlobalScope(
|
||||
__inout DiaDataSourcePtr &dataSource,
|
||||
__inout DiaSessionPtr &_session,
|
||||
__inout DiaSymbolPtr &_globalScope
|
||||
) : Symbol(_globalScope, CV_CFL_80386)
|
||||
, m_dataSource( dataSource.Detach() )
|
||||
, m_session( _session.Detach() )
|
||||
{
|
||||
m_symbol->get_machineType(&m_machineType);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GlobalScopePtr GlobalScope::loadPdb(const std::string &filePath)
|
||||
{
|
||||
class CLoaderFromPdb : public IScopeDataLoader {
|
||||
public:
|
||||
CLoaderFromPdb(const std::string &filePath) : m_filePath(filePath) {}
|
||||
|
||||
virtual void loadData(IDiaDataSource *dataSource) override {
|
||||
HRESULT hres = dataSource->loadDataFromPdb( toWStr(m_filePath) );
|
||||
if ( S_OK != hres )
|
||||
throw Exception("Call IDiaDataSource::loadDataFromPdb", hres);
|
||||
}
|
||||
|
||||
private:
|
||||
const std::string &m_filePath;
|
||||
} loaderFromPdb(filePath);
|
||||
|
||||
return loadImpl(loaderFromPdb);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GlobalScopePtr GlobalScope::loadExe(const std::string &filePath, PCSTR searchPath /*= NULL*/)
|
||||
{
|
||||
if (!searchPath)
|
||||
searchPath = "SRV**\\\\symbols\\symbols";
|
||||
|
||||
class CLoaderForExe : public IScopeDataLoader {
|
||||
public:
|
||||
CLoaderForExe(const std::string &filePath, PCSTR searchPath)
|
||||
: m_filePath(filePath), m_searchPath(searchPath)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void loadData(IDiaDataSource *dataSource) override {
|
||||
LoadCallback loadCallback;
|
||||
HRESULT hres =
|
||||
dataSource->loadDataForExe( toWStr(m_filePath), toWStr(m_searchPath), &loadCallback );
|
||||
if ( S_OK != hres )
|
||||
throw Exception("Call IDiaDataSource::loadDataForExe", hres);
|
||||
}
|
||||
|
||||
private:
|
||||
const std::string &m_filePath;
|
||||
const std::string m_searchPath;
|
||||
} loaderForExe(filePath, searchPath);
|
||||
|
||||
return loadImpl(loaderForExe);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GlobalScopePtr GlobalScope::loadImpl(IScopeDataLoader &ScopeDataLoader)
|
||||
{
|
||||
DiaDataSourcePtr dataSource;
|
||||
|
||||
HRESULT hres =
|
||||
dataSource.CoCreateInstance(__uuidof(DiaSource), NULL, CLSCTX_INPROC_SERVER);
|
||||
if ( S_OK != hres )
|
||||
throw Exception("Call ::CoCreateInstance", hres);
|
||||
|
||||
ScopeDataLoader.loadData(dataSource);
|
||||
|
||||
DiaSessionPtr _session;
|
||||
hres = dataSource->openSession(&_session);
|
||||
if ( S_OK != hres )
|
||||
throw Exception("Call IDiaDataSource::openSession", hres);
|
||||
|
||||
DiaSymbolPtr _globalScope;
|
||||
hres = _session->get_globalScope(&_globalScope);
|
||||
if ( S_OK != hres )
|
||||
throw Exception("Call IDiaSymbol::get_globalScope", hres);
|
||||
|
||||
return GlobalScopePtr( new GlobalScope(dataSource, _session, _globalScope) );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SymbolPtr GlobalScope::findByRvaImpl(
|
||||
__in ULONG rva,
|
||||
__in ULONG symTag,
|
||||
__out LONG &displacement
|
||||
)
|
||||
{
|
||||
DiaSymbolPtr child;
|
||||
HRESULT hres =
|
||||
m_session->findSymbolByRVAEx(
|
||||
rva,
|
||||
static_cast<enum SymTagEnum>(symTag),
|
||||
&child,
|
||||
&displacement);
|
||||
if (S_OK != hres)
|
||||
throw Exception("Call IDiaSession::findSymbolByRVAEx", hres);
|
||||
if (!child)
|
||||
throw Exception("Call IDiaSession::findSymbolByRVAEx", E_UNEXPECTED);
|
||||
|
||||
return SymbolPtr( new Symbol(child, m_machineType) );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SymbolPtr GlobalScope::findByVaImpl(
|
||||
__in ULONGLONG va,
|
||||
__in ULONG symTag,
|
||||
__out LONG &displacement
|
||||
)
|
||||
{
|
||||
DiaSymbolPtr child;
|
||||
HRESULT hres =
|
||||
m_session->findSymbolByVAEx(
|
||||
va,
|
||||
static_cast<enum SymTagEnum>(symTag),
|
||||
&child,
|
||||
&displacement);
|
||||
if (S_OK != hres)
|
||||
throw Exception("Call IDiaSession::findSymbolByVAEx", hres);
|
||||
if (!child)
|
||||
throw Exception("Call IDiaSession::findSymbolByVAEx", E_UNEXPECTED);
|
||||
|
||||
return SymbolPtr( new Symbol(child, m_machineType) );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SymbolPtr GlobalScope::getSymbolById(ULONG symId)
|
||||
{
|
||||
DiaSymbolPtr _symbol;
|
||||
HRESULT hres = m_session->symbolById(symId, &_symbol);
|
||||
if (S_OK != hres)
|
||||
throw Exception("Call IDiaSession::findSymbolByRVAEx", hres);
|
||||
if (!_symbol)
|
||||
throw Exception("Call IDiaSession::findSymbolByRVAEx", E_UNEXPECTED);
|
||||
|
||||
return SymbolPtr( new Symbol(_symbol, m_machineType) );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ULONGLONG GlobalScope::getLoadAddress()
|
||||
{
|
||||
ULONGLONG loadAddress;
|
||||
HRESULT hres = m_session->get_loadAddress(&loadAddress);
|
||||
if (S_OK != hres)
|
||||
throw Exception("Call IDiaSession::get_loadAddress", hres);
|
||||
return loadAddress;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void GlobalScope::setLoadAddress(ULONGLONG loadAddress)
|
||||
{
|
||||
HRESULT hres = m_session->put_loadAddress(loadAddress);
|
||||
if (S_OK != hres)
|
||||
throw Exception("Call IDiaSession::put_loadAddress", hres);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
@ -1,373 +0,0 @@
|
||||
|
||||
#pragma once
|
||||
#include <set>
|
||||
|
||||
#include <boost\smart_ptr\scoped_ptr.hpp>
|
||||
|
||||
#include <cvconst.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "dbgexcept.h"
|
||||
|
||||
namespace pyDia {
|
||||
|
||||
typedef CComPtr< IDiaSymbol > DiaSymbolPtr;
|
||||
typedef CComPtr< IDiaEnumSymbols > DiaEnumSymbolsPtr;
|
||||
typedef CComPtr< IDiaDataSource > DiaDataSourcePtr;
|
||||
typedef CComPtr< IDiaSession > DiaSessionPtr;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// DIA Exceptions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class Exception : public pykd::SymbolException {
|
||||
public:
|
||||
Exception(const std::string &desc, HRESULT hres)
|
||||
: SymbolException( makeFullDesc(desc, hres) )
|
||||
, m_hres(hres)
|
||||
{
|
||||
}
|
||||
|
||||
Exception(const std::string &desc)
|
||||
: SymbolException(descPrefix + desc)
|
||||
, m_hres(S_FALSE)
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT getRes() const {
|
||||
return m_hres;
|
||||
}
|
||||
private:
|
||||
|
||||
static const std::string descPrefix;
|
||||
|
||||
static std::string makeFullDesc(const std::string &desc, HRESULT hres);
|
||||
|
||||
HRESULT m_hres;
|
||||
};
|
||||
|
||||
class Symbol;
|
||||
typedef boost::shared_ptr< Symbol > SymbolPtr;
|
||||
typedef std::list< SymbolPtr > SymbolPtrList;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Symbol
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class Symbol {
|
||||
public:
|
||||
Symbol()
|
||||
{
|
||||
throw Exception("DiaSymbol must be created over factory from DiaScope::...");
|
||||
}
|
||||
Symbol(__inout DiaSymbolPtr &_symbol, DWORD machineType)
|
||||
: m_machineType(machineType)
|
||||
{
|
||||
m_symbol = _symbol.Detach();
|
||||
}
|
||||
Symbol(__in IDiaSymbol *_symbol, DWORD machineType)
|
||||
: m_machineType(machineType)
|
||||
{
|
||||
m_symbol = _symbol;
|
||||
}
|
||||
|
||||
|
||||
SymbolPtrList findChildrenImpl(
|
||||
ULONG symTag,
|
||||
const std::string &name = "",
|
||||
DWORD nameCmpFlags = 0
|
||||
);
|
||||
|
||||
python::list findChildrenEx(
|
||||
ULONG symTag,
|
||||
const std::string &name = "",
|
||||
DWORD nameCmpFlags = 0
|
||||
)
|
||||
{
|
||||
return toPyList( findChildrenImpl(symTag, name, nameCmpFlags) );
|
||||
}
|
||||
|
||||
python::list findChildren(
|
||||
const std::string &name
|
||||
)
|
||||
{
|
||||
return toPyList( findChildrenImpl(SymTagNull, name, nsfCaseSensitive) );
|
||||
}
|
||||
|
||||
ULONGLONG getSize();
|
||||
|
||||
std::string getName();
|
||||
std::string getUndecoratedName();
|
||||
|
||||
SymbolPtr getType();
|
||||
|
||||
SymbolPtr getIndexType();
|
||||
|
||||
ULONG getSymTag();
|
||||
|
||||
ULONG getRva();
|
||||
ULONGLONG getVa();
|
||||
|
||||
ULONG getLocType();
|
||||
|
||||
LONG getOffset();
|
||||
|
||||
ULONG getCount();
|
||||
|
||||
static void getValueImpl(IDiaSymbol *_symbol, VARIANT &vtValue);
|
||||
python::object getValue();
|
||||
void getValue( VARIANT &vtValue);
|
||||
|
||||
bool isBasicType();
|
||||
|
||||
bool isVirtualBaseClass();
|
||||
|
||||
bool isIndirectVirtualBaseClass();
|
||||
|
||||
ULONG getBaseType();
|
||||
|
||||
ULONG getBitPosition();
|
||||
|
||||
ULONG getIndexId();
|
||||
|
||||
ULONG getUdtKind();
|
||||
|
||||
ULONG getDataKind();
|
||||
|
||||
ULONG getRegisterId();
|
||||
|
||||
ULONG getMachineType() const {
|
||||
return m_machineType;
|
||||
}
|
||||
|
||||
SymbolPtr getChildByName(const std::string &_name);
|
||||
|
||||
template<ULONG symTag>
|
||||
ULONG getChildCount();
|
||||
|
||||
ULONG getChildCount() {
|
||||
return getChildCount<SymTagNull>();
|
||||
}
|
||||
|
||||
template<ULONG symTag>
|
||||
SymbolPtr getChildByIndex(ULONG _index );
|
||||
|
||||
SymbolPtr getChildByIndex(ULONG _index ) {
|
||||
return getChildByIndex<SymTagNull>( _index );
|
||||
}
|
||||
|
||||
bool isConstant();
|
||||
|
||||
std::string print();
|
||||
|
||||
bool eq(Symbol &rhs);
|
||||
|
||||
int getVirtualBasePointerOffset();
|
||||
|
||||
ULONG getVirtualBaseDispIndex();
|
||||
|
||||
ULONG getVirtualBaseDispSize();
|
||||
|
||||
ULONG getSection();
|
||||
|
||||
public:
|
||||
typedef std::pair<ULONG, const char *> ValueNameEntry;
|
||||
|
||||
static const ValueNameEntry dataKindName[DataIsConstant + 1];
|
||||
|
||||
static const ValueNameEntry symTagName[SymTagMax];
|
||||
|
||||
static const ValueNameEntry locTypeName[LocTypeMax];
|
||||
|
||||
static const ValueNameEntry basicTypeName[];
|
||||
static const size_t cntBasicTypeName;
|
||||
|
||||
static const ValueNameEntry udtKindName[];
|
||||
static const size_t cntUdtKindName;
|
||||
|
||||
static const ValueNameEntry i386RegName[];
|
||||
static const size_t cntI386RegName;
|
||||
|
||||
static const ValueNameEntry amd64RegName[];
|
||||
static const size_t cntAmd64RegName;
|
||||
|
||||
static std::string getBasicTypeName( ULONG basicType );
|
||||
|
||||
protected:
|
||||
|
||||
// Check symbols loop
|
||||
class checkSymLoop
|
||||
{
|
||||
public:
|
||||
checkSymLoop(checkSymLoop *prev)
|
||||
: m_symSetPtr( prev ? prev->m_symSetPtr : symSetPtr(new symSet) )
|
||||
{
|
||||
}
|
||||
|
||||
bool check(IDiaSymbol *_symbol)
|
||||
{
|
||||
DWORD symIndexId = 0;
|
||||
_symbol->get_symIndexId(&symIndexId);
|
||||
return !m_symSetPtr->insert(symIndexId).second;
|
||||
}
|
||||
|
||||
private:
|
||||
typedef std::set<DWORD> symSet;
|
||||
typedef boost::shared_ptr<symSet> symSetPtr;
|
||||
symSetPtr m_symSetPtr;
|
||||
};
|
||||
|
||||
static std::string printImpl(
|
||||
IDiaSymbol *_symbol,
|
||||
DWORD machineType,
|
||||
ULONG indent = 0,
|
||||
checkSymLoop *checkLoopPrev = NULL,
|
||||
const char *prefix = NULL
|
||||
);
|
||||
|
||||
template <typename TRet>
|
||||
TRet callSymbolT(
|
||||
HRESULT(STDMETHODCALLTYPE IDiaSymbol::*method)(TRet *),
|
||||
const char *methodName
|
||||
)
|
||||
{
|
||||
TRet retValue;
|
||||
HRESULT hres = (m_symbol->*method)(&retValue);
|
||||
if (S_OK != hres)
|
||||
throw Exception(std::string("Call IDiaSymbol::") + methodName, hres);
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
DiaSymbolPtr m_symbol;
|
||||
DWORD m_machineType;
|
||||
};
|
||||
|
||||
class GlobalScope;
|
||||
typedef boost::shared_ptr< GlobalScope > GlobalScopePtr;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Global scope: source + sessions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class GlobalScope : public Symbol {
|
||||
public:
|
||||
GlobalScope() {}
|
||||
|
||||
// GlobalScope factory
|
||||
static GlobalScopePtr loadPdb(const std::string &filePath);
|
||||
static GlobalScopePtr loadExe(const std::string &filePath, PCSTR searchPath = NULL);
|
||||
|
||||
// RVA -> Symbol
|
||||
python::tuple findByRva(
|
||||
ULONG rva,
|
||||
ULONG symTag
|
||||
)
|
||||
{
|
||||
LONG displacement;
|
||||
SymbolPtr child = findByRvaImpl(rva, symTag, displacement);
|
||||
return python::make_tuple(child, displacement);
|
||||
}
|
||||
SymbolPtr findByRvaImpl(
|
||||
__in ULONG rva,
|
||||
__in ULONG symTag,
|
||||
__out LONG &displacement
|
||||
);
|
||||
|
||||
// VA -> Symbol
|
||||
python::tuple findByVa(
|
||||
ULONG va,
|
||||
ULONG symTag
|
||||
)
|
||||
{
|
||||
LONG displacement;
|
||||
SymbolPtr child = findByVaImpl(va, symTag, displacement);
|
||||
return python::make_tuple(child, displacement);
|
||||
}
|
||||
SymbolPtr findByVaImpl(
|
||||
__in ULONGLONG va,
|
||||
__in ULONG symTag,
|
||||
__out LONG &displacement
|
||||
);
|
||||
|
||||
// get symbol by unique index
|
||||
SymbolPtr getSymbolById(ULONG symId);
|
||||
|
||||
// get/set load address
|
||||
ULONGLONG getLoadAddress();
|
||||
void setLoadAddress(ULONGLONG loadAddress);
|
||||
|
||||
private:
|
||||
interface IScopeDataLoader {
|
||||
virtual ~IScopeDataLoader() {}
|
||||
virtual void loadData(IDiaDataSource *dataSource) = 0;
|
||||
};
|
||||
static GlobalScopePtr loadImpl(IScopeDataLoader &ScopeDataLoader);
|
||||
|
||||
GlobalScope(
|
||||
__inout DiaDataSourcePtr &dataSource,
|
||||
__inout DiaSessionPtr &_session,
|
||||
__inout DiaSymbolPtr &_globalScope
|
||||
);
|
||||
|
||||
DiaDataSourcePtr m_dataSource;
|
||||
DiaSessionPtr m_session;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<ULONG symTag>
|
||||
ULONG Symbol::getChildCount()
|
||||
{
|
||||
DiaEnumSymbolsPtr symbols;
|
||||
HRESULT hres =
|
||||
m_symbol->findChildren(
|
||||
static_cast<enum SymTagEnum>(symTag),
|
||||
NULL,
|
||||
nsCaseSensitive,
|
||||
&symbols);
|
||||
if (S_OK != hres)
|
||||
throw Exception("Call IDiaSymbol::findChildren", hres);
|
||||
|
||||
LONG count;
|
||||
hres = symbols->get_Count(&count);
|
||||
if (S_OK != hres)
|
||||
throw Exception("Call IDiaEnumSymbols::get_Count", hres);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<ULONG symTag>
|
||||
SymbolPtr Symbol::getChildByIndex(ULONG _index )
|
||||
{
|
||||
DiaEnumSymbolsPtr symbols;
|
||||
HRESULT hres =
|
||||
m_symbol->findChildren(
|
||||
static_cast<enum SymTagEnum>(symTag),
|
||||
NULL,
|
||||
nsCaseSensitive,
|
||||
&symbols);
|
||||
if (S_OK != hres)
|
||||
throw Exception("Call IDiaSymbol::findChildren", hres);
|
||||
|
||||
LONG count;
|
||||
hres = symbols->get_Count(&count);
|
||||
if (S_OK != hres)
|
||||
throw Exception("Call IDiaEnumSymbols::get_Count", hres);
|
||||
|
||||
if (LONG(_index) >= count)
|
||||
{
|
||||
PyErr_SetString(PyExc_IndexError, "Index out of range");
|
||||
boost::python::throw_error_already_set();
|
||||
}
|
||||
|
||||
DiaSymbolPtr child;
|
||||
hres = symbols->Item(_index, &child);
|
||||
if (S_OK != hres)
|
||||
throw Exception("Call IDiaEnumSymbols::Item", hres);
|
||||
|
||||
return SymbolPtr( new Symbol(child, m_machineType) );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
};
|
@ -1,6 +1,7 @@
|
||||
#include "stdafx.h"
|
||||
#include "dbgengine.h"
|
||||
#include "module.h"
|
||||
#include "dbgexcept.h"
|
||||
|
||||
namespace pykd {
|
||||
|
||||
@ -32,6 +33,38 @@ Module::Module(ULONG64 offset )
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SymbolPtr& Module::getSymScope()
|
||||
{
|
||||
do {
|
||||
|
||||
if ( m_symScope )
|
||||
break;
|
||||
|
||||
std::string symbolName = getModuleSymbolFileName( m_base );
|
||||
if ( symbolName.empty() )
|
||||
break;
|
||||
|
||||
m_symScope = loadSymbolFile( symbolName );
|
||||
|
||||
} while( false );
|
||||
|
||||
if ( !m_symScope )
|
||||
throw SymbolException( "failed to find symbol file" );
|
||||
|
||||
return m_symScope;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ULONG Module::getRvaByName(const std::string &symName)
|
||||
{
|
||||
SymbolPtr &symScope = getSymScope();
|
||||
SymbolPtr child = symScope->getChildByName( symName );
|
||||
return child->getRva();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}; // end of namespace pykd
|
||||
|
||||
|
||||
@ -39,6 +72,17 @@ Module::Module(ULONG64 offset )
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//#include "module.h"
|
||||
//#include "dbgclient.h"
|
||||
//#include "dbgmem.h"
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "intbase.h"
|
||||
#include "symengine.h"
|
||||
|
||||
namespace pykd {
|
||||
|
||||
@ -48,15 +49,31 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
ULONG64
|
||||
getSymbol( const std::string &symbolname ) {
|
||||
return m_base + getRvaByName(symbolname);
|
||||
}
|
||||
|
||||
ULONG
|
||||
getSymbolRva( const std::string &symbolname ) {
|
||||
return getRvaByName(symbolname);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
SymbolPtr& getSymScope();
|
||||
|
||||
BaseTypeVariant getValue() {
|
||||
return BaseTypeVariant(m_base);
|
||||
}
|
||||
|
||||
ULONG getRvaByName(const std::string &symName);
|
||||
|
||||
std::string m_name;
|
||||
ULONG64 m_base;
|
||||
ULONG m_size;
|
||||
|
||||
SymbolPtr m_symScope;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -45,7 +45,7 @@
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/bigobj"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""$(DIA_SDK_ROOT)\include";"$(DBG_SDK_ROOT)\inc";"$(BOOST_ROOT)";"$(PYTHON_ROOT)\x86\include""
|
||||
AdditionalIncludeDirectories=""$(ProjectDir)";"$(DIA_SDK_ROOT)\include";"$(DBG_SDK_ROOT)\inc";"$(BOOST_ROOT)";"$(PYTHON_ROOT)\x64\include""
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;PYKD_EXPORTS"
|
||||
GeneratePreprocessedFile="0"
|
||||
KeepComments="false"
|
||||
@ -126,7 +126,7 @@
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/bigobj"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""$(DIA_SDK_ROOT)\include";"$(DBG_SDK_ROOT)\inc";"$(BOOST_ROOT)";"$(PYTHON_ROOT)\x64\include""
|
||||
AdditionalIncludeDirectories=""$(ProjectDir)";"$(DIA_SDK_ROOT)\include";"$(DBG_SDK_ROOT)\inc";"$(BOOST_ROOT)";"$(PYTHON_ROOT)\x64\include""
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;PYKD_EXPORTS"
|
||||
GeneratePreprocessedFile="0"
|
||||
KeepComments="false"
|
||||
@ -207,7 +207,7 @@
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/bigobj"
|
||||
AdditionalIncludeDirectories=""$(DIA_SDK_ROOT)\include";"$(DBG_SDK_ROOT)\inc";"$(BOOST_ROOT)";"$(PYTHON_ROOT)\x86\include""
|
||||
AdditionalIncludeDirectories=""$(ProjectDir)";"$(DIA_SDK_ROOT)\include";"$(DBG_SDK_ROOT)\inc";"$(BOOST_ROOT)";"$(PYTHON_ROOT)\x64\include""
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;PYKD_EXPORTS"
|
||||
RuntimeLibrary="2"
|
||||
UsePrecompiledHeader="2"
|
||||
@ -287,7 +287,7 @@
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/bigobj"
|
||||
AdditionalIncludeDirectories=""$(DIA_SDK_ROOT)\include";"$(DBG_SDK_ROOT)\inc";"$(BOOST_ROOT)";"$(PYTHON_ROOT)\x64\include""
|
||||
AdditionalIncludeDirectories=""$(ProjectDir)";"$(DIA_SDK_ROOT)\include";"$(DBG_SDK_ROOT)\inc";"$(BOOST_ROOT)";"$(PYTHON_ROOT)\x64\include""
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;PYKD_EXPORTS"
|
||||
RuntimeLibrary="2"
|
||||
UsePrecompiledHeader="2"
|
||||
@ -357,6 +357,10 @@
|
||||
RelativePath=".\dbgext.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\dbgmem.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\module.cpp"
|
||||
>
|
||||
@ -405,10 +409,6 @@
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\windbgeng.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
@ -423,6 +423,10 @@
|
||||
RelativePath=".\dbgexcept.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\dbgmem.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\intbase.h"
|
||||
>
|
||||
@ -444,7 +448,11 @@
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\windbgeng.h"
|
||||
RelativePath=".\symengine.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\typeinfo.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
@ -458,6 +466,38 @@
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="win"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\win\dbgeng.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\win\dbgeng.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\win\memory.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\win\utils.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="dia"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\dia\diawrapper.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\dia\diawrapper.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
|
@ -5,27 +5,46 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "pykdver.h"
|
||||
|
||||
#include "dbgengine.h"
|
||||
#include "symengine.h"
|
||||
|
||||
#include "module.h"
|
||||
#include "intbase.h"
|
||||
#include "dbgexcept.h"
|
||||
#include "dbgmem.h"
|
||||
|
||||
using namespace pykd;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
static const std::string pykdVersion = PYKD_VERSION_BUILD_STR
|
||||
#ifdef _DEBUG
|
||||
" <DBG>"
|
||||
#endif // _DEBUG
|
||||
;
|
||||
|
||||
using namespace pykd;
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
BOOST_PYTHON_FUNCTION_OVERLOADS( loadChars_, loadChars, 2, 3 );
|
||||
BOOST_PYTHON_FUNCTION_OVERLOADS( loadWChars_, loadWChars, 2, 3 );
|
||||
BOOST_PYTHON_FUNCTION_OVERLOADS( loadBytes_, loadBytes, 2, 3 );
|
||||
BOOST_PYTHON_FUNCTION_OVERLOADS( loadWords_, loadWords, 2, 3 );
|
||||
BOOST_PYTHON_FUNCTION_OVERLOADS( loadDWords_, loadDWords, 2, 3 );
|
||||
BOOST_PYTHON_FUNCTION_OVERLOADS( loadQWords_, loadQWords, 2, 3 );
|
||||
BOOST_PYTHON_FUNCTION_OVERLOADS( loadSignBytes_, loadSignBytes, 2, 3 );
|
||||
BOOST_PYTHON_FUNCTION_OVERLOADS( loadSignWords_, loadSignWords, 2, 3 );
|
||||
BOOST_PYTHON_FUNCTION_OVERLOADS( loadSignDWords_, loadSignDWords, 2, 3 );
|
||||
BOOST_PYTHON_FUNCTION_OVERLOADS( loadSignQWords_, loadSignQWords, 2, 3 );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
BOOST_PYTHON_MODULE( pykd )
|
||||
{
|
||||
python::scope().attr("version") = pykdVersion;
|
||||
|
||||
// Manage debug target
|
||||
|
||||
python::def( "startProcess", &startProcess,
|
||||
"Start process for debugging");
|
||||
python::def( "detachProcess", &detachProcess,
|
||||
@ -36,6 +55,41 @@ BOOST_PYTHON_MODULE( pykd )
|
||||
python::def( "go", &debugGo,
|
||||
"Go debugging" );
|
||||
|
||||
// Manage target memory access
|
||||
python::def( "loadBytes", &loadBytes, loadBytes_( python::args( "offset", "count", "phyAddr" ),
|
||||
"Read the block of the target's memory and return it as liat of unsigned bytes" ) );
|
||||
python::def( "loadWords", &loadWords, loadWords_( python::args( "offset", "count", "phyAddr" ),
|
||||
"Read the block of the target's memory and return it as list of unsigned shorts" ) );
|
||||
python::def( "loadDWords", &loadDWords, loadDWords_( python::args( "offset", "count", "phyAddr" ),
|
||||
"Read the block of the target's memory and return it as list of unsigned long ( double word )" ) );
|
||||
python::def( "loadQWords", &loadQWords, loadQWords_( python::args( "offset", "count", "phyAddr" ),
|
||||
"Read the block of the target's memory and return it as list of unsigned long long ( quad word )" ) );
|
||||
python::def( "loadSignBytes", &loadSignBytes, loadSignBytes_( python::args( "offset", "count", "phyAddr" ),
|
||||
"Read the block of the target's memory and return it as list of signed bytes" ) );
|
||||
python::def( "loadSignWords", &loadSignWords, loadSignWords_( python::args( "offset", "count", "phyAddr" ),
|
||||
"Read the block of the target's memory and return it as list of signed words" ) );
|
||||
python::def( "loadSignDWords", &loadSignDWords, loadSignDWords_( python::args( "offset", "count", "phyAddr" ),
|
||||
"Read the block of the target's memory and return it as list of signed longs" ) );
|
||||
python::def( "loadSignQWords", &loadSignQWords, loadSignQWords_( python::args( "offset", "count", "phyAddr" ),
|
||||
"Read the block of the target's memory and return it as list of signed long longs" ) );
|
||||
//python::def( "loadChars", &loadChars, loadChars_( python::args( "address", "count", "phyAddr" ),
|
||||
// "Load string from target memory" ) );
|
||||
//python::def( "loadWChars", &loadWChars, loadWChars_( python::args( "address", "count", "phyAddr" ),
|
||||
// "Load string from target memory" ) );
|
||||
//python::def( "loadCStr", &loadCStr,
|
||||
// "Load string from the target buffer containing 0-terminated ansi-string" );
|
||||
//python::def( "loadWStr", &loadWStr,
|
||||
// "Load string from the target buffer containing 0-terminated unicode-string" );
|
||||
//python::def( "loadUnicodeString", &loadUnicodeStr,
|
||||
// "Return string represention of windows UNICODE_STRING type" );
|
||||
//python::def( "loadAnsiString", &loadAnsiStr,
|
||||
// "Return string represention of windows ANSU_STRING type" );
|
||||
//python::def( "loadPtrList", &loadPtrList,
|
||||
// "Return list of pointers, each points to next" );
|
||||
//python::def( "loadPtrs", &loadPtrArray,
|
||||
// "Read the block of the target's memory and return it as a list of pointers" );
|
||||
|
||||
|
||||
python::class_<intBase>( "intBase", "intBase", python::no_init )
|
||||
.def( python::init<python::object&>() )
|
||||
.def( "__eq__", &intBase::eq )
|
||||
@ -92,7 +146,9 @@ BOOST_PYTHON_MODULE( pykd )
|
||||
.def("name", &Module::getName,
|
||||
"Return name of the module" )
|
||||
.def("reload", &Module::reloadSymbols,
|
||||
"(Re)load symbols for the module" );
|
||||
"(Re)load symbols for the module" )
|
||||
.def("__getattr__", &Module::getSymbol,
|
||||
"Return address of the symbol" );
|
||||
|
||||
//.def("image", &Module::getImageName,
|
||||
// "Return name of the image of the module" )
|
||||
@ -139,9 +195,9 @@ BOOST_PYTHON_MODULE( pykd )
|
||||
//.def( "__str__", &Module::print );
|
||||
|
||||
pykd::exception<DbgException>( "BaseException", "Pykd base exception class" );
|
||||
//pykd::exception<MemoryException,DbgException>( "MemoryException", "Target memory access exception class" );
|
||||
pykd::exception<MemoryException,DbgException>( "MemoryException", "Target memory access exception class" );
|
||||
//pykd::exception<WaitEventException,DbgException>( "WaitEventException", "Debug interface access exception" );
|
||||
//pykd::exception<SymbolException,DbgException>( "SymbolException", "Symbol exception" );
|
||||
pykd::exception<SymbolException,DbgException>( "SymbolException", "Symbol exception" );
|
||||
//pykd::exception<pyDia::Exception,SymbolException>( "DiaException", "Debug interface access exception" );
|
||||
//pykd::exception<TypeException,SymbolException>( "TypeException", "type exception" );
|
||||
//pykd::exception<AddSyntheticSymbolException,DbgException>( "AddSynSymbolException", "synthetic symbol exception" );
|
||||
|
1010
pykd/typeinfo.h
1010
pykd/typeinfo.h
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "windbgeng.h"
|
||||
#include "win/dbgeng.h"
|
||||
#include "dbgexcept.h"
|
||||
|
||||
namespace pykd {
|
||||
@ -174,32 +174,55 @@ std::string getModuleName( ULONG64 baseOffset )
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ULONG64 addr64( ULONG64 addr )
|
||||
std::string getModuleSymbolFileName( ULONG64 baseOffset )
|
||||
{
|
||||
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
|
||||
|
||||
HRESULT hres;
|
||||
HRESULT hres;
|
||||
IMAGEHLP_MODULEW64 moduleInfo = {};
|
||||
|
||||
hres = g_dbgEng->advanced->GetSymbolInformation(
|
||||
DEBUG_SYMINFO_IMAGEHLP_MODULEW64,
|
||||
baseOffset,
|
||||
0,
|
||||
&moduleInfo,
|
||||
sizeof(moduleInfo),
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
NULL );
|
||||
|
||||
ULONG processorMode;
|
||||
hres = g_dbgEng->control->GetActualProcessorType( &processorMode );
|
||||
if ( FAILED( hres ) )
|
||||
throw DbgException( "IDebugControl::GetEffectiveProcessorType failed" );
|
||||
throw DbgException( "IDebugAdvanced2::GetSymbolInformation failed" );
|
||||
|
||||
switch( processorMode )
|
||||
if (!*moduleInfo.LoadedPdbName)
|
||||
{
|
||||
case IMAGE_FILE_MACHINE_I386:
|
||||
if ( *( (ULONG*)&addr + 1 ) == 0 )
|
||||
return (ULONG64)(LONG)addr;
|
||||
std::wstring param = L"/f ";
|
||||
param += moduleInfo.ImageName;
|
||||
|
||||
case IMAGE_FILE_MACHINE_AMD64:
|
||||
break;
|
||||
hres = g_dbgEng->symbols->ReloadWide( param.c_str() );
|
||||
if ( FAILED( hres ) )
|
||||
throw DbgException("IDebugSymbols::Reload failed" );
|
||||
|
||||
default:
|
||||
throw DbgException( "Unknown processor type" );
|
||||
break;
|
||||
hres = g_dbgEng->advanced->GetSymbolInformation(
|
||||
DEBUG_SYMINFO_IMAGEHLP_MODULEW64,
|
||||
baseOffset,
|
||||
0,
|
||||
&moduleInfo,
|
||||
sizeof(moduleInfo),
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
NULL );
|
||||
|
||||
if ( FAILED( hres ) )
|
||||
throw DbgException( "IDebugAdvanced2::GetSymbolInformation failed" );
|
||||
}
|
||||
|
||||
return addr;
|
||||
char pdbName[ 256 ];
|
||||
WideCharToMultiByte( CP_ACP, 0, moduleInfo.LoadedPdbName, 256, pdbName, 256, NULL, NULL );
|
||||
|
||||
return std::string( pdbName );
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
@ -4,6 +4,9 @@
|
||||
#include "dbgexcept.h"
|
||||
#include "pyaux.h"
|
||||
|
||||
#include <dbgeng.h>
|
||||
#include <dbghelp.h>
|
||||
|
||||
namespace pykd {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
@ -18,6 +21,8 @@ public:
|
||||
CComQIPtr<IDebugControl4> control;
|
||||
CComQIPtr<IDebugSystemObjects2> system;
|
||||
CComQIPtr<IDebugSymbols3> symbols;
|
||||
CComQIPtr<IDebugDataSpaces4> dataspace;
|
||||
CComQIPtr<IDebugAdvanced2> advanced;
|
||||
|
||||
DbgEngBind( PDEBUG_CLIENT4 c )
|
||||
{
|
||||
@ -25,6 +30,8 @@ public:
|
||||
control = c;
|
||||
system = c;
|
||||
symbols = c;
|
||||
dataspace = c;
|
||||
advanced = c;
|
||||
}
|
||||
|
||||
PyThreadStateSaver pystate;
|
74
pykd/win/memory.cpp
Normal file
74
pykd/win/memory.cpp
Normal file
@ -0,0 +1,74 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "win/dbgeng.h"
|
||||
|
||||
namespace pykd {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ULONG64 addr64NoSafe( ULONG64 addr )
|
||||
{
|
||||
HRESULT hres;
|
||||
|
||||
ULONG processorMode;
|
||||
hres = g_dbgEng->control->GetActualProcessorType( &processorMode );
|
||||
if ( FAILED( hres ) )
|
||||
throw DbgException( "IDebugControl::GetEffectiveProcessorType failed" );
|
||||
|
||||
switch( processorMode )
|
||||
{
|
||||
case IMAGE_FILE_MACHINE_I386:
|
||||
if ( *( (ULONG*)&addr + 1 ) == 0 )
|
||||
return (ULONG64)(LONG)addr;
|
||||
|
||||
case IMAGE_FILE_MACHINE_AMD64:
|
||||
break;
|
||||
|
||||
default:
|
||||
throw DbgException( "Unknown processor type" );
|
||||
break;
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
ULONG64 addr64( ULONG64 addr )
|
||||
{
|
||||
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
|
||||
|
||||
return addr64NoSafe( addr );
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void readMemory( ULONG64 offset, PVOID buffer, ULONG length, bool phyAddr )
|
||||
{
|
||||
PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );
|
||||
|
||||
HRESULT hres;
|
||||
|
||||
if ( phyAddr == false )
|
||||
{
|
||||
offset = addr64NoSafe( offset );
|
||||
|
||||
// workitem/10473 workaround
|
||||
ULONG64 nextAddress;
|
||||
hres =
|
||||
g_dbgEng->dataspace->GetNextDifferentlyValidOffsetVirtual( offset, &nextAddress );
|
||||
|
||||
DBG_UNREFERENCED_LOCAL_VARIABLE(nextAddress);
|
||||
|
||||
hres = g_dbgEng->dataspace->ReadVirtual( offset, buffer, length, NULL );
|
||||
}
|
||||
else
|
||||
{
|
||||
hres = g_dbgEng->dataspace->ReadPhysical( offset, buffer, length, NULL );
|
||||
}
|
||||
|
||||
if ( FAILED( hres ) )
|
||||
throw MemoryException( offset, phyAddr );
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}; //namespace pykd
|
@ -12,16 +12,20 @@ sys.path.insert(0, os.path.dirname(sys.argv[1]))
|
||||
import pykd
|
||||
|
||||
import target
|
||||
import moduletest
|
||||
|
||||
import intbase
|
||||
import memtest
|
||||
import moduletest
|
||||
|
||||
|
||||
def getTestSuite( singleName = "" ):
|
||||
if singleName == "":
|
||||
return unittest.TestSuite(
|
||||
[
|
||||
unittest.TestLoader().loadTestsFromTestCase( target.TargetTest ),
|
||||
unittest.TestLoader().loadTestsFromTestCase( moduletest.ModuleTest ),
|
||||
unittest.TestLoader().loadTestsFromTestCase( intbase.IntBaseTest ),
|
||||
unittest.TestLoader().loadTestsFromTestCase( moduletest.ModuleTest ),
|
||||
unittest.TestLoader().loadTestsFromTestCase( memtest.MemoryTest )
|
||||
] )
|
||||
else:
|
||||
return unittest.TestSuite( unittest.TestLoader().loadTestsFromName( singleName ) )
|
||||
|
Loading…
Reference in New Issue
Block a user