class OrderedSetPrinter(BaseSetPrinter): """Pretty-print Ada.Containers.Ordered_Sets.Set values.""" name = 'Ordered_Set' type_pattern = Match.TypeName( suffix='.set', pattern=Match.Struct( Match.Field('_parent'), Match.Field( 'tree', get_rbtree_pattern( Match.Struct( Match.Field('parent', Match.Typedef(Match.Pointer())), Match.Field('left', Match.Typedef(Match.Pointer())), Match.Field('right', Match.Typedef(Match.Pointer())), Match.Field('color', Match.Enum()), Match.Field('element'), ))), )) @property def length(self): return self.value['tree']['length'] def get_node_iterator(self): return dfs(self.value['tree'])
class OrderedSetPrinter(BaseSetPrinter): """Pretty-print Ada.Containers.Ordered_Sets.Set values.""" name = "Ordered_Set" type_pattern = Match.TypeName( suffix=".set", pattern=Match.Struct( Match.Field("_parent"), Match.Field( "tree", get_rbtree_pattern( Match.Struct( Match.Field("parent", Match.Typedef(Match.Pointer())), Match.Field("left", Match.Typedef(Match.Pointer())), Match.Field("right", Match.Typedef(Match.Pointer())), Match.Field("color", Match.Enum()), Match.Field("element"), )), ), ), ) @property def length(self): return self.value["tree"]["length"] def get_node_iterator(self): return dfs(self.value["tree"])
class HashedSetPrinter(BaseSetPrinter): """Pretty-print Ada.Containers.Hashed_Sets.Set values.""" name = "Hashed_Set" type_pattern = Match.TypeName( suffix=".set", pattern=Match.Struct( Match.Field("_parent"), Match.Field( "ht", get_htable_pattern( Match.Struct( Match.Field("element"), Match.Field("next", Match.Typedef(Match.Pointer())), )), ), ), ) @property def length(self): return self.value["ht"]["length"] def get_node_iterator(self): return iterate(self.value["ht"])
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)
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 HashedSetPrinter(BaseSetPrinter): """Pretty-print Ada.Containers.Hashed_Sets.Set values.""" name = 'Hashed_Set' type_pattern = Match.TypeName( suffix='.set', pattern=Match.Struct( Match.Field('_parent'), Match.Field( 'ht', get_htable_pattern( Match.Struct( Match.Field('element'), Match.Field('next', Match.Typedef(Match.Pointer())), ))), )) @property def length(self): return self.value['ht']['length'] def get_node_iterator(self): return iterate(self.value['ht'])
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)