로그 분석 대시보드 Android logcat 파일 분석
← 아티클 목록

네이티브 크래시 읽는 법 — Fatal signal 한 줄과 tombstone 백트레이스

심화 · SIGSEGV·SIGABRT · Android 소스 공식 문서 기준 · 2026년 10월 5일

셋톱박스에서 "재생 중 화면이 검게 변했다", "앱이 소리 없이 꺼졌다"는 증상은 자바 크래시가 아니라 코덱·드라이버·네이티브 라이브러리의 크래시인 경우가 많습니다. 이때 logcat에는 자바 스택트레이스 대신 Fatal signal 한 줄과 암호 같은 주소 목록이 남습니다. 이 글은 그 한 줄을 해석하는 법, 그리고 tombstone 파일의 백트레이스를 읽고 소스 위치로 바꾸는 법을 정리합니다. 형식과 예시는 source.android.com의 Diagnose native crashes 문서를 기준으로 했습니다.

1. Fatal signal 한 줄 분해하기

F libc : Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0 in tid 2250 (CodecLooper), pid 2201 (com.example.player)
부분뜻
Fatal signal 11 (SIGSEGV)프로세스가 받은 시그널. 종류는 아래 2장
code 1 (SEGV_MAPERR)시그널의 세부 이유. SEGV_MAPERR는 매핑되지 않은 주소, SEGV_ACCERR는 권한이 없는 주소(예: 읽기 전용 영역에 쓰기)
fault addr 0x0접근하려던 주소. 0이나 0에 가까운 작은 값이면 널 포인터(널 구조체의 필드 접근이면 0xc처럼 작은 수)
in tid 2250 (CodecLooper)죽은 스레드와 그 이름. 이름만으로 어느 계층인지 짐작할 수 있는 경우가 많음
pid 2201 (com.example.player)죽은 프로세스. 옛 버전에는 이 부분이 없을 수 있음

2. 시그널 종류별 의미

시그널흔한 원인로그에서 볼 것
SIGSEGV (11)잘못된 메모리 접근: 널 포인터, 해제된 메모리 사용, 범위 밖 접근fault addr의 값
SIGABRT (6)의도적 중단: abort(), assert 실패, 치명 로그 호출Abort message: 줄 — 원인이 문장으로 적혀 있는 경우가 많음
SIGBUS (7)정렬되지 않은 접근, 매핑된 파일이 잘린 경우 등메모리 맵(파일 매핑) 정보
SIGILL (4)잘못된 명령어 실행(손상된 코드, 다른 CPU용 바이너리)라이브러리 버전·아키텍처
SIGFPE (8)정수 0으로 나누기 등백트레이스 맨 위 함수
SIGSYS (31)보안 정책(seccomp)이 금지한 시스템 호출SYS_SECCOMP 코드

SIGABRT의 Abort message 예

3. tombstone의 구조

네이티브 크래시가 나면 시스템은 상세 덤프를 /data/tombstones/tombstone_NN에 저장하고, 같은 내용의 앞부분을 DEBUG(버전에 따라 crash_dump) 태그로 logcat에도 남깁니다.

*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'vendor/model/device:12/.../user/release-keys'
pid: 2201, tid: 2250, name: CodecLooper  >>> com.example.player <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0
    (레지스터 값들)
backtrace:
      #00 pc 0004a1c8  /vendor/lib/libexample_codec.so (ExampleDecoder::flush()+24)
      #01 pc 00039f10  /vendor/lib/libexample_codec.so
      #02 pc 0001d2a4  /system/lib/libstagefright.so (...)
      ...
  1. Build fingerprint — 정확히 어떤 펌웨어였는지. 같은 크래시가 특정 펌웨어에서만 나는지 비교할 때 씁니다.
  2. pid / tid / name — >>> <<< 사이가 프로세스 이름입니다.
  3. signal — logcat의 Fatal signal 줄과 같은 정보.
  4. backtrace — 맨 위(#00)가 크래시가 난 지점, 아래로 갈수록 그 함수를 부른 쪽입니다.

백트레이스 한 줄은 #번호 pc 라이브러리-안-오프셋 라이브러리-경로 (함수명+오프셋)입니다. 괄호 안 함수명이 있으면 그것만으로도 큰 단서이고, 없다면 라이브러리에 심볼이 제거된(stripped) 상태입니다.

먼저 볼 줄 고르기

4. 주소를 소스 위치로 바꾸기 (심볼화)

라이브러리를 직접 빌드했고 심볼이 남은 원본 파일(.so)을 가지고 있다면 백트레이스의 오프셋을 소스 파일과 줄 번호로 바꿀 수 있습니다.

# NDK의 ndk-stack: tombstone 전체를 한 번에 변환
ndk-stack -sym 앱/obj/local/arm64-v8a -dump tombstone_02

# 한 줄만 볼 때: llvm-addr2line (NDK에 포함)
llvm-addr2line -C -f -e libexample_codec.so 0x4a1c8

5. tombstone 파일 받기

adb bugreport bugreport.zip     # 일반 사용자 빌드에서 가장 확실한 방법 (압축 안에 tombstone 포함)
adb shell ls /data/tombstones   # 개발용 빌드라면 직접 목록 확인·pull 가능

tombstone 파일은 번호를 돌려 쓰므로, 크래시가 반복되는 기기에서는 오래된 것이 금방 덮어써집니다. 재현 직후에 받으세요. logcat의 Tombstone written to: 줄이 어느 번호에 저장됐는지 알려 줍니다(대시보드의 크래시 덤프 저장 패턴).

6. 반복되는 네이티브 크래시를 묶어 보는 요령

대시보드의 반복 오류 묶음은 주소와 숫자를 지운 서명으로 묶기 때문에, Fatal signal 줄의 시그널·코드·스레드 이름이 같은 크래시를 한 줄로 모아 보여 줍니다.

정리

참고 자료: Android Open Source Project, "Diagnose native crashes" (source.android.com/docs/core/tests/debug/native-crash). 예시의 라이브러리 이름과 주소는 설명용으로 만든 것입니다.

관련 글
· 실습: 셋톱박스 2대의 로그를 대시보드로 읽어 보기
· ANR 로그 분석하기
· 앱이 크래시 없이 사라질 때
· 아티클 목록 · 패턴 사전 · 서비스 소개
문의: dkdnj123@gmail.com