[SSSD] [PATCH] CONTRIB: Add a gdb pretty-printer for ldb and sysdb_attrs

Jakub Hrozek jhrozek at redhat.com
Fri Nov 13 16:21:37 UTC 2015


Hi,

I meant to send the pretty-printers for some time already..
-------------- next part --------------
>From 2927820959e1ffdb83c8f196a9195673bc927e44 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Fri, 13 Nov 2015 16:44:45 +0100
Subject: [PATCH] CONTRIB: Add a gdb pretty-printer for ldb and sysdb_attrs

Printing ldb structures and sysdb_attrs can be a pain. This patch adds a
gdb pretty-printer to help

SSSD and LDB debugging plugins

Activate them by putting:
  source /path/to/this/file.py
to your .gdbinit file

To bypass the pretty printer and print the raw values, use the "/r" option:
  print /r foobar
---
 contrib/gdb/sssd_gdb_plugin.py | 196 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 196 insertions(+)
 create mode 100644 contrib/gdb/sssd_gdb_plugin.py

diff --git a/contrib/gdb/sssd_gdb_plugin.py b/contrib/gdb/sssd_gdb_plugin.py
new file mode 100644
index 0000000000000000000000000000000000000000..730c7e894297012d897aafff97a3d8f8a3b7d042
--- /dev/null
+++ b/contrib/gdb/sssd_gdb_plugin.py
@@ -0,0 +1,196 @@
+# SSSD and LDB debugging plugins
+#
+# Activate them by putting:
+#   source /path/to/this/file.py
+# to your .gdbinit file
+#
+# To bypass the pretty printer and print the raw values, use the "/r" option:
+#   print /r foobar
+import gdb
+
+
+def gdb_printer_decorator(fn):
+    gdb.pretty_printers.append(fn)
+    return fn
+
+
+def indent_string(s, indent):
+    return '\n'.join(["%s%s" % ("\t" * indent, part) for part in s.split('\n')])
+
+
+class StringPrinter(object):
+    "Shared code between different string-printing classes"
+    def __init__(self, val):
+        self.val = val
+
+    def to_string(self):
+        return self.as_string()
+
+
+class LdbDnPrinter(StringPrinter):
+    " print an ldb dn "
+
+    def as_string(self, indent=0):
+        ret = "{ <%s>\tlinearized:%s }" % (self.val.type, self.val['linearized'])
+        return indent_string(ret, indent)
+
+
+class LdbValPrinter(StringPrinter):
+    " print a ldb value"
+
+    def as_string(self, indent=0):
+        ret = "data = %(data)s, length = %(length)s" % self.val
+        return indent_string("{ <%s>\t%s }" % (self.val.type, ret), indent)
+
+
+class LdbMessageElementPrinter(StringPrinter):
+    " print a ldb message element "
+
+    def as_string(self, indent=0):
+        ret = "flags = %(flags)s, name = %(name)s, num_values = %(num_values)s" % self.val
+        try:
+            nvals = int(self.val['num_values'])
+        except ValueError:
+            return "num_values is not numeric?"
+
+        for i in range(nvals):
+            ldbval = LdbValPrinter(self.val['values'][i])
+            ret += "\n%s" % (ldbval.as_string(indent+1))
+
+        return indent_string("{ <%s>\t%s }" % (self.val.type, ret), indent)
+
+
+class LdbMessagePrinter(StringPrinter):
+    " print a ldb message "
+
+    def as_string(self, indent=0):
+        try:
+            nels = int(self.val['num_elements'])
+        except ValueError:
+            return "num_elements is not numeric?"
+
+        dn = LdbDnPrinter(self.val['dn'])
+        ret = "num_elements:\t%s\ndn:\t%s\nelements:\t" % (nels, dn.as_string(indent))
+
+        for i in range(nels):
+            el = LdbMessageElementPrinter(self.val['elements'][i])
+            ret += "\n%s" % (el.as_string(indent+1))
+
+        return indent_string("{ <%s>\n%s }" % (self.val.type, ret), indent)
+
+
+class LdbResultPrinter(StringPrinter):
+    " print a ldb message element "
+
+    def as_string(self, indent=0):
+        ret = "count = %(count)s, extended = %(extended)s, controls = %(controls)s, refs = %(refs)s" % self.val
+        try:
+            count = int(self.val['count'])
+        except ValueError:
+            ret += 'Count is not numeric value?'
+            return ret
+
+        for i in range(count):
+            msg = LdbMessagePrinter(self.val['msgs'][i])
+            ret += "\n%s" % (msg.as_string(indent+1))
+
+        return indent_string("{ <%s>\t%s }" % (self.val.type, ret), indent)
+
+
+class SysdbAttrsPrinter(StringPrinter):
+    " print a struct sysdb attrs "
+
+    def as_string(self, indent=0):
+        ret = "num = %(num)s" % self.val
+
+        try:
+            num = int(self.val['num'])
+        except ValueError:
+            ret += 'num is not numeric value?'
+            return ret
+
+        for i in range(num):
+            el = LdbMessageElementPrinter(self.val['a'][i])
+            ret += "\n%s" % (el.as_string(indent+1))
+
+        return indent_string("{ <%s>\t%s }" % (self.val.type, ret), indent)
+
+
+# ---
+# --- register pretty printers ---
+# ---
+ at gdb_printer_decorator
+def ldb_val_element_printer(val):
+    if str(val.type) == 'struct ldb_dn':
+        return LdbDnPrinter(val)
+    return None
+
+
+ at gdb_printer_decorator
+def ldb_val_element_printer(val):
+    if str(val.type) == 'struct ldb_val':
+        return LdbValPrinter(val)
+    return None
+
+
+ at gdb_printer_decorator
+def ldb_message_element_printer(val):
+    if str(val.type) == 'struct ldb_message_element':
+        return LdbMessageElementPrinter(val)
+    return None
+
+
+ at gdb_printer_decorator
+def ldb_message_printer(val):
+    if str(val.type) == 'struct ldb_message':
+        return LdbMessagePrinter(val)
+    return None
+
+
+ at gdb_printer_decorator
+def ldb_result_printer(val):
+    if str(val.type) == 'struct ldb_result':
+        return LdbResultPrinter(val)
+    return None
+
+
+ at gdb_printer_decorator
+def sysdb_attrs_printer(val):
+    if str(val.type) == 'struct sysdb_attrs':
+        return SysdbAttrsPrinter(val)
+    return None
+
+
+# ---
+# --- set a breakpoint at the tevent_req finish fn ---
+# ---
+class TeventBreak(gdb.Command):
+    """Break at the tevent finish location """
+
+    def __init__(self):
+        super(TeventBreak, self).__init__("tbr", gdb.COMMAND_BREAKPOINTS)
+
+    def invoke(self, arg, from_tty):
+        req = gdb.parse_and_eval(arg)
+        if not hasattr(req, 'type'):
+            print('cannot determine the type of the variable')
+            return
+        if str(req.type) != 'struct tevent_req *':
+            print('wrong attribute - must be a tevent_req pointer')
+            return
+
+        try:
+            fn = req['async']['fn']
+        except KeyError:
+            print("No async function defined?")
+            return
+
+        try:
+            fnaddr = str(fn).split()[0].strip()
+        except IndexError:
+            print("Cannot get function address")
+            return
+
+        b = gdb.Breakpoint("*%s" % fnaddr)
+
+TeventBreak()
-- 
2.4.3



More information about the sssd-devel mailing list