FANDOM


Ecco cosa faccio in genere per utilizzare GDB...

Compilo il server con i simboli di debug (--enable-debug) in /tmp utilizzando lo script allegato, poi:

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

Questo apre un'istanza GDB per il processo server, che aspetta connessioni client... procediamo e creiamone una:

Torniamo al terminale e facciamo:

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

Noterai che il client sembra disconnettersi.Torniamo alla sessione GDB che abbiamo aperto per il server e noterai che GDB (in effetti la test suite...) ha impostato un breakpoint alla funzione mysql_parse(). Vedrai qualcosa del genere:

[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)

Questo messaggio essenzialmente mostra lo stack delle chiamate e gli indirizzi degli argomenti che vengono passati alla funzione mysql_parse(), che si trova in The above is basically showing you the function call stack and argument drizzled/sql_parse.cc alla riga 2870.

Per vedere tutto lo stack:

(gdb) where

Vedrai che lo stack delle chiamate va dallo scheduler (libevent_thread_proc()) al parser (do_command(), poi dispatch_command(), poi mysql_parse()).

Per entrare nel processo server:

(gdb) step

Questo eseguirà la prossima chiamata. Semplicemente premi enter per ripetere il passaggio. Per vedere il contenuto di una variabile di volta in volta, semplicemente digita:

(gdb) print name_of_variable

Per esempio, se faccio:

(gdb) print thd

Ottengo:

$1 = (class THD*) 0x8878c18

Posso anche accedere alle variabili membro di un puntatore, come l'id della query corrente:

(gdb) print thd->query_id

$2 = 1

E così via...

Puoi impostare un altro breakpoint (per esempio una funzione che ti interessa) in questo modo:

(gdb) break function_name

Per esempio se scorro il codice sorgente mi accorgo che una volta che una SELECT è eseguita dal client, viene chiamata la funzione mysql_select(), quindi posso fare:

(gdb) break mysql_select

GDB ti informa che è stato impostato un breakpoint e ti dice il numero di riga, in questo modo:

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

Per continuare fino a quel breakpoint:

(gdb) continue

Ora sei arrivato a mysql_select()...

Continua oltre e poi torna al terminale con il client drizzle. Dovresti vedere un client al prompt dei comandi, così:

[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>>

Tieni aperto questo client, perchè eseguirai dei comandi in esso.

Nella sessione GDB scrivi:

(gdb) break mysql_parse (gdb) continue

Poi torna al client:

drizzle>> SELECT * FROM INFORMATION_SCHEMA.TABLES;

e torna nuovamente alla sessione server GDB. Vedrai che GDB si è interrotto nuovamente a mysql_parse() e che inBuf contiene la query "SELECT * FROM INFORMATION_SCHEMA.TABLES" che hai appena lanciato...

Ora gioca un po' con GDB e guarda cosa riesci a fare :)

Saluti, e spero che questo articolo ti sia stato d'aiuto,

Jay