mirror of
https://github.com/ivellioscolin/pykd.git
synced 2025-04-17 01:13:24 +08:00
[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:
parent
16c796799b
commit
d3b5f99a20
314
pykd/pydataaccess.h
Normal file
314
pykd/pydataaccess.h
Normal 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");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
}
|
@ -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
|
||||
|
||||
|
@ -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"")
|
||||
{
|
||||
|
@ -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 );
|
||||
}
|
||||
|
@ -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))
|
||||
|
Loading…
Reference in New Issue
Block a user