glib (2.79.0)

(root)/
share/
glib-2.0/
gdb/
glib_gdb.py
       1  import gdb
       2  import sys
       3  
       4  if sys.version_info[0] >= 3:
       5      long = int
       6  
       7  
       8  # This is not quite right, as local vars may override symname
       9  def read_global_var(symname):
      10      return gdb.selected_frame().read_var(symname)
      11  
      12  
      13  def g_quark_to_string(quark):
      14      if quark is None:
      15          return None
      16      quark = long(quark)
      17      if quark == 0:
      18          return None
      19      max_q = None
      20      try:
      21          val = read_global_var("quarks")
      22          try:
      23              max_q = long(read_global_var("quark_seq_id"))
      24          # quark_seq_id gets optimized out in some builds so work around it
      25          except gdb.error:
      26              pass
      27      except Exception:
      28          try:
      29              val = read_global_var("g_quarks")
      30              try:
      31                  max_q = long(read_global_var("g_quark_seq_id"))
      32              except gdb.error:
      33                  pass
      34          except Exception:
      35              return None
      36      if max_q is None or quark < max_q:
      37          try:
      38              return val[quark].string()
      39          except gdb.MemoryError:
      40              print(f"Invalid quark {quark}")
      41      return None
      42  
      43  
      44  # We override the node printers too, so that node->next is not expanded
      45  class ESC[4;38;5;81mGListNodePrinter:
      46      "Prints a GList node"
      47  
      48      def __init__(self, val):
      49          self.val = val
      50  
      51      def to_string(self):
      52          return "{data=%s, next=0x%x, prev=0x%x}" % (
      53              str(self.val["data"]),
      54              long(self.val["next"]),
      55              long(self.val["prev"]),
      56          )
      57  
      58  
      59  class ESC[4;38;5;81mGSListNodePrinter:
      60      "Prints a GSList node"
      61  
      62      def __init__(self, val):
      63          self.val = val
      64  
      65      def to_string(self):
      66          return "{data=%s, next=0x%x}" % (str(self.val["data"]), long(self.val["next"]))
      67  
      68  
      69  class ESC[4;38;5;81mGListPrinter:
      70      "Prints a GList"
      71  
      72      class ESC[4;38;5;81m_iterator:
      73          def __init__(self, head, listtype):
      74              self.link = head
      75              self.listtype = listtype
      76              self.count = 0
      77  
      78          def __iter__(self):
      79              return self
      80  
      81          def next(self):
      82              if self.link == 0:
      83                  raise StopIteration
      84              data = self.link["data"]
      85              self.link = self.link["next"]
      86              count = self.count
      87              self.count = self.count + 1
      88              return ("[%d]" % count, data)
      89  
      90          __next__ = next
      91  
      92      def __init__(self, val, listtype):
      93          self.val = val
      94          self.listtype = listtype
      95  
      96      def children(self):
      97          return self._iterator(self.val, self.listtype)
      98  
      99      def to_string(self):
     100          return "0x%x" % (long(self.val))
     101  
     102      def display_hint(self):
     103          return "array"
     104  
     105  
     106  class ESC[4;38;5;81mGHashPrinter:
     107      "Prints a GHashTable"
     108  
     109      class ESC[4;38;5;81m_iterator:
     110          class ESC[4;38;5;81m_pointer_array:
     111              def __init__(self, ptr, big_items):
     112                  self._big_items = big_items
     113                  self._gpointer_type = gdb.lookup_type("gpointer")
     114                  item_type = (
     115                      self._gpointer_type if self._big_items else gdb.lookup_type("guint")
     116                  )
     117  
     118                  self._items = ptr.cast(item_type.pointer())
     119  
     120              def __getitem__(self, item):
     121                  item = self._items[item]
     122  
     123                  if not self._big_items:
     124                      item = item.cast(self._gpointer_type)
     125  
     126                  return item
     127  
     128          def __init__(self, ht, keys_are_strings):
     129              self.ht = ht
     130              if ht != 0:
     131                  self.keys = self._pointer_array(ht["keys"], ht["have_big_keys"])
     132                  self.values = self._pointer_array(ht["values"], ht["have_big_values"])
     133                  self.hashes = ht["hashes"]
     134                  self.size = ht["size"]
     135              self.pos = 0
     136              self.keys_are_strings = keys_are_strings
     137              self.value = None
     138  
     139          def __iter__(self):
     140              return self
     141  
     142          def next(self):
     143              if self.ht == 0:
     144                  raise StopIteration
     145              if self.value is not None:
     146                  v = self.value
     147                  self.value = None
     148                  return v
     149              while long(self.pos) < long(self.size):
     150                  if long(self.hashes[self.pos]) >= 2:
     151                      key = self.keys[self.pos]
     152                      val = self.values[self.pos]
     153  
     154                      if self.keys_are_strings:
     155                          key = key.cast(gdb.lookup_type("char").pointer())
     156  
     157                      # Queue value for next result
     158                      self.value = ("[%dv]" % (self.pos), val)
     159  
     160                      # Increment pos and return key
     161                      key = ("[%dk]" % (self.pos), key)
     162                      self.pos += 1
     163                      return key
     164  
     165                  self.pos += 1
     166              raise StopIteration
     167  
     168          __next__ = next
     169  
     170      def __init__(self, val):
     171          self.val = val
     172          self.keys_are_strings = False
     173          try:
     174              string_hash = read_global_var("g_str_hash")
     175          except Exception:
     176              string_hash = None
     177          if (
     178              self.val != 0
     179              and string_hash is not None
     180              and self.val["hash_func"] == string_hash
     181          ):
     182              self.keys_are_strings = True
     183  
     184      def children(self):
     185          return self._iterator(self.val, self.keys_are_strings)
     186  
     187      def to_string(self):
     188          return "0x%x" % (long(self.val))
     189  
     190      def display_hint(self):
     191          return "map"
     192  
     193  
     194  def pretty_printer_lookup(val):
     195      # None yet, want things like hash table and list
     196  
     197      type = val.type.unqualified()
     198  
     199      # If it points to a reference, get the reference.
     200      if type.code == gdb.TYPE_CODE_REF:
     201          type = type.target()
     202  
     203      if type.code == gdb.TYPE_CODE_PTR:
     204          type = type.target().unqualified()
     205          t = str(type)
     206          if t == "GList":
     207              return GListPrinter(val, "GList")
     208          if t == "GSList":
     209              return GListPrinter(val, "GSList")
     210          if t == "GHashTable":
     211              return GHashPrinter(val)
     212      else:
     213          t = str(type)
     214          if t == "GList":
     215              return GListNodePrinter(val)
     216          if t == "GSList *":
     217              return GListPrinter(val, "GSList")
     218      return None
     219  
     220  
     221  def register(obj):
     222      if obj is None:
     223          obj = gdb
     224  
     225      obj.pretty_printers.append(pretty_printer_lookup)
     226  
     227  
     228  class ESC[4;38;5;81mForeachCommand(ESC[4;38;5;149mgdbESC[4;38;5;149m.ESC[4;38;5;149mCommand):
     229      """Foreach on list"""
     230  
     231      def __init__(self):
     232          super(ForeachCommand, self).__init__(
     233              "gforeach", gdb.COMMAND_DATA, gdb.COMPLETE_SYMBOL
     234          )
     235  
     236      def valid_name(self, name):
     237          if not name[0].isalpha():
     238              return False
     239          return True
     240  
     241      def parse_args(self, arg):
     242          i = arg.find(" ")
     243          if i <= 0:
     244              raise Exception("No var specified")
     245          var = arg[:i]
     246          if not self.valid_name(var):
     247              raise Exception("Invalid variable name")
     248  
     249          while i < len(arg) and arg[i].isspace():
     250              i = i + 1
     251  
     252          if arg[i : i + 2] != "in":
     253              raise Exception("Invalid syntax, missing in")
     254  
     255          i = i + 2
     256  
     257          while i < len(arg) and arg[i].isspace():
     258              i = i + 1
     259  
     260          colon = arg.find(":", i)
     261          if colon == -1:
     262              raise Exception("Invalid syntax, missing colon")
     263  
     264          val = arg[i:colon]
     265  
     266          colon = colon + 1
     267          while colon < len(arg) and arg[colon].isspace():
     268              colon = colon + 1
     269  
     270          command = arg[colon:]
     271  
     272          return (var, val, command)
     273  
     274      def do_iter(self, arg, item, command):
     275          item = item.cast(gdb.lookup_type("void").pointer())
     276          item = long(item)
     277          to_eval = "set $%s = (void *)0x%x\n" % (arg, item)
     278          gdb.execute(to_eval)
     279          gdb.execute(command)
     280  
     281      def slist_iterator(self, arg, container, command):
     282          list_element = container.cast(gdb.lookup_type("GSList").pointer())
     283          while long(list_element) != 0:
     284              self.do_iter(arg, list_element["data"], command)
     285              list_element = list_element["next"]
     286  
     287      def list_iterator(self, arg, container, command):
     288          list_element = container.cast(gdb.lookup_type("GList").pointer())
     289          while long(list_element) != 0:
     290              self.do_iter(arg, list_element["data"], command)
     291              list_element = list_element["next"]
     292  
     293      def pick_iterator(self, container):
     294          t = container.type.unqualified()
     295          if t.code == gdb.TYPE_CODE_PTR:
     296              t = t.target().unqualified()
     297              t = str(t)
     298              if t == "GSList":
     299                  return self.slist_iterator
     300              if t == "GList":
     301                  return self.list_iterator
     302          raise Exception("Invalid container type %s" % (str(container.type)))
     303  
     304      def invoke(self, arg, from_tty):
     305          (var, container, command) = self.parse_args(arg)
     306          container = gdb.parse_and_eval(container)
     307          func = self.pick_iterator(container)
     308          func(var, container, command)
     309  
     310  
     311  ForeachCommand()