typeinfo.py 18.9 KB
Newer Older
1
#
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
#
#

import unittest
import target
import pykd

class TypeInfoTest( unittest.TestCase ):

    def testCtor( self ):
        self.assertEqual( "structTest", pykd.typeInfo( "structTest" ).name() )
        self.assertEqual( "structTest", pykd.typeInfo( target.moduleName + "!structTest" ).name() )
        self.assertEqual( "structTest", pykd.typeInfo( "g_structTest" ).name() )
        self.assertEqual( "structTest", pykd.typeInfo( target.moduleName + "!g_structTest" ).name() )     
        self.assertEqual( "Int1B", pykd.typeInfo( "Int1B" ).name() )	
 
    def testCreateByName( self ):
        """ creating typeInfo by the type name """
        self.assertEqual( "Int4B*", target.module.type("Int4B*").name() )
        self.assertEqual( "structTest", target.module.type( "structTest" ).name() )
        self.assertEqual( "structTest**", target.module.type( "structTest**" ).name() )
        self.assertEqual( "Int4B[2][3]", target.module.type("Int4B[2][3]").name() )
        self.assertEqual( "Int4B(*[4])[2][3]", target.module.type("Int4B(*[4])[2][3]").name() )
        self.assertEqual( "Int4B(*)[2][3]", target.module.type("Int4B((*))[2][3]").name() )
        self.assertEqual( "Int4B*", pykd.typeInfo("Int4B*").name() )

    def testCreateBySymbol(self):
        """ creating typeInfo by the symbol name """
        self.assertEqual( "structTest[2]", target.module.type("g_testArray").name() )
        self.assertEqual( "Int4B[2][3]", target.module.type("intMatrix").name() )
        self.assertEqual( "structTest*", target.module.type("g_structTestPtr").name() )
        self.assertEqual( "structTest**", target.module.type("g_structTestPtrPtr").name() )
        self.assertEqual( "Char*[2]", target.module.type("strArray").name() )
        self.assertEqual( "Char*(*)[2]", target.module.type("ptrStrArray").name() )
        self.assertEqual( "Int4B(*[4])[2][3]", target.module.type("arrIntMatrixPtrs").name() )
SND\kernelnet_cp's avatar
SND\kernelnet_cp committed
37
        self.assertEqual( "Int4B(*)[2][3]", target.module.type("ptrIntMatrix").name() )
38 39 40 41

    def testGetField( self ):
        """ get field of the complex type """
        ti1 = target.module.type( "structTest" )
42
        self.assertTrue( "UInt4B", ti1.m_field0.name() )
ussrhero's avatar
ussrhero committed
43 44
        self.assertTrue( "m_field0" in ti1 )
        self.assertFalse( "not_exist" in ti1) # non-exsisting field
ussrhero's avatar
ussrhero committed
45
        self.assertRaises( AttributeError, lambda t: t.not_exists, ti1) # non-exsisting field
46 47


48
    def testBaseTypes( self ):
SND\kernelnet_cp's avatar
SND\kernelnet_cp committed
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
        self.assertEqual("Int1B", pykd.typeInfo( "Int1B" ).name() )
        self.assertEqual("Int2B", pykd.typeInfo( "Int2B" ).name() )
        self.assertEqual("Int4B", pykd.typeInfo( "Int4B" ).name() )
        self.assertEqual("Int8B", pykd.typeInfo( "Int8B" ).name() )
        self.assertEqual("UInt1B", pykd.typeInfo( "UInt1B" ).name() )
        self.assertEqual("UInt2B", pykd.typeInfo( "UInt2B" ).name() )
        self.assertEqual("UInt4B", pykd.typeInfo( "UInt4B" ).name() )
        self.assertEqual("UInt8B", pykd.typeInfo( "UInt8B" ).name() )

        self.assertEqual("Long", pykd.typeInfo( "Long" ).name() )
        self.assertEqual("ULong", pykd.typeInfo( "ULong" ).name() )
        self.assertEqual("Bool", pykd.typeInfo( "Bool" ).name() )
        self.assertEqual("Char", pykd.typeInfo("Char").name() )
        self.assertEqual("WChar", pykd.typeInfo("WChar").name() )

        self.assertEqual( 1, pykd.typeInfo("Int1B").size() )
        self.assertEqual( 1, pykd.typeInfo("UInt1B").size() )
        self.assertEqual( 2, pykd.typeInfo("Int2B").size() )
        self.assertEqual( 2, pykd.typeInfo("UInt2B").size() )
        self.assertEqual( 4, pykd.typeInfo("Int4B").size() )
        self.assertEqual( 4, pykd.typeInfo("UInt4B").size() )
        self.assertEqual( 8, pykd.typeInfo("Int8B").size() )
        self.assertEqual( 8, pykd.typeInfo("UInt8B").size() )

        self.assertEqual( 4, pykd.typeInfo("Long" ).size() )
        self.assertEqual( 4, pykd.typeInfo("ULong" ).size() )
        self.assertEqual( 1, pykd.typeInfo("Bool" ).size() )
        self.assertEqual( 1, pykd.typeInfo("Char").size() )
        self.assertEqual( 2, pykd.typeInfo("WChar").size() )
78 79

        try:
SND\kernelnet_cp's avatar
SND\kernelnet_cp committed
80
            self.assertEqual("Int9B", pykd.typeInfo( "Int9B" ).name() )
81 82 83 84
        except pykd.SymbolException:
            pass
            
    def testBaseTypePtr(self):
SND\kernelnet_cp's avatar
SND\kernelnet_cp committed
85 86
        self.assertEqual("Int1B*", pykd.typeInfo( "Int1B*" ).name() )
        self.assertEqual("Int1B", pykd.typeInfo( "Int1B*" ).deref().name() )
87 88
        
    def testBaseTypeArray(self):
SND\kernelnet_cp's avatar
SND\kernelnet_cp committed
89
        self.assertEqual("Int4B[20]", pykd.typeInfo( "Int4B[20]" ).name() )
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109

    def testName( self ):
        ti1 = target.module.type( "classChild" )
        self.assertEqual( "classChild", ti1.name() )
        self.assertEqual( "Int4B", ti1.m_childField.name() )
        self.assertEqual( "structTest", ti1.m_childField3.name() )
        self.assertEqual( "structTest", target.module.type("g_structTest").name() )
        
    def testVarName( self ):
        self.assertEqual( "structTest", target.module.type( "g_structTest").name() )
        self.assertRaises( pykd.TypeException, target.module.type, "g_testArray[0]" )
        self.assertRaises( pykd.TypeException, target.module.type, "*g_structTestPtr" )

    def testOffset( self ):
        ti1 = target.module.type( "structTest" )
        self.assertEqual( 0, ti1.fieldOffset("m_field0") )
        self.assertEqual( 4, ti1.fieldOffset("m_field1") )
        self.assertEqual( 12, ti1.fieldOffset("m_field2") )
        self.assertEqual( 14, ti1.fieldOffset("m_field3") )

SND\kernelnet_cp's avatar
SND\kernelnet_cp committed
110 111 112 113 114 115
        ti2 = target.module.type( "unionTest" )
        self.assertEqual( 0, ti2.fieldOffset("m_value") )
        self.assertEqual( 0, ti2.fieldOffset("m_structValue") )

        ti3 = target.module.type( "structWithNested" )
        self.assertEqual( ti3.fieldOffset( "m_unnameStruct"), ti3.fieldOffset( "m_unnameStruct.m_field2" ) )
116 117 118 119 120 121 122

    def testSize( self ):
        ti1 = target.module.type( "structTest" )
        self.assertEqual( 16 + pykd.ptrSize(), ti1.size() )
        self.assertEqual( pykd.ptrSize(), target.module.type("structTest**").size() )
        self.assertEqual( pykd.sizeof("structTest"), target.module.type("structTest").size() )
        self.assertEqual( pykd.sizeof("structTest**"), target.module.type("structTest**").size() )
SND\kernelnet_cp's avatar
SND\kernelnet_cp committed
123
        self.assertEqual( pykd.sizeof("Int1B"), pykd.typeInfo("Int1B").size() )
124 125 126 127 128

    def testBitField( self ):
        ti = target.module.type( "g_structWithBits" )
        self.assertEqual( 0, ti.fieldOffset("m_bit6_8") )
        self.assertEqual( 4, ti.m_bit6_8.size() )
SND\kernelnet_cp's avatar
SND\kernelnet_cp committed
129
        self.assertEqual( "UInt4B:3", ti.m_bit6_8.name() )
130 131 132 133 134 135 136 137 138 139 140 141
        self.assertEqual( 3, ti.m_bit6_8.bitWidth() )
        self.assertEqual( 6, ti.m_bit6_8.bitOffset() )

    def testEnum(self):
        ti = target.module.type("enumType")
        self.assertTrue( hasattr( ti, "TWO" ) )
        self.assertEqual( 4, ti.TWO.size() )

        ti = target.module.type("classChild")
        self.assertEqual( "enumType", ti.m_enumField.name() )

    def testPtr(self):
SND\kernelnet_cp's avatar
SND\kernelnet_cp committed
142
        self.assertEqual( "UInt8B*", target.module.type( "pbigValue" ).name() )
SND\kernelnet_cp's avatar
SND\kernelnet_cp committed
143 144
        self.assertEqual( "structTest*", target.module.type( "structTest*" ).name() )
        self.assertEqual( "UInt2B*", pykd.typeInfo( "UInt2B*" ).name() )
SND\kernelnet_cp's avatar
SND\kernelnet_cp committed
145 146 147 148
        self.assertEqual( "Void*",  target.module.type( "voidPtr" ).name() )
        self.assertEqual( "Void*[3]", target.module.type( "voidPtrArray" ).name())
        #self.assertEqual( "<function>*", target.module.type( "g_ptrToFunction" ).name())
        #self.assertEqual( "<function>*[4]", target.module.type( "g_arrOfPtrToFunc" ).name())
149 150 151 152

    def testUnion(self):
        ti = target.module.type("unionTest")
        self.assertEqual( 0, ti.fieldOffset("m_doubleValue") )
SND\kernelnet_cp's avatar
SND\kernelnet_cp committed
153 154 155
        self.assertEqual( 0, ti.fieldOffset("m_value") )
        self.assertEqual( 0, ti.fieldOffset("m_structValue") )
        self.assertEqual( ti.size(), ti.m_structValue.size() )
156 157

    def testDeref(self):
SND\kernelnet_cp's avatar
SND\kernelnet_cp committed
158 159
        ti = pykd.typeInfo("Int1B*")
        self.assertEqual( "Int1B", ti.deref().name() )
160

SND\kernelnet_cp's avatar
SND\kernelnet_cp committed
161 162 163 164
        ti = target.module.type("structTest*")
        self.assertEqual( "structTest", ti.deref().name() )

        ti =  pykd.typeInfo("structTest[2]")
165
        self.assertEqual( "structTest", ti.deref().name() )
166 167

        ti = target.module.type("classChild")
168
        self.assertRaises( pykd.TypeException, ti.deref )
169 170

    def testNestedStruct( self ):
SND\kernelnet_cp's avatar
SND\kernelnet_cp committed
171
        ti = target.module.type("structWithNested")
ussrhero's avatar
ussrhero committed
172 173 174 175 176 177
        self.assertTrue( ti.hasField("m_field"))
        self.assertTrue( ti.hasField("m_field3"))
        self.assertTrue( ti.hasField("m_unnameStruct"))
        self.assertTrue( ti.m_unnameStruct.hasField("m_field2"))
        self.assertFalse( ti.hasField( "m_field2" ) )
        self.assertFalse( ti.hasField( "m_nestedFiled" ) )
SND\kernelnet_cp's avatar
SND\kernelnet_cp committed
178
        ti = target.module.type("structWithNested::Nested")
ussrhero's avatar
ussrhero committed
179
        self.assertTrue( ti.hasField( "m_nestedFiled" ) )
180 181

    def testPrint(self):
SND\kernelnet_cp's avatar
SND\kernelnet_cp committed
182 183 184 185
        self.assertTrue( str(target.module.type( "ucharVar" ) ) )
        self.assertTrue( str(target.module.type( "ushortVar" ) ) )
        self.assertTrue( str(target.module.type( "ulongVar" ) ) )
        self.assertTrue( str(target.module.type( "ulonglongVar" ) ) )
186 187 188 189 190 191 192 193 194 195
        self.assertTrue( str(target.module.type( "g_structWithBits" ) ) )
        self.assertTrue( str(target.module.type( "g_structTest" ) ) )
        self.assertTrue( str(target.module.type( "g_structTest1" ) ) )
        self.assertTrue( str(target.module.type( "g_testArray" ) ) )
        self.assertTrue( str(target.module.type( "g_structTestPtr" ) ) )
        self.assertTrue( str(target.module.type( "g_structTestPtrPtr" ) ) )
        self.assertTrue( str(target.module.type( "longlongArray" ) ) )
        self.assertTrue( str(target.module.type( "intMatrix4" ) ) )
        self.assertTrue( str(target.module.type( "ptrIntMatrix" ) ) )
        self.assertTrue( str(target.module.type( "g_classChild" ) ) )
SND\kernelnet_cp's avatar
SND\kernelnet_cp committed
196 197 198 199
#        self.assertTrue( str(target.module.type( "g_listHead" ) ) )
#        self.assertTrue( str(target.module.type( "g_voidPtr" ) ) )
#        self.assertTrue( str(target.module.type( "g_arrOfPtrToFunc" ) ) )
#        self.assertTrue( str(target.module.type( "g_unTypedPtrToFunction" ) ) )
200

201 202 203 204 205 206 207 208 209 210 211 212 213 214
    def testTypedef(self):
        self.assertEqual( "structTest", pykd.typeInfo( "g_structTypeDef" ).name() )
        self.assertEqual( "structTest", pykd.typeInfo( "structTestTypeDef" ).name() )

    def testStaticField(self):
        ti = pykd.typeInfo( "g_classChild" )
        self.assertNotEqual( 0, ti.staticOffset( "m_staticField" ) )
        self.assertNotEqual( 0, ti.staticOffset("m_stdstr") )
        if not ti.staticOffset("m_staticConst"):
            self.assertFalse( "MS DIA bug: https://connect.microsoft.com/VisualStudio/feedback/details/737430" )

    def testVfnTable(self):
        ti = pykd.typeInfo( "g_classChild" )
        self.assertTrue( hasattr( ti, "__VFN_table" ) )
215

216 217
    def testUdtSubscribe(self):
        ti = pykd.typeInfo( "g_virtChild" )
SND\kernelnet_cp's avatar
SND\kernelnet_cp committed
218
        self.assertEqual( 6, len(ti) )
219 220
        for field in ti:
             str( field )
221

222 223 224
    def testEnumSubscribe(self):
        ti = pykd.typeInfo( "enumType" )
        self.assertEqual( 3, len(ti) )
225
        self.assertEqual( [ 1, 2, 3], [ int(field) for field in ti ] )
226 227
        self.assertEqual( [ ( "ONE", 1), ("TWO", 2), ("THREE", 3) ], ti.fields() )

228 229 230
    def testStructNullSize(self):
        ti = target.module.type("structNullSize")
        self.assertEqual( 0, len(ti) )
231

232
    def testDerefName(self):
SND\kernelnet_cp's avatar
SND\kernelnet_cp committed
233 234
        entry = pykd.typedVar("g_listHead").flink
        self.assertEqual( "listEntry*", entry.type().name() )
235 236

    def testPtrTo(self):
237 238 239
        ti = pykd.typeInfo("UInt8B").ptrTo()
        self.assertTrue( "UInt8B*", ti.name() )
        self.assertNotEqual( 0, ti.size() )
240

241 242
    def testArrayOf(self):
        ti = pykd.typeInfo("UInt8B").arrayOf(10)
243
        self.assertTrue( "UInt8B[10]", ti.name() )
244
        
ussrhero's avatar
ussrhero committed
245
    def testCompareWithNone(self):
246
        ti = pykd.typeInfo("UInt8B")
ussrhero's avatar
ussrhero committed
247 248 249 250
        self.assertFalse(ti == None)
        self.assertTrue(ti != None)
        self.assertFalse(not ti)
        self.assertTrue(ti)
251 252 253 254 255

    def testFunction(self):
        functype = target.module.typedVar( "CdeclFuncPtr" ).type().deref()
        self.assertTrue( functype.isFunction() )

256 257 258
        functype = target.module.typedVar( "g_variadicFuncPtr" ).type().deref()
        self.assertTrue( functype.isFunction() )

259 260 261 262
    def testFunctionArgs(self):
        functype = target.module.typedVar( "CdeclFuncPtr" ).type().deref()
        self.assertEqual( [ arg.name() for arg in functype ], ["Int4B", "Float"] )

263
        functype = target.module.typedVar( "g_variadicFuncPtr" ).type().deref()
264
        self.assertEqual( [ arg.name() for arg in functype ], ["Int4B", "NoType"] )
265

266 267 268 269 270 271 272 273 274 275 276
    def testFunctionCallConv(self):
        functype = target.module.typedVar( "CdeclFuncPtr" ).type().deref()
        self.assertEqual( functype.getCallingConvention(), pykd.callingConvention.NearC )

    def testFunctionThis(self):
        functype = target.module.typedVar( "MethodPtr" ).type().deref()
        self.assertEqual( [ arg.name() for arg in functype ], ["FuncTestClass*"] )

        functype = target.module.typedVar( "CdeclStaticMethodPtr" ).type().deref()
        self.assertEqual( [ arg.name() for arg in functype ], [] )

277 278 279 280
    def testFunctionName(self):
        functype = target.module.typedVar( "CdeclFuncPtr" ).type().deref()
        self.assertEqual(functype.name(), "Void(__cdecl)(Int4B, Float)")

281 282 283
        functype = target.module.typedVar( "MethodPtr" ).type().deref()
        self.assertEqual(functype.name(), "Void(__thiscall FuncTestClass::)()")

284 285 286 287 288 289
        functype = target.module.typedVar( "ArrayOfCdeclFuncPtr" ).type()[0].deref()
        self.assertEqual(functype.name(), "Void(__cdecl)(Int4B, Float)")

        functype = target.module.typedVar( "ArrayOfMethodPtr" ).type()[0].deref()
        self.assertEqual(functype.name(), "Void(__thiscall FuncTestClass::)()")

290 291 292
        functype = target.module.typedVar( "g_variadicFuncPtr" ).type().deref()
        self.assertEqual(functype.name(), "Void(__cdecl)(Int4B, ...)")

293 294 295
    def testFunctionPtrName(self):
        funcptrtype = target.module.typedVar( "CdeclFuncPtr" ).type()
        self.assertEqual(funcptrtype.name(), "Void(__cdecl*)(Int4B, Float)")
296

297
        functype = target.module.typedVar( "MethodPtr" ).type()
298
        self.assertEqual(functype.name(), "Void(__thiscall FuncTestClass::*)()")
299

300 301 302
        funcptrtype = target.module.typedVar( "g_variadicFuncPtr" ).type()
        self.assertEqual(funcptrtype.name(), "Void(__cdecl*)(Int4B, ...)")

303 304 305 306
    def testFunctionArrName(self):
        funcptrtype = target.module.typedVar( "ArrayOfCdeclFuncPtr" ).type()
        self.assertEqual(funcptrtype.name(), "Void(__cdecl*[3])(Int4B, Float)")

307
        functype = target.module.typedVar( "ArrayOfMethodPtr" ).type()
308
        self.assertEqual(functype.name(), "Void(__thiscall FuncTestClass::*[2])()")
309 310 311 312 313 314

    def testDir(self):
        ti = target.module.type("structTest")
        self.assertEqual(5, len(dir(ti)))
        self.assertTrue("m_field3" in dir(ti))
        self.assertFalse("m_field33" in dir(ti))
315 316 317 318 319 320 321 322 323

    def testEnumTypes(self):
        lst = target.module.enumTypes()
        self.assertNotEqual([], lst)
        lst = target.module.enumTypes("structTest")
        self.assertEqual(["structTest"], lst)
        lst = target.module.enumTypes("NonExsistType")
        self.assertEqual([],lst)

324 325
    def testArrayOverflow(self):
        self.assertRaises(pykd.TypeException, pykd.baseTypes.UInt8B.arrayOf, 0xFFFFFFFFFFFFFFFF)
326 327

    def testMethodCount(self):
328 329
        self.assertEqual( 14, target.module.type("classChild").getNumberMethods() )
        
330 331
    def testGetMethod(self):
        self.assertEqual( "Int4B(__thiscall classChild::)(Int4B)", target.module.type("classChild").method("childMethod").name() )
332
        self.assertEqual( "Int4B(__thiscall classChild::)(Int4B)", target.module.type("classChild").childMethod.name() )
333
        self.assertEqual( "Int4B(__thiscall classChild::)(Int4B)", target.module.type("classChild").method(1).name() )
334

335 336 337 338
    def testMethods(self):
        self.assertEqual( 14, len(target.module.type("classChild").methods()))

    def testGetBaseClass(self):
339
        classChild = target.module.type("classChild")
340
        self.assertEqual( ["classBase1", "classBase2"], [ classChild.baseClass(i).name() for i in range(classChild.getNumberBaseClasses()) ] )
341 342 343 344 345 346 347
        self.assertEqual( ["classBase1", "classBase2"], [ name for name, _, _ in classChild.baseClasses()] )

    def testGetBaseClassOffset(self):
        classChild = target.module.type("classChild")
        self.assertEqual( classChild.baseClassOffset(0), classChild.baseClassOffset('classBase1'))
        self.assertEqual(classChild.baseClassOffset(1), classChild.baseClassOffset('classBase2'))

ussrhero's avatar
ussrhero committed
348 349 350 351 352
    def  testPdbTypeProvider(self):
        pdb = target.module.symfile()
        typeProvider = pykd.getTypeInfoProviderFromPdb(pdb)
        self.assertEqual("structTest", typeProvider.getTypeByName("structTest").name())
        self.assertEqual("structTest", typeProvider.structTest.name())
ussrhero's avatar
ussrhero committed
353
        self.assertEqual(15, len(list(typeProvider.typeIterator("*struct*"))))
ussrhero's avatar
ussrhero committed
354 355 356 357

    def testScopeName(self):
        self.assertEqual( target.module.name(), pykd.typeInfo( "structTest" ).scopeName() )
        self.assertEqual( target.module.name(), pykd.typeInfo( "structWithNested::Nested" ).scopeName() )
358 359 360 361 362 363
 
    def testContain(self):
        ti = target.module.type( "structTest" )
        self.assertTrue("m_field1" in ti)
        self.assertFalse("NotExist" in ti)
        self.assertRaises(Exception, lambda t : 2 in t, ti)
ussrhero's avatar
ussrhero committed
364 365 366 367 368 369

    def testTemplateType(self):
        ti = target.module.type("g_testTemplateTwoTypes")
        self.assertTrue(ti.isTemplate)
        self.assertEqual(['int', 'TestClassTemplate<int>'], ti.getTemplateArgs() )

370 371 372 373 374 375 376 377 378
    def testMembers(self):
        self.assertEqual(
           ['__VFN_table', '__VFN_table', 'm_staticConst', 'm_staticField', 'm_childField',
           'm_childField2', 'm_childField3', 'm_enumField'],
           [ member[0] for member in pykd.typeInfo( "classChild" ).members() ])

    def testIsStaticField(self):
        ti = pykd.typeInfo("classChild")
        self.assertTrue(ti.isStaticField("m_staticField"))
379 380 381 382 383
        self.assertFalse(ti.isStaticField("m_baseField"))

    def testIsConstField(self):
        ti = pykd.typeInfo("classChild")
        self.assertTrue(ti.isStaticField("m_staticConst"))
ussrhero's avatar
ussrhero committed
384 385
        self.assertFalse(ti.isConstField("m_staticConst"))

ussrhero's avatar
ussrhero committed
386
    #def testClangCompile(self):
ussrhero's avatar
ussrhero committed
387 388 389 390 391 392
    #    src_code = '#include <windows.h>\r\n'
    #    include_path = '"C:/Program Files (x86)/Windows Kits/8.1/Include/um";"C:/Program Files (x86)/Windows Kits/8.1/Include/shared'
    #    compile_opts = '-I%s -w' % include_path
    #    symbolEnum = pykd.getSymbolProviderFromSource(src_code, compile_opts)
    #    for symName, _, symType in symbolEnum :
    #        print( symName, symType.name() )