From f241ea851b75edba2748baab8fcfeb82a6270339 Mon Sep 17 00:00:00 2001 From: "SND\\EreTIk_cp" Date: Sun, 18 Sep 2011 16:50:42 +0000 Subject: [PATCH] [+] dia get type [+] dia get location [+] dia print to string git-svn-id: https://pykd.svn.codeplex.com/svn@69841 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgext.cpp | 32 +++- pykd/diawrapper.cpp | 386 +++++++++++++++++++++++++++++++++--------- pykd/diawrapper.h | 31 +++- pykd/pykd_2008.vcproj | 4 + pykd/utils.h | 78 +++++++++ 5 files changed, 439 insertions(+), 92 deletions(-) create mode 100644 pykd/utils.h diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp index 556119e..ab8b668 100644 --- a/pykd/dbgext.cpp +++ b/pykd/dbgext.cpp @@ -3,7 +3,6 @@ #include #include -#include #include "module.h" #include "diawrapper.h" @@ -98,13 +97,19 @@ BOOST_PYTHON_MODULE( pykd ) "Retrieves the children of the symbol" ) .def( "size", &pyDia::Symbol::getSize, "Retrieves the number of bits or bytes of memory used by the object represented by this symbol" ) - //.def( "getName", &pyDia::Symbol::getName, - // "Retrieves the name of the symbol" ) - //.def( "getType", &pyDia::Symbol::getType, - // "Retrieves the symbol that represents the type for this symbol" ) - .def( "getSymTag", &pyDia::Symbol::getSymTag, + .def( "name", &pyDia::Symbol::getName, + "Retrieves the name of the symbol" ) + .def( "type", &pyDia::Symbol::getType, + "Retrieves the symbol that represents the type for this symbol" ) + .def( "rva", &pyDia::Symbol::getRva, + "Retrieves the relative virtual address (RVA) of the location") + .def( "symTag", &pyDia::Symbol::getSymTag, "Retrieves the symbol type classifier: SymTagXxx" ) - //__str__ &pyDia::Symbol::print + .def( "locType", &pyDia::Symbol::getLocType, + "Retrieves the location type of a data symbol: LocIsXxx" ) + .def( "value", &pyDia::Symbol::getValue, + "Retrieves the value of a constant") + .def( "__str__", &pyDia::Symbol::print) .def("__getattr__", &pyDia::Symbol::getChildByName) .def("__len__", &pyDia::Symbol::getChildCount ) .def("__getitem__", &pyDia::Symbol::getChildByIndex); @@ -156,6 +161,19 @@ BOOST_PYTHON_MODULE( pykd ) DEF_PY_CONST_ULONG(nsRegularExpression); DEF_PY_CONST_ULONG(nsCaseInRegularExpression); + // location type + DEF_PY_CONST_ULONG(LocIsNull); + DEF_PY_CONST_ULONG(LocIsStatic); + DEF_PY_CONST_ULONG(LocIsTLS); + DEF_PY_CONST_ULONG(LocIsRegRel); + DEF_PY_CONST_ULONG(LocIsThisRel); + DEF_PY_CONST_ULONG(LocIsEnregistered); + DEF_PY_CONST_ULONG(LocIsBitField); + DEF_PY_CONST_ULONG(LocIsSlot); + DEF_PY_CONST_ULONG(LocIsIlRel); + DEF_PY_CONST_ULONG(LocInMetaData); + DEF_PY_CONST_ULONG(LocIsConstant); + // exception: // base exception python::class_ dbgExceptionClass( "BaseException", diff --git a/pykd/diawrapper.cpp b/pykd/diawrapper.cpp index b93aa7f..376111b 100644 --- a/pykd/diawrapper.cpp +++ b/pykd/diawrapper.cpp @@ -1,28 +1,77 @@ #include "stdafx.h" -#include #include #include #include "diawrapper.h" - -using namespace pykd; +#include "utils.h" namespace pyDia { //////////////////////////////////////////////////////////////////////////////// PyObject *Exception::diaExceptTypeObject = NULL; + const std::string Exception::descPrefix("pyDia: "); //////////////////////////////////////////////////////////////////////////////// +const char *Symbol::symTagName[SymTagMax] = { + "Null", + "Exe", + "Compiland", + "CompilandDetails", + "CompilandEnv", + "Function", + "Block", + "Data", + "Annotation", + "Label", + "PublicSymbol", + "UDT", + "Enum", + "FunctionType", + "PointerType", + "ArrayType", + "BaseType", + "Typedef", + "BaseClass", + "Friend", + "FunctionArgType", + "FuncDebugStart", + "FuncDebugEnd", + "UsingNamespace", + "VTableShape", + "VTable", + "Custom", + "Thunk", + "CustomType", + "ManagedType", + "Dimension" +}; + +const char *Symbol::locTypeName[LocTypeMax] = { + "Null", + "Static", + "TLS", + "RegRel", + "ThisRel", + "Enregistered", + "BitField", + "Slot", + "IlRel", + "InMetaData", + "Constant" +}; + +//////////////////////////////////////////////////////////////////////////////// + std::string Exception::makeFullDesc(const std::string &desc, HRESULT hres) { - std::strstream res; - res << descPrefix << desc << " failed" << std::endl; - res << "Return value is 0x" << std::hex << hres; + std::stringstream sstream; + sstream << descPrefix << desc << " failed" << std::endl; + sstream << "Return value is 0x" << std::hex << hres; PCHAR errMessage = NULL; FormatMessageA( @@ -35,16 +84,16 @@ std::string Exception::makeFullDesc(const std::string &desc, HRESULT hres) NULL); if (errMessage) { - res << ":" << std::endl; - res << errMessage; + sstream << ": " << std::endl; + sstream << errMessage; LocalFree(errMessage); } else { - res << std::endl; + sstream << std::endl; } - return res.str(); + return sstream.str(); } //////////////////////////////////////////////////////////////////////////////// @@ -56,25 +105,6 @@ void Exception::exceptionTranslate( const Exception &e ) PyErr_SetObject( diaExceptTypeObject, pyExcept.ptr() ); } -//////////////////////////////////////////////////////////////////////////////// -// Convert to OLESTR helper -//////////////////////////////////////////////////////////////////////////////// -class toOleStr { -public: - toOleStr(const std::string &sz) - { - m_buf.resize( sz.size() + 1, L'\0' ); - ::MultiByteToWideChar( CP_ACP, 0, sz.c_str(), sz.size(), &m_buf[0], m_buf.size() ); - } - - operator const OLECHAR *() const { - return m_buf.empty() ? NULL : &m_buf[0]; - } - -private: - std::vector m_buf; -}; - //////////////////////////////////////////////////////////////////////////////// python::list Symbol::findChildrenImpl( @@ -85,19 +115,19 @@ python::list Symbol::findChildrenImpl( { throwIfNull(__FUNCTION__); - CComPtr< IDiaEnumSymbols > symbols; + DiaEnumSymbolsPtr symbols; HRESULT hres = m_symbol->findChildren( static_cast(symTag), - toOleStr(name), + toWStr(name), nameCmpFlags, &symbols); - if (FAILED(hres)) - throw Exception("Get list of children", hres); + if (S_OK != hres) + throw Exception("Call IDiaSymbol::findChildren", hres); python::list childList; - CComPtr< IDiaSymbol > child; + DiaSymbolPtr child; ULONG celt; while ( SUCCEEDED(symbols->Next(1, &child, &celt)) && (celt == 1) ) childList.append( Symbol(child) ); @@ -113,57 +143,162 @@ ULONGLONG Symbol::getSize() ULONGLONG retValue; HRESULT hres = m_symbol->get_length(&retValue); - if (FAILED(hres)) - throw Exception("Get length", hres); + if (S_OK != hres) + throw Exception("Call IDiaSymbol::get_length", hres); return retValue; } //////////////////////////////////////////////////////////////////////////////// +std::string Symbol::getName() +{ + throwIfNull(__FUNCTION__); + + autoBstr bstrName; + HRESULT hres = m_symbol->get_name(&bstrName); + if (S_OK != hres) + throw Exception("Call IDiaSymbol::get_name", hres); + + return bstrName.asStr(); +} + +//////////////////////////////////////////////////////////////////////////////// + +python::object Symbol::getType() +{ + throwIfNull(__FUNCTION__); + + DiaSymbolPtr _type; + HRESULT hres = m_symbol->get_type(&_type); + if (S_OK != hres) + throw Exception("Call IDiaSymbol::get_type", hres); + + return python::object( Symbol(_type) ); +} + +//////////////////////////////////////////////////////////////////////////////// + ULONG Symbol::getSymTag() { throwIfNull(__FUNCTION__); DWORD retValue; HRESULT hres = m_symbol->get_symTag(&retValue); - if (FAILED(hres)) - throw Exception("Get symbol type", hres); + if (S_OK != hres) + throw Exception("Call IDiaSymbol::get_symTag", hres); return retValue; } //////////////////////////////////////////////////////////////////////////////// +ULONG Symbol::getRva() +{ + throwIfNull(__FUNCTION__); + + DWORD retValue; + HRESULT hres = m_symbol->get_relativeVirtualAddress(&retValue); + if (S_OK != hres) + throw Exception("Call IDiaSymbol::get_relativeVirtualAddress", hres); + + return retValue; +} + +//////////////////////////////////////////////////////////////////////////////// + +ULONG Symbol::getLocType() +{ + throwIfNull(__FUNCTION__); + + DWORD retValue; + HRESULT hres = m_symbol->get_locationType(&retValue); + if (S_OK != hres) + throw Exception("Call IDiaSymbol::get_locationType", hres); + + return retValue; +} + +//////////////////////////////////////////////////////////////////////////////// + +python::object Symbol::getValue() +{ + throwIfNull(__FUNCTION__); + + VARIANT variant = { VT_EMPTY }; + HRESULT hres = m_symbol->get_value(&variant); + if (S_OK != hres) + throw Exception("Call IDiaSymbol::get_value", hres); + + switch (variant.vt) + { + case VT_I1: + case VT_UI1: + return python::object( static_cast(variant.bVal) ); + + case VT_BOOL: + return python::object( static_cast(!!variant.iVal) ); + + case VT_I2: + case VT_UI2: + return python::object( static_cast(variant.iVal) ); + + case VT_I4: + case VT_UI4: + case VT_INT: + case VT_UINT: + case VT_ERROR: + case VT_HRESULT: + return python::object( variant.lVal ); + + case VT_I8: + case VT_UI8: + return python::object( variant.llVal ); + + case VT_R4: + return python::object( variant.fltVal ); + + case VT_R8: + return python::object( variant.dblVal ); + + case VT_BSTR: + return python::object( autoBstr::asStr(variant.bstrVal).c_str() ); + + } + throw Exception("Unknown value type"); +} + +//////////////////////////////////////////////////////////////////////////////// + python::object Symbol::getChildByName(const std::string &_name) { throwIfNull(__FUNCTION__); - CComPtr< IDiaEnumSymbols > symbols; + DiaEnumSymbolsPtr symbols; HRESULT hres = m_symbol->findChildren( SymTagNull, - toOleStr(_name), + toWStr(_name), nsCaseSensitive, &symbols); - if (FAILED(hres)) - throw Exception("Get child by name", hres); + if (S_OK != hres) + throw Exception("Call IDiaSymbol::findChildren", hres); LONG count; hres = symbols->get_Count(&count); - if (FAILED(hres)) - throw Exception("Get count of children", hres); + if (S_OK != hres) + throw Exception("Call IDiaEnumSymbols::get_Count", hres); if (!count) - throw Exception(_name + " not found as children"); + throw Exception(_name + " not found"); if (count != 1) throw Exception(_name + " is not unique"); - CComPtr< IDiaSymbol > child; + DiaSymbolPtr child; hres = symbols->Item(0, &child); - if (FAILED(hres)) - throw Exception("Build child object", hres); + if (S_OK != hres) + throw Exception("Call IDiaEnumSymbols::Item", hres); return python::object( Symbol(child) ); } @@ -174,20 +309,20 @@ ULONG Symbol::getChildCount() { throwIfNull(__FUNCTION__); - CComPtr< IDiaEnumSymbols > symbols; + DiaEnumSymbolsPtr symbols; HRESULT hres = m_symbol->findChildren( SymTagNull, NULL, nsCaseSensitive, &symbols); - if (FAILED(hres)) - throw Exception("Get child count", hres); + if (S_OK != hres) + throw Exception("Call IDiaSymbol::findChildren", hres); LONG count; hres = symbols->get_Count(&count); - if (FAILED(hres)) - throw Exception("Get count of count", hres); + if (S_OK != hres) + throw Exception("Call IDiaEnumSymbols::get_Count", hres); return count; } @@ -198,38 +333,135 @@ python::object Symbol::getChildByIndex(ULONG _index) { throwIfNull(__FUNCTION__); - CComPtr< IDiaEnumSymbols > symbols; + DiaEnumSymbolsPtr symbols; HRESULT hres = m_symbol->findChildren( SymTagNull, NULL, nsCaseSensitive, &symbols); - if (FAILED(hres)) - throw Exception("Get child by index", hres); + if (S_OK != hres) + throw Exception("Call IDiaSymbol::findChildren", hres); LONG count; hres = symbols->get_Count(&count); - if (FAILED(hres)) - throw Exception("Get count of children", hres); + if (S_OK != hres) + throw Exception("Call IDiaEnumSymbols::get_Count", hres); if (LONG(_index) >= count) - throw Exception("Attempt to access non-existing element: index overflow"); + throw Exception("Attempt to access non-existing element by index"); - CComPtr< IDiaSymbol > child; + DiaSymbolPtr child; hres = symbols->Item(_index, &child); - if (FAILED(hres)) - throw Exception("Build child object", hres); + if (S_OK != hres) + throw Exception("Call IDiaEnumSymbols::Item", hres); return python::object( Symbol(child) ); } //////////////////////////////////////////////////////////////////////////////// +std::string Symbol::print() +{ + std::stringstream sstream; + if (m_symbol) + { + DWORD dwValue; + autoBstr bstrValue; + VARIANT vtValue = { VT_EMPTY }; + + sstream << "symTag: "; + HRESULT hres = m_symbol->get_symTag(&dwValue); + if ((S_OK == hres) && dwValue < _countof(symTagName)) + sstream << symTagName[dwValue]; + else + sstream << ""; + sstream << ", "; + + hres = m_symbol->get_name(&bstrValue); + if (S_OK == hres) + sstream << "\"" << bstrValue.asStr().c_str() << "\""; + else + sstream << ""; + bstrValue.free(); + + hres = m_symbol->get_locationType(&dwValue); + if ((S_OK == hres) && dwValue < _countof(locTypeName)) + { + sstream << std::endl; + sstream << "Location: " << locTypeName[dwValue]; + if (dwValue == LocIsStatic) + { + hres = m_symbol->get_relativeVirtualAddress(&dwValue); + if (S_OK == hres) + sstream << ", RVA: 0x" << std::hex << dwValue; + } + } + + hres = m_symbol->get_value(&vtValue); + if (S_OK == hres) + { + switch (vtValue.vt) + { + case VT_I1: + case VT_UI1: + sstream << std::endl << "Value is "; + sstream << std::hex << "0x" << vtValue.bVal; + break; + + case VT_BOOL: + sstream << std::endl << "Value is "; + sstream << vtValue.iVal ? "True" : "False"; + break; + + case VT_I2: + case VT_UI2: + sstream << std::endl << "Value is "; + sstream << std::hex << "0x" << vtValue.iVal; + break; + + case VT_I4: + case VT_UI4: + case VT_INT: + case VT_UINT: + case VT_ERROR: + case VT_HRESULT: + sstream << std::endl << "Value is "; + sstream << std::hex << "0x" << vtValue.lVal; + break; + + case VT_I8: + case VT_UI8: + sstream << std::endl << "Value is "; + sstream << std::hex << "0x" << vtValue.llVal; + break; + + case VT_R4: + sstream << std::endl << "Value is "; + sstream << vtValue.fltVal; + break; + + case VT_R8: + sstream << std::endl << "Value is "; + sstream << vtValue.dblVal; + break; + + case VT_BSTR: + sstream << std::endl << "Value is "; + sstream << "\"" << autoBstr::asStr(vtValue.bstrVal).c_str() << "\""; + break; + } + } + } + return sstream.str(); +} + +//////////////////////////////////////////////////////////////////////////////// + GlobalScope::GlobalScope( - __inout CComPtr< IDiaDataSource > &_scope, - __inout CComPtr< IDiaSession > &_session, - __inout CComPtr< IDiaSymbol > &_globalScope + __inout DiaDataSourcePtr &_scope, + __inout DiaSessionPtr &_session, + __inout DiaSymbolPtr &_globalScope ) : Symbol(_globalScope) , m_source( _scope.Detach() ) , m_session( _session.Detach() ) @@ -240,26 +472,26 @@ GlobalScope::GlobalScope( python::object GlobalScope::openPdb(const std::string &filePath) { - CComPtr< IDiaDataSource > _scope; + DiaDataSourcePtr _scope; HRESULT hres = _scope.CoCreateInstance(__uuidof(DiaSource), NULL, CLSCTX_INPROC_SERVER); - if ( FAILED(hres) ) - throw Exception("Create scope instance", hres); + if ( S_OK != hres ) + throw Exception("Call ::CoCreateInstance", hres); - hres = _scope->loadDataFromPdb( toOleStr(filePath) ); - if ( FAILED(hres) ) - throw Exception("Load pdb file", hres); + hres = _scope->loadDataFromPdb( toWStr(filePath) ); + if ( S_OK != hres ) + throw Exception("Call IDiaDataSource::loadDataFromPdb", hres); - CComPtr< IDiaSession > _session; + DiaSessionPtr _session; hres = _scope->openSession(&_session); - if ( FAILED(hres) ) - throw Exception("Open session for querying symbols", hres); + if ( S_OK != hres ) + throw Exception("Call IDiaDataSource::openSession", hres); - CComPtr< IDiaSymbol > _globalScope; + DiaSymbolPtr _globalScope; hres = _session->get_globalScope(&_globalScope); - if ( FAILED(hres) ) - throw Exception("Retrieves a reference to the global scope", hres); + if ( S_OK != hres ) + throw Exception("Call IDiaSymbol::get_globalScope", hres); return python::object(GlobalScope(_scope, _session, _globalScope)); } diff --git a/pykd/diawrapper.h b/pykd/diawrapper.h index 36c73c8..d2e64f6 100644 --- a/pykd/diawrapper.h +++ b/pykd/diawrapper.h @@ -1,9 +1,16 @@ #pragma once + +#include #include "dbgexcept.h" namespace pyDia { +typedef CComPtr< IDiaSymbol > DiaSymbolPtr; +typedef CComPtr< IDiaEnumSymbols > DiaEnumSymbolsPtr; +typedef CComPtr< IDiaDataSource > DiaDataSourcePtr; +typedef CComPtr< IDiaSession > DiaSessionPtr; + //////////////////////////////////////////////////////////////////////////////// // DIA Exceptions //////////////////////////////////////////////////////////////////////////////// @@ -63,13 +70,18 @@ public: } ULONGLONG getSize(); - + std::string getName(); + python::object getType(); ULONG getSymTag(); + ULONG getRva(); + ULONG getLocType(); + python::object getValue(); python::object getChildByName(const std::string &_name); ULONG getChildCount(); python::object getChildByIndex(ULONG _index); + std::string print(); protected: void throwIfNull(const char *desc) @@ -78,11 +90,14 @@ protected: throw Exception(std::string(desc) + " failed, object not preinitialized"); } - Symbol(__inout CComPtr< IDiaSymbol > &_symbol) { + Symbol(__inout DiaSymbolPtr &_symbol) { m_symbol = _symbol.Detach(); } - CComPtr< IDiaSymbol > m_symbol; + static const char *symTagName[SymTagMax]; + static const char *locTypeName[LocTypeMax]; + + DiaSymbolPtr m_symbol; }; //////////////////////////////////////////////////////////////////////////////// @@ -98,13 +113,13 @@ public: private: GlobalScope( - __inout CComPtr< IDiaDataSource > &_scope, - __inout CComPtr< IDiaSession > &_session, - __inout CComPtr< IDiaSymbol > &_globalScope + __inout DiaDataSourcePtr &_scope, + __inout DiaSessionPtr &_session, + __inout DiaSymbolPtr &_globalScope ); - CComPtr< IDiaDataSource > m_source; - CComPtr< IDiaSession > m_session; + DiaDataSourcePtr m_source; + DiaSessionPtr m_session; }; //////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/pykd_2008.vcproj b/pykd/pykd_2008.vcproj index bfbca6f..a5dc5b2 100644 --- a/pykd/pykd_2008.vcproj +++ b/pykd/pykd_2008.vcproj @@ -439,6 +439,10 @@ RelativePath=".\stdafx.h" > + + const WCHAR * +//////////////////////////////////////////////////////////////////////////////// +class toWStr { +public: + toWStr(const std::string &sz) + { + m_buf.resize( sz.size() + 1, L'\0' ); + ::MultiByteToWideChar( CP_ACP, 0, sz.c_str(), sz.size(), &m_buf[0], m_buf.size() ); + } + + operator const WCHAR *() const { + return m_buf.empty() ? NULL : &m_buf[0]; + } + +private: + std::vector m_buf; +}; + +//////////////////////////////////////////////////////////////////////////////// +// BSTR wrapper +//////////////////////////////////////////////////////////////////////////////// +class autoBstr { +public: + autoBstr() : m_bstr(NULL) {} + ~autoBstr() { + free(); + } + + void free() + { + if (m_bstr) + { + SysFreeString(m_bstr); + m_bstr = NULL; + } + } + + BSTR *operator &() { + return &m_bstr; + } + operator BSTR() const { + return m_bstr; + } + + std::string asStr() const + { + return asStr(m_bstr); + } + static std::string asStr(BSTR bstr) + { + if (!bstr) + return ""; + + const int chars = static_cast( wcslen(bstr) ); + if (!chars) + return ""; + + std::string ret; + ret.resize(chars + 1, '\0'); + ::WideCharToMultiByte( + CP_ACP, + 0, + bstr, + chars, + &ret[0], + ret.size(), + NULL, + NULL); + return ret; + } + +private: + BSTR m_bstr; +};