Search code examples
c++boostgdbmetaprogrammingboost-mpl

pretty printing boost::mpl::string<...> types in gdb


I use boost::mpl::string<...> types extensively... enough that it would really help with debugging to have the types pretty-printed in gdb.

So... instead of gdb showing the individual (multicharacter literal) components like it currently does ...

boost::mpl::string<1668248165, 778856802, 778858343, ..., ..., 0, 0, 0, 0, 0, 0>

It would display the equivalent string value instead ...

boost::mpl::string<"The way out is through">

I've seen gdb macros and python scripts for pretty-printing STL containers in gdb, but I couldn't find one for pretty-printing boost::mpl strings. Can anyone help with this?


UPDATE: I've added a +100 bounty... I'm looking for a solution that utilizes the latest GDB support for pretty-printing via python (as described here for STL containers).


Solution

  • Here is my solution utilizing Boost-Pretty-Printer (https://github.com/ruediger/Boost-Pretty-Printer/wiki):

    File mpl_printers.py:

    import printers
    import re
    import string
    import struct
    
    @printers.register_pretty_printer
    class BoostMplString:
        "Pretty Printer for boost::mpl::string"
        regex = re.compile('^boost::mpl::string<(.*)>$')
    
        @printers.static
        def supports(typename):
            return BoostMplString.regex.search(typename)
    
        def __init__(self, typename, value):
            self.typename = typename
            self.value = value
    
        def to_string(self):
                s = ''
                try:
                    m = BoostMplString.regex.match(self.typename)
                    args = string.split(m.group(1), ', ')
                    for packed in args: 
                        i = int(packed)
                        if i == 0: 
                            break
                        r = ''
                        while i != 0:
                            i, c = divmod(i, 0x100)
                            r += chr(c)
                        s += r[::-1]
                except RuntimeError:
                    s = '[Exception]'
                return '(boost::mpl::string) %s' % (s)
    
    def register_boost_mpl_printers(obj):
        "Register Boost Pretty Printers."
        pass
    

    File register_printers.gdb:

    python
    
    # Add the following line in your .gdbinit:
    # source /usr/local/share/gdb/register_printers.gdb
    
    import sys
    sys.path.insert(0, '/usr/local/share/gdb/python')
    # You might have these, too
    # from libstdcxx.v6.printers import register_libstdcxx_printers
    from boost.printers import register_boost_printers
    from boost.mpl_printers import register_boost_mpl_printers
    
    # register_libstdcxx_printers(None)
    register_boost_printers(None)
    register_boost_mpl_printers(None)
    
    end
    
    • Install printers.py and the above mpl_printers.py in the directory /usr/local/share/gdb/python/boost.
    • Ensure you have an __init__.py in /usr/local/share/gdb/python/boost (An empty file will do it)
    • Install the above 'register_printers.gdb' in /usr/local/share/gdb.
    • Add 'source /usr/local/share/gdb/register_printers.gdb' in your .gdbinit

    (You might choose different directories)

    Test:

    #include <boost/mpl/string.hpp>
    int main() {
        boost::mpl::string<'hell','o wo','rld'> s;
        return 0;
    }
    

    gdb Test -ex 'b main' -ex 'r' -ex 'p s' -ex 'c' -ex 'q'

    $1 = (boost::mpl::string) hello world