Condividi tramite


Debug in modalità origine

Il debug di un'applicazione è più semplice se è possibile analizzare l'origine del codice anziché i file binari disassemblati.

WinDbg, CDB e KD possono usare il codice sorgente nel debug, se il linguaggio di origine è C, C++o assembly.

Requisiti di compilazione

Per usare il debug di origine, è necessario che il compilatore o il linker crei file di simboli (file con estensione pdb) quando vengono compilati i file binari. Questi file di simboli mostrano al debugger il modo in cui le istruzioni binarie corrispondono alle righe di origine.

Inoltre, il debugger deve essere in grado di accedere ai file di origine effettivi, perché i file di simboli non contengono il testo di origine effettivo.

Se possibile, il compilatore e il linker non devono ottimizzare il codice. Il debug e l'accesso alle variabili locali di origine sono più difficili e talvolta quasi impossibili, se il codice è stato ottimizzato. Se si usa l'utilità Di compilazione come compilatore e linker, impostare la macro MSC_OPTIMIZATION su /Od /Oi per evitare l'ottimizzazione.

Individuazione dei file di simboli e dei file di origine

Per eseguire il debug in modalità di origine, il debugger deve essere in grado di trovare i file di origine e i file di simboli. Per altre informazioni, vedere Percorso di origine.

Inizio del debug dell'origine

Il debugger può visualizzare le informazioni sull'origine ogni volta che contiene simboli e file di origine appropriati per il thread in fase di debug.

Se si avvia una nuova applicazione in modalità utente usando il debugger, l'interruzione iniziale si verifica quando Ntdll.dll carica l'applicazione. Poiché il debugger non ha accesso ai file di origine Ntdll.dll, a questo punto non è possibile accedere alle informazioni di origine per l'applicazione.

Per spostare il contatore del programma all'inizio dell'applicazione, aggiungere un punto di interruzione nel punto di ingresso al file binario. Nella finestra Comando debugger digitare il comando seguente.

bp main
g

L'applicazione viene quindi caricata e arrestata quando viene immessa la funzione main . Naturalmente, è possibile usare qualsiasi punto di ingresso, non solo principale.

Se l'applicazione genera un'eccezione, si interrompe nel debugger. Le informazioni di origine sono disponibili a questo punto. Tuttavia, se si esegue un'interruzione tramite CTRL+C, CTRL+INTERR o Debug | Comando di interruzione, il debugger crea un nuovo thread, quindi non è possibile visualizzare il codice sorgente.

Dopo aver raggiunto un thread per cui si dispone di file di origine, è possibile usare la finestra Comando debugger per eseguire i comandi di debug di origine. Se si usa WinDbg, viene visualizzata la finestra Origine . Se è già stata aperta una finestra Origine facendo clic su Apri file sorgente dal menu File , WinDbg crea in genere una nuova finestra per l'origine. È possibile chiudere la finestra precedente senza influire sul processo di debug.

Debug di origine nell'interfaccia utente grafica di WinDbg

Se si usa WinDbg, viene visualizzata una finestra Origine non appena il contatore del programma si trova nel codice per cui il debugger dispone di informazioni di origine.

WinDbg visualizza una finestra di origine per ogni file di origine aperto o WinDbg. Per altre informazioni sulle proprietà di testo di questa finestra, vedere Source Windows.For more information about the text properties of this window, see Source Windows.

È quindi possibile scorrere l'applicazione o eseguirla in un punto di interruzione o nel cursore. Per altre informazioni sulle istruzioni e sui comandi di traccia, vedere Controllo della destinazione.

Se si è in modalità di origine, la finestra Origine appropriata viene spostata in primo piano durante l'esecuzione dell'applicazione.If you are in source mode, the appropriate Source window moves to the foreground as you step through your application. Poiché sono presenti anche routine di Microsoft Windows chiamate durante l'esecuzione dell'applicazione, il debugger potrebbe spostare una finestra Disassembly in primo piano quando si verifica questo tipo di chiamata (perché il debugger non ha accesso all'origine per queste funzioni). Quando il contatore del programma torna ai file di origine noti, la finestra Origine appropriata diventa attiva.

Durante lo spostamento nell'applicazione, WinDbg evidenzia la posizione nella finestra Origine e nella finestra Disassembly. Vengono evidenziate anche le righe in corrispondenza delle quali vengono impostati punti di interruzione. Il codice sorgente è colorato in base all'analisi del linguaggio. Se è stata selezionata la finestra Origine, è possibile passare il puntatore del mouse su un simbolo per valutarlo. Per altre informazioni su queste funzionalità e su come controllarle, vedere Source Windows.For more information about these features and how to control them, see Source Windows.

Per attivare la modalità di origine in WinDbg, usare il comando l+t , fare clic sulla modalità di origine nel menu di debug oppure fare clic sulla modalità di origine sul pulsante . Quando la modalità di origine è attiva, l'indicatore ASM viene visualizzato non disponibile sulla barra di stato.

È possibile visualizzare o modificare i valori di qualsiasi variabile locale durante l'esecuzione di una funzione in modalità di origine. Per altre informazioni, vedere Lettura e scrittura di memoria.

Debug di origine nella finestra di comando del debugger

Se si usa la rete CDB, non è disponibile una finestra origine separata. Tuttavia, è comunque possibile visualizzare lo stato di avanzamento durante l'esecuzione dell'origine.

Prima di poter eseguire il debug dell'origine in CDB, è necessario caricare i simboli della riga di origine eseguendo il comando .lines (Toggle Source Line Support) o avviando il debugger con l'opzione della riga di comando -lines.

Se si esegue un comando l+t , tutte le istruzioni del programma vengono eseguite una riga di origine alla volta. Usare l-t per eseguire un'istruzione di assembly alla volta. Se si usa WinDbg, questo comando ha lo stesso effetto della selezione o della cancellazione della modalità di origine nel menu Debug o tramite i pulsanti della barra degli strumenti.

Il comando l+s visualizza la riga di origine e il numero di riga correnti al prompt. Se si desidera visualizzare solo il numero di riga, usare l+l .

Se si utilizza l+o e l+s, durante l'esecuzione del programma viene visualizzata solo la riga di origine. Il contatore del programma, il codice disassembly e le informazioni di registrazione sono nascoste. Questo tipo di visualizzazione consente di eseguire rapidamente il codice e visualizzare solo l'origine.

È possibile usare il comando lsp (Set Number of Source Lines) per specificare esattamente il numero di righe di origine visualizzate quando si esegue o si esegue l'applicazione.

La sequenza di comandi seguente è un modo efficace per eseguire un'istruzione all'interno di un file di origine.

.lines        enable source line information
bp main       set initial breakpoint
l+t           stepping will be done by source line
l+s           source lines will be displayed at prompt
g             run program until "main" is entered
pr            execute one source line, and toggle register display off
p             execute one source line 

Poiché INVIO ripete l'ultimo comando, è ora possibile scorrere l'applicazione usando il tasto INVIO. Ogni passaggio determina la visualizzazione della riga di origine, dell'offset di memoria e del codice assembly.

Per altre informazioni su come interpretare la visualizzazione disassembly, vedere Debug in modalità assembly.

Quando viene visualizzato il codice assembly, qualsiasi percorso di memoria a cui si accede viene visualizzato alla fine destra della riga. È possibile usare i comandi d* (Display Memory) e e* (Enter Values) per visualizzare o modificare i valori in queste posizioni.

Se è necessario visualizzare ogni istruzione di assembly per determinare gli offset o le informazioni sulla memoria, usare l-t per istruzioni di assembly invece delle righe di origine. Le informazioni sulla riga di origine possono comunque essere visualizzate. Ogni riga di origine corrisponde a una o più istruzioni di assembly.

Tutti questi comandi sono disponibili in WinDbg e in CDB. È possibile usare i comandi per visualizzare le informazioni della riga di origine dalla finestra di comando debugger di WinDbg anziché dalla finestra Di origine.

Linee di origine e offset

È anche possibile eseguire il debug dell'origine usando l'analizzatore di espressioni per determinare l'offset corrispondente a una riga di origine specifica.

Il comando seguente visualizza un offset di memoria.

? `[[module!]filename][:linenumber]` 

Se si omette il nome file, il debugger cerca il file di origine corrispondente al contatore del programma corrente.

Il debugger legge linenumber come numero decimale, a meno che non si aggiunga 0x prima, indipendentemente dal radix predefinito corrente. Se si omette il numero di riga, l'espressione restituisce l'indirizzo iniziale del file eseguibile corrispondente al file di origine.

Questa sintassi viene riconosciuta in CDB solo se il comando .lines o l'opzione della riga di comando -lines ha caricato i simboli della riga di origine.

Questa tecnica è molto versatile, perché è possibile usarla indipendentemente dalla posizione in cui punta il contatore del programma. Ad esempio, questa tecnica consente di impostare in anticipo i punti di interruzione usando comandi come i seguenti.

bp `source.c:31` 

Per altre informazioni, vedere Sintassi della riga di origine e Uso dei punti di interruzione.

Esecuzione di istruzioni e traccia in modalità origine

Quando si esegue il debug in modalità di origine, possono essere presenti più chiamate di funzione su una singola riga di origine. Non è possibile usare i comandi p e t per separare queste chiamate di funzione.

Ad esempio, nel comando seguente, i passaggi del comando t in GetTickCount e printf, mentre i passaggi del comando p su entrambe le chiamate di funzione.

printf( "%x\n", GetTickCount() );

Se si desidera eseguire alcune chiamate durante l'analisi in altre chiamate, usare .step_filter (Imposta filtro passaggio) per indicare le chiamate da eseguire.

È possibile usare _step_filter per filtrare le funzioni del framework (ad esempio, Microsoft Foundation Classes (MFC) o le chiamate ATL (Active Template Library).