Пример #1
0
    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,
        )
Пример #2
0
    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)
Пример #3
0
    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)
Пример #4
0
    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))
Пример #5
0
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
Пример #6
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)
Пример #7
0
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
Пример #8
0
    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)
Пример #9
0
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
Пример #10
0
    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]]])
Пример #11
0
    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)
Пример #12
0
    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)
Пример #13
0
Файл: fs.py Проект: osandov/drgn
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
Пример #14
0
    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)
Пример #15
0
    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),
        )
Пример #16
0
    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,
        )
Пример #17
0
    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)
Пример #18
0
    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)
Пример #19
0
    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)
Пример #20
0
    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)
Пример #21
0
    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}
        )
Пример #22
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, ),
        )
Пример #23
0
    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),
            ),
        )
Пример #24
0
    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), ))
Пример #25
0
    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),
        ))
Пример #26
0
    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),
        ))
Пример #27
0
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
Пример #28
0
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)
Пример #29
0
    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,
                ),
            ),
        )
Пример #30
0
    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,
                ),
            ),
        )