How to Enable Gdb Pretty Printing For C++ Stl Objects in Eclipse Cdt

How to enable gdb pretty printing for C++ STL objects in Eclipse CDT?

This is the solution that works for me.

Download ( http://www.gnu.org/software/gdb/download/) and install latest gdb (i.e. with --prefix $HOME). It supports python scripting.

Get python pretty printers by executing

svn co svn://gcc.gnu.org/svn/gcc/trunk/libstdc++-v3/python

in a directory of your choice (i.e. $(HOME)/distribs/gdb_printers). You will get 'python' subdirectory in the checkout directory.

Put this in your $(HOME)/.gdbinit file with proper path to pretty printers:

python
import sys
sys.path.insert(0, '/home/YOUR_NAME_HERE/distribs/gdb_printers/python')
from libstdcxx.v6.printers import register_libstdcxx_printers
register_libstdcxx_printers (None)
end

This makes pretty printing usable via command-line interface of gdb ( >(gdb) p my_std_string).

Next explains usage while debugging in Eclipse.

Download ( http://download.eclipse.org/eclipse/downloads/) latest Stream Stable Build or Release of Eclipse (>=3.7 version).

Download ( http://download.eclipse.org/tools/cdt/builds/8.0.0/index.html for Eclipse Indigo or http://www.eclipse.org/cdt/downloads.php for Eclipse Juno) latest Eclipse C/C++ Development Tooling (Eclipse CDT).

Run Eclipse and chose workspace directory where your options will be stored (i.e. $HOME/projects). Click Help->Install New Software... Click Add...->Archive... and choose the CDT build that you've just downloaded. Then you must choose components to install: click CDT Main Features -> C/C++ Development Tools (and possibly other components of your choice). Then proceed with installation and restart Eclipse.

Specify proper location of gdb and .gdbinit in Eclipse and make sure the Pretty Printing option is enabled:

Window -> preferences -> C/C++ -> Debug -> GDB

Now you can see STL containers pretty-printed in Variables view while debugging in Eclipse.

Other commands can be used to make gdb output more decent:

set print pretty on
set print object on
set print static-members on
set print vtbl on
set print demangle on
set demangle-style gnu-v3
set print sevenbit-strings off

UPDATE: Regarding getting it to work for old projects, see point 4) in rustyx answer below.

UPDATE2: ubuntu 12.04 has libstdc++6-4.6-dbg that installs /usr/share/gcc-4.6/python/libstdcxx/ python module for you

Eclipse/CDT Pretty Print Errors

I finally decided to revisit this issue and finally resolved it by following solutions similar to this one, and by additional editing of my custom printers.py. Hopefully this helps someone else who's hit this.

  1. Checkout pretty printers (svn co svn://gcc.gnu.org/svn/gcc/trunk/libstdc++-v3/python) to $HOME/gdb/gdb_printers/.

    • If you cannot checkout (if your organization blocks external svn like mine does), see if you can copy it from a system location (such as /usr/share/gdb/).
      You should have a directory structure like this when you're done:

gdb printer tree

This structure has to be EXACT or it won't use your printers.py down in /v6/.


  1. Edit printers.py, specifically StdStringPrinter::to_string as follows (adding try/except/else):

    def to_string(self):
    # Make sure &string works, too.
    type = self.val.type
    if type.code == gdb.TYPE_CODE_REF:
    type = type.target ()

    # Calculate the length of the string so that to_string returns
    # the string according to length, not according to first null
    # encountered.
    # I wrapped this section in a try/except/else block so that uninitialized
    # strings don't cause massive RuntimeError exception reporting during debugging
    # with or without pretty printers enabled. -jkw
    try:
    ptr = self.val ['_M_dataplus']['_M_p']
    realtype = type.unqualified ().strip_typedefs ()
    reptype = gdb.lookup_type (str (realtype) + '::_Rep').pointer ()
    header = ptr.cast(reptype) - 1
    len = header.dereference ()['_M_length']
    except RuntimeError:
    #print 'Caught exception'
    return ''
    else:
    return self.val['_M_dataplus']['_M_p'].lazy_string (length = len)
  2. Create/edit $HOME/gdb/.gdbinit file and put the following in it. Note the path must match the path to the 'python' directory in the above image/tree view.

     python
    import sys
    sys.path.insert(0, '/home/(user_id)/gdb/gdb_printers/python')
    from libstdcxx.v6.printers import register_libstdcxx_printers
    register_libstdcxx_printers (None)
    end
  3. In Eclipse, under Window -> preferences -> C/C++ -> Debug -> GDB, set the path to gdb and your .gdbinit file. You may also need to set this on any existing debug configurations that you want to use your printers.py.

    GDB debugger: /usr/bin/gdb
    GDB command file: /home/(user_id)/gdb/.gdbinit

From there, debugging functions just as you think it should.

Display smart pointers in eclipse cdt using gdb pretty printers

Following your link, I did exactly what Michael described, and it works fine. Probably, you did some mistake in applying the changes. The libstdcxx/v6/printers.py should now have in lines 103 - 174:

class SharedPointerPrinter:
"Print a shared_ptr or weak_ptr"

class _iterator:
def __init__(self, sharedPointer):
self.sharedPointer = sharedPointer
self.managedValue = sharedPointer.val['_M_ptr']
self.count = 0

def __iter__(self):
return self

def next(self):
if self.managedValue == 0:
raise StopIteration
self.count = self.count + 1
if (self.count == 1):
return ('Use count', self.sharedPointer.val['_M_refcount']['_M_pi']['_M_use_count'])
elif (self.count == 2):
return ('Weak count', self.sharedPointer.val['_M_refcount']['_M_pi']['_M_weak_count'] - 1)
elif (self.count == 3):
return ('Managed value', self.managedValue)
else:
raise StopIteration

def __init__ (self, typename, val):
self.typename = typename
self.val = val

def children (self):
return self._iterator(self)

def to_string (self):
state = 'empty'
refcounts = self.val['_M_refcount']['_M_pi']
if refcounts != 0:
usecount = refcounts['_M_use_count']
weakcount = refcounts['_M_weak_count']
if usecount == 0:
state = 'expired, weakcount %d' % weakcount
else:
state = 'usecount %d, weakcount %d' % (usecount, weakcount - 1)
return '%s (%s) to %s' % (self.typename, state, self.val['_M_ptr'])

class UniquePointerPrinter:
"Print a unique_ptr"

class _iterator:
def __init__(self, uniquePointer):
self.uniquePointer = uniquePointer
self.managedValue = uniquePointer.val['_M_t']['_M_head_impl']
self.count = 0

def __iter__(self):
return self

def next(self):
if self.managedValue == 0 or self.count == 1:
raise StopIteration
self.count = self.count + 1
return ('Managed value', self.managedValue)

def __init__ (self, typename, val):
self.val = val

def children (self):
return self._iterator(self)

def to_string (self):
v = self.val['_M_t']['_M_head_impl']
return ('std::unique_ptr<%s> containing %s' % (str(v.type.target()),
str(v)))

Kind regards



Related Topics



Leave a reply



Submit