From dba842eea04236c9d769a9902a03579c1fda2c7e Mon Sep 17 00:00:00 2001 From: Stephan Hageboeck <stephan.hageboeck@cern.ch> Date: Thu, 25 Apr 2019 15:49:10 +0200 Subject: [PATCH] Add alpha version of gdb pretty printers. This adds gdb pretty printers for a few objects such as TString and TNamed, as well as a couple of RooFit objects. gdb can automatically load them if gdb's `add-auto-load-safe-path` is set to ROOT's lib directory. `print /r <obj>` allows to still print raw. --- build/CMakeLists.txt | 11 ++ build/gdbPrinters/libCore.so-gdb.py | 72 ++++++++++++ build/gdbPrinters/libRooFitCore.so-gdb.py | 136 ++++++++++++++++++++++ 3 files changed, 219 insertions(+) create mode 100644 build/gdbPrinters/libCore.so-gdb.py create mode 100644 build/gdbPrinters/libRooFitCore.so-gdb.py diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 2d5e3ef6c27..b84481041b3 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -18,3 +18,14 @@ ROOT_EXECUTABLE(rmkdepend rmkdepend/parse.c rmkdepend/pr.c ) + +IF(CMAKE_BUILD_TYPE MATCHES "Debug|RelWithDebInfo") + file(COPY "gdbPrinters/" + DESTINATION ${CMAKE_BINARY_DIR}/lib + FILES_MATCHING PATTERN "*-gdb.py") + + file(GLOB PRETTY_PRINTERS "gdbPrinters/*-gdb.py") + install(FILES ${PRETTY_PRINTERS} + DESTINATION lib + CONFIGURATIONS Debug RelWithDebInfo) +ENDIF() diff --git a/build/gdbPrinters/libCore.so-gdb.py b/build/gdbPrinters/libCore.so-gdb.py new file mode 100644 index 00000000000..c9613beb2e0 --- /dev/null +++ b/build/gdbPrinters/libCore.so-gdb.py @@ -0,0 +1,72 @@ +# Pretty printers for gdb +# \author: Stephan Hageboeck, CERN +# These pretty printers will make ROOT objects more readable when printed in gdb. +# If the pretty-printed output is not sufficient, one can always use "print /r <object>" +# for raw printing. +# +# When a debug build is used, they will be installed next to the ROOT libraries. +# gdb will load them automatically if the auto-load-safe-path is set to ROOT's library directory. +# For this, one has to add `add-auto-load-safe-path <ROOT lib dir>` to .gdbinit +# +# If loaded successfully, typing `info pretty-printer` at the gdb prompt should list the +# printers registered at the end of this file. + +import gdb + + +class TObjectPrinter(object): + "Print TObjects" + + def __init__(self, val): + self.val = val + + def children(self): + yield "fUniqueID", self.val['fUniqueID'] + yield "fBits", self.val['fBits'] + + def to_string(self): + return "(TObject)" + + + +class TNamedPrinter(object): + "Print TNamed" + + def __init__(self, val): + self.val = val + + def to_string(self): + return "(TNamed) " + str(self.val['fName']) + " " + str(self.val['fTitle']) + + + +class TStringPrinter(object): + "Print TStrings" + + def __init__(self, val): + self.val = val + typeAndAddr = "(*(TString*)"+str(val.address)+")" + query = typeAndAddr + ".fRep.fShort.fSize & TString::kShortMask" + self.isLong = bool(gdb.parse_and_eval(query)) + + def display_hint(self): + return 'string' + + def to_string(self): + theStr = self.val['fRep']['fLong']['fData'] if self.isLong else self.val['fRep']['fShort']['fData'] + return theStr.string() + + + + +def build_pretty_printer(): + pp = gdb.printing.RegexpCollectionPrettyPrinter("libCore") + pp.add_printer('TObject', '^TObject$', TObjectPrinter) + pp.add_printer('TNamed', '^TNamed$', TNamedPrinter) + pp.add_printer('TString', '^TString$', TStringPrinter) + + return pp + + +gdb.printing.register_pretty_printer(gdb.current_objfile(), + build_pretty_printer()) diff --git a/build/gdbPrinters/libRooFitCore.so-gdb.py b/build/gdbPrinters/libRooFitCore.so-gdb.py new file mode 100644 index 00000000000..28d1e268fb5 --- /dev/null +++ b/build/gdbPrinters/libRooFitCore.so-gdb.py @@ -0,0 +1,136 @@ +# Pretty printers for gdb +# \author: Stephan Hageboeck, CERN +# These pretty printers will make ROOT objects more readable when printed in gdb. +# If the pretty-printed output is not sufficient, one can always use "print /r <object>" +# for raw printing. +# +# When a debug build is used, they will be installed next to the ROOT libraries. +# gdb will load them automatically if the auto-load-safe-path is set to ROOT's library directory. +# For this, one has to add `add-auto-load-safe-path <ROOT lib dir>` to .gdbinit +# +# If loaded successfully, typing `info pretty-printer` at the gdb prompt should list the +# printers registered at the end of this file. + +import gdb + + +class RooCollectionPrinter(object): + "Print a RooAbsCollection" + + def __init__(self, val): + self.val = val + self.viz = gdb.default_visualizer(self.val['_list']) + + def to_string(self): + ret = "{" + str(self.val.dynamic_type) + " " + str(self.val['_name']) +": " + try: + for name,val in self.viz.children(): + itemName = val.referenced_value()['fName'] + ret += str(itemName) + "," + except: + ret += "<exception " + str(sys.exc_info()[0]) + ">," + + ret += "}" + return ret + + def children(self): + for name,val in self.viz.children(): + try: + itemName = val.referenced_value()['fName'] + key = name + " " + str(val.address) + " (" + str(val.dynamic_type) +") " + str(itemName) + yield key, val.referenced_value() + except: +# print("<exception " + str(sys.exc_info()[0]) + ">,") + raise + + def display_hint(self): + return 'RooAbsCollection printer' + + + +class RooSpanPrinter(object): + "Print a RooSpan" + + def __init__(self, val): + self.val = val + + def to_string(self): + return "span of length " + str(self.val['_span']['length_']) + + def children(self): + length = self.val['_span']['length_'] + values = "" + for i in range(0, min(length, 10)): + values += ' ' + str((self.val['_span']['data_']+i).dereference()) + yield 'Values', values + '...' + yield 'Aux storage', self.val['_auxStorage'] + + def display_hint(self): + return 'RooSpan printer' + + + +class RooAbsArgPrinter(object): + "Print a RooAbsArg" + + def __init__(self, val): + self.val = val + + def children(self): + for name,item in self.val.fields(): + yield name, item + + def to_string(self): + ret += str(self.val.address) + " " + str(self.val.dynamic_type) + itemName = self.val['fName'] + ret += " = { <fName> = {" + str(itemName) + "} }" + return ret + + def display_hint(self): + return 'RooAbsArg printer' + + + +class RooSTLRefCountListPrinter(object): + "Print ref count lists" + + def __init__(self, val): + self.val = val + + def to_string(self): + ret = "{" + viz = gdb.default_visualizer(self.val['_storage']) + vizRC = gdb.default_visualizer(self.val['_refCount']) + for (name,val), (name2,val2) in zip(viz.children(), vizRC.children()): + ret += str(val['fName']) + ": " + str(val2) + ", " + return ret + "}" + + + +class NonePrinter(object): + "Prevent printing an object" + + def __init__(self, val): + self.val = val + + def to_string(self): + return "" + + def display_hint(self): + return 'Disables printing' + + + + +def build_pretty_printer(): + pp = gdb.printing.RegexpCollectionPrettyPrinter("libRooFitCore") + pp.add_printer('RooSpan', '^RooSpan.*$', RooSpanPrinter) + pp.add_printer('Collections', '^Roo(AbsCollection|ArgList|ArgSet)$', RooCollectionPrinter) + pp.add_printer('RooSTLRefCountList', '^RooSTLRefCountList.*$', RooSTLRefCountListPrinter) + pp.add_printer('RooPrintable', '^RooPrintable$', NonePrinter) + + return pp + + +gdb.printing.register_pretty_printer(gdb.current_objfile(), + build_pretty_printer()) -- GitLab