使用 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 日志设置一个全局可写目录,因为 strace 将在应用的 uid 下运行
    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 宽容模式下启动设备。您可以通过在 Android 12 中使用内核版本 5.10 或更高版本,将 androidboot.selinux=permissive 添加到 BOARD_KERNEL_CMDLINEBOARD_BOOTCONFIG 来执行此操作。(此变量在 build/core/Makefile 中变为只读,但始终在 /device/*/BoardConfig 下可用。)

    Pixel (sailfish) 设备在 /device/google/marlin/sailfish/BoardConfig.mk 中的示例
    - BOARD_KERNEL_CMDLINE := ....  androidboot.hardware=sailfish ...
    +BOARD_KERNEL_CMDLINE := ....  androidboot.hardware=sailfish ...  androidboot.selinux=permissive
    
    进行更改后,构建并刷写启动映像,设备将在宽容模式下启动。