When I define a Python pretty printer, I see it only works for a normal variable, but not class member variable. Here is a simple test case, it contains 3 files: main.cpp, reco.h and reco.cpp. main.cpp -------------------------------------- #include "reco.h" class CTest { public: CTest(float input) :r(input), v(18), f(65.7) { } reco r; int v; float f; }; double DummyFunctionForwxreco(void *dummy) { reco* p = (reco*)dummy; return p->getWeight(); } int main() { reco sss(5.0); CTest ccc(7.8); return 0; } -------------------------------------- reco.h -------------------------------------- #ifndef RECO_H #define RECO_H class reco { public: reco(float input); ~reco(void); virtual float getWeight(); private: float weight; }; #endif -------------------------------------- reco.cpp -------------------------------------- #include "reco.h" reco::reco(float input) { weight = input; } reco::~reco(void) { } float reco::getWeight() { return weight; } -------------------------------------- To build the main.exe, you have to type the following command, not the "-g0" option means you don't have debug information in the reco.o. -------------------------------------- gcc -c -g0 reco.cpp gcc -c -g main.cpp g++ -o main.exe main.o reco.o -------------------------------------- The python pretty printer test.py -------------------------------------- import gdb import sys class recoPrinter: def __init__(self, val): self.val = val def to_string(self): return gdb.parse_and_eval('DummyFunctionForwxreco((void*)%s)' % self.val.address ) # call the dummy function here! def CustomPrettyPrinters(val): if str(val.type) == 'reco': return recoPrinter(val) return None gdb.pretty_printers.append(CustomPrettyPrinters) -------------------------------------- Here is the debug session: you set the breakpoint by this command "b main.cpp:27", and run the exe file by command "r", when it hit the breakpoint, you can try to print some variables. -------------------------------------- # gdb main.exe GNU gdb (GDB) 11.2 Copyright (C) 2022 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-w64-mingw32". Type "show configuration" for configuration details. For bug reporting instructions, please see: <https://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from main.exe... (gdb) b main.cpp:27 Breakpoint 1 at 0x1400015a3: file main.cpp, line 27. (gdb) r Starting program: E:\code\gdb-incomplete-type\main.exe Breakpoint 1, main () at main.cpp:27 27 return 0; (gdb) p sss $1 = <incomplete type> (gdb) p ccc $2 = {r = <incomplete type>, v = 18, f = 65.6999969} (gdb) source test.py (gdb) p sss $3 = 5 (gdb) p ccc $4 = {r = <incomplete type>, v = 18, f = 65.6999969} (gdb) -------------------------------------- You see, the "p sss" works OK after "source test.py", but the "p ccc" is still not good. I think the pretty printer is simple, because I don't even use pretty printer for std library.
ssbssa wrote a patch to fix this issue: Here is the patch: ================ diff --git a/gdb/valprint.c b/gdb/valprint.c index 6b1531ef442..f540c681403 100644 --- a/gdb/valprint.c +++ b/gdb/valprint.c @@ -1028,16 +1028,6 @@ common_val_print (struct value *value, struct ui_file *stream, int recurse, QUIT; - /* Ensure that the type is complete and not just a stub. If the type is - only a stub and we can't find and substitute its complete type, then - print appropriate string and return. */ - - if (real_type->is_stub ()) - { - fprintf_styled (stream, metadata_style.style (), _("<incomplete type>")); - return; - } - if (!valprint_check_validity (stream, real_type, 0, value)) return; @@ -1048,6 +1038,16 @@ common_val_print (struct value *value, struct ui_file *stream, int recurse, return; } + /* Ensure that the type is complete and not just a stub. If the type is + only a stub and we can't find and substitute its complete type, then + print appropriate string and return. */ + + if (real_type->is_stub ()) + { + fprintf_styled (stream, metadata_style.style (), _("<incomplete type>")); + return; + } + /* Handle summary mode. If the value is a scalar, print it; otherwise, print an ellipsis. */ if (options->summary && !val_print_scalar_type_p (type)) ======================================= For more details, you can see the discussion here: Re: [solved] Creating a gdb Pretty-Printer for wxIPV4address — https://forums.wxwidgets.org/viewtopic.php?p=211799#p211799
The master branch has been updated by Hannes Domani <ssbssa@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=7543c960b00ddea23f6105eff4358ec214a7f93c commit 7543c960b00ddea23f6105eff4358ec214a7f93c Author: Hannes Domani <ssbssa@yahoo.de> Date: Fri Dec 8 18:19:42 2023 +0100 Use pretty printers for struct member stubs PR29079 shows that pretty printers can be used for an incomplete type (stub), but only when printing it directly, not if it's part of another struct: ``` (gdb) p s $1 = {pp m_i = 5} (gdb) p s2 $2 = {m_s = <incomplete type>, m_l = 20} ``` The reason is simply that in common_val_print the check for stubs is before any pretty printer is tried. It works if the pretty printer is tried before the stub check: ``` (gdb) p s $1 = {pp m_i = 5} (gdb) p s2 $2 = {m_s = {pp m_i = 10}, m_l = 20} ``` Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29079 Approved-By: Tom Tromey <tom@tromey.com>
Fixed.
It is really nice to see the patch is in gdb git now! I see GDB 14.1 was just released recently, so will wait for the next release 15.1. Thanks.