This is the mail archive of the gdb@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Python pretty printer/API questions


I'd like to write a pretty printer for a custom type. The type already
has a C++-side pretty printer that would be way too much work to
duplicate in Python, so I figured I could just hijack that and have
the Python printer just call back into the inferior. (Essentially,
make it so that the pretty printer does a 'print myobj.to_string()'
and returns the result.) Obviously this has some drawbacks like you
need to be debugging an inferior with a reasonably sane state, but
implementing a "proper" Python pretty printer isn't gonna happen and
this seems like it is still rather better than sticking with the
default.

However, I'm having trouble getting it to work. I've come up with with
the following small example that crashes in what I hope is the same
manner as my full program. Unfortunately I'm only on GDB 7.7 and I
don't have a reasonable way of trying a more recent version, but if
there's some bug that has been fixed and what I'm doing *should* work,
feel free to yell at me to upgrade. :-)

I have this test program:

    #include <string>
    #include <sstream>

    class TestClass
    {
        int m_x;
    public:
        TestClass(int x) : m_x(x) {}

        std::string to_string() const {
            std::stringstream ss;
            ss << "x: " << m_x;
            return ss.str();
        }
    };

    int main()
    {
        TestClass c(5);
        c.to_string(); // so to_string isn't omitted from the exe
        return 0;
    }

which I compile (GCC 4.9) with 'gcc -g gdb_test.cpp -o gdb_test' and
then run under GDB and break it in main. I load my pretty printers
with `source /path/to/testclass.py', which contains:

    import gdb
    import gdb.printing

    to_string = gdb.parse_and_eval("TestClass::to_string")

    class TestPrinter:
        def __init__(self, val):
            self.val = val

        def to_string(self):
            return to_string(self.val)

    def build_pretty_printer():
        pp = gdb.printing.RegexpCollectionPrettyPrinter("Test")
        pp.add_printer('TestClass', '^TestClass$', TestPrinter)
        return pp

    gdb.printing.register_pretty_printer(
        gdb.current_objfile(),
        build_pretty_printer())

If I let it construct 'c' (by issuing 'next') and then 'print c', I get this:

    (gdb) print c
    $2 =
    Program received signal SIGSEGV, Segmentation fault.
    0x0000000000400a66 in TestClass::to_string (this=0x5) at gdb_test.cpp:17
    12                      ss << "x: " << m_x;
    Python Exception <class 'gdb.error'> The program being debugged
was signaled while in a function called from GDB.
    GDB remains in the frame where the signal was received
    ...

So somehow it's (I'm :-)) borking up the value being printed.

Is there some way to get this to work?


As a related question, in our program we really use *pointers* to the
relevant class everywhere (so an analogue to 'TestClass*'). Can I
somehow register a pretty printer for a pointer type so if I have
'TestClass * p' and say 'print p' I can have it print some info that
you'd normally only see with 'print *p'?

Thanks,
Evan


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]