Bei der Fehlerbehebung und Profilerstellung für Anwendungen mit nativem Code ist es oft nützlich, Debugging-Tools, die beim Start eines Prozesses aktiviert werden müssen. Dies erfordert, dass führen Sie Ihre App in einem neuen Prozess aus, anstatt sie aus der Zygote zu klonen. Hier einige Beispiele:
- Tracing von Systemaufrufen mit strace
- Gedächtnis-Bugs finden mit Malloc-Debug oder Address Sanitizer (ASan):
- Profilerstellung mit Simpleperf
Shell-Script für Wrapping verwenden
Die Verwendung von wrap.sh
ist einfach:
- Kompilieren Sie ein benutzerdefiniertes debugfähiges APK, das Folgendes in einem Paket enthält:
<ph type="x-smartling-placeholder">
- </ph>
- Ein Shell-Skript mit dem Namen
wrap.sh
. Weitere Informationen finden Sie unter Erstellen Sie das Wrap-Shell-Skript und Package wrap.sh. - Alle zusätzlichen Tools, die das Shell-Skript benötigt (z. B. Ihre eigene
strace
-Binärdatei)
- Ein Shell-Skript mit dem Namen
- Installieren Sie das debugfähige APK auf einem Gerät.
- Starten Sie die App.
Shell-Script für Wrapping erstellen
Wenn du ein debugfähiges APK startest, das wrap.sh
enthält, führt das System
das Skript und übergibt den Befehl zum Starten der App als Argumente. Das Skript ist
ist für das Starten der Anwendung verantwortlich, kann aber jede Umgebung oder jedes Argument
Änderungen. Das Skript sollte
Syntax der MirBSD Korn Shell (mksh)
Das folgende Snippet zeigt, wie Sie eine einfache wrap.sh
-Datei schreiben, die
startet die App:
#!/system/bin/sh exec "$@"
Malloc-Fehlerbehebung
Zur Verwendung
Malloc-Debug
über wrap.sh
würden Sie die folgende Zeile einfügen:
#!/system/bin/sh LIBC_DEBUG_MALLOC_OPTIONS=backtrace logwrapper "$@"
San Francisco
Es gibt ein Beispiel dafür, wie Sie dies für ASan tun können, in der ASan-Dokumentation
Paket wrap.sh
Wenn du wrap.sh
nutzen möchtest, muss dein APK debug-fähig sein. Achten Sie darauf, dass der
Die Einstellung android:debuggable="true"
ist in der
<application>
in Ihrem Android-Manifest einfügen oder wenn Sie Android Studio verwenden,
haben Sie einen Debug-Build im
build.gradle
-Datei.
Außerdem müssen useLegacyPackaging
festgelegt werden.
in der build.gradle
-Datei deiner App auf true
. In den meisten Fällen ist diese Option
ist standardmäßig auf false
gesetzt. Sie sollten dies also explizit auf true
setzen,
um Überraschungen zu vermeiden.
Du musst das Skript wrap.sh
mit den nativen Bibliotheken der App verpacken. Wenn
Ihre Anwendung keine nativen Bibliotheken enthält, fügen Sie das lib-Verzeichnis manuell zu
Ihr Projektverzeichnis. Für jede Architektur, die Ihre Anwendung unterstützt, müssen Sie
stellen Sie eine Kopie des Wrap-Shell-Skripts in diesem nativen Bibliotheksverzeichnis bereit.
Das folgende Beispiel zeigt das Dateilayout, das sowohl ARMv8 als auch x86-64 unterstützt Architekturen:
# App Directory |- AndroidManifest.xml |- … |- lib |- arm64-v8a |- ... |- wrap.sh |- x86_64 |- ... |- wrap.sh
Android Studio verpackt nur .so
-Dateien aus den lib/
-Verzeichnissen.
verwenden Sie Android Studio, müssen Sie Ihre wrap.sh
-Dateien im Ordner
src/main/resources/lib/*
-Verzeichnisse, sodass sie in ein Paket umgewandelt werden.
korrekt sind.
resources/lib/x86
wird in der Benutzeroberfläche als
lib.x86
, obwohl es eigentlich ein Unterverzeichnis sein sollte:
Fehler bei Verwendung von wrap.sh beheben
Wenn Sie bei Verwendung von wrap.sh
einen Debugger anhängen möchten, wird Ihr Shell-Skript
müssen Sie das Debugging manuell aktivieren. Wie das geht, unterscheidet sich je nach Veröffentlichung,
In diesem Beispiel wird gezeigt, wie die
entsprechenden Optionen für alle Releases hinzugefügt werden,
unterstützen 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