Commits (16)
......@@ -33,6 +33,9 @@ bool isLocalKernelDebuggerEnabled();
PROCESS_DEBUG_ID attachKernel( const std::wstring &connectOptions = L"" );
bool isDumpAnalyzing();
DumpType getDumpType();
DumpFormatFlagsSet getDumpFormat();
bool isKernelDebugging();
std::wstring debugCommand(const std::wstring &command, bool suppressOutput = false, const OutputFlagsSet& captureFlags = OutputFlag::Normal);
......
......@@ -239,6 +239,43 @@ enum OutputFlag
typedef unsigned long OutputFlagsSet;
enum DumpType
{
Small = 1024,
Default = 1025,
Full = 1026,
Image = 1027,
KernelSmall = Small,
Kernel = Default,
KernelFull = Full
};
enum DumpFormat
{
UserSmallFullMemory = 0x1,
UserSmallHandleData = 0x2,
UserSmallUnloadedModules = 0x4,
UserSmallIndirectMemory = 0x8,
UserSmallDataSegments = 0x10,
UserSmallFilterMemory = 0x20,
UserSmallFilterPaths = 0x40,
UserSmallProcessThreadData = 0x80,
UserSmallPrivateReadWriteMemory = 0x100,
UserSmallNoOptionalData = 0x200,
UserSmallFullMemoryInfo = 0x400,
UserSmallThreadInfo = 0x800,
UserSmallCodeSegments = 0x1000,
UserSmallNoAuxiliaryState = 0x2000,
UserSmallFullAuxiliaryState = 0x4000,
UserSmallModuleHeaders = 0x8000,
UserSmallFilterTriage = 0x10000,
UserSmallAddAvxXStateContext = 0x20000,
UserSmallIptTrace = 0x40000,
UserSmallIgnoreInaccessibleMem = 0x08000000
};
typedef unsigned long DumpFormatFlagsSet;
///////////////////////////////////////////////////////////////////////////////
} // kdlib namespace end
......
......@@ -171,10 +171,7 @@ enum CallingConventionType
class Symbol {
public:
typedef unsigned long SymIndexId;
static const SymIndexId InvalidId = -1;
virtual SymIndexId getSymIndexId() { return InvalidId; }
virtual SymbolPtrList findChildren( unsigned long symTag, const std::wstring &name = L"", bool caseSensitive = false ) = 0;
virtual SymbolPtrList findChildrenByRVA(unsigned long symTag, unsigned long rva) = 0;
virtual unsigned long getBaseType() = 0;
......
......@@ -154,6 +154,7 @@ protected:
static bool isBaseType( const std::wstring &typeName );
static bool isComplexType( const std::wstring &typeName );
static TypeInfoPtr getTypeInfoFromCache(const std::wstring &typeName );
static TypeInfoPtr getBaseTypeInfo( const std::wstring &typeName, size_t ptrSize = 0);
static TypeInfoPtr getBaseTypeInfo( const SymbolPtr &symbolScope );
......
......@@ -200,18 +200,6 @@ SymbolPtr DiaSymbol::fromGlobalScope( IDiaSymbol *_symbol, const std::wstring& _
//////////////////////////////////////////////////////////////////////////////////
Symbol::SymIndexId DiaSymbol::getSymIndexId()
{
SymIndexId id;
HRESULT hres = m_symbol->get_symIndexId(&id);
if(S_OK == hres)
return id;
return Symbol::getSymIndexId();
}
//////////////////////////////////////////////////////////////////////////////////
SymbolPtrList DiaSymbol::findChildren(
ULONG symTag,
const std::wstring &name,
......
......@@ -59,8 +59,6 @@ public:
static SymbolPtr fromGlobalScope( IDiaSymbol *_symbol, const std::wstring &_scope );
SymIndexId getSymIndexId() override;
SymbolPtr getChildByName(const std::wstring &_name ) override;
ULONG getRva() override;
......
......@@ -701,10 +701,6 @@ ScopePtr ModuleImp::getScope()
MEMOFFSET_64 findModuleBySymbol( const std::wstring &symbolName )
{
MEMOFFSET_64 module_base = ProcessMonitor::getModuleBaseBySymbol(symbolName);
if (module_base)
return module_base;
std::vector<MEMOFFSET_64> moduleList = getModuleBasesList();
std::vector<MEMOFFSET_64>::const_iterator it;
......@@ -715,8 +711,7 @@ MEMOFFSET_64 findModuleBySymbol( const std::wstring &symbolName )
try {
SymbolPtr typeInfo = module->getSymbolByName( symbolName );
module_base = *it;
break;
return *it;
}
catch( SymbolException& )
{}
......@@ -724,19 +719,12 @@ MEMOFFSET_64 findModuleBySymbol( const std::wstring &symbolName )
try {
TypeInfoPtr typeInfo = module->getTypeByName( symbolName );
module_base = *it;
break;
return *it;
}
catch( SymbolException& )
{}
}
if (module_base)
{
ProcessMonitor::insertModuleBaseBySymbol(symbolName, module_base);
return module_base;
}
std::wstringstream sstr;
sstr << L"failed to find module for symbol: " << symbolName;
throw SymbolException( sstr.str() );
......
......@@ -25,11 +25,8 @@ public:
void insertModule( ModulePtr& module);
void removeModule(MEMOFFSET_64 offset );
MEMOFFSET_64 getModuleBaseBySymbol(const std::wstring& sym);
void insertModuleBaseBySymbol(const std::wstring& sym, MEMOFFSET_64 module_base);
TypeInfoPtr getTypeInfo(const SymbolPtr& sym);
void insertTypeInfo(const SymbolPtr& sym, const TypeInfoPtr& typeInfo);
TypeInfoPtr getTypeInfo(const std::wstring& name);
void insertTypeInfo(const TypeInfoPtr& typeInfo);
void insertBreakpoint(const BreakpointPtr& breakpoint);
void removeBreakpoint(const BreakpointPtr& breakpoint);
......@@ -44,14 +41,10 @@ private:
ModuleMap m_moduleMap;
boost::recursive_mutex m_moduleLock;
typedef std::map<std::wstring, MEMOFFSET_64> SymbolMap;
SymbolMap m_symbolMap;
boost::recursive_mutex m_symbolLock;
typedef std::map<std::pair<std::wstring, Symbol::SymIndexId>, TypeInfoPtr> TypeInfoMap;
TypeInfoMap m_typeInfoMap;
boost::recursive_mutex m_typeInfoLock;
typedef std::map<std::wstring, TypeInfoPtr> TypeInfoMap;
TypeInfoMap m_typeInfoMap;
boost::recursive_mutex m_typeInfoLock;
typedef std::map<BREAKPOINT_ID, BreakpointPtr> BreakpointIdMap;
BreakpointIdMap m_breakpointMap;
boost::recursive_mutex m_breakpointLock;
......@@ -96,8 +89,8 @@ public:
ModulePtr getModule( MEMOFFSET_64 offset, PROCESS_DEBUG_ID id );
void insertModule( ModulePtr& module, PROCESS_DEBUG_ID id );
MEMOFFSET_64 getModuleBaseBySymbol(const std::wstring& sym, PROCESS_DEBUG_ID id);
void insertModuleBaseBySymbol(const std::wstring& sym, MEMOFFSET_64 module_base, PROCESS_DEBUG_ID id);
TypeInfoPtr getTypeInfo(const std::wstring& name, PROCESS_DEBUG_ID id = -1);
void insertTypeInfo(const TypeInfoPtr& typeInfo, PROCESS_DEBUG_ID id = -1);
void registerEventsCallback(DebugEventsCallback *callback);
void removeEventsCallback(DebugEventsCallback *callback);
......@@ -105,9 +98,6 @@ public:
void registerBreakpoint( const BreakpointPtr& breakpoint, PROCESS_DEBUG_ID id = -1 );
void removeBreakpoint( const BreakpointPtr& breakpoint, PROCESS_DEBUG_ID id = -1 );
TypeInfoPtr getTypeInfo(const SymbolPtr& sym, PROCESS_DEBUG_ID id = -1);
void insertTypeInfo(const SymbolPtr& sym, const TypeInfoPtr& typeInfo, PROCESS_DEBUG_ID id = -1);
private:
ProcessInfoPtr getProcess( PROCESS_DEBUG_ID id );
......@@ -204,26 +194,6 @@ void ProcessMonitor::removeBreakpoint( const BreakpointPtr& breakpoint, PROCESS_
/////////////////////////////////////////////////////////////////////////////
TypeInfoPtr ProcessMonitor::getTypeInfo(const SymbolPtr& sym, PROCESS_DEBUG_ID id)
{
if (id == -1)
id = getCurrentProcessId();
return g_procmon->getTypeInfo(sym, id);
}
/////////////////////////////////////////////////////////////////////////////
void ProcessMonitor::insertTypeInfo(const SymbolPtr& sym, const TypeInfoPtr& typeInfo, PROCESS_DEBUG_ID id)
{
if (id == -1)
id = getCurrentProcessId();
return g_procmon->insertTypeInfo(sym, typeInfo, id);
}
/////////////////////////////////////////////////////////////////////////////
DebugCallbackResult ProcessMonitor::processStart(PROCESS_DEBUG_ID id)
{
return g_procmon->processStart(id);
......@@ -377,22 +347,22 @@ void ProcessMonitor::insertModule( ModulePtr& module, PROCESS_DEBUG_ID id )
///////////////////////////////////////////////////////////////////////////////
MEMOFFSET_64 ProcessMonitor::getModuleBaseBySymbol(const std::wstring& sym, PROCESS_DEBUG_ID id)
TypeInfoPtr ProcessMonitor::getTypeInfo(const std::wstring& name, PROCESS_DEBUG_ID id)
{
if (id == -1)
id = getCurrentProcessId();
return g_procmon->getModuleBaseBySymbol(sym, id);
return g_procmon->getTypeInfo(name, id);
}
///////////////////////////////////////////////////////////////////////////////
void ProcessMonitor::insertModuleBaseBySymbol(const std::wstring& sym, MEMOFFSET_64 module_base, PROCESS_DEBUG_ID id)
void ProcessMonitor::insertTypeInfo(const TypeInfoPtr& typeInfo, PROCESS_DEBUG_ID id)
{
if (id == -1)
id = getCurrentProcessId();
return g_procmon->insertModuleBaseBySymbol(sym, module_base, id);
return g_procmon->insertTypeInfo(typeInfo, id);
}
///////////////////////////////////////////////////////////////////////////////
......@@ -746,42 +716,22 @@ void ProcessMonitorImpl::insertModule( ModulePtr& module, PROCESS_DEBUG_ID id )
///////////////////////////////////////////////////////////////////////////////
MEMOFFSET_64 ProcessMonitorImpl::getModuleBaseBySymbol(const std::wstring& sym, PROCESS_DEBUG_ID id)
{
ProcessInfoPtr processInfo = getProcess(id);
if (processInfo)
return processInfo->getModuleBaseBySymbol(sym);
return 0;
}
///////////////////////////////////////////////////////////////////////////////
void ProcessMonitorImpl::insertModuleBaseBySymbol(const std::wstring& sym, MEMOFFSET_64 module_base, PROCESS_DEBUG_ID id)
{
ProcessInfoPtr processInfo = getProcess(id);
if (processInfo)
return processInfo->insertModuleBaseBySymbol(sym, module_base);
}
///////////////////////////////////////////////////////////////////////////////
TypeInfoPtr ProcessMonitorImpl::getTypeInfo(const SymbolPtr& sym, PROCESS_DEBUG_ID id)
TypeInfoPtr ProcessMonitorImpl::getTypeInfo(const std::wstring& name, PROCESS_DEBUG_ID id)
{
ProcessInfoPtr processInfo = getProcess(id);
if (processInfo)
return processInfo->getTypeInfo(sym);
if ( processInfo )
return processInfo->getTypeInfo(name);
return TypeInfoPtr();
}
///////////////////////////////////////////////////////////////////////////////
void ProcessMonitorImpl::insertTypeInfo(const SymbolPtr& sym, const TypeInfoPtr& typeInfo, PROCESS_DEBUG_ID id)
void ProcessMonitorImpl::insertTypeInfo(const TypeInfoPtr& typeInfo, PROCESS_DEBUG_ID id)
{
ProcessInfoPtr processInfo = getProcess(id);
if (processInfo)
return processInfo->insertTypeInfo(sym, typeInfo);
return processInfo->insertTypeInfo(typeInfo);
}
///////////////////////////////////////////////////////////////////////////////
......@@ -876,78 +826,19 @@ void ProcessInfo::insertModule( ModulePtr& module)
void ProcessInfo::removeModule(MEMOFFSET_64 offset )
{
ModulePtr module;
{
boost::recursive_mutex::scoped_lock l(m_moduleLock);
ModuleMap::iterator it = m_moduleMap.find(offset);
if(it != m_moduleMap.end())
{
module = it->second;
m_moduleMap.erase(it);
}
}
// clear symbol cache for this module
{
boost::recursive_mutex::scoped_lock l(m_symbolLock);
SymbolMap::iterator it = m_symbolMap.begin();
while (it != m_symbolMap.end())
{
if(it->second == offset)
it = m_symbolMap.erase(it);
else
++it;
}
}
// clear TypeInfo cache for this module
if(module)
{
std::wstring scope = module->getSymbolScope()->getScopeName();
boost::recursive_mutex::scoped_lock l(m_typeInfoLock);
TypeInfoMap::iterator it = m_typeInfoMap.begin();
while (it != m_typeInfoMap.end())
{
if (it->first.first == scope)
it = m_typeInfoMap.erase(it);
else
++it;
}
}
}
///////////////////////////////////////////////////////////////////////////////
MEMOFFSET_64 ProcessInfo::getModuleBaseBySymbol(const std::wstring& sym)
{
boost::recursive_mutex::scoped_lock l(m_symbolLock);
SymbolMap::iterator it = m_symbolMap.find(sym);
if(it != m_symbolMap.end())
return it->second;
return 0;
}
///////////////////////////////////////////////////////////////////////////////
void ProcessInfo::insertModuleBaseBySymbol(const std::wstring& sym, MEMOFFSET_64 module_base)
{
boost::recursive_mutex::scoped_lock l(m_symbolLock);
m_symbolMap[sym] = module_base;
boost::recursive_mutex::scoped_lock l(m_moduleLock);
m_moduleMap.erase(offset);
}
///////////////////////////////////////////////////////////////////////////////
TypeInfoPtr ProcessInfo::getTypeInfo(const SymbolPtr& sym)
TypeInfoPtr ProcessInfo::getTypeInfo(const std::wstring& name)
{
TypeInfoMap::key_type key{ sym->getScopeName(), sym->getSymIndexId() };
boost::recursive_mutex::scoped_lock l(m_typeInfoLock);
TypeInfoMap::iterator it = m_typeInfoMap.find(key);
if(it != m_typeInfoMap.end())
TypeInfoMap::iterator it = m_typeInfoMap.find(name);
if (it != m_typeInfoMap.end())
return it->second;
return TypeInfoPtr();
......@@ -955,15 +846,11 @@ TypeInfoPtr ProcessInfo::getTypeInfo(const SymbolPtr& sym)
///////////////////////////////////////////////////////////////////////////////
void ProcessInfo::insertTypeInfo(const SymbolPtr& sym, const TypeInfoPtr& typeInfo)
void ProcessInfo::insertTypeInfo(const TypeInfoPtr& typeInfo)
{
TypeInfoMap::key_type key{ sym->getScopeName(), sym->getSymIndexId() };
boost::recursive_mutex::scoped_lock l(m_typeInfoLock);
if (key.second != Symbol::InvalidId)
{
boost::recursive_mutex::scoped_lock l(m_typeInfoLock);
m_typeInfoMap[key] = typeInfo;
}
m_typeInfoMap.insert(std::make_pair(typeInfo->getName(), typeInfo));
}
///////////////////////////////////////////////////////////////////////////////
......
......@@ -48,9 +48,6 @@ public: // module manipulation
static ModulePtr getModule( MEMOFFSET_64 offset, PROCESS_DEBUG_ID id = -1 );
static void insertModule( ModulePtr& module, PROCESS_DEBUG_ID id = -1 );
static MEMOFFSET_64 getModuleBaseBySymbol(const std::wstring& sym, PROCESS_DEBUG_ID id = -1);
static void insertModuleBaseBySymbol(const std::wstring& sym, MEMOFFSET_64 module_base, PROCESS_DEBUG_ID id = -1);
public: //breakpoint callbacks
static void registerBreakpoint( const BreakpointPtr& breakpoint, PROCESS_DEBUG_ID id = -1 );
......@@ -60,9 +57,10 @@ public: //callbacks
static void registerEventsCallback(DebugEventsCallback *callback);
static void removeEventsCallback(DebugEventsCallback *callback);
public: // TypeInfo cache
static TypeInfoPtr getTypeInfo(const SymbolPtr& sym, PROCESS_DEBUG_ID id = -1);
static void insertTypeInfo(const SymbolPtr& sym, const TypeInfoPtr& typeInfo, PROCESS_DEBUG_ID id = -1);
public: //
static TypeInfoPtr getTypeInfo(const std::wstring& name, PROCESS_DEBUG_ID id = -1);
static void insertTypeInfo( const TypeInfoPtr& typeInfo, PROCESS_DEBUG_ID id = -1);
};
///////////////////////////////////////////////////////////////////////////////
......
......@@ -441,7 +441,12 @@ bool StackFrameImpl::findStaticVar(const std::wstring& varName)
TypedVarPtr StackFrameImpl::getFunction()
{
auto funcPtr = loadTypedVar(kdlib::findSymbol(m_ip));
MEMDISPLACEMENT displacement;
auto module = loadModule(m_ip);
module->getSymbolByVa(m_ip, SymTagFunction, &displacement);
auto funcPtr = module->getTypedVarByAddr(m_ip - displacement);
if (m_inlineIndex == 0 )
return funcPtr;
......@@ -465,17 +470,10 @@ std::wstring StackFrameImpl::findSymbol(MEMDISPLACEMENT &displacement)
if (m_inlineIndex == 0)
return kdlib::findSymbol(m_ip, displacement);
auto funcPtr = loadTypedVar(kdlib::findSymbol(m_ip));
for (MEMDISPLACEMENT i = 0; i <= 1; ++i)
{
const auto& inlineFunctions = funcPtr->getInlineFunctions(m_ip - i);
if (inlineFunctions.size() >= m_inlineIndex)
return (*std::next(inlineFunctions.rbegin(), m_inlineIndex - 1))->getName();
}
throw TypeException(L"failed to find inline function");
auto func = getFunction();
displacement = (MEMDISPLACEMENT)((long long)m_ip - (long long)func->getAddress());
return func->getName();
}
/////////////////////////////////////////////////////////////////////////////
......@@ -489,7 +487,11 @@ void StackFrameImpl::getSourceLine(std::wstring& fileName, unsigned long& lineNo
return;
}
auto funcPtr = loadTypedVar(kdlib::findSymbol(m_ip));
MEMDISPLACEMENT displacement;
auto module = loadModule(m_ip);
module->getSymbolByVa(m_ip, SymTagFunction, &displacement);
auto funcPtr = module->getTypedVarByAddr(m_ip - displacement);
for (MEMDISPLACEMENT i = 0; i <= 1; ++i)
{
......
......@@ -107,6 +107,8 @@ bool getArrayExpression( std::wstring &suffix, size_t &arraySize )
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
} // end nameless namespace
namespace kdlib {
......@@ -284,18 +286,12 @@ TypeInfoPtr loadType( const std::wstring &typeName )
splitSymName( typeName, moduleName, symName );
ModulePtr module;
if ( moduleName.empty() )
{
MEMOFFSET_64 moduleOffset = findModuleBySymbol(symName);
module = loadModule(moduleOffset);
}
else
{
module = loadModule(moduleName);
return TypeInfo::getTypeInfoFromCache(symName);
}
ModulePtr module = loadModule(moduleName);
SymbolPtr symbolScope = module->getSymbolScope();
......@@ -332,9 +328,7 @@ TypeInfoPtr loadType( const SymbolPtr &symbolScope, const std::wstring &symbolNa
TypeInfoPtr loadType( const SymbolPtr &symbol )
{
unsigned long symTag = symbol->getSymTag();
TypeInfoPtr ptr = ProcessMonitor::getTypeInfo(symbol);
if (ptr)
return ptr;
TypeInfoPtr ptr;
switch( symTag )
{
......@@ -351,32 +345,27 @@ TypeInfoPtr loadType( const SymbolPtr &symbol )
NumVariant constVal;
symbol->getValue( constVal );
ptr = TypeInfo::getBaseTypeInfo(symbol->getType());
ptr = loadType( symbol->getType() );
dynamic_cast<TypeInfoImp*>( ptr.get() )->setConstant( constVal );
break;
}
ptr = loadType(symbol->getType());
break;
return loadType( symbol->getType() );
case SymTagBaseType:
ptr = TypeInfo::getBaseTypeInfo(symbol);
break;
return TypeInfo::getBaseTypeInfo( symbol );
case SymTagUDT:
case SymTagBaseClass:
ptr = TypeInfoPtr(new TypeInfoUdt(symbol));
break;
return TypeInfoPtr( new TypeInfoUdt( symbol ) );
case SymTagArrayType:
ptr = TypeInfoPtr(new TypeInfoSymbolArray(symbol));
break;
return TypeInfoPtr( new TypeInfoSymbolArray( symbol ) );
case SymTagPointerType:
ptr = TypeInfoPtr(new TypeInfoSymbolPointer(symbol));
break;
return TypeInfoPtr( new TypeInfoSymbolPointer( symbol ) );
case SymTagVTable:
ptr = TypeInfoPtr( new TypeInfoSymbolPointer( symbol->getType() ) );
......@@ -417,7 +406,6 @@ TypeInfoPtr loadType( const SymbolPtr &symbol )
//if ( ptr )
// ptr->m_ptrSize = getTypePointerSize(typeSym);
ProcessMonitor::insertTypeInfo(symbol, ptr);
return ptr;
}
......@@ -564,6 +552,153 @@ bool isPrototypeMatch(TypeInfoPtr& methodType, const std::wstring& methodProtot
///////////////////////////////////////////////////////////////////////////////
std::vector<TypeFieldPtr> enumFields(
const SymbolPtr &rootSym,
const SymbolPtr &parentSym,
MEMOFFSET_32 startOffset = 0,
MEMOFFSET_32 virtualBasePtr = 0,
size_t virtualDispIndex = 0,
size_t virtualDispSize = 0)
{
std::vector<TypeFieldPtr> fields;
bool firstVtbl = true;
size_t childCount = parentSym->getChildCount();
for (unsigned long i = 0; i < childCount; ++i)
{
SymbolPtr childSym = parentSym->getChildByIndex(i);
SymTags symTag = childSym->getSymTag();
if (symTag == SymTagBaseClass)
{
if (childSym->isVirtualBaseClass() )
{
if (rootSym != parentSym)
continue;
auto childFields = enumFields(
rootSym,
childSym,
0,
childSym->getVirtualBasePointerOffset(),
childSym->getVirtualBaseDispIndex(),
childSym->getVirtualBaseDispSize());
for (const auto& childField : childFields)
{
fields.push_back(childField);
}
}
else
{
auto childFields = enumFields(
rootSym,
childSym,
startOffset + childSym->getOffset(),
virtualBasePtr,
virtualDispIndex,
virtualDispSize);
for (const auto& childField : childFields)
{
if (childField->isVtbl() && firstVtbl)
{
firstVtbl = false;
auto vtblField = SymbolUdtField::getVtblField(
parentSym->getVirtualTableShape(),
L"__VFN_table",
startOffset + childSym->getOffset(),
virtualBasePtr,
virtualDispIndex,
virtualDispSize);
fields.push_back(vtblField);
}
else
{
fields.push_back(childField);
}
}
}
}
else
if (symTag == SymTagData)
{
TypeFieldPtr fieldPtr;
auto dataKind = childSym->getDataKind();
switch (dataKind)
{
case DataIsMember:
fieldPtr = SymbolUdtField::getField(
childSym,
childSym->getName(),
startOffset + childSym->getOffset(),
virtualBasePtr,
virtualDispIndex,
virtualDispSize);
break;
case DataIsStaticMember:
{
MEMOFFSET_64 staticOffset = 0L;
try
{
staticOffset = childSym->getVa();
}
catch (SymbolException&)
{
}
fieldPtr = SymbolUdtField::getStaticField(childSym, childSym->getName(), staticOffset);
}
break;
case DataIsConstant:
fieldPtr = SymbolUdtField::getConstField(childSym, childSym->getName());
break;
default:
continue;
}
if (rootSym != parentSym)
fieldPtr->setMemberInherited();
fields.push_back(fieldPtr);
}
else
if (symTag == SymTagVTable)
{
TypeFieldPtr fieldPtr;
fieldPtr = SymbolUdtField::getVtblField(
parentSym->getVirtualTableShape(),
L"__VFN_table",
startOffset + childSym->getOffset(),
virtualBasePtr,
virtualDispIndex,
virtualDispSize);
fields.push_back( fieldPtr );
}
else
if (symTag == SymTagEnum)
{
auto childFields = enumFields(rootSym, childSym, startOffset);
for (const auto& childField : childFields)
fields.push_back(childField);
}
}
return fields;
}
///////////////////////////////////////////////////////////////////////////////
static const std::wregex baseMatch(L"^(Char)|(WChar)|(Int1B)|(UInt1B)|(Int2B)|(UInt2B)|(Int4B)|(UInt4B)|(Int8B)|(UInt8B)|(Long)|(ULong)|(Float)|(Bool)|(Double)|(Void)|(Hresult)|(NoType)$" );
bool TypeInfo::isBaseType( const std::wstring &typeName )
......@@ -765,6 +900,23 @@ TypeInfoPtr TypeInfo::getRecursiveComplexType( const std::wstring &typeName, Typ
///////////////////////////////////////////////////////////////////////////////
TypeInfoPtr TypeInfo::getTypeInfoFromCache(const std::wstring &typeName)
{
TypeInfoPtr cachedType = ProcessMonitor::getTypeInfo(typeName);
if (cachedType)
return cachedType;
MEMOFFSET_64 moduleOffset = findModuleBySymbol(typeName);
TypeInfoPtr typeInfo = loadModule(moduleOffset)->getTypeByName(typeName);;
ProcessMonitor::insertTypeInfo(typeInfo);
return typeInfo;
}
///////////////////////////////////////////////////////////////////////////////
TypeInfoPtr TypeInfoImp::ptrTo( size_t ptrSize )
{
return TypeInfoPtr( new TypeInfoPointer( shared_from_this(), ptrSize ? ptrSize : getPtrSize() ) );
......@@ -1047,8 +1199,14 @@ TypeInfoPtr TypeInfoFields::getElement( const std::wstring &name )
TypeInfoPtr fieldType = m_fields.lookup( std::wstring( name, 0, pos) )->getTypeInfo();
if ( pos == std::wstring::npos )
if (pos == std::wstring::npos)
{
if (fieldType->isVtbl())
{
return fieldType->ptrTo(fieldType->getPtrSize());
}
return fieldType;
}
return fieldType->getElement( std::wstring( name, pos + 1 ) );
}
......@@ -1059,7 +1217,12 @@ TypeInfoPtr TypeInfoFields::getElement(size_t index )
{
checkFields();
return m_fields.lookup(index)->getTypeInfo();
auto typeInfo = m_fields.lookup(index)->getTypeInfo();
if (typeInfo->isVtbl())
{
return typeInfo->ptrTo(typeInfo->getPtrSize());
}
return typeInfo;
}
///////////////////////////////////////////////////////////////////////////////
......@@ -1542,135 +1705,10 @@ TypeInfoPtr TypeInfoUdt::getVTBL()
void TypeInfoUdt::getFields()
{
getFields( m_symbol, SymbolPtr() );
getVirtualFields();
}
///////////////////////////////////////////////////////////////////////////////
void TypeInfoUdt::getFields(
const SymbolPtr &rootSym,
const SymbolPtr &baseVirtualSym,
MEMOFFSET_32 startOffset,
MEMOFFSET_32 virtualBasePtr,
size_t virtualDispIndex,
size_t virtualDispSize )
{
size_t childCount = rootSym->getChildCount();
for ( unsigned long i = 0; i < childCount; ++i )
{
SymbolPtr childSym = rootSym->getChildByIndex( i );
SymTags symTag = childSym->getSymTag();
if ( symTag == SymTagBaseClass )
{
if ( !childSym->isVirtualBaseClass() )
{
getFields( childSym, SymbolPtr(), startOffset + childSym->getOffset() );
}
}
else
if ( symTag == SymTagData )
{
TypeFieldPtr fieldPtr;
auto dataKind = childSym->getDataKind();
switch (dataKind )
{
case DataIsMember:
if ( baseVirtualSym )
{
fieldPtr = SymbolUdtField::getVirtualField( childSym, childSym->getName(), startOffset + childSym->getOffset(), virtualBasePtr, virtualDispIndex, virtualDispSize );
}
else
{
fieldPtr = SymbolUdtField::getField( childSym, childSym->getName(), startOffset + childSym->getOffset() );
}
break;
case DataIsStaticMember:
{
std::wstring fieldName = childSym->getName();
MEMOFFSET_64 staticOffset = 0L;
try
{
staticOffset = childSym->getVa();
}
catch (SymbolException&)
{
}
fieldPtr = SymbolUdtField::getStaticField(childSym, fieldName, staticOffset);
}
break;
case DataIsConstant:
fieldPtr = SymbolUdtField::getConstField(childSym, childSym->getName());
break;
default:
throw TypeException(m_name, L"Unsupported field type");
}
if (rootSym != m_symbol)
fieldPtr->setMemberInherited();
m_fields.push_back( fieldPtr );
}
else
if ( symTag == SymTagVTable )
{
TypeFieldPtr fieldPtr;
if ( baseVirtualSym )
{
fieldPtr = SymbolUdtField::getVirtualField( childSym, L"__VFN_table", startOffset + childSym->getOffset(), virtualBasePtr, virtualDispIndex, virtualDispSize );
}
else
{
fieldPtr = SymbolUdtField::getField( childSym, L"__VFN_table", startOffset + childSym->getOffset() );
}
m_fields.push_back( fieldPtr );
}
else
if (symTag == SymTagEnum)
{
getFields(childSym, SymbolPtr(), startOffset);
}
}
}
///////////////////////////////////////////////////////////////////////////////
void TypeInfoUdt::getVirtualFields()
{
SymbolPtrList baseClasses = m_symbol->findChildren(SymTagBaseClass);
auto fields = kdlib::enumFields(m_symbol, m_symbol);
for ( SymbolPtrList::iterator baseClass = baseClasses.begin(); baseClass != baseClasses.end(); ++baseClass)
{
SymbolPtr childSym = *baseClass;
std::wstring baseClassName = childSym->getName();
if ( !childSym->isVirtualBaseClass() )
continue;
getFields(
childSym,
childSym,
0,
childSym->getVirtualBasePointerOffset(),
childSym->getVirtualBaseDispIndex(),
childSym->getVirtualBaseDispSize() );
}
for (auto& field : fields)
m_fields.push_back(field);
}
///////////////////////////////////////////////////////////////////////////////
......
......@@ -542,17 +542,6 @@ protected:
virtual void getVirtualDisplacement( const std::wstring& fieldName, MEMOFFSET_32 &virtualBasePtr, size_t &virtualDispIndex, size_t &virtualDispSize );
virtual void getVirtualDisplacement( size_t fieldIndex, MEMOFFSET_32 &virtualBasePtr, size_t &virtualDispIndex, size_t &virtualDispSize );
void getFields(
const SymbolPtr &rootSym,
const SymbolPtr &baseVirtualSym,
MEMOFFSET_32 startOffset = 0,
MEMOFFSET_32 virtualBasePtr = 0,
size_t virtualDispIndex = 0,
size_t m_virtualDispSize = 0 );
void getVirtualFields();
};
///////////////////////////////////////////////////////////////////////////////
......
......@@ -88,6 +88,11 @@ public:
return m_inheritedMember;
}
bool isVtbl() const
{
return m_vtblMember;
}
void setMemberInherited()
{
m_inheritedMember = true;
......@@ -130,7 +135,8 @@ protected:
m_virtualMember( false ),
m_methodMember(false),
m_constMember(false),
m_inheritedMember(false)
m_inheritedMember(false),
m_vtblMember(false)
{}
std::wstring m_name;
......@@ -150,6 +156,7 @@ protected:
bool m_methodMember;
bool m_constMember;
bool m_inheritedMember;
bool m_vtblMember;
};
///////////////////////////////////////////////////////////////////////////////////
......@@ -161,10 +168,18 @@ public:
static TypeFieldPtr getField(
const SymbolPtr &sym,
const std::wstring& name,
MEMOFFSET_32 offset )
MEMOFFSET_32 offset,
MEMOFFSET_32 virtualBasePtr,
size_t virtualDispIndex,
size_t virtualDispSize)
{
SymbolUdtField *p = new SymbolUdtField( sym, name );
p->m_offset = offset;
p->m_virtualBasePtr = virtualBasePtr;
p->m_virtualDispIndex = virtualDispIndex;
p->m_virtualDispSize = virtualDispSize;
p->m_virtualMember = virtualBasePtr != 0;
return TypeFieldPtr(p);
}
......@@ -188,23 +203,6 @@ public:
return TypeFieldPtr(p);
}
static TypeFieldPtr getVirtualField(
const SymbolPtr &sym,
const std::wstring& name,
MEMOFFSET_32 offset,
MEMOFFSET_32 virtualBasePtr,
size_t virtualDispIndex,
size_t virtualDispSize )
{
SymbolUdtField *p = new SymbolUdtField( sym, name );
p->m_offset = offset;
p->m_virtualBasePtr = virtualBasePtr;
p->m_virtualDispIndex = virtualDispIndex;
p->m_virtualDispSize = virtualDispSize;
p->m_virtualMember = true;
return TypeFieldPtr(p);
}
static TypeFieldPtr getVirtualMethodField(
const SymbolPtr& sym,
const std::wstring& name
......@@ -216,6 +214,24 @@ public:
return TypeFieldPtr(p);
}
static TypeFieldPtr getVtblField(
const SymbolPtr& sym,
const std::wstring& name,
MEMOFFSET_32 offset,
MEMOFFSET_32 virtualBasePtr,
size_t virtualDispIndex,
size_t virtualDispSize
)
{
SymbolUdtField *p = new SymbolUdtField(sym, name);
p->m_vtblMember = true;
p->m_offset = offset;
p->m_virtualBasePtr = virtualBasePtr;
p->m_virtualDispIndex = virtualDispIndex;
p->m_virtualDispSize = virtualDispSize;
p->m_virtualMember = virtualBasePtr != 0;
return TypeFieldPtr(p);
}
public:
......
......@@ -12,8 +12,8 @@ namespace kdlib {
const TypeFieldPtr& FieldCollection::lookup(const std::wstring &name) const
{
FieldList::const_reverse_iterator it;
for ( it = m_fields.rbegin(); it != m_fields.rend(); ++it )
FieldList::const_iterator it;
for (it = m_fields.begin(); it != m_fields.end(); ++it)
{
if ( (*it)->getName() == name )
return *it;
......
......@@ -394,9 +394,8 @@ PROCESS_DEBUG_ID loadDump( const std::wstring &fileName )
if ( FAILED( hres ) )
throw DbgEngException( L"IDebugControl::WaitForEvent", hres );
hres = g_dbgMgr->control->OutputCurrentState(DEBUG_OUTCTL_IGNORE, DEBUG_CURRENT_SYMBOL);
if (FAILED(hres))
throw DbgEngException(L"IDebugControl::OutputCurrentState", hres);
//skip error checking
g_dbgMgr->control->OutputCurrentState(DEBUG_OUTCTL_IGNORE, DEBUG_CURRENT_SYMBOL);
ULONG processId = -1;
hres = g_dbgMgr->system->GetCurrentProcessId( &processId );
......@@ -514,6 +513,42 @@ bool isDumpAnalyzing()
///////////////////////////////////////////////////////////////////////////////////
DumpType getDumpType()
{
HRESULT hres;
ULONG debugClass, debugQualifier;
hres = g_dbgMgr->control->GetDebuggeeType(&debugClass, &debugQualifier);
if (FAILED(hres))
throw DbgEngException(L"IDebugControl::GetDebuggeeType", hres);
if (debugQualifier < DEBUG_DUMP_SMALL)
throw DbgException("Target is not a dump");
if (debugQualifier > DEBUG_DUMP_IMAGE_FILE)
throw DbgException("Unsupported dump type");
return static_cast<DumpType>(debugQualifier);
}
///////////////////////////////////////////////////////////////////////////////////
DumpFormatFlagsSet getDumpFormat()
{
HRESULT hres;
ULONG formatFlags;
hres = g_dbgMgr->control->GetDumpFormatFlags(&formatFlags);
if (FAILED(hres))
throw DbgEngException(L"IDebugControl::GetDumpFormatFlags", hres);
return formatFlags;
}
///////////////////////////////////////////////////////////////////////////////////
bool isKernelDebugging()
{
HRESULT hres;
......
......@@ -89,3 +89,10 @@ TEST_F(ARM64KernelMiniDump, Test)
}
}
}
TEST_F(ARM64KernelMiniDump, DumpType)
{
EXPECT_TRUE(isDumpAnalyzing());
EXPECT_TRUE(isKernelDebugging());
EXPECT_EQ(DumpType::KernelSmall, getDumpType());
}
......@@ -78,3 +78,10 @@ TEST_F(ARMKernelMiniDump, Test)
}
}
TEST_F(ARMKernelMiniDump, DumpType)
{
EXPECT_TRUE(isDumpAnalyzing());
EXPECT_TRUE(isKernelDebugging());
EXPECT_EQ(DumpType::KernelSmall, getDumpType());
}
#include <stdafx.h>
#include "procfixture.h"
#include "memdumpfixture.h"
#include "kdlib/dbgengine.h"
using namespace kdlib;
......@@ -26,3 +27,24 @@ TEST_F(DbgEngineTest, DbgCommandUnicode)
{
EXPECT_EQ(L"💩", kdlib::debugCommand(kdlib::debugCommand(L".printf \"💩\""), true));
}
class MiniDump : public MemDumpFixture
{
public:
MiniDump()
: MemDumpFixture(makeDumpFullName(MemDumps::MINIDUMP))
{
}
};
TEST_F(MiniDump, DumpType)
{
EXPECT_TRUE(isDumpAnalyzing());
EXPECT_EQ(DumpType::Small, getDumpType());
}
TEST_F(MiniDump, DumpFormat)
{
auto expected = DumpFormat::UserSmallFullMemoryInfo | DumpFormat::UserSmallUnloadedModules | DumpFormat::UserSmallHandleData;
EXPECT_EQ(expected, getDumpFormat());
}
......@@ -20,6 +20,7 @@ public:
static constexpr wchar_t* WIN10_ARM64 = L"win10_arm64_mem";
static constexpr wchar_t* WIN10_ARM = L"win10_arm_rpi3_mem";
static constexpr wchar_t* WIN8_X64 = L"win8_x64_mem";
static constexpr wchar_t* MINIDUMP = L"targetapp_minidump";
};
inline std::wstring makeDumpDirName(const wchar_t* dumpName)
......