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 [] ad esempio: load /sys/example LOAD /sys/aclock w200 h200 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 (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 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 /sys/example.dbg). Se tale file esiste, questo viene caricato 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 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 Il comando "d", senza parametri mostra la "dump window". In modo analogo funziona il seguente comando per la "code window" u 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 ? 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 r = 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 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 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 - interrompe ad ogni accesso ad ogni byte ad un indirizzo dato bpm w - interrompe alla scrittura di ogni byte ad un indirizzo dato bpmb,bpmw,bpmd - 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 - 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 ". È possibile rimuovere i breakpoint con il comando "bc ", oppure disabilitati momentaneamente con il comando "bd " e riabilitati con "be " 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