使用 strace

通过 strace,您可以看到进程执行的系统调用,以及这些系统调用返回的内容。通常情况下,一次进程会执行大量系统调用,因此您需要查看 strace 手册页面,了解如何只收集您真正感兴趣的数据。

构建 strace

要构建 strace,请运行以下命令:

$ mmma -j6 external/strace

附加到正在运行的进程

对于 strace,最简单和最常见的用例即是附加到正在运行的进程,方法是使用下面这行命令:

$ adb shell strace -f -p PID

-f 标记表明 strace 会附加到相应进程中的所有现有线程,以及之后会产生的所有新线程。

在应用上使用

要在应用上使用 strace,请执行以下操作:

  1. 为 strace 日志设置一个目录:
    $ adb shell setenforce 0
    $ adb shell mkdir /data/local/tmp/strace
    $ adb shell chmod 777 /data/local/tmp/strace
    
  2. 在启动前选择要跟踪的进程:
    $ adb shell setprop wrap.com.google.android.browser "logwrapper strace -f -o /data/local/tmp/strace/strace.com.google.android.browser.txt"
    
  3. 正常启动该进程。

在 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/xbin/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/xbin/strace u:object_r:zygote_socket:s0
    
  • 添加内核命令,然后在 SELinux 宽容模式下启动相应设备。为此,请将 androidboot.selinux=permissive 添加到 BOARD_KERNEL_CMDLINE。(该变量在 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
    
    待做出上述更改后,编译并刷写启动映像;这样一来,该设备便会在宽容模式下启动了。