Przy debugowaniu i profilowaniu aplikacji za pomocą kodu natywnego często przydaje się użycie oraz narzędzia do debugowania, które muszą być włączone podczas uruchamiania procesu. Wymaga to wykonania tych czynności: uruchamiasz aplikację w nowym procesie, zamiast klonować wersję zygote. Przykłady:
- Śledzenie wywołań systemowych za pomocą strace.
- Znajdowanie błędów pamięci za pomocą debugowanie malloc lub Adres Sanitizer (ASan).
- Profiluję za pomocą Simpleperf.
Używanie skryptu zawijania powłoki
Korzystanie z wrap.sh
jest proste:
- Skompiluj niestandardowy plik APK możliwy do debugowania, który zawiera następujące elementy:
- Skrypt powłoki o nazwie
wrap.sh
. Zobacz Utwórz skrypt opakowujący powłokę oraz Więcej informacji znajdziesz w pliku Package wrap.sh. - Dodatkowe narzędzia potrzebne skryptowi powłoki (np. własny plik binarny
strace
).
- Skrypt powłoki o nazwie
- Zainstaluj na urządzeniu plik APK możliwy do debugowania.
- Uruchom aplikację.
Tworzenie skryptu opakowań powłoki
Gdy uruchomisz możliwy do debugowania plik APK, który zawiera wrap.sh
, system uruchomi
w skrypcie i przekazuje polecenie uruchomienia aplikacji jako argumenty. Skrypt jest
odpowiada za uruchomienie aplikacji, ale może sprawić, że środowisko lub argument
zmian. Skrypt powinien następować
Składnia MirBSD Korn (mksh).
Ten fragment kodu pokazuje, jak napisać prosty plik wrap.sh
, który po prostu
uruchamia aplikację:
#!/system/bin/sh exec "$@"
Debugowanie Malloc
Aby użyć funkcji
debugowanie malloc
przez wrap.sh
, wpisz ten wiersz:
#!/system/bin/sh LIBC_DEBUG_MALLOC_OPTIONS=backtrace logwrapper "$@"
ASan
W ASan znajdziesz przykład Dokumentacja ASan.
Pakiet wrap.sh
Aby można było używać funkcji wrap.sh
, plik APK musi umożliwiać debugowanie. Upewnij się, że
android:debuggable="true"
jest skonfigurowane w
<application>
.
w pliku manifestu Androida, a jeśli używasz Androida Studio,
masz skonfigurowaną kompilację do debugowania w
build.gradle
.
Musisz też ustawić useLegacyPackaging
do true
w pliku build.gradle
aplikacji. W większości przypadków ta opcja jest ustawiona
Wartość domyślna to false
, więc możesz ustawić jawną wartość true
jako
uniknąć niespodzianek.
Musisz spakować skrypt wrap.sh
z natywnymi bibliotekami aplikacji. Jeśli
aplikacja nie zawiera bibliotek natywnych, ręcznie dodaj katalog lib do
katalogu projektu. W przypadku każdej architektury, którą obsługuje aplikacja, musisz określić,
udostępnić kopię skryptu powłoki
w tym katalogu biblioteki natywnej.
Poniższy przykład pokazuje układ pliku umożliwiający obsługę procesorów ARMv8 i x86-64. architektury:
# App Directory |- AndroidManifest.xml |- … |- lib |- arm64-v8a |- ... |- wrap.sh |- x86_64 |- ... |- wrap.sh
Android Studio pakuje tylko pliki .so
z katalogów lib/
, więc jeśli
Korzystasz z Android Studio, musisz umieścić pliki wrap.sh
w
src/main/resources/lib/*
, tak aby zostały one spakowane
.
Pamiętaj, że resources/lib/x86
będzie wyświetlany w interfejsie jako
lib.x86
, a w rzeczywistości to podkatalog:
Debuguj z użyciem pliku wrap.sh
Jeśli podczas korzystania z narzędzia wrap.sh
chcesz dołączyć debuger, skrypt powłoki
ręcznie włączyć debugowanie. Jak to wyglądało w różnych wersjach,
W tym przykładzie pokazujemy, jak dodać odpowiednie opcje do wszystkich wersji, które
pomoc wrap.sh
:
#!/system/bin/sh
cmd=$1
shift
os_version=$(getprop ro.build.version.sdk)
if [ "$os_version" -eq "27" ]; then
cmd="$cmd -Xrunjdwp:transport=dt_android_adb,suspend=n,server=y -Xcompiler-option --debuggable $@"
elif [ "$os_version" -eq "28" ]; then
cmd="$cmd -XjdwpProvider:adbconnection -XjdwpOptions:suspend=n,server=y -Xcompiler-option --debuggable $@"
else
cmd="$cmd -XjdwpProvider:adbconnection -XjdwpOptions:suspend=n,server=y $@"
fi
exec $cmd