2012-12-28 14:24:35 +01:00
|
|
|
Introduzione.
|
|
|
|
|
|
|
|
mtdbg è un debugger per il sistema operativo KolibriOS. Questo documento
|
|
|
|
descrive come utilizzare tale programma. Per eventuali domande conviene
|
|
|
|
scrivere sul forum (in russo, ma esiste anche una sezione inglese)
|
|
|
|
-- board.kolibrios.org.
|
|
|
|
|
|
|
|
Descrizione generica.
|
|
|
|
|
|
|
|
mtdbg è in grado di fare il debug di un solo programma alla volta, se non
|
|
|
|
viene caricato nessun programma, il debug viene disabilitato.
|
|
|
|
|
|
|
|
Il programma è a linea di comando, e accetta in input comandi da tastiera
|
|
|
|
La linea di comando è posizionata in basso, e accetta in input tasti
|
|
|
|
Backspace,Delete,Home,End,frecce sinistra/destra.
|
|
|
|
I comandi non sono case-sensitive e il delimitatore è un numero arbitrario
|
|
|
|
non nullo di spazi.
|
|
|
|
|
|
|
|
Per chiudere il debugger è sufficiente usare il comando "quit" senza
|
|
|
|
nessun argomento, altrimenti da interfaccia cliccando sul pulsante di
|
|
|
|
chiusura come per le altre applicazioni.
|
|
|
|
|
|
|
|
Quando il debugger viene avviato senza argomenti, non viene caricato
|
|
|
|
nessun programma. Se invece viene avviato con degli argomenti, mtdbg
|
|
|
|
cercherà di caricare il programma indicato come primo argomento e con
|
|
|
|
eventuali parametri per il programma passati come argomenti successivi.
|
|
|
|
|
|
|
|
È possibile caricare un qualsiasi programma in un secondo
|
|
|
|
momento con il comando
|
|
|
|
load <percorso all'eseguibile> [<parametri>]
|
|
|
|
ad esempio:
|
2022-01-06 20:34:04 +01:00
|
|
|
load /sys/example
|
|
|
|
LOAD /sys/aclock w200 h200
|
2012-12-28 14:24:35 +01:00
|
|
|
LoaD /hd0/1/menuetos/dosbox/dosbox
|
|
|
|
negli esempi, mtdbg caricherà il programma passato come primo argomenti,
|
|
|
|
un eventuale secondo argomento è il parametro da passare al programma
|
|
|
|
che si vuole caricare.
|
|
|
|
Il comando "load" restituisce in output nel "messages window", poco più
|
|
|
|
in alto della linea di comando, se il programma è stato caricato con
|
|
|
|
successo o meno. In caso di errore, verra mostrata la causa.
|
|
|
|
L'errore più comune è del tipo, "file not found", probabilmente perché
|
|
|
|
si è digitato in modo errato il percorso o il nome del programma da
|
|
|
|
caricare.
|
|
|
|
|
|
|
|
Il debugger è in grado di caricare file con simboli relativi al
|
|
|
|
programma di cui si vuole effetuare il debug.
|
|
|
|
Si tratta di file di testo, dei quali ogni riga inizia con
|
|
|
|
0x<hex_value_of_addr> <name>
|
|
|
|
(righe che non iniziano in questo modo vengono ignorate). Tali file si
|
|
|
|
possono creare a mano o tramite fasm. È possibile caricare questi file
|
|
|
|
esplicitamente con il comando
|
|
|
|
load-symbols <percorso al file>
|
|
|
|
Inoltre, quando viene eseguito il comando "load", mtdbg controllerà
|
|
|
|
la presenza di un file contenente simboli relativi al programma e di
|
|
|
|
estensione .dbg (nel primo esempio controlla la presenza del file
|
2022-01-06 20:34:04 +01:00
|
|
|
/sys/example.dbg). Se tale file esiste, questo viene caricato
|
2012-12-28 14:24:35 +01:00
|
|
|
automaticamente and if such file exists, e verrà notificato tramite il
|
|
|
|
messaggio "Symbols loaded", se il caricamento viene eseguito con
|
|
|
|
successo.
|
|
|
|
|
|
|
|
Può succedere che un programma che si vuole caricare è stato
|
|
|
|
compresso. La compressione funziona, in linea generale, nel
|
|
|
|
seguente modo: il file di input viene compresso (da qualche
|
|
|
|
programma apposito), successivamente viene aggiunto un pezzo di codice
|
|
|
|
che all'avvio del programma effettua una decompressione in memoria.
|
|
|
|
Se un programma è stato compresso, il suo codice non è visibile al
|
|
|
|
debugger, e deve venir prima decompresso.
|
|
|
|
mtdbg è in grado di determinare la maggior parte di compressori
|
|
|
|
(mxp,mxp_lzo,mxp_nrv,mtappack) e in questi casi suggerisce in automatico
|
|
|
|
di effettuare la decompressione per vedere il codice del programma.
|
|
|
|
È sufficiente pigiare 'y' e enter per accettare l'opzione, altrimenti
|
|
|
|
rifiutarla. Se non viene riconosciuto il metodo di compressione, è
|
|
|
|
sempre possibile usare il comando unpack (senza argomenti).
|
|
|
|
Tale comando è da usare solamente se si è sicuro che il programma sia
|
|
|
|
compresso e che non sia già stato decompresso dal debugger.
|
|
|
|
[A partire da Kolibri 0.6.5.0, questo paragrafo non è più attuale poiché
|
|
|
|
è possibile comprimere le applicazioni con kpack e il decompressore è
|
|
|
|
implementato a livello kernel, in modo da rendere il debug trasparente]
|
|
|
|
|
|
|
|
Un programma caricato può essere terminato tramite il comando
|
|
|
|
"terminate" senza argomenti. Il comando "detach", senza parametri
|
|
|
|
aggiuntivi "stacca" il programma dal debugger, nel senso che questo
|
|
|
|
continuerà la sua normale esecuzione senza il debugger, come se questo
|
|
|
|
non vi fosse mai stato.
|
|
|
|
Dato uno di questi due comandi, l'attività di debug viene terminata.
|
|
|
|
|
|
|
|
È possibile ricaricare il programma precedente con il comando "reload",
|
|
|
|
senza parametri. Se nel frattempo è stato caricato un altro programma,
|
|
|
|
questo viene terminato e viene ricaricato il programma precedente con
|
|
|
|
gli argomenti passati precedentemente, come se fossero stati dati i
|
|
|
|
comandi
|
|
|
|
terminate
|
|
|
|
load <vecchio programma> <vecchi parametri>
|
|
|
|
Il vantaggio di reload sta nel fatto di essere più immediato e che viene
|
|
|
|
mantenuto l'indirizzo di memoria, mentre con il comando load questo
|
|
|
|
viene spostato all'indirizzo 0. (vedi sotto)
|
|
|
|
|
|
|
|
Il comando "help", oppure "h", è sempre disponibile.
|
|
|
|
Tutti i comandi sono divisi in gruppi
|
|
|
|
"help" senza argomenti mostra l'elenco dei comandi disponibili
|
|
|
|
"help" con il nome di un gruppo mostra i comandi relativi al gruppo
|
|
|
|
"help" con il nome di un comando mostra informazioni sull'uso di tale
|
|
|
|
comando
|
|
|
|
esempi:
|
|
|
|
help
|
|
|
|
help control
|
|
|
|
h LoaD
|
|
|
|
|
|
|
|
La finestra del debugger è composta dai seguenti elementi enumerati
|
|
|
|
dall'alto al basso:
|
|
|
|
- status string. Se è stato caricato un programma, mostra il suo nome e
|
|
|
|
stato ("Running/Paused"), altrimenti "No program
|
|
|
|
loaded".
|
|
|
|
- registers window - Mostra valori di caratteri generico, valori di
|
|
|
|
registro e stato delle singole flag:
|
|
|
|
CF,PF,AF,ZF,SF,DF,OF: se una flag viene rimossa,
|
|
|
|
allora è contrassegnata da lettere minuscole, se
|
|
|
|
creata allora da lettere maiuscole. I valori di
|
|
|
|
registro che vengono modificati sono contrassegnati
|
|
|
|
in verde.
|
|
|
|
- data window (dump window) - mostra la porzione di memoria contenente
|
|
|
|
il programma caricato
|
|
|
|
- code window (disassembler window) - mostra il codice del programma come
|
|
|
|
"disassembled instructions"
|
|
|
|
- messages window
|
|
|
|
- command line window
|
|
|
|
|
|
|
|
Nella "Dump window" è possibile osservare i dati a partire da ogni
|
|
|
|
indirizzo, usare il comando
|
|
|
|
d <espressione>
|
|
|
|
Il comando "d", senza parametri mostra la "dump window".
|
|
|
|
In modo analogo funziona il seguente comando per la "code window"
|
|
|
|
u <espressione>
|
|
|
|
oppure "u".
|
|
|
|
Esempi:
|
|
|
|
d esi - mostra i dati all'indirizzo esi (e.g. utile prima di eseguire
|
|
|
|
una istruzione rep movsb)
|
|
|
|
d esp - mostra lo stack
|
|
|
|
u eip - disassembla le istruzioni a partire dall'attuale indirizzo
|
|
|
|
|
|
|
|
Le espressioni in mtdbg possono includere
|
|
|
|
- costanti esadecimali
|
|
|
|
- nomi generici dei registri degli indirizzi (8 32-bits, 8 16-bits e
|
|
|
|
8 8-bits) e registri eip; valori di 16- e 8-bits sono riempiti nel
|
|
|
|
registro di 0 fino a raggiungere i 32 bit.
|
|
|
|
- quattro operatori aritmetici +,-,*,/ (con le priorità standard) e le
|
|
|
|
parentesi
|
|
|
|
- [se sono stati caricati i simboli del programma] nomi, caricati dal
|
|
|
|
file dbg
|
|
|
|
Tutti i calcoli sono effettuati modulo 2^32.
|
|
|
|
Esempi di espressioni:
|
|
|
|
eax
|
|
|
|
eip+2
|
|
|
|
ecx-esi-1F
|
|
|
|
al+AH*bl
|
|
|
|
ax + 2* bH*(eip+a73)
|
|
|
|
3*esi*di/EAX
|
|
|
|
Il comando
|
|
|
|
? <espressione>
|
|
|
|
calcola il valore della espressione passata come argomento.
|
|
|
|
|
|
|
|
I valori del registro caricato nel programma può essere modificato con
|
|
|
|
il comando "r" in uno dei seguenti modi (sono equivalenti)
|
|
|
|
r <registro> <espressione>
|
|
|
|
r <registro>=<espressione>
|
|
|
|
|
|
|
|
Supponendo che sia stato caricato un programma con successo per il
|
|
|
|
debug, subito dopo il programma verrà sospeso e non più eseguito.
|
|
|
|
Premendo Ctrl+F7 (oppure dalla linea di comando "s") è possibile far
|
|
|
|
effettuare una azione al programma, dopodiché questo verrà sospeso
|
|
|
|
immediatamente, e il debugger mostrerà i nuovi valori nel registro e in
|
|
|
|
memoria.
|
|
|
|
la chiamata di sistema "int 40h" è considerata una azione.
|
|
|
|
Premendo Ctrl+F8 (oppure dalla linea di comando "p") permette di
|
|
|
|
eseguire il programma, e chiamate a procedure esterne, cicli e altre
|
|
|
|
strutture di controllo oppure operazioni con prefisso rep/repz/repnz
|
|
|
|
verranno interpretate come una singola azione.
|
|
|
|
Solitamente si chiede di eseguire azioni singole su sezioni di
|
|
|
|
programmi, ad esempio per tenere traccia dei valori in memoria e nel
|
|
|
|
registro.
|
|
|
|
Il comando
|
|
|
|
g <espressione>
|
|
|
|
riprende l'esecuzione del programma e attende che il controllo vada a
|
|
|
|
eip=indirizzo dato, e in quel momento sospende il programma.
|
|
|
|
Se il comando "g" viene dato senza argomenti, viene semplicemente
|
|
|
|
ripresa l'esecuzione del programma.
|
|
|
|
|
|
|
|
Per sospendere l'esecuzione del programma è sufficiente usare il comando
|
|
|
|
"stop", senza parametri o argomenti.
|
|
|
|
|
|
|
|
In una situazione standard il programma viene eseguito normalmente,
|
|
|
|
quando sono soddisfatte alcune condizioni, il programma viene sospeso e
|
|
|
|
invia un segnale al debugger. Tali condizioni sono chiamate
|
|
|
|
"breakpoints" o "breaks".
|
|
|
|
L'utilizzo principale dei breakpoints è quello di interrompere
|
|
|
|
l'esecuzione del programma in determinati punti. I breakpoint si
|
|
|
|
impostano con il comando
|
|
|
|
bp <espressione>
|
|
|
|
Si noti che se è presente un solo breakpoint, allora è più conveniente
|
|
|
|
usare il comando "g" con parametri.
|
|
|
|
|
|
|
|
Vi sono altri tipi di breakpoint che permettono di accedera ad una data
|
|
|
|
area di memoria. Il numero massimo di breakpoint di questo tipo sono 4,
|
|
|
|
causa limitazioni hardware.
|
|
|
|
bpm <espressione> - interrompe ad ogni accesso ad ogni byte ad un
|
|
|
|
indirizzo dato
|
|
|
|
bpm w <espressione> - interrompe alla scrittura di ogni byte ad un
|
|
|
|
indirizzo dato
|
|
|
|
bpmb,bpmw,bpmd <espressione> - interrompe all'accesso di ogni byte, o
|
|
|
|
dword all'indirizzo dato. bpm e bpmb sono
|
|
|
|
sinonimi. Quando viene usato bpmw o bpmd,
|
|
|
|
gli indirizzi devono essere del tipo
|
|
|
|
corrispondenti al tipo di dato, quindi
|
|
|
|
per i word è dispari, per i dword è
|
|
|
|
divisibile per 4.
|
|
|
|
bpmb,bpmw,bpmd w <espressione> - simile al break in scrittura.
|
|
|
|
|
|
|
|
Per vedere la lista dei breakpoints impostati, usare il comando "bl",
|
|
|
|
per ottenere informazioni su un particolare breakpoint, usare il
|
|
|
|
comando "bl <numero>".
|
|
|
|
È possibile rimuovere i breakpoint con il comando "bc <numero>", oppure
|
|
|
|
disabilitati momentaneamente con il comando "bd <numero>" e riabilitati
|
|
|
|
con "be <numero>"
|
|
|
|
|
|
|
|
Note.
|
|
|
|
1. Quando si effettua il debug di un proprio programma, è possibile
|
|
|
|
mettere nel codice istruzione int3. Queste istruzioni creano delle
|
|
|
|
eccezioni durante la normale esecuzione, che porta alla terminazione
|
|
|
|
del programma, ma durante l'attività di debug permette di non dover
|
|
|
|
pensare agli indirizzi di memoria da usare nei comandi g e bp.
|
|
|
|
2. La notazione standard per l'output e input è quella esadecimale.
|
|
|
|
3. Quando il programma viene eseguito, la finestra del registro e dei
|
|
|
|
dati mostrano delle informazioni prima dell'avvio. Non si possono
|
|
|
|
impostare i valori di registro in questo mode. Tuttavia il
|
|
|
|
comando "d" in questo modo mostra informazioni che erano vere nel
|
|
|
|
momento in cui si è immesso il comando.
|
|
|
|
|
|
|
|
diamond
|