add: secondary callback data (issue #14)

This commit is contained in:
2018-02-26 20:14:15 +03:00
parent 64bdab59cc
commit 15eae98a0f
8 changed files with 137 additions and 0 deletions

View File

@ -590,6 +590,7 @@
<ClInclude Include="pymodule.h" /> <ClInclude Include="pymodule.h" />
<ClInclude Include="pyprocess.h" /> <ClInclude Include="pyprocess.h" />
<ClInclude Include="pysymengine.h" /> <ClInclude Include="pysymengine.h" />
<ClInclude Include="pytagged.h" />
<ClInclude Include="pythreadstate.h" /> <ClInclude Include="pythreadstate.h" />
<ClInclude Include="pytypedvar.h" /> <ClInclude Include="pytypedvar.h" />
<ClInclude Include="pytypeinfo.h" /> <ClInclude Include="pytypeinfo.h" />
@ -623,6 +624,7 @@
</ClCompile> </ClCompile>
<ClCompile Include="pymodule.cpp" /> <ClCompile Include="pymodule.cpp" />
<ClCompile Include="pyprocess.cpp" /> <ClCompile Include="pyprocess.cpp" />
<ClCompile Include="pytagged.cpp" />
<ClCompile Include="pytypedvar.cpp" /> <ClCompile Include="pytypedvar.cpp" />
<ClCompile Include="pytypeinfo.cpp" /> <ClCompile Include="pytypeinfo.cpp" />
<ClCompile Include="stdafx.cpp"> <ClCompile Include="stdafx.cpp">

View File

@ -81,6 +81,9 @@
<ClInclude Include="pydataaccess.h"> <ClInclude Include="pydataaccess.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="pytagged.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="stdafx.cpp"> <ClCompile Include="stdafx.cpp">
@ -248,6 +251,9 @@
<ClCompile Include="pyprocess.cpp"> <ClCompile Include="pyprocess.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="pytagged.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="pykd.def"> <None Include="pykd.def">

View File

@ -20,6 +20,7 @@
#include "pytypeinfo.h" #include "pytypeinfo.h"
#include "pycpucontext.h" #include "pycpucontext.h"
#include "pyprocess.h" #include "pyprocess.h"
#include "pytagged.h"
using namespace pykd; using namespace pykd;
@ -597,6 +598,12 @@ BOOST_PYTHON_MODULE( pykd )
python::def( "removeSyntheticSymbol", pykd::removeSyntheticSymbol, python::def( "removeSyntheticSymbol", pykd::removeSyntheticSymbol,
"The removeSyntheticSymbol function removes a synthetic symbol from a module in the current proces" ); "The removeSyntheticSymbol function removes a synthetic symbol from a module in the current proces" );
// secondary callback data
python::def("enumTagged", pykd::enumTagged,
"Return the list of secondary callback data IDs (as a strings)" );
python::def("loadTaggedBuffer", pykd::loadTaggedBuffer,
"Read the buffer of secondary callback data by ID" );
python::class_<kdlib::NumBehavior, boost::noncopyable>( "numVariant", "numVariant", python::no_init ) python::class_<kdlib::NumBehavior, boost::noncopyable>( "numVariant", "numVariant", python::no_init )
.def("__init__", python::make_constructor(&NumVariantAdaptor::getVariant) ) .def("__init__", python::make_constructor(&NumVariantAdaptor::getVariant) )
.def( "__eq__", &NumVariantAdaptor::eq ) .def( "__eq__", &NumVariantAdaptor::eq )

76
pykd/pytagged.cpp Normal file
View File

@ -0,0 +1,76 @@
#include "stdafx.h"
#include "pytagged.h"
#include "kdlib\tagged.h"
#include "kdlib\exceptions.h"
#include "pythreadstate.h"
#include "stladaptor.h"
#include <rpc.h>
#pragma comment(lib, "Rpcrt4.lib")
namespace pykd {
void __declspec(noreturn) throwRpcStatus( const std::string &functionName, RPC_STATUS status )
{
std::stringstream sstr;
sstr << "Call " << functionName << " failed\n";
sstr << "RPC_STATUS 0x" << std::hex << status;
throw kdlib::DbgException( sstr.str() );
}
python::list enumTagged()
{
std::list<kdlib::TaggedId> ids;
{
AutoRestorePyState pystate;
ids = std::move( kdlib::enumTagged() );
}
python::list result;
for (const auto &id : ids)
{
RPC_WSTR id_str = nullptr;
auto status = ::UuidToString(&id, &id_str);
if (RPC_S_OK != status)
throwRpcStatus("UuidToString", status);
const auto stringFree =
[](RPC_WSTR *str)
{
auto status = ::RpcStringFree(str);
if (RPC_S_OK != status)
throwRpcStatus("RpcStringFree", status);
};
std::unique_ptr<RPC_WSTR, decltype(stringFree)> freeGuard{&id_str, stringFree};
result.append( std::wstring(reinterpret_cast<wchar_t *>(id_str)) );
}
return result;
}
python::list loadTaggedBuffer(const std::wstring &id_str)
{
const auto rcp_str =
reinterpret_cast<RPC_WSTR>( const_cast<wchar_t *>(id_str.c_str()) );
kdlib::TaggedId id;
auto status = ::UuidFromString(rcp_str, &id);
if (RPC_S_OK != status)
throwRpcStatus("UuidFromString", status);
kdlib::TaggedBuffer buff;
{
AutoRestorePyState pystate;
buff = std::move( kdlib::loadTaggedBuffer(id) );
}
return vectorToList(buff);
}
} // namespace pykd

12
pykd/pytagged.h Normal file
View File

@ -0,0 +1,12 @@
#pragma once
namespace python = boost::python;
namespace pykd {
python::list enumTagged();
python::list loadTaggedBuffer(const std::wstring &id_str);
} // namespace pykd

View File

@ -27,6 +27,7 @@ import excepttest
import targetprocess import targetprocess
import ehloadtest import ehloadtest
import synsymtest import synsymtest
import taggedtest
pykd.initialize() pykd.initialize()
@ -65,6 +66,7 @@ def getTestSuite( singleName = "" ):
unittest.TestLoader().loadTestsFromTestCase( mspdbtest.MsPdbTest ), unittest.TestLoader().loadTestsFromTestCase( mspdbtest.MsPdbTest ),
unittest.TestLoader().loadTestsFromTestCase( targetprocess.ProcessTest ), unittest.TestLoader().loadTestsFromTestCase( targetprocess.ProcessTest ),
unittest.TestLoader().loadTestsFromTestCase( ehloadtest.EhLoadTest ), unittest.TestLoader().loadTestsFromTestCase( ehloadtest.EhLoadTest ),
unittest.TestLoader().loadTestsFromTestCase( taggedtest.TaggedTest ),
#unittest.TestLoader().loadTestsFromTestCase( excepttest.ExceptionTest ), #unittest.TestLoader().loadTestsFromTestCase( excepttest.ExceptionTest ),
] ) ] )

View File

@ -50,6 +50,7 @@
<Compile Include="regtest.py" /> <Compile Include="regtest.py" />
<Compile Include="stacktest.py" /> <Compile Include="stacktest.py" />
<Compile Include="synsymtest.py" /> <Compile Include="synsymtest.py" />
<Compile Include="taggedtest.py" />
<Compile Include="target.py" /> <Compile Include="target.py" />
<Compile Include="targetprocess.py" /> <Compile Include="targetprocess.py" />
<Compile Include="testutils.py" /> <Compile Include="testutils.py" />

View File

@ -0,0 +1,31 @@
import unittest
import pykd
import sys
import os
class TaggedTest(unittest.TestCase):
def setUp(self):
dump_file = os.path.join( os.path.dirname(sys.argv[0]),
r"..\..\kdlibcpp\kdlib\tests\dumps\win8_x64_mem.cab" )
self.dump_id = pykd.loadDump( dump_file )
self._existing_id = "D03DC06F-D88E-44C5-BA2A-FAE035172D19"
self._non_existing_id = "88597A32-1493-41CA-BF87-2A950DF4CEE0"
def tearDown(self):
pykd.closeDump( self.dump_id )
def testEnum(self):
ids = pykd.enumTagged()
self.assertTrue( self._existing_id.lower() in [i.lower() for i in ids] )
self.assertFalse( self._non_existing_id.lower() in [i.lower() for i in ids] )
def testLoadBuffer(self):
buff = pykd.loadTaggedBuffer( self._existing_id )
self.assertEqual( len(buff), 0x410 )
self.assertRaises( pykd.DbgException, pykd.loadTaggedBuffer, self._non_existing_id )