Using Strace

Strace enables you to see the system calls a process makes and what those system calls return. A typical process makes a lot of system calls, so you'll want to review the strace man page to learn how to collect only data you're actually interested in.

Building strace

To build strace, run the following:

mmma -j6 external/strace

Attaching to a running process

The simplest and most common use case for strace is to attach it to a running process, which you can do with:

adb shell strace -f -p PID

The -f flag tells strace to attach to all the threads in the process, plus any new threads spawned later.

Using on an application

To use strace on an application:

  1. Set up a directory for strace logs:
    adb shell setenforce 0
    adb shell mkdir /data/local/tmp/strace
    adb shell chmod 777 /data/local/tmp/strace
  2. Choose the process to trace before launching it:
    adb shell setprop "logwrapper strace -f -o /data/local/tmp/strace/"
  3. Launch the process normally.

Using on the zygote

To use strace on the zygote, fix the relevant init.rc zygote line (requires 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

Getting strace logs during Android boot

To get strace logs during Android boot, make the following changes:

  • Since the process name changes from zygote to strace, the given service may fail to start due to the missing SELinux file_context for strace. The solution is to add a new line for strace in system/sepolicy/private/file_contexts and copy the original file context over. Example:
    /dev/socket/zygote      u:object_r:zygote_socket:s0
    + /system/xbin/strace u:object_r:zygote_socket:s0
  • Add kernel command, then boot the device in SELinux permissive mode. You can do this by adding androidboot.selinux=permissiveto BOARD_KERNEL_CMDLINE. (This variable becomes read-only in build/core/Makefile but is always available under /device/*/BoardConfig.)

    Example for the Pixel (sailfish) device in /device/google/marlin/sailfish/
    - BOARD_KERNEL_CMDLINE := ....  androidboot.hardware=sailfish ...
    +BOARD_KERNEL_CMDLINE := ....  androidboot.hardware=sailfish ...  androidboot.selinux=permissive
    After making the change, build and flash the boot image and the device will boot in permissive mode.