From c63f340d90800895f007de64b7d2d14624263331 Mon Sep 17 00:00:00 2001 From: nthnluu Date: Sun, 28 Jan 2024 21:20:27 -0500 Subject: Created student weenix repository --- python/weenix/list.py | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 python/weenix/list.py (limited to 'python/weenix/list.py') diff --git a/python/weenix/list.py b/python/weenix/list.py new file mode 100644 index 0000000..6f951ae --- /dev/null +++ b/python/weenix/list.py @@ -0,0 +1,100 @@ +import gdb +import weenix + +_char_type = gdb.lookup_type("char") +_list_type = gdb.lookup_type("list_t") +_list_link_type = gdb.lookup_type("list_link_t") + +class Link: + + def __init__(self, value, dtype=None, dmemb=None): + self._value = value + self._dtype = dtype + self._dmemb = dmemb + + def value(self): + return self._value + + def item(self, typ=None, memb=None): + if (typ == None): + typ = self._dtype + if (memb == None): + memb = self._dmemb + if (typ == None or memb == None): + raise RuntimeError("list reference requires " + "both type and member name") + + for field in gdb.lookup_type(typ).fields(): + if (field.name == memb): + link = self._value.address.cast(_char_type.pointer()) + link -= (field.bitpos // 8) + link = link.cast(gdb.lookup_type(typ).pointer()) + return link.dereference() + raise weenix.WeenixError("no member {0} of {1}" + .format(memb, typ)) + + def link_addr(self): + return self._value.address + +class List: + + def __init__(self, value, dtype=None, dmemb=None): + self._value = value + self._dtype = dtype + self._dmemb = dmemb + + def __iter__(self): + curr = self._value["l_next"].dereference() + while (curr.address != self._value.address): + yield Link(curr, self._dtype, self._dmemb) + curr = curr["l_next"].dereference() + raise StopIteration + + def __len__(self): + try: + return self.__count + except AttributeError: + self.__count = 0 + curr = self._value["l_next"].dereference() + while (curr.address != self._value.address): + curr = curr["l_next"].dereference() + self.__count += 1 + return self.__count + + def __getitem__(self, key): + if (type(key) != int): + raise TypeError(key) + + for i, item in enumerate(self): + if (i == key): + return item + raise IndexError(key) + +def load(name, dtype=None, dmemb=None): + weenix.assert_type(name, _list_type) + + if (dtype != None): + try: + if (not isinstance(dtype, gdb.Type)): + typ = gdb.lookup_type(dtype) + else: + typ = dtype + except RuntimeError: + raise gdb.GdbError("no such type: {0}".format(dtype)) + + found = False + for field in typ.strip_typedefs().fields(): + if (field.name == dmemb): + try: + weenix.assert_type(field.type, _list_link_type) + except gdb.GdbError as err: + raise gdb.GdbError( + "field '{0}' of type '{1}' has wrong type: {2}" + .format(dmemb, dtype, str(err))) + found = True + if (not found): + raise gdb.GdbError("'{0}' type does not contain field '{1}'" + .format(dtype, dmemb)) + + value = name if isinstance(name, gdb.Value) else gdb.parse_and_eval(name) + return List(value, dtype, dmemb) -- cgit v1.2.3-70-g09d2