m Protegit «Debugging» ([edit=autoconfirmed] (indefinit) [move=autoconfirmed] (indefinit)) |
Cap resum de modificació |
||
| Línia 1: | Línia 1: | ||
[[Category:SAPO]] | |||
[[Category:Devel]] | |||
== Com Compilar == | == Com Compilar == | ||
Revisió de 12:40, 7 gen 2015
Com Compilar
Per poder treballar amb el debugger hem de compilar en mode debug. Per això es fa servir el switch -g de gcc. No es recomanable treballar a l'hora amb funcions d'optimització (-O2). Als programes (no llibreries), hem d'afegir, a més, STRIP=no dintre del makefile.
Una manera alternativa, es, per programes, pasar-li les opcions de makefile per argument:
make CF=-g STRIP=no
A llibreries
make CF=-g
S'ha de tenir cura de que internament el Makefile estigui modificat per fer servir '$(CF)' a les opcions de cada sistema. La majoria ho estan.
Carregar
$ gdb ./binari
Sortirà molt de texte i a la darrera línia, hem de fixar-nos que no digui (no debugging symbols found). Això voldria dir que hem fallat a l'hora de compilar amb debug.
No podem afegir els arguments a la mateixa línia de comandes del gdb, s'ha de fer una vegada l'hem carregat:
(gdb) set args -bla bla
Comandes diverses
gdb ens permet resumir les comandes. Per exemple, run, pot ser ru o r. Similarment continue o cont pero no c doncs hi ha col·lisions amb d'altres comandes. Aquí faré servir-les tal como jo estic acostumat, i no necessariament en el seu nom complert.
S'ha de tenir especial cura de no presionar enter sense cap comanda escrita:
(gdb) // enter
doncs gdb això ho interpreta com repetir la darrera comanda.
Configurar arguments
Podem afegir-hi redireccions de shell:
(gdb) set args -bla bla < fitxer 2> /dev/null
No sortirà efecte fins al següent run.
Executar el programa
(gdb) r
Breakpoints
Afegir
(gdb) break NomFuncio (gdb) break NomFitxer.c:numlinea
Eliminar actual
(gdb) clear
Només funciona quan estem sobre la línia on es troba.
Llistar
(gdb) info breakpoints
Eliminar sel·lectivament
(gdb) delete 2 (gdb) clear main
On 2 es el número que surt al llistar, main es el nom de funció on teníem un altre breakpoint.
traçar
(gdb) n // executa la línia on ens trobem
(gdb) s // executa la línia, entrant dintre de les funcions
(gdb) adv 33 // executa fins que arribem a la línia 33
// es lo mateix que un breakpoint però només una vegada
(gdb) conti // el programa continua l'execució per si mateix
(gdb) r // tornem a executar el programa des del començament
Veure variables
Per veure el contingut d'una variable fem print. Ens pot mostrar el contingut d'estructures, vectors, inclús operacions més complexes i el resultat de cridar a funcions.
(gdb) print sapo // com que es un punter ens mostra el seu valor
$10 = (sapotype *) 0x88324c0
(gdb) print *sapo // dereferenciem
$11 = {maqnom = "jacq43b", '\0' <repeats 248 times>,
maqpath = '\0' <repeats 1023 times>,
drawnom = "jacq43b", '\0' <repeats 248 times>,
drawpath = '\0' <repeats 1023 times>,
drawdate = "\000\000\000\000\000\000\000",
[...]
(gdb) print sapo->maqnom // ens mostra tot el tamany del vector (256 bytes)
$8 = "jacq43b", '\0' <repeats 248 times>
(gdb) print (char*)sapo->maqnom // fem cast
$9 = 0x88324c0 "jacq43b"
(gdb) print is_jacquard_repeat
$16 = {int (sapotype *, int)} 0x8190ea0 <is_jacquard_repeat>
(gdb) print is_jacquard_repeat (sapo,1)
$17 = 1
Display es similar a print pero s'imprimirà per pantalla cada vegada que fem 'n' o 's'. Es molt útil a bucles per veure com van evolucionant les variables.
Watches
Els watches son expressions que volem veure quan canvien. Voldríem fer:
(gdb) watch sapo->maqnom[0] Hardware watchpoint 7: sapo->maqnom[0] (gdb) conti Continuing.
I quan canviem el maqnom al Machine Settings:
Hardware watchpoint 7: sapo->maqnom[0]
Old value = 106 'j' New value = 75 'K' 0x49298b96 in strcpy () from /lib/libc.so.6 (gdb)
De vegades això no funciona, diu:
Hardware watchpoint 6 deleted because the program has left the block in which its expression is valid.
Això ens passa per exemple al fer un watch de sapo quan sapo es una variable local (argument a la funció). Per fer el watchpoint moltes vegades ens va millor treballar amb direccions de memoria:
(gdb) print sapo $1 = (sapotype *) 0x88324c0 (gdb) watch ((sapotype *) 0x88324c0)->maqnom[0] Hardware watchpoint 3: ((struct sapostruct *) 142812352)->maqnom[0] (gdb)
D'aquesta manera el watchpoint funcionarà sempre que la direcció de memoria sigui vàlida, en aquest cas sempre perque sapo es realment una variable global.
Per llistar/eliminar watchpoints es fan servir les mateixes comandes que per breakpoints.
On estem
Moltes vegades ens interessa saber des d'on s'ens ha cridat, o el programa pinya dintre d'una funció standar (ex. strcpy), etc. Per situar-nos fem:
(gdb) backtrace
#0 0x49298b96 in strcpy () from /lib/libc.so.6
#1 0x081b28ad in llibera (fil=0x8829480, sapo=0x88324c0, what=4)
at /svn/svn.cadt.com/carta/devel/6.1.0/src/fonts/llibera.c:313
#2 0x08110cd1 in do_fgetpro (fil=0x8829480, sapo=0x88324c0, mensa=0x8830000,
pattern=0x883f2d0,
fname=0xbf82c6e0 "/opt/sapo/users/adria/revisar/jm.drf", load_temporal=0)
at /svn/svn.cadt.com/carta/devel/6.1.0/src/fonts/fgetpro.c:82
#3 0x0811101e in fgetpro (fil=0x8829480, sapo=0x88324c0, mensa=0x8830000,
pattern=0x883f2d0,
fname=0xbf82c6e0 "/opt/sapo/users/adria/revisar/jm.drf", load_temporal=0)
at /svn/svn.cadt.com/carta/devel/6.1.0/src/fonts/fgetpro.c:213
#4 0x0820c092 in projectrecent (fil=0x8829480, mensa=0x8830000,
sapo=0x88324c0, pattern=0x883f2d0, num=3)
at /svn/svn.cadt.com/carta/devel/6.1.0/src/fonts/projectrecent.c:153
#5 0x080b6a29 in main_loop (arglist=0x9dcee50)
at /svn/svn.cadt.com/carta/devel/6.1.0/src/fonts/carta.c:593
#6 0x085586aa in SAPO_Crash_Protect_Func ()
#7 0x080b52ce in main (argc=1, argv=0xbf82e854)
at /svn/svn.cadt.com/carta/devel/6.1.0/src/fonts/carta.c:327
(gdb)
Aquí veiem que ens trobem dintre de strcpy (no tenim nom de fitxer ni línia per que /lib/libc.so.6 no està compilat amb debug). Aquest strcpy s'ha cridat des de la línia llibera.c:313, etc. Realment no es la línia des d'on s'ha cridat sinó la línia següent (a on retornarem).
En alguns casos també necessitem saber a quin thread estem:
(gdb) thread [Current thread is 1 (Thread 1115840 (LWP 22397))] (gdb) info threads 2 Thread 13278096 (LWP 22400) 0x002a4402 in __kernel_vsyscall ()
- 1 Thread 1115840 (LWP 22397) 0x49298b96 in strcpy () from /lib/libc.so.6
També podem canviar de thread:
(gdb) thread 2
[Switching to thread 2 (Thread 13278096 (LWP 22400))]#0 0x002a4402 in __kernel_vsyscall ()
(gdb) backtrace
#0 0x002a4402 in __kernel_vsyscall ()
#1 0x493aa1c8 in recvfrom () from /lib/libpthread.so.0
#2 0x08573b0a in libsm_recv_any_buf (sock=6, buf=0xca91d0 "", ep=0xca8e80)
at /svn/svn.cadt.com/libsapomngr/trunk/src/fonts/comms.c:236
#3 0x08573b82 in libsm_recv_from_buf (sock=6, buf=0xca91d0 "", ep=0x9da90c0)
at /svn/svn.cadt.com/libsapomngr/trunk/src/fonts/comms.c:263
#4 0x08573bfc in libsm_recv_from (sock=6, msg=0xca91d0, ep=0x9da90c0)
at /svn/svn.cadt.com/libsapomngr/trunk/src/fonts/comms.c:289
[...]
En aquest cas estem al thread dintre de libsapo que es dedica a esperar que un altre carta ens digui RAISE i mostrar la finestra X.