Korzystanie z debugerów

Ta strona zawiera szczegółowe informacje na temat korzystania z LLDB lub GDB do tworzenia systemów operacyjnych. Aby uzyskać informacje na temat tworzenia aplikacji, zobacz Debugowanie aplikacji , w którym wyjaśniono, jak używać interfejsu GUI Android Studio (opartego na LLDB).

GDB jest przestarzałe i wkrótce zostanie usunięte. Jeśli przechodzisz z GDB na LLDB, prawdopodobnie powinieneś zacząć od przeczytania samouczka LLDB . Jeśli jesteś doświadczonym użytkownikiem GDB, mapa poleceń GDB do LLDB jest bardzo pomocna podczas przechodzenia.

Wymagania wstępne

Aby użyć debugera:

  • Skonfiguruj środowisko kompilacji za pomocą zwykłego polecenia envsetup.sh .
  • Uruchom to samo polecenie lunch , którego użyłeś podczas budowania. Pamiętaj, że element lunchu powinien dokładnie pasować do debugowanego urządzenia. Jeśli element lunchu nie pasuje do podłączonego urządzenia, pojawi się błąd w postaci: You used the wrong lunch: TARGET_PRODUCT (aosp_arm64) does not match attached device (xyzabc)
  • Podłącz swoje urządzenie do maszyny.

Aby uzyskać dodatkową pomoc dotyczącą konfigurowania środowiska, zobacz Konfigurowanie środowiska .

Debugowanie pliku binarnego

Aby debugować plik binarny, który zbudowałeś na swoim komputerze, najpierw musisz skopiować plik binarny na urządzenie, a następnie uruchomić debuger. Na przykład:

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

Debugowanie uruchomionych aplikacji lub procesów

Aby połączyć się z uruchomioną aplikacją lub natywnym demonem, użyj gdbclient.py z identyfikatorem PID. Na przykład, aby debugować proces z PID 1234, uruchom to na hoście:

gdbclient.py -p 1234

Skrypt konfiguruje przekierowanie portów, uruchamia odpowiedni kod pośredniczący zdalnego debugowania na urządzeniu, uruchamia debuger na hoście, konfiguruje go do znajdowania symboli i łączy go ze kodem pośredniczącym zdalnego debugowania.

Debugowanie natywnego uruchamiania procesu

Aby debugować proces podczas jego uruchamiania, użyj gdbclient.py z opcją -r . Na przykład, aby debugować ls /bin , uruchom to na hoście:

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

Następnie wpisz continue w monicie debugera.

Debugowanie uruchamiania aplikacji

Czasami chcesz debugować aplikację podczas jej uruchamiania, na przykład w przypadku awarii i chcesz przejść przez kod, aby zobaczyć, co się stało przed awarią. Dołączanie działa w niektórych przypadkach, ale w innych jest niemożliwe, ponieważ aplikacja ulega awarii, zanim będzie można dołączyć. Podejście logwrapper (używane dla strace ) nie zawsze działa, ponieważ aplikacja może nie mieć uprawnień do otwierania portu, a gdbserver dziedziczy to ograniczenie.

Aby debugować uruchamianie aplikacji, użyj opcji programisty w Ustawieniach, aby poinstruować aplikację, aby czekała na podłączenie debugera Java:

  1. Przejdź do opcji Ustawienia > Opcje programisty > Wybierz aplikację do debugowania i wybierz swoją aplikację z listy, a następnie kliknij opcję Czekaj na debuger .
  2. Uruchom aplikację z programu uruchamiającego lub za pomocą wiersza poleceń, aby uruchomić:
    adb shell am start -a android.intent.action.MAIN -n APP_NAME/.APP_ACTIVITY
    
  3. Poczekaj, aż aplikacja się załaduje i pojawi się okno dialogowe z informacją, że aplikacja czeka na debuger.
  4. Podłącz normalnie gdbserver / gdbclient , ustaw punkty przerwania, a następnie kontynuuj proces.

Aby aplikacja mogła działać, dołącz debuger Java Debug Wire Protocol (JDWP), taki jak Java Debugger (jdb):

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

Debugowanie aplikacji lub procesów, które ulegają awarii

Jeśli chcesz, aby debuggerd zawiesił zawieszone procesy, aby można było dołączyć debugger, ustaw odpowiednią właściwość:

  • Po Androidzie 11
    adb shell setprop debug.debuggerd.wait_for_debugger true
    
  • Android 11 i niższy
    adb shell setprop debug.debuggerd.wait_for_gdb true
    
  • Android 6.0 Marshmallow i niższy
    adb shell setprop debug.db.uid 999999
    

Na końcu zwykłego wyjścia awarii debuggerd udostępnia instrukcje kopiowania i wklejania w logcat, pokazujące, jak połączyć debugger z procesem, który uległ awarii.

Debugowanie bez symboli

W przypadku 32-bitowego ARM, jeśli nie masz symboli, gdb nie może określić, który zestaw instrukcji jest dezasemblowany (ARM lub Thumb). Aby określić zestaw instrukcji wybrany jako domyślny, gdy brakuje informacji o symbolu, ustaw następującą właściwość:

set arm fallback-mode arm  # or thumb

Debugowanie za pomocą VS Code

LLDB obsługuje debugowanie kodu platformy w Visual Studio Code . Możesz użyć interfejsu debugera VS Code zamiast interfejsu LLDB CLI do kontrolowania i debugowania kodu natywnego działającego na urządzeniach.

Przed użyciem VS Code do debugowania zainstaluj rozszerzenie CodeLLDB .

Aby debugować kod za pomocą VS Code:

  1. Upewnij się, że obecne są wszystkie artefakty kompilacji (takie jak symbole) wymagane do uruchomienia gdbclient.py lub lldbclient.py .
  2. W programie VS Code naciśnij klawisze Ctrl+Shift+P , aby uruchomić polecenie, wyszukaj Debug: Add Configuration... , a następnie wybierz pozycję LLDB . Spowoduje to otwarcie pliku launch.json i dodanie nowego obiektu JSON do listy.
  3. Zastąp nowo dodaną konfigurację debuggera dwiema liniami komentarza — // #lldbclient-generated-begin i // #lldbclient-generated-end , aby lista konfiguracji wyglądała następująco:
    "configurations": [
        // #lldbclient-generated-begin
        // #lldbclient-generated-end
    ]

    lldbclient.py używa tych komentarzy do wykrycia, gdzie zapisać konfigurację. Jeśli na liście znajdują się inne pozycje, dodaj wiersze komentarza na końcu po innych konfiguracjach.

  4. Uruchom następujące polecenie w terminalu, w którym uruchomiłeś envsetup.sh i lunch :
    lldbclient.py --setup-forwarding vscode-lldb \
          --vscode-launch-file LAUNCH_JSON_PATH \
          ANY_OTHER_FLAGS -p pid | -n proc-name | -r ...

    lldbclient.py zapisuje wygenerowaną konfigurację do launch.json i kontynuuje działanie. To jest oczekiwane; nie zabijaj programu lldbclient.py . Jeśli pominiesz plik --vscode-launch-file skrypt wydrukuje fragment kodu JSON, który musisz ręcznie skopiować i wkleić do launch.json .

    Flaga -r musi być ostatnią flagą, jeśli jest obecna ze względu na sposób analizowania flag przez narzędzie.

  5. Otwórz pasek boczny Uruchom i debuguj — nowa konfiguracja powinna pojawić się na liście debugera. Naciśnij Rozpocznij debugowanie (F5) . Debuger powinien połączyć się po 10 do 30 sekundach.

    Jeśli nowa konfiguracja nie pojawiła się w widoku Uruchom i debuguj, ponownie załaduj okno, aby odświeżyć listę debuggera — naciśnij klawisze Ctrl+Shift+P i wpisz reload window .

  6. Po zakończeniu debugowania przejdź do terminala z uruchomionym lldbclient.py i naciśnij klawisz Enter , aby zakończyć działanie programu lldbclient.py . Kolejne uruchomienia skryptu wygenerują konfigurację między komentarzami #lldbclient-generated i zastąpią starą zawartość, nie trzeba ich usuwać ręcznie.

Aby dodać niestandardowe właściwości do wygenerowanej konfiguracji uruchamiania, możesz użyć flagi --vscode-launch-props . Na przykład:

lldbclient.py --setup-forwarding vscode-lldb \
    --vscode-launch-props \
    '{"initCommands" : ["script print(\"Hello\")"], "preLaunchTask" : "Build"}' \
    ...
Przykładowe właściwości spowodują, że VS Code uruchomi zadanie o nazwie Build przed debugowaniem i dołączy nowy krok inicjalizacji debugowania do kroków generowanych przez skrypt. Przegląd dostępnych właściwości można znaleźć w dokumentacji VS Code oraz w Podręczniku użytkownika rozszerzenia CodeLLDB .