Diapositiva 1 - PowerPoint PPT Presentation

1 / 42
About This Presentation
Title:

Diapositiva 1

Description:

Corso di Programmazione di Sistema Anno accademico 2005/2006 Debugging e gdb E. P. Mancini e U. Villano Strategie generali di debugging Conferma Quando un programma ... – PowerPoint PPT presentation

Number of Views:69
Avg rating:3.0/5.0
Slides: 43
Provided by: ingUnisan6
Category:

less

Transcript and Presenter's Notes

Title: Diapositiva 1


1
Corso di Programmazione di Sistema Anno
accademico 2005/2006
Debugging e gdb E. P. Mancini e U. Villano
2
Strategie generali di debugging
  • Conferma
  • Quando un programma contiene un bug, da qualche
    parte cè qualcosa che voi credete vero ma che in
    realtà non lo è.
  • Esempi
  • credete che a un certo punto una variabile abbia
    un certo valore
  • credete che in uno statement if-then-else sia
    eseguito il ramo else
  • credete che richiamando una funzione, essa riceva
    correttamente i parametri

3
Strategie generali di debugging
  • Il processo dellindividuazione della locazione
    di un bug consiste nel confermare quello che
    credete
  • Se credete che la variabile abbia un certo
    valore, controllate!
  • Se credete che venga eseguito un ramo else,
    controllate!
  • Prima o poi troverete che quello che credete non
    è confermato ? avete individuato il bug

4
Strategie generali di debugging
  • Ricerca binaria
  • Nella ricerca di conferme a quello che credete,
    usate una tecnica di ricerca binaria
  • Es. supponiamo di avere un file sorgente unico
    di 200 linee senza chiamate di funzione.
  • Credete che x49 per tutta lesecuzione de
    programma. Esaminate x4 alla linea 100. Se è 9,
    la ricerca si restringe alle linee 101-200. Poi
    provate alla linea 150, ...

5
Strategie generali di debugging
  • E se il programma non viene nemmeno compilato?
  • Spesso il compilatore segnala lerrore allultima
    linea della definizione di una funzione (o
    classe). Lerrore può essere in un qualsiasi
    punto della funzione.
  • Usate la ricerca binaria
  • Commentate metà della funzione e ricompilate, ...

6
Usate un tool di debugging e un buon editor di
testo
  • Non usate printf()/cout come principale strumento
    di debugging
  • Confermare il valore assunto da variabili
    potrebbe essere fatto aggiungendo printf() o cout
    nel sorgente
  • Questa è una tecnica particolarmente poco
    conveniente (aggiunta di printf, ricompilazione,
    esecuzione, aggiunta di altri printf,
    ricompilazione, ..., eliminazione del bug,
    eliminazione dei printf)

7
Usate un tool di debugging e un buon editor di
testo
  • Un tool di debugging permette di esaminare i
    valori di variabili in maniera molto più comoda
  • Non occorre ricompilare
  • Potete monitorare automaticamente tutte le
    variabili che volete
  • Questo vi permette di concentrarvi sulla ricerca
    del bug!!

8
Usate un tool di debugging e un buon editor di
testo
  • Un tool di debugging vi dice anche dove si è
    verificato un errore dalle conseguenze peggiori
    (per es., un segmentation fault)
  • Vi segnala anche chi ha chiamato la funzione che
    ha generato lerrore
  • Fatevi un favore usate un debugger, non printf
    !!!

9
Quali tool utilizzare?
  • gdb
  • Un classico, disponibile sulla maggioranza dei
    sistemi Unix (e non ? Cygwin)
  • front-end grafici per gdb
  • gdb è un tool in modalità testo. Sono stati
    sviluppati molti front-end GUI per il gdb. Es.
  • ddd
  • KDbg (kde)
  • Insight (Red Hat, Cygwin)

10
Quali tool utilizzare?
  • Un buon editor di testo può aiutare molto
  • Fondamentale lutilizzo di un editor con
  • funzionalità di undo/redo (? ricerca binaria)
  • subwindows (anche in modalità testo)
  • interfaccia con debugger e compilatore
  • Consigli
  • vim (vi improved)
  • emacs
  • ....

11
Strategie di base
  • lanciare gdb
  • settare un certo numero di breakpoints (posizioni
    nel codice nelle quali vogliamo sospendere
    lesecuzione del programma)
  • esaminare (a programma sospeso) i valori di
    variabili
  • magari procedere in single step (esecuzione di
    una istruzione per volta) per esaminare il flusso
    dellesecuzione

12
Strategie di base
  • Per i segmentation faults
  • eseguire il programma sotto gdb (magari senza
    breakpoints)
  • al fault, gdb ci dice la locazione dellerrore
  • se questa fosse in una funzione di
    libreria/system call, il comando bt (backtrace)
    ci permette di risalire alla chiamata della
    funzione che ha causato lerrore

13
Debugger
  • Un debugger è un programma che permette di
    effettuare un'analisi approfondita di un altro
    programma in modo da aiutare a trovare i difetti
    dello stesso.
  • Un debugger, tra le altre cose, può,
    relativamente ad un programma
  • avviarlo
  • interromperlo
  • esaminarlo
  • modificarne lo stato (variabili, registri)

14
Debugger
DEBUGGER
controllo dellesecuzione
Programma
15
Debugger
Debugger
Sorgente
controlla
memoria (stack, heap)
codice macchina
registri
Programma in esecuzione
16
Sessione di debugging
  • Un programma deve essere compilato in modo
    adeguato
  • Con gcc
  • gcc g o testprog testprog.c
  • -g inclusione dei dati di debug
  • -o nome nome delleseguibile.
  • .c sorgenti c
  • Lopzione ggdb al posto di g permette di
    inserire informazioni specifiche per gdb ma
    potrebbe non essere compatibile con altri
    debugger.

17
Sessione di debugging
sorgenti (es. .c)
Editor (es. vim)
codice oggetto (es. .o, .obj)
Compilatore (es. gcc)
informazioni di debug
eseguibile/libreria
Linker (es. ld)
18
Sessione di debugging
Se nelleseguibile non vengono inserite le
informazioni di debug non è possibile avere una
corrispondenza con il codice ad alto livello ? si
ha la sola vista del codice assembly.
19
Operazioni possibili
  • Avvio programma
  • Esecuzione a passi (single-stepping)
  • Inserimento di punti di interruzione
    (breakpoints)
  • Ispezione dei dati e visualizzazione strutturata

20
Esempio
  • Creare un programma, chiamato test, che accetti
    un parametro da linea di comando. Se il parametro
    è la parola utente (senza controllo delle
    maiuscole), deve stampare la frase abilitato,
    altrimenti deve stampare la frase accesso
    fallito. Compilarlo con le opzioni per il debug
    attive. Il controllo della stringa deve avvenire
    in unapposita funzione che usa strcmp (che però
    è case sensitive).
  • gt ./test utente
  • abilitato
  • gt ./test Utente
  • abilitato
  • gt ./test prova
  • accesso fallito

21
Esempio con errori
  • include ltstdio.hgt
  • include ltstring.hgt
  • define BUFLEN 7
  • int test(char word)
  • return (strcmp("utente", word)0)
  • int main(int argc, char argv)
  • char bufferBUFLEN
  • int result
  • strcpy(buffer, argv0)
  • result test(buffer)
  • if (result)
  • printf("abilitato\n")
  • else
  • printf("accesso fallito\n")
  • return result

22
Problemi nel programma di esempio
  • non cè controllo sul numero di parametri
  • argv0 non è il primo parametro
  • strcpy non controlla il superamento del buffer (?
    segmentation fault)
  • strcmp è sensibile alla differenza
    maiuscole/minuscole

23
Avvio del debugger
  • Su un eseguibile esterno
  • gdb nome_eseguibile
  • es. gdb test
  • Su un programma in esecuzione
  • gdb programma pid
  • Su un core dump
  • gdb programma corefile
  • Per terminare
  • q, quit o ctrl-D

24
gdb in versione GUI
Uscita
Esecuzione di una funzione
Espressioni
Entrata in una funzione
Stack
Memoria
Avvio
Variabili locali
Breakpoints
Registri
Modalità di visualizzazione - sorgente, -
assembly, - mista.
Funzione
Modulo
25
Avvio del programma
  • run esegue il programma caricato fino a quando
    non trova un punto di interruzione (breakpoint o
    watchpoint)

26
Avvio del programma
  • Argomenti da linea di comando
  • (gdb) set args
  • imposta gli argomenti.
  • (gdb) show args
  • visualizza gli argomenti
  • oppure
  • (gdb) run args
  • esecuzione con gli argomenti dati
  • Ambiente
  • path aggiunge una directory al path.
  • cd cambia la directory corrente.
  • set environment imposta una var. di ambiente.

27
Avvio del programma
  • Connessione a programmi già in esecuzione
    (attach)
  • (gdb) attach pid
  • si collega ad un processo avviato fuori dal gdb.
  • (gdb) detach
  • rilascia il processo cui ci si è collegati
    tramite attach.

28
Avvio del programma
  • Esame di un core dump
  • Un core dump è unistantanea prodotta dal
    sistema operativo di un programma che ha avuto un
    errore grave (es. Segmentation Fault) durante
    lesecuzione. Permette di effettuare unanalisi
    post-mortem del programma.
  • gdb test core
  • 0 0x40054b03 in ?? () from /lib/libc.so.6
  • a questo punto si può fare un backtrace (analisi
    delle chiamate) per capire dove si trova
    lerrore
  • (gdb) bt

29
Esecuzione a passi
  • (gdb) continue ignorecount
  • (gdb) c ignorecount
  • Continua lesecuzione di un programma
    dallistruzione in cui era stato fermato.
  • (gdb) step count
  • (gdb) s count
  • Esegue una o più istruzioni successive.
  • (gdb) next count
  • (gdb) n count
  • Esegue le istruzioni successive considerando le
    funzioni come atomiche. Non entra, cioè,
    allinterno del corpo delle funzioni che
    incontra.
  • (gdb) finish
  • Continua fino alla terminazione della funzione
    corrente.

30
Analisi dello stack
  • Ogni funzione chiamata crea un frame sullo stack.
  • (gdb) frame
  • (gdb) frame num
  • (gdb) frame address
  • Visualizza il frame corrente o si sposta su uno
    diverso.
  • (gdb) backtrace n
  • (gdb) bt n
  • Visualizza una riga per gli ultimi n frames
    presenti sullo stack. Fa unanalisi delle
    chiamate.

31
Analisi dello stack
Allinizio dellesecuzione programma gli unici
frame dello stack sono quelli di libreria
kernel32 e del main.
32
Analisi delle espressioni e delle variabili
  • (gdb) print expr
  • (gdb) p/formato expr
  • visualizza il risultato dellespressione
    utilizzando un formato specificato (es. p/x
    stampa in esadecimale, p/d in decimale con segno,
    ...), se non viene indicato un formato, questo
    viene desunto dalle informazioni di debug.
  • Es. allinizio del programma test
  • (gdb) p argv0
  • 1 0x22fdc4 /home/user/testgdb/test
  • mostra che argv0 è il nome del programma e non
    il primo parametro.

33
Analisi delle espressioni e delle variabili
  • (gdb) display expr
  • (gdb) disp/formato expr
  • visualizza il valore dellespressione utilizzando
    un formato specificato ogni volta che
    lesecuzione del programma viene sospesa (cioè ai
    breakpoints e nello stepping).
  • Leffetto di un comando display si cancella con
  • (gdb) undisplay expr_code_number
  • (gdb)info display
  • mostra la lista corrente di code numbers

34
Analisi delle espressioni e delle variabili
  • gdb accetta anche comandi printf, assolutamente
    simili alla omonima funzione C
  • (gdb) printf Xd, Yd\n,X,Y
  • Con display e print, tenere sempre presente la
    differenza tra variabili globali e locali
  • se x è una variabile dichiarata nella funzione f
    e f non e attiva, il comando print x produce un
    messaggio
  • No variable x in current context

35
Analisi della memoria
  • (gdb) x/formato indirizzo
  • visualizza il contenuto della memoria.

36
Disassemblare il codice
  • Per disassemblare il codice
  • (gdb) disassemble nome_funzione
  • (gdb) disass main
  • Dump of assembler code for function main
  • 0x8048420 ltmaingt push ebp
  • 0x8048421 ltmain1gt mov esp,ebp
  • 0x8048423 ltmain3gt sub 0x8,esp
  • 0x8048426 ltmain6gt call 0x8048400 ltfungt
  • 0x804842b ltmain11gt sub 0xc,esp
  • 0x804842e ltmain14gt push 0x80484a8
  • 0x8048433 ltmain19gt call 0x80482f0 ltprintfgt
  • 0x8048438 ltmain24gt add 0x10,esp
  • 0x804843b ltmain27gt mov ebp,esp
  • 0x804843d ltmain29gt pop ebp
  • 0x804843e ltmain30gt ret
  • 0x804843f ltmain31gt nop
  • End of assembler dump.

37
Analisi dei registri
  • Si fa riferimento ai registri indicandone il nome
    preceduto dal simbolo . Ad esempio pc per il
    program counter e sp per lo stack pointer.
  • (gdb) info registers
  • visualizza tutti i registri escluso quelli in
    virgola mobile.
  • (gdb) info all-registers
  • visualizza tutti i registri.
  • Es. (gdb) p/x pc
  • 6 0x401100
  • visualizza il program counter
  • (gdb) x/i pc
  • lea 0xffffffe8(ebp),eax
  • 0x401100 ltmain30gt
  • visualizza listruzione successiva
  • (gdb) set sp 4
  • modifica il valore dello stack pointer

38
Breakpoints
  • Sono punti di interruzione del flusso
    dellapplicazione, si inseriscono con il comando
    break (abbreviato b) seguito dal nome di una
    funzione, da un indirizzo di memoria o da un
    numero di linea.
  • es. (gdb) b main
  • interrompe lesecuzione allinizio della funzione
    main
  • es.(gdb) b 7
  • Breakpoint 2 at 0x40109e file test.c, line 7.
  • inserisce un breakpoint sulla linea 7 (per vedere
    il sorgente coi numeri di linea list)

39
Breakpoints
  • I punti di interruzione possono essere inseriti
  • su una funzione break funzione
  • su un indirizzo relativo break -offset
  • su una linea break numlinea
  • su una linea di un file specifico break
    filenamenumlinea
  • su un indirizzo break indirizzo
  • sulla prossima istruzione break
  • E possibile inserire breakpoints condizionali
  • es. (gdb) b 3 zgt92
  • ferma listruzione al breakpoint n. 3 (settato in
    precedenza) solo se zgt92

40
Watchpoints
  • Un watchpoint è uno speciale breakpoint che si
    attiva quando il valore di unespressione cambia.
  • es. (gdb) watch expr
  • il programma viene interrotto quando cambia il
    valore dellespressione indicata.

41
Comandi set e call
  • Il comando set può essere utilizzato per
    modificare il valore di una variabile o di un
    registro
  • es. (gdb) set variable x12
  • Il comando call serve per invocare lesecuzione
    di una funzione (tipicamente una funzione scritta
    per il debugging, per es. per stampare una lista
    a puntatori)

42
Ricompilazione
  • Non occorre uscire dal gdb prima di ricompilare
  • Ricompilate in unaltra finestra. Allesecuzione
    di r (run), il gdb automaticamente utilizzerà
    leseguibile più recente.
Write a Comment
User Comments (0)
About PowerShow.com