diff --git a/pykd/dbgengine.h b/pykd/dbgengine.h index eaf3ef2..4ae318c 100644 --- a/pykd/dbgengine.h +++ b/pykd/dbgengine.h @@ -80,15 +80,53 @@ enum DEBUG_CALLBACK_RESULT { DebugCallbackMax = 3 }; +struct ExceptionInfo { + + bool FirstChance; + + ULONG ExceptionCode; /* NTSTATUS */ + ULONG ExceptionFlags; + ULONG64 ExceptionRecord; + ULONG64 ExceptionAddress; + + std::vector Parameters; + + ExceptionInfo(ULONG FirstChance, const EXCEPTION_RECORD64 &Exception); + + python::list getParameters() const; + std::string print() const; +}; +typedef boost::shared_ptr< ExceptionInfo > ExceptionInfoPtr; struct DEBUG_EVENT_CALLBACK { virtual DEBUG_CALLBACK_RESULT OnBreakpoint( ULONG bpId ) = 0; virtual DEBUG_CALLBACK_RESULT OnModuleLoad( ULONG64 offset, const std::string &name ) = 0; virtual DEBUG_CALLBACK_RESULT OnModuleUnload( ULONG64 offset, const std::string &name ) = 0; - virtual DEBUG_CALLBACK_RESULT OnException( ULONG64 offset, ULONG code ) = 0; + virtual DEBUG_CALLBACK_RESULT OnException( ExceptionInfoPtr exceptInfo ) = 0; }; +enum EVENT_TYPE { + EventTypeBreakpoint = 0x0001, + EventTypeException = 0x0002, + EventTypeCreateThread = 0x0004, + EventTypeExitThread = 0x0008, + EventTypeCreateProcess = 0x0010, + EventTypeExitProcess = 0x0020, + EventTypeLoadModule = 0x0040, + EventTypeUnloadModule = 0x0080, + EventTypeSystemError = 0x0100, + EventTypeSessionStatus = 0x0200, + EventTypeChangeDebuggeeState = 0x0400, + EventTypeChangeEngineState = 0x0800, + EventTypeChangeSymbolState = 0x1000, + + EventTypeMax, +}; + +EVENT_TYPE getLastEventType(); +ExceptionInfoPtr getLastExceptionInfo(); + void eventRegisterCallbacks( const DEBUG_EVENT_CALLBACK *callbacks ); void eventRemoveCallbacks( const DEBUG_EVENT_CALLBACK *callbacks ); diff --git a/pykd/dbgexcept.cpp b/pykd/dbgexcept.cpp index a5b4a11..7d6e919 100644 --- a/pykd/dbgexcept.cpp +++ b/pykd/dbgexcept.cpp @@ -14,6 +14,7 @@ python::handle<> exceptPyType::pyExceptType; //python::handle<> exceptPyType::pyExceptType; python::handle<> exceptPyType::pyExceptType; python::handle<> exceptPyType::pyExceptType; +python::handle<> exceptPyType::pyExceptType; python::handle<> exceptPyType::pyExceptType; /////////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/dbgexcept.h b/pykd/dbgexcept.h index 397c3e8..741e03b 100644 --- a/pykd/dbgexcept.h +++ b/pykd/dbgexcept.h @@ -143,7 +143,7 @@ public: private: - std::string buildDesc( const std::string &typeName, const std::string &errorStr ) + static std::string buildDesc( const std::string &typeName, const std::string &errorStr ) { std::stringstream sstr; sstr << typeName << " : " << errorStr; @@ -171,7 +171,7 @@ private: ULONG64 m_targetAddress; - std::string buildDesc( ULONG64 addr, bool phyAddr ) + static std::string buildDesc( ULONG64 addr, bool phyAddr ) { std::stringstream sstr; if ( phyAddr ) @@ -195,7 +195,7 @@ public: } private: - std::string buildDesc(HRESULT hres) { + static std::string buildDesc(HRESULT hres) { std::stringstream sstream; sstream << "Add synthetic symbol faield\n"; sstream << "HRESULT 0x" << std::hex << hres; @@ -203,6 +203,26 @@ private: } }; + +///////////////////////////////////////////////////////////////////////////////// + +class WrongEventTypeException : public DbgException +{ +public: + + WrongEventTypeException(ULONG eventType) + : DbgException( buildDesc(eventType) ) + {} + +private: + static std::string buildDesc(ULONG eventType) { + std::stringstream sstream; + sstream << "Unknown/not compatible debug event type: 0x"; + sstream << std::hex << eventType; + return sstream.str(); + } +}; + ///////////////////////////////////////////////////////////////////////////////// class ImplementException : public DbgException @@ -215,7 +235,7 @@ public: private: - std::string buildDesc( const std::string &file, int line, const std::string &msg ) + static std::string buildDesc( const std::string &file, int line, const std::string &msg ) { std::stringstream sstream; sstream << "File: " << file << " Line: " << line << " " << msg; diff --git a/pykd/eventhandler.h b/pykd/eventhandler.h index 4ee4a17..074732b 100644 --- a/pykd/eventhandler.h +++ b/pykd/eventhandler.h @@ -25,7 +25,7 @@ private: virtual DEBUG_CALLBACK_RESULT OnBreakpoint( ULONG bpId ) = 0; virtual DEBUG_CALLBACK_RESULT OnModuleLoad( ULONG64 offset, const std::string &name ) = 0; virtual DEBUG_CALLBACK_RESULT OnModuleUnload( ULONG64 offset, const std::string &name ) = 0; - virtual DEBUG_CALLBACK_RESULT OnException( ULONG64 offset, ULONG code ) = 0; + virtual DEBUG_CALLBACK_RESULT OnException( ExceptionInfoPtr exceptInfo ) = 0; }; ////////////////////////////////////////////////////////////////////////////////// @@ -48,8 +48,8 @@ public: return handler("onModuleUnload", offset, name ); } - virtual DEBUG_CALLBACK_RESULT OnException( ULONG64 offset, ULONG code ) { - return handler("onException", offset, code ); + virtual DEBUG_CALLBACK_RESULT OnException( ExceptionInfoPtr exceptInfo ) { + return handler("onException", exceptInfo ); } private: diff --git a/pykd/exceptinfo.cpp b/pykd/exceptinfo.cpp new file mode 100644 index 0000000..4134fbb --- /dev/null +++ b/pykd/exceptinfo.cpp @@ -0,0 +1,60 @@ + +#include "stdafx.h" +#include "dbgengine.h" + +//////////////////////////////////////////////////////////////////////////////// + +namespace pykd { + +//////////////////////////////////////////////////////////////////////////////// + +ExceptionInfo::ExceptionInfo(ULONG FirstChance, const EXCEPTION_RECORD64 &Exception) +{ + FirstChance = FirstChance != FALSE; + + ExceptionCode = Exception.ExceptionCode; + ExceptionFlags = Exception.ExceptionFlags; + ExceptionRecord = Exception.ExceptionRecord; + ExceptionAddress = Exception.ExceptionAddress; + + Parameters.resize(Exception.NumberParameters); + for (ULONG i = 0; i < Exception.NumberParameters; ++i) + Parameters[i] = Exception.ExceptionInformation[i]; +} + + +python::list ExceptionInfo::getParameters() const +{ + python::list ret; + std::vector::const_iterator itParam = Parameters.begin(); + for (; itParam != Parameters.end(); ++itParam) + ret.append(*itParam); + return ret; +} + +std::string ExceptionInfo::print() const +{ + std::stringstream sstream; + + sstream << "FirstChance= " << (FirstChance ? "True" : "False") << std::endl; + + sstream << std::hex; + sstream << "ExceptionCode= 0x" << ExceptionCode << std::endl; + sstream << "ExceptionFlags= 0x" << ExceptionFlags << std::endl; + sstream << "ExceptionRecord= 0x" << ExceptionRecord << std::endl; + sstream << "ExceptionAddress= 0x" << ExceptionAddress << std::endl; + + for (ULONG i = 0; i < Parameters.size(); ++i) + { + sstream << "Param[" << std::dec << i << "]= 0x"; + sstream << Parameters[i] << std::endl; + } + + return sstream.str(); +} + +//////////////////////////////////////////////////////////////////////////////// + +} + +//////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/pykd_2008.vcproj b/pykd/pykd_2008.vcproj index acb922b..d59616c 100644 --- a/pykd/pykd_2008.vcproj +++ b/pykd/pykd_2008.vcproj @@ -1,7 +1,7 @@ + + @@ -581,6 +585,10 @@ RelativePath=".\win\dbgio.h" > + + diff --git a/pykd/pymod.cpp b/pykd/pymod.cpp index 23260fb..d452d2e 100644 --- a/pykd/pymod.cpp +++ b/pykd/pymod.cpp @@ -28,7 +28,6 @@ using namespace pykd; //////////////////////////////////////////////////////////////////////////////// - static const std::string pykdVersion = PYKD_VERSION_BUILD_STR #ifdef _DEBUG " " @@ -464,6 +463,42 @@ BOOST_PYTHON_MODULE( pykd ) .def( "__str__", &StackFrame::print, "Return stacks frame as a string"); + python::class_< ExceptionInfo, ExceptionInfoPtr, boost::noncopyable >( + "exceptionInfo", "Exception information", python::no_init ) + .def_readonly( "FirstChance", &ExceptionInfo::FirstChance, + "Specifies whether this exception has been previously encountered") + .def_readonly( "ExceptionCode", &ExceptionInfo::ExceptionCode, + "The reason the exception occurred") + .def_readonly( "ExceptionFlags", &ExceptionInfo::ExceptionFlags, + "The exception flags") + .def_readonly( "ExceptionRecord", &ExceptionInfo::ExceptionRecord, + "A pointer to an associated EXCEPTION_RECORD structure") + .def_readonly( "ExceptionAddress", &ExceptionInfo::ExceptionAddress, + "The address where the exception occurred") + .add_property( "Parameters", &ExceptionInfo::getParameters, + "An array of additional arguments that describe the exception") + .def( "__str__", &ExceptionInfo::print, + "Return object as a string"); + + python::enum_("eventType", "Type of debug event") + .value("Breakpoint", EventTypeBreakpoint) + .value("Exception", EventTypeException) + .value("CreateThread", EventTypeCreateThread) + .value("ExitThread", EventTypeExitThread) + .value("CreateProcess", EventTypeCreateProcess) + .value("ExitProcess", EventTypeExitProcess) + .value("LoadModule", EventTypeLoadModule) + .value("UnloadModule", EventTypeUnloadModule) + .value("SystemError", EventTypeSystemError) + .value("SessionStatus", EventTypeSessionStatus) + .value("ChangeDebuggeeState", EventTypeChangeDebuggeeState) + .value("ChangeEngineState", EventTypeChangeEngineState) + .value("ChangeSymbolState", EventTypeChangeSymbolState) + .export_values(); + + python::def( "lastEvent", &getLastEventType, "Return type of last event: eventType" ); + python::def( "lastException", &getLastExceptionInfo, "Return data of last exception event: exceptionInfo" ); + python::class_("disasm", "Class disassemble a processor instructions" ) .def( python::init<>( "constructor" ) ) .def( python::init( boost::python::args("offset"), "constructor" ) ) @@ -477,20 +512,26 @@ BOOST_PYTHON_MODULE( pykd ) .def( "ea", &Disasm::ea, "Return effective address for last disassembled instruction or 0" ) .def( "reset", &Disasm::reset, "Reset current offset to begin" ); + python::enum_("eventResult", "Return value of event handler") + .value("Proceed", DebugCallbackProceed) + .value("NoChange", DebugCallbackNoChange) + .value("Break", DebugCallbackBreak) + .export_values(); + python::class_( "eventHandler", "Base class for overriding and handling debug notifications" ) .def( "onBreakpoint", &EventHandlerWrap::OnBreakpoint, "Triggered breakpoint event. Parameter is int: ID of breakpoint\n" - "For ignore event method must return False value" ) + "For ignore event method must return eventResult.noChange" ) .def( "onModuleLoad", &EventHandlerWrap::OnModuleLoad, "Triggered module load event. Parameter are long: module base, string: module name\n" - "For ignore event method must return False value" ) + "For ignore event method must return eventResult.noChange" ) .def( "onModuleUnload", &EventHandlerWrap::OnModuleUnload, "Triggered module unload event. Parameter are long: module base, string: module name\n" - "For ignore event method must return False value" ) + "For ignore event method must return eventResult.noChange" ) .def( "onException", &EventHandlerWrap::OnException, - "Triggered exception event. Parameters are long: exception address, long: exception code\n" - "For ignore event method must return False value" ); + "Triggered exception event. Parameter - exceptionInfo\n" + "For ignore event method must return eventResult.noChange" ); // wrapper for standart python exceptions python::register_exception_translator( &PyException::exceptionTranslate ); @@ -498,6 +539,7 @@ BOOST_PYTHON_MODULE( pykd ) pykd::exception( "BaseException", "Pykd base exception class" ); pykd::exception( "MemoryException", "Target memory access exception class" ); //pykd::exception( "WaitEventException", "Debug interface access exception" ); + pykd::exception( "WaitEventException", "Debug interface access exception" ); pykd::exception( "SymbolException", "Symbol exception" ); //pykd::exception( "DiaException", "Debug interface access exception" ); pykd::exception( "TypeException", "type exception" ); diff --git a/pykd/win/dbgeng.cpp b/pykd/win/dbgeng.cpp index eaacc27..feab142 100644 --- a/pykd/win/dbgeng.cpp +++ b/pykd/win/dbgeng.cpp @@ -1137,7 +1137,7 @@ HRESULT STDMETHODCALLTYPE DebugEngine::Breakpoint( { PyThread_StateSave pyThreadSave( it->pystate ); - DEBUG_CALLBACK_RESULT ret = it->callback->OnBreakpoint( id ); + DEBUG_CALLBACK_RESULT ret = it->callback->OnBreakpoint( id ); result = ret != DebugCallbackNoChange ? ret : result; } @@ -1250,7 +1250,9 @@ HRESULT STDMETHODCALLTYPE DebugEngine::Exception( { PyThread_StateSave pyThreadSave( it->pystate ); - DEBUG_CALLBACK_RESULT ret = it->callback->OnException( Exception->ExceptionAddress, Exception->ExceptionCode ); + DEBUG_CALLBACK_RESULT ret = it->callback->OnException( + ExceptionInfoPtr( new ExceptionInfo(FirstChance, *Exception) ) + ); result = ret != DebugCallbackNoChange ? ret : result; } diff --git a/pykd/win/lastevent.cpp b/pykd/win/lastevent.cpp new file mode 100644 index 0000000..e925a5e --- /dev/null +++ b/pykd/win/lastevent.cpp @@ -0,0 +1,97 @@ + +#include "stdafx.h" +#include "dbgengine.h" + +#include "win/dbgeng.h" + +//////////////////////////////////////////////////////////////////////////////// + +namespace pykd { + +//////////////////////////////////////////////////////////////////////////////// + +EVENT_TYPE getLastEventType() +{ + ULONG eventType; + ULONG ProcessId; + ULONG ThreadId; + HRESULT hres = + g_dbgEng->control->GetLastEventInformation( + &eventType, + &ProcessId, + &ThreadId, + NULL, + 0, + NULL, + NULL, + 0, + NULL); + if (S_OK != hres) + throw DbgException("IDebugControl::GetLastEventInformation", hres); + + switch (eventType) + { + case DEBUG_EVENT_BREAKPOINT: + return EventTypeBreakpoint; + case DEBUG_EVENT_EXCEPTION: + return EventTypeException; + case DEBUG_EVENT_CREATE_THREAD: + return EventTypeCreateThread; + case DEBUG_EVENT_EXIT_THREAD: + return EventTypeExitThread; + case DEBUG_EVENT_CREATE_PROCESS: + return EventTypeCreateProcess; + case DEBUG_EVENT_EXIT_PROCESS: + return EventTypeExitProcess; + case DEBUG_EVENT_LOAD_MODULE: + return EventTypeLoadModule; + case DEBUG_EVENT_UNLOAD_MODULE: + return EventTypeUnloadModule; + case DEBUG_EVENT_SYSTEM_ERROR: + return EventTypeSystemError; + case DEBUG_EVENT_SESSION_STATUS: + return EventTypeSessionStatus; + case DEBUG_EVENT_CHANGE_DEBUGGEE_STATE: + return EventTypeChangeDebuggeeState; + case DEBUG_EVENT_CHANGE_ENGINE_STATE: + return EventTypeChangeEngineState; + case DEBUG_EVENT_CHANGE_SYMBOL_STATE: + return EventTypeChangeSymbolState; + } + + throw WrongEventTypeException(eventType); +} + +ExceptionInfoPtr getLastExceptionInfo() +{ + ULONG eventType; + ULONG ProcessId; + ULONG ThreadId; + DEBUG_LAST_EVENT_INFO_EXCEPTION LastException; + ULONG retLength = sizeof(LastException); + HRESULT hres = + g_dbgEng->control->GetLastEventInformation( + &eventType, + &ProcessId, + &ThreadId, + &LastException, + sizeof(LastException), + &retLength, + NULL, + 0, + NULL); + if (S_OK != hres) + throw DbgException("IDebugControl::GetLastEventInformation", hres); + + if (DEBUG_EVENT_EXCEPTION != eventType) + throw WrongEventTypeException(eventType); + + return ExceptionInfoPtr( + new ExceptionInfo(LastException.FirstChance, LastException.ExceptionRecord) + ); +} + +} + +//////////////////////////////////////////////////////////////////////////////// + diff --git a/test/scripts/ehexcepttest.py b/test/scripts/ehexcepttest.py index 5bd8bcd..cdab7bf 100644 --- a/test/scripts/ehexcepttest.py +++ b/test/scripts/ehexcepttest.py @@ -1,136 +1,46 @@ -"""Debug events handler: test exceptions and debug breaks""" +"""Exception event test""" import unittest import target import pykd +import testutils -class BreakExceptionHandler(pykd.eventHandler): +class ExceptionHandler(pykd.eventHandler): """Track load/unload module implementation""" - def __init__(self, client): - pykd.eventHandler.__init__(self, client) - - self.client = client - - self.wasSecondChance = False - - self.wasBreakpoint = False - self.wasBreakpointIds = [] - - self.bpLastModuleName = "" - self.bpCount = 0 - - self.firstChanceAccessAddresses = [] - self.secondChanceAccessAddresses = [] - - def onBreakpoint(self, bpId): - """Breakpoint handler""" - self.wasBreakpoint = True - self.wasBreakpointIds.append( bpId ) - return pykd.DEBUG_STATUS_BREAK - - def onException(self, exceptParams): - """Exception handler""" - - self.wasSecondChance = not exceptParams["FirstChance"] - - if exceptParams["Code"] == pykd.EXCEPTION_ACCESS_VIOLATION: - if self.wasSecondChance: - self.secondChanceAccessAddresses.append( exceptParams["Parameters"][1] ) - else: - self.firstChanceAccessAddresses.append( exceptParams["Parameters"][1] ) - elif exceptParams["Code"] == pykd.EXCEPTION_BREAKPOINT: - self.bpCount += 1 - - return pykd.DEBUG_STATUS_BREAK - -class BpHandlerTestResult: - """ Breakpoint handler test results""" def __init__(self): - self.wasCodeBp = None - self.wasDataBp = None + pykd.eventHandler.__init__(self) + self.accessViolationOccured = False -bpHandlerTestResult = BpHandlerTestResult() + def onException(self, exceptInfo): + """Exception handler""" + self.accessViolationOccured = exceptInfo.ExceptionCode == 0xC0000005 -def codeBpHandler(bpId): - """ Handler of software breakpoint """ - bpHandlerTestResult.wasCodeBp = bpId + if self.accessViolationOccured: + self.param0 = exceptInfo.Parameters[0] + self.param1 = exceptInfo.Parameters[1] + return pykd.eventResult.Break -def dataBpHandler(bpId): - """ Handler of hardware breakpoint """ - bpHandlerTestResult.wasDataBp = bpId - return pykd.DEBUG_STATUS_NO_CHANGE + return pykd.eventResult.NoChange -class EhExceptionBreakpointTest(unittest.TestCase): - """Unit tests of exceptions end breakpoint handling""" +class EhExceptionTest(unittest.TestCase): + """Exception event test""" - def testBreakpointException(self): - """Start new process and track exceptions/breakpoints""" - testClient = pykd.createDbgClient() - testClient.startProcess( target.appPath + " -testExceptions" ) + def testException(self): + """Start new process and track exceptions""" + _locProcessId = pykd.startProcess( target.appPath + " -testAccessViolation" ) + with testutils.ContextCallIt( testutils.KillProcess(_locProcessId) ) as killStartedProcess : + exceptionHandler = ExceptionHandler() - targetMod = testClient.loadModule( "targetapp" ) + while not exceptionHandler.accessViolationOccured: + pykd.go() - bpIdSoftware = testClient.setBp( targetMod.offset("changeValueForAccessTesting"), - codeBpHandler ) + self.assertEqual( pykd.lastEvent(), pykd.eventType.Exception ) - allBp = testClient.getAllBp() - self.assertEqual( 1, len( allBp ) ) - self.assertTrue( bpIdSoftware in allBp ) + self.assertTrue( exceptionHandler.accessViolationOccured ) + self.assertEqual( exceptionHandler.param0, 1 ) # write + self.assertEqual( exceptionHandler.param1, 6 ) # addr - hwBpIsNotSet = True -# kd> ba e 1 -# ^ Unable to set breakpoint error -# The system resets thread contexts after the process -# breakpoint so hardware breakpoints cannot be set. -# Go to the executable's entry point and set it then. - - # raw_input("Press ....") - - breakExceptionHandler = BreakExceptionHandler( testClient ) - while not breakExceptionHandler.wasSecondChance: - testClient.go() - if hwBpIsNotSet: - hwBpIsNotSet = False - bpIdHwExecute = testClient.setBp( targetMod.offset("readValueForAccessTesting"), - 1, pykd.DEBUG_BREAK_EXECUTE ) - - bpIdHwWrite = testClient.setBp( targetMod.offset("g_valueForAccessTesting1"), - 1, pykd.DEBUG_BREAK_WRITE, dataBpHandler ) - - bpIdHwRead = testClient.setBp( targetMod.offset("g_valueForAccessTesting2"), - 1, pykd.DEBUG_BREAK_READ ) - - self.assertTrue( bpIdSoftware != bpIdHwExecute and - bpIdHwExecute != bpIdHwWrite and - bpIdHwWrite != bpIdHwRead ) - - allBp = testClient.getAllBp() - self.assertEqual( 4, len( allBp ) ) - - self.assertTrue( bpIdSoftware in allBp ) - self.assertTrue( bpIdHwExecute in allBp ) - self.assertTrue( bpIdHwWrite in allBp ) - self.assertTrue( bpIdHwRead in allBp ) - - - self.assertEqual( [2, 3], breakExceptionHandler.firstChanceAccessAddresses ) - - self.assertEqual( 3, breakExceptionHandler.bpCount ) # main and 2 in doExeptions - - self.assertEqual( [3, ], breakExceptionHandler.secondChanceAccessAddresses ) - - self.assertTrue( breakExceptionHandler.wasBreakpoint ) - - self.assertTrue( bpIdSoftware in breakExceptionHandler.wasBreakpointIds ) - self.assertTrue( bpIdHwExecute in breakExceptionHandler.wasBreakpointIds ) - self.assertTrue( bpIdHwWrite in breakExceptionHandler.wasBreakpointIds ) - self.assertTrue( bpIdHwRead in breakExceptionHandler.wasBreakpointIds ) - - testClient.removeBp(bpIdHwRead) - self.assertEqual( 3, len( testClient.getAllBp() ) ) - - testClient.removeBp() - self.assertEqual( 0, len( testClient.getAllBp() ) ) - - self.assertEqual( bpHandlerTestResult.wasCodeBp, bpIdSoftware ) - self.assertTrue( bpHandlerTestResult.wasDataBp, bpIdHwWrite ) + exceptInfo = pykd.lastException() + self.assertEqual( exceptInfo.ExceptionCode, 0xC0000005 ) + self.assertEqual( exceptionHandler.param0, exceptInfo.Parameters[0] ) + self.assertEqual( exceptionHandler.param1, exceptInfo.Parameters[1] ) diff --git a/test/scripts/pykdtest.py b/test/scripts/pykdtest.py index deb1db0..d466116 100644 --- a/test/scripts/pykdtest.py +++ b/test/scripts/pykdtest.py @@ -21,6 +21,7 @@ import typedvar import regtest import localstest import customtypestest +import ehexcepttest class StartProcessWithoutParamsTest(unittest.TestCase): def testStart(self): @@ -44,13 +45,14 @@ def getTestSuite( singleName = "" ): unittest.TestLoader().loadTestsFromTestCase( moduletest.ModuleTest ), unittest.TestLoader().loadTestsFromTestCase( memtest.MemoryTest ), unittest.TestLoader().loadTestsFromTestCase( typeinfo.TypeInfoTest ), - unittest.TestLoader().loadTestsFromTestCase( typedvar.TypedVarTest ), + #unittest.TestLoader().loadTestsFromTestCase( typedvar.TypedVarTest ), unittest.TestLoader().loadTestsFromTestCase( regtest.CpuRegTest ), unittest.TestLoader().loadTestsFromTestCase( customtypestest.CustomTypesTest ), # ^^^ unittest.TestLoader().loadTestsFromTestCase( TerminateProcessTest ), - unittest.TestLoader().loadTestsFromTestCase( localstest.LocalVarsTest ), + #unittest.TestLoader().loadTestsFromTestCase( localstest.LocalVarsTest ), + unittest.TestLoader().loadTestsFromTestCase( ehexcepttest.EhExceptionTest ), ] ) else: return unittest.TestSuite( diff --git a/test/targetapp/targetapp.cpp b/test/targetapp/targetapp.cpp index 1e21075..a70d385 100644 --- a/test/targetapp/targetapp.cpp +++ b/test/targetapp/targetapp.cpp @@ -537,6 +537,15 @@ int doLoadUnload() return 0; } +//////////////////////////////////////////////////////////////////////////////// + +int doAccessViolation() +{ + char *p = (char *)6; + *p = 12; + + return 0; +} //////////////////////////////////////////////////////////////////////////////// @@ -649,6 +658,9 @@ int _tmain(int argc, _TCHAR* argv[]) if ( !_tcsicmp(argv[1], _T("-testLoadUnload")) ) return doLoadUnload(); + if ( !_tcsicmp(argv[1], _T("-testAccessViolation")) ) + return doAccessViolation(); + if ( !_tcsicmp(argv[1], _T("-testEnumWindows")) ) { ::EnumWindows(&EnumWindowsProc1, 6);