mirror of
https://github.com/ivellioscolin/pykd.git
synced 2025-04-21 12:53:23 +08:00

[0.1.x] added : getOffset routine [0.1.x] added : support for working with bit fields git-svn-id: https://pykd.svn.codeplex.com/svn@72292 9b283d60-5439-405e-af05-b73fd8c4d996
329 lines
9.9 KiB
C++
329 lines
9.9 KiB
C++
#include "stdafx.h"
|
|
|
|
#include "typeinfo.h"
|
|
|
|
namespace pykd {
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TypeInfoPtr TypeInfo::getTypeInfo( pyDia::SymbolPtr &typeSym )
|
|
{
|
|
ULONG tag = typeSym->getSymTag();
|
|
|
|
switch( typeSym->getSymTag() )
|
|
{
|
|
case SymTagBaseType:
|
|
return getBaseTypeInfo( typeSym );
|
|
|
|
case SymTagUDT:
|
|
return TypeInfoPtr( new UdtTypeInfo( typeSym ) );
|
|
|
|
case SymTagArrayType:
|
|
return TypeInfoPtr( new ArrayTypeInfo( typeSym ) );
|
|
|
|
case SymTagPointerType:
|
|
return TypeInfoPtr( new PointerTypeInfo( typeSym ) );
|
|
}
|
|
|
|
throw DbgException( "type name invalid" );
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TypeInfoPtr TypeInfo::getTypeInfo( pyDia::SymbolPtr &symScope, const std::string &symName )
|
|
{
|
|
size_t pos = symName.find_first_of( "*[" );
|
|
|
|
if ( pos == std::string::npos )
|
|
{
|
|
TypeInfoPtr basePtr = getBaseTypeInfo( symName );
|
|
if ( basePtr != 0 )
|
|
return basePtr;
|
|
|
|
pyDia::SymbolPtr typeSym = symScope->getChildByName( symName );
|
|
|
|
if ( typeSym->getSymTag() == SymTagData )
|
|
{
|
|
if ( typeSym->getLocType() == LocIsBitField )
|
|
{
|
|
return TypeInfoPtr( new BitFieldTypeInfo(typeSym) );
|
|
}
|
|
|
|
typeSym = typeSym->getType();
|
|
}
|
|
|
|
return getTypeInfo( typeSym );
|
|
}
|
|
|
|
return getComplexType( symScope, symName );
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static const boost::regex baseMatch("^(Char)|(WChar)|(Int2B)|(UInt2B)|(Int4B)|(UInt4B)|(Int8B)|(UInt8B)|(Long)|(ULong)|(Float)|(Bool)$" );
|
|
|
|
TypeInfoPtr
|
|
TypeInfo::getBaseTypeInfo( const std::string &symName )
|
|
{
|
|
boost::cmatch baseMatchResult;
|
|
|
|
if ( boost::regex_match( symName.c_str(), baseMatchResult, baseMatch ) )
|
|
{
|
|
if ( baseMatchResult[1].matched )
|
|
return TypeInfoPtr( new TypeInfoWrapper<char>("Char") );
|
|
|
|
if ( baseMatchResult[2].matched )
|
|
return TypeInfoPtr( new TypeInfoWrapper<wchar_t>("WChar") );
|
|
|
|
if ( baseMatchResult[3].matched )
|
|
return TypeInfoPtr( new TypeInfoWrapper<short>("Int2B") );
|
|
|
|
if ( baseMatchResult[4].matched )
|
|
return TypeInfoPtr( new TypeInfoWrapper<unsigned short>("UInt2B") );
|
|
|
|
if ( baseMatchResult[5].matched )
|
|
return TypeInfoPtr( new TypeInfoWrapper<long>("Int4B") );
|
|
|
|
if ( baseMatchResult[6].matched )
|
|
return TypeInfoPtr( new TypeInfoWrapper<unsigned long>("UInt4B") );
|
|
|
|
if ( baseMatchResult[7].matched )
|
|
return TypeInfoPtr( new TypeInfoWrapper<__int64>("Int8B") );
|
|
|
|
if ( baseMatchResult[8].matched )
|
|
return TypeInfoPtr( new TypeInfoWrapper<unsigned __int64>("UInt8B") );
|
|
|
|
if ( baseMatchResult[9].matched )
|
|
return TypeInfoPtr( new TypeInfoWrapper<long>("Long") );
|
|
|
|
if ( baseMatchResult[10].matched )
|
|
return TypeInfoPtr( new TypeInfoWrapper<unsigned long>("ULong") );
|
|
|
|
if ( baseMatchResult[11].matched )
|
|
return TypeInfoPtr( new TypeInfoWrapper<float>("Float") );
|
|
|
|
if ( baseMatchResult[12].matched )
|
|
return TypeInfoPtr( new TypeInfoWrapper<bool>("Bool") );
|
|
}
|
|
|
|
return TypeInfoPtr();
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TypeInfoPtr
|
|
TypeInfo::getBaseTypeInfo( pyDia::SymbolPtr &symbol )
|
|
{
|
|
std::string symName = symbol->getBasicTypeName( symbol->getBaseType() );
|
|
|
|
if ( symName == "Int" || symName == "UInt" )
|
|
{
|
|
std::stringstream sstr;
|
|
sstr << symName << symbol->getSize() << "B";
|
|
|
|
return getBaseTypeInfo( sstr.str() );
|
|
}
|
|
|
|
return getBaseTypeInfo( symName );
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
BitFieldTypeInfo::BitFieldTypeInfo( pyDia::SymbolPtr &symbol )
|
|
{
|
|
m_bitWidth = (ULONG)symbol->getSize();
|
|
m_bitPos = (ULONG)symbol->getBitPosition();
|
|
|
|
TypeInfoPtr typeInfo = TypeInfo::getBaseTypeInfo( symbol->getType() );
|
|
|
|
m_size = (ULONG)typeInfo->getSize();
|
|
|
|
std::stringstream sstr;
|
|
|
|
sstr << typeInfo->getName() << ":" << (ULONG)m_bitWidth;
|
|
m_name = sstr.str();
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
PointerTypeInfo::PointerTypeInfo( pyDia::SymbolPtr &symbol )
|
|
{
|
|
m_derefType = TypeInfo::getTypeInfo( symbol->getType() );
|
|
m_size = (ULONG)symbol->getSize();
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
PointerTypeInfo::PointerTypeInfo( pyDia::SymbolPtr &symScope, const std::string &symName )
|
|
{
|
|
m_derefType = TypeInfo::getTypeInfo( symScope, symName );
|
|
m_size = (symScope->getMachineType() == IMAGE_FILE_MACHINE_AMD64) ? 8 : 4;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
std::string PointerTypeInfo::getName()
|
|
{
|
|
return getComplexName();
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
ULONG PointerTypeInfo::getSize()
|
|
{
|
|
return m_size;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
ArrayTypeInfo::ArrayTypeInfo( pyDia::SymbolPtr &symbol )
|
|
{
|
|
m_derefType = TypeInfo::getTypeInfo( symbol->getType() );
|
|
m_count = symbol->getCount();
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
ArrayTypeInfo::ArrayTypeInfo( pyDia::SymbolPtr &symScope, const std::string &symName, ULONG count )
|
|
{
|
|
m_derefType = TypeInfo::getTypeInfo( symScope, symName );
|
|
m_count = count;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
std::string ArrayTypeInfo::getName()
|
|
{
|
|
return getComplexName();
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
ULONG ArrayTypeInfo::getSize()
|
|
{
|
|
return m_derefType->getSize() * m_count;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
std::string TypeInfo::getComplexName()
|
|
{
|
|
std::string name;
|
|
TypeInfo *typeInfo = this;
|
|
|
|
do {
|
|
|
|
if ( typeInfo->isArray() )
|
|
{
|
|
std::vector<ULONG> indices;
|
|
|
|
do {
|
|
indices.push_back( typeInfo->getCount() );
|
|
}
|
|
while( ( typeInfo = dynamic_cast<ArrayTypeInfo*>(typeInfo)->getDerefType().get() )->isArray() );
|
|
|
|
if ( !name.empty() )
|
|
{
|
|
name.insert( 0, 1, '(' );
|
|
name.insert( name.size(), 1, ')' );
|
|
}
|
|
|
|
std::stringstream sstr;
|
|
|
|
for ( std::vector<ULONG>::iterator it = indices.begin(); it != indices.end(); ++it )
|
|
sstr << '[' << *it << ']';
|
|
|
|
name += sstr.str();
|
|
|
|
continue;
|
|
}
|
|
else
|
|
if ( typeInfo->isPointer() )
|
|
{
|
|
name.insert( 0, 1, '*' );
|
|
|
|
typeInfo = dynamic_cast<PointerTypeInfo*>(typeInfo)->getDerefType().get();
|
|
|
|
continue;
|
|
}
|
|
|
|
break;
|
|
|
|
} while ( true );
|
|
|
|
name.insert( 0, typeInfo->getName() );
|
|
|
|
return name;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static const boost::regex bracketMatch("^([^\\(]*)\\((.*)\\)([^\\)]*)$");
|
|
|
|
static const boost::regex typeMatch("^([^\\(\\)\\*\\[\\]]*)([\\(\\)\\*\\[\\]\\d]*)$");
|
|
|
|
static const boost::regex ptrMatch("^\\*(.*)$");
|
|
|
|
static const boost::regex arrayMatch("^(.*)\\[(\\d+)\\]$");
|
|
|
|
TypeInfoPtr TypeInfo::getComplexType( pyDia::SymbolPtr &symScope, const std::string &symName )
|
|
{
|
|
ULONG ptrSize = (symScope->getMachineType() == IMAGE_FILE_MACHINE_AMD64) ? 8 : 4;
|
|
|
|
boost::cmatch matchResult;
|
|
|
|
if ( !boost::regex_match( symName.c_str(), matchResult, typeMatch ) )
|
|
DbgException( "type name invalid" );
|
|
|
|
TypeInfoPtr lowestTypeInfo = getTypeInfo( symScope, std::string( matchResult[1].first, matchResult[1].second ) );
|
|
|
|
return getRecurciveComplexType( lowestTypeInfo, std::string( matchResult[2].first, matchResult[2].second ), ptrSize );
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TypeInfoPtr TypeInfo::getRecurciveComplexType( TypeInfoPtr &lowestType, std::string &suffix, ULONG ptrSize )
|
|
{
|
|
boost::cmatch matchResult;
|
|
|
|
std::string bracketExpr;
|
|
|
|
if ( boost::regex_match( suffix.c_str(), matchResult, bracketMatch ) )
|
|
{
|
|
bracketExpr = std::string( matchResult[2].first, matchResult[2].second );
|
|
|
|
suffix = "";
|
|
|
|
if ( matchResult[1].matched )
|
|
suffix += std::string( matchResult[1].first, matchResult[1].second );
|
|
|
|
if ( matchResult[3].matched )
|
|
suffix += std::string( matchResult[3].first, matchResult[3].second );
|
|
}
|
|
|
|
while( !suffix.empty() )
|
|
{
|
|
if ( boost::regex_match( suffix.c_str(), matchResult, ptrMatch ) )
|
|
{
|
|
lowestType = TypeInfoPtr( new PointerTypeInfo( lowestType, ptrSize ) );
|
|
suffix = std::string(matchResult[1].first, matchResult[1].second );
|
|
continue;
|
|
}
|
|
|
|
if ( boost::regex_match( suffix.c_str(), matchResult, arrayMatch ) )
|
|
{
|
|
lowestType = TypeInfoPtr( new ArrayTypeInfo( lowestType, std::atoi( matchResult[2].first ) ) );
|
|
suffix = std::string(matchResult[1].first, matchResult[1].second );
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if ( !bracketExpr.empty() )
|
|
return getRecurciveComplexType( lowestType, bracketExpr, ptrSize );
|
|
|
|
return lowestType;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
}; // end namespace pykd
|