При отладке и профилировании приложений с использованием собственного кода часто бывает полезно использовать инструменты отладки, которые необходимо включать при запуске процесса. Для этого необходимо запустить приложение в новом процессе, а не клонировать из зиготы. Примеры включают в себя:
- Отслеживание системных вызовов с помощью strace .
- Поиск ошибок памяти с помощью отладки malloc или Address Sanitizer (ASan) .
- Профилирование с помощью Simpleperf .
Используйте сценарий оболочки оболочки
Использовать wrap.sh
очень просто:
- Скомпилируйте собственный отлаживаемый APK, который содержит следующее:
- Сценарий оболочки с именем
wrap.sh
Дополнительные сведения см. в разделах Создание сценария оболочки оболочки и Пакет Wrap.sh. - Любые дополнительные инструменты, необходимые вашему сценарию оболочки (например, ваш собственный двоичный файл
strace
).
- Сценарий оболочки с именем
- Установите отлаживаемый APK на устройство.
- Запустите приложение.
Создайте сценарий оболочки оболочки
Когда вы запускаете отлаживаемый APK-файл, содержащий wrap.sh
, система выполняет сценарий и передает команду для запуска приложения в качестве аргументов. Скрипт отвечает за запуск приложения, но может вносить любые изменения в среду или аргументы. Сценарий должен следовать синтаксису оболочки MirBSD Korn (mksh).
В следующем фрагменте показано, как написать простой файл wrap.sh
, который просто запускает приложение:
#!/system/bin/sh exec "$@"
Отладка Malloc
Чтобы использовать отладку malloc через wrap.sh
, вы должны включить следующую строку:
#!/system/bin/sh LIBC_DEBUG_MALLOC_OPTIONS=backtrace logwrapper "$@"
Асан
В документации ASan есть пример того, как это сделать для ASan.
Пакет Wrap.sh
Чтобы воспользоваться преимуществами wrap.sh
, ваш APK должен поддерживать отладку. Убедитесь, что параметр android:debuggable="true"
настроен в элементе <application>
манифеста Android, или, если вы используете Android Studio, вы настроили отладочную сборку в файле build.gradle
.
Также необходимо установить useLegacyPackaging
значение true
в файле build.gradle
вашего приложения. В большинстве случаев для этой опции по умолчанию установлено значение false
, поэтому вы можете явно установить для нее значение true
, чтобы избежать каких-либо неожиданностей.
Вы должны упаковать сценарий wrap.sh
с собственными библиотеками приложения. Если ваше приложение не содержит собственных библиотек, добавьте каталог lib вручную в каталог вашего проекта. Для каждой архитектуры, которую поддерживает ваше приложение, вы должны предоставить копию сценария оболочки оболочки в каталоге собственной библиотеки.
В следующем примере показан макет файла для поддержки архитектур ARMv8 и x86-64:
# App Directory |- AndroidManifest.xml |- … |- lib |- arm64-v8a |- ... |- wrap.sh |- x86_64 |- ... |- wrap.sh
Android Studio упаковывает файлы .so
только из каталогов lib/
, поэтому, если вы являетесь пользователем Android Studio, вам нужно вместо этого поместить файлы wrap.sh
в каталоги src/main/resources/lib/*
, чтобы они будут упакованы правильно.
Обратите внимание, что resources/lib/x86
будет отображаться в пользовательском интерфейсе как lib.x86
, но на самом деле это должен быть подкаталог:
Отладка при использовании Wrap.sh
Если вы хотите подключить отладчик при использовании wrap.sh
, ваш сценарий оболочки должен будет вручную включить отладку. Как это сделать, в разных выпусках различается, поэтому в этом примере показано, как добавить соответствующие параметры для всех выпусков, поддерживающих 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