Strace 사용

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

Srace 빌드

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

    mmma -j6 external/strace
    

실행 중인 프로세스에 연결

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

    adb shell strace -f -p PID
    

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

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

애플리케이션에 사용

애플리케이션에 strace를 사용하는 방법은 다음과 같습니다.

  1. strace를 실행할 수 있도록 기기를 설정합니다. 루트인 상태에서 SELinux를 사용 중지하고 런타임을 재시작하여 seccomp 필터를 제거해야 합니다. 그렇지 않으면 필터로 인해 다음이 실행되지 않습니다.
        adb root
        adb shell setenforce 0
        adb shell stop
        adb shell start
        
  2. 로그에 누구나 쓸 수 있는 디렉터리를 설정합니다. 이는 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
        
  • 커널 명령어를 추가한 다음 SELinux 허용 모드에서 기기를 부팅합니다. androidboot.selinux=permissiveBOARD_KERNEL_CMDLINE에 추가하여 부팅할 수도 있습니다. (이 변수는 build/core/Makefile에서는 읽기 전용이지만 /device/*/BoardConfig 아래에서 항상 사용 가능함)

    /device/google/marlin/sailfish/BoardConfig.mk의 픽셀(sailfish) 기기 예시:
        - BOARD_KERNEL_CMDLINE := ....  androidboot.hardware=sailfish ...
        +BOARD_KERNEL_CMDLINE := ....  androidboot.hardware=sailfish ...  androidboot.selinux=permissive
        
    변경 후에 부팅 이미지를 빌드하고 플래시하면 기기가 허용 모드에서 부팅됩니다.