strace 사용

strace는 프로세스에서 생성하는 시스템 호출, 그리고 이러한 시스템 호출이 무엇을 반환하는지 확인할 수 있게 해줍니다.

strace 빌드

strace를 빌드하려면 다음을 실행합니다.

mmma -j6 external/strace

실행 중인 프로세스에 연결

strace와 관련된 가장 간단하고 일반적인 사용 사례는 다음을 사용하여 실행 중인 프로세스에 연결하는 것입니다.

adb shell strace -f -p PID

-f 플래그는 프로세스의 모든 스레드, 그리고 나중에 생성되는 새 스레드에 연결되도록 strace에 지시합니다.

일반적인 프로세스는 다수의 시스템 호출을 생성하므로 strace man page를 검토하여 실제로 관심 있는 데이터만 수집하는 방법을 알아보는 것이 좋습니다.

앱에서 사용

앱에서 strace를 사용하는 방법:

  1. strace를 실행할 수 있도록 기기를 설정합니다. 루트인 상태에서 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에 사용

strace를 zygote에 사용하려면 관련 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 허용 모드에서 기기를 부팅합니다. androidboot.selinux=permissiveBOARD_KERNEL_CMDLINE에 추가하거나 Android 12의 커널 버전 5.10 이상에서 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
    
    변경 후에 부팅 이미지를 빌드하고 플래시하면 기기가 허용 모드에서 부팅됩니다.