strace の使用

strace を使用すると、プロセスが行うシステムコールと、そのシステムコールが返す結果を確認できます。

strace を作成する

strace を作成するには、次のコマンドを実行します。

mmma -j6 external/strace

実行中のプロセスにアタッチする

strace の非常に簡単かつ一般的な使用例は、次のように、実行中のプロセスにアタッチすることです。

adb shell strace -f -p PID

-f フラグを指定すると、strace はプロセス内のすべてのスレッドと、後で生成される新しいスレッドにアタッチされます。

一般的なプロセスでは大量のシステムコールが行われるため、strace のマニュアル ページを参照して、実際に必要なデータのみを収集する方法を確認することをおすすめします。

アプリで使用する

アプリで strace を使用する手順は次のとおりです。

  1. strace を実行できるようにデバイスを設定します。root 権限で SELinux を無効にし、ランタイムを再起動して、seccomp フィルタを削除する必要があります。削除しないと、strace を実行できません。
    adb root
    adb shell setenforce 0
    adb shell stop
    adb shell start
    
  2. strace はアプリの uid で実行されるため、strace ログ用に、グローバルに書き込み可能なディレクトリを設定します。
    adb shell mkdir -m 777 /data/local/tmp/strace
    
  3. トレースするプロセスを選択して起動します。
    adb shell setprop wrap.com.android.calendar '"logwrapper strace -f -o /data/local/tmp/strace/strace.com.android.calendar.txt"'
    
  4. プロセスを通常どおり起動します。

zygote で使用する

zygote で strace を使用するには、関連する init.rc の zygote 行を修正します(adb shell setenforce 0 が必要です)。

cd system/core/
patch -p1 <<EOF
--- a/rootdir/init.zygote32.rc
+++ b/rootdir/init.zygote32.rc
@@ -1,4 +1,4 @@
-service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
+service zygote /system/bin/strace -o /data/local/tmp/zygote.strace /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
     class main
     socket zygote stream 660 root system
     onrestart write /sys/android_power/request_state wake
EOF

Android の起動時に strace ログを取得する

Android の起動時に strace ログを取得するには、次の変更を行います。

  • プロセス名が zygote から strace に変更されるため、strace の SELinux file_context がないことが原因で、指定されたサービスを開始できない場合があります。この問題を解決するには、system/sepolicy/private/file_contexts に strace 用の新しい行を追加し、元のファイル コンテキストをコピーします。例:
    /dev/socket/zygote      u:object_r:zygote_socket:s0
    + /system/bin/strace u:object_r:zygote_socket:s0
    
  • カーネルまたは bootconfig のパラメータを追加し、SELinux の permissive モードでデバイスを起動します。これを行うには、androidboot.selinux=permissiveBOARD_KERNEL_CMDLINE に追加するか、カーネル バージョン 5.10 以降の Android 12 では BOARD_BOOTCONFIG に追加します。(この変数は、build/core/Makefile では読み取り専用ですが、/device/*/BoardConfig の下では常に使用可能です)。

    /device/google/marlin/sailfish/BoardConfig.mk の Pixel(sailfish)デバイスの例を次に示します。
    - BOARD_KERNEL_CMDLINE := ....  androidboot.hardware=sailfish ...
    +BOARD_KERNEL_CMDLINE := ....  androidboot.hardware=sailfish ...  androidboot.selinux=permissive
    
    変更後、ブートイメージをビルドしてフラッシュすると、デバイスが permissive モードで起動します。