I’m trying to debug some STL based C++ code in gdb.
The code has something like
int myfunc()
{
std::map<int,int> m;
...
}
Now in gdb, inside myfunc using “print m” gives something very ugly.
What I’ve seen recommended is compiling something like
void printmap( std::map<int,int> m )
{
for( std::map<int,int>::iterator it = ... )
{
printf("%d : %d", it->first, it->second );
}
}
Then in gdb doing
(gdb) call printmap( m )
This seems like a good way to handle the issue… but can I put printmap into a seperate object file (or even dynamic library) that I then load into gdb at runtime rather than compiling it into my binary – as recompiling the binary every time I want to look at another STL variable is not fun .. while compiling and loading a single .o file for the print routine may be acceptable.
UPDATE:
Prompted by Nikolais suggestion I’m looking at dlopen/dlsym.
So I haven’t yet got this working but it feels like I’m getting closer.
In printit.cpp
#include <stdio.h>
extern "C" void printit()
{
printf("OMG Fuzzies");
}
Compile to a .so using
g++ -Wall -g -fPIC -c printit.cpp
g++ -shared -Wl,-undefined,dynamic_lookup -o printit.so printit.o
Start my test application and load the .so using dlopen ( 2 = RTLD_NOW ) then try to get the symbol for a debugging function using dlsym.
(gdb) break main
(gdb) run
(gdb) print (void*) dlopen("printit.so", 2 )
$1 = (void *) 0x100270
(gdb) print (void*) dlsym( 0x100270, "_printit" )
$2 = (void *) 0x0
So close but for some reason I cant get that symbol… ( I cant even get it if I put the
dlopen/dlsym calls in my executable) I’m guessing I’m either compiling the lib wrong or using dlsym incorrectly.
If I can get the symbol I’m assuming I can call the function using something like
(gdb) print (( void(*)() )(0x....))()
I’m compiling this on OS X 10.4, which might be causing some of my .so woes… any pointers would be appreciated.
Found out how to get all this working. Have posted as a solution below.
So my solution is to load a shared object containing my debugging routines at run time, using
dlopen. Turns out it is even simpler than I thought when you get all the compile flags right.On OS X this means you compile your application and debugging object like this:
The
-fPICon the application is critical, as is the-dynamiclib(rather than trying the linux-sharedflag )An example
debug_helper.cppmight look like thisDon’t know why I chose to use stdio rather than iostream stuff… I guess you can use either. (just don’t forget to flush the streams…)
Now my application file looks like this:
And here’s an example debugging session (some output removed)
Start the application and break at an interesting point
Load in the debug helper library
GDB is smart and catches all the new symbols for us so we don’t need to use
dlsymetc.We can just call the functions directly.
Let’s add some more info to printMap.
First, unload the library.
Edit the source to add in the sum of the entries. Recompile and then load
the new library back into gdb (without restarting the executable or gdb )
Use the modified function
I think this does everything that I need.