From 60c71e8ff1b89a2e3f407f3e8604b177ff183fab Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Fri, 17 May 2013 11:18:11 +0000 Subject: [PATCH 01/30] [0.2.x] added : searchMemory routine ( Search in virtual memory ) git-svn-id: https://pykd.svn.codeplex.com/svn@83704 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgmem.h | 2 +- pykd/pykdver.h | 2 +- pykd/python/pymod.cpp | 3 ++- pykd/win/memory.cpp | 17 +++++++++++++ snippets/findtag.py | 56 +++++++++++++++++++++++++++++++++++++++++++ snippets/nbl.py | 7 +++--- 6 files changed, 80 insertions(+), 7 deletions(-) create mode 100644 snippets/findtag.py diff --git a/pykd/dbgmem.h b/pykd/dbgmem.h index 0c5d50a..0b346f8 100644 --- a/pykd/dbgmem.h +++ b/pykd/dbgmem.h @@ -12,7 +12,7 @@ bool readMemoryUnsafeNoSafe( ULONG64 offset, PVOID buffer, ULONG length, bool ph bool isVaValid( ULONG64 addr ); bool compareMemory( ULONG64 addr1, ULONG64 addr2, ULONG length, bool phyAddr = FALSE ); ULONG getVaProtect( ULONG64 offset ); - +ULONG64 searchMemory( ULONG64 offset, ULONG length, const std::string& pattern ); void findMemoryRegion( ULONG64 beginOffset, ULONG64 *startOffset, ULONG64* length ); python::tuple findMemoryRegionPy( ULONG64 beginOffset ); diff --git a/pykd/pykdver.h b/pykd/pykdver.h index f09e6a5..3f3f688 100644 --- a/pykd/pykdver.h +++ b/pykd/pykdver.h @@ -2,7 +2,7 @@ #define PYKD_VERSION_MAJOR 0 #define PYKD_VERSION_MINOR 2 #define PYKD_VERSION_SUBVERSION 0 -#define PYKD_VERSION_BUILDNO 20 +#define PYKD_VERSION_BUILDNO 21 #define __VER_STR2__(x) #x diff --git a/pykd/python/pymod.cpp b/pykd/python/pymod.cpp index 6011fe4..55ab7c3 100644 --- a/pykd/python/pymod.cpp +++ b/pykd/python/pymod.cpp @@ -155,7 +155,8 @@ BOOST_PYTHON_MODULE( pykd ) "Check if the virtual address is valid" ); python::def( "compareMemory", &compareMemory, compareMemory_( python::args( "offset1", "offset2", "length", "phyAddr" ), "Compare two memory buffers by virtual or physical addresses" ) ); - + python::def( "searchMemory", &searchMemory, + "Search in virtual memory" ); python::def( "findMemoryRegion", &findMemoryRegionPy, "Return address of begining valid memory region nearest to offset" ); python::def( "getVaProtect", &getVaProtect, diff --git a/pykd/win/memory.cpp b/pykd/win/memory.cpp index 0e8a17d..78e3499 100644 --- a/pykd/win/memory.cpp +++ b/pykd/win/memory.cpp @@ -228,6 +228,23 @@ void findMemoryRegion( ULONG64 beginOffset, ULONG64 *startOffset, ULONG64* lengt /////////////////////////////////////////////////////////////////////////////////// +ULONG64 searchMemory( ULONG64 offset, ULONG length, const std::string& pattern ) +{ + PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); + + offset = addr64NoSafe(offset); + + ULONG64 foundOffset; + HRESULT hres = g_dbgEng->dataspace->SearchVirtual( offset, length, (PVOID)pattern.c_str(), (ULONG)pattern.size(), 1, &foundOffset ); + + if ( FAILED( hres ) ) + return 0LL; + + return foundOffset; +} + +/////////////////////////////////////////////////////////////////////////////////// + ULONG getVaProtect( ULONG64 offset ) { PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); diff --git a/snippets/findtag.py b/snippets/findtag.py new file mode 100644 index 0000000..a713d4c --- /dev/null +++ b/snippets/findtag.py @@ -0,0 +1,56 @@ +from pykd import * +from sys import argv + +nt = module("nt") +LDR_DATA_TABLE_ENTRY = nt.type("_LDR_DATA_TABLE_ENTRY") + + +def getModuleList(): + ldrLst = typedVarList( nt.PsLoadedModuleList, LDR_DATA_TABLE_ENTRY, "InLoadOrderLinks.Flink") + return [ module(m.DllBase) for m in ldrLst ] + +def findTagInModule(mod, tag): + + matchLst = [] + begin = mod.begin() + end = mod.end() + offset = begin + size = mod.size() + while True: + match = searchMemory( offset, size, tag ) + if not match: + break; + matchLst.append(match) + offset = match + 1 + size = end - offset + return matchLst + + +def main(): + + if len(argv) < 2: + print "You should note tag's value" + return + + if len(argv[1])!=4: + print "Tag must have 4 symbols length" + return + + tag = argv[1] + + modLst = getModuleList() + for m in modLst: + matchLst = findTagInModule( m, tag ) + if len(matchLst) == 0: + #print m.name(), "tag not found" + pass + else: + print m.name(), "found", len(matchLst), "entries" + for offset in matchLst: + print "\t", hex(offset) + + +if __name__=="__main__": + main() + + diff --git a/snippets/nbl.py b/snippets/nbl.py index 15b0a60..6882bc5 100644 --- a/snippets/nbl.py +++ b/snippets/nbl.py @@ -349,7 +349,7 @@ class EthernetType: return self.typeVal == IPv6 def __str__( self ): - return { IPv4 : "IPv4", ARP : "ARP", IPv6 : "IPv6" }.get( self.typeVal, self.typeVal ) + return { IPv4 : "IPv4", ARP : "ARP", IPv6 : "IPv6" }.get( self.typeVal, str(self.typeVal) ) def getNextLayerPacket( self, dataPos ): return { @@ -388,7 +388,7 @@ class EthernetPacket: def __str__( self): - + s = "Ethernet header: " if self.parsed: @@ -409,8 +409,7 @@ class NetPacket: def __init__( self, rawData, startProtocol="eth", beginOffset=0 ): self.rawData = rawData - dataPos = iter( self.rawData[ beginOffset : ] ) - + dataPos = iter( self.rawData[ beginOffset : ] ) self.mediaParsed = { "eth" : lambda : EthernetPacket( dataPos ), From ea8a8cda98457639085ad207f3ef7e3ec2671b8f Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Sun, 11 Aug 2013 09:35:23 +0000 Subject: [PATCH 02/30] [0.2.x] fixed : issue #12017 ( Exception Always First Chance ) git-svn-id: https://pykd.svn.codeplex.com/svn@84627 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/exceptinfo.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pykd/exceptinfo.cpp b/pykd/exceptinfo.cpp index 4134fbb..d8eac99 100644 --- a/pykd/exceptinfo.cpp +++ b/pykd/exceptinfo.cpp @@ -8,9 +8,9 @@ namespace pykd { //////////////////////////////////////////////////////////////////////////////// -ExceptionInfo::ExceptionInfo(ULONG FirstChance, const EXCEPTION_RECORD64 &Exception) +ExceptionInfo::ExceptionInfo(ULONG FirstChance_, const EXCEPTION_RECORD64 &Exception) { - FirstChance = FirstChance != FALSE; + FirstChance = FirstChance_ != 0; ExceptionCode = Exception.ExceptionCode; ExceptionFlags = Exception.ExceptionFlags; From 1fb1f483dd04c68e3ab62a6c603c48d77e34b6a8 Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Sun, 11 Aug 2013 10:05:42 +0000 Subject: [PATCH 03/30] [0.2.x] fixed : issue #12017 ( Exception Always First Chance ) git-svn-id: https://pykd.svn.codeplex.com/svn@84628 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/exceptinfo.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/pykd/exceptinfo.cpp b/pykd/exceptinfo.cpp index d8eac99..2c63494 100644 --- a/pykd/exceptinfo.cpp +++ b/pykd/exceptinfo.cpp @@ -38,16 +38,15 @@ std::string ExceptionInfo::print() const 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; + sstream << "ExceptionCode= 0x" << std::hex << ExceptionCode << std::endl; + sstream << "ExceptionFlags= 0x" << std::hex << ExceptionFlags << std::endl; + sstream << "ExceptionRecord= 0x" << std::hex << ExceptionRecord << std::endl; + sstream << "ExceptionAddress= 0x" << std::hex << ExceptionAddress << std::endl; for (ULONG i = 0; i < Parameters.size(); ++i) { sstream << "Param[" << std::dec << i << "]= 0x"; - sstream << Parameters[i] << std::endl; + sstream << std::hex << Parameters[i] << std::endl; } return sstream.str(); From 95d13652333e5257b0c603186d66d190f403559a Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Tue, 13 Aug 2013 15:45:14 +0000 Subject: [PATCH 04/30] [0.2.x] fixed : set version to 0.2.0.22 git-svn-id: https://pykd.svn.codeplex.com/svn@84686 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dia/diasymbol.cpp | 4 ++-- pykd/pykdver.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pykd/dia/diasymbol.cpp b/pykd/dia/diasymbol.cpp index c72c904..03d3690 100644 --- a/pykd/dia/diasymbol.cpp +++ b/pykd/dia/diasymbol.cpp @@ -198,8 +198,8 @@ SymbolPtr DiaSymbol::getChildByName(const std::string &name) SymbolPtr DiaSymbol::getChildBySelected(const SelectedChilds &selected, const std::string &name) { - if (selected.second > 1) - throw SymbolException(name + "is ambiguous"); + if (selected.second == 0) + throw SymbolException(name + " is not found"); DiaSymbolPtr child; HRESULT hres = selected.first->Item(0, &child); diff --git a/pykd/pykdver.h b/pykd/pykdver.h index 3f3f688..44b84b5 100644 --- a/pykd/pykdver.h +++ b/pykd/pykdver.h @@ -2,7 +2,7 @@ #define PYKD_VERSION_MAJOR 0 #define PYKD_VERSION_MINOR 2 #define PYKD_VERSION_SUBVERSION 0 -#define PYKD_VERSION_BUILDNO 21 +#define PYKD_VERSION_BUILDNO 22 #define __VER_STR2__(x) #x From 3e271a7c1a91b0b6bc1b6030b18f9b15c83b174b Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Thu, 22 Aug 2013 12:40:25 +0000 Subject: [PATCH 05/30] [0.2.x] fixed : issue #12068 ( windbg crash at loadWStr(0) ) git-svn-id: https://pykd.svn.codeplex.com/svn@84891 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/win/memory.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pykd/win/memory.cpp b/pykd/win/memory.cpp index 78e3499..2d8f89b 100644 --- a/pykd/win/memory.cpp +++ b/pykd/win/memory.cpp @@ -185,6 +185,9 @@ std::wstring loadWStr( ULONG64 offset ) 0, &strLength ); + if ( FAILED( hres ) ) + throw MemoryException( offset ); + std::vector buffer(strLength); hres = @@ -195,8 +198,7 @@ std::wstring loadWStr( ULONG64 offset ) strLength, NULL ); - if ( FAILED( hres ) ) - throw MemoryException( offset ); + return std::wstring( &buffer[0] ); } From 772dd6cac751cf124404af1356fad5ff5e4b0c4b Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Fri, 23 Aug 2013 13:36:16 +0000 Subject: [PATCH 06/30] [0.2.x] added : snippet for printing VEH git-svn-id: https://pykd.svn.codeplex.com/svn@84933 9b283d60-5439-405e-af05-b73fd8c4d996 --- snippets/veh.py | 245 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 245 insertions(+) create mode 100644 snippets/veh.py diff --git a/snippets/veh.py b/snippets/veh.py new file mode 100644 index 0000000..58adb6a --- /dev/null +++ b/snippets/veh.py @@ -0,0 +1,245 @@ +import sys +import re + +from pykd import * + +tbuilder = typeBuilder() + +IMAGE_RUNTIME_FUNCTION_ENTRY = tbuilder.createStruct( "IMAGE_RUNTIME_FUNCTION_ENTRY", 1 ) +IMAGE_RUNTIME_FUNCTION_ENTRY.append( "BeginAddress", tbuilder.UInt4B ) +IMAGE_RUNTIME_FUNCTION_ENTRY.append( "EndAddress", tbuilder.UInt4B ) +IMAGE_RUNTIME_FUNCTION_ENTRY.append( "UnwindData", tbuilder.UInt4B ) + +PIMAGE_RUNTIME_FUNCTION_ENTRY = IMAGE_RUNTIME_FUNCTION_ENTRY.ptrTo() + +IMAGE_DOS_HEADER = tbuilder.createStruct( "IMAGE_DOS_HEADER", 1 ) +IMAGE_DOS_HEADER.append("e_magic", tbuilder.UInt2B ) +IMAGE_DOS_HEADER.append("e_cblp", tbuilder.UInt2B ) +IMAGE_DOS_HEADER.append("e_cp", tbuilder.UInt2B ) +IMAGE_DOS_HEADER.append("e_crlc", tbuilder.UInt2B ) +IMAGE_DOS_HEADER.append("e_cparhdr", tbuilder.UInt2B ) +IMAGE_DOS_HEADER.append("e_minalloc", tbuilder.UInt2B ) +IMAGE_DOS_HEADER.append("e_maxalloc", tbuilder.UInt2B ) +IMAGE_DOS_HEADER.append("e_ss", tbuilder.UInt2B ) +IMAGE_DOS_HEADER.append("e_sp", tbuilder.UInt2B ) +IMAGE_DOS_HEADER.append("e_csum", tbuilder.UInt2B ) +IMAGE_DOS_HEADER.append("e_ip", tbuilder.UInt2B ) +IMAGE_DOS_HEADER.append("e_cs", tbuilder.UInt2B ) +IMAGE_DOS_HEADER.append("e_lfarlc", tbuilder.UInt2B ) +IMAGE_DOS_HEADER.append("e_ovno", tbuilder.UInt2B ) +IMAGE_DOS_HEADER.append("e_res", tbuilder.UInt2B.arrayOf(4) ) +IMAGE_DOS_HEADER.append("e_oemid", tbuilder.UInt2B ) +IMAGE_DOS_HEADER.append("e_oeminfo", tbuilder.UInt2B ) +IMAGE_DOS_HEADER.append("e_res2", tbuilder.UInt2B.arrayOf(10) ) +IMAGE_DOS_HEADER.append("e_lfanew", tbuilder.UInt4B ) + +IMAGE_DATA_DIRECTORY = tbuilder.createStruct( "IMAGE_DATA_DIRECTORY", 1 ) +IMAGE_DATA_DIRECTORY.append("VirtualAddress", tbuilder.UInt4B) +IMAGE_DATA_DIRECTORY.append("Size", tbuilder.UInt4B) + +IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16 + +IMAGE_DIRECTORY_ENTRY_EXCEPTION = 3 + +IMAGE_OPTIONAL_HEADER64 = tbuilder.createStruct( "IMAGE_OPTIONAL_HEADER64", 1 ) +IMAGE_OPTIONAL_HEADER64.append( "Magic", tbuilder.UInt2B) +IMAGE_OPTIONAL_HEADER64.append( "MajorLinkerVersion", tbuilder.UInt1B) +IMAGE_OPTIONAL_HEADER64.append( "MinorLinkerVersion", tbuilder.UInt1B) +IMAGE_OPTIONAL_HEADER64.append( "SizeOfCode", tbuilder.UInt4B) +IMAGE_OPTIONAL_HEADER64.append( "SizeOfInitializedData", tbuilder.UInt4B) +IMAGE_OPTIONAL_HEADER64.append( "SizeOfUninitializedData", tbuilder.UInt4B) +IMAGE_OPTIONAL_HEADER64.append( "AddressOfEntryPoint", tbuilder.UInt4B) +IMAGE_OPTIONAL_HEADER64.append( "BaseOfCode", tbuilder.UInt4B) +IMAGE_OPTIONAL_HEADER64.append( "ImageBase", tbuilder.UInt8B) +IMAGE_OPTIONAL_HEADER64.append( "SectionAlignment", tbuilder.UInt4B) +IMAGE_OPTIONAL_HEADER64.append( "FileAlignment", tbuilder.UInt4B) +IMAGE_OPTIONAL_HEADER64.append( "MajorOperatingSystemVersion", tbuilder.UInt2B) +IMAGE_OPTIONAL_HEADER64.append( "MinorOperatingSystemVersion", tbuilder.UInt2B) +IMAGE_OPTIONAL_HEADER64.append( "MajorImageVersion", tbuilder.UInt2B) +IMAGE_OPTIONAL_HEADER64.append( "MinorImageVersion", tbuilder.UInt2B) +IMAGE_OPTIONAL_HEADER64.append( "MajorSubsystemVersion", tbuilder.UInt2B) +IMAGE_OPTIONAL_HEADER64.append( "MinorSubsystemVersion", tbuilder.UInt2B) +IMAGE_OPTIONAL_HEADER64.append( "Win32VersionValue", tbuilder.UInt4B) +IMAGE_OPTIONAL_HEADER64.append( "SizeOfImage", tbuilder.UInt4B) +IMAGE_OPTIONAL_HEADER64.append( "SizeOfHeaders", tbuilder.UInt4B) +IMAGE_OPTIONAL_HEADER64.append( "CheckSum", tbuilder.UInt4B) +IMAGE_OPTIONAL_HEADER64.append( "Subsystem", tbuilder.UInt2B) +IMAGE_OPTIONAL_HEADER64.append( "DllCharacteristics", tbuilder.UInt2B) +IMAGE_OPTIONAL_HEADER64.append( "SizeOfStackReserve", tbuilder.UInt8B) +IMAGE_OPTIONAL_HEADER64.append( "SizeOfStackCommit", tbuilder.UInt8B) +IMAGE_OPTIONAL_HEADER64.append( "SizeOfHeapReserve", tbuilder.UInt8B) +IMAGE_OPTIONAL_HEADER64.append( "SizeOfHeapCommit", tbuilder.UInt8B) +IMAGE_OPTIONAL_HEADER64.append( "LoaderFlags", tbuilder.UInt4B) +IMAGE_OPTIONAL_HEADER64.append( "NumberOfRvaAndSizes", tbuilder.UInt4B) +IMAGE_OPTIONAL_HEADER64.append( "DataDirectory", IMAGE_DATA_DIRECTORY.arrayOf(IMAGE_NUMBEROF_DIRECTORY_ENTRIES) ) + +IMAGE_FILE_HEADER = tbuilder.createStruct( "IMAGE_FILE_HEADER", 1 ) +IMAGE_FILE_HEADER.append( "Machine", tbuilder.UInt2B) +IMAGE_FILE_HEADER.append( "NumberOfSections", tbuilder.UInt2B) +IMAGE_FILE_HEADER.append( "TimeDateStamp", tbuilder.UInt4B) +IMAGE_FILE_HEADER.append( "PointerToSymbolTable", tbuilder.UInt4B) +IMAGE_FILE_HEADER.append( "NumberOfSymbols", tbuilder.UInt4B) +IMAGE_FILE_HEADER.append( "SizeOfOptionalHeader", tbuilder.UInt2B) +IMAGE_FILE_HEADER.append( "Characteristics", tbuilder.UInt2B) + +IMAGE_NT_HEADERS64 = tbuilder.createStruct( "IMAGE_NT_HEADERS64", 1 ) +IMAGE_NT_HEADERS64.append( "Signature", tbuilder.UInt4B) +IMAGE_NT_HEADERS64.append( "FileHeader", IMAGE_FILE_HEADER ) +IMAGE_NT_HEADERS64.append( "OptionalHeader", IMAGE_OPTIONAL_HEADER64 ) + +#def findRuntimeFunctionEntry(addr): +# pass + +def findRuntimeFunctionTable( mod ): + + dosHeader = typedVar( IMAGE_DOS_HEADER, mod ) + ntHeader = typedVar( IMAGE_NT_HEADERS64, mod + dosHeader.e_lfanew ) + runtimeTablePtr = mod + ntHeader.OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXCEPTION ].VirtualAddress + functionCount = ntHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size / IMAGE_RUNTIME_FUNCTION_ENTRY.size() + + runtimeTable = typedVarArray( runtimeTablePtr, IMAGE_RUNTIME_FUNCTION_ENTRY, functionCount ) + + return runtimeTable + +def getInstruction( funcaddr, prologOffset ): + dasm = disasm( funcaddr ) + while dasm.current() < funcaddr + prologOffset: + instr = dasm.instruction() + offset = dasm.current() + dasm.disasm() + + match = re.match( r"^[0-9a-f`]+\s+[0-9a-f]+\s+(\w+\s+(?:qword ptr |dword ptr )?[^\s]+)(?:\s+[^\s]+)?$", instr ) + if match: + return ( offset, match.group(1) ) + + return ( offset, instr ) + +def uwopSaveNonvol( arg ): + code, data = arg + data.next() + return "4 - UWOP_SAVE_NONVOL" + +def uwopAllocLarge( arg ): + code, data = arg + operationInfo = ( code >> 12 ) & 0xF + if operationInfo == 0: + data.next() + else: + data.next() + data.next() + return "1 - UWOP_ALLOC_LARGE" + +def printUnwindCodes( funcaddr, data, prefixstr = "", postfixstr = "" ): + + try: + + while True: + + unwindCode = data.next() + + prologOffset = ( unwindCode ) & 0xFF + unwindOperation = ( unwindCode >> 8 ) & 0xF + operationInfo = ( unwindCode >> 12 ) & 0xF + + unwindCodeStr = { + 0 : lambda x : "0 - UWOP_PUSH_NONVOL", + 1 : lambda x : uwopAllocLarge(x), + 2 : lambda x : "2 - UWOP_ALLOC_SMALL", + 3 : lambda x : "3 - UWOP_SET_FPREG", + 4 : lambda x : uwopSaveNonvol(x), + 10 : lambda x : "10 - UWOP_PUSH_MACHFRAME", + }.get( unwindOperation, "%d - unknown unwind operation" % unwindOperation )( (unwindCode, data ) ) + + instrOffset, instrMnem = getInstruction( funcaddr, prologOffset ) + + dprint( prefixstr ) + dprint(hex(instrOffset) ) + dprint("\t") + dprint( unwindCodeStr ) + dprint("\t") + dprint( instrMnem ) + dprint( postfixstr ) + dprintln("") + + except StopIteration: + pass + +def getUnwindFlags( flags ): + + return { + 0 : "0", + 1 : "1 - EHANDLER", + 2 : "2 - UHANDLER", + 4 : "4 - CHAININFO" + }.get(flags, "%x - Unknown flag" % flags) + +def printUnwindInfo( modaddr, funcaddr, unwindInfo ): + dprintln( "Unwind Info:" ) + + version = ptrByte( unwindInfo ) & 7 + flags = ( ptrByte( unwindInfo ) >> 3 ) & 0x1F + sizeOfProlog = ptrByte( unwindInfo + 1 ) + countOfCodes = ptrByte( unwindInfo + 2 ) + frameRegsiter = ptrByte( unwindInfo + 3 ) & 0xF + frameOffset = ( ptrByte( unwindInfo + 3 ) >> 4 ) & 0xF + unwindCodes = loadWords( unwindInfo + 4, countOfCodes ) + + dprintln( "\tversion: %d" % version ) + dprintln( "\tflags: " + getUnwindFlags( flags ) ) + dprintln( "\tsize of prolog %d" % sizeOfProlog ) + dprintln( "\tcount of unwind code slots %d" % countOfCodes ) + + if frameRegsiter > 0: + dprintln( "\tframe regsiter: %s" % reg(frameRegsiter).name() ) + dprintln( "\tframe offset: %d" % ( 16 * frameOffset ) ) + + dprintln( "\n\tUnwind codes:" ) + + printUnwindCodes( funcaddr, iter(unwindCodes), "\t\t" ) + + if flags == 1: + dprintln( "\n\tException handler:" ) + addr = modaddr + ptrDWord( unwindInfo + 3 + 2*countOfCodes) + dprintln( "\t\t" + findSymbol(addr) ) + + +def printVEHInfo(addr): + + dprintln( "\nVEH Info\n" ) + dprintln( "Function address: %x" % addr ) + dprintln( "Function symbolic name: " + findSymbol(addr) ) + + funcModule = module(addr) + dprintln( "Module: %s %x-%x" % ( funcModule.name(), funcModule.begin(), funcModule.end() ) ) + + runtimeFunctionTable = findRuntimeFunctionTable(funcModule) + dprintln( "Found runtime function table at %x with %d elements" % ( runtimeFunctionTable[0].getAddress(), len(runtimeFunctionTable) ) ) + + runtimeFunction = filter( lambda x: funcModule + x.BeginAddress == addr, runtimeFunctionTable )[0] + dprintln( "runtime function info for function:" ) + dprintln( "\tBegin Address: %x ( RVA = %x )" % ( funcModule + runtimeFunction.BeginAddress, runtimeFunction.BeginAddress ) ) + dprintln( "\tEnd Address: %x ( RVA = %x )" % ( funcModule + runtimeFunction.EndAddress, runtimeFunction.EndAddress ) ) + dprintln( "\tUnwind Info: %x ( RVA = %x )" % ( funcModule + runtimeFunction.UnwindData, runtimeFunction.UnwindData ) ) + + printUnwindInfo( funcModule, addr, funcModule + runtimeFunction.UnwindData ) + +def printUsage(): + pass + +def main(): + if len(sys.argv) <=1 : + printUsage() + return + + if not is64bitSystem(): + dprintln("for 64-bit system only") + return + + funcAddr = expr( sys.argv[1] ) + printVEHInfo( funcAddr ) + +if __name__ == "__main__": + main() + + + \ No newline at end of file From 116e45c98990a6e42007581d942f86c7ee23ee77 Mon Sep 17 00:00:00 2001 From: "SND\\EreTIk_cp" Date: Mon, 2 Sep 2013 15:11:32 +0000 Subject: [PATCH 07/30] [0.2.x] + attachKernel, isLocalKernelDebuggerEnabled git-svn-id: https://pykd.svn.codeplex.com/svn@85044 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgengine.h | 2 ++ pykd/python/pymod.cpp | 6 ++++++ pykd/win/dbgps.cpp | 30 +++++++++++++++++++++++++++++- 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/pykd/dbgengine.h b/pykd/dbgengine.h index 79baf04..5008493 100644 --- a/pykd/dbgengine.h +++ b/pykd/dbgengine.h @@ -8,6 +8,8 @@ namespace pykd { // manage debug target ULONG startProcess( const std::wstring &processName ); ULONG attachProcess( ULONG pid ); +void attachKernel( const std::string &connectOptions = "" ); +bool isLocalKernelDebuggerEnabled(); void detachProcess( ULONG processId = -1); void terminateProcess( ULONG processId = -1); diff --git a/pykd/python/pymod.cpp b/pykd/python/pymod.cpp index 55ab7c3..0b51a1e 100644 --- a/pykd/python/pymod.cpp +++ b/pykd/python/pymod.cpp @@ -38,6 +38,7 @@ static const std::string pykdVersion = PYKD_VERSION_BUILD_STR //////////////////////////////////////////////////////////////////////////////// +BOOST_PYTHON_FUNCTION_OVERLOADS( attachKernel_, attachKernel, 0, 1 ); BOOST_PYTHON_FUNCTION_OVERLOADS( detachProcess_, detachProcess, 0, 1 ); BOOST_PYTHON_FUNCTION_OVERLOADS( dprint_, dprint, 1, 2 ); @@ -92,6 +93,11 @@ BOOST_PYTHON_MODULE( pykd ) "Start process for debugging" ); python::def( "attachProcess", &attachProcess, "Attach debugger to a exsisting process" ); + python::def( "attachKernel", &attachKernel, attachKernel_( boost::python::args( "connectOptions" ), + "Connect the debugger engine to a kernel target.\n" + "If connectOptions is not specified - attach to the local kernel") ); + python::def( "isLocalKernelDebuggerEnabled", &isLocalKernelDebuggerEnabled, + "Check whether kernel debugging is enabled for the local kernel" ); python::def( "detachProcess", &detachProcess, detachProcess_( boost::python::args( "pid" ), "Stop process debugging") ); python::def( "killProcess", &terminateProcess, diff --git a/pykd/win/dbgps.cpp b/pykd/win/dbgps.cpp index 3e6127f..5aa5517 100644 --- a/pykd/win/dbgps.cpp +++ b/pykd/win/dbgps.cpp @@ -65,7 +65,7 @@ ULONG attachProcess( ULONG pid ) hres = g_dbgEng->control->SetEngineOptions( opt ); if ( FAILED( hres ) ) throw DbgException( "IDebugControl::SetEngineOptions failed" ); - + hres = g_dbgEng->client->AttachProcess( 0, pid, 0 ); if ( FAILED( hres ) ) throw DbgException( "IDebugClient::AttachProcess failed" ); @@ -84,6 +84,34 @@ ULONG attachProcess( ULONG pid ) /////////////////////////////////////////////////////////////////////////////////// +void attachKernel( const std::string &connectOptions ) +{ + PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); + + HRESULT hres = + g_dbgEng->client->AttachKernel( + connectOptions.empty() ? DEBUG_ATTACH_LOCAL_KERNEL : DEBUG_ATTACH_KERNEL_CONNECTION, + connectOptions.empty() ? NULL : connectOptions.c_str()); + if ( FAILED( hres ) ) + throw DbgException( "IDebugClient::AttachKernel", hres ); + + hres = g_dbgEng->control->WaitForEvent(DEBUG_WAIT_DEFAULT, INFINITE); + if ( FAILED( hres ) ) + throw DbgException( "IDebugControl::WaitForEvent", hres ); +} + +/////////////////////////////////////////////////////////////////////////////////// + +bool isLocalKernelDebuggerEnabled() +{ + HRESULT hres = g_dbgEng->client->IsKernelDebuggerEnabled(); + if ( ( hres != S_OK ) && ( hres != S_FALSE ) ) + throw DbgException( "IDebugClient::IsKernelDebuggerEnabled", hres ); + return hres == S_OK; +} + +/////////////////////////////////////////////////////////////////////////////////// + void detachProcess( ULONG processId ) { PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); From b31456877d33301aca4194204ecb1a27f52f0ba6 Mon Sep 17 00:00:00 2001 From: "SND\\EreTIk_cp" Date: Mon, 2 Sep 2013 16:14:14 +0000 Subject: [PATCH 08/30] [2.0.x] + DEBUG_ENGOPT_INITIAL_BREAK for attachKernel git-svn-id: https://pykd.svn.codeplex.com/svn@85045 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/win/dbgps.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/pykd/win/dbgps.cpp b/pykd/win/dbgps.cpp index 5aa5517..474f5d7 100644 --- a/pykd/win/dbgps.cpp +++ b/pykd/win/dbgps.cpp @@ -88,7 +88,17 @@ void attachKernel( const std::string &connectOptions ) { PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); - HRESULT hres = + ULONG opt; + HRESULT hres = g_dbgEng->control->GetEngineOptions( &opt ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugControl::GetEngineOptions", hres ); + + opt |= DEBUG_ENGOPT_INITIAL_BREAK; + hres = g_dbgEng->control->SetEngineOptions( opt ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugControl::SetEngineOptions", hres ); + + hres = g_dbgEng->client->AttachKernel( connectOptions.empty() ? DEBUG_ATTACH_LOCAL_KERNEL : DEBUG_ATTACH_KERNEL_CONNECTION, connectOptions.empty() ? NULL : connectOptions.c_str()); From 594ebc15a147999bb227c4221f3e7d0c104f72a1 Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Thu, 5 Sep 2013 07:04:59 +0000 Subject: [PATCH 09/30] [0.2.x] fixed : issue #12145 ( getOffset failes with SymbolException ) git-svn-id: https://pykd.svn.codeplex.com/svn@85081 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/win/dbgmod.cpp | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/pykd/win/dbgmod.cpp b/pykd/win/dbgmod.cpp index 1a3c898..0a32414 100644 --- a/pykd/win/dbgmod.cpp +++ b/pykd/win/dbgmod.cpp @@ -55,15 +55,38 @@ ULONG64 findModuleBySymbol( const std::string &symbolName ) HRESULT hres; ULONG64 base; - hres = g_dbgEng->symbols->GetSymbolModule( ( std::string("!") + symbolName ).c_str(), &base ); - if ( FAILED( hres ) ) + std::string str = "!"; + str += symbolName; + + hres = g_dbgEng->symbols->GetSymbolModule( str.c_str(), &base ); + if ( SUCCEEDED( hres ) ) + return base; + + DEBUG_VALUE debugValue = {}; + ULONG remainderIndex = 0; + + hres = + g_dbgEng->control->Evaluate( + symbolName.c_str(), + DEBUG_VALUE_INT64, + &debugValue, + &remainderIndex ); + + if ( SUCCEEDED( hres ) ) { - std::stringstream sstr; - sstr << "failed to find module for symbol: " << symbolName; - throw SymbolException( sstr.str() ); + ULONG64 base; + ULONG moduleIndex; + + hres = g_dbgEng->symbols->GetModuleByOffset( debugValue.I64, 0, &moduleIndex, &base ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugSymbol::GetModuleByOffset", hres ); + + return base; } - return base; + std::stringstream sstr; + sstr << "failed to find module for symbol: " << symbolName; + throw SymbolException( sstr.str() ); } /////////////////////////////////////////////////////////////////////////////////// From 17e82d1ee16ae2eefa9fa2e5a03adc5873a9874e Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Mon, 9 Sep 2013 15:36:12 +0000 Subject: [PATCH 10/30] [0.2.x] fixed : um samples git-svn-id: https://pykd.svn.codeplex.com/svn@85129 9b283d60-5439-405e-af05-b73fd8c4d996 --- samples/um/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 samples/um/__init__.py diff --git a/samples/um/__init__.py b/samples/um/__init__.py new file mode 100644 index 0000000..e69de29 From 1f45804a5bc29835878d0751e851c2b63c66896b Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Wed, 11 Sep 2013 16:21:50 +0000 Subject: [PATCH 11/30] [0.2.x] added : expr support cplusplus syntax git-svn-id: https://pykd.svn.codeplex.com/svn@85176 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgengine.h | 2 +- pykd/pykd_2008.vcproj | 10 ++--- pykd/python/pymod.cpp | 5 ++- pykd/python/pysupport.cpp | 9 +++++ pykd/python/pysupport.h | 2 + pykd/win/dbgeng.cpp | 83 ++++++++++++++++++++++++--------------- 6 files changed, 71 insertions(+), 40 deletions(-) diff --git a/pykd/dbgengine.h b/pykd/dbgengine.h index 5008493..642896b 100644 --- a/pykd/dbgengine.h +++ b/pykd/dbgengine.h @@ -24,7 +24,7 @@ void debugStep(); void debugStepIn(); void debugBreak(); std::string debugCommand( const std::wstring &command ); -ULONG64 evaluate( const std::wstring &expression ); +BaseTypeVariant evaluate( const std::wstring &expression, bool cplusplus = false ); // debug output void dprint( const std::wstring &str, bool dml = false ); diff --git a/pykd/pykd_2008.vcproj b/pykd/pykd_2008.vcproj index 3588998..11a2d62 100644 --- a/pykd/pykd_2008.vcproj +++ b/pykd/pykd_2008.vcproj @@ -1,7 +1,7 @@ +#include /////////////////////////////////////////////////////////////////////////////// @@ -71,4 +72,12 @@ std::string printSystemVersion(SystemVersionPtr sysVer) /////////////////////////////////////////////////////////////////////////////// +std::string evaluate( const std::wstring &expression, bool cplusplus ) +{ + BaseTypeVariant var = pykd::evaluate( expression, cplusplus ); + + return boost::apply_visitor( pykd::VariantToStr(), var ); +} + +/////////////////////////////////////////////////////////////////////////////// } } //pykd::support namespace end \ No newline at end of file diff --git a/pykd/python/pysupport.h b/pykd/python/pysupport.h index b68d6b8..96aa834 100644 --- a/pykd/python/pysupport.h +++ b/pykd/python/pysupport.h @@ -20,6 +20,8 @@ python::tuple moduleFindSymbolAndDisp( pykd::Module &module, ULONG64 offset ); std::string printSystemVersion(SystemVersionPtr sysVer); +std::string evaluate( const std::wstring &expression, bool cplusplus = false ); + } } //pykd::support namespace end /////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/win/dbgeng.cpp b/pykd/win/dbgeng.cpp index b9b57d8..e5f2d0c 100644 --- a/pykd/win/dbgeng.cpp +++ b/pykd/win/dbgeng.cpp @@ -198,7 +198,7 @@ void debugBreak() /////////////////////////////////////////////////////////////////////////////// -ULONG64 evaluate( const std::wstring &expression ) +BaseTypeVariant evaluate( const std::wstring &expression, bool cplusplus ) { PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); @@ -207,41 +207,60 @@ ULONG64 evaluate( const std::wstring &expression ) DEBUG_VALUE debugValue = {}; ULONG remainderIndex = 0; - - hres = g_dbgEng->control->IsPointer64Bit(); - if ( FAILED( hres ) ) - throw DbgException( "IDebugControl::IsPointer64Bit failed" ); + ULONG expresionSyntax; - if ( hres == S_OK ) + hres = g_dbgEng->control->GetExpressionSyntax( &expresionSyntax ); + if ( FAILED(hres) ) { - hres = g_dbgEng->control->EvaluateWide( - expression.c_str(), - DEBUG_VALUE_INT64, - &debugValue, - &remainderIndex ); - - if ( FAILED( hres ) ) - throw DbgException( "IDebugControl::Evaluate failed" ); - - if ( remainderIndex == expression.length() ) - value = debugValue.I64; - } - else - { - hres = g_dbgEng->control->EvaluateWide( - expression.c_str(), - DEBUG_VALUE_INT32, - &debugValue, - &remainderIndex ); - - if ( FAILED( hres ) ) - throw DbgException( "IDebugControl::Evaluate failed" ); - - if ( remainderIndex == expression.length() ) - value = debugValue.I32; + throw DbgException( "IDebugControl3::GetExpressionSyntax failed" ); } - return value; + hres = g_dbgEng->control->SetExpressionSyntax( cplusplus ? DEBUG_EXPR_CPLUSPLUS : DEBUG_EXPR_MASM ); + if ( FAILED(hres) ) + { + throw DbgException( "IDebugControl3::GetExpressionSyntax failed" ); + } + + hres = g_dbgEng->control->EvaluateWide( + expression.c_str(), + DEBUG_VALUE_INVALID, + &debugValue, + &remainderIndex ); + + if ( FAILED( hres ) ) + { + g_dbgEng->control->SetExpressionSyntax( expresionSyntax ); + throw DbgException( "IDebugControl::Evaluate failed" ); + } + + BaseTypeVariant var; + + switch( debugValue.Type ) + { + case DEBUG_VALUE_INT8: + var = BaseTypeVariant( (LONG)debugValue.I8 ); + break; + + case DEBUG_VALUE_INT16: + var = BaseTypeVariant( (LONG)debugValue.I16 ); + break; + + case DEBUG_VALUE_INT32: + var = BaseTypeVariant( debugValue.I32 ); + break; + + case DEBUG_VALUE_INT64: + var = BaseTypeVariant( debugValue.I64 ); + break; + + default: + g_dbgEng->control->SetExpressionSyntax( expresionSyntax ); + throw DbgException("unsupported type"); + } + + g_dbgEng->control->SetExpressionSyntax( expresionSyntax ); + + return var; } /////////////////////////////////////////////////////////////////////////////// From ab92133f281f52363e60955ffa529c823376f038 Mon Sep 17 00:00:00 2001 From: "SND\\EreTIk_cp" Date: Wed, 11 Sep 2013 16:57:48 +0000 Subject: [PATCH 12/30] [0.2.x] fix: Hresult as ULong git-svn-id: https://pykd.svn.codeplex.com/svn@85177 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/typedvar.cpp | 5 ++++- pykd/typeinfo.cpp | 5 ++++- test/scripts/typedvar.py | 4 ++++ test/scripts/typeinfo.py | 15 +++++++-------- test/targetapp/targetapp.cpp | 6 +++--- 5 files changed, 22 insertions(+), 13 deletions(-) diff --git a/pykd/typedvar.cpp b/pykd/typedvar.cpp index d4a77fb..9cf0cd7 100644 --- a/pykd/typedvar.cpp +++ b/pykd/typedvar.cpp @@ -149,7 +149,10 @@ BaseTypeVariant BasicTypedVar::getValue() if ( m_typeInfo->getName() == "Bool" ) return *(bool*)&val; - + + if ( m_typeInfo->getName() == "Hresult" ) + return *(PULONG)&val; + throw DbgException( "failed get value " ); } diff --git a/pykd/typeinfo.cpp b/pykd/typeinfo.cpp index 3b387b6..a47827c 100644 --- a/pykd/typeinfo.cpp +++ b/pykd/typeinfo.cpp @@ -252,7 +252,7 @@ TypeInfoPtr TypeInfo::getTypeInfo( SymbolPtr &symScope, const std::string &symN ///////////////////////////////////////////////////////////////////////////////////// -static const boost::regex baseMatch("^(Char)|(WChar)|(Int1B)|(UInt1B)|(Int2B)|(UInt2B)|(Int4B)|(UInt4B)|(Int8B)|(UInt8B)|(Long)|(ULong)|(Float)|(Bool)|(Double)$" ); +static const boost::regex baseMatch("^(Char)|(WChar)|(Int1B)|(UInt1B)|(Int2B)|(UInt2B)|(Int4B)|(UInt4B)|(Int8B)|(UInt8B)|(Long)|(ULong)|(Float)|(Bool)|(Double)|(Hresult)$" ); bool TypeInfo::isBaseType( const std::string &symName ) @@ -313,6 +313,9 @@ TypeInfo::getBaseTypeInfo( const std::string &symName, ULONG pointerSize ) if ( baseMatchResult[15].matched ) return TypeInfoPtr( new TypeInfoWrapper("Double", pointerSize) ); + + if ( baseMatchResult[16].matched ) + return TypeInfoPtr( new TypeInfoWrapper("Hresult", pointerSize) ); } return TypeInfoPtr(); diff --git a/test/scripts/typedvar.py b/test/scripts/typedvar.py index a11edeb..d3234b0 100644 --- a/test/scripts/typedvar.py +++ b/test/scripts/typedvar.py @@ -323,3 +323,7 @@ class TypedVarTest( unittest.TestCase ): self.assertRaises( pykd.BaseException, pykd.typedVarList, target.module.g_listHead1, None, "next" ) self.assertRaises( pykd.BaseException, pykd.typedVarArray, target.module.g_testArray, None, 2 ) self.assertRaises( pykd.BaseException, pykd.containingRecord, target.module.offset( "g_structTest" ), None, "m_field2" ) + + def testHresult(self): + tv = pykd.typedVar( "g_atlException" ) + self.assertEqual( tv.m_hr, 0x8000FFFF ) diff --git a/test/scripts/typeinfo.py b/test/scripts/typeinfo.py index 67bd6f4..a03fabb 100644 --- a/test/scripts/typeinfo.py +++ b/test/scripts/typeinfo.py @@ -192,7 +192,7 @@ class TypeInfoTest( unittest.TestCase ): self.assertTrue( str(target.module.type( "g_voidPtr" ) ) ) self.assertTrue( str(target.module.type( "g_arrOfPtrToFunc" ) ) ) self.assertTrue( str(target.module.type( "g_unTypedPtrToFunction" ) ) ) - + def testTypedef(self): self.assertEqual( "structTest", pykd.typeInfo( "g_structTypeDef" ).name() ) self.assertEqual( "structTest", pykd.typeInfo( "structTestTypeDef" ).name() ) @@ -213,21 +213,20 @@ class TypeInfoTest( unittest.TestCase ): self.assertEqual( 5, len(ti) ) for field in ti: str( field ) - + def testStructNullSize(self): ti = target.module.type("structNullSize") self.assertEqual( 0, len(ti) ) - + def testDerefName(self): entry = pykd.typedVar("entry1").Flink self.assertEqual( "_LIST_ENTRY*", entry.type().name() ) - - def testPtrTo(self): + + def testPtrTo(self): ti = pykd.typeInfo("UInt8B").ptrTo() self.assertTrue( "UInt8B*", ti.name() ) self.assertNotEqual( 0, ti.size() ) - + def testArrayOf(self): ti = pykd.typeInfo("UInt8B").arrayOf(10) - self.assertTrue( "UInt8B[10]", ti.name() ) - + self.assertTrue( "UInt8B[10]", ti.name() ) diff --git a/test/targetapp/targetapp.cpp b/test/targetapp/targetapp.cpp index 043cbd2..92f4688 100644 --- a/test/targetapp/targetapp.cpp +++ b/test/targetapp/targetapp.cpp @@ -1,7 +1,7 @@ #include "stdafx.h" #include - +#include #include #include @@ -206,7 +206,7 @@ struct struct3 { struct3 g_struct3 = { { 0, 2 }, 3 }; __int64 g_bigValue = 0x8080808080808080; - +volatile ATL::CAtlException g_atlException(E_UNEXPECTED); static LIST_ENTRY g_listHead; @@ -437,7 +437,7 @@ void FuncWithName0() std::cout << g_charValue; std::cout << g_shortValue; std::cout << g_longValue; - std::cout << g_longlongValue; + std::cout << g_longlongValue << g_atlException.m_hr; std::cout << g_structTest.m_field0; std::cout << g_testArray[1].m_field3; From b5548159c0fdf5f0c79fac1f983d2a003dff0105 Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Fri, 13 Sep 2013 14:08:37 +0000 Subject: [PATCH 13/30] [0.2.x] fixed : expr with cplusplus syntax git-svn-id: https://pykd.svn.codeplex.com/svn@85197 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/python/pysupport.cpp | 4 ++-- pykd/python/pysupport.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pykd/python/pysupport.cpp b/pykd/python/pysupport.cpp index 0069d42..6f6d7b7 100644 --- a/pykd/python/pysupport.cpp +++ b/pykd/python/pysupport.cpp @@ -72,11 +72,11 @@ std::string printSystemVersion(SystemVersionPtr sysVer) /////////////////////////////////////////////////////////////////////////////// -std::string evaluate( const std::wstring &expression, bool cplusplus ) +python::object evaluate( const std::wstring &expression, bool cplusplus ) { BaseTypeVariant var = pykd::evaluate( expression, cplusplus ); - return boost::apply_visitor( pykd::VariantToStr(), var ); + return boost::apply_visitor( pykd::VariantToPyobj(), var ); } /////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/python/pysupport.h b/pykd/python/pysupport.h index 96aa834..c1dbe86 100644 --- a/pykd/python/pysupport.h +++ b/pykd/python/pysupport.h @@ -20,7 +20,7 @@ python::tuple moduleFindSymbolAndDisp( pykd::Module &module, ULONG64 offset ); std::string printSystemVersion(SystemVersionPtr sysVer); -std::string evaluate( const std::wstring &expression, bool cplusplus = false ); +python::object evaluate( const std::wstring &expression, bool cplusplus = false ); } } //pykd::support namespace end From e9923606b382683249fc2bb3af96ea2f509ec9c0 Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Fri, 27 Sep 2013 08:13:19 +0000 Subject: [PATCH 14/30] [0.2.x] fixed : findSymbol return empty string git-svn-id: https://pykd.svn.codeplex.com/svn@85394 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/module.cpp | 12 ++++++++++-- pykd/pykdver.h | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/pykd/module.cpp b/pykd/module.cpp index 69fe906..c984496 100644 --- a/pykd/module.cpp +++ b/pykd/module.cpp @@ -337,9 +337,17 @@ void Module::getSymbolAndDispByVa( ULONG64 offset, std::string &symbolName, LONG { offset = prepareVa(offset); - SymbolPtr sym = getSymSession()->findByRva( (ULONG)(offset - m_base ), SymTagNull, &displacement ); + symbolName.clear(); - symbolName = sym->getName(); + while ( symbolName.empty() ) + { + SymbolPtr sym = getSymSession()->findByRva( (ULONG)(offset - m_base ), SymTagNull, &displacement ); + symbolName = sym->getName(); + if ( !symbolName.empty() ) + break; + + offset = offset - displacement - 1; + } } /////////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/pykdver.h b/pykd/pykdver.h index 44b84b5..9d1240e 100644 --- a/pykd/pykdver.h +++ b/pykd/pykdver.h @@ -2,7 +2,7 @@ #define PYKD_VERSION_MAJOR 0 #define PYKD_VERSION_MINOR 2 #define PYKD_VERSION_SUBVERSION 0 -#define PYKD_VERSION_BUILDNO 22 +#define PYKD_VERSION_BUILDNO 24 #define __VER_STR2__(x) #x From 843ab7ac07e295e113e81805282dec776079b52b Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Wed, 16 Oct 2013 13:27:13 +0000 Subject: [PATCH 15/30] [0.2.x] added : debugAccess enum git-svn-id: https://pykd.svn.codeplex.com/svn@85781 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgengine.h | 7 +++++++ pykd/pykdver.h | 2 +- pykd/python/pymod.cpp | 7 +++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/pykd/dbgengine.h b/pykd/dbgengine.h index 642896b..4b6a796 100644 --- a/pykd/dbgengine.h +++ b/pykd/dbgengine.h @@ -160,6 +160,13 @@ enum EXECUTION_STATUS { DebugStatusNoDebuggee = 7 }; +enum DEBUG_ACCESS_TYPE { + DebugAccessRead = 0x00000001, + DebugAccessWrite = 0x00000002, + DebugAccessExecute = 0x00000004, + DebugAccessIo = 0x00000008 +}; + struct BUG_CHECK_DATA { ULONG code; diff --git a/pykd/pykdver.h b/pykd/pykdver.h index 9d1240e..b4c8e7c 100644 --- a/pykd/pykdver.h +++ b/pykd/pykdver.h @@ -2,7 +2,7 @@ #define PYKD_VERSION_MAJOR 0 #define PYKD_VERSION_MINOR 2 #define PYKD_VERSION_SUBVERSION 0 -#define PYKD_VERSION_BUILDNO 24 +#define PYKD_VERSION_BUILDNO 25 #define __VER_STR2__(x) #x diff --git a/pykd/python/pymod.cpp b/pykd/python/pymod.cpp index b29375f..00d69f0 100644 --- a/pykd/python/pymod.cpp +++ b/pykd/python/pymod.cpp @@ -634,6 +634,13 @@ BOOST_PYTHON_MODULE( pykd ) .value("NoDebuggee", DebugStatusNoDebuggee ) .export_values(); + python::enum_("debugAccess", "Debud Access Types") + .value("Read", DebugAccessRead ) + .value("Write", DebugAccessWrite ) + .value("Execute", DebugAccessExecute ) + .value("DebugAccessIo", DebugAccessIo ) + .export_values(); + python::class_( "eventHandler", "Base class for overriding and handling debug notifications" ) .def( "onBreakpoint", &EventHandlerWrap::OnBreakpoint, From 16dc23f44ff78b342922a6e563b058e08ed47c9a Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Wed, 16 Oct 2013 17:14:28 +0000 Subject: [PATCH 16/30] [0.2.x] fixed : issue # 12324 ( windbg crash after exception in the multithreading script ) git-svn-id: https://pykd.svn.codeplex.com/svn@85785 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgext.cpp | 87 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 64 insertions(+), 23 deletions(-) diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp index e0f1492..11011da 100644 --- a/pykd/dbgext.cpp +++ b/pykd/dbgext.cpp @@ -192,10 +192,12 @@ HRESULT CALLBACK py( PDEBUG_CLIENT4 client, PCSTR args ) { + WindbgGlobalSession::RestorePyState(); PyThreadState *globalInterpreter = PyThreadState_Swap( NULL ); - PyThreadState *localInterpreter = Py_NewInterpreter(); + + PyThreadState *localState = Py_NewInterpreter(); try { @@ -235,7 +237,8 @@ py( PDEBUG_CLIENT4 client, PCSTR args ) if ( argsList.size() == 0 ) { - Py_EndInterpreter( localInterpreter ); + Py_EndInterpreter( localState ); + PyThreadState_Swap( globalInterpreter ); WindbgGlobalSession::SavePyState(); @@ -243,33 +246,37 @@ py( PDEBUG_CLIENT4 client, PCSTR args ) return S_OK; } - char **pythonArgs = new char* [ argsList.size() ]; - - for ( size_t i = 0; i < argsList.size(); ++i ) - pythonArgs[i] = const_cast( argsList[i].c_str() ); - - PySys_SetArgv( (int)argsList.size(), pythonArgs ); - - delete[] pythonArgs; - // найти путь к файлу std::string fullScriptName; DbgPythonPath dbgPythonPath; - - if ( !dbgPythonPath.getFullFileName( argsList[0], fullScriptName ) ) + + if ( dbgPythonPath.getFullFileName( argsList[0], fullScriptName ) ) { - eprintln( L"script file not found" ); + char **pythonArgs = new char* [ argsList.size() ]; + + for ( size_t i = 1; i < argsList.size(); ++i ) + pythonArgs[i] = const_cast( argsList[i].c_str() ); + + pythonArgs[0] = const_cast( fullScriptName.c_str() ); + + PySys_SetArgv( (int)argsList.size(), pythonArgs ); + + delete[] pythonArgs; + + try { + + python::object result; + + result = python::exec_file( fullScriptName.c_str(), global, global ); + } + catch( boost::python::error_already_set const & ) + { + printException(); + } } else - try { - - python::object result; - - result = python::exec_file( fullScriptName.c_str(), global, global ); - } - catch( boost::python::error_already_set const & ) { - printException(); + eprintln( L"script file not found" ); } } catch(...) @@ -277,7 +284,41 @@ py( PDEBUG_CLIENT4 client, PCSTR args ) eprintln( L"unexpected error" ); } - Py_EndInterpreter( localInterpreter ); + PyInterpreterState *interpreter = localState->interp; + + while( interpreter->tstate_head != NULL ) + { + PyThreadState *threadState = (PyThreadState*)(interpreter->tstate_head); + + PyThreadState_Clear(threadState); + + PyThreadState_Swap( NULL ); + + //interpreter->tstate_head = threadState->next; + + PyThreadState_Delete(threadState); + } + + PyInterpreterState_Clear(interpreter); + + PyInterpreterState_Delete(interpreter); + + //Py_EndInterpreter( localInterpreter ); + + //std::list localThreadsState; + //localThread = PyInterpreterState_ThreadHead( localInterpreter ); + //while( localThread ) + //{ + // localThreadsState.push_back(localThread); + // localThread = PyThreadState_Next(localThread); + //} + + //std::for_each( localThreadsState.begin(), localThreadsState.end(), PyThreadState_Clear ); + //std::for_each( localThreadsState.begin(), localThreadsState.end(), PyThreadState_Delete ); + + //PyInterpreterState_Clear( localInterpreter ); + //PyInterpreterState_Delete( localInterpreter ); + PyThreadState_Swap( globalInterpreter ); WindbgGlobalSession::SavePyState(); From ed00ec2b6704e7d10c3cf9b5008f5fdfb5550cda Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Wed, 16 Oct 2013 17:45:49 +0000 Subject: [PATCH 17/30] [0.2.x] fixed : cleanup code git-svn-id: https://pykd.svn.codeplex.com/svn@85786 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgext.cpp | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp index 11011da..8ffc5fd 100644 --- a/pykd/dbgext.cpp +++ b/pykd/dbgext.cpp @@ -294,30 +294,12 @@ py( PDEBUG_CLIENT4 client, PCSTR args ) PyThreadState_Swap( NULL ); - //interpreter->tstate_head = threadState->next; - PyThreadState_Delete(threadState); } PyInterpreterState_Clear(interpreter); - PyInterpreterState_Delete(interpreter); - - //Py_EndInterpreter( localInterpreter ); - - //std::list localThreadsState; - //localThread = PyInterpreterState_ThreadHead( localInterpreter ); - //while( localThread ) - //{ - // localThreadsState.push_back(localThread); - // localThread = PyThreadState_Next(localThread); - //} - - //std::for_each( localThreadsState.begin(), localThreadsState.end(), PyThreadState_Clear ); - //std::for_each( localThreadsState.begin(), localThreadsState.end(), PyThreadState_Delete ); - - //PyInterpreterState_Clear( localInterpreter ); - //PyInterpreterState_Delete( localInterpreter ); + PyInterpreterState_Delete(interpreter); PyThreadState_Swap( globalInterpreter ); From feb9e84a6eac8ef3848ecbe74d35ce975f68b77f Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Thu, 17 Oct 2013 08:26:50 +0000 Subject: [PATCH 18/30] [0.2.x] added : IPython adaptation git-svn-id: https://pykd.svn.codeplex.com/svn@85804 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgext.cpp | 6 ++++++ pykd/python/pymod.cpp | 3 ++- pykd/win/dbgio.h | 5 +++++ snippets/ipython.py | 14 ++++++++++++++ 4 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 snippets/ipython.py diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp index 8ffc5fd..901ca82 100644 --- a/pykd/dbgext.cpp +++ b/pykd/dbgext.cpp @@ -193,6 +193,10 @@ CALLBACK py( PDEBUG_CLIENT4 client, PCSTR args ) { + ULONG mask = 0; + client->GetOutputMask( &mask ); + client->SetOutputMask( mask & ~DEBUG_OUTPUT_PROMPT ); // убрать эхо ввода + WindbgGlobalSession::RestorePyState(); PyThreadState *globalInterpreter = PyThreadState_Swap( NULL ); @@ -305,6 +309,8 @@ py( PDEBUG_CLIENT4 client, PCSTR args ) WindbgGlobalSession::SavePyState(); + client->SetOutputMask( mask ); + return S_OK; } diff --git a/pykd/python/pymod.cpp b/pykd/python/pymod.cpp index 00d69f0..be10781 100644 --- a/pykd/python/pymod.cpp +++ b/pykd/python/pymod.cpp @@ -139,7 +139,8 @@ BOOST_PYTHON_MODULE( pykd ) python::class_( "dout", "dout", python::no_init ) .def( "write", &DbgErr::write ); python::class_( "din", "din", python::no_init ) - .def( "readline", &DbgIn::readline ); + .def( "readline", &DbgIn::readline ) + .add_property( "encoding", &DbgIn::encoding ); // system properties python::def( "ptrSize", &ptrSize, diff --git a/pykd/win/dbgio.h b/pykd/win/dbgio.h index ebab51c..b5f412d 100644 --- a/pykd/win/dbgio.h +++ b/pykd/win/dbgio.h @@ -44,6 +44,11 @@ public: return dreadline(); } + std::string + encoding() { + return "ascii"; + } + }; /////////////////////////////////////////////////////////////////////////////// diff --git a/snippets/ipython.py b/snippets/ipython.py new file mode 100644 index 0000000..e07ac04 --- /dev/null +++ b/snippets/ipython.py @@ -0,0 +1,14 @@ +from IPython.config.loader import Config +from IPython.terminal.embed import InteractiveShellEmbed +from pykd import * + +cfg = Config() + +cfg.InteractiveShell.colors = 'NoColor' +cfg.PromptManager.in_template = 'In <\\#>: ' +cfg.PromptManager.in2_template = ' .\\D.: ' +cfg.PromptManager.out_template = 'Out<\\#>: ' + +ipshell = InteractiveShellEmbed(config=cfg) + +ipshell() From fd89d45dfe14cb1a84ef126b0983bbcc09947d66 Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Thu, 17 Oct 2013 12:38:32 +0000 Subject: [PATCH 19/30] [0.2.x] fixed : IPython integrations bugs git-svn-id: https://pykd.svn.codeplex.com/svn@85811 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/python/pymod.cpp | 10 +++++++--- pykd/win/dbgio.h | 15 +++++++++++++++ snippets/ipython.py | 10 ++++++++-- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/pykd/python/pymod.cpp b/pykd/python/pymod.cpp index be10781..c02d8d6 100644 --- a/pykd/python/pymod.cpp +++ b/pykd/python/pymod.cpp @@ -135,9 +135,13 @@ BOOST_PYTHON_MODULE( pykd ) // Python debug output console helper classes python::class_( "dout", "dout", python::no_init ) - .def( "write", &DbgOut::write ); - python::class_( "dout", "dout", python::no_init ) - .def( "write", &DbgErr::write ); + .def( "write", &DbgOut::write ) + .def( "flush", &DbgOut::flush ) + .add_property( "encoding", &DbgOut::encoding ); + python::class_( "derr", "derr", python::no_init ) + .def( "write", &DbgErr::write ) + .def( "flush", &DbgOut::flush ) + .add_property( "encoding", &DbgErr::encoding ); python::class_( "din", "din", python::no_init ) .def( "readline", &DbgIn::readline ) .add_property( "encoding", &DbgIn::encoding ); diff --git a/pykd/win/dbgio.h b/pykd/win/dbgio.h index b5f412d..121b143 100644 --- a/pykd/win/dbgio.h +++ b/pykd/win/dbgio.h @@ -17,6 +17,13 @@ public: dprint( str ); } + void flush() { + } + + std::string + encoding() { + return "ascii"; + } }; /////////////////////////////////////////////////////////////////////////////// @@ -30,6 +37,14 @@ public: { eprint( str ); } + + void flush() { + } + + std::string + encoding() { + return "ascii"; + } }; /////////////////////////////////////////////////////////////////////////////// diff --git a/snippets/ipython.py b/snippets/ipython.py index e07ac04..630890f 100644 --- a/snippets/ipython.py +++ b/snippets/ipython.py @@ -1,14 +1,20 @@ from IPython.config.loader import Config from IPython.terminal.embed import InteractiveShellEmbed -from pykd import * + +from IPython.terminal.interactiveshell import TerminalInteractiveShell + +import pykd cfg = Config() cfg.InteractiveShell.colors = 'NoColor' +cfg.InteractiveShell.readline_use = False +cfg.InteractiveShell.autoindent = True + cfg.PromptManager.in_template = 'In <\\#>: ' cfg.PromptManager.in2_template = ' .\\D.: ' cfg.PromptManager.out_template = 'Out<\\#>: ' ipshell = InteractiveShellEmbed(config=cfg) -ipshell() +ipshell() \ No newline at end of file From cf6eea3f784433a03ec1565b7c66fc6ea1ac0552 Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Thu, 17 Oct 2013 13:34:07 +0000 Subject: [PATCH 20/30] [0.2.x] fixed : dbgCommand return unicode string git-svn-id: https://pykd.svn.codeplex.com/svn@85813 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgengine.h | 6 +++--- pykd/win/dbgeng.cpp | 10 +++++----- pykd/win/dbgio.cpp | 10 +++++----- pykd/win/dbgio.h | 22 +++++++++++----------- snippets/ipython.py | 2 ++ snippets/pykdmagic.py | 23 +++++++++++++++++++++++ 6 files changed, 49 insertions(+), 24 deletions(-) create mode 100644 snippets/pykdmagic.py diff --git a/pykd/dbgengine.h b/pykd/dbgengine.h index 4b6a796..f19ee5d 100644 --- a/pykd/dbgengine.h +++ b/pykd/dbgengine.h @@ -23,13 +23,13 @@ void debugGo(); void debugStep(); void debugStepIn(); void debugBreak(); -std::string debugCommand( const std::wstring &command ); +std::wstring debugCommand( const std::wstring &command ); BaseTypeVariant evaluate( const std::wstring &expression, bool cplusplus = false ); // debug output void dprint( const std::wstring &str, bool dml = false ); void dprintln( const std::wstring &str, bool dml = false ); -std::string dreadline(); +std::wstring dreadline(); void eprint( const std::wstring &str ); void eprintln( const std::wstring &str ); @@ -203,7 +203,7 @@ void appendSymbolPath(const std::string &symPath); // Extensions ULONG64 loadExtension(const std::wstring &extPath ); void removeExtension( ULONG64 extHandle ); -std::string callExtension( ULONG64 extHandle, const std::wstring command, const std::wstring ¶ms ); +std::wstring callExtension( ULONG64 extHandle, const std::wstring command, const std::wstring ¶ms ); }; diff --git a/pykd/win/dbgeng.cpp b/pykd/win/dbgeng.cpp index e5f2d0c..17bb778 100644 --- a/pykd/win/dbgeng.cpp +++ b/pykd/win/dbgeng.cpp @@ -265,7 +265,7 @@ BaseTypeVariant evaluate( const std::wstring &expression, bool cplusplus ) /////////////////////////////////////////////////////////////////////////////// -std::string debugCommand( const std::wstring &command ) +std::wstring debugCommand( const std::wstring &command ) { PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); @@ -275,9 +275,9 @@ std::string debugCommand( const std::wstring &command ) hres = g_dbgEng->control->ExecuteWide( DEBUG_OUTCTL_THIS_CLIENT, command.c_str(), 0 ); if ( FAILED( hres ) ) - throw DbgException( "IDebugControl::Execute failed" ); + throw DbgException( "IDebugControl::ExecuteWide failed" ); - return std::string( outReader.Line() ); + return outReader.Line(); } /////////////////////////////////////////////////////////////////////////////// @@ -1314,7 +1314,7 @@ void removeExtension( ULONG64 extHandle ) /////////////////////////////////////////////////////////////////////////////// -std::string callExtension( ULONG64 extHandle, const std::wstring command, const std::wstring ¶ms ) +std::wstring callExtension( ULONG64 extHandle, const std::wstring command, const std::wstring ¶ms ) { PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); @@ -1327,7 +1327,7 @@ std::string callExtension( ULONG64 extHandle, const std::wstring command, const if ( FAILED( hres ) ) throw DbgException( "IDebugControl::CallExtension failed" ); - return std::string( outReader.Line() ); + return std::wstring( outReader.Line() ); } /////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/win/dbgio.cpp b/pykd/win/dbgio.cpp index 6e40704..b03080f 100644 --- a/pykd/win/dbgio.cpp +++ b/pykd/win/dbgio.cpp @@ -67,16 +67,16 @@ void eprintln( const std::wstring &str ) /////////////////////////////////////////////////////////////////////////////////// -std::string dreadline() +std::wstring dreadline() { PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); - char str[0x100]; - ULONG inputSize = 0; + wchar_t str[0x100]; + ULONG inputSize = 0; - g_dbgEng->control->Input( str, sizeof(str), &inputSize ); + g_dbgEng->control->InputWide( str, sizeof(str), &inputSize ); - return std::string( str ) + "\n"; + return std::wstring( str ) + L"\n"; } /////////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/win/dbgio.h b/pykd/win/dbgio.h index 121b143..7892829 100644 --- a/pykd/win/dbgio.h +++ b/pykd/win/dbgio.h @@ -54,7 +54,7 @@ class DbgIn { public: - std::string + std::wstring readline() { return dreadline(); } @@ -68,7 +68,7 @@ public: /////////////////////////////////////////////////////////////////////////////// -class OutputReader : public IDebugOutputCallbacks, private boost::noncopyable { +class OutputReader : public IDebugOutputCallbacksWide, private boost::noncopyable { public: @@ -78,21 +78,21 @@ public: m_client = client; - hres = m_client->GetOutputCallbacks( &m_previousCallback ); + hres = m_client->GetOutputCallbacksWide( &m_previousCallback ); if ( FAILED( hres ) ) throw DbgException( "IDebugClient::GetOutputCallbacks failed" ); - hres = m_client->SetOutputCallbacks( this ); + hres = m_client->SetOutputCallbacksWide( this ); if ( FAILED( hres ) ) throw DbgException( "IDebugClient::GetOutputCallbacks failed" ); } ~OutputReader() { - m_client->SetOutputCallbacks( m_previousCallback ); + m_client->SetOutputCallbacksWide( m_previousCallback ); } - const std::string& + const std::wstring& Line() const { return m_readLine; } @@ -117,22 +117,22 @@ private: STDMETHOD(Output)( __in ULONG Mask, - __in PCSTR Text ) + __in PCWSTR Text ) { if ( Mask == DEBUG_OUTPUT_NORMAL ) { - m_readLine += std::string( Text ); + m_readLine += std::wstring( Text ); } return S_OK; } private: - std::string m_readLine; + std::wstring m_readLine; - CComPtr m_previousCallback; + CComPtr m_previousCallback; - CComPtr m_client; + CComQIPtr m_client; }; /////////////////////////////////////////////////////////////////////////////// diff --git a/snippets/ipython.py b/snippets/ipython.py index 630890f..c1e9109 100644 --- a/snippets/ipython.py +++ b/snippets/ipython.py @@ -15,6 +15,8 @@ cfg.PromptManager.in_template = 'In <\\#>: ' cfg.PromptManager.in2_template = ' .\\D.: ' cfg.PromptManager.out_template = 'Out<\\#>: ' +cfg.InteractiveShellApp.extensions = [ 'pykdmagic' ] + ipshell = InteractiveShellEmbed(config=cfg) ipshell() \ No newline at end of file diff --git a/snippets/pykdmagic.py b/snippets/pykdmagic.py new file mode 100644 index 0000000..a000ad0 --- /dev/null +++ b/snippets/pykdmagic.py @@ -0,0 +1,23 @@ + +from IPython.core.magic import Magics, magics_class, line_magic, cell_magic, line_cell_magic +import pykd + +@magics_class +class PykdMagic (Magics): + + @line_magic + def kd(self,line): + "any windbg command" + try: + pykd.dprintln( pykd.dbgCommand(line) ) + except pykd.BaseException: + pykd.dprintln("invalid windbg syntax") + return None + +def load_ipython_extension(ipython): + ipython.register_magics(PykdMagic) + +def unload_ipython_extension(ipython): + pass + + From 5cb3fc858bc045e0dac23c80822c2f0fdfce9f2a Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Mon, 21 Oct 2013 13:59:58 +0000 Subject: [PATCH 21/30] [0.2.x] fixed : issue #12335 ( TypeError: object has no len() for array ) git-svn-id: https://pykd.svn.codeplex.com/svn@85918 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/typeinfo.h | 22 ++++++++++++++++++++-- test/scripts/typeinfo.py | 13 +++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/pykd/typeinfo.h b/pykd/typeinfo.h index e8c594c..d0aa827 100644 --- a/pykd/typeinfo.h +++ b/pykd/typeinfo.h @@ -203,7 +203,7 @@ public: throw PyException( PyExc_TypeError, "object has no len()" ); } - virtual python::tuple getElementByIndex( ULONG index ) { + virtual python::object getElementByIndex( ULONG index ) { throw PyException( PyExc_TypeError, "object is unsubscriptable"); } @@ -400,7 +400,7 @@ protected: return getFieldCount(); } - virtual python::tuple getElementByIndex( ULONG index ) { + virtual python::object getElementByIndex( ULONG index ) { return python::make_tuple( getFieldNameByIndex(index), getFieldByIndex(index) ); } @@ -542,6 +542,14 @@ protected: return getSize(); } + virtual ULONG getElementCount() { + return getFieldCount(); + } + + virtual python::object getElementByIndex( ULONG index ) { + return python::make_tuple( getFieldNameByIndex(index), getFieldByIndex(index) ); + } + SymbolPtr m_dia; }; @@ -630,6 +638,16 @@ public: return m_count; } + virtual ULONG getElementCount() { + return getCount(); + } + + virtual python::object getElementByIndex( ULONG index ) { + if( index < m_count ) + return python::object( m_derefType ); + throw PyException( PyExc_IndexError, "index out of range" ); + } + virtual TypeInfoPtr getElementType() { return m_derefType; } diff --git a/test/scripts/typeinfo.py b/test/scripts/typeinfo.py index a03fabb..de75fde 100644 --- a/test/scripts/typeinfo.py +++ b/test/scripts/typeinfo.py @@ -213,6 +213,19 @@ class TypeInfoTest( unittest.TestCase ): self.assertEqual( 5, len(ti) ) for field in ti: str( field ) + + def testArraySubscribe(self): + ti = pykd.typeInfo("g_testArray") + self.assertEqual(2, len(ti) ) + for field in ti: + str( field ) + + def testEnumSubscribe(self): + ti = pykd.typeInfo("enumType") + self.assertEqual(3, len(ti) ) + self.assertEqual( ( "TWO", 2 ), ti[1] ) + for field in ti: + str( field ) def testStructNullSize(self): ti = target.module.type("structNullSize") From 81fe97052f90963052526f56d8bce326b7816c7f Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Wed, 23 Oct 2013 11:52:00 +0000 Subject: [PATCH 22/30] [0.2.x] fixed : issue #12353 ( typedVar for bit field returns a wrong result for width >= 32 bits ) git-svn-id: https://pykd.svn.codeplex.com/svn@85967 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/typedvar.cpp | 2 +- test/scripts/moduletest.py | 4 ++-- test/scripts/typedvar.py | 2 ++ test/scripts/typeinfo.py | 2 +- test/targetapp/targetapp.cpp | 6 ++++-- 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/pykd/typedvar.cpp b/pykd/typedvar.cpp index 9cf0cd7..fc8e6e6 100644 --- a/pykd/typedvar.cpp +++ b/pykd/typedvar.cpp @@ -470,7 +470,7 @@ BaseTypeVariant BitFieldVar::getValue() else { val >>= m_typeInfo->getBitOffset(); - val &= ( 1 << m_typeInfo->getBitWidth() ) - 1; + val &= ( 1LL << m_typeInfo->getBitWidth() ) - 1LL; switch ( m_typeInfo->getSize() ) { diff --git a/test/scripts/moduletest.py b/test/scripts/moduletest.py index 1b960b2..ebc203d 100644 --- a/test/scripts/moduletest.py +++ b/test/scripts/moduletest.py @@ -78,11 +78,11 @@ class ModuleTest( unittest.TestCase ): fileName = pykd.getSourceFile(target.module.FuncWithName0 ) self.assertTrue( re.search('targetapp\\.cpp', fileName ) ) fileName, lineNo, displacement = pykd.getSourceLine( target.module.FuncWithName0 + 2) - self.assertEqual( 421, lineNo ) + self.assertEqual( 423, lineNo ) self.assertTrue( re.search('targetapp\\.cpp', fileName ) ) self.assertEqual( 2, displacement ) fileName, lineNo, displacement = pykd.getSourceLine() - self.assertEqual( 698, lineNo ) + self.assertEqual( 700, lineNo ) def testEnumSymbols( self ): lst = target.module.enumSymbols() diff --git a/test/scripts/typedvar.py b/test/scripts/typedvar.py index d3234b0..7c51044 100644 --- a/test/scripts/typedvar.py +++ b/test/scripts/typedvar.py @@ -144,10 +144,12 @@ class TypedVarTest( unittest.TestCase ): self.assertEqual( 4, tv.m_bit0_4 ) self.assertEqual( 1, tv.m_bit5 ) self.assertEqual( 5, tv.m_bit6_8 ) + self.assertEqual( 0xFF00000000, tv.m_bit0_60 ) tv = target.module.typedVar("g_structWithSignBits") self.assertEqual( 4, tv.m_bit0_4 ) self.assertEqual( -1, tv.m_bit5 ) self.assertEqual( -3, tv.m_bit6_8 ) + self.assertEqual( -1, tv.m_bit0_60 ) def testTypedVarList(self): tvl = target.module.typedVarList( target.module.g_listHead, "listStruct", "listEntry" ) diff --git a/test/scripts/typeinfo.py b/test/scripts/typeinfo.py index de75fde..522cffb 100644 --- a/test/scripts/typeinfo.py +++ b/test/scripts/typeinfo.py @@ -147,7 +147,7 @@ class TypeInfoTest( unittest.TestCase ): ti = target.module.type("unionTest") self.assertEqual( 0, ti.fieldOffset("m_doubleValue") ) self.assertEqual( 0, ti.fieldOffset("m_bits") ) - self.assertEqual( ti.size(), ti.m_doubleValue.size() ) + self.assertEqual( 12, ti.size() ) def testAsMap(self): ti = target.module.type("enumType") diff --git a/test/targetapp/targetapp.cpp b/test/targetapp/targetapp.cpp index 92f4688..4c716d7 100644 --- a/test/targetapp/targetapp.cpp +++ b/test/targetapp/targetapp.cpp @@ -45,12 +45,14 @@ struct structWithBits { ULONG m_bit0_4 : 5; ULONG m_bit5 : 1; ULONG m_bit6_8 : 3; + ULONG64 m_bit0_60 : 60; }; struct structWitSignBits { LONG m_bit0_4 : 5; LONG m_bit5 : 1; LONG m_bit6_8 : 3; + LONG64 m_bit0_60 : 60; }; @@ -104,8 +106,8 @@ typedef struct structAbstract *pstructAbstract; pstructAbstract g_structAbstract = 0; -structWithBits g_structWithBits = { 4, 1, 5}; -structWitSignBits g_structWithSignBits = { 4, 1, 5 }; +structWithBits g_structWithBits = { 4, 1, 5, 0xFF00000000 }; +structWitSignBits g_structWithSignBits = { 4, 1, 5, -1LL }; structTest g_structTest = { 0, 500, true, 1, NULL }; structTest g_structTest1 = { 0, 500, true, 1, &g_structTest }; From 0b80b372582210cab84645cdd50e292d920d0e40 Mon Sep 17 00:00:00 2001 From: "SND\\EreTIk_cp" Date: Fri, 25 Oct 2013 11:18:42 +0000 Subject: [PATCH 23/30] [0.2.x] fixed: module("mymod").queryVersion(""), AV-exception git-svn-id: https://pykd.svn.codeplex.com/svn@86003 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/win/dbgmod.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pykd/win/dbgmod.cpp b/pykd/win/dbgmod.cpp index 0a32414..0cdd0b9 100644 --- a/pykd/win/dbgmod.cpp +++ b/pykd/win/dbgmod.cpp @@ -379,7 +379,7 @@ std::string getModuleVersionInfo( ULONG64 baseOffset, const std::string &value ) << std::setw(4) << std::setfill('0') << codePages[0].wCodePage << "\\" << value; - ULONG valueLength; + ULONG valueLength = 0; g_dbgEng->symbols->GetModuleVersionInformation( DEBUG_ANY_ID, @@ -389,6 +389,9 @@ std::string getModuleVersionInfo( ULONG64 baseOffset, const std::string &value ) 0, &valueLength ); + if (!valueLength) + return ""; + std::vector valueStr(valueLength); hres = g_dbgEng->symbols->GetModuleVersionInformation( From 976e43a31a9d81d742ddb048573fa5d075c09129 Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Thu, 31 Oct 2013 08:10:01 +0000 Subject: [PATCH 24/30] [0.2.x] added : startProcess routine extra parameter debugChildren [0.2.x] fixed : killProcess correctly detaching from target now git-svn-id: https://pykd.svn.codeplex.com/svn@86120 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgengine.h | 2 +- pykd/pykdver.h | 2 +- pykd/python/pymod.cpp | 5 +++-- pykd/win/dbgps.cpp | 13 +++++++++++-- snippets/pykdmagic.py | 5 ++--- test/scripts/pykdtest.py | 1 - 6 files changed, 18 insertions(+), 10 deletions(-) diff --git a/pykd/dbgengine.h b/pykd/dbgengine.h index f19ee5d..806e783 100644 --- a/pykd/dbgengine.h +++ b/pykd/dbgengine.h @@ -6,7 +6,7 @@ namespace pykd { // manage debug target -ULONG startProcess( const std::wstring &processName ); +ULONG startProcess( const std::wstring &processName, bool debugChildren = false ); ULONG attachProcess( ULONG pid ); void attachKernel( const std::string &connectOptions = "" ); bool isLocalKernelDebuggerEnabled(); diff --git a/pykd/pykdver.h b/pykd/pykdver.h index b4c8e7c..e2e9113 100644 --- a/pykd/pykdver.h +++ b/pykd/pykdver.h @@ -2,7 +2,7 @@ #define PYKD_VERSION_MAJOR 0 #define PYKD_VERSION_MINOR 2 #define PYKD_VERSION_SUBVERSION 0 -#define PYKD_VERSION_BUILDNO 25 +#define PYKD_VERSION_BUILDNO 26 #define __VER_STR2__(x) #x diff --git a/pykd/python/pymod.cpp b/pykd/python/pymod.cpp index c02d8d6..412a4a8 100644 --- a/pykd/python/pymod.cpp +++ b/pykd/python/pymod.cpp @@ -38,6 +38,7 @@ static const std::string pykdVersion = PYKD_VERSION_BUILD_STR //////////////////////////////////////////////////////////////////////////////// +BOOST_PYTHON_FUNCTION_OVERLOADS( startProcess_, startProcess, 1, 2 ); BOOST_PYTHON_FUNCTION_OVERLOADS( attachKernel_, attachKernel, 0, 1 ); BOOST_PYTHON_FUNCTION_OVERLOADS( detachProcess_, detachProcess, 0, 1 ); @@ -90,8 +91,8 @@ BOOST_PYTHON_MODULE( pykd ) // Manage debug target - python::def( "startProcess", &startProcess, - "Start process for debugging" ); + python::def( "startProcess", &startProcess, startProcess_( boost::python::args( "commandline", "debugChildren" ), + "Start process for debugging" ) ); python::def( "attachProcess", &attachProcess, "Attach debugger to a exsisting process" ); python::def( "attachKernel", &attachKernel, attachKernel_( boost::python::args( "connectOptions" ), diff --git a/pykd/win/dbgps.cpp b/pykd/win/dbgps.cpp index 474f5d7..745ebed 100644 --- a/pykd/win/dbgps.cpp +++ b/pykd/win/dbgps.cpp @@ -13,7 +13,7 @@ namespace pykd { /////////////////////////////////////////////////////////////////////////////////// -ULONG startProcess( const std::wstring &processName ) +ULONG startProcess( const std::wstring &processName, bool debugChildren ) { PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); @@ -32,7 +32,12 @@ ULONG startProcess( const std::wstring &processName ) std::vector< std::wstring::value_type > cmdLine( processName.size() + 1 ); wcscpy_s( &cmdLine[0], cmdLine.size(), processName.c_str() ); - hres = g_dbgEng->client->CreateProcessWide( 0, &cmdLine[0], DEBUG_PROCESS | DETACHED_PROCESS ); + hres = g_dbgEng->client->CreateProcessWide( + 0, + &cmdLine[0], + ( debugChildren ? DEBUG_PROCESS : DEBUG_ONLY_THIS_PROCESS) | DETACHED_PROCESS + ); + if ( FAILED( hres ) ) throw DbgException( "IDebugClient4::CreateProcessWide failed" ); @@ -159,6 +164,10 @@ void terminateProcess( ULONG processId ) if ( FAILED( hres ) ) throw DbgException( "IDebugClient::TerminateCurrentProcess", hres ); + hres = g_dbgEng->client->DetachCurrentProcess(); + if ( FAILED( hres ) ) + throw DbgException( "IDebugClient::DetachCurrentProcess failed" ); + } /////////////////////////////////////////////////////////////////////////////// diff --git a/snippets/pykdmagic.py b/snippets/pykdmagic.py index a000ad0..427d11c 100644 --- a/snippets/pykdmagic.py +++ b/snippets/pykdmagic.py @@ -7,7 +7,7 @@ class PykdMagic (Magics): @line_magic def kd(self,line): - "any windbg command" + "magic for calling any windbg command" try: pykd.dprintln( pykd.dbgCommand(line) ) except pykd.BaseException: @@ -18,6 +18,5 @@ def load_ipython_extension(ipython): ipython.register_magics(PykdMagic) def unload_ipython_extension(ipython): - pass - + pass diff --git a/test/scripts/pykdtest.py b/test/scripts/pykdtest.py index aa2535b..25f7517 100644 --- a/test/scripts/pykdtest.py +++ b/test/scripts/pykdtest.py @@ -37,7 +37,6 @@ class StartProcessWithoutParamsTest(unittest.TestCase): class TerminateProcessTest(unittest.TestCase): def testKill(self): pykd.killProcess( target.processId ) - pykd.detachProcess( target.processId ) def getTestSuite( singleName = "" ): if singleName == "": From 6f7c574b6b8c1e6ba6671d589904936253b79644 Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Tue, 5 Nov 2013 06:08:27 +0000 Subject: [PATCH 25/30] [0.2.x] added : detachAllProcesses ( detach from all process and resume all their threads ) [0.2.x] added : killAllProcesses ( detach from all process then terminate them ) git-svn-id: https://pykd.svn.codeplex.com/svn@86269 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgengine.h | 2 ++ pykd/python/pymod.cpp | 4 ++++ pykd/win/dbgps.cpp | 34 +++++++++++++++++++++++++++++++++- 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/pykd/dbgengine.h b/pykd/dbgengine.h index 806e783..e880f5c 100644 --- a/pykd/dbgengine.h +++ b/pykd/dbgengine.h @@ -12,6 +12,8 @@ void attachKernel( const std::string &connectOptions = "" ); bool isLocalKernelDebuggerEnabled(); void detachProcess( ULONG processId = -1); void terminateProcess( ULONG processId = -1); +void detachAllProcesses(); +void terminateAllProcesses(); void loadDump( const std::wstring &fileName ); void writeDump( const std::wstring &fileNamem, bool smallDump ); diff --git a/pykd/python/pymod.cpp b/pykd/python/pymod.cpp index 412a4a8..1a63a3b 100644 --- a/pykd/python/pymod.cpp +++ b/pykd/python/pymod.cpp @@ -102,8 +102,12 @@ BOOST_PYTHON_MODULE( pykd ) "Check whether kernel debugging is enabled for the local kernel" ); python::def( "detachProcess", &detachProcess, detachProcess_( boost::python::args( "pid" ), "Stop process debugging") ); + python::def( "detachAllProcesses", &detachAllProcesses, + "Detach from all process and resume all their threads" ); python::def( "killProcess", &terminateProcess, "Stop debugging and terminate current process" ); + python::def( "killAllProcesses", &terminateAllProcesses, + "Detach from all process then terminate them"); python::def( "loadDump", &loadDump, "Load crash dump"); python::def( "isDumpAnalyzing", &isDumpAnalyzing, diff --git a/pykd/win/dbgps.cpp b/pykd/win/dbgps.cpp index 745ebed..2644aad 100644 --- a/pykd/win/dbgps.cpp +++ b/pykd/win/dbgps.cpp @@ -166,7 +166,39 @@ void terminateProcess( ULONG processId ) hres = g_dbgEng->client->DetachCurrentProcess(); if ( FAILED( hres ) ) - throw DbgException( "IDebugClient::DetachCurrentProcess failed" ); + throw DbgException( "IDebugClient::DetachCurrentProcess", hres ); + +} + +/////////////////////////////////////////////////////////////////////////////// + +void detachAllProcesses() +{ + PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); + + HRESULT hres; + + hres = g_dbgEng->client->DetachProcesses(); + + if ( FAILED(hres) ) + throw DbgException( "IDebugClient::DetachProcesses", hres ); +} + +/////////////////////////////////////////////////////////////////////////////// + +void terminateAllProcesses() +{ + PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); + + HRESULT hres; + + hres = g_dbgEng->client->TerminateProcesses(); + if ( FAILED(hres) ) + throw DbgException( "IDebugClient::TerminateProcesses", hres ); + + hres = g_dbgEng->client->DetachProcesses(); + if ( FAILED(hres) ) + throw DbgException( "IDebugClient::DetachProcesses", hres ); } From aefe5b470678e2b7d011ecf96950e029e790820b Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Fri, 6 Dec 2013 07:08:32 +0000 Subject: [PATCH 26/30] [0.2.x] fixed : issue #12559 ( wrong enum value ) git-svn-id: https://pykd.svn.codeplex.com/svn@86720 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dia/diasymbol.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pykd/dia/diasymbol.cpp b/pykd/dia/diasymbol.cpp index 03d3690..75c468b 100644 --- a/pykd/dia/diasymbol.cpp +++ b/pykd/dia/diasymbol.cpp @@ -383,7 +383,7 @@ void DiaSymbol::getValue( BaseTypeVariant &btv ) break; case VT_BOOL: - btv = !!vtValue.iVal; + btv = !!vtValue.boolVal; break; case VT_I2: @@ -391,7 +391,7 @@ void DiaSymbol::getValue( BaseTypeVariant &btv ) break; case VT_UI2: - btv = (ULONG)vtValue.iVal; + btv = (ULONG)vtValue.uiVal; break; case VT_I4: From 27d8ce7296abc4b60063316de57f661777ae45c9 Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Fri, 13 Dec 2013 16:29:51 +0000 Subject: [PATCH 27/30] [0.2.x] added: test for issue #12591 ( typeBuilder generates a error alignment for array fields ) git-svn-id: https://pykd.svn.codeplex.com/svn@86824 9b283d60-5439-405e-af05-b73fd8c4d996 --- test/scripts/customtypestest.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/test/scripts/customtypestest.py b/test/scripts/customtypestest.py index bd702ed..41e162f 100644 --- a/test/scripts/customtypestest.py +++ b/test/scripts/customtypestest.py @@ -129,5 +129,20 @@ class CustomTypesTest(unittest.TestCase): mySubStruct.append( "m_uint2", tb.UInt2B ) mySubStructPtr = mySubStruct.ptrTo() self.assertEqual( pykd.ptrSize(), mySubStructPtr.size() ) - - + + def testAlign(self): + tb = pykd.typeBuilder() + struct = tb.createStruct(name ="MyAlignStruct", align=4) + struct.append( "m_field1", tb.UInt1B ) + self.assertEqual( 1, struct.size() ) + struct.append( "m_field2", tb.UInt1B ) + self.assertEqual( 2, struct.size() ) + struct.append( "m_field3", tb.UInt1B ) + struct.append( "m_field4", tb.UInt2B ) + self.assertEqual( 6, struct.size() ) + struct.append( "m_field5", tb.UInt4B ) + self.assertEqual( 12, struct.size() ) + struct.append( "m_field6", tb.UInt1B ) + self.assertEqual( 16, struct.size() ) + struct.append( "m_field7", tb.UInt1B.arrayOf(5) ) + self.assertEqual( 20, struct.size() ) From c2c1ec1592d8a1fb8d71c1f665f07a31748475d0 Mon Sep 17 00:00:00 2001 From: "SND\\EreTIk_cp" Date: Tue, 17 Dec 2013 13:38:07 +0000 Subject: [PATCH 28/30] [0.2.x] fixed: issue #12591, issue #12592. ~typeBuilder: alignment-requirement implemented git-svn-id: https://pykd.svn.codeplex.com/svn@86871 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/customtypes.cpp | 217 +++++--------------------------- pykd/customtypes.h | 125 ++---------------- pykd/typeinfo.cpp | 29 +++-- pykd/typeinfo.h | 52 ++++---- test/scripts/customtypestest.py | 33 +++-- 5 files changed, 110 insertions(+), 346 deletions(-) diff --git a/pykd/customtypes.cpp b/pykd/customtypes.cpp index be646a4..3491d8c 100644 --- a/pykd/customtypes.cpp +++ b/pykd/customtypes.cpp @@ -7,7 +7,6 @@ namespace pykd { - //////////////////////////////////////////////////////////////////////////////// TypeInfoPtr TypeBuilder::createStruct( const std::string &name, ULONG align ) @@ -24,20 +23,31 @@ TypeInfoPtr TypeBuilder::createUnion( const std::string &name ) //////////////////////////////////////////////////////////////////////////////// +ULONG CustomBase::getSize() +{ + return alignUp( m_size, getAlignReq() ); +} + +//////////////////////////////////////////////////////////////////////////////// + +ULONG CustomBase::alignUp(ULONG val, ULONG align) +{ + return val + (val % align ? align - (val % align) : 0); +} + +//////////////////////////////////////////////////////////////////////////////// + void CustomBase::throwIfFiledExist(const std::string &fieldName) { - bool fieldExist = false; try { lookupField(fieldName); - fieldExist = true; } catch (const TypeException&) { + return; } - - if (fieldExist) - throw TypeException(getName(), "duplicate field name: " + fieldName); + throw TypeException(getName(), "duplicate field name: " + fieldName); } //////////////////////////////////////////////////////////////////////////////// @@ -50,56 +60,44 @@ void CustomBase::throwIfTypeRecursive(TypeInfoPtr type) if ( !type->isUserDefined() ) return; - try - { - const ULONG fields = type->getFieldCount(); - for (ULONG i = 0; i < fields; ++i) - { - TypeInfoPtr fileldType = type->getFieldByIndex(i); - if (fileldType->is(this)) - throw TypeException(getName(), "wrong type of field"); - - throwIfTypeRecursive(fileldType); - } - } - catch (const TypeException &except) - { - DBG_UNREFERENCED_PARAMETER(except); - } + const ULONG fields = type->getFieldCount(); + for (ULONG i = 0; i < fields; ++i) + throwIfTypeRecursive(type->getFieldByIndex(i)); } -//////////////////////////////////////////////////////////////////////////////// - -void CustomStruct::appendField(const std::string &fieldName, TypeInfoPtr &fieldType ) +void CustomBase::checkAppendField(const std::string &fieldName, TypeInfoPtr &fieldType) { if ( !fieldType ) throw DbgException( "typeInfo can not be None" ); throwIfFiledExist(fieldName); throwIfTypeRecursive(fieldType); +} + +//////////////////////////////////////////////////////////////////////////////// + +void CustomStruct::appendField(const std::string &fieldName, TypeInfoPtr &fieldType) +{ + checkAppendField(fieldName, fieldType); CustomUdtField *field = new CustomUdtField( fieldType, fieldName ); - ULONG fieldSize = fieldType->getSize(); - ULONG offset = m_size; - ULONG align = fieldSize < m_align ? fieldSize : m_align; + const ULONG fieldAlignReq = fieldType->getAlignReq(); + const ULONG align = fieldAlignReq < m_align ? fieldAlignReq : m_align; + const ULONG fieldOffset = alignUp(m_size, align); - if (align) - offset += offset % align > 0 ? align - offset % align : 0; + field->setOffset( fieldOffset ); - field->setOffset( offset ); - - m_size = offset + fieldSize; + m_size = fieldOffset + fieldType->getSize(); m_fields.push_back( UdtFieldPtr( field ) ); } //////////////////////////////////////////////////////////////////////////////// -void CustomUnion::appendField(const std::string &fieldName, TypeInfoPtr &fieldType ) +void CustomUnion::appendField(const std::string &fieldName, TypeInfoPtr &fieldType) { - throwIfFiledExist(fieldName); - throwIfTypeRecursive(fieldType); + checkAppendField(fieldName, fieldType); CustomUdtField *field = new CustomUdtField( fieldType, fieldName ); @@ -112,153 +110,6 @@ void CustomUnion::appendField(const std::string &fieldName, TypeInfoPtr &fieldTy //////////////////////////////////////////////////////////////////////////////// - - - - - - - - - -////////////////////////////////////////////////////////////////////////////////// -// -//CustomTypeBase::CustomTypeBase(const std::string &name, ULONG pointerSize) -// : UdtFieldColl(name) -//{ -// m_ptrSize = pointerSize ? pointerSize : ptrSize(); -//} -// -////////////////////////////////////////////////////////////////////////////////// -// -//void CustomTypeBase::throwIfFiledExist(const std::string &fieldName) -//{ -// bool fieldExist = false; -// try -// { -// lookupField(fieldName); -// fieldExist = true; -// } -// catch (const TypeException &except) -// { -// DBG_UNREFERENCED_PARAMETER(except); -// } -// if (fieldExist) -// throw TypeException(getName(), "duplicate field name: " + fieldName); -//} -// -////////////////////////////////////////////////////////////////////////////////// -// -//void CustomTypeBase::throwIfTypeRecursive(TypeInfoPtr type) -//{ -// if (type->is(this)) -// throw TypeException(getName(), "wrong type of field"); -// -// return throwIfTypeRecursiveImpl(type); -//} -// -////////////////////////////////////////////////////////////////////////////////// -// -//void CustomTypeBase::throwIfTypeRecursiveImpl(TypeInfoPtr type) -//{ -// if (type->isEnum()) -// return; -// -// try -// { -// const ULONG fields = type->getFieldCount(); -// for (ULONG i = 0; i < fields; ++i) -// { -// TypeInfoPtr fileldType = type->getFieldByIndex(i); -// if (fileldType->is(this)) -// throw TypeException(getName(), "wrong type of field"); -// -// throwIfTypeRecursiveImpl(fileldType); -// } -// } -// catch (const TypeException &except) -// { -// DBG_UNREFERENCED_PARAMETER(except); -// } -//} -// -////////////////////////////////////////////////////////////////////////////////// -// -//TypeInfoPtr CustomStruct::create( -// const std::string &name, -// ULONG alignReq /*= 0*/, -// ULONG pointerSize /*= 0*/) -//{ -// return TypeInfoPtr( new CustomStruct(name, alignReq, pointerSize) ); -//} -// -////////////////////////////////////////////////////////////////////////////////// -// -//ULONG CustomStruct::getSize() -//{ -// if (Base::empty()) -// return 0; -// -// UdtUtils::Field &field = Base::last(); -// return field.m_offset + field.m_type->getSize(); -//} -// -////////////////////////////////////////////////////////////////////////////////// -// -//void CustomStruct::appendField(const std::string &fieldName, TypeInfoPtr fieldType) -//{ -// Base::throwIfFiledExist(fieldName); -// Base::throwIfTypeRecursive(fieldType); -// -// ULONG offset = getSize(); -// offset += offset % (m_align ? m_align : fieldType->getAlignReq()); -// Base::push_back( -// UdtUtils::Field(offset, fieldName, fieldType) -// ); -//} -// -////////////////////////////////////////////////////////////////////////////////// -// -//TypeInfoPtr CustomUnion::create(const std::string &name, ULONG pointerSize /*= 0*/) -//{ -// return TypeInfoPtr( new CustomUnion(name, pointerSize) ); -//} -// -////////////////////////////////////////////////////////////////////////////////// -// -//ULONG CustomUnion::getSize() -//{ -// ULONG size = 0; -// for (ULONG i = 0; i < getFieldCount(); ++i) -// { -// ULONG fieldSize = lookupField(i).m_type->getSize(); -// if (fieldSize > size) -// size = fieldSize; -// } -// return size; -//} -// -////////////////////////////////////////////////////////////////////////////////// -// -//void CustomUnion::appendField(const std::string &fieldName, TypeInfoPtr fieldType) -//{ -// Base::throwIfFiledExist(fieldName); -// Base::throwIfTypeRecursive(fieldType); -// -// Base::push_back( -// UdtUtils::Field(0, fieldName, fieldType) -// ); -//} -// -////////////////////////////////////////////////////////////////////////////////// -// -//TypeInfoPtr PtrToVoid() -//{ -// return TypeInfoPtr( new PointerTypeInfo(ptrSize()) ); -//} - -//////////////////////////////////////////////////////////////////////////////// - } // namespace pykd //////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/customtypes.h b/pykd/customtypes.h index 462b479..3015e18 100644 --- a/pykd/customtypes.h +++ b/pykd/customtypes.h @@ -53,9 +53,12 @@ private: class CustomBase : public UdtTypeInfoBase { +public: + + virtual ULONG getSize(); protected: - + CustomBase( const std::string &name, ULONG pointerSize, ULONG align ) : UdtTypeInfoBase( name ) { @@ -64,14 +67,12 @@ protected: m_size = 0; } + static ULONG alignUp(ULONG val, ULONG align); + void throwIfFiledExist(const std::string &fieldName); void throwIfTypeRecursive(TypeInfoPtr type); -protected: - - virtual ULONG getSize() { - return m_size; - } + void checkAppendField(const std::string &fieldName, TypeInfoPtr &fieldType); protected: @@ -85,15 +86,12 @@ protected: class CustomStruct : public CustomBase { public: - + CustomStruct( const std::string &name, ULONG ptrSize, ULONG align ) : CustomBase( name, ptrSize, align ) {} -private: - - virtual void appendField(const std::string &fieldName, TypeInfoPtr &fieldType ); - + virtual void appendField(const std::string &fieldName, TypeInfoPtr &fieldType); }; //////////////////////////////////////////////////////////////////////////////// @@ -101,115 +99,14 @@ private: class CustomUnion : public CustomBase { public: - + CustomUnion( const std::string &name, ULONG ptrSize, ULONG align ) : CustomBase( name, ptrSize, align ) {} -private: - - virtual void appendField(const std::string &fieldName, TypeInfoPtr &fieldType ); - + virtual void appendField(const std::string &fieldName, TypeInfoPtr &fieldType); }; -//////////////////////////////////////////////////////////////////////////////// - - - - - - - - - - - - - - - - - - - - -// -////////////////////////////////////////////////////////////////////////////////// -// -//class CustomTypeBase : public UdtFieldColl -//{ -// typedef UdtFieldColl Base; -//protected: -// CustomTypeBase(const std::string &name, ULONG pointerSize); -// -// void throwIfFiledExist(const std::string &fieldName); -// void throwIfTypeRecursive(TypeInfoPtr type); -// -//private: -// void throwIfTypeRecursiveImpl(TypeInfoPtr type); -//}; -// -////////////////////////////////////////////////////////////////////////////////// -// -//class CustomStruct : public CustomTypeBase -//{ -// typedef CustomTypeBase Base; -//public: -// static TypeInfoPtr create(const std::string &name, ULONG align = 0, ULONG pointerSize = 0); -// -//protected: -// CustomStruct(const std::string &name, ULONG align, ULONG pointerSize) -// : Base(name, pointerSize), m_name(name), m_align(align) -// { -// } -// -// virtual std::string getName() override { -// return m_name; -// } -// -// virtual ULONG getSize() override; -// -// virtual void appendField(const std::string &fieldName, TypeInfoPtr fieldType) override; -// -// virtual std::string getTypeString() const override { -// return "custom struct"; -// } -// -//private: -// std::string m_name; -// ULONG m_align; -//}; -// -////////////////////////////////////////////////////////////////////////////////// -// -//class CustomUnion : public CustomTypeBase -//{ -// typedef CustomTypeBase Base; -//public: -// static TypeInfoPtr create(const std::string &name, ULONG pointerSize = 0); -// -//protected: -// CustomUnion(const std::string &name, ULONG pointerSize) -// : Base(name, pointerSize) -// { -// } -// -// virtual ULONG getSize() override; -// -// virtual void appendField(const std::string &fieldName, TypeInfoPtr fieldType) override; -// -// virtual std::string getTypeString() const override { -// return "custom union"; -// } -// -//private: -// std::string m_name; -//}; -// -////////////////////////////////////////////////////////////////////////////////// -// -//TypeInfoPtr PtrToVoid(); -// ////////////////////////////////////////////////////////////////////////////////// } // namespace pykd diff --git a/pykd/typeinfo.cpp b/pykd/typeinfo.cpp index a47827c..bc5c486 100644 --- a/pykd/typeinfo.cpp +++ b/pykd/typeinfo.cpp @@ -721,20 +721,6 @@ std::string UdtTypeInfoBase::print() ///////////////////////////////////////////////////////////////////////////////////// -ULONG UdtTypeInfoBase::getAlignReq() -{ - //ULONG alignReq = 1; - //const ULONG fieldCount = getFieldCount(); - //for ( ULONG i = 0; i < fieldCount; ++i ) - // alignReq = max(alignReq, lookupField(i).m_type->getAlignReq()); - - //return alignReq; - - throw ImplementException( __FILE__, __LINE__, "TODO" ); -} - -///////////////////////////////////////////////////////////////////////////////////// - void UdtTypeInfoBase::getVirtualDisplacement( const std::string& fieldName, ULONG &virtualBasePtr, ULONG &virtualDispIndex, ULONG &virtualDispSize ) { const UdtFieldPtr &field = lookupField(fieldName); @@ -747,7 +733,7 @@ void UdtTypeInfoBase::getVirtualDisplacement( const std::string& fieldName, ULON ///////////////////////////////////////////////////////////////////////////////////// -void UdtTypeInfoBase::getVirtualDisplacementByIndex( ULONG index, ULONG &virtualBasePtr, ULONG &virtualDispIndex, ULONG &virtualDispSize ) +void UdtTypeInfoBase::getVirtualDisplacementByIndex( ULONG index, ULONG &virtualBasePtr, ULONG &virtualDispIndex, ULONG &virtualDispSize ) { const UdtFieldPtr &field = lookupField(index); @@ -759,6 +745,19 @@ void UdtTypeInfoBase::getVirtualDisplacementByIndex( ULONG index, ULONG &virtua ///////////////////////////////////////////////////////////////////////////////////// +ULONG UdtTypeInfoBase::getAlignReq() +{ + ULONG alignReq = 1; + for (ULONG i = 0; i < getFieldCount(); ++i) + { + const ULONG fieldAlignReq = getFieldByIndex(i)->getAlignReq(); + alignReq = (fieldAlignReq > alignReq) ? fieldAlignReq : alignReq; + } + return alignReq; +} + +///////////////////////////////////////////////////////////////////////////////////// + void UdtTypeInfo::getFields( SymbolPtr &rootSym, SymbolPtr &baseVirtualSym, diff --git a/pykd/typeinfo.h b/pykd/typeinfo.h index d0aa827..ca83690 100644 --- a/pykd/typeinfo.h +++ b/pykd/typeinfo.h @@ -215,10 +215,6 @@ public: TypeInfoPtr arrayOf( ULONG count ); - virtual ULONG getAlignReq() { - return 1; - } - void setConstant( const BaseTypeVariant& var ) { m_constant = true; @@ -237,6 +233,10 @@ public: return m_ptrSize; } + // http://msdn.microsoft.com/en-us/library/hx1b6kkd.aspx + // "Padding and Alignment of Structure Members" + virtual ULONG getAlignReq() = 0; + protected: std::string getComplexName(); @@ -266,7 +266,11 @@ public: m_ptrSize = pointerSize; } -private: + virtual ULONG getAlignReq() { + return getSize(); + } + +protected: virtual std::string getName() { return m_name; @@ -285,6 +289,8 @@ private: return t < 0; } +private: + std::string m_name; }; @@ -321,14 +327,14 @@ public: return m_bitWidth; } - virtual ULONG getAlignReq() override { - return m_size; - } - virtual bool isSigned() { return m_signed; } + virtual ULONG getAlignReq() { + return getSize(); + } + private: bool m_signed; @@ -410,8 +416,6 @@ protected: return true; } - virtual ULONG getAlignReq() override; - virtual bool isVirtualMember( const std::string& fieldName ) { return lookupField(fieldName)->isVirtualMember(); @@ -425,6 +429,8 @@ protected: virtual void getVirtualDisplacement( const std::string& fieldName, ULONG &virtualBasePtr, ULONG &virtualDispIndex, ULONG &virtualDispSize ); virtual void getVirtualDisplacementByIndex( ULONG index, ULONG &virtualBasePtr, ULONG &virtualDispIndex, ULONG &virtualDispSize ); + virtual ULONG getAlignReq(); + protected: UdtTypeInfoBase(const std::string &typeName) : @@ -512,6 +518,10 @@ public: m_dia( symbol ) {} + virtual ULONG getAlignReq() { + return getSize(); + } + protected: virtual std::string getName() { @@ -538,10 +548,6 @@ protected: virtual std::string print(); - virtual ULONG getAlignReq() override { - return getSize(); - } - virtual ULONG getElementCount() { return getFieldCount(); } @@ -583,10 +589,6 @@ public: return getDerefType(); } - virtual ULONG getAlignReq() override { - return m_size; - } - TypeInfoPtr getDerefType() { if (!m_derefType) throw TypeException("", "this pointer can not be dereferenced"); @@ -603,6 +605,10 @@ public: return m_derefName; } + virtual ULONG getAlignReq() { + return getSize(); + } + private: static std::string VoidTypeName; @@ -652,14 +658,14 @@ public: return m_derefType; } - virtual ULONG getAlignReq() override { - return m_derefType->getAlignReq(); - } - TypeInfoPtr getDerefType() { return m_derefType; } + virtual ULONG getAlignReq() { + return getDerefType()->getAlignReq(); + } + private: TypeInfoPtr m_derefType; diff --git a/test/scripts/customtypestest.py b/test/scripts/customtypestest.py index 41e162f..6280c92 100644 --- a/test/scripts/customtypestest.py +++ b/test/scripts/customtypestest.py @@ -6,9 +6,8 @@ import pykd class CustomTypesTest(unittest.TestCase): def testCommonStruct(self): - tb = pykd.typeBuilder() - + mySubStruct =tb.createStruct("MySubCustomStruct") mySubStruct.append( "m_uint1", tb.UInt1B ) mySubStruct.append( "m_uint2", tb.UInt2B ) @@ -42,12 +41,9 @@ class CustomTypesTest(unittest.TestCase): self.assertTrue( myType.fieldOffset("m_struct") < myType.fieldOffset("m_union") ) self.assertTrue( myType.fieldOffset("m_struct") + myType.m_struct.size() <= myType.fieldOffset("m_union") ) - # print myType - def testCommonUnion(self): - tb = pykd.typeBuilder() - + myType = tb.createUnion("MyCustomStruct") myType.append( "m_uint1", tb.UInt1B ) myType.append( "m_uint4", tb.UInt4B ) @@ -77,9 +73,8 @@ class CustomTypesTest(unittest.TestCase): self.assertEqual( 0, myEmptyUnion1.size() ) def testDupFieldName(self): - tb = pykd.typeBuilder() - + myType = tb.createStruct("MyCustomStruct") exceptionRised = False myType.append( "m_uint1", tb.UInt1B ) @@ -97,7 +92,7 @@ class CustomTypesTest(unittest.TestCase): except pykd.TypeException: exceptionRised = True self.assertTrue(exceptionRised) - + def testBasicType(self): tb = pykd.typeBuilder() self.assertEqual( 1, tb.UInt1B.size() ) @@ -121,7 +116,7 @@ class CustomTypesTest(unittest.TestCase): self.assertEqual( 4, pykd.typeBuilder(4).UInt1B.ptrTo().size() ) self.assertEqual( 8, pykd.typeBuilder(8).UInt1B.ptrTo().size() ) self.assertEqual( pykd.ptrSize(), pykd.typeBuilder().UInt1B.ptrTo().size() ) - + def testPtrToCustomType(self): tb = pykd.typeBuilder() mySubStruct =tb.createStruct("MySubCustomStruct") @@ -129,7 +124,7 @@ class CustomTypesTest(unittest.TestCase): mySubStruct.append( "m_uint2", tb.UInt2B ) mySubStructPtr = mySubStruct.ptrTo() self.assertEqual( pykd.ptrSize(), mySubStructPtr.size() ) - + def testAlign(self): tb = pykd.typeBuilder() struct = tb.createStruct(name ="MyAlignStruct", align=4) @@ -146,3 +141,19 @@ class CustomTypesTest(unittest.TestCase): self.assertEqual( 16, struct.size() ) struct.append( "m_field7", tb.UInt1B.arrayOf(5) ) self.assertEqual( 20, struct.size() ) + + def testWi12591(self): + tb = pykd.typeBuilder() + struct = tb.createStruct(name ="MyAlignStruct", align=4) + struct.append( "m_field1", tb.UInt1B ) + struct.append( "m_field2", tb.UInt1B.arrayOf(2) ) + self.assertEqual( struct.size(), 3 ) + self.assertEqual( struct.fieldOffset("m_field2"), 1 ) + + def testWi12592(self): + tb = pykd.typeBuilder() + struct = tb.createStruct(name ="MyAlignStruct", align=4) + struct.append( "field1", tb.UInt4B ) + struct.append( "field2", tb.UInt1B ) + self.assertEqual( struct.size(), 8 ) + self.assertEqual( struct.fieldOffset("field2"), 4 ) From ae1e83e9d5182df7a1eb0ad28304dd7af8ef43e0 Mon Sep 17 00:00:00 2001 From: "SND\\EreTIk_cp" Date: Tue, 17 Dec 2013 14:13:48 +0000 Subject: [PATCH 29/30] [0.2.x] + align for custom union git-svn-id: https://pykd.svn.codeplex.com/svn@86872 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/customtypes.cpp | 8 ++++---- pykd/customtypes.h | 4 ++-- pykd/python/pymod.cpp | 5 +++-- test/scripts/customtypestest.py | 8 ++++++++ 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/pykd/customtypes.cpp b/pykd/customtypes.cpp index 3491d8c..32d9351 100644 --- a/pykd/customtypes.cpp +++ b/pykd/customtypes.cpp @@ -9,16 +9,16 @@ namespace pykd { //////////////////////////////////////////////////////////////////////////////// -TypeInfoPtr TypeBuilder::createStruct( const std::string &name, ULONG align ) +TypeInfoPtr TypeBuilder::createStruct( const std::string &name, ULONG align ) { - return TypeInfoPtr( new CustomStruct( name, m_ptrSize, align ? align : m_ptrSize ) ); + return TypeInfoPtr( new CustomStruct( name, m_ptrSize, align ) ); } //////////////////////////////////////////////////////////////////////////////// -TypeInfoPtr TypeBuilder::createUnion( const std::string &name ) +TypeInfoPtr TypeBuilder::createUnion( const std::string &name, ULONG align ) { - return TypeInfoPtr( new CustomUnion( name, m_ptrSize, m_ptrSize ) ); + return TypeInfoPtr( new CustomUnion( name, m_ptrSize, align ) ); } //////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/customtypes.h b/pykd/customtypes.h index 3015e18..75344fc 100644 --- a/pykd/customtypes.h +++ b/pykd/customtypes.h @@ -41,7 +41,7 @@ public: TypeInfoPtr createStruct( const std::string &name, ULONG align = 0 ); - TypeInfoPtr createUnion( const std::string &name); + TypeInfoPtr createUnion( const std::string &name, ULONG align = 0); private: @@ -63,7 +63,7 @@ protected: UdtTypeInfoBase( name ) { m_ptrSize = pointerSize; - m_align = align; + m_align = align ? align : m_ptrSize; m_size = 0; } diff --git a/pykd/python/pymod.cpp b/pykd/python/pymod.cpp index 1a63a3b..e9e613a 100644 --- a/pykd/python/pymod.cpp +++ b/pykd/python/pymod.cpp @@ -69,6 +69,7 @@ BOOST_PYTHON_FUNCTION_OVERLOADS( setHardwareBp_, setHardwareBp, 3, 4 ); BOOST_PYTHON_FUNCTION_OVERLOADS( findSymbol_, TypeInfo::findSymbol, 1, 2 ); BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS( TypeBuilder_createStruct, TypeBuilder::createStruct, 1, 2 ); +BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS( TypeBuilder_createUnion, TypeBuilder::createUnion, 1, 2 ); BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS( Module_enumSymbols, Module::enumSymbols, 0, 1 ); BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS( Module_findSymbol, Module::getSymbolNameByVa, 1, 2 ); @@ -518,8 +519,8 @@ BOOST_PYTHON_MODULE( pykd ) .add_property( "VoidPtr", &TypeBuilder::getVoidPtr ) .def( "createStruct", &TypeBuilder::createStruct, TypeBuilder_createStruct( python::args( "name", "align" ), "Create custom struct" ) ) - .def( "createUnion", &TypeBuilder::createUnion, - "Create custom union" ); + .def( "createUnion", &TypeBuilder::createUnion, TypeBuilder_createUnion( python::args( "name", "align" ), + "Create custom union" ) ); python::class_ >( "cpuReg", "CPU regsiter class", boost::python::no_init ) diff --git a/test/scripts/customtypestest.py b/test/scripts/customtypestest.py index 6280c92..55ab8d7 100644 --- a/test/scripts/customtypestest.py +++ b/test/scripts/customtypestest.py @@ -142,6 +142,14 @@ class CustomTypesTest(unittest.TestCase): struct.append( "m_field7", tb.UInt1B.arrayOf(5) ) self.assertEqual( 20, struct.size() ) + def testUnionAlignedSize(self): + tb = pykd.typeBuilder() + union = tb.createUnion("MyCustomUnion", align=4) + union.append( "m_field1", tb.UInt2B ) + self.assertEqual( 2, union.size() ) + union.append( "m_field2", tb.UInt1B.arrayOf(3) ) + self.assertEqual( 4, union.size() ) + def testWi12591(self): tb = pykd.typeBuilder() struct = tb.createStruct(name ="MyAlignStruct", align=4) From 9ac635b5d37266a3908b2067e2ae2bf624f33c2a Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Fri, 20 Dec 2013 10:45:38 +0000 Subject: [PATCH 30/30] [0.2.x] fixed : issue #12599 (exception raised when comparing typeInfo with None ) git-svn-id: https://pykd.svn.codeplex.com/svn@86901 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/pykdver.h | 2 +- pykd/variant.h | 25 +++++++++++++++++++++++-- test/scripts/typeinfo.py | 7 +++++++ 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/pykd/pykdver.h b/pykd/pykdver.h index e2e9113..3081774 100644 --- a/pykd/pykdver.h +++ b/pykd/pykdver.h @@ -2,7 +2,7 @@ #define PYKD_VERSION_MAJOR 0 #define PYKD_VERSION_MINOR 2 #define PYKD_VERSION_SUBVERSION 0 -#define PYKD_VERSION_BUILDNO 26 +#define PYKD_VERSION_BUILDNO 27 #define __VER_STR2__(x) #x diff --git a/pykd/variant.h b/pykd/variant.h index a431c5c..9162db9 100644 --- a/pykd/variant.h +++ b/pykd/variant.h @@ -1,5 +1,7 @@ #pragma once +#include "dbgexcept.h" + namespace pykd { typedef boost::variant BaseTypeVariant; @@ -81,6 +83,11 @@ public: } }; +inline bool isConvertable( python::object& obj ) +{ + return PyInt_Check(obj.ptr()) || PyLong_Check(obj.ptr()) || PyBool_Check(obj.ptr()); +} + class intBase { @@ -114,11 +121,25 @@ public: } python::object eq( python::object& obj ) { - return boost::apply_visitor( VariantToPyobj(), getValue() ) == obj; + + try { + return boost::apply_visitor( VariantToPyobj(), getValue() ) == obj; + } + catch( DbgException& ) + {} + + return python::object(false); } python::object ne( python::object& obj ) { - return boost::apply_visitor( VariantToPyobj(), getValue() ) != obj; + + try { + return boost::apply_visitor( VariantToPyobj(), getValue() ) != obj; + } + catch( DbgException& ) + {} + + return python::object(true); } python::object lt( python::object& obj ) { diff --git a/test/scripts/typeinfo.py b/test/scripts/typeinfo.py index 522cffb..0ccae3a 100644 --- a/test/scripts/typeinfo.py +++ b/test/scripts/typeinfo.py @@ -243,3 +243,10 @@ class TypeInfoTest( unittest.TestCase ): def testArrayOf(self): ti = pykd.typeInfo("UInt8B").arrayOf(10) self.assertTrue( "UInt8B[10]", ti.name() ) + + def testCompareWihNone(self): + ti = None + if ti == None: + ti = pykd.typeInfo("UInt8B") + if ti == None: + pass