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)
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)
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"), )
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, )
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, )
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'), )
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)
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)
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)