You are on page 1of 24

WINDEBUG

Manuale di uso

Windebug è un debug con interfaccia grafica, basato sulle funzioni del debugger Gnu-GDB, utilizzabile per
programmi sviluppati con Proteus, su piattaforme:
ARM7-DTMI (V4L,V4C…)
Cortex M3 (V7,V8,V10,Pineapple…)
Cortex M4 (Vxx DSP)
Cortex A53 (Sistema T, Raspberry Pi2-Pi3-Pi4 con sistema operativo LINUX-ARM Raspbian
Jessie/Stretch/Buster)
Windows (PC con sistema operativo Windows XP/Vista/7/8/10/11)

Caratteristiche comuni a tutte le versioni:

- Si può debuggare il codice dell’ ultima versione compilata del programma. Se si fanno modifiche
occorre ricompilare e il debug non funziona su eseguibili precedenti, in quanto le linee di programma
non corrispondono più agli indirizzi di memoria.
- Si può lanciare il debug al di fuori di Proteus, ma occorre che la directory del programma che si vuole
debuggare non sia stata spostata o rinominata dopo la compilazione.
- Non occorre l’ opzione di compilazione DEBUG. Se tale opzione viene settata l’ unica differenza è che
nel codice del source appare per ogni linea l’ indirizzo di memoria relativo, ma in tal caso la
compilazione è (inutilmente) molto più lenta.
- Non occorre l’ opzione di ottimizzazione ZERO, anche se con tale opzione l’ esecuzione passo-passo del
programma è più leggibile.
- Si possono mettere un numero illimitato di breakpoints sulle linee di programma.
- Si può avanzare linea per linea (step-out) o seguire il flusso del programma (step-in). In altre parole se
una linea di programma contiene una Call, con step-in si entra nella call, mentre con step-out la call
viene eseguita in modo silenzioso e il debug si ferma alla riga successiva.
- Si possono esaminare i valori delle variabili cliccando sulla variabile nel listato del source.
- Si può esaminare ed eventualmente mettere dei breakpoints sul codice di tutti i sorgenti del
programma, comprese le librerie usate dal programma.
- Si può esaminare il back-trace (lo stack delle chiamate fino al punto di arresto in corso) e visualizzarne il
source (con il click del mouse destro)
- Si può avere la lista dei threads attualmente attivi.
- Si può fare una lista di variabili che verranno automaticamente visualizzate ad ogni break e ad ogni
step.
- Si può visualizzare la linea di programma in cui una variabile viene definita (con il click del mouse
destro)
- Si può avere una lista di tutte le occorrenze di una variabile, e visualizzarne il source (con il click del
mouse destro)
- Si può visualizzare il contenuto di un’ area di memoria
- Per i programmi ARM, Cortex e Linux è necessario per il debug un collegamento Ethernet o Wi-Fi.
Pur essendo WinDebug un unico programma, vi sono alcune differenze nelle funzionalità del
debug tra l’ esecuzione del debug per un programma ARM-CORTEX rispetto ad un programma
LINUX-WINDOWS.

Per la versione ARM-CORTEX:

- Il debug è compatibile con ogni versione del bios ARM, mentre per la versione CORTEX, il bios
deve essere versioe 9.1 o successiva.
- Si può debuggare un programma che sta già girando, senza interromperlo, e un breakpoint ferma
solo il task su cui è eseguito.
- Debuggando un programma fermo per un errore (TASK xx FAULT) il programma mostra la linea su
cui è avvenuto l’ errore, e si possono visualizzare i valori delle variabili e il back-trace dello stack che
ha portato all’ errore. Il debug può essere eseguito anche dopo che il programma si è bloccato, nel
qual caso il debug deve essere lanciato fuori da Proteus.
- Lanciando il debug da Proteus, il programma, se non già in esecuzione, viene automaticamente
caricato sulla periferica, tutti i breakpoints vengono cancellati e il programma è stoppato all’ inizio
del main.
- Tutti i comandi sono attivi anche quando il programma non è fermo su un breakpoint.
- Si possono mettere breakpoints multipli e contemporanei su task diversi.
- Si può visualizzare lo stato dei singoli task, i relativi tempi di esecuzione e i semafori associati.
- Un breakpoint ferma solo il task del breakpoint, mentre gli altri task continuano a girare.
- Non è possibile mettere breakpoint sul task ethernet (che è quello che gestisce i breakpoints).

Per le versioni LINUX e WINDOWS:

- Nelle versioni Windows e Linux il programma viene lanciato e stoppato all’ inizio del main,
pertanto il programma non deve essere in esecuzione quando si lancia il debug.
- Nella versione Linux il programma deve essere precedentemente stato inviato alla periferica, ma
non è necessario che stia girando.
- Un breakpoint ferma tutti i threads del programma.
- Quando il programma sta girando non si possono eseguire comandi dal debug (solo dopo un break
o uno step)
- Quando il programma sta girando si può fermare con uno stop (Linux) o premendo Esc con il
cursore sulla finestra del programma (Windows).
- Si possono eseguire step fino alla fine di un loop o fino alla fine della funzione.
- Si possono visualizzare i valori delle variabili locali della funzione su cui è avvenuto il breakpoint
- Si possono creare breakpoints sul cambiamento del valore di una variabile, o della sua scrittura, o
della sua lettura (watchpoints)
- Si possono creare breakpoints condizionati (break if …)
- Si possono creare breakpoints e watchpoints che non interrompono l’ esecuzione del programma,
ma semplicemente stampano una stringa creata con un printf() contenente valori di variabili od
altro, e continuano l’ esecuzione.
- È possibile cambiare il valore di una o più variabili quando il programma è fermo.
- È possibile continuare il programma da un punto diverso da quello in cui si è fermato.
- È possibile creare liste di comandi, salvarle con un nome, caricarle ed eseguirle.
- È possibile visualizzare un’ intera struttura, ed i valori di tutti i campi relativi.
- È possibile visualizzare i registri della CPU ed il codice assembler della linea su cui il programma è
fermo, oppure il codice assembler dell’ intera funzione.

Alcune note sul funzionamento di Windebug.

Il compilatore gnu-gcc produce un eseguibile di tipo ELF, indipendentemente dalla cpu target.
Proteus usa 5 diversi compilatori gcc:

Per ARM C:\commons\c\armgcc\Bin\arm-hitex-elf-gcc.exe con switch -mcpu=arm7tdmi


Per CORTEX C:\commons\c\armgcc2\Bin\arm-none-eabi-g++.exe con switch -mcpu=cortex-m3
Per CORTX DSP C:\commons\c\armgcc3\Bin\arm-none-eabi-gcc.exe con switch -march=armv7e-m -fpu=fpv4-sp-d16
Per LINUX C:\commons\c\armgcc4\bin\arm-linux-gnueabihf con switch -march=armv8-a -mfpu=vf
Per Windows C:\commons\c\dev-cpp\gcc.exe con switch –mwindows

Compilando con opzione –g (oppure –ggdb) l’ eseguibile contiene tutte le informazioni necessarie a gdb per gesire la
sessione di debug dell’ eseguibile.

Windebug usa come motore principale l’ applicazione gdb.exe

Per ARM,CORTEX e CORTEX DSP usa C:\\COMMONS\\C\\armgcc2\\bin\\arm-none-eabi-gdb.exe


Per LINUX usa C:\\COMMONS\\C\\armgcc4\\bin\\arm-linux-gnueabihf-gdb.exe
Per Windows usa C:\\COMMONS\\C\\dev-cpp\\bin\\gdb32.exe

Il programma gdb.exe selezionato gira sempre sul PC con cui è stato compilato il programma, in una shell di
DOS in background, collegato con Windebug con 2 pipes, una di lettura e una di scrittura.
GDB è un programma a linee di testo, che accetta i comandi da tastiera (stdin) e stampa le risposte nella
finestra di DOS in cui gira (stdout).
Stdin è rediretto su una pipe di output di Windebug, e stdout è rediretto su una pipe di input di Windebug,
così Windebug ha il pieno controllo di gdb e si sostituisce all’ utilizzatore da console.

Le risorse utilizzate da gdb sono:

- La tastiera e lo schermo del PC (stdin e stdout) per ricevere i comandi e mostrare le risposte (nel
nostro caso sostituite dalle due pipes da e verso Windebug)
- L’ eseguibile, che viene mandato in esecuzione e che contiene le informazioni relative ai files del
sorgente, alle librerie e all’ indirizzo di memoria del codice eseguibile e delle variabili.
- I sorgenti (.C, .H, .CPP …) che debbono trovarsi nelle directory in cui erano al momento della
compilazione.
- Un hardware su cui far girare il programma, che può essere il PC stesso (programma per Windows),
oppure un hardware esterno, collegato via ethernet o wi-fi, su cui gira un server (gdbserver), è il
caso di programma LINUX.
- Per i programmi per ARM e CORTEX, non esiste un server gdb, per cui i comandi diretti verso il
server e le relative risposte vengono deviati verso un client UDP sulla porta 0x2764, che colloquia
con il relativo server sulla macchina su cui gira il programma. Si tratta dei comandi RUN, STEP-IN,
STEP-OUT, read-ram e read status e delle relative risposte. Tutti gli altri comandi vengono eseguiti
da GDB leggendo i dati presenti sul PC, senza bisogno di consultare l’ hardware esterno.
- Una connessione TCP sulla porta 0x2700 e una connessione UDP sulla porta 0x2764 (caso ARM-
CRTEX)
- Una connessione TCP sulla porta 1234 verso gdbserver e una connessione UDP sulla porta 0x2764
verso console2 (caso LINUX)
All’ avvio viene esaminato il tipo di eseguibile (.exe per windows, .bin per linux, .elf per arm-cortex).

Eseguibile PC:
- Viene lanciato in background il processo GDB per windows, con 2 pipes rispettivamente per stdin e
stdout, collegate con windebug
- Dal processo GDB viene lanciato l’ eseguibile .exe, stoppandolo su winmain.
- Windebug controlla il processo GDB tramite le 2 pipes, inviando i comandi ed attendendo le
risposte.
- Ad ogni comando è attesa una risposta immediata, salvo per i comandi run, continue e step, per cui
la risposta avviene quando l’ azione è eseguita ed il programma è fermo.
- Ogni risposta (che può essere multi linea) termina con la linea “(gdb)”
- Le risposte vengono interpretate e il loro contenuto visualizzato nei campi relativi.

Eseguibile LINUX:
- Viene lanciato in background il processo GDB per linux, con 2 pipes rispettivamente per stdin e
stdout, collegate con windebug.
- Viene lanciato il gdbserver con un comando diretto verso console2.
- Dal processo GDB viene lanciato il collegamento con gdbserver, comunicandogli la porta TCP di
colloquio (porta 1234).
- Dal processo GDB viene lanciato l’ eseguibile, stoppandolo su main.
- Windebug controlla il processo GDB tramite le 2 pipes, inviando i comandi ed attendendo le
risposte. Le richieste che implicano una modifica di esecuzione o la lettura di variabili dell’
eseguibile, vengono inoltrate al gdbserver e la risposta arriva da esso, prima che il gdb la visualizzi
su stdout.
- Ad ogni comando è attesa una risposta immediata, salvo per i comandi run, continue e step, per cui
la risposta avviene quando l’ azione è eseguita ed il programma è fermo.
- Ogni risposta (che può essere multi linea) termina con la linea “(gdb)”
- Le risposte vengono interpretate e il loro contenuto visualizzato nei campi relativi.

Eseguibile ARM-CORTEX:
- Viene lanciato in background il processo GDB per arm-cortex, con 2 pipes rispettivamente per stdin
e stdout, collegate con windebug.
- Windebug invia il programma alla macchina in remoto, se il programma non è già in esecuzione.
- Da Windebug, se il programma non sta già girando, viene lanciato l’ eseguibile, stoppandolo su
main.
- Windebug controlla il processo GDB tramite le 2 pipes, inviando i comandi ed attendendo le
risposte. Le richieste che implicano una modifica di esecuzione o la lettura di variabili dell’
eseguibile, vengono inoltrate direttamente da Windebug ramite UDP sulla porta 0x2764 e la
risposta arriva da esso e viene visualizzata bypassando GDB.
- Ad ogni comando è attesa una risposta immediata, salvo per i comandi run, continue e step, per cui
la risposta avviene quando l’ azione è eseguita ed il task relativo è fermo.
- Ogni risposta (che può essere multi linea) termina con la linea “(gdb)”
- Le risposte vengono interpretate e il loro contenuto visualizzato nei campi relativi.

LE FUNZIONI DI Windebug

Figura 1:
Lanciando Windebug
esternamente da Proteus
appare una finestra che
consente di scegliere il
programma da debuggare e
il tipo di hardware su cui
gira.

Figura 2:
Se l’ hardware è Linux o
Cortex viene tentato il
collegamento con la
periferica. Se l’ indirizzo IP
non è corretto occorre
impostarlo e premere il
bottone Connect. L’ indirizzo
IP verrà memorizzato per le
volte successive.

Figura 3:
Se l’ hardware è di tipo arm-cortex il debugger tenta
di inviare l’ eseguibile alla periferica.
Se il programma è già in funzione appare un
messaggio di errore e si può uscire dalla funzione di
invio premendo il bottone Exit. In tal caso il debug
funziona correttamente ed è possibile fermarlo
mettendo dei breakpoints.
Figura 4:
Dopo la procedura di avvio, necessaria per programmi Linux e arm-cortex per collegarsi con l’ hardware su
cui gira il programma, appare la videata principale, e il programma effettua automaticamente un
breakpoint all’ inizio del main.
La colonna di destra contiene la lista in ordine alfabetico dei sources del programma.
Cliccando su un elemento della lista viene visualizzata la relativa pagina, su cui possiamo ad esempio
mettere dei breakpoints o leggere il valore delle variabili.
Con un doppio click sulla lista, vengono visualizzati i nomi di tutti i sources usati dal programma, comprese
le librerie di sistema.
dovre

Breakpoints:
Per mettere un breakpoint selezionare con un doppio click la linea del source relativa. Dovrebbe apparire
un punto rosso a sinistra del numero della linea. Se ciò non avviene significa che la linea non contiene
codice eseguibile e quindi non può essere associata ad un breakpoint
Con un nuovo doppio click si disattiva il breakpoint.
La prima colonna in alto di sinistra contiene la lista dei breakpoints (attivi e non), e cliccando con il pulsante
destro del mouse su un elemento della lista, la finestra centrale si sposta sul source del breakpoint.

Figura 5:
Vi sono altri metodi per attivare un breakpoint:
Premendo il bottone Breakpoint (cerchio rosso)
appare una finestra che consente di impostare un
breakpoint su una linea del source attualmente
visualizzato. La finestra consente di imporre delle
condizioni al breakpoint, e di associare una serie di azioni da eseguire all’ occorrenza dello stesso.
La finestra consente inoltre di inserire dei watchpoints, ovvero dei breakpoints non legati all’ esecuzione di
una linea di programma ma al cambiamento del valore di una variabile o alla chiamata di una funzione.
Anche ad un watchpoint può essere associata una serie di azioni da eseguire.

Figura 6:
Un altro metodo per inserire un
breakpoint o un watchpoint è quello
di aprire la console di GDB e
impostare sul pannello superiore il
comando o la serie di comandi gdb da
eseguire, quindi premere Execute.
Le serie di comandi possono essere
salvate e ricaricate all’ occorrenza.
GDB ha un set di oltre 900 tipi di
comandi che possono essere eseguiti
da console. Per una lista completa
consultare il manuale PDF di GDB.

I pannelli di visualizzazione.

6
8

1 2 3

5 6

Figura 7:

1 - Lista dei breakpoints e watchpoints e loro stato di attivazione


2 - Lista del source corrente
3 – Lista dei sources del progetto
4 – Messaggi inviati all’ esecuzione dei breakpoints
5 – Registri della CPU (se disassembler attivato)
6 – Lista del codice assembler (se disassembler attivato)
7 – Lista multipla di visualizzazione dei parametri del programma
8 – Barra dei comandi
1 - Lista dei breakpoints e watchpoints e loro stato di attivazione
Contiene la lista numerata dei breakpoints (BP) e watchpoints (WP) attualmente presenti.
La lista mostra il numero progressivo del breakpoint, lo stato (Y=abilitato, N=sospeso) e il nome del file e il
numero della linea del breakpoint. Cliccando con il tasto destro del mouse su un elemento della lista, viene
mostrato il source del file alla linea del breakpoint, contrassegnata da un punto rosso a sinistra del numero
della linea. Se il breakpoint è condizionato, la lista contiene anche la condizione di attivazione dello stesso.

2 - Lista del source corrente


Mostra il source del file selezionato cliccando sulla lista dei surces (pannello 3).
All’ occorrenza di un breakpoint viene selezionato il source relativo, evidenziando in rosso la riga dell’
occorrenza del bp.
Avanzando con step-in, step-out ecc… a step eseguito la visualizzazione si sposta sulla linea relativa
evidenziata in colore arancio.
Cliccando con il tasto sinistro del mouse sul nome di una variabile contenuta nel source, viene mostrato in
sovraimpressione il valore della variabile, ed il suo nome viene copiato nel campo Search (in alto a destra).
Con i bottoni freccia-avanti e freccia-indietro ai lati del campo Search, la visualizzazione del file corrente si
sposta sulle varie occorrenze del nome della variabile nel source.
Premendo il bottone Search in Files l’ occorrenza del nome della variabile viene cercata in tutti i files della
lista del pannello 3, e la scheda Found del pannello 7 mostra tutte le occorrenze trovate.
Cliccando con il bottone destro del mouse su una di tale occorrenze, il pannello 2 mostra il file relativo,
puntando alla riga dell’ occorrenza.
Con un doppio click su una linea di codice del pannello 2 si crea e si attiva un breakpoint alla riga.
Un successivo doppio click disattiva il breakpoint.
In ogni caso, se un breakpoint viene eseguito su un source non presente nella lista delpannello 3, viene
comunque visualizzato il file relativo (ad esempio all’ inizio per il breakpoint sul main).

3 – Lista dei sources del progetto


Contiene la lista in ordine alfabetico dei nomi dei sources del progetto.
Con un click su un elemento della lista, il pannello 2 mostra il source relativo.
Con un doppio click invece la lista mostra otre ai sources del progetto anche i nomi di tutti i sources delle
librerie e di tutti i files coinvoti nella compilazione.

4 – Messaggi inviati all’ esecuzione dei breakpoints


Se ad un breakpoint è associata una procedura da eseguire (vedi figura 5) il pannello mostra il testo
prodotto da eventuali printf della procedura.

5 – Registri della CPU (visibile solo se disassembler attivato)


Il pannello è visibile solo quando è attivata la modalità disassembly, e mostra i registri della CPU al
momento del breakpoint.

6 – Lista del codice assembler (visibile solo se disassembler attivato)


Il pannello è visibile solo quando è attivata la modalità disassembly, e mostra il codice assembler della riga
di programma corrente (breakpoint o step). Con un doppio click nel pannello, viene mostrato il codice
assembler dell’ intera funzione anziché della sola riga del breakpoint.
Quando è attivato il modo assembler, con step-in si avanza per singola istruzione assembler anziché per
singola istruzione C.

7 – Lista multipla di visualizzazione dei parametri del programma

Questo pannello contiene uno schedario di diversi pannelli di visualizzazione:

1. Messages
2. Variables
3. Backtrace
4. Ram
5. Found
6. Threads
7. Local Vars
8. BreakPoint

Messages
Pannello contenente messaggi generici (non importante)

Variables

Mostra il valore delle variabili aggiunte al pannello con il tasto Add (il nome è quello mostrato nel campo
Search in alto a destra (che viene settato cliccando sul nome di una variabile nel pannello 2).
I valori vengono aggiornati all’ occorrenza di un breakpoint o di uno step.
Solo per ARM-CORTEX si può chiedere un aggiornamento continuo selezionando il flag Refresh.
Nel caso in cui il nome di una variabile sia il nome di una struttura, vengono mostrati i nomi e i valori di tutti
gli elementi della struttura. Per ulteriori dettagli vedere l’ appendice C.

Backtrace

Mostra la lista dei nexting delle chiamate che hanno portato al breakpoint.
L’ elemento 0 è la riga del breakpoint stesso.
La riga 1 e’ la riga della chiamata alla riga 0 ecc…
Cliccando con il tasto destro del mouse su un elemento della lista, il pannello 2 mostra il file relativo (se non
è un file di sistema) puntando alla chiamata della funzione successiva.
Ram

Scrivendo nel campo address un indirizzo (0x + 8 cifre esadecimali) viene mostrato (se accessibile) il
contenuto della memoria a partire dall’ indirizzo specificato.

Found

Mostra tutte le occorrenze, in tutti i files della lista delpannello 3, della stringa del campo Search.
Anche in questo caso, cliccando con il tasto destro del mouse su una linea della lista, il pannello 2 mostra il
file relativo puntando alla linea relativa.

Threads

Mostra la lista di tutti i threads attivi dell’ applicazione, evidenziando con un asterisco quello del breakpont.
Local Vars

Mostra il nome ed il valore di tutte le variabili locali della funzione che ha generato il breakpoint, con il
valore aggiornato al momento del breakpoint (o dello step). Le variabili locali posson essere aggiunte anche
al pannello delle variabili, nel qual caso compaiono nella lista solo quando siamo dentro la funzione in cui
sono definite.

BreakPoint

Mostra il numero del breakpoint attuale e il nome del file e della riga in cui è avvenuto.

8 - La barra dei comandi:

A B C D E F G H I J K L M N O P

A – Chiusura del debug e uscita da programma. I programmi Linux e Windows si chiudono, mentre i programmi ARM-
CORTEX continuano l’ esecuzione

B – Collegamento ethernet/wifi con la periferica. Attivo solo per programmi ARM-CORTEX con Debug lanciato
esternamente da Proteus. Negli altri casi il collegamento è effettuato automaticamente all’ avvio di Windebug.

C – Invio del programma alla periferica. Attivo solo per programmi ARM-CORTEX con Debug lanciato esternamente da
Proteus. Negli altri casi il collegamento è effettuato automaticamente all’ avvio di Windebug.

D – Run/Continue. Lancia il programma all’ inizio o ne riprende l’ esecuzione dopo un breakpoint. È consigliabile di
settare gli opportuni breakpoins prima di utilizzare questa funzione, in quanto quando il programma è in esecuzione la
barra dei comandi è inattiva (salvo il caso ARM-CORTEX).

E – Stop del programma. Attivo per programmi Linux e ARM-CORTEX. Per programmi Windows per arrestare il
programma selezionare con il mouse il programma in esecuzione e premere il tasto Esc.
F – Step-In. Avanza l’ esecuzione del programma eseguendo l’ istruzione C su cui è fermo. Se è selezionata la
visualizzazione del codice assembler il programma vanza di una sola istruzione assembler.

G – Step-Out. Avanza l’ esecuzione del programma fino al raggiungimento della linea di programma successiva. Non
utilizzare questa funzione quando il programma è fermo sull’ ultima linea di una funzione.

H – Step to end. Il programma avanza fino all’ uscita della funzione che sta eseguendo.

I – Step to exit loop. Se il programma si trova in un FOR o in un DO-WHILE il programma avanza fino all’ uscita dal
loop.

J – Apre la finestra di dialogo di costruzione di breakpoints (Figura 5). Questa funzione è utile per settare breakpoints
condizionati o watchpoints. Per settare un semplice breakpoint su una linea di programma è sufficiente un doppio
click con il bottone sinistro del mouse sulla linea di programma.

K – Abilita/disabilita la visualizzazione del codice assembler e dei registri della CPU.

L – Apre la finestra di console GDB (figura 6) , nella quale possiamo eseguire tutti i comandi GDB (vedi appendice A)

N – Search. Scrivendo un nome in questa finestra, con i tasti M ed O il listato del pannelo 2 si ferma sulle varie
occorrenze del nome nel file corrente.Con il tsto P si cercano invece tutte le occorrenze del nome in tutti i files della
lista del pannello 2. Con un click sul pannello 2 sul nome di una variabile o di una funzione tale nome viene copiato
sulla finestra N.
Appendice A: Principali comandi GDB

Dalla console di GDB possiamo impostare ed eseguire tutti i comandi GDB.


Esaminiamo una lista dei principali comandi (per una lista completa consultare il manuale GDB)

- Settare bp
- Vedere bp settati
- Cancellare bp
- Disabilitare bp
- Riabilitare bp
- Settare wp
- Visualizzare wp
- Condizioni per i bp/wp
- Modificare/Aggiungere la condizione
- Cancellare la condizione
- Eseguire lo stop del programma solo dopo m volte che si e’ verificato il bp/wp
- Eseguire comandi in automatico quando si verifica lo stop per un bp
- Continuare l’esecuzione del programma
- Vedere il disassemblato
- Assegnare il valore ad una variabile
- Continuare ad un indirizzo diverso
- Ritornare da una funzione
- Chiamare funzioni
- Stampare il valore di una espressione
- Visualizzare il contenuto delle locazioni di memoria
- Settare una visualizzazione automatica
- Visualizzare le visualizzazioni automatiche settate
- Disabilitare le visualizzazioni automatiche settate
- Riabilitare le visualizzazioni automatiche settate
- Cancellare le visualizzazioni automatiche settate
- Vedere tutti i registri e i loro valori
- Esaminare la symbol-table

Settare bp:
Comando break (abbreviato b)
break nome_funzione
bp sulla funzione (solo se sono presenti le info di debug, o se avete usato labelz ;)
break +offset
break -offset
bp offset linee dopo/prima l’istruzione corrente
break *indirizzo
bp all’istruzione a indirizzo
break (niente)
bp all’istruzione successiva a quella corrente
bp condizionati:
break ... if condizione
stop solo se e’ valutata VERA la condizione
bp particolari:
tbreak ...
come break ma valido solo per uno stop, poi viene cancellato automaticamente
Vedere bp settati:
info breakpoints [n]
visualizza tutti i bp (o il bp numero n se indicato)
Indicazioni visualizzate:
Numero_bp | Tipo (bp/wp) | Disposizioni | Abilitato(y)/Disabilitato(n) | Indirizzo_bp |
Posizione_nel_sorgente

Cancellare bp:
Comando delete (abbreviato d)
delete [n]
cancella tutti i bp (o il bp numero n se indicato)
Comando clear (se si da il comando appena dopo che il programma si e’ appena fermato ad un bp
si
cancella il bp stesso)
clear [nome_funzione]
cancella il bp sulla prossima istruzione (o il bp su nome_funzione se indicato)

Disabilitare bp:
Comando disable (abbreviato dis)
disable [n]
disabilita tutti i bp (o il bp numero n se indicato)

Riabilitare bp:
Comando enable
enable [n]
riabilita tutti i bp (o il bp numero n se indicato)
enable once [n]
riabilita tutti i bp (o il bp numero n se indicato) ma al primo stop viene disabilitato
automaticamente

Settare wp:
Comandi
watch locazione
wp quando il programma scrive su locazione
rwatch locazione
wp quando il programma legge da locazione
awatch locazione
wp quando il programma scrive o legge locazione

Visualizzare wp:
info watchpoints
equivale a "info breakpoints"
Condizioni per i bp/wp:
Osservazioni:
- per i wp la condizione puo’ essere settata solo con il comando "condition"
- devono essere condizioni booleane
- viene fermato il programma solo se la condizione indicata e’ valutata vera
- e’ possibile negare la condizione anteponendo il simbolo ’!’ alla condizione (! not in C)

Modificare/Aggiungere la condizione
condition n condizione
aggiunge condizione al bp/wp numero n

Cancellare la condizione
condition n (niente)
cancella la condizione al bp/wp numero n (in realta’ setta la condizione a niente)

Eseguire lo stop del programma solo dopo m volte che si e’ verificato il bp/wp
ignore n m
setta il bp/wp numero n in modo che generi lo stop del programma solo dopo m volte che si e’
verificato il bp/wp stesso

Eseguire comandi in automatico quando si verifica lo stop per un bp


Comando commands
commands n
lista_comandi
end
imposta la lista dei comandi da eseguire per il bp numero n
Suggerimento: mettere come primo comando "silent" per sopprimere il normale output del bp
es. Stampare il valore della variabile x, settando il bp sulla funzione prova, solo se x e’ >0 e poi
continuare l’esecuzione del programma. I comandi vengono indicati quando viene dichiarato il bp.

break prova if x>0


commands
silent
printf "x vale: %d\n",x
continue
end

Continuare l’esecuzione del programma


Comando continue (abbreviato c o fg)
continue [n]
continua l’esecuzione del programma; se n e’ indicato ignora per n stop l’ultimo bp su cui si e’
fermato

Comando step (abbreviato s)


step [n]
continua l’esecuzione del programma fino alla prossima riga del codice sorgente; ATTENZIONE:
se non si ha a disposizione il sorgente o si e’ in una funzione senza informazioni di debug ritorna
alla funzione chiamante.
Se n e’ indicato esegue n step

Comando stepi (abbreviato si)


stepi [n]
continua l’esecuzione del programma eseguendo ogni singola istruzione macchina
Se n e’ indicato esegue n stepi
Suggerimento: dare il comando "display/i $pc" per visulizzare in modo automatico l’istruzione che
deve
essere eseguita (vedere Visualizzazione automatica)

Comando next (abbreviato n)


next [n]
continua l’esecuzione fino alla prossima istruzione nello stack frame corrente; se l’istruzione e’
una funzione, non entra nella funzione ma la esegue come fosse una singola istruzione
Se n e’ indicato esegue n next

Comando nexti (abbreviato ni)


nexti [n]
continua l’esecuzione fino alla prossima istruzione nello stack frame corrente; se l’istruzione e’
una funzione, entra nella funzione
Se n e’ presente esegue n nexti

Comando finish
finish
continua l’esecuzione del programma fino alla termianzione della funzione corrente e stampa il
valore di ritorno (se c’e’)

Comando until (abbreviato u)


until
continua l’esecuzione del programma fino a quando le istruzioni eseguite hanno indirizzo minore
dell’istruzione sulla quale si da il comando until.
Utile nei cicli con salto all’indietro
until indirizzo
continua l’esecuzione del programma fino a quando viene raggiunta l’istruzione all’indirizzo
"indirizzo"

Vedere il disassemblato
Comando disassemble
disassemble
visualizza il sorgente assembly della funzione in cui si trova l’istruzione corrente
disassemble indirizzo
visualizza il sorgente assembly della funzione in cui si trova l’istruzione a indirizzo
disassemble ind_i ind_f
visualizza il sorgente assembly delle istruzioni dall’indirizzo ind_i (compreso) all’indirizzo ind_f
(escluso)

Alterare l’esecuzione del programma:


Assegnare il valore ad una variabile
Comando set
set nome_var=valore
setta la variabile nome_var a valore
Suggerimento: se il nome di nome_var coincide con un sottocomando di set usare la sintassi "set
var
nome_var=valore"
Se si vuole effettuare il casting di una locazione di memoria
set {tipo_dato}indirizzo=valore
es. Copiare 4 come intero nella locazione 0x83040
set {int}0x83040=4

Continuare ad un indirizzo diverso


Comando jump
jump num_linea
riprende l’esecuzione dalla linea num_linea
jump *indirizzo
riprende l’esecuzione dall’istruzione all’indirizzo indirizzo
Comando set
set $pc=indirizzo
la prossima istruzione sara’ l’istruzione all’indirizzo indirizzo, ma a differenza di jump non
riprende l’esecuzione

Ritornare da una funzione


return [val_ritorno]
cancella l’esecuzione della funzione; se presente ritorna val_ritorno coma valore di ritorno della
funzione

Chiamare funzioni
call nome_funzione
chiama la funzione nome_funzione

Esaminare i dati:
Stampare il valore di una espressione
Comando print (abbreviato p)
print[/f] espressione
visualizza il valore di espressione; se presente /f utilizza il formato indicato
Formati di visualizzazione

 x intero esadecimale
 d intero decimale
 u intero decimale senza segno
 intero ottale
 t intero binario
 a indirizzo
 c carattere
 f virgola mobile

es. Stampare il valore di $pc in esadecimale


print/x $pc

Visualizzare il contenuto delle locazioni di memoria


Comando x
x[/nfu] indirizzo
visualizza il contenuto della locazione di memoria a indirizzo; se presenti utiliza i parametri /nfu
Parametri

 n intero decimale; indica quante unita’ di memoria visualizzare partendo da


indirizzo
 f formato di visualizzazione
 s stringhe null-terminated
 i istruzioni macchina
 u dimensione di una unita’
 b byte
 h mezza word
 w word
 g doppia word

es. Visualizzazione di 3 istruzioni da quella a indirizzo


x/3i indirizzo
Suggerimento: per visualizzare m unita’ successive mantendendo lo stesso formato e’ sufficiente
dare il
comando x/m
es. visualizzare 7 istruzioni macchina dopo aver dato il comando "x/3i"
x/7

Visualizzazione automatica
Settare una visualizzazione automatica
Comando display
display[/f] espressione
visualizza il valore di espressione; se /f e’ presente usa il formato indicato
Formati di visualizzazione

 x intero esadecimale
 d intero decimale
 u intero decimale senza segno
 intero ottale
 t intero binario
 a indirizzo
 c carattere
 f virgola mobile
 i istruzione
 s striga null-terminated

Se il formato e’ i o s
display[/f] indirizzo
visualizza il contenuto della locazionea indirizzo

Visualizzare le visualizzazioni automatiche settate


info display
visualizza tutte le le visualizzazioni automatiche settate
Disabilitare le visualizzazioni automatiche settate
disable display n
disabilita la visualizzazione automatica numero n

Riabilitare le visualizzazioni automatiche settate


enable display n
abilita la visualizzazione automatica numero n

Cancellare le visualizzazioni automatiche settate


delete display n
cancella la visualizzazione automatica numero n

Vedere tutti i registri e i loro valori


info registers
visualizza tutti i registri e i loro valori, esclusi i registri floating point
info all-registers
visualizza tutti i registri e i loro valori, compresi i registri floating point

Esaminare la symbol-table
info address simbolo
visualizza dove e’ memorizzato simbolo
whatis espressione
visualizza il tipo di dato di espressione
ptype nome_tipo
visualizza una descrizione del tipo di dato
ptype espressione
visualizza una descrizione di espressione; piu’ completo di whatis
info source
visualizza il nome del file sorgente attuale
info sources
visualizza tutti i file sorgenti con informazioni di debug
info functions [expr]
visualizza nome e tipo di dati di tutte le funzioni; se e’ presente expr, solo di quelle il cui nome
contiene expr
info variables [expr]
visualizza informazioni su tutte le varibili; se e’ presente expr, solo di quelle il cui nome contiene
expr
Appendice B: GDB su eseguibili ARM-CORTEX

Il debug per programmi ARM-CORTEX presenta alcune differenze rispetto al debug per programmi
Linux o Windows:

- Un breakpoint arresta solo il task in cui avviene.


- In caso di blocco del programma per un errore è possibile vedere la linea di programma che ha
generato l’ errore, il back trace delle chiamate e il valore di tutte le variabili al momento dell’
errore.
- Quando il programma sta girando e non è fermo su un breakpoint è possibile leggere il valore
delle variabili, i threads, la Ram e tutte le altre funzioni.
- Non è possibile creare watchpoints né breakpoints condizionati.
- Non è possibile leggere il valore delle variabili locali.

Per il resto la sessione di breakpoint è uguale per tutte le versioni.


Appendice C: visualizzazione delle variabili
Cliccando sul nome di una variabile, il suo valore viene visualizzato in sovraimpressione sul pannello 2. Se la variabile è
un puntatore, viene visualizzato il valore dell’ oggetto puntato, in quanto il valore del puntatore non indica niente di
utile.

Ad esempio:

int x=100;
int *y=malloc(4);*y=200;

cliccando su x appare il valore 100


cliccando su y appare il valore 200

Se una variabile è definita


come variabile globale e
come variabile locale in
alcune funzioni, il valore
visualizzato sarà quello della
variabile globale quando
siamo fuori da una funzione
che la definisce come locale,
e quello della variabile locale
quando siamo dentro una
funzione che la definisce
come locale.

Le strutture, se contengono
numerosi campi, non
vengono interamente
visualizzate cliccando sul
loro nome.
Per una visualizzazione
completa occorre
aggiungere il loro nome alla
lista delle variabili da
visualizzare.
Se una struttura contiene
altre strutture, se la casella
Next è attivata, appare l’
intero albero della struttura,
altrimenti vengono
visualizzati solo i valori della
struttura principale.
I valori delle variabili possono essere visualizzati sotto forme diverse.
Prendiamo come esempio il seguente programma:

COM *mycom=COM1;
char *pp1=0;
char pp2[40];
short sss[10];
float fff1;
double ddd1;

typedef struct STRUCT1


{
int a1;
char b1[20];
}STRUCT1;

typedef struct STRUCT2


{
int a2;
STRUCT1 s1;
char b2[20];
}STRUCT2;

volatile STRUCT2 s2;


volatile STRUCT2 *s2p=0;

void prova(void)
{
if (pp1==0) pp1=calloc(1,40);
sprintf(pp1,"12345");
sprintf(pp2,"67890");
fff1=3.1415926539;
ddd1=fff1 * 2.;
com_open(mycom,9600);
s2.s1.a1=1;
s2.a2=2;
for (int i=0;i<10;i++)
{
sss[i]=i*100;
lll[i]=i*1000;
}
strcpy(s2.s1.b1,"aaaa");
strcpy(s2.b2,"bbbb");
s2p->s1.a1=3;
s2p->a2=4;
strcpy(s2p->s1.b1,"cccc");
strcpy(s2p->b2,"dddd");
}

Vogliamo visualizzare i valori di pp1,pp2,sss,fff1,ddd1,s2,s2p e mycom.


Aggiungiamo tali variabili al pannello Variables.

La forma più semplice di visualizzazione è:

Se vogliamo visualizzare i valori dei char[] come valori numerici anziché in ascii, selezioniamo View mode=Hex (oppure
=Dec). Notare che in questo modo pp1 (che è un puntatore) visualizza il valore del puntatore anziché il contenuto,
mentre pp2, che è un array di bytes, continua a visualizzare il contenuto.
Se vogliamo visualizzare in forma multi-linea (ad es. se vogliamo vedere l’ intera struttura mycom, che non entra nella
finestra di visualizzazione, selezioniamo Multiline Array.

Volendo vedere nei dettagli anche le strutture di livello superiore di mycom, potremmo selezionare l’ opzione
Recursive structures, che dà una lista dettagliata ma estremamente lunga della variabile mycom:

mycom = {
+ open = 0
+ mode = 0
+ baud = 9600
+ subrx = 0x0
+ subtx = 0x0
+ rx0 = 0
+ rx1 = 0
+ tx0 = 0
+ tx1 = 0
+ rxbuff = 0x0
+ txbuff = 0x0
+ rbuff = 0x0
+ rbufn = 0
+ rbufp = 0
+ rx_sleep = 0
+ or = {
++ Internal = 0
++ InternalHigh = 0
++ {
+++ {
++++ Offset = 0
++++ OffsetHigh = 0}
+++ Pointer = 0x0}
++ hEvent = 0x0}
+ tbuff = 0x0
+ tbufn = 0
+ tbufp = 0
+ tx_sleep = 0
+ ow = {
++ Internal = 0
++ InternalHigh = 0
++ {
+++ {
++++ Offset = 0
++++ OffsetHigh = 0}
+++ Pointer = 0x0}
++ hEvent = 0x0}
+ rxstatus = 0
+ txstatus = 0
+ rxchk = 0
+ txchk = 0
+ rxsize = 0
+ txsize = 0
+ centr = 0
+ perif = 0
+ echo = 0
+ txrun = 0
+ enabled = 0
+ parity = 0
+ stops = 0
+ errors = 0
+ NameCom = "COM1" '0x00'
+ protocol = 0x0
+ hCom = 0xffffffff
+ ctmoNew = {
++ ReadIntervalTimeout = 0
++ ReadTotalTimeoutMultiplier = 0
++ ReadTotalTimeoutConstant = 0
++ WriteTotalTimeoutMultiplier = 0
++ WriteTotalTimeoutConstant = 0}
+ ctmoOld = {
++ ReadIntervalTimeout = 0
++ ReadTotalTimeoutMultiplier = 0
++ ReadTotalTimeoutConstant = 0
++ WriteTotalTimeoutMultiplier = 0
++ WriteTotalTimeoutConstant = 0}
+ dcb = {
++ DCBlength = 0
++ BaudRate = 0
++ fBinary = 0
++ fParity = 0
++ fOutxCtsFlow = 0
++ fOutxDsrFlow = 0
++ fDtrControl = 0
++ fDsrSensitivity = 0
++ fTXContinueOnXoff = 0
++ fOutX = 0
++ fInX = 0
++ fErrorChar = 0
++ fNull = 0
++ fRtsControl = 0
++ fAbortOnError = 0
++ fDummy2 = 0
++ wReserved = 0
++ XonLim = 0
++ XoffLim = 0
++ ByteSize = 0
++ Parity = 0
++ StopBits = 0
++ XonChar = 0
++ XoffChar = 0
++ ErrorChar = 0
++ EofChar = 0
++ EvtChar = 0
++ wReserved1 = 0}}

You might also like