Example #1
0
class HashedMapPrinter(BaseMapPrinter):
    """Pretty-print Ada.Containers.Hashed_Maps.Map values."""

    name = "Hashed_Map"

    type_pattern = Match.TypeName(
        suffix=".map",
        pattern=Match.Struct(
            Match.Field("_parent"),
            Match.Field(
                "ht",
                get_htable_pattern(
                    Match.Struct(
                        Match.Field("key"),
                        Match.Field("element"),
                        Match.Field("next", Match.Pointer()),
                    )),
            ),
        ),
    )

    @property
    def length(self):
        return self.value["ht"]["length"]

    def get_node_iterator(self):
        return iterate(self.value["ht"])
Example #2
0
class HashedMapPrinter(BaseMapPrinter):
    """Pretty-print Ada.Containers.Hashed_Maps.Map values."""

    name = 'Hashed_Map'

    type_pattern = Match.TypeName(suffix='.map',
                                  pattern=Match.Struct(
                                      Match.Field('_parent'),
                                      Match.Field(
                                          'ht',
                                          get_htable_pattern(
                                              Match.Struct(
                                                  Match.Field('key'),
                                                  Match.Field('element'),
                                                  Match.Field(
                                                      'next', Match.Pointer()),
                                              ))),
                                  ))

    @property
    def length(self):
        return self.value['ht']['length']

    def get_node_iterator(self):
        return iterate(self.value['ht'])
Example #3
0
class HashedMapCursorPrinter(PrettyPrinter):
    """Pretty-print Ada.Containers.Hashed_Maps.Cursor values."""

    name = "Hashed_Map_Cursor"

    type_pattern = Match.TypeName(
        suffix=".cursor",
        pattern=Match.Struct(
            Match.Field("container",
                        Match.Pointer(HashedMapPrinter.type_pattern)),
            Match.Field("node", Match.Pointer()),
            Match.Field("position",
                        Match.TypeName(name="ada.containers.hash_type")),
        ),
    )

    def to_string(self):
        if self.value["container"]:
            assoc = "{} => {}".format(
                self.value["node"]["key"],
                self.value["node"]["element"],
            )
        else:
            assoc = "No_Element"
        return "Cursor ({})".format(assoc)
def get_rbtree_pattern(node_pattern):
    """
    Return the type pattern for red-black trees used in GNAT's implementation
    of standard containers for nodes that match the given `node_pattern`.
    """
    node_access_pattern = Match.Pointer(node_pattern)
    return Match.Struct(
        Match.Field("_tag"),
        Match.Field("first", node_access_pattern),
        Match.Field("last", node_access_pattern),
        Match.Field("root", node_access_pattern),
        Match.Field("length", Match.Integer()),
        Match.Field("tc"),
    )
Example #5
0
class TimePrettyPrinter(PrettyPrinter):
    name = "main.time"
    type_pattern = Match.TypeName(
        name=re.compile('universal_calendar__(T?)time(B?).*'),
        recursive=True,
        match_pretty_name=False,
    )

    def to_string(self):
        return 'time'
Example #6
0
class StringAccess(object):
    """
    Helper class to inspect String accesses.
    """

    type_pattern = Match.Typedef(
        Match.Struct(
            Match.Field('P_ARRAY',
                        Match.Pointer(Match.Array(element=Match.Char(), ))),
            Match.Field('P_BOUNDS'),
        ))

    default_encodings = {
        1: None,
        2: 'utf-16',
        4: 'utf-32',
    }

    def __init__(self, value):
        if not self.matches(value):
            raise TypeError('Input is not an access to string')
        self.value = value

    @classmethod
    def matches(cls, value):
        """
        Return whether `value` is a string access.

        :param gdb.Value value: Value to test.
        :rtype: bool
        """
        return cls.type_pattern.match(value.type)

    @property
    def bounds(self):
        """
        Return the bounds of the accessed string.

        :rtype: (int, int)
        """
        struct = self.value['P_BOUNDS']
        return (int(struct['LB0']), int(struct['UB0']))

    @property
    def length(self):
        lb, ub = self.bounds
        return 0 if lb > ub else (ub - lb + 1)

    def get_string(self, encoding=None, errors=None):
        """
        Return the accessed string.

        :rtype: str
        """
        return _fetch_string(self.value['P_ARRAY'], self.length, encoding,
                             errors)
Example #7
0
class VectorCursorPrinter(PrettyPrinter):
    """Pretty-print Ada.Containers.Vectors.Cursor values."""

    name = 'Vector_Cursor'

    type_pattern = Match.TypeName(
        suffix='.cursor',
        pattern=Match.Struct(
            Match.Field('container',
                        Match.Pointer(VectorPrinter.type_pattern)),
            Match.Field('index', Match.Integer()),
        ))

    def to_string(self):
        if self.value['container']:
            vector = VectorPrinter(self.value['container'])
            index = self.value['index']
            try:
                element = str(vector.element(index))
            except gdb.MemoryError:
                return 'Cursor ([Invalid])'
            assoc = '{} => {}'.format(index, element)
        else:
            assoc = 'No_Element'
        return 'Cursor ({})'.format(assoc)
Example #8
0
class DoublyLinkedListCursorPrinter(PrettyPrinter):
    """Pretty-print Ada.Containers.Doubly_Linked_Lists.Cursor values."""

    name = 'Doubly_Linked_List_Cursor'

    type_pattern = Match.TypeName(
        suffix='.cursor',
        pattern=Match.Struct(
            Match.Field('container',
                        Match.Pointer(DoublyLinkedListPrinter.type_pattern)),
            Match.Field('node', Match.Pointer()),
        ))

    def display_hint(self):
        return 'array'

    def to_string(self):
        if self.value['container']:
            try:
                assoc = '{}'.format(self.value['node']['element'])
            except gdb.MemoryError:
                return 'Cursor ([Invalid])'
        else:
            assoc = 'No_Element'
        return 'Cursor ({})'.format(assoc)
Example #9
0
class DoublyLinkedListCursorPrinter(PrettyPrinter):
    """Pretty-print Ada.Containers.Doubly_Linked_Lists.Cursor values."""

    name = "Doubly_Linked_List_Cursor"

    type_pattern = Match.TypeName(
        suffix=".cursor",
        pattern=Match.Struct(
            Match.Field(
                "container",
                Match.Pointer(DoublyLinkedListPrinter.type_pattern),
            ),
            Match.Field("node", Match.Pointer()),
        ),
    )

    def display_hint(self):
        return "array"

    def to_string(self):
        if self.value["container"]:
            try:
                assoc = "{}".format(self.value["node"]["element"])
            except gdb.MemoryError:
                return "Cursor ([Invalid])"
        else:
            assoc = "No_Element"
        return "Cursor ({})".format(assoc)
Example #10
0
class VectorCursorPrinter(PrettyPrinter):
    """Pretty-print Ada.Containers.Vectors.Cursor values."""

    name = "Vector_Cursor"

    type_pattern = Match.TypeName(
        suffix=".cursor",
        pattern=Match.Struct(
            Match.Field("container",
                        Match.Pointer(VectorPrinter.type_pattern)),
            Match.Field("index", Match.Integer()),
        ),
    )

    def to_string(self):
        if self.value["container"]:
            vector = VectorPrinter(self.value["container"])
            index = self.value["index"]
            try:
                element = str(vector.element(index))
            except gdb.MemoryError:
                return "Cursor ([Invalid])"
            assoc = "{} => {}".format(index, element)
        else:
            assoc = "No_Element"
        return "Cursor ({})".format(assoc)
Example #11
0
class HashedSetCursorPrinter(PrettyPrinter):
    """Pretty-print Ada.Containers.Hashed_Sets.Cursor values."""

    name = 'Ordered_Set_Cursor'

    type_pattern = Match.TypeName(
        suffix='.cursor',
        pattern=Match.Struct(
            Match.Field('container',
                        Match.Pointer(HashedSetPrinter.type_pattern)),
            Match.Field('node', Match.Pointer()),
            Match.Field('position',
                        Match.TypeName(name='ada.containers.hash_type')),
        ))

    def to_string(self):
        if self.value['container']:
            assoc = self.value['node']['element']
        else:
            assoc = 'No_Element'
        return 'Cursor ({})'.format(assoc)
Example #12
0
class OrderedSetCursorPrinter(PrettyPrinter):
    """Pretty-print Ada.Containers.Ordered_Sets.Cursor values."""

    name = "Ordered_Set_Cursor"

    type_pattern = Match.TypeName(
        suffix=".cursor",
        pattern=Match.Struct(
            Match.Field("container",
                        Match.Pointer(OrderedSetPrinter.type_pattern)),
            Match.Field("node", Match.Pointer()),
        ),
    )

    def to_string(self):
        if self.value["container"]:
            assoc = self.value["node"]["element"]
        else:
            assoc = "No_Element"
        return "Cursor ({})".format(assoc)
Example #13
0
class OrderedMapCursorPrinter(PrettyPrinter):
    """Pretty-print Ada.Containers.Ordered_Maps.Cursor values."""

    name = 'Ordered_Map_Cursor'

    type_pattern = Match.TypeName(
        suffix='.cursor',
        pattern=Match.Struct(
            Match.Field('container',
                        Match.Pointer(OrderedMapPrinter.type_pattern)),
            Match.Field('node', Match.Pointer()),
        ))

    def to_string(self):
        if self.value['container']:
            assoc = '{} => {}'.format(
                self.value['node']['key'],
                self.value['node']['element'],
            )
        else:
            assoc = 'No_Element'
        return 'Cursor ({})'.format(assoc)
Example #14
0
import re

from gnatdbg.generics import Match

nr = gdb.parse_and_eval('nr')
r = gdb.parse_and_eval('r')
i = gdb.parse_and_eval('i')

# Only structs can match
assert not Match.Struct().match(i.type)
assert Match.Struct().match(nr.type)

# The number of fields must match
assert not Match.Struct(Match.Field('i')).match(nr.type)
assert Match.Struct(Match.Field('i')).match(r.type)

# The field names must match
assert not Match.Struct(Match.Field('o')).match(r.type)
assert Match.Struct(Match.Field('i')).match(r.type)

# The field types must match
assert not Match.Struct(Match.Field('i', Match.Char())).match(r.type)
assert Match.Struct(Match.Field('i', Match.Integer())).match(r.type)
Example #15
0
class OrderedMapPrinter(BaseMapPrinter):
    """Pretty-print Ada.Containers.Ordered_Maps.Map values."""

    name = "Ordered_Map"

    type_pattern = Match.TypeName(
        suffix=".map",
        pattern=Match.Struct(
            Match.Field("_parent"),
            Match.Field(
                "tree",
                get_rbtree_pattern(
                    Match.Struct(
                        Match.Field("parent", Match.Pointer()),
                        Match.Field("left", Match.Pointer()),
                        Match.Field("right", Match.Pointer()),
                        Match.Field("color", Match.Enum()),
                        Match.Field("key"),
                        Match.Field("element"),
                    )),
            ),
        ),
    )

    @property
    def length(self):
        return self.value["tree"]["length"]

    def get_node_iterator(self):
        return dfs(self.value["tree"])
Example #16
0
import re

from gnatdbg.generics import Match


s = gdb.parse_and_eval('s')
char_type = s.type.target()

# Only arrays can match
assert not Match.Array().match(s.type.target())
assert Match.Array().match(s.type)

# The element type must match
assert not Match.Array(element=Match.Array()).match(s.type)
assert Match.Array(element=Match.Char()).match(s.type)

# The first bound must match
assert not Match.Array(first=2).match(s.type)
assert Match.Array(first=1).match(s.type)

# The last bound must match
assert not Match.Array(last=1).match(s.type)
assert Match.Array(last=2).match(s.type)
Example #17
0
class MyIntPrinter(PrettyPrinter):
    name = 'My Int'
    type_pattern = Match.TypeName(name=re.compile(r'foo\.my_int_\d+'))

    def to_string(self):
        return 'My_Int ({})'.format(int(self.value))
Example #18
0
class MyNatPrinter(PrettyPrinter):
    name = 'My Nat'
    type_pattern = Match.TypeName(name='foo.my_nat')

    def to_string(self):
        return 'My_Nat ({})'.format(int(self.value))
Example #19
0
class VectorPrinter(PrettyPrinter):
    """Pretty-print Ada.Containers.Vectors.Vector values."""

    name = "Vector"

    type_pattern = Match.TypeName(
        suffix=".vector",
        pattern=Match.Struct(
            Match.Field("_parent"),
            Match.Field(
                "elements",
                Match.Pointer(
                    Match.Struct(
                        Match.Field("last", Match.Integer()),
                        Match.Field("ea", Match.Array()),
                    )),
            ),
            Match.Field("last", Match.Integer()),
            Match.Field("tc"),
        ),
    )

    def display_hint(self):
        return "array"

    @property
    def array_bounds(self):
        elements = self.value["elements"]
        if not elements:
            return (1, 0)
        array_type = elements["ea"].type
        first_index, _ = array_type.range()
        last_index = int(self.value["last"])
        return (first_index, last_index)

    @property
    def length(self):
        first, last = self.array_bounds
        if first <= last:
            return last - first + 1
        else:
            return 0

    @property
    def array_elements(self):
        first, last = self.array_bounds
        if first <= last:
            base_value = self.value["elements"]["ea"]
            return base_value.cast(base_value.type.target().array(first, last))
        else:
            return None

    def element(self, index):
        first, last = self.array_bounds
        if first <= index and index <= last:
            return self.array_elements[index]
        else:
            raise gdb.MemoryError(
                "Out of bound vector access ({} not in {} ..  {})".format(
                    index, first, last))

    def children(self):
        elements = self.array_elements
        if elements:
            first_index, last_index = elements.type.range()
            for i in range(first_index, last_index + 1):
                elt = elements[i]
                elt.fetch_lazy()
                yield ("[{}]".format(i), elt)

    def to_string(self):
        return "{} of length {}".format(pretty_typename(self.value.type),
                                        self.length)
Example #20
0
class VectorPrinter(PrettyPrinter):
    """Pretty-print Ada.Containers.Vectors.Vector values."""

    name = 'Vector'

    type_pattern = Match.TypeName(
        suffix='.vector',
        pattern=Match.Struct(
            Match.Field('_parent'),
            Match.Field(
                'elements',
                Match.Pointer(
                    Match.Struct(
                        Match.Field('last', Match.Integer()),
                        Match.Field('ea', Match.Array()),
                    ))),
            Match.Field('last', Match.Integer()),
            Match.Field('tc'),
        ))

    def display_hint(self):
        return 'array'

    @property
    def array_bounds(self):
        elements = self.value['elements']
        if not elements:
            return (1, 0)
        array_type = elements['ea'].type
        first_index, _ = array_type.range()
        last_index = int(self.value['last'])
        return (first_index, last_index)

    @property
    def length(self):
        first, last = self.array_bounds
        if first <= last:
            return last - first + 1
        else:
            return 0

    @property
    def array_elements(self):
        first, last = self.array_bounds
        if first <= last:
            base_value = self.value['elements']['ea']
            return base_value.cast(base_value.type.target().array(first, last))
        else:
            return None

    def element(self, index):
        first, last = self.array_bounds
        if first <= index and index <= last:
            return self.array_elements[index]
        else:
            raise gdb.MemoryError(
                'Out of bound vector access ({} not in {} ..  {})'.format(
                    index, first, last))

    def children(self):
        elements = self.array_elements
        if elements:
            first_index, last_index = elements.type.range()
            for i in range(first_index, last_index + 1):
                elt = elements[i]
                elt.fetch_lazy()
                yield ('[{}]'.format(i), elt)

    def to_string(self):
        return '{} of length {}'.format(pretty_typename(self.value.type),
                                        self.length)
Example #21
0
class StringAccess(object):
    """
    Helper class to inspect String accesses.
    """

    type_pattern = Match.Typedef(
        Match.Struct(
            Match.Field(
                "P_ARRAY",
                Match.Pointer(
                    Match.Array(
                        element=Match.Char(),
                    )
                ),
            ),
            Match.Field("P_BOUNDS"),
        )
    )

    def __init__(self, value):
        if not self.matches(value):
            raise TypeError("Input is not an access to string")
        self.value = value

    @classmethod
    def matches(cls, value):
        """
        Return whether `value` is a string access.

        :param gdb.Value value: Value to test.
        :rtype: bool
        """
        return cls.type_pattern.match(value.type)

    @property
    def bounds(self):
        """
        Return the bounds of the accessed string.

        :rtype: (int, int)
        """
        struct = self.value["P_BOUNDS"]
        return (int(struct["LB0"]), int(struct["UB0"]))

    @property
    def length(self):
        lb, ub = self.bounds
        return 0 if lb > ub else (ub - lb + 1)

    def _ptr(self):
        """Return the string pointer for this value."""
        access = self.value["P_ARRAY"]
        ptr_to_elt_type = access.type.target().target().pointer()
        return access.cast(ptr_to_elt_type)

    @property
    def is_valid(self):
        """Return True if the string is valid (has non-zero address)."""
        return self._ptr() != 0

    def get_string(self):
        """
        Return the accessed string.

        :rtype: str
        """
        return self._ptr().lazy_string(length=self.length)
Example #22
0
class DoublyLinkedListPrinter(PrettyPrinter):
    """Pretty-print Ada.Containers.Doubly_Linked_Lists values."""

    name = 'Doubly_Linked_List'

    node_pattern = Match.TypeName(suffix='.node_type',
                                  pattern=Match.Struct(
                                      Match.Field('element'),
                                      Match.Field('next', Match.Pointer()),
                                      Match.Field('prev', Match.Pointer()),
                                  ))

    type_pattern = Match.TypeName(suffix='.list',
                                  pattern=Match.Struct(
                                      Match.Field('_parent'),
                                      Match.Field('first',
                                                  Match.Pointer(node_pattern)),
                                      Match.Field('last',
                                                  Match.Pointer(node_pattern)),
                                      Match.Field('length', Match.Integer()),
                                      Match.Field('tc'),
                                  ))

    def display_hint(self):
        return 'array'

    @property
    def length(self):
        return self.value['length']

    def children(self):
        if self.value['first']:
            node = self.value['first']
            for i in range(self.length):
                yield ('[{}]'.format(i), node['element'])
                node = node['next']
            if node:
                raise gdb.MemoryError('The linked list seems invalid')

    def to_string(self):
        return '{} of length {}'.format(
            pretty_typename(self.value.type),
            self.length,
        )
Example #23
0
class OrderedMapPrinter(BaseMapPrinter):
    """Pretty-print Ada.Containers.Ordered_Maps.Map values."""

    name = 'Ordered_Map'

    type_pattern = Match.TypeName(
        suffix='.map',
        pattern=Match.Struct(
            Match.Field('_parent'),
            Match.Field(
                'tree',
                get_rbtree_pattern(
                    Match.Struct(
                        Match.Field('parent', Match.Pointer()),
                        Match.Field('left', Match.Pointer()),
                        Match.Field('right', Match.Pointer()),
                        Match.Field('color', Match.Enum()),
                        Match.Field('key'),
                        Match.Field('element'),
                    ))),
        ))

    @property
    def length(self):
        return self.value['tree']['length']

    def get_node_iterator(self):
        return dfs(self.value['tree'])
Example #24
0
class DoublyLinkedListPrinter(PrettyPrinter):
    """Pretty-print Ada.Containers.Doubly_Linked_Lists values."""

    name = "Doubly_Linked_List"

    node_pattern = Match.TypeName(
        suffix=".node_type",
        pattern=Match.Struct(
            Match.Field("element"),
            Match.Field("next", Match.Pointer()),
            Match.Field("prev", Match.Pointer()),
        ),
    )

    type_pattern = Match.TypeName(
        suffix=".list",
        pattern=Match.Struct(
            Match.Field("_parent"),
            Match.Field("first", Match.Pointer(node_pattern)),
            Match.Field("last", Match.Pointer(node_pattern)),
            Match.Field("length", Match.Integer()),
            Match.Field("tc"),
        ),
    )

    def display_hint(self):
        return "array"

    @property
    def length(self):
        return self.value["length"]

    def children(self):
        if self.value["first"]:
            node = self.value["first"]
            for i in range(self.length):
                yield ("[{}]".format(i), node["element"])
                node = node["next"]
            if node:
                raise gdb.MemoryError("The linked list seems invalid")

    def to_string(self):
        return "{} of length {}".format(
            pretty_typename(self.value.type),
            self.length,
        )
Example #25
0
import re

from gnatdbg.generics import Match

value = gdb.parse_and_eval('r')
type_matcher = Match.Struct(
    Match.Field('i'),
    Match.Field('n', Match.TypeName(name='natural')),
)
assert not type_matcher.match(value.type, debug=True)
Example #26
0
def get_htable_pattern(node_pattern):
    """
    Return the type pattern for hash tables used in GNAT's implementation of
    standard containers for nodes that match the given `node_pattern`.
    """
    # TODO: unfortunately, due to the current state of DWARF/GDB, it is not
    # possible to reach `node_pattern` through hash table's value type.
    return Match.Struct(
        Match.Field('_tag'),
        # See below for the type of `buckets`.
        Match.Field(
            'buckets',
            Match.Typedef(
                Match.Struct(
                    Match.Field('P_ARRAY', Match.Pointer()),
                    Match.Field('P_BOUNDS', Match.Pointer()),
                ))),
        Match.Field('length', Match.Integer()),
        Match.Field('tc'),
    )