Utilizzo dei debugger

Questa pagina descrive in dettaglio l'utilizzo di LLDB o GDB per lo sviluppo del sistema operativo. Per lo sviluppo di app, vedi Debug della tua app , che spiega come usare la GUI di Android Studio (basata su LLDB).

GDB è deprecato e verrà presto rimosso. Se stai passando da GDB a LLDB, probabilmente dovresti iniziare leggendo il Tutorial LLDB . Se sei un utente esperto di GDB, la mappa dei comandi da GDB a LLDB è molto utile durante la transizione.

Prerequisiti

Per utilizzare un debugger:

  • Imposta l'ambiente di compilazione con il solito comando envsetup.sh .
  • Esegui lo stesso comando lunch che hai usato durante la costruzione. Tieni presente che l'elemento del pranzo deve corrispondere esattamente al dispositivo di cui stai eseguendo il debug. Se l'articolo del pranzo non corrisponde al dispositivo collegato, riceverai un errore del tipo: You used the wrong lunch: TARGET_PRODUCT (aosp_arm64) does not match attached device (xyzabc)
  • Collega il tuo dispositivo alla macchina.

Per ulteriori informazioni sulla configurazione dell'ambiente, consulta Configurare l'ambiente .

Debug di un binario

Per eseguire il debug di un binario che hai creato sulla tua macchina, devi prima copiare il binario sul dispositivo e quindi avviare il debugger. Per esempio:

adb push test.exe /data/local/tmp/test.exe
gdbclient.py --port 5038 -r /data/local/tmp/test.exe

Debug di app o processi in esecuzione

Per connetterti a un'app in esecuzione o a un demone nativo, usa gdbclient.py con un PID. Ad esempio, per eseguire il debug del processo con PID 1234, esegui questo sull'host:

gdbclient.py -p 1234

Lo script imposta il port forwarding, avvia lo stub di debug remoto appropriato sul dispositivo, avvia il debugger sull'host, lo configura per trovare i simboli e lo connette allo stub di debug remoto.

Debug dell'avvio del processo nativo

Per eseguire il debug di un processo all'avvio, usa gdbclient.py con l'opzione -r . Ad esempio, per eseguire il debug ls /bin , esegui questo sull'host:

gdbclient.py -r /system/bin/ls /bin

Quindi, immetti continue al prompt del debugger.

Debug dell'avvio dell'app

A volte si desidera eseguire il debug di un'app all'avvio, ad esempio quando si verifica un arresto anomalo e si desidera eseguire il codice per vedere cosa è successo prima dell'arresto anomalo. L'allegato funziona in alcuni casi, ma in altri casi è impossibile perché l'app si arresta in modo anomalo prima che tu possa allegare. L'approccio logwrapper (utilizzato per strace ) non funziona sempre perché l'app potrebbe non disporre delle autorizzazioni per aprire una porta e gdbserver eredita tale restrizione.

Per eseguire il debug dell'avvio dell'app, utilizza le opzioni sviluppatore in Impostazioni per indicare all'app di attendere il collegamento di un debugger Java:

  1. Vai a Impostazioni > Opzioni sviluppatore > Seleziona app di debug e scegli la tua app dall'elenco, quindi fai clic su Attendi debugger .
  2. Avvia l'app, dall'utilità di avvio o utilizzando la riga di comando per eseguire:
    adb shell am start -a android.intent.action.MAIN -n APP_NAME/.APP_ACTIVITY
    
  3. Attendi il caricamento dell'app e la visualizzazione di una finestra di dialogo che ti informa che l'app è in attesa di un debugger.
  4. Collega gdbserver / gdbclient normalmente, imposta i punti di interruzione, quindi continua il processo.

Per consentire l'esecuzione dell'app, collega un debugger JDWP (Java Debug Wire Protocol) come Java Debugger (jdb):

adb forward tcp:12345 jdwp:XXX  # (Where XXX is the PID
of the debugged process.)
jdb -attach localhost:12345

Debug di app o processi che si arrestano in modo anomalo

Se vuoi che debuggerd sospenda i processi in crash in modo da poter collegare un debugger, imposta la proprietà appropriata:

  • Dopo Android 11
    adb shell setprop debug.debuggerd.wait_for_debugger true
    
  • Android 11 e versioni precedenti
    adb shell setprop debug.debuggerd.wait_for_gdb true
    
  • Android 6.0 Marshmallow e inferiore
    adb shell setprop debug.db.uid 999999
    

Alla fine del consueto output del crash, debuggerd fornisce istruzioni di copia e incolla in logcat che mostrano come connettere il debugger al processo in crash.

Debug senza simboli

Per ARM a 32 bit, se non si dispone di simboli, gdb non è in grado di determinare quale set di istruzioni sta disassemblando (ARM o Thumb). Per specificare il set di istruzioni scelto come predefinito quando mancano le informazioni sui simboli, impostare la seguente proprietà:

set arm fallback-mode arm  # or thumb

Debug con VS Code

LLDB supporta il debug del codice della piattaforma in Visual Studio Code . Puoi utilizzare il front-end del debugger VS Code invece dell'interfaccia CLI LLDB per controllare ed eseguire il debug del codice nativo in esecuzione sui dispositivi.

Prima di utilizzare VS Code per il debug, installa l' estensione CodeLLDB .

Per eseguire il debug del codice utilizzando VS Code:

  1. Assicurarsi che siano presenti tutti gli artefatti di compilazione (come i simboli) richiesti per eseguire gdbclient.py o lldbclient.py .
  2. In VS Code premere Ctrl+Maiusc+P per eseguire un comando, cercare Debug: Add Configuration... , quindi selezionare LLDB . Questo apre un file launch.json e aggiunge un nuovo oggetto JSON a un elenco.
  3. Sostituisci la configurazione del debugger appena aggiunta con due righe di commento - // #lldbclient-generated-begin e // #lldbclient-generated-end , in modo che l'elenco delle configurazioni sia simile al seguente:
    "configurations": [
        // #lldbclient-generated-begin
        // #lldbclient-generated-end
    ]

    lldbclient.py utilizza questi commenti per rilevare dove scrivere la configurazione. Se ci sono altri elementi nell'elenco, aggiungi le righe di commento alla fine dopo le altre configurazioni.

  4. Esegui il seguente comando nel terminale in cui hai eseguito envsetup.sh e lunch :
    lldbclient.py --setup-forwarding vscode-lldb \
          --vscode-launch-file LAUNCH_JSON_PATH \
          ANY_OTHER_FLAGS -p pid | -n proc-name | -r ...

    lldbclient.py scrive la configurazione generata in launch.json e continua a funzionare. Questo è previsto; non uccidere il programma lldbclient.py . Se ometti --vscode-launch-file lo script stamperà lo snippet JSON che dovrai copiare e incollare manualmente in launch.json .

    Il flag -r deve essere l'ultimo flag se è presente a causa del modo in cui i flag vengono analizzati dallo strumento.

  5. Apri la barra laterale Esegui e esegui debug : la nuova configurazione dovrebbe apparire nell'elenco del debugger. Premere Avvia debug (F5) . Il debugger dovrebbe connettersi dopo 10-30 secondi.

    Se la nuova configurazione non è stata visualizzata nella vista Esegui e debug, ricarica la finestra per aggiornare l'elenco del debugger: premi Ctrl+Maiusc+P e digita reload window .

  6. Al termine del debug, vai al terminale che esegue lldbclient.py e premi Invio per terminare il programma lldbclient.py . Le esecuzioni successive dello script genererebbero la configurazione tra i commenti #lldbclient-generated e sostituirebbero i vecchi contenuti, non è necessario rimuoverli manualmente.

Per aggiungere proprietà personalizzate alla configurazione di avvio generata, puoi utilizzare il flag --vscode-launch-props . Ad esempio:

lldbclient.py --setup-forwarding vscode-lldb \
    --vscode-launch-props \
    '{"initCommands" : ["script print(\"Hello\")"], "preLaunchTask" : "Build"}' \
    ...
Le proprietà di esempio fanno in modo che VS Code esegua un'attività denominata Build prima del debug e aggiunga un nuovo passaggio di inizializzazione del debug ai passaggi generati dallo script. È possibile trovare una panoramica delle proprietà disponibili nella documentazione di VS Code e nel Manuale dell'utente dell'estensione CodeLLDB .