Commit 2b4fa087 authored by SND\ussrhero_cp's avatar SND\ussrhero_cp Committed by Mikhail I. Izmestev

added managed array support

git-svn-id: https://kdlibcpp.svn.codeplex.com/svn@91254 9b283d60-5439-405e-af05-b73fd8c4d996
parent 0b1f0cd2
......@@ -19,7 +19,7 @@ void uninitialize();
// manage debug target
PROCESS_DEBUG_ID startProcess(const std::wstring &processName, const ProcessDebugFlags& flags = ProcessDebugDefault);
PROCESS_DEBUG_ID attachProcess(PROCESS_ID pid, const ProcessDebugFlags& flags = ProcessDebugDefault);
PROCESS_DEBUG_ID attachProcess(PROCESS_ID pid);
void detachProcess( PROCESS_DEBUG_ID processId = -1);
void terminateProcess( PROCESS_DEBUG_ID processId = -1);
void detachAllProcesses();
......
......@@ -3,6 +3,7 @@
#include <boost/smart_ptr.hpp>
#include "kdlib/dbgtypedef.h"
#include "kdlib/typedvar.h"
namespace kdlib {
......@@ -34,6 +35,8 @@ public:
TargetHeapPtr getManagedHeap();
TypedVarPtr getManagedVar(MEMOFFSET_64 addr);
///////////////////////////////////////////////////////////////////////////////
}
......
......@@ -93,6 +93,7 @@ public:
virtual bool isManaged() = 0;
virtual TargetHeapPtr getManagedHeap() = 0;
virtual TypedVarPtr getManagedVar(MEMOFFSET_64 addr) = 0;
};
///////////////////////////////////////////////////////////////////////////////
......
......@@ -13,8 +13,6 @@ namespace kdlib {
///////////////////////////////////////////////////////////////////////////////
class TypedVar;
typedef boost::shared_ptr<TypedVar> TypedVarPtr;
typedef std::vector<TypedVarPtr> TypedVarList;
class TypedValue;
......
......@@ -7,6 +7,7 @@
#include "kdlib/symengine.h"
#include "kdlib/variant.h"
#include "kdlib/dataaccessor.h"
namespace kdlib {
......@@ -15,6 +16,9 @@ namespace kdlib {
class TypeInfo;
typedef boost::shared_ptr<TypeInfo> TypeInfoPtr;
class TypedVar;
typedef boost::shared_ptr<TypedVar> TypedVarPtr;
TypeInfoPtr loadType( const std::wstring &symName );
TypeInfoPtr loadType( SymbolPtr &symbol );
TypeInfoPtr loadType( SymbolPtr &symbolScope, const std::wstring &symbolName );
......@@ -122,6 +126,8 @@ public:
virtual MEMOFFSET_REL getVtblOffset() = 0;
virtual TypedVarPtr getVar(const DataAccessorPtr &dataSource) = 0;
protected:
static bool isBaseType( const std::wstring &typeName );
......
......@@ -50,6 +50,7 @@
<ClCompile Include="net\net.cpp" />
<ClCompile Include="net\netheap.cpp" />
<ClCompile Include="net\netmodule.cpp" />
<ClCompile Include="net\netobject.cpp" />
<ClCompile Include="net\nettype.cpp" />
<ClCompile Include="processmon.cpp" />
<ClCompile Include="stack.cpp" />
......
......@@ -109,7 +109,6 @@
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\lib\native\src\boost_regex.wc_regex_traits.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\lib\native\src\boost_regex.wide_posix_api.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\lib\native\src\boost_regex.winstances.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\lib\native\src\boost_chrono.chrono.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\lib\native\src\boost_chrono.process_cpu_clocks.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\lib\native\src\boost_chrono.thread_clock.cpp" />
<ClCompile Include="clang\clang.cpp">
......@@ -133,6 +132,10 @@
<ClCompile Include="net\metadata.cpp">
<Filter>net</Filter>
</ClCompile>
<ClCompile Include="net\netobject.cpp">
<Filter>net</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\lib\native\src\boost_chrono.chrono.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h" />
......
......@@ -49,11 +49,162 @@ MetaDataProvider::MetaDataProvider(ICorDebugModule* module)
throw DbgException("Failed ICorDebugModule::GetMetaDataInterface");
}
TypeInfoPtr MetaDataProvider::getTypeByToken(mdTypeDef typeDef)
//TypeInfoPtr MetaDataProvider::getTypeByToken(mdTypeDef typeDef)
//{
// return TypeInfoPtr( new NetTypeClass( shared_from_this(), getTypeNameByToken(typeDef), typeDef ) );//}
CorElementType MetaDataProvider::getFieldElementType(mdFieldDef fieldDef)
{
return TypeInfoPtr( new NetTypeClass( shared_from_this(), getTypeNameByToken(typeDef), typeDef ) );
std::vector<wchar_t> fieldNameBuf(0x100);
ULONG fieldNameLen;
DWORD flags;
mdTypeDef classTypeDef;
DWORD valueFlag;
PCCOR_SIGNATURE sigBlob;
ULONG sigBlobSize;
HRESULT hres = m_metaDataImport->GetFieldProps(
fieldDef,
&classTypeDef,
&fieldNameBuf.front(),
fieldNameBuf.size(),
&fieldNameLen,
&flags,
&sigBlob,
&sigBlobSize,
&valueFlag,
NULL,
NULL);
if ( FAILED(hres) )
throw DbgException("Failed IMetaDataImport::GetFieldProps");
ULONG callingConv = (CorCallingConvention)CorSigUncompressCallingConv(sigBlob);
return CorSigUncompressElementType(sigBlob);
}
CorElementType MetaDataProvider::getFieldSZArrayElementType(mdFieldDef fieldDef)
{
std::vector<wchar_t> fieldNameBuf(0x100);
ULONG fieldNameLen;
DWORD flags;
mdTypeDef classTypeDef;
DWORD valueFlag;
PCCOR_SIGNATURE sigBlob;
ULONG sigBlobSize;
HRESULT hres = m_metaDataImport->GetFieldProps(
fieldDef,
&classTypeDef,
&fieldNameBuf.front(),
fieldNameBuf.size(),
&fieldNameLen,
&flags,
&sigBlob,
&sigBlobSize,
&valueFlag,
NULL,
NULL);
if ( FAILED(hres) )
throw DbgException("Failed IMetaDataImport::GetFieldProps");
ULONG callingConv = (CorCallingConvention)CorSigUncompressCallingConv(sigBlob);
CorSigUncompressElementType(sigBlob);
return CorSigUncompressElementType(sigBlob);
}
mdTypeDef MetaDataProvider::getFieldClassToken(mdFieldDef fieldDef)
{
std::vector<wchar_t> fieldNameBuf(0x100);
ULONG fieldNameLen;
DWORD flags;
mdTypeDef classTypeDef;
DWORD valueFlag;
PCCOR_SIGNATURE sigBlob;
ULONG sigBlobSize;
HRESULT hres = m_metaDataImport->GetFieldProps(
fieldDef,
&classTypeDef,
&fieldNameBuf.front(),
fieldNameBuf.size(),
&fieldNameLen,
&flags,
&sigBlob,
&sigBlobSize,
&valueFlag,
NULL,
NULL);
if ( FAILED(hres) )
throw DbgException("Failed IMetaDataImport::GetFieldProps");
CorSigUncompressCallingConv(sigBlob);
CorSigUncompressElementType(sigBlob);
return CorSigUncompressToken(sigBlob);
}
DWORD MetaDataProvider::getFieldAttr(mdFieldDef fieldDef)
{
mdTypeDef classTypeDef;
DWORD attr;
HRESULT hres = m_metaDataImport->GetFieldProps(
fieldDef,
&classTypeDef,
NULL,
0,
NULL,
&attr,
NULL,
NULL,
NULL,
NULL,
NULL);
if ( FAILED(hres) )
throw DbgException("Failed IMetaDataImport::GetFieldProps");
return attr;
}
std::wstring MetaDataProvider::getFieldName(mdFieldDef fieldDef)
{
std::vector<wchar_t> fieldNameBuf(0x100);
ULONG fieldNameLen;
mdTypeDef typeDef;
HRESULT hres = m_metaDataImport->GetFieldProps(
fieldDef,
&typeDef,
&fieldNameBuf.front(),
fieldNameBuf.size(),
&fieldNameLen,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL);
if ( FAILED(hres) )
throw DbgException("Failed IMetaDataImport::GetFieldProps");
return std::wstring(&fieldNameBuf.front());
}
std::wstring MetaDataProvider::getTypeNameByToken(mdTypeDef typeDef)
{
......@@ -83,15 +234,26 @@ std::wstring MetaDataProvider::getTypeNameByToken(mdTypeDef typeDef)
if ( FAILED(hres) )
throw DbgException("Failed IMetaDataImport::GetNestedClassProps");
TypeInfoPtr encloseType = getTypeByToken(encloseClass);
std::wstring encloseTypeName = getTypeNameByToken(encloseClass);
typeName = encloseType->getName() + std::wstring(L".") + typeName;
typeName = encloseTypeName + std::wstring(L".") + typeName;
}
return typeName;
}
mdTypeDef MetaDataProvider::getTypeTokenByName(const std::wstring& typeName)
{
mdTypeDef typeDef;
HRESULT hres = m_metaDataImport->FindTypeDefByName(typeName.c_str(), 0, &typeDef);
if (FAILED(hres) )
throw DbgException("Failed IMetaDataImport::FindTypeDefByName");
return typeDef;
}
TypeNameList MetaDataProvider::getTypeNames(const std::wstring& mask)
{
HCORENUM enumTypeDefs = NULL;
......@@ -121,4 +283,48 @@ TypeNameList MetaDataProvider::getTypeNames(const std::wstring& mask)
return typeList;
}
void MetaDataProvider::getFields(mdTypeDef typeDef, NetFieldList& fields)
{
HCORENUM enumFieldDefs = NULL;
fields.clear();
auto enumCloseFn = [=](HCORENUM*){ if ( enumFieldDefs ) m_metaDataImport->CloseEnum(enumFieldDefs); };
std::unique_ptr<HCORENUM, decltype(enumCloseFn)> enumCloser(&enumFieldDefs, enumCloseFn);
while(true)
{
mdFieldDef fieldDef;
ULONG fetched;
HRESULT hres = m_metaDataImport->EnumFields(&enumFieldDefs, typeDef, &fieldDef, 1, &fetched);
if ( FAILED(hres) )
throw DbgException("Failed IMetaDataImport::EnumTypeDefs");
if ( hres != S_OK )
break;
std::vector<wchar_t> fieldNameBuf(0x100);
ULONG fieldNameLen;
hres = m_metaDataImport->GetFieldProps(
fieldDef,
&typeDef,
&fieldNameBuf.front(),
fieldNameBuf.size(),
&fieldNameLen,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL);
if ( FAILED(hres) )
throw DbgException("Failed IMetaDataImport::GetFieldProps");
fields.push_back( std::make_pair( std::wstring(&fieldNameBuf.front()), fieldDef) );
}
}
}
......@@ -19,6 +19,8 @@ typedef boost::shared_ptr<MetaDataProvider> MetaDataProviderPtr;
MetaDataProviderPtr getMetaDataProvider(ICorDebugModule* module);
typedef std::list< std::pair< std::wstring, mdFieldDef > > NetFieldList;
class MetaDataProvider : public boost::enable_shared_from_this<MetaDataProvider>
{
......@@ -26,12 +28,27 @@ class MetaDataProvider : public boost::enable_shared_from_this<MetaDataProvider>
public:
TypeInfoPtr getTypeByToken(mdTypeDef typeDef);
CorElementType getFieldElementType(mdFieldDef fieldDef);
CorElementType getFieldSZArrayElementType(mdFieldDef fieldDef);
DWORD getFieldAttr(mdFieldDef fieldDef);
mdTypeDef getFieldClassToken(mdFieldDef fieldDef);
std::wstring getFieldName(mdFieldDef fieldDef);
TypeNameList getTypeNames(const std::wstring& mask);
std::wstring getTypeNameByToken(mdTypeDef typeDef);
mdTypeDef getTypeTokenByName(const std::wstring& typeName);
void getFields(mdTypeDef typeDef, NetFieldList& fields);
private:
MetaDataProvider(ICorDebugModule* module);
......
#pragma once
#include <MetaHost.h>
#include <CorHdr.h>
#include <CorDebug.h>
#include <ClrData.h>
#include <MetaHost.h>
#include <atlbase.h>
//#include "kdlib/dbgtypedef.h"
......
......@@ -71,7 +71,7 @@ size_t NetHeap::getCount(const std::wstring& typeName, size_t minSize, size_t
if ( !typeName.empty() || minSize != 0 || maxSize != -1 )
{
TypeInfoPtr typeObj = getTypeById(heapObj.type);
TypeInfoPtr typeObj = getNetTypeById(heapObj.type);
std::wstring tn = typeObj->getName();
......@@ -127,7 +127,7 @@ bool NetHeapEnum::Next(MEMOFFSET_64& addr, std::wstring& typeName, size_t& size)
if ( S_OK != hres )
return false;
TypeInfoPtr typeObj = getTypeById(heapObj.type);
TypeInfoPtr typeObj = getNetTypeById(heapObj.type);
std::wstring tn = typeObj->getName();
......
......@@ -3,6 +3,7 @@
#include "netmodule.h"
#include "net.h"
#include "nettype.h"
#include <cor.h>
......@@ -151,8 +152,37 @@ MEMOFFSET_64 NetModule::getImageBase(ICorDebugModule* module)
///////////////////////////////////////////////////////////////////////////////
TypeInfoPtr NetModule::getTypeByName( const std::wstring &typeName )
{
initCorDebugModule();
NOT_IMPLEMENTED();
// return TypeInfoPtr( new NetTypeClass(m_metaDataProvider, typeName) );
}
///////////////////////////////////////////////////////////////////////////////
}
//
......
......@@ -39,6 +39,8 @@ protected:
TypeNameList NetModule::enumTypes(const std::wstring& mask);
TypeInfoPtr getTypeByName( const std::wstring &typeName );
protected:
static
......
#include "stdafx.h"
#include "kdlib/exceptions.h"
#include "kdlib/memaccess.h"
#include "net/netobject.h"
#include "net/net.h"
#include "net/nettype.h"
namespace kdlib {
///////////////////////////////////////////////////////////////////////////////
TypedVarPtr getManagedVar(MEMOFFSET_64 addr)
{
COR_TYPEID typeId;
HRESULT hres = g_netMgr->targetProcess5()->GetTypeID(addr, &typeId);
if (FAILED(hres))
throw DbgException("Failed ICorDebugProcess5::GetTypeID");
TypeInfoPtr typeInfo = getNetTypeById(typeId);
return loadTypedVar(typeInfo, addr);
}
///////////////////////////////////////////////////////////////////////////////
TypedVarPtr NetObjectClass::getElement( const std::wstring& fieldName )
{
TypeInfoPtr fieldType = m_typeInfo->getElement( fieldName );
MEMOFFSET_32 fieldOffset = m_typeInfo->getElementOffset(fieldName);
return loadTypedVar( fieldType, m_dataAccessor->copy(fieldOffset, fieldType->getSize()) );
}
///////////////////////////////////////////////////////////////////////////////
NetObjectArray::NetObjectArray(const TypeInfoPtr& typeInfo, MEMOFFSET_64 addr, const COR_ARRAY_LAYOUT& arrayLayout, std::vector<size_t> indices ) :
m_typeInfo(typeInfo),
m_arrayLayout(arrayLayout),
m_arrayObjAddr(addr)
{
m_elementSize = m_arrayLayout.elementSize;
m_elementCount = ptrDWord(addr + m_arrayLayout.countOffset);
m_indices = indices;
if ( arrayLayout.numRanks == 1 )
{
m_ranks.push_back(m_elementCount);
}
else
{
for ( auto rank = 0; rank < arrayLayout.numRanks; rank++)
{
switch( arrayLayout.rankSize )
{
case 1:
m_ranks.push_back( ptrByte(addr + m_arrayLayout.rankOffset + arrayLayout.rankSize * m_ranks.size() ) );
break;
case 2:
m_ranks.push_back( ptrWord(addr + m_arrayLayout.rankOffset + arrayLayout.rankSize * m_ranks.size() ) );
break;
case 4:
m_ranks.push_back( ptrDWord(addr + m_arrayLayout.rankOffset + arrayLayout.rankSize * m_ranks.size() ) );
break;
case 8:
m_ranks.push_back( ptrQWord(addr + m_arrayLayout.rankOffset + arrayLayout.rankSize * m_ranks.size() ) );
break;
default:
throw DbgException("Unsupported array rank size");
}
}
}
MEMOFFSET_64 dataBegin = addr + m_arrayLayout.firstElementOffset;
m_dataAccessor = getMemoryAccessor(dataBegin, m_elementCount*m_elementSize);
}
///////////////////////////////////////////////////////////////////////////////
TypedVarPtr NetObjectArray::getElement( size_t index )
{
if ( index >= m_ranks[ m_indices.size() ] )
throw IndexException( index );
auto indices = m_indices;
indices.push_back(index);
if ( m_indices.size() + 1 < m_ranks.size() )
{
return TypedVarPtr( new NetObjectArray(m_typeInfo, m_arrayObjAddr, m_arrayLayout, indices) );
}
TypeInfoPtr elementType;
switch ( m_arrayLayout.componentType )
{
case ELEMENT_TYPE_CHAR:
elementType = loadType(L"Char");
break;
case ELEMENT_TYPE_I1:
elementType = loadType(L"Int1B");
break;
case ELEMENT_TYPE_U1:
elementType = loadType(L"UInt1B");
break;
case ELEMENT_TYPE_I2:
elementType = loadType(L"Int2B");
break;
case ELEMENT_TYPE_U2:
elementType = loadType(L"UInt1B");
break;
case ELEMENT_TYPE_I4:
elementType = loadType(L"Int4B");
break;
case ELEMENT_TYPE_U4:
elementType = loadType(L"UInt4B");
break;
case ELEMENT_TYPE_I8:
elementType = loadType(L"Int8B");
break;
case ELEMENT_TYPE_U8:
elementType = loadType(L"UInt8B");
break;
case ELEMENT_TYPE_R4:
elementType = loadType(L"Float");
break;
case ELEMENT_TYPE_R8:
elementType = loadType(L"Double");
break;
case ELEMENT_TYPE_CLASS:
elementType = getNetTypeById(m_arrayLayout.componentID);
break;
default:
NOT_IMPLEMENTED();
}
size_t rawIndex = 0;
size_t elements = m_elementCount;
for ( size_t i = 0; i < m_ranks.size(); ++i)
{
elements = elements / m_ranks[i];
rawIndex += elements * indices[i];
}
return loadTypedVar( elementType, m_dataAccessor->copy(m_elementSize*rawIndex, m_elementSize) );
}
///////////////////////////////////////////////////////////////////////////////
size_t NetObjectArray::getElementCount()
{
return m_ranks.back();
}
///////////////////////////////////////////////////////////////////////////////
}
This diff is collapsed.
#include "stdafx.h"
#include <sstream>
#include <iomanip>
#include <metahost.h>
#include "kdlib/memaccess.h"
#include "net/nettype.h"
#include "net/netmodule.h"
#include "net/metadata.h"
#include "net/netobject.h"
namespace kdlib {
///////////////////////////////////////////////////////////////////////////////
TypeInfoPtr getTypeClass(ICorDebugType* typeClass)
TypeInfoPtr getNetTypeClass(COR_TYPEID typeId)
{
return TypeInfoPtr( NetTypeClass::createById(typeId) );
}
///////////////////////////////////////////////////////////////////////////////
TypeInfoPtr getNetTypeArray(COR_TYPEID typeId)
{
COR_ARRAY_LAYOUT arrayLayout;
HRESULT hres = g_netMgr->targetProcess5()->GetArrayLayout(typeId, &arrayLayout);
if ( FAILED(hres) )
throw DbgException("Failed ICorDebugProcess5::GetArrayLayout");
return TypeInfoPtr( new NetTypeArray( arrayLayout ) );
}
///////////////////////////////////////////////////////////////////////////////
TypeInfoPtr getNetTypeById(COR_TYPEID typeId)
{
CComPtr<ICorDebugType> objType;
HRESULT hres = g_netMgr->targetProcess5()->GetTypeForTypeID(typeId, &objType);
if (FAILED(hres))
throw DbgException("Failed ICorDebugProcess5::GetTypeForTypeID");
CorElementType elementType;
hres = objType->GetType(&elementType);
if (FAILED(hres))
throw DbgException("Failed ICorDebugType::GetType");
switch( elementType )
{
case ELEMENT_TYPE_CLASS:
case ELEMENT_TYPE_VALUETYPE:
return getNetTypeClass(typeId);
case ELEMENT_TYPE_SZARRAY:
case ELEMENT_TYPE_ARRAY:
return getNetTypeArray(typeId);
}
NOT_IMPLEMENTED();
}
///////////////////////////////////////////////////////////////////////////////
NetTypeClass* NetTypeClass::createById(COR_TYPEID typeId)
{
CComPtr<ICorDebugType> objType;
HRESULT hres = g_netMgr->targetProcess5()->GetTypeForTypeID(typeId, &objType);
if (FAILED(hres))
throw DbgException("Failed ICorDebugProcess5::GetTypeForTypeID");
CComPtr<ICorDebugClass> objClass;
HRESULT hres = typeClass->GetClass(&objClass);
hres = objType->GetClass(&objClass);
if (FAILED(hres))
throw DbgException("Failed ICorDebugType::GetClass");
......@@ -27,53 +88,209 @@ TypeInfoPtr getTypeClass(ICorDebugType* typeClass)
if ( FAILED(hres) )
throw DbgException("Failed ICorDebugClass::GetToken");