Skip to content

data_type

ArrayType

Bases: ComplexType

Array type

Parameters:

Name Type Description Default
proto CompositeType

Protobuf data

required
program Program

Back reference to the program

required

Attributes:

Name Type Description
name str

Type name

size

Type size (if known)

c_str

C declaration of the type

Source code in bindings/python/quokka/data_type.py
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
class ArrayType(ComplexType):
    """Array type

    Arguments:
        proto: Protobuf data
        program: Back reference to the program

    Attributes:
        name: Type name
        size: Type size (if known)
        c_str: C declaration of the type
    """
    def __init__(self, index: Index, proto: Pb.CompositeType, program: "Program") -> None:
        """Constructor"""
        super().__init__(index, proto, program)

    @property
    def array_size(self) -> int:
        """Return the number of items in the array"""
        return self.proto.size // self.element_type.size if self.element_type.size > 0 else 0

    @property
    def element_type(self) -> 'TypeT':
        """Return the type of the array elements"""
        return self._program.get_type(self.proto.element_type_idx)

    def __str__(self) -> str:
        return f"<TArray: {self.name} {self.element_type}[{self.size}]>"

array_size property

Return the number of items in the array

element_type property

Return the type of the array elements

__init__(index, proto, program)

Constructor

Source code in bindings/python/quokka/data_type.py
268
269
270
def __init__(self, index: Index, proto: Pb.CompositeType, program: "Program") -> None:
    """Constructor"""
    super().__init__(index, proto, program)

BaseType

Bases: CoreType, IntEnum

Data Type

Source code in bindings/python/quokka/data_type.py
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
class BaseType(CoreType, IntEnum, metaclass=EnumABCMeta):
    """Data Type"""

    UNKNOWN = 0
    BYTE = 1
    WORD = 2
    DOUBLE_WORD = 3
    QUAD_WORD = 4
    OCTO_WORD = 5
    FLOAT = 6
    DOUBLE = 7
    VOID = 8

    @staticmethod
    def from_proto(data_type: Pb.BaseType) -> "BaseType":
        """Convert the protobuf value into this enumeration"""
        return BaseType(data_type)

    @property
    def size(self) -> int:
        """Size of the data type in bytes"""
        mapping = {
            BaseType.BYTE: 1,
            BaseType.WORD: 2,
            BaseType.DOUBLE_WORD: 4,
            BaseType.QUAD_WORD: 8,
            BaseType.OCTO_WORD: 16,
            BaseType.FLOAT: 4,
            BaseType.DOUBLE: 8,
            BaseType.VOID: 0,
        }

        return mapping.get(self, 0)

    def __str__(self) -> str:
        """String representation of the data type"""
        ts = {
            BaseType.UNKNOWN: "unknown",
            BaseType.BYTE: "char",
            BaseType.WORD: "short",
            BaseType.DOUBLE_WORD: "int",
            BaseType.QUAD_WORD: "int64_t",
            BaseType.OCTO_WORD: "int128_t",
            BaseType.FLOAT: "float",
            BaseType.DOUBLE: "double",
            BaseType.VOID: "void",
        }[self]
        return f"<T:{ts}>"

    @property
    def type_index(self) -> int:
        """Return the protobuf type index of this type"""
        return self.value

    @property
    def c_str(self) -> str:
        """Return the C declaration of this type"""
        return str(self)

c_str property

Return the C declaration of this type

size property

Size of the data type in bytes

type_index property

Return the protobuf type index of this type

__str__()

String representation of the data type

Source code in bindings/python/quokka/data_type.py
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
def __str__(self) -> str:
    """String representation of the data type"""
    ts = {
        BaseType.UNKNOWN: "unknown",
        BaseType.BYTE: "char",
        BaseType.WORD: "short",
        BaseType.DOUBLE_WORD: "int",
        BaseType.QUAD_WORD: "int64_t",
        BaseType.OCTO_WORD: "int128_t",
        BaseType.FLOAT: "float",
        BaseType.DOUBLE: "double",
        BaseType.VOID: "void",
    }[self]
    return f"<T:{ts}>"

from_proto(data_type) staticmethod

Convert the protobuf value into this enumeration

Source code in bindings/python/quokka/data_type.py
77
78
79
80
@staticmethod
def from_proto(data_type: Pb.BaseType) -> "BaseType":
    """Convert the protobuf value into this enumeration"""
    return BaseType(data_type)

ComplexType

Bases: CoreType

Source code in bindings/python/quokka/data_type.py
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
class ComplexType(CoreType):
    def __init__(self, proto_index: Index, proto: Pb.CompositeType|Pb.EnumType, program: "Program"):
        self.type_index = proto_index
        self.proto = proto
        self._program = program

        self.name: str = proto.name
        # type is not used here
        self.size = proto.size if hasattr(proto, "size") else 0
        self.c_str = proto.c_str

        # Xrefs attached to the type itself
        self._xrefs_to = [self._program.proto.references[x] for x in proto.xref_to]
        self._xrefs_to = [(RefType(ref.reference_type), ref) for ref in self._xrefs_to]

    @property
    def comments(self) -> list[str]:
        """Return the type comments"""
        return self.proto.comments if hasattr(self.proto, "comments") else []

    @property
    def data_refs_to(self) -> list['Data']:
        """Returns all data reference to this type"""
        # Get protobuf type ids
        return [self._program.data_holder[xref.source.address] for t, xref in self._xrefs_to if t.is_data]

    @property
    def data_read_refs_to(self) -> list['Data']:
        """Returns all data read reference to this instruction"""
        return [self._program.data_holder[xref.source.address] for t, xref in self._xrefs_to if t in [RefType.DATA_READ, RefType.DATA_INDIR]]

    @property
    def data_write_refs_to(self) -> list['Data']:
        """Returns all data write reference to this instruction"""
        return [self._program.data_holder[xref.source.address] for t, xref in self._xrefs_to if t == RefType.DATA_WRITE]

comments property

Return the type comments

data_read_refs_to property

Returns all data read reference to this instruction

data_refs_to property

Returns all data reference to this type

data_write_refs_to property

Returns all data write reference to this instruction

CoreType

Bases: ABC

Abstract base class for all types in quokka

Source code in bindings/python/quokka/data_type.py
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
class CoreType(ABC):
    """Abstract base class for all types in quokka"""

    @property
    def is_member(self) -> bool:
        """Return True if this type is a member (StructureTypeMember or EnumTypeMember)"""
        return False

    @property
    def is_base_type(self) -> bool:
        """Return True if this type is a base type"""
        return isinstance(self, BaseType)

    @property
    def is_enum(self) -> bool:
        """Return True if this type is an enum"""
        return isinstance(self, EnumType)

    @property
    def is_struct(self) -> bool:
        """Return True if this type is a structure"""
        return isinstance(self, StructureType)

    @property
    def is_union(self) -> bool:
        """Return True if this type is a union"""
        return isinstance(self, UnionType)

    @property
    def is_array(self) -> bool:
        """Return True if this type is an array"""
        return isinstance(self, ArrayType)

    @property
    def is_pointer(self) -> bool:
        """Return True if this type is a pointer"""
        return isinstance(self, PointerType)

    @property
    def is_composite(self) -> bool:
        """Return True if this type is a composite type (struct, union, array, pointer)"""
        return isinstance(self, ComplexType)

is_array property

Return True if this type is an array

is_base_type property

Return True if this type is a base type

is_composite property

Return True if this type is a composite type (struct, union, array, pointer)

is_enum property

Return True if this type is an enum

is_member property

Return True if this type is a member (StructureTypeMember or EnumTypeMember)

is_pointer property

Return True if this type is a pointer

is_struct property

Return True if this type is a structure

is_union property

Return True if this type is a union

EnumABCMeta

Bases: EnumMeta, ABCMeta

Combined metaclass for ABC + Enum compatibility

Source code in bindings/python/quokka/data_type.py
59
60
61
class EnumABCMeta(EnumMeta, ABCMeta):
    """Combined metaclass for ABC + Enum compatibility"""
    pass

EnumType

Bases: ComplexType

Base class for all enums in quokka

Source code in bindings/python/quokka/data_type.py
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
class EnumType(ComplexType):
    """Base class for all enums in quokka"""

    def __init__(self, index: Index, proto: Pb.EnumType, program: "Program") -> None:
        """Create an enum from a protobuf enum value"""
        super().__init__(index, proto, program)
        self.name = proto.name
        self._members: dict[str, EnumTypeMember] = {member.name: EnumTypeMember(member, self) 
                                                    for member in proto.values}
        self._members_by_idx = [self._members[x.name] for x in proto.values]
        self.size = self.base_type.size

    @property
    def base_type(self) -> BaseType:
        """Return the base type of the enum"""
        typ = self._program.get_type(self.proto.base_type)
        assert isinstance(typ, BaseType)
        return typ

    @property
    def members(self) -> Iterable[EnumTypeMember]:
        """Return the enum members as a mapping from member names to members"""
        return iter(self)

    def __iter__(self):
        """Iterate over the enum members"""
        return iter(self._members.values())

    def __getitem__(self, key: int) -> EnumTypeMember:
        return self._members_by_idx[key]

    def __getattr__(self, name):
        if name in self._members:
            return self._members[name]
        else:
            return super().__getattribute__(name)

    def __str__(self) -> str:
        return f"<TEnum: {self.name}>"

base_type property

Return the base type of the enum

members property

Return the enum members as a mapping from member names to members

__init__(index, proto, program)

Create an enum from a protobuf enum value

Source code in bindings/python/quokka/data_type.py
219
220
221
222
223
224
225
226
def __init__(self, index: Index, proto: Pb.EnumType, program: "Program") -> None:
    """Create an enum from a protobuf enum value"""
    super().__init__(index, proto, program)
    self.name = proto.name
    self._members: dict[str, EnumTypeMember] = {member.name: EnumTypeMember(member, self) 
                                                for member in proto.values}
    self._members_by_idx = [self._members[x.name] for x in proto.values]
    self.size = self.base_type.size

__iter__()

Iterate over the enum members

Source code in bindings/python/quokka/data_type.py
240
241
242
def __iter__(self):
    """Iterate over the enum members"""
    return iter(self._members.values())

EnumTypeMember

Bases: CoreType

EnumTypeMember

This class represents enum members.

Parameters:

Name Type Description Default
member EnumValue

Protobuf data

required
enum_type EnumType

Reference to the parent enum type

required

Attributes:

Name Type Description
name str

Member name

size int

Member size (if known)

value int

Member value

comments list[str]

Member comments

Source code in bindings/python/quokka/data_type.py
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
class EnumTypeMember(CoreType):
    """EnumTypeMember

    This class represents enum members.

    Arguments:
        member: Protobuf data
        enum_type: Reference to the parent enum type

    Attributes:
        name: Member name
        size: Member size (if known)
        value: Member value
        comments: Member comments
    """

    def __init__(self, member: "Pb.EnumType.EnumValue", enum_type: "EnumType") -> None:
        """Constructor"""
        self.proto = member
        self.name: str = member.name
        self.value: int = member.value
        self.size: int = enum_type.size
        self._enum_type: weakref.ref[EnumType] = weakref.ref(enum_type)
        self._xrefs_to = [enum_type._program.proto.references[x] for x in member.xref_to]

    @property
    def base_type(self) -> BaseType:
        """Return the base type of the enum member"""
        return self._enum_type().base_type # type: ignore

    @property
    def comments(self) -> list[str]:
        """Return the enum member comments"""
        return self.proto.comments

    @property
    def parent(self) -> "EnumType":
        """Back reference to the parent enum"""
        return self._enum_type() # type: ignore

    @property
    def data_refs_to(self) -> list['Data']:
        """Returns all data reference to this type"""
        # Get protobuf type ids
        return [self.parent._program.data_holder[xref.source.address] for xref in self._xrefs_to 
                if RefType.from_proto(xref.reference_type).is_data]

    @property
    def is_member(self) -> bool:
        return True

    def __str__(self) -> str:
        return f"<TEnumTypeMember: {self.parent.name}.{self.name}>"

base_type property

Return the base type of the enum member

comments property

Return the enum member comments

data_refs_to property

Returns all data reference to this type

parent property

Back reference to the parent enum

__init__(member, enum_type)

Constructor

Source code in bindings/python/quokka/data_type.py
177
178
179
180
181
182
183
184
def __init__(self, member: "Pb.EnumType.EnumValue", enum_type: "EnumType") -> None:
    """Constructor"""
    self.proto = member
    self.name: str = member.name
    self.value: int = member.value
    self.size: int = enum_type.size
    self._enum_type: weakref.ref[EnumType] = weakref.ref(enum_type)
    self._xrefs_to = [enum_type._program.proto.references[x] for x in member.xref_to]

PointerType

Bases: ComplexType

Pointer type

Parameters:

Name Type Description Default
proto CompositeType

Protobuf data

required
program Program

Back reference to the program

required

Attributes:

Name Type Description
name str

Type name

size

Type size (if known)

c_str

C declaration of the type

Source code in bindings/python/quokka/data_type.py
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
class PointerType(ComplexType):
    """Pointer type

    Arguments:
        proto: Protobuf data
        program: Back reference to the program

    Attributes:
        name: Type name
        size: Type size (if known)
        c_str: C declaration of the type
    """
    def __init__(self, index: Index, proto: Pb.CompositeType, program: "Program") -> None:
        """Constructor"""
        super().__init__(index, proto, program)

    @property
    def pointed_type(self) -> 'TypeT':
        """Return the type of the pointed element"""
        return self._program.get_type(self.proto.element_type_idx)

    def __str__(self) -> str:
        return f"<TPtr: {self.name}->{self.pointed_type}*>"

pointed_type property

Return the type of the pointed element

__init__(index, proto, program)

Constructor

Source code in bindings/python/quokka/data_type.py
297
298
299
def __init__(self, index: Index, proto: Pb.CompositeType, program: "Program") -> None:
    """Constructor"""
    super().__init__(index, proto, program)

StructureType

Bases: dict, ComplexType

Structure

Members are stored in a dict keyed by bit offset and also in an ordered list (_members_list) for positional access.

Parameters:

Name Type Description Default
structure

Structure protobuf data

required
program Program

Program back reference

required

Attributes:

Name Type Description
program

Program backreference

name str

Structure name

size

Structure size (if known)

type

Structure type

comments list[str]

Structure comments

Source code in bindings/python/quokka/data_type.py
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
class StructureType(dict, ComplexType):
    """Structure

    Members are stored in a dict keyed by **bit offset** and also in an ordered
    list (``_members_list``) for positional access.

    Arguments:
        structure: Structure protobuf data
        program: Program back reference

    Attributes:
        program: Program backreference
        name: Structure name
        size: Structure size (if known)
        type: Structure type
        comments: Structure comments
    """

    def __init__(self, index: Index, proto: "Pb.CompositeType", program: "Program") -> None:
        """Constructor"""
        dict.__init__(self)
        ComplexType.__init__(self, index, proto, program)

        # self.index_to_offset: dict[int, int] = {}
        for index, member in enumerate(proto.members):
            self[index] = StructureTypeMember(member, self)

    @cached_property
    def members(self) -> list[StructureTypeMember]:
        """Return all members in declaration order"""
        return list(x[1] for x in sorted(self.items(), key=lambda x: x[0]))

    def is_variable_size(self) -> bool:
        """Is the structure of variable size?"""
        return self.size <= 0

    def __str__(self) -> str:
        return f"<TStruct: {self.name}>"

members cached property

Return all members in declaration order

__init__(index, proto, program)

Constructor

Source code in bindings/python/quokka/data_type.py
387
388
389
390
391
392
393
394
def __init__(self, index: Index, proto: "Pb.CompositeType", program: "Program") -> None:
    """Constructor"""
    dict.__init__(self)
    ComplexType.__init__(self, index, proto, program)

    # self.index_to_offset: dict[int, int] = {}
    for index, member in enumerate(proto.members):
        self[index] = StructureTypeMember(member, self)

is_variable_size()

Is the structure of variable size?

Source code in bindings/python/quokka/data_type.py
401
402
403
def is_variable_size(self) -> bool:
    """Is the structure of variable size?"""
    return self.size <= 0

StructureTypeMember

Bases: CoreType

StructureMember

This class represents structure members (fields).

Parameters:

Name Type Description Default
member Member

Protobuf data

required
structure StructureType

Reference to the parent structure

required

Attributes:

Name Type Description
name str

Member name

offset int

Bit offset within the parent composite type

size int

Member size in bits (0 for variable-length members)

type TypeT

Member data type

comments list[str]

Member comments

Source code in bindings/python/quokka/data_type.py
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
class StructureTypeMember(CoreType):
    """StructureMember

    This class represents structure members (fields).

    Arguments:
        member: Protobuf data
        structure: Reference to the parent structure

    Attributes:
        name: Member name
        offset: Bit offset within the parent composite type
        size: Member size in bits (0 for variable-length members)
        type: Member data type
        comments: Member comments
    """

    def __init__(self, member: "Pb.CompositeType.Member", structure: "StructureType") -> None:
        """Constructor"""
        self.proto = member
        self.name: str = member.name
        self.offset: int = member.offset  # Bit offset within composite
        self.size: int = member.size  # Size in bits
        self._structure: weakref.ref[StructureType] = weakref.ref(structure)
        self._xrefs_to = [structure._program.proto.references[x] for x in member.xref_to]

    @property
    def comments(self) -> list[str]:
        """Return the structure member comments"""
        return self.proto.comments

    @property
    def type(self) -> 'TypeT':
        """Return the type of the member"""
        return self.parent._program.get_type(self.proto.type_index)

    @property
    def parent(self) -> "StructureType":
        """Back reference to the parent structure"""
        return self._structure() # type: ignore

    @property
    def data_refs_to(self) -> list['AddressT']:
        """Returns all data reference to this type.

        Addresses can originates from code or data."""
        # Get protobuf type ids
        return [xref.source.address for xref in self._xrefs_to 
                if RefType.from_proto(xref.reference_type).is_data]

    @property
    def is_member(self) -> bool:
        return True

    def __str__(self) -> str:
        t = "Struct" if self.parent.is_struct else "Union"
        return f"<T{t}Member: {self.parent.name}.{self.name}>"

comments property

Return the structure member comments

data_refs_to property

Returns all data reference to this type.

Addresses can originates from code or data.

parent property

Back reference to the parent structure

type property

Return the type of the member

__init__(member, structure)

Constructor

Source code in bindings/python/quokka/data_type.py
327
328
329
330
331
332
333
334
def __init__(self, member: "Pb.CompositeType.Member", structure: "StructureType") -> None:
    """Constructor"""
    self.proto = member
    self.name: str = member.name
    self.offset: int = member.offset  # Bit offset within composite
    self.size: int = member.size  # Size in bits
    self._structure: weakref.ref[StructureType] = weakref.ref(structure)
    self._xrefs_to = [structure._program.proto.references[x] for x in member.xref_to]

UnionType

Bases: StructureType

Union

This class represents a union. It is a special case of structure where all members are at the same offset. To avoid dict-key collisions the dict is keyed by positional index instead of offset.

Parameters:

Name Type Description Default
structure

Structure protobuf data

required
program Program

Program back reference

required
Source code in bindings/python/quokka/data_type.py
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
class UnionType(StructureType):
    """Union

    This class represents a union. It is a special case of structure where all members are at the same offset.
    To avoid dict-key collisions the
    dict is keyed by **positional index** instead of offset.

    Arguments:
        structure: Structure protobuf data
        program: Program back reference
    """

    def __init__(self, proto: "Pb.CompositeType", program: "Program") -> None:
        dict.__init__(self)
        ComplexType.__init__(self, proto, program)

        self._members_list: list[StructureTypeMember] = []
        self.index_to_offset: dict[int, int] = {}
        for index, member in enumerate(proto.members):
            m = StructureTypeMember(member, self)
            self._members_list.append(m)
            self[index] = m
            self.index_to_offset[index] = member.offset

    def __str__(self) -> str:
        return f"<TUnion: {self.name}>"