How to print <incomplete type> variable in gdb

Disclaimer: I'm a Python developer with only some minimum knowledge of C++ and how Linux OS functions, so what I describe below is just my solution to a problem I personally experienced.

If you trying to work with types coming from 3rd party libraries, make sure those libraries aren't missing debug info.

Example

(gdb) info share Qt
From                To                  Syms Read   Shared Object Library
0x00007ffff5336080  0x00007ffff56ba585  Yes (*)     /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
0x00007ffff4ad3510  0x00007ffff4ef0cbe  Yes (*)     /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5
0x00007ffff47829c0  0x00007ffff47e1ba1  Yes (*)     /usr/lib/x86_64-linux-gnu/libQt5DBus.so.5
0x00007ffff40bb5e0  0x00007ffff439dd92  Yes (*)     /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
0x00007ffff2e581e0  0x00007ffff2e78e4f  Yes (*)     /usr/lib/x86_64-linux-gnu/libQt5Xml.so.5
0x00007ffff28c8a00  0x00007ffff29d9999  Yes (*)     /usr/lib/x86_64-linux-gnu/libQt5Network.so.5
0x00007ffff2251750  0x00007ffff2252a46  Yes (*)     /usr/lib/x86_64-linux-gnu/libQt5X11Extras.so.5
0x00007ffff1cc9f80  0x00007ffff1cfc861  Yes (*)     /usr/lib/x86_64-linux-gnu/libQt5PrintSupport.so.5
0x00007fffee269c10  0x00007fffee297b57  Yes (*)     /usr/lib/x86_64-linux-gnu/libQt5Svg.so.5
0x00007fffed987560  0x00007fffed98b6a8  Yes (*)     /usr/lib/x86_64-linux-gnu/libQt5TextToSpeech.so.5
0x00007fffe980e130  0x00007fffe9900c0c  Yes (*)     /usr/lib/x86_64-linux-gnu/libQt5XcbQpa.so.5
0x00007fffe69ef650  0x00007fffe69ffe0d  Yes (*)     /usr/lib/x86_64-linux-gnu/libQt5QuickControls2.so.5
0x00007fffe5c0f890  0x00007fffe5eae1c1  Yes (*)     /usr/lib/x86_64-linux-gnu/libQt5Quick.so.5
0x00007fffe5522690  0x00007fffe581f636  Yes (*)     /usr/lib/x86_64-linux-gnu/libQt5Qml.so.5
0x00007fffe51996b0  0x00007fffe5221363  Yes (*)     /usr/lib/x86_64-linux-gnu/libQt5QuickTemplates2.so.5
(*): Shared library is missing debugging information.

^ all Qt libraries in current example are missing debug info. This is because debug info for qt libs are coming in separate packages, which are not being installed.

Whenever I did whatis everything worked fine:

(gdb) whatis e
type = QEvent *

but when I tried to access it's members

(gdb) p e->type()
Couldn't find method QEvent::type

and trying to get detailed type description

(gdb) ptype e
type = class QEvent {
  <incomplete type>
} *

Solution (for Qt on Ubuntu)

  1. Find to which package within your OS distribution does the file belongs
$ dpkg -S /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
libqt5core5a:amd64: /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
  1. Search for related packages

    Search with keywork libqt5core5a returned 2 packages, one is libqt5core5a itself, and another is libqt5core5a-dbgsym. Description for the latter says: "debug symbols for libqt5core5a"

  2. Install packages with debug symbols (I also installed debug symbols for some other essential Qt libraries)

$ sudo apt install libqt5core5a-dbgsym libqt5widgets5-dbgsym libqt5gui5-dbgsym
  1. Make sure in gdb that libraries now have debug info
(gdb) info share Qt
From                To                  Syms Read   Shared Object Library
0x00007ffff5336080  0x00007ffff56ba585  Yes         /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5
0x00007ffff4ad3510  0x00007ffff4ef0cbe  Yes         /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5
0x00007ffff47829c0  0x00007ffff47e1ba1  Yes (*)     /usr/lib/x86_64-linux-gnu/libQt5DBus.so.5
0x00007ffff40bb5e0  0x00007ffff439dd92  Yes         /usr/lib/x86_64-linux-gnu/libQt5Core.so.5
0x00007ffff2e571e0  0x00007ffff2e77e4f  Yes (*)     /usr/lib/x86_64-linux-gnu/libQt5Xml.so.5
0x00007ffff28c7a00  0x00007ffff29d8999  Yes (*)     /usr/lib/x86_64-linux-gnu/libQt5Network.so.5
0x00007ffff2250750  0x00007ffff2251a46  Yes (*)     /usr/lib/x86_64-linux-gnu/libQt5X11Extras.so.5
0x00007ffff1cc8f80  0x00007ffff1cfb861  Yes (*)     /usr/lib/x86_64-linux-gnu/libQt5PrintSupport.so.5
0x00007fffee268c10  0x00007fffee296b57  Yes (*)     /usr/lib/x86_64-linux-gnu/libQt5Svg.so.5
0x00007fffed985560  0x00007fffed9896a8  Yes (*)     /usr/lib/x86_64-linux-gnu/libQt5TextToSpeech.so.5
0x00007fffe95fc130  0x00007fffe96eec0c  Yes (*)     /usr/lib/x86_64-linux-gnu/libQt5XcbQpa.so.5
0x00007fffe701f650  0x00007fffe702fe0d  Yes (*)     /usr/lib/x86_64-linux-gnu/libQt5QuickControls2.so.5
0x00007fffe623c890  0x00007fffe64db1c1  Yes (*)     /usr/lib/x86_64-linux-gnu/libQt5Quick.so.5
0x00007fffe5b4f690  0x00007fffe5e4c636  Yes (*)     /usr/lib/x86_64-linux-gnu/libQt5Qml.so.5
0x00007fffe57c66b0  0x00007fffe584e363  Yes (*)     /usr/lib/x86_64-linux-gnu/libQt5QuickTemplates2.so.5
(*): Shared library is missing debugging information.
  1. Now working with Qt types works as expected
(gdb) p e->type()
$4 = QEvent::Paint
(gdb) ptype e
type = class QEvent {
  public:
...
}

What I've found is that if you disassemble a function that uses the incomplete struct type gdb 'discovers' the struct members and can subsequently display them. For example, say you have a string struct:

struct my_string {
    char * _string,
    int _size
} ;

some functions to create and get the string via pointer:

my_string * create_string(const char *) {...}
const char * get_string(my_string *){...}

and a test that creates a string:

int main(int argc, char *argv[]) {
    my_string *str = create_string("Hello World!") ;
    printf("String value: %s\n", get_string(str)) ;
    ...
}

Run it in gdb and try to 'print *str' and you'll get an 'incomplete type' response. However, try 'disassemble get_string' and then 'print *str' and it'll display the struct and values properly. I have no idea why this works, but it does.


It means that the type of that variable has been incompletely specified. For example:

struct hatstand;
struct hatstand *foo;

GDB knows that foo is a pointer to a hatstand structure, but the members of that structure haven't been defined. Hence, "incomplete type".

To print the value, you can cast it to a compatible type.

For example, if you know that foo is really a pointer to a lampshade structure:

print (struct lampshade *)foo

Or, you could print it as a generic pointer, or treat it as if it were an integer:

print (void *)foo
print (int)foo

See also these pages from the GDB manual:

  • http://sourceware.org/gdb/current/onlinedocs/gdb/Data.html#Data
  • http://sourceware.org/gdb/current/onlinedocs/gdb/Symbols.html#Symbols

Tags:

Gdb