mirror of
https://github.com/ivellioscolin/pykd.git
synced 2025-05-03 06:33:23 +08:00

[0.2.x] added : findSymbolAndDisp routine ( Return tuple(symbol_name, displacement) by virtual address ) git-svn-id: https://pykd.svn.codeplex.com/svn@82900 9b283d60-5439-405e-af05-b73fd8c4d996
645 lines
15 KiB
C++
645 lines
15 KiB
C++
#pragma once
|
|
|
|
#include <string>
|
|
|
|
#include <boost\enable_shared_from_this.hpp>
|
|
|
|
#include "udtutils.h"
|
|
#include "variant.h"
|
|
#include "symengine.h"
|
|
#include "dbgexcept.h"
|
|
|
|
namespace pykd {
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
class TypeInfo;
|
|
typedef boost::shared_ptr<TypeInfo> TypeInfoPtr;
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
class TypeInfo : boost::noncopyable, public intBase, public boost::enable_shared_from_this<TypeInfo> {
|
|
|
|
public:
|
|
|
|
static
|
|
TypeInfoPtr getTypeInfoByName( const std::string &symName );
|
|
|
|
static
|
|
ULONG64 getSymbolSize( const std::string &symName );
|
|
|
|
static
|
|
std::string findSymbol( ULONG64 offset, bool showDisplacement = true );
|
|
|
|
static
|
|
void findSymbolAndDisp( ULONG64 offset, std::string &symbolName, LONG &displacement );
|
|
|
|
static
|
|
ULONG64 getOffset( const std::string &symbolName );
|
|
|
|
static
|
|
TypeInfoPtr getTypeInfo( SymbolPtr &symScope, const std::string &symName );
|
|
|
|
static
|
|
TypeInfoPtr getTypeInfo( SymbolPtr &symbol );
|
|
|
|
static
|
|
TypeInfoPtr getBaseTypeInfo( const std::string &name, ULONG pointerSize );
|
|
|
|
static
|
|
TypeInfoPtr getBaseTypeInfo( SymbolPtr &symbol );
|
|
|
|
static
|
|
bool isBaseType( const std::string &name );
|
|
|
|
public:
|
|
|
|
TypeInfo() :
|
|
m_constant( false ),
|
|
m_ptrSize( 0 )
|
|
{}
|
|
|
|
virtual ~TypeInfo()
|
|
{}
|
|
|
|
virtual std::string print() {
|
|
std::stringstream sstr;
|
|
sstr << "Type name: " << getName();
|
|
sstr << " Size: 0x" << std::hex << getSize() << " (" << std::dec << getSize() << ")";
|
|
return sstr.str();
|
|
}
|
|
|
|
virtual std::string getName() = 0;
|
|
|
|
virtual ULONG getSize() = 0;
|
|
|
|
virtual TypeInfoPtr getField( const std::string &fieldName ) {
|
|
throw TypeException( getName(), "type is not a struct" );
|
|
}
|
|
|
|
virtual TypeInfoPtr getFieldRecursive(const std::string &fieldName ) {
|
|
throw TypeException( getName(), "type is not a struct" );
|
|
}
|
|
|
|
virtual TypeInfoPtr getFieldByIndex( ULONG index ) {
|
|
throw TypeException( getName(), "type is not a struct" );
|
|
}
|
|
|
|
virtual std::string getFieldNameByIndex( ULONG index ) {
|
|
throw TypeException( getName(), "type is not a struct" );
|
|
}
|
|
|
|
virtual ULONG getFieldOffsetByNameRecursive( const std::string &fieldName ) {
|
|
throw TypeException( getName(), "type is not a struct" );
|
|
}
|
|
|
|
virtual ULONG getFieldOffsetByNameNotRecursively( const std::string &fieldName ) {
|
|
throw TypeException( getName(), "type is not a struct" );
|
|
}
|
|
|
|
virtual ULONG getFieldOffsetByIndex( ULONG index ) {
|
|
throw TypeException( getName(), "type is not a struct" );
|
|
}
|
|
|
|
virtual ULONG getFieldCount() {
|
|
throw TypeException( getName(), "type is not a struct" );
|
|
}
|
|
|
|
virtual bool isStaticMember( const std::string& fieldName )
|
|
{
|
|
throw TypeException( getName(), "type is not a struct" );
|
|
}
|
|
|
|
virtual bool isStaticMemberByIndex( ULONG index )
|
|
{
|
|
throw TypeException( getName(), "type is not a struct" );
|
|
}
|
|
|
|
virtual ULONG64 getStaticOffsetByName( const std::string& fieldName )
|
|
{
|
|
throw TypeException( getName(), "type is not a struct" );
|
|
}
|
|
|
|
virtual ULONG64 getStaticOffsetByIndex( ULONG index )
|
|
{
|
|
throw TypeException( getName(), "type is not a struct" );
|
|
}
|
|
|
|
virtual bool isVirtualMember( const std::string& fieldName )
|
|
{
|
|
throw TypeException( getName(), "type is not a struct" );
|
|
}
|
|
|
|
virtual bool isVirtualMemberByIndex( ULONG index )
|
|
{
|
|
throw TypeException( getName(), "type is not a struct" );
|
|
}
|
|
|
|
virtual void getVirtualDisplacement( const std::string& fieldName, ULONG &virtualBasePtr, ULONG &virtualDispIndex, ULONG &virtualDispSize )
|
|
{
|
|
throw TypeException( getName(), "type is not a struct" );
|
|
}
|
|
|
|
virtual void getVirtualDisplacementByIndex( ULONG index, ULONG &virtualBasePtr, ULONG &virtualDispIndex, ULONG &virtualDispSize )
|
|
{
|
|
throw TypeException( getName(), "type is not a struct" );
|
|
}
|
|
|
|
virtual BaseTypeVariant getValue();
|
|
|
|
virtual bool isBasicType() {
|
|
return false;
|
|
}
|
|
|
|
virtual bool isPointer() {
|
|
return false;
|
|
}
|
|
|
|
virtual bool isArray() {
|
|
return false;
|
|
}
|
|
|
|
virtual bool isUserDefined() {
|
|
return false;
|
|
}
|
|
|
|
virtual bool isBitField() {
|
|
return false;
|
|
}
|
|
|
|
virtual bool isEnum() {
|
|
return false;
|
|
}
|
|
|
|
virtual ULONG getCount() {
|
|
throw TypeException( getName(), "type is not an array" );
|
|
}
|
|
|
|
virtual TypeInfoPtr getElementType() {
|
|
throw TypeException( getName(), "type is not an array" );
|
|
}
|
|
|
|
virtual ULONG getBitOffset() {
|
|
return 0;
|
|
}
|
|
|
|
virtual ULONG getBitWidth() {
|
|
return 8 * getSize();
|
|
}
|
|
|
|
virtual python::dict asMap() {
|
|
throw TypeException( getName(), "type cannot be converted to a dict" );
|
|
}
|
|
|
|
virtual TypeInfoPtr deref() {
|
|
throw TypeException( getName(), "type is not a pointer" );
|
|
}
|
|
|
|
virtual ULONG getElementCount() {
|
|
throw PyException( PyExc_TypeError, "object has no len()" );
|
|
}
|
|
|
|
virtual python::tuple getElementByIndex( ULONG index ) {
|
|
throw PyException( PyExc_TypeError, "object is unsubscriptable");
|
|
}
|
|
|
|
virtual void appendField(const std::string &fieldName, TypeInfoPtr &fieldType) {
|
|
throw TypeException( getName(), "type is not is not editable" );
|
|
}
|
|
|
|
TypeInfoPtr ptrTo();
|
|
|
|
TypeInfoPtr arrayOf( ULONG count );
|
|
|
|
virtual ULONG getAlignReq() {
|
|
return 1;
|
|
}
|
|
|
|
void setConstant( const BaseTypeVariant& var )
|
|
{
|
|
m_constant = true;
|
|
m_constantValue = var;
|
|
}
|
|
bool isConstant() const
|
|
{
|
|
return m_constant == true;
|
|
}
|
|
|
|
bool is(TypeInfo *rhs) const {
|
|
return this == rhs;
|
|
}
|
|
|
|
ULONG ptrSize() const {
|
|
return m_ptrSize;
|
|
}
|
|
|
|
protected:
|
|
|
|
std::string getComplexName();
|
|
|
|
static
|
|
TypeInfoPtr getComplexType( SymbolPtr &symScope, const std::string &symName );
|
|
|
|
static
|
|
TypeInfoPtr getRecurciveComplexType( TypeInfoPtr &lowestType, std::string &suffix, ULONG ptrSize );
|
|
|
|
bool m_constant;
|
|
|
|
BaseTypeVariant m_constantValue;
|
|
|
|
ULONG m_ptrSize;
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
template<typename T>
|
|
class TypeInfoWrapper : public TypeInfo
|
|
{
|
|
public:
|
|
TypeInfoWrapper( const std::string &name, ULONG pointerSize )
|
|
: m_name(name)
|
|
{
|
|
m_ptrSize = pointerSize;
|
|
}
|
|
|
|
private:
|
|
|
|
virtual std::string getName() {
|
|
return m_name;
|
|
}
|
|
|
|
virtual ULONG getSize() {
|
|
return sizeof(T);
|
|
}
|
|
|
|
virtual bool isBasicType() {
|
|
return true;
|
|
}
|
|
|
|
std::string m_name;
|
|
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
class BitFieldTypeInfo : public TypeInfo
|
|
{
|
|
public:
|
|
|
|
BitFieldTypeInfo( SymbolPtr &symbol );
|
|
|
|
virtual std::string getName() {
|
|
return m_name;
|
|
}
|
|
|
|
virtual ULONG getSize() {
|
|
return m_size;
|
|
}
|
|
|
|
virtual bool isBitField() {
|
|
return true;
|
|
}
|
|
|
|
virtual ULONG getBitOffset() {
|
|
return m_bitPos;
|
|
}
|
|
|
|
virtual ULONG getBitWidth() {
|
|
return m_bitWidth;
|
|
}
|
|
|
|
virtual ULONG getAlignReq() override {
|
|
return m_size;
|
|
}
|
|
|
|
private:
|
|
|
|
ULONG m_size;
|
|
ULONG m_bitWidth;
|
|
ULONG m_bitPos;
|
|
std::string m_name;
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
class UdtTypeInfoBase : public TypeInfo
|
|
{
|
|
protected:
|
|
virtual std::string getName() {
|
|
return m_name;
|
|
}
|
|
|
|
virtual TypeInfoPtr getField( const std::string &fieldName ) {
|
|
return lookupField(fieldName)->getTypeInfo();
|
|
}
|
|
|
|
virtual TypeInfoPtr getFieldByIndex( ULONG index ) {
|
|
return lookupField(index)->getTypeInfo();
|
|
}
|
|
|
|
virtual std::string getFieldNameByIndex( ULONG index ) {
|
|
return lookupField(index)->getName();
|
|
}
|
|
|
|
virtual ULONG getFieldOffsetByNameRecursive( const std::string &fieldName );
|
|
|
|
virtual TypeInfoPtr getFieldRecursive(const std::string &fieldName );
|
|
|
|
virtual ULONG getFieldOffsetByNameNotRecursively( const std::string &fieldName ) {
|
|
return lookupField(fieldName)->getOffset();
|
|
}
|
|
|
|
virtual ULONG getFieldOffsetByIndex( ULONG index ) {
|
|
return lookupField(index)->getOffset();
|
|
}
|
|
|
|
virtual bool isStaticMember( const std::string& fieldName ) {
|
|
return lookupField(fieldName)->isStaticMember();
|
|
}
|
|
|
|
virtual bool isStaticMemberByIndex( ULONG index ) {
|
|
return lookupField(index)->isStaticMember();
|
|
}
|
|
|
|
virtual ULONG64 getStaticOffsetByName( const std::string& fieldName ) {
|
|
return lookupField(fieldName)->getStaticOffset();
|
|
}
|
|
|
|
virtual ULONG64 getStaticOffsetByIndex( ULONG index ) {
|
|
return lookupField(index)->getStaticOffset();
|
|
}
|
|
|
|
virtual ULONG getFieldCount() {
|
|
if ( !m_fieldsGot )
|
|
{
|
|
refreshFields();
|
|
m_fieldsGot = true;
|
|
}
|
|
return m_fields.count();
|
|
}
|
|
|
|
virtual ULONG getElementCount() {
|
|
return getFieldCount();
|
|
}
|
|
|
|
virtual python::tuple getElementByIndex( ULONG index ) {
|
|
return python::make_tuple( getFieldNameByIndex(index), getFieldByIndex(index) );
|
|
}
|
|
|
|
virtual std::string print();
|
|
|
|
virtual bool isUserDefined() {
|
|
return true;
|
|
}
|
|
|
|
virtual ULONG getAlignReq() override;
|
|
|
|
virtual bool isVirtualMember( const std::string& fieldName )
|
|
{
|
|
return lookupField(fieldName)->isVirtualMember();
|
|
}
|
|
|
|
virtual bool isVirtualMemberByIndex( ULONG index )
|
|
{
|
|
return lookupField(index)->isVirtualMember();
|
|
}
|
|
|
|
virtual void getVirtualDisplacement( const std::string& fieldName, ULONG &virtualBasePtr, ULONG &virtualDispIndex, ULONG &virtualDispSize );
|
|
virtual void getVirtualDisplacementByIndex( ULONG index, ULONG &virtualBasePtr, ULONG &virtualDispIndex, ULONG &virtualDispSize );
|
|
|
|
protected:
|
|
|
|
UdtTypeInfoBase(const std::string &typeName) :
|
|
m_fields(typeName),
|
|
m_name(typeName),
|
|
m_fieldsGot( false )
|
|
{}
|
|
|
|
virtual void refreshFields() {}
|
|
|
|
void push_back(const UdtFieldPtr &field) {
|
|
m_fields.push_back(field);
|
|
}
|
|
|
|
template <typename T>
|
|
const UdtFieldPtr &lookupField( T index)const {
|
|
if ( !m_fieldsGot )
|
|
{
|
|
refreshFields();
|
|
m_fieldsGot = true;
|
|
}
|
|
return m_fields.lookup(index);
|
|
}
|
|
|
|
template <typename T>
|
|
UdtFieldPtr &lookupField( T index) {
|
|
if ( !m_fieldsGot )
|
|
{
|
|
refreshFields();
|
|
m_fieldsGot = true;
|
|
}
|
|
return m_fields.lookup(index);
|
|
}
|
|
|
|
protected:
|
|
|
|
bool m_fieldsGot;
|
|
|
|
FieldCollection m_fields;
|
|
|
|
std::string m_name;
|
|
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
class UdtTypeInfo : public UdtTypeInfoBase
|
|
{
|
|
public:
|
|
|
|
UdtTypeInfo (SymbolPtr &symbol ) :
|
|
UdtTypeInfoBase( symbol->getName() ),
|
|
m_dia( symbol )
|
|
{
|
|
}
|
|
|
|
protected:
|
|
virtual ULONG getSize() {
|
|
return (ULONG)m_dia->getSize();
|
|
}
|
|
void getVirtualFields();
|
|
|
|
virtual void refreshFields() override;
|
|
|
|
void getFields(
|
|
SymbolPtr &rootSym,
|
|
SymbolPtr &baseVirtualSym,
|
|
ULONG startOffset = 0,
|
|
LONG virtualBasePtr = 0,
|
|
ULONG virtualDispIndex = 0,
|
|
ULONG m_virtualDispSize = 0 );
|
|
|
|
|
|
private:
|
|
SymbolPtr m_dia;
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
class EnumTypeInfo : public TypeInfo
|
|
{
|
|
public:
|
|
|
|
EnumTypeInfo ( SymbolPtr &symbol ) :
|
|
m_dia( symbol )
|
|
{}
|
|
|
|
protected:
|
|
|
|
virtual std::string getName() {
|
|
return m_dia->getName();
|
|
}
|
|
|
|
virtual ULONG getSize() {
|
|
return (ULONG)m_dia->getSize();
|
|
}
|
|
|
|
virtual TypeInfoPtr getFieldByIndex( ULONG index );
|
|
|
|
virtual std::string getFieldNameByIndex( ULONG index );
|
|
|
|
virtual ULONG getFieldCount();
|
|
|
|
virtual TypeInfoPtr getField( const std::string &fieldName );
|
|
|
|
virtual python::dict asMap();
|
|
|
|
virtual bool isEnum() {
|
|
return true;
|
|
}
|
|
|
|
virtual std::string print();
|
|
|
|
virtual ULONG getAlignReq() override {
|
|
return getSize();
|
|
}
|
|
|
|
SymbolPtr m_dia;
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
class PointerTypeInfo : public TypeInfo {
|
|
|
|
public:
|
|
|
|
PointerTypeInfo( const TypeInfoPtr ptr, ULONG ptrSize ) :
|
|
m_size( ptrSize ),
|
|
m_derefType( ptr )
|
|
{}
|
|
|
|
PointerTypeInfo( SymbolPtr &symbol );
|
|
|
|
PointerTypeInfo( SymbolPtr &symScope, const std::string &symName );
|
|
|
|
// void *
|
|
PointerTypeInfo( ULONG size );
|
|
|
|
virtual std::string getName();
|
|
|
|
virtual ULONG getSize();
|
|
|
|
virtual bool isPointer() {
|
|
return true;
|
|
}
|
|
|
|
virtual TypeInfoPtr deref() {
|
|
return getDerefType();
|
|
}
|
|
|
|
virtual ULONG getAlignReq() override {
|
|
return m_size;
|
|
}
|
|
|
|
TypeInfoPtr getDerefType() {
|
|
if (!m_derefType)
|
|
throw TypeException("<ptr>", "this pointer can not be dereferenced");
|
|
return m_derefType;
|
|
}
|
|
|
|
bool derefPossible() const {
|
|
return m_derefType;
|
|
}
|
|
|
|
const std::string getDerefName() const {
|
|
if (m_derefName.empty())
|
|
throw TypeException("<ptr>", "this pointer can not be dereferenced");
|
|
return m_derefName;
|
|
}
|
|
|
|
private:
|
|
static std::string VoidTypeName;
|
|
|
|
TypeInfoPtr m_derefType;
|
|
ULONG m_size;
|
|
std::string m_derefName;
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
class ArrayTypeInfo : public TypeInfo {
|
|
|
|
public:
|
|
|
|
ArrayTypeInfo( const TypeInfoPtr ptr, ULONG count ) :
|
|
m_derefType( ptr ),
|
|
m_count( count )
|
|
{}
|
|
|
|
ArrayTypeInfo( SymbolPtr &symbol );
|
|
|
|
ArrayTypeInfo( SymbolPtr &symScope, const std::string &symName, ULONG count );
|
|
|
|
virtual std::string getName();
|
|
|
|
virtual ULONG getSize();
|
|
|
|
virtual bool isArray() {
|
|
return true;
|
|
}
|
|
|
|
virtual ULONG getCount() {
|
|
return m_count;
|
|
}
|
|
|
|
virtual TypeInfoPtr getElementType() {
|
|
return m_derefType;
|
|
}
|
|
|
|
virtual ULONG getAlignReq() override {
|
|
return m_derefType->getAlignReq();
|
|
}
|
|
|
|
TypeInfoPtr getDerefType() {
|
|
return m_derefType;
|
|
}
|
|
|
|
private:
|
|
|
|
TypeInfoPtr m_derefType;
|
|
|
|
ULONG m_count;
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void splitSymName( const std::string &fullName, std::string &moduleName, std::string &symbolName );
|
|
|
|
python::tuple getSourceLine( ULONG64 offset = 0 );
|
|
|
|
std::string getSourceFile( ULONG64 offset = 0 );
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
}; // namespace pykd
|