[0.3.x] reworked : typedVar can change python byte sequences

git-svn-id: https://pykd.svn.codeplex.com/svn@91219 9b283d60-5439-405e-af05-b73fd8c4d996
This commit is contained in:
SND\ussrhero_cp 2017-04-23 15:34:46 +00:00 committed by Mikhail I. Izmestev
parent 16c796799b
commit d3b5f99a20
5 changed files with 400 additions and 54 deletions

314
pykd/pydataaccess.h Normal file
View File

@ -0,0 +1,314 @@
#pragma once
#include "boost/python/object.hpp"
#include "boost/python/wrapper.hpp"
#include "kdlib/dataaccessor.h"
#include "kdlib/exceptions.h"
#include "pythreadstate.h"
namespace python = boost::python;
namespace pykd {
///////////////////////////////////////////////////////////////////////////////
using kdlib::ImplementException;
///////////////////////////////////////////////////////////////////////////////
class PythonObjectAccessor : public kdlib::DataAccessor
{
public:
PythonObjectAccessor(python::object& obj, size_t pos = 0) : m_object(obj)
{
m_pystate = PyThreadState_Get();
m_startPos = pos;
}
public:
virtual size_t getLength() const {
AutoSavePythonState pystate(&m_pystate);
return python::len(m_object);
}
virtual unsigned char readByte(size_t pos=0) const {
return readValue<unsigned char>(pos);
}
virtual void writeByte(unsigned char value, size_t pos=0) {
writeValue(value,pos);
}
virtual char readSignByte(size_t pos=0) const {
return readValue<char>(pos);
}
virtual void writeSignByte(char value, size_t pos=0) {
writeValue(value,pos);
}
virtual unsigned short readWord(size_t pos=0) const {
return readValue<unsigned short>(pos);
}
virtual void writeWord(unsigned short value, size_t pos=0) {
writeValue(value,pos);
}
virtual short readSignWord(size_t pos=0) const {
return readValue<short>(pos);
}
virtual void writeSignWord(short value, size_t pos=0) {
writeValue(value,pos);
}
virtual unsigned long readDWord(size_t pos=0) const {
return readValue<unsigned long>(pos);
}
virtual void writeDWord(unsigned long value, size_t pos=0) {
writeValue(value,pos);
}
virtual long readSignDWord(size_t pos=0) const {
return readValue<long>(pos);
}
virtual void writeSignDWord(long value, size_t pos=0) {
writeValue(value,pos);
}
virtual unsigned long long readQWord(size_t pos=0) const {
return readValue<unsigned long long>(pos);
}
virtual void writeQWord(unsigned long long value, size_t pos=0) {
writeValue(value,pos);
}
virtual long long readSignQWord(size_t pos=0) const {
return readValue<long long>(pos);
}
virtual void writeSignQWord(long long value, size_t pos=0) {
writeValue(value,pos);
}
virtual float readFloat(size_t pos=0) const {
return readValue<float>(pos);
}
virtual void writeFloat(float value, size_t pos=0) {
writeValue(value,pos);
}
virtual double readDouble(size_t pos=0) const {
return readValue<double>(pos);
}
virtual void writeDouble(double value, size_t pos=0) {
writeValue(value,pos);
}
virtual void readBytes( std::vector<unsigned char>& dataRange, size_t count, size_t pos=0) const {
readValues(dataRange, count, pos);
}
virtual void writeBytes( const std::vector<unsigned char>& dataRange, size_t pos=0) {
writeValues(dataRange,pos);
}
void readWords( std::vector<unsigned short>& dataRange, size_t count, size_t pos) const {
readValues(dataRange, count, pos);
}
virtual void writeWords( const std::vector<unsigned short>& dataRange, size_t pos=0) {
writeValues(dataRange,pos);
}
virtual void readDWords( std::vector<unsigned long>& dataRange, size_t count, size_t pos=0) const {
readValues(dataRange, count, pos);
}
virtual void writeDWords( const std::vector<unsigned long>& dataRange, size_t pos=0) {
writeValues(dataRange,pos);
}
virtual void readQWords( std::vector<unsigned long long>& dataRange, size_t count, size_t pos=0) const {
readValues(dataRange, count, pos);
}
virtual void writeQWords( const std::vector<unsigned long long>& dataRange, size_t pos=0) {
writeValues(dataRange,pos);
}
virtual void readSignBytes( std::vector<char>& dataRange, size_t count, size_t pos=0) const {
readValues(dataRange, count, pos);
}
virtual void writeSignBytes( const std::vector<char>& dataRange, size_t pos=0) {
writeValues(dataRange,pos);
}
virtual void readSignWords( std::vector<short>& dataRange, size_t count, size_t pos=0) const {
readValues(dataRange, count, pos);
}
virtual void writeSignWords( const std::vector<short>& dataRange, size_t pos=0) {
writeValues(dataRange,pos);
}
virtual void readSignDWords( std::vector<long>& dataRange, size_t count, size_t pos=0) const {
readValues(dataRange, count, pos);
}
virtual void writeSignDWords( const std::vector<long>& dataRange, size_t pos=0) {
writeValues(dataRange, pos);
}
virtual void readSignQWords( std::vector<long long>& dataRange, size_t count, size_t pos=0) const {
readValues(dataRange, count, pos);
}
virtual void writeSignQWords( const std::vector<long long>& dataRange, size_t pos=0) {
writeValues(dataRange,pos);
}
virtual void readFloats( std::vector<float>& dataRange, size_t count, size_t pos=0) const {
readValues(dataRange, count, pos);
}
virtual void writeFloats( const std::vector<float>& dataRange, size_t pos=0) {
writeValues(dataRange, pos);
}
virtual void readDoubles( std::vector<double>& dataRange, size_t count, size_t pos=0) const {
readValues(dataRange, count, pos);
}
virtual void writeDoubles( const std::vector<double>& dataRange, size_t pos=0) {
writeValues(dataRange, pos);
}
virtual kdlib::DataAccessorPtr copy( size_t startOffset = 0, size_t length = 0 ) {
AutoSavePythonState pystate(&m_pystate);
return kdlib::DataAccessorPtr( new PythonObjectAccessor(m_object, startOffset) );
}
virtual std::wstring getLocationAsStr() const {
return L"python byte sequance";
}
virtual kdlib::MEMOFFSET_64 getAddress() const {
throw kdlib::DbgException("python accessor error");
}
virtual kdlib::VarStorage getStorageType() const {
throw kdlib::DbgException("python accessor error");
}
virtual std::wstring getRegisterName() const {
throw kdlib::DbgException("python accessor error");
}
private:
python::object m_object;
mutable PyThreadState* m_pystate;
size_t m_startPos;
template<typename T>
T readValue(size_t pos) const
{
AutoSavePythonState pystate(&m_pystate);
try
{
return readValueUnsafe<T>(pos);
}
catch( python::error_already_set const & )
{}
throw kdlib::DbgException("python accessor error");
}
template<typename T>
T readValueUnsafe(size_t pos) const
{
unsigned long long value = 0;
for ( size_t i = sizeof(T); i > 0; --i)
value = ( value << 8 ) + python::extract<unsigned char>(m_object[m_startPos + pos*sizeof(T) + i - 1])();
return *reinterpret_cast<T*>(&value);
}
template<typename T>
void writeValue(T value, size_t pos)
{
AutoSavePythonState pystate(&m_pystate);
try
{
writeValueUnsafe(value,pos);
return;
}
catch( python::error_already_set const & )
{}
throw kdlib::DbgException("python accessor error");
}
template<typename T>
void writeValueUnsafe(T value, size_t pos)
{
unsigned long long val = *reinterpret_cast<unsigned long long*>(&value);
for ( size_t i = 0; i < sizeof(T); ++i )
m_object[m_startPos + pos*sizeof(T) + i] = static_cast<unsigned char>( ( val >> (8*i)) & 0xFF );
}
template<typename T>
void readValues( std::vector<T>& dataRange, size_t count, size_t pos) const
{
AutoSavePythonState pystate(&m_pystate);
try
{
dataRange.resize(count);
for ( size_t i = 0; i < count; ++i )
dataRange[i] = readValueUnsafe<T>(pos + i);
return;
}
catch( python::error_already_set const & )
{}
throw kdlib::DbgException("python accessor error");
}
template<typename T>
void writeValues( const std::vector<T>& dataRange, size_t pos)
{
AutoSavePythonState pystate(&m_pystate);
try
{
for ( size_t i = 0; i < dataRange.size(); ++i )
writeValueUnsafe(dataRange[i], pos + i );
return;
}
catch( python::error_already_set const & )
{}
throw kdlib::DbgException("python accessor error");
}
};
///////////////////////////////////////////////////////////////////////////////
}

View File

@ -3,6 +3,10 @@
#include "pytypedvar.h"
#include "kdlib/exceptions.h"
#include "pytypeinfo.h"
#include "pydataaccess.h"
namespace pykd {
///////////////////////////////////////////////////////////////////////////////
@ -17,15 +21,10 @@ kdlib::TypedVarPtr getTypedVarByTypeName(const std::wstring &name, python::objec
return kdlib::loadTypedVar( name, offset );
}
std::vector<char> byteArray;
kdlib::DataAccessorPtr dataAceesor( new PythonObjectAccessor(dataStorage) );
for (int i = 0; i < python::len(dataStorage); ++i)
{
byteArray.push_back( python::extract<unsigned char>(dataStorage[i]) );
}
AutoRestorePyState pystate;
return kdlib::loadTypedVar( name, kdlib::getCacheAccessor(byteArray) );
return kdlib::loadTypedVar(name, dataAceesor );
}
///////////////////////////////////////////////////////////////////////////////
@ -40,15 +39,10 @@ kdlib::TypedVarPtr getTypedVarByTypeInfo( const kdlib::TypeInfoPtr &typeInfo, py
return kdlib::loadTypedVar(typeInfo, offset );
}
std::vector<char> byteArray;
kdlib::DataAccessorPtr dataAceesor( new PythonObjectAccessor(dataStorage) );
for (int i = 0; i < python::len(dataStorage); ++i)
{
byteArray.push_back( python::extract<unsigned char>(dataStorage[i]) );
}
AutoRestorePyState pystate;
return kdlib::loadTypedVar(typeInfo, kdlib::getCacheAccessor(byteArray) );
return kdlib::loadTypedVar(typeInfo, dataAceesor );
}
///////////////////////////////////////////////////////////////////////////////
@ -198,23 +192,6 @@ kdlib::TypedVarPtr TypedVarAdapter::getFieldAttr(kdlib::TypedVar& typedVar, cons
throw AttributeException(std::string(_bstr_t(sstr.str().c_str())).c_str());
}
///////////////////////////////////////////////////////////////////////////////
void TypedVarAdapter::setFieldAttr(kdlib::TypedVar& typedVar, const std::wstring &name, NumVariantAdaptor& var)
{
try
{
AutoRestorePyState pystate;
typedVar.setElement(name, var);
return;
}
catch (kdlib::TypeException&)
{}
std::wstringstream sstr;
sstr << L"typed var has no field " << L'\'' << name << L'\'';
throw AttributeException(std::string(_bstr_t(sstr.str().c_str())).c_str());
}
///////////////////////////////////////////////////////////////////////////////
@ -236,5 +213,50 @@ python::list TypedVarAdapter::getRawBytes(kdlib::TypedVar& typedVar)
///////////////////////////////////////////////////////////////////////////////
void TypedVarAdapter::setField(kdlib::TypedVar& typedVar, const std::wstring &name, python::object& object)
{
kdlib::TypedValue value = NumVariantAdaptor::convertToVariant(object);
{
AutoRestorePyState pystate;
typedVar.setElement(name, value);
}
}
///////////////////////////////////////////////////////////////////////////////
void TypedVarAdapter::setElementByIndex(kdlib::TypedVar& typedVar, long index, python::object& object)
{
kdlib::TypedValue value = NumVariantAdaptor::convertToVariant(object);
{
AutoRestorePyState pystate;
typedVar.setElement(index, value);
}
}
///////////////////////////////////////////////////////////////////////////////
void TypedVarAdapter::setFieldAttr(kdlib::TypedVar& typedVar, const std::wstring &name, python::object& object)
{
kdlib::TypedValue value = NumVariantAdaptor::convertToVariant(object);
try
{
AutoRestorePyState pystate;
typedVar.setElement(name, value);
return;
}
catch (kdlib::TypeException&)
{}
std::wstringstream sstr;
sstr << L"typed var has no field " << L'\'' << name << L'\'';
throw AttributeException(std::string(_bstr_t(sstr.str().c_str())).c_str());
}
///////////////////////////////////////////////////////////////////////////////
} // namesapce pykd

View File

@ -110,15 +110,11 @@ struct TypedVarAdapter {
return typedVar.getElement( name );
}
static void setField(kdlib::TypedVar& typedVar, const std::wstring &name, NumVariantAdaptor& var)
{
AutoRestorePyState pystate;
typedVar.setElement(name, var);
}
static void setField(kdlib::TypedVar& typedVar, const std::wstring &name, python::object& object);
static kdlib::TypedVarPtr getFieldAttr(kdlib::TypedVar& typedVar, const std::wstring &name);
static void setFieldAttr(kdlib::TypedVar& typedVar, const std::wstring &name, NumVariantAdaptor& var);
static void setFieldAttr(kdlib::TypedVar& typedVar, const std::wstring &name, python::object& object);
static size_t getElementCount( kdlib::TypedVar& typedVar )
{
@ -138,11 +134,7 @@ struct TypedVarAdapter {
return typedVar.getElement( index );
}
static void setElementByIndex(kdlib::TypedVar& typedVar, long index, NumVariantAdaptor& var)
{
AutoRestorePyState pystate;
typedVar.setElement(index, var);
}
static void setElementByIndex(kdlib::TypedVar& typedVar, long index, python::object& object);
static kdlib::TypedVarPtr getMethodByName(kdlib::TypedVar& typedVar, const std::wstring &name, const std::wstring &prototype = L"")
{

View File

@ -5,6 +5,7 @@
#include "kdlib/variant.h"
#include "kdlib/exceptions.h"
#include "dbgexcept.h"
#include "pythreadstate.h"
namespace pykd {
@ -122,7 +123,12 @@ public:
static python::object NumVariantAdaptor::convertToPython( kdlib::NumBehavior& num )
{
kdlib::NumVariant var = kdlib::NumVariant( num );
kdlib::NumVariant var;
{
AutoRestorePyState pystate;
var = kdlib::NumVariant( num );
}
return convertToPython( var );
}

View File

@ -305,12 +305,12 @@ class TypedVarTest( unittest.TestCase ):
for field in tv.fields():
str( field )
def testDeadlockList(self):
lst = []
entry = pykd.typedVar("deadlockEntry").flink
for i in range( 0, 100000 ):
lst.append(entry)
entry = entry.deref().flink
#def testDeadlockList(self):
# lst = []
# entry = pykd.typedVar("deadlockEntry").flink
# for i in xrange( 0, 100000 ):
# lst.append(entry)
# entry = entry.deref().flink
def testHresult(self):
tv = pykd.typedVar( "g_atlException" )
@ -427,9 +427,21 @@ class TypedVarTest( unittest.TestCase ):
self.assertEqual( [ 0x55, 0x55, 0, 0], target.module.typedVar( "ulongConst" ).rawBytes() )
def testSetField(self):
var = target.module.typedVar("structTest", [0x55] * 20 )
var.setField("m_field2", 0xAA)
var.m_field3 == 0xAAAA
self.assertEqual( 0xAAAA, var.m_filed3)
byteseq = [0x55] * 20
var = target.module.typedVar("structTest", byteseq)
var.setField("m_field1", 0xFF000000000000AA)
self.assertEqual( [0xAA, 0, 0, 0, 0, 0, 0, 0xFF], byteseq[4:12] )
var.m_field3 = 0xAAAA
self.assertEqual( 0xAAAA, var.m_field3)
self.assertEqual( 0xAAAA, var.field("m_field3") )
def testAttr(self):
var = target.module.typedVar("structTest", [0x55] * 20 )
self.assertTrue(hasattr(var, "m_field3"))
setattr(var, "m_field1", 11)
self.assertEqual(11, getattr(var, "m_field1"))
self.assertFalse(hasattr(var, "noexisit"))
self.assertRaises(AttributeError, getattr, *(var, "noexists"))
self.assertRaises(AttributeError, setattr, *(var, "noexists", 0))