Debug firmware avr con simavr e avr-gdb

Condividi:

Gli strumenti che utilizzerò per il debug del firmware sono simavr e avr-gdb. simavr è un emulatore modulare di mcu che permette anche collegare virtualmente alla mcu dell’hardware supplementare come pulsanti ecc. E’ possibile iniettare segnali, alterare lo stato dei pin e loggare su file .vcd lo stato dei registri interni. In questo articolo utilizzeremo simavr solo come simulatore. avr-gdb è il debugger gcc che utilizzeremo per l’esecuzione del firmware e per ispezionare i dati che ci interessano durante il debug.

Installazione di avr-gcc

Nel caso non fosse già stato installato

Installazione di simavr

Scarichiamo i sorgenti dal repo git

Per la compilazione dei sorgenti avremo bisogno di alcune librerie

Ora compiliamo

Firmware di esempio

Compiliamo questo semplice firmware con le opzioni per l’Atmega328p. Per prima cosa compileremo il listato per ottenere il sorgente da assemblare, inseriremo il primo break ed compileremo il file .elf da eseguire in emulazione. Analizzeremo le informazioni che ci interessano dopodichè sposteremo il break, ricompileremo e rieseguiremo il firmware analizzando i registri che sono stati moficati dalle istruzioni che prima non erano state eseguite.

Otteniamo il listato assembler da editare

Inseriamo un comando break all’interno del codice, prima dell’ incremento della variabile all’interno del ciclo while identificato dalla label .L2
In questo listato notiamo che la variabile c di tipo char viene indirizzata dal valore del registro Y incrementato di 1. Viene copiata nel registro r24, a cui viene sottratto -1 e poi il valore del registro viene ricopiato all’indirizzo puntato dal registro Y incrementato di 1.

Ora compiliamo il file elf

In una console avviamo simavr

In un’altra console avviamo avr-gdb

avr-gdb ci avvisa che non ha trovato simboli per il debug, ed è corretto perchè abbiamo compilato senza l’opzione -ggdb. Infondo non ci interessa il codice C in questo momento.
Da avr-gdb colleghiamoci al processo simavr

I comandi che utilizzeremo in avr-gbd sono

  • disassemble
  • x/xb
  • info reg
  • continue
  • next

Ci troviamo all’indirizzo 0x00, dove si trova il RESET interrupt vector. Avviamo l’esecuzione con continue che si fermerà in corrispondenza del comando break

Il programma si è fermato sulla break che abbiamo inserito

Analizziamo lo stato dei registri

Osserviamo che il registro r24 contiene il valore 0, lo Stack Pointer ed il registro Y ( formato da r28 ed r29 ) puntano all’indirizzo 0x800fa  che rappresenta la base della memoria delle variabili locali della funzione main. Visualizziamo il contenuto degli indirizzi puntatu da Y e da Y+1

Ora usciamo da simavr ed editiamo il file main.s spostando la break dopo l’istruzione subi

Ricompiliamo il main.elf

Riavviamo simavr

E nell’altra console ricolleghiamoci a simavr

Eseguiamo il programma

Disassembliamo

E visualizziamo lo stato dei registri

Notiamo che il registro r24 ora contiene un uno.

Il valore degli indirizzi puntati da Y ed Y+1 è ancora lo stesso

Ripetiamo gli ultimi passaggi spostando la break dopo std, ricompiliamo, rieseguiamo simavr e ricolleghiamoci da avr-gdb. Dopo aver impartito i comandi continue e disassemble dovremo trovarci qui

Lo stato de dei registri non è cambiato

Invece il valore che è contenuto in r24 è stato copiato nella nostra variabile locale c rappresentata da Y+1

Il valore di 0x8008fb quindi è stato incrementato di 1