diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp index 519342d..61064bc 100644 --- a/pykd/dbgext.cpp +++ b/pykd/dbgext.cpp @@ -73,6 +73,16 @@ pycmd( PDEBUG_CLIENT4 client, PCSTR args ) //////////////////////////////////////////////////////////////////////////////// +static python::dict genDict(const pyDia::Symbol::ValueNameEntry srcValues[], size_t cntValues) +{ + python::dict resDict; + for (size_t i = 0; i < cntValues; ++i) + resDict[srcValues[i].first] = srcValues[i].second; + return resDict; +} + +//////////////////////////////////////////////////////////////////////////////// + #define DEF_PY_CONST_ULONG(x) \ python::scope().attr(#x) = ULONG(##x) @@ -94,7 +104,6 @@ BOOST_PYTHON_MODULE( pykd ) "Return size of the module" ) .def("name", &pykd::Module::getName, "Return name of the module" ); - python::def( "diaOpenPdb", &pyDia::GlobalScope::openPdb, "Open pdb file for quering debug symbols. Return DiaSymbol of global scope"); @@ -110,6 +119,8 @@ BOOST_PYTHON_MODULE( pykd ) "Retrieves the name of the symbol" ) .def( "type", &pyDia::Symbol::getType, "Retrieves the symbol that represents the type for this symbol" ) + .def( "indexType", &pyDia::Symbol::getIndexType, + "Retrieves the symbol interface of the array index type of the symbol" ) .def( "rva", &pyDia::Symbol::getRva, "Retrieves the relative virtual address (RVA) of the location") .def( "symTag", &pyDia::Symbol::getSymTag, @@ -118,8 +129,12 @@ BOOST_PYTHON_MODULE( pykd ) "Retrieves the location type of a data symbol: LocIsXxx" ) .def( "value", &pyDia::Symbol::getValue, "Retrieves the value of a constant") + .def( "isBasic", &pyDia::Symbol::isBasicType, + "Retrieves a flag of basic type for symbol") + .def( "baseType", &pyDia::Symbol::getBaseType, + "Retrieves the base type for this symbol") .def( "__str__", &pyDia::Symbol::print) - .def("__getattr__", &pyDia::Symbol::getChildByName) +// .def("__getattr__", &pyDia::Symbol::getChildByName) .def("__len__", &pyDia::Symbol::getChildCount ) .def("__getitem__", &pyDia::Symbol::getChildByIndex); @@ -157,6 +172,8 @@ BOOST_PYTHON_MODULE( pykd ) DEF_PY_CONST_ULONG(SymTagCustomType); DEF_PY_CONST_ULONG(SymTagManagedType); DEF_PY_CONST_ULONG(SymTagDimension); + python::scope().attr("diaSymTagName") = + genDict(pyDia::Symbol::symTagName, _countof(pyDia::Symbol::symTagName)); // search options for symbol and file names DEF_PY_CONST_ULONG(nsfCaseSensitive); @@ -182,6 +199,29 @@ BOOST_PYTHON_MODULE( pykd ) DEF_PY_CONST_ULONG(LocIsIlRel); DEF_PY_CONST_ULONG(LocInMetaData); DEF_PY_CONST_ULONG(LocIsConstant); + python::scope().attr("diaLocTypeName") = + genDict(pyDia::Symbol::symTagName, _countof(pyDia::Symbol::locTypeName)); + + DEF_PY_CONST_ULONG(btNoType); + DEF_PY_CONST_ULONG(btVoid); + DEF_PY_CONST_ULONG(btChar); + DEF_PY_CONST_ULONG(btWChar); + DEF_PY_CONST_ULONG(btInt); + DEF_PY_CONST_ULONG(btUInt); + DEF_PY_CONST_ULONG(btFloat); + DEF_PY_CONST_ULONG(btBCD); + DEF_PY_CONST_ULONG(btBool); + DEF_PY_CONST_ULONG(btLong); + DEF_PY_CONST_ULONG(btULong); + DEF_PY_CONST_ULONG(btCurrency); + DEF_PY_CONST_ULONG(btDate); + DEF_PY_CONST_ULONG(btVariant); + DEF_PY_CONST_ULONG(btComplex); + DEF_PY_CONST_ULONG(btBit); + DEF_PY_CONST_ULONG(btBSTR); + DEF_PY_CONST_ULONG(btHresult); + python::scope().attr("diaBasicType") = + genDict(pyDia::Symbol::basicTypeName, pyDia::Symbol::cntBasicTypeName); // exception: // base exception diff --git a/pykd/diawrapper.cpp b/pykd/diawrapper.cpp index 376111b..39fe9f8 100644 --- a/pykd/diawrapper.cpp +++ b/pykd/diawrapper.cpp @@ -17,53 +17,117 @@ 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" +#define _DEF_SYM_TAG_VAL(x) Symbol::ValueNameEntry(SymTag##x, #x) +const Symbol::ValueNameEntry Symbol::symTagName[SymTagMax] = { + _DEF_SYM_TAG_VAL(Null), + _DEF_SYM_TAG_VAL(Exe), + _DEF_SYM_TAG_VAL(Compiland), + _DEF_SYM_TAG_VAL(CompilandDetails), + _DEF_SYM_TAG_VAL(CompilandEnv), + _DEF_SYM_TAG_VAL(Function), + _DEF_SYM_TAG_VAL(Block), + _DEF_SYM_TAG_VAL(Data), + _DEF_SYM_TAG_VAL(Annotation), + _DEF_SYM_TAG_VAL(Label), + _DEF_SYM_TAG_VAL(PublicSymbol), + _DEF_SYM_TAG_VAL(UDT), + _DEF_SYM_TAG_VAL(Enum), + _DEF_SYM_TAG_VAL(FunctionType), + _DEF_SYM_TAG_VAL(PointerType), + _DEF_SYM_TAG_VAL(ArrayType), + _DEF_SYM_TAG_VAL(BaseType), + _DEF_SYM_TAG_VAL(Typedef), + _DEF_SYM_TAG_VAL(BaseClass), + _DEF_SYM_TAG_VAL(Friend), + _DEF_SYM_TAG_VAL(FunctionArgType), + _DEF_SYM_TAG_VAL(FuncDebugStart), + _DEF_SYM_TAG_VAL(FuncDebugEnd), + _DEF_SYM_TAG_VAL(UsingNamespace), + _DEF_SYM_TAG_VAL(VTableShape), + _DEF_SYM_TAG_VAL(VTable), + _DEF_SYM_TAG_VAL(Custom), + _DEF_SYM_TAG_VAL(Thunk), + _DEF_SYM_TAG_VAL(CustomType), + _DEF_SYM_TAG_VAL(ManagedType), + _DEF_SYM_TAG_VAL(Dimension) }; +#undef _DEF_SYM_TAG_VAL -const char *Symbol::locTypeName[LocTypeMax] = { - "Null", - "Static", - "TLS", - "RegRel", - "ThisRel", - "Enregistered", - "BitField", - "Slot", - "IlRel", - "InMetaData", - "Constant" +#define _DEF_LOC_TYPE(x) Symbol::ValueNameEntry(LocIs##x, #x) +const Symbol::ValueNameEntry Symbol::locTypeName[LocTypeMax] = { + _DEF_LOC_TYPE(Null), + _DEF_LOC_TYPE(Static), + _DEF_LOC_TYPE(TLS), + _DEF_LOC_TYPE(RegRel), + _DEF_LOC_TYPE(ThisRel), + _DEF_LOC_TYPE(Enregistered), + _DEF_LOC_TYPE(BitField), + _DEF_LOC_TYPE(Slot), + _DEF_LOC_TYPE(IlRel), + Symbol::ValueNameEntry(LocInMetaData, "InMetaData"), + _DEF_LOC_TYPE(Constant) }; +#undef _DEF_LOC_TYPE + +#define _DEF_BASIC_TYPE(x) Symbol::ValueNameEntry(bt##x, #x) +const Symbol::ValueNameEntry Symbol::basicTypeName[] = { + _DEF_BASIC_TYPE(NoType), + _DEF_BASIC_TYPE(Void), + _DEF_BASIC_TYPE(Char), + _DEF_BASIC_TYPE(WChar), + _DEF_BASIC_TYPE(Int), + _DEF_BASIC_TYPE(UInt), + _DEF_BASIC_TYPE(Float), + _DEF_BASIC_TYPE(BCD), + _DEF_BASIC_TYPE(Bool), + _DEF_BASIC_TYPE(Long), + _DEF_BASIC_TYPE(ULong), + _DEF_BASIC_TYPE(Currency), + _DEF_BASIC_TYPE(Date), + _DEF_BASIC_TYPE(Variant), + _DEF_BASIC_TYPE(Complex), + _DEF_BASIC_TYPE(Bit), + _DEF_BASIC_TYPE(BSTR), + _DEF_BASIC_TYPE(Hresult) +}; +#undef _DEF_BASIC_TYPE + +const size_t Symbol::cntBasicTypeName = _countof(Symbol::basicTypeName); + +//////////////////////////////////////////////////////////////////////////////// + +#define callSymbol(retType, method) \ +do { \ + throwIfNull(__FUNCTION__); \ + retType retValue; \ + HRESULT hres = m_symbol->##method(&retValue); \ + if (FAILED(hres)) \ + throw Exception("Call IDiaSymbol::" #method, hres); \ + return retValue; \ +} while(false) + +#define callSymbolDword(method) callSymbol(DWORD, method) +#define callSymbolUlonglong(method) callSymbol(ULONGLONG, method) + +#define callSymbolObjectFromSymbol(method) \ +do { \ + throwIfNull(__FUNCTION__); \ + DiaSymbolPtr retSymbol; \ + HRESULT hres = m_symbol->##method(&retSymbol); \ + if (S_OK != hres) \ + throw Exception("Call IDiaSymbol::" #method, hres); \ + return python::object( Symbol(retSymbol) ); \ +} while(false) + +#define callSymbolStr(method) \ +do { \ + throwIfNull(__FUNCTION__); \ + autoBstr bstrName; \ + HRESULT hres = m_symbol->##method(&bstrName); \ + if (S_OK != hres) \ + throw Exception("Call IDiaSymbol" #method, hres); \ + return bstrName.asStr(); \ +} while(false) //////////////////////////////////////////////////////////////////////////////// @@ -139,84 +203,49 @@ python::list Symbol::findChildrenImpl( ULONGLONG Symbol::getSize() { - throwIfNull(__FUNCTION__); - - ULONGLONG retValue; - HRESULT hres = m_symbol->get_length(&retValue); - if (S_OK != hres) - throw Exception("Call IDiaSymbol::get_length", hres); - - return retValue; + callSymbolUlonglong(get_length); } //////////////////////////////////////////////////////////////////////////////// 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(); + callSymbolStr(get_name); } //////////////////////////////////////////////////////////////////////////////// python::object Symbol::getType() { - throwIfNull(__FUNCTION__); + callSymbolObjectFromSymbol(get_type); +} - 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) ); +python::object Symbol::getIndexType() +{ + callSymbolObjectFromSymbol(get_arrayIndexType); } //////////////////////////////////////////////////////////////////////////////// ULONG Symbol::getSymTag() { - throwIfNull(__FUNCTION__); - - DWORD retValue; - HRESULT hres = m_symbol->get_symTag(&retValue); - if (S_OK != hres) - throw Exception("Call IDiaSymbol::get_symTag", hres); - - return retValue; + callSymbolDword(get_symTag); } //////////////////////////////////////////////////////////////////////////////// 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; + callSymbolDword(get_relativeVirtualAddress); } //////////////////////////////////////////////////////////////////////////////// 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; + callSymbolDword(get_locationType); } //////////////////////////////////////////////////////////////////////////////// @@ -270,6 +299,32 @@ python::object Symbol::getValue() //////////////////////////////////////////////////////////////////////////////// +bool Symbol::isBasicType() +{ + throwIfNull(__FUNCTION__); + + DWORD baseType = btNoType; + return + SUCCEEDED( m_symbol->get_baseType(&baseType) ) && + (btNoType != baseType); +} + +//////////////////////////////////////////////////////////////////////////////// + +ULONG Symbol::getBaseType() +{ + callSymbolDword(get_baseType); +} + +//////////////////////////////////////////////////////////////////////////////// + +ULONG Symbol::getBitPosition() +{ + callSymbolDword(get_bitPosition); +} + +//////////////////////////////////////////////////////////////////////////////// + python::object Symbol::getChildByName(const std::string &_name) { throwIfNull(__FUNCTION__); @@ -373,7 +428,7 @@ std::string Symbol::print() sstream << "symTag: "; HRESULT hres = m_symbol->get_symTag(&dwValue); if ((S_OK == hres) && dwValue < _countof(symTagName)) - sstream << symTagName[dwValue]; + sstream << symTagName[dwValue].second; else sstream << ""; sstream << ", "; @@ -389,7 +444,7 @@ std::string Symbol::print() if ((S_OK == hres) && dwValue < _countof(locTypeName)) { sstream << std::endl; - sstream << "Location: " << locTypeName[dwValue]; + sstream << "Location: " << locTypeName[dwValue].second; if (dwValue == LocIsStatic) { hres = m_symbol->get_relativeVirtualAddress(&dwValue); @@ -452,6 +507,20 @@ std::string Symbol::print() break; } } + + hres = m_symbol->get_baseType(&dwValue); + if (SUCCEEDED(hres) && btNoType != dwValue) + { + for (ULONG i = 0; i < cntBasicTypeName; ++i) + { + if (basicTypeName[i].first == dwValue) + { + sstream << std::endl; + sstream << "Basic type is " << basicTypeName[i].second; + break; + } + } + } } return sstream.str(); } diff --git a/pykd/diawrapper.h b/pykd/diawrapper.h index d2e64f6..f990da2 100644 --- a/pykd/diawrapper.h +++ b/pykd/diawrapper.h @@ -70,33 +70,53 @@ public: } ULONGLONG getSize(); + std::string getName(); + python::object getType(); + + python::object getIndexType(); + ULONG getSymTag(); + ULONG getRva(); + ULONG getLocType(); + python::object getValue(); + bool isBasicType(); + + ULONG getBaseType(); + + ULONG getBitPosition(); + python::object getChildByName(const std::string &_name); ULONG getChildCount(); python::object getChildByIndex(ULONG _index); std::string print(); + +public: + typedef std::pair ValueNameEntry; + + static const ValueNameEntry symTagName[SymTagMax]; + static const ValueNameEntry locTypeName[LocTypeMax]; + static const ValueNameEntry basicTypeName[]; + static const size_t cntBasicTypeName; + protected: void throwIfNull(const char *desc) { if (!m_symbol) - throw Exception(std::string(desc) + " failed, object not preinitialized"); + throw Exception(std::string(desc) + " failed, DIA object is not initialized"); } Symbol(__inout DiaSymbolPtr &_symbol) { m_symbol = _symbol.Detach(); } - static const char *symTagName[SymTagMax]; - static const char *locTypeName[LocTypeMax]; - DiaSymbolPtr m_symbol; };