Debugging drizzle with GDB

To use GDB, this is what I typically do...

Build the server with debugging symbols (--enable-debug) into /tmp using the attached script, then:

cd /tmp/mybranch/tests ./dtr --start-and-exit --gdb

This will pop open a GDB instance for the server process, and it is waiting for client connections...so let's go ahead and create one:

Switch back to your terminal and do:

cd /tmp/mybranch/client ./drizzle --user=root --port=9306

You will notice that the client seems to just "hang". Switch back the GDB session you have open for the server and you will notice that GDB (actually the test suite...) has set a breakpoint at the mysql_parse function. You'll see something like this:

[Switching to Thread 0xb317fb90 (LWP 11710)]

Breakpoint 1, mysql_parse (thd=0x8878c18), inBuf=0x8882290 "select @@version_comment limit 1", length=32, found_semicolon=0xb317f040) at sql_parse.cc:2870 2870                         const char ** found_semicolon) (gdb)

The above is basically showing you the function call stack and argument addresses being passed to the mysql_parse function, located in drizzled/sql_parse.cc at line 2870.

To see the full call stack, do:

(gdb) where

You'll see that the call stack goes from the thread scheduler (libevent_thread_proc) to the parser (do_command, then dispatch_command, then mysql_parse).

To step into the server process, do:

(gdb) step

This will run to the next function call. Simply hit enter to repeat the step. To see what a variable contains at any time, simple do:

(gdb) print name_of_variable

For instance, if I do:

(gdb) print thd

I get:

$1 = (class THD*) 0x8878c18

I can also grab a pointer's member variables, such as the thread's current query ID:

(gdb) print thd->query_id

$2 = 1

And so on...

You can set another break point (for instance, a function you are interested in) by doing:

(gdb) break function_name

for instance, if I look through the source code, I see that once a SELECT query is issued by the client, the function mysql_select is called, so I could do:

(gdb) break mysql_select

GDB will inform you a breakpoint has been set, and the line number of the file, like so:

Breakpoint 2 at 0x814ea09: file sql_select.cc, line 2618.

To continue until that breakpoint, do:

(gdb) continue

And you are now at mysql_select...

If you continue again, and you switch back to your terminal with the drizzle client in it. You should see a drizzle client at the command prompt, like so:

[503][jpipes@serialcoder: /tmp/trunk/client]$ ./drizzle --user=root --port=9306 Welcome to the Drizzle client.. Commands end with ; or \g. Your Drizzle connection id is 1 Server version: 7.0.0-log Source distribution

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

drizzle>>

Keep this client open, since you will be executing commands through it.

In the GDB session, type:

(gdb) break mysql_parse (gdb) continue

Then the client, do:

drizzle>> SELECT * FROM INFORMATION_SCHEMA.TABLES;

and switch back to the server GDB session. You will see that GDB has broken once more at mysql_parse and that the inBuf is the "SELECT * FROM INFORMATION_SCHEMA.TABLES" you just sent it...

I'll let you play around with GDB and see what else it can do. :)

Cheers, and hope this gets you on your way at least,

Jay

Debug di Drizzle con GDB