def test_typedef(self): t = self.prog.typedef_type("INT", self.prog.int_type("int", 4, True)) self.assertEqual(t.kind, TypeKind.TYPEDEF) self.assertIsNone(t.primitive) self.assertEqual(t.language, DEFAULT_LANGUAGE) self.assertEqual(t.name, "INT") self.assertIdentical(t.type, self.prog.int_type("int", 4, True)) self.assertTrue(t.is_complete()) self.assertEqual( repr(t), "prog.typedef_type(name='INT', type=prog.int_type(name='int', size=4, is_signed=True))", ) self.assertEqual(sizeof(t), 4) t = self.prog.typedef_type("VOID", self.prog.void_type()) self.assertFalse(t.is_complete()) self.assertRaises(TypeError, self.prog.typedef_type, None, self.prog.int_type("int", 4, True)) self.assertRaises(TypeError, self.prog.typedef_type, "INT", 4) self.assertEqual( self.prog.typedef_type( "size_t", self.prog.int_type("unsigned long", 8, False)).primitive, PrimitiveType.C_SIZE_T, ) self.assertEqual( self.prog.typedef_type("ptrdiff_t", self.prog.int_type("long", 8, True)).primitive, PrimitiveType.C_PTRDIFF_T, )
def test_array(self): t = self.prog.array_type(self.prog.int_type("int", 4, True), 10) self.assertEqual(t.kind, TypeKind.ARRAY) self.assertIsNone(t.primitive) self.assertEqual(t.language, DEFAULT_LANGUAGE) self.assertEqual(t.length, 10) self.assertIdentical(t.type, self.prog.int_type("int", 4, True)) self.assertTrue(t.is_complete()) self.assertEqual( repr(t), "prog.array_type(type=prog.int_type(name='int', size=4, is_signed=True), length=10)", ) self.assertEqual(sizeof(t), 40) t = self.prog.array_type(self.prog.int_type("int", 4, True), 0) self.assertEqual(t.kind, TypeKind.ARRAY) self.assertIsNone(t.primitive) self.assertEqual(t.length, 0) self.assertIdentical(t.type, self.prog.int_type("int", 4, True)) self.assertTrue(t.is_complete()) t = self.prog.array_type(self.prog.int_type("int", 4, True)) self.assertEqual(t.kind, TypeKind.ARRAY) self.assertIsNone(t.primitive) self.assertIsNone(t.length) self.assertIdentical(t.type, self.prog.int_type("int", 4, True)) self.assertFalse(t.is_complete()) self.assertRaises(TypeError, self.prog.array_type, 10, 4)
def test_pointer(self): t = pointer_type(8, int_type('int', 4, True)) self.assertEqual(t.kind, TypeKind.POINTER) self.assertIsNone(t.primitive) self.assertEqual(t.size, 8) self.assertEqual(t.type, int_type('int', 4, True)) self.assertTrue(t.is_complete()) self.assertEqual(t, pointer_type(8, int_type('int', 4, True))) # Qualified type argument. self.assertEqual(t, pointer_type(8, int_type('int', 4, True))) # Different size. self.assertNotEqual(t, pointer_type(4, int_type('int', 4, True))) # Different type. self.assertNotEqual(t, pointer_type(8, void_type())) self.assertNotEqual(t, pointer_type(8, void_type(Qualifiers.CONST))) self.assertEqual( repr(t), "pointer_type(size=8, type=int_type(name='int', size=4, is_signed=True))" ) self.assertEqual(sizeof(t), 8) self.assertRaises(TypeError, pointer_type, None, int_type('int', 4, True)) self.assertRaises(TypeError, pointer_type, 8, 4)
def test_complex(self): t = complex_type('double _Complex', 16, float_type('double', 8)) self.assertEqual(t.kind, TypeKind.COMPLEX) self.assertIsNone(t.primitive) self.assertEqual(t.name, 'double _Complex') self.assertEqual(t.size, 16) self.assertEqual(t.type, float_type('double', 8)) self.assertTrue(t.is_complete()) self.assertEqual( t, complex_type('double _Complex', 16, float_type('double', 8))) self.assertNotEqual( t, complex_type('float _Complex', 16, float_type('double', 8))) self.assertNotEqual( t, complex_type('double _Complex', 32, float_type('double', 8))) self.assertNotEqual( t, complex_type('double _Complex', 16, float_type('float', 4))) self.assertEqual( repr(t), "complex_type(name='double _Complex', size=16, type=float_type(name='double', size=8))" ) self.assertEqual(sizeof(t), 16) self.assertRaises(TypeError, complex_type, None, 16, float_type('double', 8)) self.assertRaises(TypeError, complex_type, 'double _Complex', 16, None) self.assertRaisesRegex(ValueError, 'must be floating-point or integer type', complex_type, 'double _Complex', 16, void_type()) self.assertRaisesRegex(ValueError, 'must be unqualified', complex_type, 'double _Complex', 16, float_type('double', 8, Qualifiers.CONST))
def test_bit(nr: IntegerLike, bitmap: Object) -> bool: """ Return whether a bit in a bitmap is set. :param nr: Bit number. :param bitmap: ``unsigned long *`` """ nr = int(nr) word_bits = 8 * sizeof(bitmap.type_.type) return ((bitmap[nr // word_bits].value_() >> (nr & (word_bits - 1))) & 1) != 0
def test_float(self): t = self.prog.float_type("float", 4) self.assertEqual(t.primitive, PrimitiveType.C_FLOAT) self.assertEqual(t.kind, TypeKind.FLOAT) self.assertEqual(t.name, "float") self.assertEqual(t.size, 4) self.assertTrue(t.is_complete()) self.assertEqual(repr(t), "prog.float_type(name='float', size=4)") self.assertEqual(sizeof(t), 4) self.assertRaises(TypeError, self.prog.float_type, None, 4)
def for_each_cpu(mask: Object) -> Iterator[int]: """ Iterate over all of the CPUs in the given mask. :param mask: ``struct cpumask`` """ bits = mask.bits word_bits = 8 * sizeof(bits.type_.type) for i in range(bits.type_.length): # type: ignore word = bits[i].value_() for j in range(word_bits): if word & (1 << j): yield (word_bits * i) + j
def test_bool(self): t = self.prog.bool_type("_Bool", 1) self.assertEqual(t.kind, TypeKind.BOOL) self.assertEqual(t.primitive, PrimitiveType.C_BOOL) self.assertEqual(t.language, DEFAULT_LANGUAGE) self.assertEqual(t.name, "_Bool") self.assertEqual(t.size, 1) self.assertTrue(t.is_complete()) self.assertEqual(repr(t), "prog.bool_type(name='_Bool', size=1)") self.assertEqual(sizeof(t), 1) self.assertRaises(TypeError, self.prog.bool_type, None, 1)
def for_each_clear_bit(bitmap: Object, size: IntegerLike) -> Iterator[int]: """ Iterate over all clear (zero) bits in a bitmap. :param bitmap: ``unsigned long *`` :param size: Size of *bitmap* in bits. """ size = int(size) word_bits = 8 * sizeof(bitmap.type_.type) for i in range((size + word_bits - 1) // word_bits): word = bitmap[i].value_() for j in range(min(word_bits, size - word_bits * i)): if not (word & (1 << j)): yield (word_bits * i) + j
def test_array(self): segment = bytearray() for i in range(10): segment.extend(i.to_bytes(4, "little")) self.add_memory_segment(segment, virt_addr=0xFFFF0000) obj = Object(self.prog, "int [5]", address=0xFFFF0000) self.assertEqual(obj.value_(), [0, 1, 2, 3, 4]) self.assertEqual(sizeof(obj), 20) obj = Object(self.prog, "int [2][5]", address=0xFFFF0000) self.assertEqual(obj.value_(), [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]) obj = Object(self.prog, "int [2][2][2]", address=0xFFFF0000) self.assertEqual(obj.value_(), [[[0, 1], [2, 3]], [[4, 5], [6, 7]]])
def test_bool(self): t = bool_type('_Bool', 1) self.assertEqual(t.kind, TypeKind.BOOL) self.assertEqual(t.primitive, PrimitiveType.C_BOOL) self.assertEqual(t.name, '_Bool') self.assertEqual(t.size, 1) self.assertTrue(t.is_complete()) self.assertEqual(t, bool_type('_Bool', 1)) self.assertNotEqual(t, bool_type('bool', 1)) self.assertNotEqual(t, bool_type('_Bool', 2)) self.assertEqual(repr(t), "bool_type(name='_Bool', size=1)") self.assertEqual(sizeof(t), 1) self.assertRaises(TypeError, bool_type, None, 1)
def test_float(self): t = float_type('float', 4) self.assertEqual(t.primitive, PrimitiveType.C_FLOAT) self.assertEqual(t.kind, TypeKind.FLOAT) self.assertEqual(t.name, 'float') self.assertEqual(t.size, 4) self.assertTrue(t.is_complete()) self.assertEqual(t, float_type('float', 4)) self.assertNotEqual(t, float_type('double', 4)) self.assertNotEqual(t, float_type('float', 8)) self.assertEqual(repr(t), "float_type(name='float', size=4)") self.assertEqual(sizeof(t), 4) self.assertRaises(TypeError, float_type, None, 4)
def for_each_file(task: Object) -> Iterator[Tuple[int, Object]]: """ Iterate over all of the files open in a given task. :param task: ``struct task_struct *`` :return: Iterator of (fd, ``struct file *``) tuples. """ fdt = task.files.fdt.read_() bits_per_long = 8 * sizeof(fdt.open_fds.type_.type) for i in range( (fdt.max_fds.value_() + bits_per_long - 1) // bits_per_long): word = fdt.open_fds[i].value_() for j in range(bits_per_long): if word & (1 << j): fd = i * bits_per_long + j file = fdt.fd[fd].read_() yield fd, file
def test_int(self): t = self.prog.int_type("int", 4, True) self.assertEqual(t.kind, TypeKind.INT) self.assertEqual(t.primitive, PrimitiveType.C_INT) self.assertEqual(t.language, DEFAULT_LANGUAGE) self.assertEqual(t.name, "int") self.assertEqual(t.size, 4) self.assertTrue(t.is_signed) self.assertTrue(t.is_complete()) self.assertEqual(repr(t), "prog.int_type(name='int', size=4, is_signed=True)") self.assertEqual(sizeof(t), 4) self.assertRaises(TypeError, self.prog.int_type, None, 4, True) self.assertIsNone(self.prog.int_type("my_int", 4, True).primitive) self.assertIsNone(self.prog.int_type("int", 4, False).primitive)
def test_complex(self): t = complex_type("double _Complex", 16, float_type("double", 8)) self.assertEqual(t.kind, TypeKind.COMPLEX) self.assertIsNone(t.primitive) self.assertEqual(t.language, DEFAULT_LANGUAGE) self.assertEqual(t.name, "double _Complex") self.assertEqual(t.size, 16) self.assertEqual(t.type, float_type("double", 8)) self.assertTrue(t.is_complete()) self.assertEqual( t, complex_type("double _Complex", 16, float_type("double", 8))) self.assertNotEqual( t, complex_type("float _Complex", 16, float_type("double", 8))) self.assertNotEqual( t, complex_type("double _Complex", 32, float_type("double", 8))) self.assertNotEqual( t, complex_type("double _Complex", 16, float_type("float", 4))) self.assertEqual( repr(t), "complex_type(name='double _Complex', size=16, type=float_type(name='double', size=8))", ) self.assertEqual(sizeof(t), 16) self.assertRaises(TypeError, complex_type, None, 16, float_type("double", 8)) self.assertRaises(TypeError, complex_type, "double _Complex", 16, None) self.assertRaisesRegex( ValueError, "must be floating-point or integer type", complex_type, "double _Complex", 16, void_type(), ) self.assertRaisesRegex( ValueError, "must be unqualified", complex_type, "double _Complex", 16, float_type("double", 8, Qualifiers.CONST), )
def test_typedef(self): t = typedef_type("INT", int_type("int", 4, True)) self.assertEqual(t.kind, TypeKind.TYPEDEF) self.assertIsNone(t.primitive) self.assertEqual(t.language, DEFAULT_LANGUAGE) self.assertEqual(t.name, "INT") self.assertEqual(t.type, int_type("int", 4, True)) self.assertTrue(t.is_complete()) self.assertEqual(t, typedef_type("INT", int_type("int", 4, True))) # Qualified type argument. self.assertEqual(t, typedef_type("INT", int_type("int", 4, True))) # Different name. self.assertNotEqual(t, typedef_type("integer", int_type("int", 4, True))) # Different type. self.assertNotEqual( t, typedef_type("integer", int_type("unsigned int", 4, False))) self.assertNotEqual( t, typedef_type("INT", int_type("int", 4, True, Qualifiers.CONST))) self.assertEqual( repr(t), "typedef_type(name='INT', type=int_type(name='int', size=4, is_signed=True))", ) self.assertEqual(sizeof(t), 4) t = typedef_type("VOID", void_type()) self.assertFalse(t.is_complete()) self.assertRaises(TypeError, typedef_type, None, int_type("int", 4, True)) self.assertRaises(TypeError, typedef_type, "INT", 4) self.assertEqual( typedef_type("size_t", int_type("unsigned long", 8, False)).primitive, PrimitiveType.C_SIZE_T, ) self.assertEqual( typedef_type("ptrdiff_t", int_type("long", 8, True)).primitive, PrimitiveType.C_PTRDIFF_T, )
def test_typedef(self): t = typedef_type('INT', int_type('int', 4, True)) self.assertEqual(t.kind, TypeKind.TYPEDEF) self.assertIsNone(t.primitive) self.assertEqual(t.name, 'INT') self.assertEqual(t.type, int_type('int', 4, True)) self.assertTrue(t.is_complete()) self.assertEqual(t, typedef_type('INT', int_type('int', 4, True))) # Qualified type argument. self.assertEqual(t, typedef_type('INT', int_type('int', 4, True))) # Different name. self.assertNotEqual(t, typedef_type('integer', int_type('int', 4, True))) # Different type. self.assertNotEqual( t, typedef_type('integer', int_type('unsigned int', 4, False))) self.assertNotEqual( t, typedef_type('INT', int_type('int', 4, True, Qualifiers.CONST))) self.assertEqual( repr(t), "typedef_type(name='INT', type=int_type(name='int', size=4, is_signed=True))" ) self.assertEqual(sizeof(t), 4) t = typedef_type('VOID', void_type()) self.assertFalse(t.is_complete()) self.assertRaises(TypeError, typedef_type, None, int_type('int', 4, True)) self.assertRaises(TypeError, typedef_type, 'INT', 4) self.assertEqual( typedef_type('size_t', int_type('unsigned long', 8, False)).primitive, PrimitiveType.C_SIZE_T) self.assertEqual( typedef_type('ptrdiff_t', int_type('long', 8, True)).primitive, PrimitiveType.C_PTRDIFF_T)
def test_array(self): t = array_type(10, int_type("int", 4, True)) self.assertEqual(t.kind, TypeKind.ARRAY) self.assertIsNone(t.primitive) self.assertEqual(t.language, DEFAULT_LANGUAGE) self.assertEqual(t.length, 10) self.assertEqual(t.type, int_type("int", 4, True)) self.assertTrue(t.is_complete()) self.assertEqual(t, array_type(10, int_type("int", 4, True))) # Qualified type argument. self.assertEqual(t, array_type(10, int_type("int", 4, True))) # Different length. self.assertNotEqual(t, array_type(4, int_type("int", 4, True))) # Different type. self.assertNotEqual(t, array_type(10, void_type())) self.assertNotEqual(t, array_type(10, void_type(Qualifiers.CONST))) self.assertEqual( repr(t), "array_type(length=10, type=int_type(name='int', size=4, is_signed=True))", ) self.assertEqual(sizeof(t), 40) t = array_type(0, int_type("int", 4, True)) self.assertEqual(t.kind, TypeKind.ARRAY) self.assertIsNone(t.primitive) self.assertEqual(t.length, 0) self.assertEqual(t.type, int_type("int", 4, True)) self.assertTrue(t.is_complete()) t = array_type(None, int_type("int", 4, True)) self.assertEqual(t.kind, TypeKind.ARRAY) self.assertIsNone(t.primitive) self.assertIsNone(t.length) self.assertEqual(t.type, int_type("int", 4, True)) self.assertFalse(t.is_complete()) self.assertRaises(TypeError, array_type, 10, 4)
def test_pointer(self): t = self.prog.pointer_type(self.prog.int_type("int", 4, True), 8) self.assertEqual(t.kind, TypeKind.POINTER) self.assertIsNone(t.primitive) self.assertEqual(t.language, DEFAULT_LANGUAGE) self.assertEqual(t.size, 8) self.assertIdentical(t.type, self.prog.int_type("int", 4, True)) self.assertTrue(t.is_complete()) self.assertEqual( repr(t), "prog.pointer_type(type=prog.int_type(name='int', size=4, is_signed=True))", ) self.assertEqual( repr(self.prog.pointer_type(self.prog.int_type("int", 4, True), 4)), "prog.pointer_type(type=prog.int_type(name='int', size=4, is_signed=True), size=4)", ) self.assertEqual(sizeof(t), 8) self.assertRaises(TypeError, self.prog.pointer_type, 4)
def test_int(self): t = int_type('int', 4, True) self.assertEqual(t.kind, TypeKind.INT) self.assertEqual(t.primitive, PrimitiveType.C_INT) self.assertEqual(t.name, 'int') self.assertEqual(t.size, 4) self.assertTrue(t.is_signed) self.assertTrue(t.is_complete()) self.assertEqual(t, int_type('int', 4, True)) self.assertNotEqual(t, int_type('long', 4, True)) self.assertNotEqual(t, int_type('int', 2, True)) self.assertNotEqual(t, int_type('int', 4, False)) self.assertEqual(repr(t), "int_type(name='int', size=4, is_signed=True)") self.assertEqual(sizeof(t), 4) self.assertRaises(TypeError, int_type, None, 4, True) self.assertIsNone(int_type('my_int', 4, True).primitive) self.assertIsNone(int_type('int', 4, False).primitive)
def test_struct(self): self.add_memory_segment( ( (99).to_bytes(4, "little") + (-1).to_bytes(4, "little", signed=True) + (12345).to_bytes(4, "little") + (0).to_bytes(4, "little") ), virt_addr=0xFFFF0000, ) self.types.append(self.point_type) obj = Object(self.prog, "struct point", address=0xFFFF0000) self.assertEqual(obj.value_(), {"x": 99, "y": -1}) self.assertEqual(sizeof(obj), 8) type_ = self.prog.struct_type( "foo", 16, ( TypeMember(self.point_type, "point"), TypeMember( self.prog.struct_type( None, 8, ( TypeMember(self.prog.int_type("int", 4, True), "bar"), TypeMember(self.prog.int_type("int", 4, True), "baz", 32), ), ), None, 64, ), ), ) obj = Object(self.prog, type_, address=0xFFFF0000) self.assertEqual( obj.value_(), {"point": {"x": 99, "y": -1}, "bar": 12345, "baz": 0} )
def test_enum(self): t = self.prog.enum_type( "color", self.prog.int_type("unsigned int", 4, False), ( TypeEnumerator("RED", 0), TypeEnumerator("GREEN", 1), TypeEnumerator("BLUE", 2), ), ) self.assertEqual(t.kind, TypeKind.ENUM) self.assertIsNone(t.primitive) self.assertEqual(t.language, DEFAULT_LANGUAGE) self.assertEqual(t.tag, "color") self.assertIdentical(t.type, self.prog.int_type("unsigned int", 4, False)) self.assertEqual( t.enumerators, ( TypeEnumerator("RED", 0), TypeEnumerator("GREEN", 1), TypeEnumerator("BLUE", 2), ), ) self.assertTrue(t.is_complete()) self.assertEqual( repr(t), "prog.enum_type(tag='color', type=prog.int_type(name='unsigned int', size=4, is_signed=False), enumerators=(TypeEnumerator('RED', 0), TypeEnumerator('GREEN', 1), TypeEnumerator('BLUE', 2)))", ) self.assertEqual(sizeof(t), 4) t = self.prog.enum_type("color", None, None) self.assertEqual(t.kind, TypeKind.ENUM) self.assertIsNone(t.primitive) self.assertEqual(t.tag, "color") self.assertIsNone(t.type) self.assertIsNone(t.enumerators) self.assertFalse(t.is_complete()) self.assertEqual( repr(t), "prog.enum_type(tag='color', type=None, enumerators=None)") # A type with no enumerators isn't valid in C, but we allow it. t = self.prog.enum_type("color", self.prog.int_type("unsigned int", 4, False), ()) self.assertEqual(t.kind, TypeKind.ENUM) self.assertIsNone(t.primitive) self.assertEqual(t.tag, "color") self.assertIdentical(t.type, self.prog.int_type("unsigned int", 4, False)) self.assertEqual(t.enumerators, ()) self.assertTrue(t.is_complete()) self.assertEqual( repr(t), "prog.enum_type(tag='color', type=prog.int_type(name='unsigned int', size=4, is_signed=False), enumerators=())", ) self.assertRaisesRegex(TypeError, "must be Type", self.prog.enum_type, "color", 4, ()) self.assertRaisesRegex( ValueError, "must be integer type", self.prog.enum_type, "color", self.prog.void_type(), (), ) self.assertRaisesRegex( ValueError, "must be unqualified", self.prog.enum_type, "color", self.prog.int_type("unsigned int", 4, True, qualifiers=Qualifiers.CONST), (), ) self.assertRaisesRegex( ValueError, "must not have compatible type", self.prog.enum_type, "color", self.prog.int_type("unsigned int", 4, False), None, ) self.assertRaisesRegex( ValueError, "must have compatible type", self.prog.enum_type, "color", None, (), ) self.assertRaisesRegex( TypeError, "must be sequence or None", self.prog.enum_type, "color", self.prog.int_type("unsigned int", 4, False), 4, ) self.assertRaisesRegex( TypeError, "must be TypeEnumerator", self.prog.enum_type, "color", self.prog.int_type("unsigned int", 4, False), (4, ), )
def test_struct(self): t = self.prog.struct_type( "point", 8, ( TypeMember(self.prog.int_type("int", 4, True), "x", 0), TypeMember(self.prog.int_type("int", 4, True), "y", 32), ), ) self.assertEqual(t.kind, TypeKind.STRUCT) self.assertIsNone(t.primitive) self.assertEqual(t.language, DEFAULT_LANGUAGE) self.assertEqual(t.tag, "point") self.assertEqual(t.size, 8) self.assertIdentical( t.members, ( TypeMember(self.prog.int_type("int", 4, True), "x", 0, 0), TypeMember(self.prog.int_type("int", 4, True), "y", 32, 0), ), ) self.assertTrue(t.is_complete()) self.assertEqual( repr(t), "prog.struct_type(tag='point', size=8, members=(TypeMember(type=prog.int_type(name='int', size=4, is_signed=True), name='x', bit_offset=0), TypeMember(type=prog.int_type(name='int', size=4, is_signed=True), name='y', bit_offset=32)))", ) self.assertEqual(sizeof(t), 8) t = self.prog.struct_type( None, 8, ( TypeMember(self.prog.int_type("int", 4, True), "x", 0), TypeMember(self.prog.int_type("int", 4, True), "y", 32), ), ) self.assertEqual(t.kind, TypeKind.STRUCT) self.assertIsNone(t.primitive) self.assertIsNone(t.tag) self.assertEqual(t.size, 8) self.assertIdentical( t.members, ( TypeMember(self.prog.int_type("int", 4, True), "x", 0, 0), TypeMember(self.prog.int_type("int", 4, True), "y", 32, 0), ), ) self.assertTrue(t.is_complete()) t = self.prog.struct_type("color", 0, ()) self.assertEqual(t.kind, TypeKind.STRUCT) self.assertIsNone(t.primitive) self.assertEqual(t.tag, "color") self.assertEqual(t.size, 0) self.assertEqual(t.members, ()) self.assertTrue(t.is_complete()) self.assertEqual(repr(t), "prog.struct_type(tag='color', size=0, members=())") t = self.prog.struct_type("color") self.assertEqual(t.kind, TypeKind.STRUCT) self.assertIsNone(t.primitive) self.assertEqual(t.tag, "color") self.assertIsNone(t.size) self.assertIsNone(t.members) self.assertFalse(t.is_complete()) self.assertEqual( repr(t), "prog.struct_type(tag='color', size=None, members=None)") t = self.prog.struct_type(None, None, None) self.assertEqual(t.kind, TypeKind.STRUCT) self.assertIsNone(t.primitive) self.assertEqual(t.tag, None) self.assertIsNone(t.size) self.assertIsNone(t.members) self.assertFalse(t.is_complete()) self.assertEqual( repr(t), "prog.struct_type(tag=None, size=None, members=None)") self.assertRaises(TypeError, self.prog.struct_type, 4) self.assertRaisesRegex(ValueError, "must not have size", self.prog.struct_type, "point", 8, None) self.assertRaisesRegex(ValueError, "must have size", self.prog.struct_type, "point", None, ()) self.assertRaisesRegex(TypeError, "must be sequence or None", self.prog.struct_type, "point", 8, 4) self.assertRaisesRegex(TypeError, "must be TypeMember", self.prog.struct_type, "point", 8, (4, )) # Bit size. t = self.prog.struct_type( "point", 8, ( TypeMember(self.prog.int_type("int", 4, True), "x", 0, 4), TypeMember(self.prog.int_type("int", 4, True), "y", 32, 4), ), ) self.assertIdentical( t.members, ( TypeMember(self.prog.int_type("int", 4, True), "x", 0, 4), TypeMember(self.prog.int_type("int", 4, True), "y", 32, 4), ), )
def test_enum(self): t = enum_type('color', int_type('unsigned int', 4, False), (('RED', 0), ('GREEN', 1), ('BLUE', 2))) self.assertEqual(t.kind, TypeKind.ENUM) self.assertIsNone(t.primitive) self.assertEqual(t.tag, 'color') self.assertEqual(t.type, int_type('unsigned int', 4, False)) self.assertEqual(t.enumerators, (('RED', 0), ('GREEN', 1), ('BLUE', 2))) self.assertTrue(t.is_complete()) self.assertEqual( t, enum_type('color', int_type('unsigned int', 4, False), (('RED', 0), ('GREEN', 1), ('BLUE', 2)))) # Different tag. self.assertNotEqual( t, enum_type('COLOR', int_type('unsigned int', 4, False), (('RED', 0), ('GREEN', 1), ('BLUE', 2)))) # One is anonymous. self.assertNotEqual( t, enum_type(None, int_type('unsigned int', 4, False), (('RED', 0), ('GREEN', 1), ('BLUE', 2)))) # Different compatible type. self.assertNotEqual( t, enum_type('color', int_type('int', 4, True), (('RED', 0), ('GREEN', 1), ('BLUE', 2)))) # Different enumerators. self.assertNotEqual( t, enum_type('color', int_type('unsigned int', 4, False), (('RED', 0), ('YELLOW', 1), ('BLUE', 2)))) # Different number of enumerators. self.assertNotEqual( t, enum_type('color', int_type('unsigned int', 4, False), (('RED', 0), ('GREEN', 1)))) # One is incomplete. self.assertNotEqual(t, enum_type('color')) self.assertEqual( repr(t), "enum_type(tag='color', type=int_type(name='unsigned int', size=4, is_signed=False), enumerators=(('RED', 0), ('GREEN', 1), ('BLUE', 2)))" ) self.assertEqual(sizeof(t), 4) t = enum_type('color', None, None) self.assertEqual(t.kind, TypeKind.ENUM) self.assertIsNone(t.primitive) self.assertEqual(t.tag, 'color') self.assertIsNone(t.type) self.assertIsNone(t.enumerators) self.assertFalse(t.is_complete()) self.assertEqual( repr(t), "enum_type(tag='color', type=None, enumerators=None)") # A type with no enumerators isn't valid in C, but we allow it. t = enum_type('color', int_type('unsigned int', 4, False), ()) self.assertEqual(t.kind, TypeKind.ENUM) self.assertIsNone(t.primitive) self.assertEqual(t.tag, 'color') self.assertEqual(t.type, int_type('unsigned int', 4, False)) self.assertEqual(t.enumerators, ()) self.assertTrue(t.is_complete()) self.assertEqual( repr(t), "enum_type(tag='color', type=int_type(name='unsigned int', size=4, is_signed=False), enumerators=())" ) self.assertRaisesRegex(TypeError, 'must be Type', enum_type, 'color', 4, ()) self.assertRaisesRegex(ValueError, 'must be integer type', enum_type, 'color', void_type(), ()) self.assertRaisesRegex( ValueError, 'must be unqualified', enum_type, 'color', int_type('unsigned int', 4, True, Qualifiers.CONST), ()) self.assertRaisesRegex(ValueError, 'must not have compatible type', enum_type, 'color', int_type('unsigned int', 4, False), None) self.assertRaisesRegex(ValueError, 'must have compatible type', enum_type, 'color', None, ()) self.assertRaisesRegex(TypeError, 'must be sequence or None', enum_type, 'color', int_type('unsigned int', 4, False), 4) self.assertRaisesRegex(TypeError, 'must be.*sequence', enum_type, 'color', int_type('unsigned int', 4, False), (4, )) self.assertRaisesRegex(ValueError, 'must be.*sequence', enum_type, 'color', int_type('unsigned int', 4, False), ((), )) self.assertRaisesRegex(TypeError, 'must be string', enum_type, 'color', int_type('unsigned int', 4, False), ((None, 0), )) self.assertRaisesRegex(TypeError, 'must be integer', enum_type, 'color', int_type('unsigned int', 4, False), (('RED', None), ))
def test_class(self): t = class_type('coord', 12, ( (int_type('int', 4, True), 'x', 0), (int_type('int', 4, True), 'y', 32), (int_type('int', 4, True), 'z', 64), )) self.assertEqual(t.kind, TypeKind.CLASS) self.assertIsNone(t.primitive) self.assertEqual(t.tag, 'coord') self.assertEqual(t.size, 12) self.assertEqual(t.members, ( (int_type('int', 4, True), 'x', 0, 0), (int_type('int', 4, True), 'y', 32, 0), (int_type('int', 4, True), 'z', 64, 0), )) self.assertTrue(t.is_complete()) self.assertEqual( t, class_type('coord', 12, ( (int_type('int', 4, True), 'x', 0), (int_type('int', 4, True), 'y', 32), (int_type('int', 4, True), 'z', 64), ))) # Different tag. self.assertNotEqual( t, class_type('crd', 12, ( (int_type('int', 4, True), 'x', 0), (int_type('int', 4, True), 'y', 32), (int_type('int', 4, True), 'z', 64), ))) # Different size. self.assertNotEqual( t, class_type('coord', 16, ( (int_type('int', 4, True), 'x', 0), (int_type('int', 4, True), 'y', 32), (int_type('int', 4, True), 'z', 64), ))) # One is anonymous. self.assertNotEqual( t, class_type(None, 12, ( (int_type('int', 4, True), 'x', 0), (int_type('int', 4, True), 'y', 32), (int_type('int', 4, True), 'z', 64), ))) # Different members. self.assertNotEqual( t, class_type('coord', 12, ( (int_type('long', 8, True), 'x', 0), (int_type('long', 8, True), 'y', 64), (int_type('long', 8, True), 'z', 128), ))) # Different number of members. self.assertNotEqual( t, class_type('coord', 12, ( (int_type('int', 4, True), 'x', 0), (int_type('int', 4, True), 'y', 32), ))) # One member is anonymous. self.assertNotEqual( t, class_type('coord', 8, ( (int_type('int', 4, True), 'x', 0, 0), (int_type('int', 4, True), None, 32, 0), (int_type('int', 4, True), 'z', 64, 0), ))) # One is incomplete. self.assertNotEqual(t, class_type('coord')) self.assertEqual( repr(t), "class_type(tag='coord', size=12, members=((int_type(name='int', size=4, is_signed=True), 'x', 0, 0), (int_type(name='int', size=4, is_signed=True), 'y', 32, 0), (int_type(name='int', size=4, is_signed=True), 'z', 64, 0)))" ) self.assertEqual(sizeof(t), 12) t = class_type(None, 12, ( (int_type('int', 4, True), 'x', 0), (int_type('int', 4, True), 'y', 32), (int_type('int', 4, True), 'z', 64), )) self.assertEqual(t.kind, TypeKind.CLASS) self.assertIsNone(t.primitive) self.assertIsNone(t.tag) self.assertEqual(t.size, 12) self.assertEqual(t.members, ( (int_type('int', 4, True), 'x', 0, 0), (int_type('int', 4, True), 'y', 32, 0), (int_type('int', 4, True), 'z', 64, 0), )) self.assertTrue(t.is_complete()) t = class_type('color', 0, ()) self.assertEqual(t.kind, TypeKind.CLASS) self.assertIsNone(t.primitive) self.assertEqual(t.tag, 'color') self.assertEqual(t.size, 0) self.assertEqual(t.members, ()) self.assertTrue(t.is_complete()) self.assertEqual(repr(t), "class_type(tag='color', size=0, members=())") t = class_type('color') self.assertEqual(t.kind, TypeKind.CLASS) self.assertIsNone(t.primitive) self.assertEqual(t.tag, 'color') self.assertIsNone(t.size) self.assertIsNone(t.members) self.assertFalse(t.is_complete()) self.assertEqual(repr(t), "class_type(tag='color', size=None, members=None)") t = class_type(None, None, None) self.assertEqual(t.kind, TypeKind.CLASS) self.assertIsNone(t.primitive) self.assertEqual(t.tag, None) self.assertIsNone(t.size) self.assertIsNone(t.members) self.assertFalse(t.is_complete()) self.assertEqual(repr(t), "class_type(tag=None, size=None, members=None)") self.assertRaises(TypeError, class_type, 4) self.assertRaisesRegex(ValueError, 'must not have size', class_type, 'coord', 12, None) self.assertRaisesRegex(ValueError, 'must have size', class_type, 'coord', None, ()) self.assertRaisesRegex(TypeError, 'must be sequence or None', class_type, 'coord', 12, 4) self.assertRaisesRegex(TypeError, 'must be.*sequence', class_type, 'coord', 12, (4)) self.assertRaisesRegex(ValueError, 'must be.*sequence', class_type, 'coord', 12, ((), )) self.assertRaisesRegex(TypeError, 'must be string or None', class_type, 'coord', 12, ((int_type('int', 4, True), 4, 0), )) self.assertRaisesRegex(TypeError, 'must be integer', class_type, 'coord', 12, ((int_type('int', 4, True), 'x', None), )) self.assertRaisesRegex(TypeError, 'must be Type', class_type, 'coord', 12, ((None, 'x', 0), )) # Bit size. t = class_type('coord', 12, ( (int_type('int', 4, True), 'x', 0, 4), (int_type('int', 4, True), 'y', 32, 4), (int_type('int', 4, True), 'z', 64, 4), )) self.assertEqual(t.members, ( (int_type('int', 4, True), 'x', 0, 4), (int_type('int', 4, True), 'y', 32, 4), (int_type('int', 4, True), 'z', 64, 4), ))
def test_union(self): t = union_type('option', 4, ( (int_type('int', 4, True), 'x'), (int_type('unsigned int', 4, False), 'y'), )) self.assertEqual(t.kind, TypeKind.UNION) self.assertIsNone(t.primitive) self.assertEqual(t.tag, 'option') self.assertEqual(t.size, 4) self.assertEqual(t.members, ( (int_type('int', 4, True), 'x', 0, 0), (int_type('unsigned int', 4, False), 'y', 0, 0), )) self.assertTrue(t.is_complete()) self.assertEqual( t, union_type('option', 4, ( (int_type('int', 4, True), 'x'), (int_type('unsigned int', 4, False), 'y'), ))) # Different tag. self.assertNotEqual( t, union_type('pt', 4, ( (int_type('int', 4, True), 'x'), (int_type('unsigned int', 4, False), 'y'), ))) # Different size. self.assertNotEqual( t, union_type('option', 8, ( (int_type('int', 4, True), 'x'), (int_type('unsigned int', 4, False), 'y'), ))) # One is anonymous. self.assertNotEqual( t, union_type(None, 4, ( (int_type('int', 4, True), 'x'), (int_type('unsigned int', 4, False), 'y'), ))) # Different members. self.assertNotEqual( t, union_type('option', 4, ( (int_type('long', 8, True), 'x'), (int_type('unsigned long', 8, False), 'y'), ))) # Different number of members. self.assertNotEqual( t, union_type('option', 4, ( (int_type('int', 4, True), 'x'), (int_type('unsigned int', 4, False), 'y'), (float_type('float', 4), 'z'), ))) # One member is anonymous. self.assertNotEqual( t, union_type('option', 4, ( (int_type('int', 4, True), 'x'), (int_type('unsigned int', 4, False), ), ))) # One is incomplete. self.assertNotEqual(t, union_type('option')) self.assertEqual( repr(t), "union_type(tag='option', size=4, members=((int_type(name='int', size=4, is_signed=True), 'x', 0, 0), (int_type(name='unsigned int', size=4, is_signed=False), 'y', 0, 0)))" ) self.assertEqual(sizeof(t), 4) t = union_type(None, 4, ( (int_type('int', 4, True), 'x'), (int_type('unsigned int', 4, False), 'y'), )) self.assertEqual(t.kind, TypeKind.UNION) self.assertIsNone(t.primitive) self.assertIsNone(t.tag) self.assertEqual(t.size, 4) self.assertEqual(t.members, ( (int_type('int', 4, True), 'x', 0, 0), (int_type('unsigned int', 4, False), 'y', 0, 0), )) self.assertTrue(t.is_complete()) t = union_type('color', 0, ()) self.assertEqual(t.kind, TypeKind.UNION) self.assertIsNone(t.primitive) self.assertEqual(t.tag, 'color') self.assertEqual(t.size, 0) self.assertEqual(t.members, ()) self.assertTrue(t.is_complete()) self.assertEqual(repr(t), "union_type(tag='color', size=0, members=())") t = union_type('color') self.assertEqual(t.kind, TypeKind.UNION) self.assertIsNone(t.primitive) self.assertEqual(t.tag, 'color') self.assertIsNone(t.size) self.assertIsNone(t.members) self.assertFalse(t.is_complete()) self.assertEqual(repr(t), "union_type(tag='color', size=None, members=None)") t = union_type(None, None, None) self.assertEqual(t.kind, TypeKind.UNION) self.assertIsNone(t.primitive) self.assertEqual(t.tag, None) self.assertIsNone(t.size) self.assertIsNone(t.members) self.assertFalse(t.is_complete()) self.assertEqual(repr(t), "union_type(tag=None, size=None, members=None)") self.assertRaises(TypeError, union_type, 4) self.assertRaisesRegex(ValueError, 'must not have size', union_type, 'option', 8, None) self.assertRaisesRegex(ValueError, 'must have size', union_type, 'option', None, ()) self.assertRaisesRegex(TypeError, 'must be sequence or None', union_type, 'option', 8, 4) self.assertRaisesRegex(TypeError, 'must be.*sequence', union_type, 'option', 8, (4, )) self.assertRaisesRegex(ValueError, 'must be.*sequence', union_type, 'option', 8, ((), )) self.assertRaisesRegex(TypeError, 'must be string or None', union_type, 'option', 8, ((int_type('int', 4, True), 4), )) self.assertRaisesRegex(TypeError, 'must be integer', union_type, 'option', 8, ((int_type('int', 4, True), 'x', None), )) self.assertRaisesRegex(TypeError, 'must be Type', union_type, 'option', 8, ((None, 'x'), )) # Bit size. t = union_type('option', 4, ( (int_type('int', 4, True), 'x', 0, 4), (int_type('unsigned int', 4, False), 'y', 0, 4), )) self.assertEqual(t.members, ( (int_type('int', 4, True), 'x', 0, 4), (int_type('unsigned int', 4, False), 'y', 0, 4), ))
def _get_printk_records_lockless(prog: Program, prb: Object) -> List[PrintkRecord]: ulong_size = sizeof(prog.type("unsigned long")) DESC_SV_BITS = ulong_size * 8 DESC_FLAGS_SHIFT = DESC_SV_BITS - 2 DESC_FLAGS_MASK = 3 << DESC_FLAGS_SHIFT DESC_ID_MASK = DESC_FLAGS_MASK ^ ((1 << DESC_SV_BITS) - 1) LOG_CONT = prog["LOG_CONT"].value_() desc_committed = prog["desc_committed"].value_() desc_finalized = prog["desc_finalized"].value_() def record_committed(current_id: int, state_var: int) -> bool: state_desc_id = state_var & DESC_ID_MASK state = 3 & (state_var >> DESC_FLAGS_SHIFT) return (current_id == state_desc_id) and (state == desc_committed or state == desc_finalized) desc_ring = prb.desc_ring descs = desc_ring.descs.read_() infos = desc_ring.infos.read_() desc_ring_mask = (1 << desc_ring.count_bits.value_()) - 1 text_data_ring = prb.text_data_ring text_data_ring_data = text_data_ring.data.read_() text_data_ring_mask = (1 << text_data_ring.size_bits) - 1 result = [] def add_record(current_id: int) -> None: idx = current_id & desc_ring_mask desc = descs[idx].read_() if not record_committed(current_id, desc.state_var.counter.value_()): return lpos_begin = desc.text_blk_lpos.begin & text_data_ring_mask lpos_next = desc.text_blk_lpos.next & text_data_ring_mask lpos_begin += ulong_size if lpos_begin == lpos_next: # Data-less record. return if lpos_begin > lpos_next: # Data wrapped. lpos_begin -= lpos_begin info = infos[idx].read_() text_len = info.text_len if lpos_next - lpos_begin < text_len: # Truncated record. text_len = lpos_next - lpos_begin caller_tid, caller_cpu = _caller_id(info.caller_id.value_()) context = {} subsystem = info.dev_info.subsystem.string_() device = info.dev_info.device.string_() if subsystem: context[b"SUBSYSTEM"] = subsystem if device: context[b"DEVICE"] = device result.append( PrintkRecord( text=prog.read(text_data_ring_data + lpos_begin, text_len), facility=info.facility.value_(), level=info.level.value_(), seq=info.seq.value_(), timestamp=info.ts_nsec.value_(), caller_tid=caller_tid, caller_cpu=caller_cpu, continuation=bool(info.flags.value_() & LOG_CONT), context=context, )) head_id = desc_ring.head_id.counter.value_() current_id = desc_ring.tail_id.counter.value_() while current_id != head_id: add_record(current_id) current_id = (current_id + 1) & DESC_ID_MASK add_record(current_id) return result
def slab_cache_for_each_allocated_object( slab_cache: Object, type: Union[str, Type] ) -> Iterator[Object]: """ Iterate over all allocated objects in a given slab cache. Only the SLUB and SLAB allocators are supported; SLOB does not store enough information to identify objects in a slab cache. >>> dentry_cache = find_slab_cache(prog, "dentry") >>> next(slab_cache_for_each_allocated_object(dentry_cache, "struct dentry")) *(struct dentry *)0xffff905e41404000 = { ... } :param slab_cache: ``struct kmem_cache *`` :param type: Type of object in the slab cache. :return: Iterator of ``type *`` objects. """ prog = slab_cache.prog_ slab_cache_size = slab_cache.size.value_() pointer_type = prog.pointer_type(prog.type(type)) try: freelist_type = prog.type("freelist_idx_t *") slub = False except LookupError: slub = True if slub: try: red_left_pad = slab_cache.red_left_pad.value_() except AttributeError: red_left_pad = 0 # In SLUB, the freelist is a linked list with the next pointer located # at ptr + slab_cache->offset. try: freelist_offset = slab_cache.offset.value_() except AttributeError: raise ValueError("SLOB is not supported") from None # If CONFIG_SLAB_FREELIST_HARDENED is enabled, then the next pointer is # obfuscated using slab_cache->random. try: freelist_random = slab_cache.random.value_() except AttributeError: def _freelist_dereference(ptr_addr: int) -> int: return prog.read_word(ptr_addr) else: ulong_size = sizeof(prog.type("unsigned long")) def _freelist_dereference(ptr_addr: int) -> int: # *ptr_addr ^ slab_cache->random ^ byteswap(ptr_addr) return ( prog.read_word(ptr_addr) ^ freelist_random ^ int.from_bytes(ptr_addr.to_bytes(ulong_size, "little"), "big") ) def _slub_get_freelist(freelist: Object, freelist_set: Set[int]) -> None: ptr = freelist.value_() while ptr: freelist_set.add(ptr) ptr = _freelist_dereference(ptr + freelist_offset) cpu_freelists: Set[int] = set() cpu_slab = slab_cache.cpu_slab.read_() # Since Linux kernel commit bb192ed9aa71 ("mm/slub: Convert most struct # page to struct slab by spatch") (in v5.17), the current slab for a # CPU is `struct slab *slab`. Before that, it is `struct page *page`. cpu_slab_attr = "slab" if hasattr(cpu_slab, "slab") else "page" for cpu in for_each_online_cpu(prog): this_cpu_slab = per_cpu_ptr(cpu_slab, cpu) slab = getattr(this_cpu_slab, cpu_slab_attr).read_() if slab and slab.slab_cache == slab_cache: _slub_get_freelist(this_cpu_slab.freelist, cpu_freelists) def _slab_page_objects(page: Object, slab: Object) -> Iterator[Object]: freelist: Set[int] = set() _slub_get_freelist(slab.freelist, freelist) addr = page_to_virt(page).value_() + red_left_pad end = addr + slab_cache_size * slab.objects while addr < end: if addr not in freelist and addr not in cpu_freelists: yield Object(prog, pointer_type, value=addr) addr += slab_cache_size else: try: obj_offset = slab_cache.obj_offset.value_() except AttributeError: obj_offset = 0 slab_cache_num = slab_cache.num.value_() cpu_cache = slab_cache.cpu_cache.read_() cpu_caches_avail: Set[int] = set() for cpu in for_each_online_cpu(prog): ac = per_cpu_ptr(cpu_cache, cpu) for i in range(ac.avail): cpu_caches_avail.add(ac.entry[i].value_()) def _slab_freelist(slab: Object) -> Set[int]: # In SLAB, the freelist is an array of free object indices. freelist = cast(freelist_type, slab.freelist) return {freelist[i].value_() for i in range(slab.active, slab_cache_num)} def _slab_page_objects(page: Object, slab: Object) -> Iterator[Object]: freelist = _slab_freelist(slab) s_mem = slab.s_mem.value_() for i in range(slab_cache_num): if i in freelist: continue addr = s_mem + i * slab_cache_size + obj_offset if addr in cpu_caches_avail: continue yield Object(prog, pointer_type, value=addr) # Linux kernel commit d122019bf061cccc4583eb9ad40bf58c2fe517be ("mm: Split # slab into its own type") (in v5.17) moved slab information from struct # page to struct slab. The former can be casted to the latter. try: slab_type = prog.type("struct slab *") except LookupError: slab_type = prog.type("struct page *") PG_slab_mask = 1 << prog.constant("PG_slab") for page in for_each_page(prog): try: if not page.flags & PG_slab_mask: continue except FaultError: continue slab = cast(slab_type, page) if slab.slab_cache == slab_cache: yield from _slab_page_objects(page, slab)
def test_class(self): t = self.prog.class_type( "coord", 12, ( TypeMember(self.prog.int_type("int", 4, True), "x", 0), TypeMember(self.prog.int_type("int", 4, True), "y", 32), TypeMember(self.prog.int_type("int", 4, True), "z", 64), ), ) self.assertEqual(t.kind, TypeKind.CLASS) self.assertIsNone(t.primitive) self.assertEqual(t.language, DEFAULT_LANGUAGE) self.assertEqual(t.tag, "coord") self.assertEqual(t.size, 12) self.assertIdentical( t.members, ( TypeMember(self.prog.int_type("int", 4, True), "x", 0), TypeMember(self.prog.int_type("int", 4, True), "y", 32), TypeMember(self.prog.int_type("int", 4, True), "z", 64), ), ) self.assertTrue(t.is_complete()) self.assertEqual( repr(t), "prog.class_type(tag='coord', size=12, members=(TypeMember(prog.type('int'), name='x', bit_offset=0), TypeMember(prog.type('int'), name='y', bit_offset=32), TypeMember(prog.type('int'), name='z', bit_offset=64)))", ) self.assertEqual(sizeof(t), 12) t = self.prog.class_type( None, 12, ( TypeMember(self.prog.int_type("int", 4, True), "x", 0), TypeMember(self.prog.int_type("int", 4, True), "y", 32), TypeMember(self.prog.int_type("int", 4, True), "z", 64), ), ) self.assertEqual(t.kind, TypeKind.CLASS) self.assertIsNone(t.primitive) self.assertIsNone(t.tag) self.assertEqual(t.size, 12) self.assertIdentical( t.members, ( TypeMember(self.prog.int_type("int", 4, True), "x", 0), TypeMember(self.prog.int_type("int", 4, True), "y", 32), TypeMember(self.prog.int_type("int", 4, True), "z", 64), ), ) self.assertTrue(t.is_complete()) t = self.prog.class_type("color", 0, ()) self.assertEqual(t.kind, TypeKind.CLASS) self.assertIsNone(t.primitive) self.assertEqual(t.tag, "color") self.assertEqual(t.size, 0) self.assertEqual(t.members, ()) self.assertTrue(t.is_complete()) self.assertEqual(repr(t), "prog.class_type(tag='color', size=0, members=())") t = self.prog.class_type("color") self.assertEqual(t.kind, TypeKind.CLASS) self.assertIsNone(t.primitive) self.assertEqual(t.tag, "color") self.assertIsNone(t.size) self.assertIsNone(t.members) self.assertFalse(t.is_complete()) self.assertEqual( repr(t), "prog.class_type(tag='color', size=None, members=None)") t = self.prog.class_type(None, None, None) self.assertEqual(t.kind, TypeKind.CLASS) self.assertIsNone(t.primitive) self.assertEqual(t.tag, None) self.assertIsNone(t.size) self.assertIsNone(t.members) self.assertFalse(t.is_complete()) self.assertEqual(repr(t), "prog.class_type(tag=None, size=None, members=None)") self.assertRaises(TypeError, self.prog.class_type, 4) self.assertRaisesRegex(ValueError, "must not have size", self.prog.class_type, "coord", 12, None) self.assertRaisesRegex(ValueError, "must have size", self.prog.class_type, "coord", None, ()) self.assertRaisesRegex(TypeError, "must be sequence or None", self.prog.class_type, "coord", 12, 4) self.assertRaisesRegex(TypeError, "must be TypeMember", self.prog.class_type, "coord", 12, (4, )) # Bit size. t = self.prog.class_type( "coord", 12, ( TypeMember( Object(self.prog, self.prog.int_type("int", 4, True), bit_field_size=4), "x", 0, ), TypeMember( Object(self.prog, self.prog.int_type("int", 4, True), bit_field_size=4), "y", 32, ), TypeMember( Object(self.prog, self.prog.int_type("int", 4, True), bit_field_size=4), "z", 64, ), ), ) self.assertIdentical( t.members, ( TypeMember( Object(self.prog, self.prog.int_type("int", 4, True), bit_field_size=4), "x", 0, ), TypeMember( Object(self.prog, self.prog.int_type("int", 4, True), bit_field_size=4), "y", 32, ), TypeMember( Object(self.prog, self.prog.int_type("int", 4, True), bit_field_size=4), "z", 64, ), ), )
def test_union(self): t = self.prog.union_type( "option", 4, ( TypeMember(self.prog.int_type("int", 4, True), "x"), TypeMember(self.prog.int_type("unsigned int", 4, False), "y"), ), ) self.assertEqual(t.kind, TypeKind.UNION) self.assertIsNone(t.primitive) self.assertEqual(t.language, DEFAULT_LANGUAGE) self.assertEqual(t.tag, "option") self.assertEqual(t.size, 4) self.assertIdentical( t.members, ( TypeMember(self.prog.int_type("int", 4, True), "x", 0), TypeMember(self.prog.int_type("unsigned int", 4, False), "y", 0), ), ) self.assertTrue(t.is_complete()) self.assertEqual( repr(t), "prog.union_type(tag='option', size=4, members=(TypeMember(prog.type('int'), name='x', bit_offset=0), TypeMember(prog.type('unsigned int'), name='y', bit_offset=0)))", ) self.assertEqual(sizeof(t), 4) t = self.prog.union_type( None, 4, ( TypeMember(self.prog.int_type("int", 4, True), "x"), TypeMember(self.prog.int_type("unsigned int", 4, False), "y"), ), ) self.assertEqual(t.kind, TypeKind.UNION) self.assertIsNone(t.primitive) self.assertIsNone(t.tag) self.assertEqual(t.size, 4) self.assertIdentical( t.members, ( TypeMember(self.prog.int_type("int", 4, True), "x", 0), TypeMember(self.prog.int_type("unsigned int", 4, False), "y", 0), ), ) self.assertTrue(t.is_complete()) t = self.prog.union_type("color", 0, ()) self.assertEqual(t.kind, TypeKind.UNION) self.assertIsNone(t.primitive) self.assertEqual(t.tag, "color") self.assertEqual(t.size, 0) self.assertEqual(t.members, ()) self.assertTrue(t.is_complete()) self.assertEqual(repr(t), "prog.union_type(tag='color', size=0, members=())") t = self.prog.union_type("color") self.assertEqual(t.kind, TypeKind.UNION) self.assertIsNone(t.primitive) self.assertEqual(t.tag, "color") self.assertIsNone(t.size) self.assertIsNone(t.members) self.assertFalse(t.is_complete()) self.assertEqual( repr(t), "prog.union_type(tag='color', size=None, members=None)") t = self.prog.union_type(None, None, None) self.assertEqual(t.kind, TypeKind.UNION) self.assertIsNone(t.primitive) self.assertEqual(t.tag, None) self.assertIsNone(t.size) self.assertIsNone(t.members) self.assertFalse(t.is_complete()) self.assertEqual(repr(t), "prog.union_type(tag=None, size=None, members=None)") self.assertRaises(TypeError, self.prog.union_type, 4) self.assertRaisesRegex(ValueError, "must not have size", self.prog.union_type, "option", 8, None) self.assertRaisesRegex(ValueError, "must have size", self.prog.union_type, "option", None, ()) self.assertRaisesRegex(TypeError, "must be sequence or None", self.prog.union_type, "option", 8, 4) self.assertRaisesRegex(TypeError, "must be TypeMember", self.prog.union_type, "option", 8, (4, )) # Bit size. t = self.prog.union_type( "option", 4, ( TypeMember( Object(self.prog, self.prog.int_type("int", 4, True), bit_field_size=4), "x", 0, ), TypeMember( Object( self.prog, self.prog.int_type("unsigned int", 4, False), bit_field_size=4, ), "y", 0, ), ), ) self.assertIdentical( t.members, ( TypeMember( Object(self.prog, self.prog.int_type("int", 4, True), bit_field_size=4), "x", 0, ), TypeMember( Object( self.prog, self.prog.int_type("unsigned int", 4, False), bit_field_size=4, ), "y", 0, ), ), )