Chẩn đoán trục trặc mã gốc

Các phần sau bao gồm các loại sự cố gốc phổ biến, bản phân tích về mẫu tệp kết xuất sự cố và nội dung thảo luận về tombstone. Mỗi loại sự cố bao gồm ví dụ về đầu ra của debuggerd, trong đó có các bằng chứng chính được làm nổi bật để hỗ trợ bạn có thể phân biệt loại sự cố cụ thể.

Hủy

Việc huỷ bỏ là thú vị vì chúng có chủ ý. Có nhiều giải pháp cách huỷ (bao gồm cả lệnh gọi abort(3), không thành công assert(3), sử dụng một trong các loại ghi nhật ký quan trọng dành riêng cho Android), nhưng tất cả đều liên quan đến đang gọi abort. Lệnh gọi đến abort sẽ báo hiệu lệnh gọi luồng có SIGABRT, do đó, khung hiển thị "cancel" trong libc.so+ SIGABRT là những thứ cần tìm trong đầu ra debuggerd để nhận ra trường hợp này.

Có thể có "thông báo huỷ bỏ" rõ ràng . Bạn cũng nên xem trong Đầu ra logcat để xem luồng này đã ghi lại gì trước khi có chủ ý tự tử, vì không giống như assert(3) hoặc hành vi gây tử vong cấp cao cơ sở ghi nhật ký, abort(3) không chấp nhận thông báo.

Các phiên bản hiện tại của Android cùng dòng tgkill(2) lệnh gọi hệ thống để ngăn xếp của chúng là dễ đọc nhất, với lệnh gọi đến huỷ(3) ở trên cùng:

pid: 4637, tid: 4637, name: crasher  >>> crasher <<<
signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
Abort message: 'some_file.c:123: some_function: assertion "false" failed'
    r0  00000000  r1  0000121d  r2  00000006  r3  00000008
    r4  0000121d  r5  0000121d  r6  ffb44a1c  r7  0000010c
    r8  00000000  r9  00000000  r10 00000000  r11 00000000
    ip  ffb44c20  sp  ffb44a08  lr  eace2b0b  pc  eace2b16
backtrace:
    #00 pc 0001cb16  /system/lib/libc.so (abort+57)
    #01 pc 0001cd8f  /system/lib/libc.so (__assert2+22)
    #02 pc 00001531  /system/bin/crasher (do_action+764)
    #03 pc 00002301  /system/bin/crasher (main+68)
    #04 pc 0008a809  /system/lib/libc.so (__libc_init+48)
    #05 pc 00001097  /system/bin/crasher (_start_main+38)

Các phiên bản Android cũ hơn đi theo một lộ trình phức tạp giữa phiên bản gốc huỷ lệnh gọi (khung 4 ở đây) và việc gửi tín hiệu thực tế (khung 0 ở đây). Điều này đặc biệt đúng trên ARM 32 bit, công nghệ __libc_android_abort (khung hình 3 tại đây) với các nền tảng khác chuỗi raise/pthread_kill/tgkill:

pid: 1656, tid: 1656, name: crasher  >>> crasher <<<
signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
Abort message: 'some_file.c:123: some_function: assertion "false" failed'
    r0 00000000  r1 00000678  r2 00000006  r3 f70b6dc8
    r4 f70b6dd0  r5 f70b6d80  r6 00000002  r7 0000010c
    r8 ffffffed  r9 00000000  sl 00000000  fp ff96ae1c
    ip 00000006  sp ff96ad18  lr f700ced5  pc f700dc98  cpsr 400b0010
backtrace:
    #00 pc 00042c98  /system/lib/libc.so (tgkill+12)
    #01 pc 00041ed1  /system/lib/libc.so (pthread_kill+32)
    #02 pc 0001bb87  /system/lib/libc.so (raise+10)
    #03 pc 00018cad  /system/lib/libc.so (__libc_android_abort+34)
    #04 pc 000168e8  /system/lib/libc.so (abort+4)
    #05 pc 0001a78f  /system/lib/libc.so (__libc_fatal+16)
    #06 pc 00018d35  /system/lib/libc.so (__assert2+20)
    #07 pc 00000f21  /system/xbin/crasher
    #08 pc 00016795  /system/lib/libc.so (__libc_init+44)
    #09 pc 00000abc  /system/xbin/crasher

Bạn có thể tái tạo một thực thể của loại sự cố này bằng crasher abort.

Tham chiếu con trỏ rỗng hoàn toàn

Đây là lỗi gốc cổ điển, mặc dù đây chỉ là một trường hợp đặc biệt loại sự cố tiếp theo, bạn nên đề cập riêng vì loại sự cố này thường yêu cầu ít được suy nghĩ nhất.

Trong ví dụ bên dưới, mặc dù hàm sự cố nằm trong libc.so, vì các hàm chuỗi chỉ hoạt động trên con trỏ bạn được cấp, bạn có thể suy luận rằng strlen(3) được gọi bằng con trỏ rỗng; và sự cố này sẽ xảy ra ngay tác giả của mã gọi điện. Trong trường hợp này, khung số 01 là phương thức gọi không hợp lệ.

pid: 25326, tid: 25326, name: crasher  >>> crasher <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0
    r0 00000000  r1 00000000  r2 00004c00  r3 00000000
    r4 ab088071  r5 fff92b34  r6 00000002  r7 fff92b40
    r8 00000000  r9 00000000  sl 00000000  fp fff92b2c
    ip ab08cfc4  sp fff92a08  lr ab087a93  pc efb78988  cpsr 600d0030

backtrace:
    #00 pc 00019988  /system/lib/libc.so (strlen+71)
    #01 pc 00001a8f  /system/xbin/crasher (strlen_null+22)
    #02 pc 000017cd  /system/xbin/crasher (do_action+948)
    #03 pc 000020d5  /system/xbin/crasher (main+100)
    #04 pc 000177a1  /system/lib/libc.so (__libc_init+48)
    #05 pc 000010e4  /system/xbin/crasher (_start+96)

Bạn có thể tái tạo một thực thể của loại sự cố này bằng crasher strlen-NULL.

Tham chiếu con trỏ rỗng địa chỉ thấp

Trong nhiều trường hợp, địa chỉ lỗi sẽ không bằng 0, nhưng vẫn còn một số số nhỏ khác. Hai hoặc đặc biệt là địa chỉ gồm ba chữ số rất phổ biến, trong khi địa chỉ gồm sáu chữ số địa chỉ gần như chắc chắn không phải là việc tham chiếu con trỏ rỗng – điều đó sẽ yêu cầu độ lệch 1MiB. Điều này thường xảy ra khi bạn có mã tham chiếu con trỏ rỗng như thể đó là một cấu trúc hợp lệ. Sau đây là các hàm phổ biến fprintf(3) (hoặc bất kỳ hàm nào khác lấy TỆP*) và readdir(3), vì mã thường không thể kiểm tra xem fopen(3) hoặc opendir(3) thực sự đã thành công trước tiên.

Dưới đây là một ví dụ về readdir:

pid: 25405, tid: 25405, name: crasher  >>> crasher <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xc
    r0 0000000c  r1 00000000  r2 00000000  r3 3d5f0000
    r4 00000000  r5 0000000c  r6 00000002  r7 ff8618f0
    r8 00000000  r9 00000000  sl 00000000  fp ff8618dc
    ip edaa6834  sp ff8617a8  lr eda34a1f  pc eda618f6  cpsr 600d0030

backtrace:
    #00 pc 000478f6  /system/lib/libc.so (pthread_mutex_lock+1)
    #01 pc 0001aa1b  /system/lib/libc.so (readdir+10)
    #02 pc 00001b35  /system/xbin/crasher (readdir_null+20)
    #03 pc 00001815  /system/xbin/crasher (do_action+976)
    #04 pc 000021e5  /system/xbin/crasher (main+100)
    #05 pc 000177a1  /system/lib/libc.so (__libc_init+48)
    #06 pc 00001110  /system/xbin/crasher (_start+96)

Ở đây, nguyên nhân trực tiếp gây ra sự cố là pthread_mutex_lock(3) đã cố truy cập địa chỉ 0xc (khung 0). Nhưng điều đầu tiên pthread_mutex_lock tham chiếu đến state của pthread_mutex_t* mà nó được cung cấp. Nếu bạn nhìn vào nguồn, bạn có thể thấy phần tử đó nằm bù trừ 0 trong cấu trúc, giá trị này cho bạn biết rằng pthread_mutex_lock đã được cấp con trỏ 0xc không hợp lệ. Từ bạn có thể thấy rằng khung hình 1 đã được readdir cấp cho con trỏ đó, Thao tác này sẽ trích xuất trường mutex_ từ DIR*. đã cho. Nhìn vào cấu trúc đó, bạn có thể thấy rằng mutex_ đang ở tại bù sizeof(int) + sizeof(size_t) + sizeof(dirent*) thành struct DIR, trên thiết bị 32 bit là 4 + 4 + 4 = 12 = 0xc, vì vậy bạn phát hiện thấy lỗi: readdir đã được truyền một con trỏ rỗng người gọi. Tại thời điểm này, bạn có thể dán ngăn xếp vào công cụ ngăn xếp để tìm hiểu where (nơi điều này xảy ra) trong logcat.

  struct DIR {
    int fd_;
    size_t available_bytes_;
    dirent* next_;
    pthread_mutex_t mutex_;
    dirent buff_[15];
    long current_pos_;
  };

Trong hầu hết các trường hợp, bạn có thể thực sự bỏ qua quá trình phân tích này. Lỗi ở mức vừa phải thường có nghĩa là bạn có thể bỏ qua bất kỳ khung libc.so nào trong và trực tiếp cáo buộc mã gọi đó. Nhưng không phải lúc nào cũng vậy, và đây là cách bạn sẽ trình bày một trường hợp thuyết phục.

Bạn có thể tái tạo các thực thể của loại sự cố này bằng cách sử dụng crasher fprintf-NULL hoặc crasher readdir-NULL.

Lỗi FORTIFY

Lỗi FORTIFY là một trường hợp huỷ đặc biệt xảy ra khi thư viện C phát hiện một vấn đề có thể dẫn đến lỗ hổng bảo mật. Thư viện C nhiều các hàm được củng cố; các em sẽ lấy thêm một lập luận để kích thước thực sự của bộ đệm và kiểm tra trong thời gian chạy xem thao tác mà bạn đang cố gắng thực hiện. Sau đây là ví dụ về trường hợp mã cố gắng vào read(fd, buf, 32) vào một bộ đệm thực ra chỉ 10 byte dài...

pid: 25579, tid: 25579, name: crasher  >>> crasher <<<
signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
Abort message: 'FORTIFY: read: prevented 32-byte write into 10-byte buffer'
    r0 00000000  r1 000063eb  r2 00000006  r3 00000008
    r4 ff96f350  r5 000063eb  r6 000063eb  r7 0000010c
    r8 00000000  r9 00000000  sl 00000000  fp ff96f49c
    ip 00000000  sp ff96f340  lr ee83ece3  pc ee86ef0c  cpsr 000d0010

backtrace:
    #00 pc 00049f0c  /system/lib/libc.so (tgkill+12)
    #01 pc 00019cdf  /system/lib/libc.so (abort+50)
    #02 pc 0001e197  /system/lib/libc.so (__fortify_fatal+30)
    #03 pc 0001baf9  /system/lib/libc.so (__read_chk+48)
    #04 pc 0000165b  /system/xbin/crasher (do_action+534)
    #05 pc 000021e5  /system/xbin/crasher (main+100)
    #06 pc 000177a1  /system/lib/libc.so (__libc_init+48)
    #07 pc 00001110  /system/xbin/crasher (_start+96)

Bạn có thể tái tạo một thực thể của loại sự cố này bằng crasher fortify.

Lỗi ngăn xếp do -fstack-protector phát hiện

Tuỳ chọn -fstack-protector của trình biên dịch sẽ chèn các lượt kiểm tra vào các hàm có vùng đệm trên ngăn xếp để bảo vệ khỏi tình trạng tràn bộ đệm. Lựa chọn này được bật theo mặc định cho mã nền tảng nhưng không bật cho ứng dụng. Khi lựa chọn này là bật, trình biên dịch sẽ thêm hướng dẫn vào hàm mở đầu để viết một giá trị ngẫu nhiên vừa qua cục bộ cuối cùng trên ngăn xếp và vào phần kết của hàm để đọc lại và kiểm tra nhằm đảm bảo rằng hàm không thay đổi. Nếu giá trị đó thay đổi, nó bị ghi đè bởi một tình trạng tràn vùng đệm, nên phần kết gọi __stack_chk_fail để ghi nhật ký thông báo và huỷ.

pid: 26717, tid: 26717, name: crasher  >>> crasher <<<
signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
Abort message: 'stack corruption detected'
    r0 00000000  r1 0000685d  r2 00000006  r3 00000008
    r4 ffd516d8  r5 0000685d  r6 0000685d  r7 0000010c
    r8 00000000  r9 00000000  sl 00000000  fp ffd518bc
    ip 00000000  sp ffd516c8  lr ee63ece3  pc ee66ef0c  cpsr 000e0010

backtrace:
    #00 pc 00049f0c  /system/lib/libc.so (tgkill+12)
    #01 pc 00019cdf  /system/lib/libc.so (abort+50)
    #02 pc 0001e07d  /system/lib/libc.so (__libc_fatal+24)
    #03 pc 0004863f  /system/lib/libc.so (__stack_chk_fail+6)
    #04 pc 000013ed  /system/xbin/crasher (smash_stack+76)
    #05 pc 00001591  /system/xbin/crasher (do_action+280)
    #06 pc 00002219  /system/xbin/crasher (main+100)
    #07 pc 000177a1  /system/lib/libc.so (__libc_init+48)
    #08 pc 00001144  /system/xbin/crasher (_start+96)

Bạn có thể phân biệt hành vi này với các loại hành vi huỷ bỏ khác bằng sự hiện diện của __stack_chk_fail trong dấu vết ngược và thông báo huỷ cụ thể.

Bạn có thể tái tạo một thực thể của loại sự cố này bằng crasher smash-stack.

Bảo vệ SIGSYS khỏi một lệnh gọi hệ thống không được phép

seccomp hệ thống (cụ thể là seccomp-bpf) hạn chế quyền truy cập vào các lệnh gọi hệ thống. Để biết thêm thông tin về seccomp dành cho các nhà phát triển nền tảng, hãy xem bài đăng trên blog Seccomp trong Android O. Một luồng gọi một lệnh gọi hệ thống bị hạn chế sẽ nhận tín hiệu SIGSYS có mã SYS_SECCOMP. Số cuộc gọi hệ thống sẽ là được hiển thị trong dòng nguyên nhân cùng với cấu trúc. Điều quan trọng cần lưu ý số lệnh gọi hệ thống khác nhau giữa các cấu trúc. Ví dụ: Lệnh gọi hệ thống readlinkat(2) là số 305 trên x86 nhưng lại là số 267 trên x86-64. Số cuộc gọi trên cả arm và arm64 lại khác nhau. Vì lệnh gọi hệ thống số lượng khác nhau giữa các cấu trúc, thường thì cách dễ dàng hơn là sử dụng dấu vết ngăn xếp để tìm ra lệnh gọi hệ thống nào không được phép thay vì tìm kiếm số điện thoại hệ thống trong tiêu đề.

pid: 11046, tid: 11046, name: crasher  >>> crasher <<<
signal 31 (SIGSYS), code 1 (SYS_SECCOMP), fault addr --------
Cause: seccomp prevented call to disallowed arm system call 99999
    r0 cfda0444  r1 00000014  r2 40000000  r3 00000000
    r4 00000000  r5 00000000  r6 00000000  r7 0001869f
    r8 00000000  r9 00000000  sl 00000000  fp fffefa58
    ip fffef898  sp fffef888  lr 00401997  pc f74f3658  cpsr 600f0010

backtrace:
    #00 pc 00019658  /system/lib/libc.so (syscall+32)
    #01 pc 00001993  /system/bin/crasher (do_action+1474)
    #02 pc 00002699  /system/bin/crasher (main+68)
    #03 pc 0007c60d  /system/lib/libc.so (__libc_init+48)
    #04 pc 000011b0  /system/bin/crasher (_start_main+72)

Bạn có thể phân biệt các lệnh gọi hệ thống không được phép với các sự cố khác qua sự hiện diện của SYS_SECCOMP trên đường tín hiệu và nội dung mô tả trên đường nguyên nhân.

Bạn có thể tái tạo một thực thể của loại sự cố này bằng crasher seccomp.

Vi phạm bộ nhớ chỉ thực thi (chỉ dành cho Android 10)

Chỉ đối với arm64 trong Android 10, các phân đoạn có thể thực thi của tệp nhị phân và thư viện đã được ánh xạ vào bộ nhớ – chỉ thực thi (không đọc được) như một kỹ thuật tăng cường bảo vệ chống lại các cuộc tấn công sử dụng lại mã. Giải pháp giảm thiểu này tương tác kém với các giải pháp giảm thiểu khác nên sau đó đã bị xoá.

Việc khiến đoạn mã không thể đọc được sẽ khiến các lượt đọc có chủ đích và ngoài ý muốn vào các phân đoạn bộ nhớ được đánh dấu chỉ thực thi để gửi một SIGSEGV với mã SEGV_ACCERR. Điều này có thể xảy ra do lỗi, lỗ hổng bảo mật, dữ liệu kết hợp với mã (chẳng hạn như một nhóm ký tự), hoặc có chủ ý truy vấn bộ nhớ.

Trình biên dịch giả định mã và dữ liệu không kết hợp với nhau, nhưng các vấn đề có thể phát sinh từ việc viết thủ công lắp ráp. Trong nhiều trường hợp, bạn chỉ cần di chuyển các hằng số đến .data . Nếu thực sự cần phải xem xét mã trong các phần mã có thể thực thi, mprotect(2) sẽ được gọi trước để đánh dấu mã có thể đọc được và một lần nữa để đánh dấu mã là không thể đọc sau đã hoàn tất.

pid: 2938, tid: 2940, name: crasher64  >>> crasher64 <<<
signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 0x5f2ced24a8
Cause: execute-only (no-read) memory access error; likely due to data in .text.
    x0  0000000000000000  x1  0000005f2cecf21f  x2  0000000000000078  x3  0000000000000053
    x4  0000000000000074  x5  8000000000000000  x6  ff71646772607162  x7  00000020dcf0d16c
    x8  0000005f2ced24a8  x9  000000781251c55e  x10 0000000000000000  x11 0000000000000000
    x12 0000000000000014  x13 ffffffffffffffff  x14 0000000000000002  x15 ffffffffffffffff
    x16 0000005f2ced52f0  x17 00000078125c0ed8  x18 0000007810e8e000  x19 00000078119fbd50
    x20 00000078125d6020  x21 00000078119fbd50  x22 00000b7a00000b7a  x23 00000078119fbdd8
    x24 00000078119fbd50  x25 00000078119fbd50  x26 00000078119fc018  x27 00000078128ea020
    x28 00000078119fc020  x29 00000078119fbcb0
    sp  00000078119fba40  lr  0000005f2ced1b94  pc  0000005f2ced1ba4

backtrace:
      #00 pc 0000000000003ba4  /system/bin/crasher64 (do_action+2348)
      #01 pc 0000000000003234  /system/bin/crasher64 (thread_callback+44)
      #02 pc 00000000000e2044  /apex/com.android.runtime/lib64/bionic/libc.so (__pthread_start(void*)+36)
      #03 pc 0000000000083de0  /apex/com.android.runtime/lib64/bionic/libc.so (__start_thread+64)

Bạn có thể phân biệt các lỗi vi phạm bộ nhớ chỉ thực thi với các sự cố khác theo dòng nguyên nhân.

Bạn có thể tái tạo một thực thể của loại sự cố này bằng crasher xom.

Lỗi do fdsan phát hiện

Trình dọn dẹp mô tả tệp fdsan của Android giúp phát hiện các lỗi phổ biến với chỉ số mô tả tệp như dưới dạng use-after-close và kép đóng. Xem fdsan tài liệu để biết thêm thông tin chi tiết về cách gỡ lỗi (và tránh) loại lỗi này.

pid: 32315, tid: 32315, name: crasher64  >>> crasher64 <<<
signal 35 (), code -1 (SI_QUEUE), fault addr --------
Abort message: 'attempted to close file descriptor 3, expected to be unowned, actually owned by FILE* 0x7d8e413018'
    x0  0000000000000000  x1  0000000000007e3b  x2  0000000000000023  x3  0000007fe7300bb0
    x4  3033313465386437  x5  3033313465386437  x6  3033313465386437  x7  3831303331346538
    x8  00000000000000f0  x9  0000000000000000  x10 0000000000000059  x11 0000000000000034
    x12 0000007d8ebc3a49  x13 0000007fe730077a  x14 0000007fe730077a  x15 0000000000000000
    x16 0000007d8ec9a7b8  x17 0000007d8ec779f0  x18 0000007d8f29c000  x19 0000000000007e3b
    x20 0000000000007e3b  x21 0000007d8f023020  x22 0000007d8f3b58dc  x23 0000000000000001
    x24 0000007fe73009a0  x25 0000007fe73008e0  x26 0000007fe7300ca0  x27 0000000000000000
    x28 0000000000000000  x29 0000007fe7300c90
    sp  0000007fe7300860  lr  0000007d8ec2f22c  pc  0000007d8ec2f250

backtrace:
      #00 pc 0000000000088250  /bionic/lib64/libc.so (fdsan_error(char const*, ...)+384)
      #01 pc 0000000000088060  /bionic/lib64/libc.so (android_fdsan_close_with_tag+632)
      #02 pc 00000000000887e8  /bionic/lib64/libc.so (close+16)
      #03 pc 000000000000379c  /system/bin/crasher64 (do_action+1316)
      #04 pc 00000000000049c8  /system/bin/crasher64 (main+96)
      #05 pc 000000000008021c  /bionic/lib64/libc.so (_start_main)

Bạn có thể phân biệt hành vi này với các loại hành vi huỷ bỏ khác bằng sự hiện diện của fdsan_error trong dấu vết ngược và thông báo huỷ cụ thể.

Bạn có thể tái tạo một thực thể của loại sự cố này bằng cách sử dụng crasher fdsan_file hoặc crasher fdsan_dir.

Điều tra tệp báo lỗi

Nếu không có sự cố cụ thể nào mà bạn đang điều tra ngay bây giờ, nguồn nền tảng bao gồm một công cụ để kiểm thử debuggerd có tên là va chạm. Nếu mm trong system/core/debuggerd/, bạn sẽ nhận cả crashercrasher64 trên đường dẫn của bạn (phương thức cho phép bạn kiểm thử các sự cố 64 bit). Crasher có thể gặp sự cố trong nhiều cách thú vị dựa trên đối số dòng lệnh mà bạn cung cấp. Sử dụng crasher --help để xem lựa chọn hiện được hỗ trợ.

Để đưa các phần khác nhau vào tệp kết xuất sự cố, hãy cùng tìm hiểu ví dụ về tệp kết xuất sự cố:

*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'Android/aosp_flounder/flounder:5.1.51/AOSP/enh08201009:eng/test-keys'
Revision: '0'
ABI: 'arm'
pid: 1656, tid: 1656, name: crasher  >>> crasher <<<
signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
Abort message: 'some_file.c:123: some_function: assertion "false" failed'
    r0 00000000  r1 00000678  r2 00000006  r3 f70b6dc8
    r4 f70b6dd0  r5 f70b6d80  r6 00000002  r7 0000010c
    r8 ffffffed  r9 00000000  sl 00000000  fp ff96ae1c
    ip 00000006  sp ff96ad18  lr f700ced5  pc f700dc98  cpsr 400b0010
backtrace:
    #00 pc 00042c98  /system/lib/libc.so (tgkill+12)
    #01 pc 00041ed1  /system/lib/libc.so (pthread_kill+32)
    #02 pc 0001bb87  /system/lib/libc.so (raise+10)
    #03 pc 00018cad  /system/lib/libc.so (__libc_android_abort+34)
    #04 pc 000168e8  /system/lib/libc.so (abort+4)
    #05 pc 0001a78f  /system/lib/libc.so (__libc_fatal+16)
    #06 pc 00018d35  /system/lib/libc.so (__assert2+20)
    #07 pc 00000f21  /system/xbin/crasher
    #08 pc 00016795  /system/lib/libc.so (__libc_init+44)
    #09 pc 00000abc  /system/xbin/crasher
Tombstone written to: /data/tombstones/tombstone_06
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***

Dòng dấu hoa thị có dấu cách rất hữu ích nếu bạn đang tìm kiếm nhật ký cho các trục trặc mã gốc. Chuỗi "*** ***" hiếm khi xuất hiện trong nhật ký khi bắt đầu sự cố gốc.

Build fingerprint:
'Android/aosp_flounder/flounder:5.1.51/AOSP/enh08201009:eng/test-keys'

Vân tay số này giúp bạn xác định chính xác bản dựng xảy ra sự cố. Hệ thống này giống hệt như hệ thống ro.build.fingerprint thuộc tính này.

Revision: '0'

Bản sửa đổi đề cập đến phần cứng chứ không phải phần mềm. Việc này thường không được sử dụng nhưng có thể hữu ích trong việc giúp bạn tự động bỏ qua các lỗi đã biết do phần cứng xấu gây ra. Điều này hoàn toàn giống với Thuộc tính hệ thống ro.revision.

ABI: 'arm'

ABI là một trong các arm, arm64, x86 hoặc x86-64. Việc này chủ yếu hữu ích cho tập lệnh stack nêu trên để tập lệnh biết nên sử dụng chuỗi công cụ nào.

pid: 1656, tid: 1656, name: crasher >>> crasher <<<

Dòng này xác định luồng cụ thể trong quy trình bị sự cố. Trong phần này đó là một quá trình" luồng chính, vì vậy, mã quy trình và mã luồng sẽ khớp với nhau. Tên đầu tiên là tên luồng và tên được đặt trong dấu >>> và <<< là tên quy trình. Đối với một ứng dụng, tên quy trình thường là tên gói đủ điều kiện (chẳng hạn như com.facebook.katana), tức là hữu ích khi báo lỗi hoặc cố gắng tìm ứng dụng trong Google Play. Pid và txt cũng có thể hữu ích trong việc tìm các dòng nhật ký liên quan trước sự cố.

signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------

Dòng này cho bạn biết tín hiệu nào (SIGABRT) đã nhận được cùng với thông tin khác về cách tín hiệu đó đã nhận được (SI_TKILL). Các tín hiệu do debuggerd báo cáo là SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGSEGV và SIGTRAP. Tín hiệu cụ thể sẽ khác nhau tuỳ theo tín hiệu cụ thể.

Abort message: 'some_file.c:123: some_function: assertion "false" failed'

Không phải sự cố nào cũng có dòng thông báo huỷ bỏ, nhưng sẽ bị huỷ. Đây là tự động được thu thập từ dòng cuối cùng của đầu ra logcat quan trọng cho pid/nghiên cứu và trong trường hợp cố ý phá thai có thể lời giải thích lý do chương trình tự tử.

r0 00000000 r1 00000678 r2 00000006 r3 f70b6dc8
r4 f70b6dd0 r5 f70b6d80 r6 00000002 r7 0000010c
r8 ffffffed r9 00000000 sl 00000000 fp ff96ae1c
ip 00000006 sp ff96ad18 lr f700ced5 pc f700dc98 cpsr 400b0010

Tệp kết xuất thanh ghi hiển thị nội dung của các thanh ghi CPU tại thời điểm đã nhận được tín hiệu. (Phần này khác nhau rất nhiều giữa các ABI.) Mức độ hữu ích những vấn đề này sẽ tuỳ thuộc vào sự cố cụ thể.

backtrace:
    #00 pc 00042c98 /system/lib/libc.so (tgkill+12)
    #01 pc 00041ed1 /system/lib/libc.so (pthread_kill+32)
    #02 pc 0001bb87 /system/lib/libc.so (raise+10)
    #03 pc 00018cad /system/lib/libc.so (__libc_android_abort+34)
    #04 pc 000168e8 /system/lib/libc.so (abort+4)
    #05 pc 0001a78f /system/lib/libc.so (__libc_fatal+16)
    #06 pc 00018d35 /system/lib/libc.so (__assert2+20)
    #07 pc 00000f21 /system/xbin/crasher
    #08 pc 00016795 /system/lib/libc.so (__libc_init+44)
    #09 pc 00000abc /system/xbin/crasher

Dấu vết ngược cho bạn biết chúng tôi đã ở đâu trong mã tại thời điểm xảy ra sự cố. Chiến lược phát hành đĩa đơn cột đầu tiên là số khung (phù hợp với kiểu của gdb trong đó khung sâu nhất là 0). Các giá trị của PC có liên quan đến vị trí của thư viện dùng chung thay vì so với địa chỉ tuyệt đối. Cột tiếp theo là tên của khu vực được liên kết (thường là thư viện dùng chung hoặc tệp thực thi, nhưng có thể không dành cho, chẳng hạn như mã được biên dịch JIT). Cuối cùng, nếu có sẵn các biểu tượng, biểu tượng mà máy tính giá trị tương ứng với được hiển thị, cùng với độ lệch vào biểu tượng đó trong byte. Bạn có thể sử dụng thuộc tính này cùng với objdump(1) để tìm hướng dẫn tương ứng dành cho đối tượng tập hợp.

Đọc tombstone

Tombstone written to: /data/tombstones/tombstone_06

Thông tin này cho bạn biết vị trí debuggerd đã viết thêm thông tin. debuggerd sẽ lưu giữ tối đa 10 bia mộ, đạp xe xuyên suốt các số từ 00 đến 09 và ghi đè lên những bia mộ hiện có nếu cần.

Tombstone chứa cùng một thông tin với tệp kết xuất sự cố, cộng với một vài thông tin ứng dụng khác. Ví dụ: Tệp này bao gồm các dấu vết ngược cho tất cả các luồng (không phải luồng bị sự cố), thanh ghi dấu phẩy động, tệp kết xuất ngăn xếp thô, và tệp kết xuất bộ nhớ xung quanh địa chỉ trong thanh ghi. Hữu ích nhất là khi bao gồm một bản đồ bộ nhớ đầy (tương tự như /proc/pid/maps). Dưới đây là ví dụ có chú thích từ sự cố xử lý ARM 32 bit:

memory map: (fault address prefixed with --->)
--->ab15f000-ab162fff r-x 0 4000 /system/xbin/crasher (BuildId:
b9527db01b5cf8f5402f899f64b9b121)

Có hai điều cần lưu ý ở đây. Đầu tiên là dòng này có tiền tố bằng "--->". Các tệp ánh xạ sẽ hữu ích nhất khi sự cố của bạn không chỉ là một giá trị rỗng tham chiếu con trỏ. Nếu địa chỉ lỗi nhỏ, thì có thể là do một số biến thể của tham chiếu con trỏ rỗng. Nếu không, hãy xem bản đồ xung quanh lỗi thường có thể cung cấp cho bạn manh mối về điều gì đã xảy ra. Một số vấn đề có thể xảy ra có thể được nhận ra bằng cách nhìn vào bản đồ, bao gồm:

  • Đọc/ghi qua phần cuối của khối bộ nhớ.
  • Đọc/ghi trước điểm bắt đầu của một khối bộ nhớ.
  • Cố gắng thực thi những đoạn mã không phải mã.
  • Chạy ra khỏi kết thúc ngăn xếp.
  • Cố gắng ghi vào mã (như trong ví dụ ở trên).

Điều thứ hai cần lưu ý là các tệp thực thi và tệp thư viện dùng chung sẽ hiển thị BuildId (nếu có) trong Android 6.0 trở lên để bạn có thể thấy chính xác phiên bản mã nào của bạn gặp sự cố. Tệp nhị phân nền tảng bao gồm BuildId theo mặc định kể từ Android 6.0; NDK r12 trở lên tự động vượt qua -Wl,--build-id cũng cho trình liên kết.

ab163000-ab163fff r--      3000      1000  /system/xbin/crasher
ab164000-ab164fff rw-         0      1000
f6c80000-f6d7ffff rw-         0    100000  [anon:libc_malloc]

Trên Android, vùng nhớ khối xếp không nhất thiết phải là một khu vực. Vùng nhớ khối xếp sẽ được gắn nhãn [anon:libc_malloc].

f6d82000-f6da1fff r--         0     20000  /dev/__properties__/u:object_r:logd_prop:s0
f6da2000-f6dc1fff r--         0     20000  /dev/__properties__/u:object_r:default_prop:s0
f6dc2000-f6de1fff r--         0     20000  /dev/__properties__/u:object_r:logd_prop:s0
f6de2000-f6de5fff r-x         0      4000  /system/lib/libnetd_client.so (BuildId: 08020aa06ed48cf9f6971861abf06c9d)
f6de6000-f6de6fff r--      3000      1000  /system/lib/libnetd_client.so
f6de7000-f6de7fff rw-      4000      1000  /system/lib/libnetd_client.so
f6dec000-f6e74fff r-x         0     89000  /system/lib/libc++.so (BuildId: 8f1f2be4b37d7067d366543fafececa2) (load base 0x2000)
f6e75000-f6e75fff ---         0      1000
f6e76000-f6e79fff r--     89000      4000  /system/lib/libc++.so
f6e7a000-f6e7afff rw-     8d000      1000  /system/lib/libc++.so
f6e7b000-f6e7bfff rw-         0      1000  [anon:.bss]
f6e7c000-f6efdfff r-x         0     82000  /system/lib/libc.so (BuildId: d189b369d1aafe11feb7014d411bb9c3)
f6efe000-f6f01fff r--     81000      4000  /system/lib/libc.so
f6f02000-f6f03fff rw-     85000      2000  /system/lib/libc.so
f6f04000-f6f04fff rw-         0      1000  [anon:.bss]
f6f05000-f6f05fff r--         0      1000  [anon:.bss]
f6f06000-f6f0bfff rw-         0      6000  [anon:.bss]
f6f0c000-f6f21fff r-x         0     16000  /system/lib/libcutils.so (BuildId: d6d68a419dadd645ca852cd339f89741)
f6f22000-f6f22fff r--     15000      1000  /system/lib/libcutils.so
f6f23000-f6f23fff rw-     16000      1000  /system/lib/libcutils.so
f6f24000-f6f31fff r-x         0      e000  /system/lib/liblog.so (BuildId: e4d30918d1b1028a1ba23d2ab72536fc)
f6f32000-f6f32fff r--      d000      1000  /system/lib/liblog.so
f6f33000-f6f33fff rw-      e000      1000  /system/lib/liblog.so

Thông thường, một thư viện chia sẻ có ba mục nhập liền kề. Một mã có thể đọc được và tệp thực thi (mã), một thuộc tính chỉ đọc (dữ liệu chỉ đọc) và một thuộc tính chỉ đọc-ghi (dữ liệu có thể biến đổi). Cột đầu tiên hiển thị dải địa chỉ cho liên kết, cột thứ hai các quyền (theo kiểu Unix ls(1) thông thường), cột thứ ba giá trị bù trừ vào tệp (theo hệ thập lục phân), cột thứ tư thể hiện kích thước của khu vực (theo hệ thập lục phân) và cột thứ năm là tệp (hoặc tên khu vực khác).

f6f34000-f6f53fff r-x         0     20000  /system/lib/libm.so (BuildId: 76ba45dcd9247e60227200976a02c69b)
f6f54000-f6f54fff ---         0      1000
f6f55000-f6f55fff r--     20000      1000  /system/lib/libm.so
f6f56000-f6f56fff rw-     21000      1000  /system/lib/libm.so
f6f58000-f6f58fff rw-         0      1000
f6f59000-f6f78fff r--         0     20000  /dev/__properties__/u:object_r:default_prop:s0
f6f79000-f6f98fff r--         0     20000  /dev/__properties__/properties_serial
f6f99000-f6f99fff rw-         0      1000  [anon:linker_alloc_vector]
f6f9a000-f6f9afff r--         0      1000  [anon:atexit handlers]
f6f9b000-f6fbafff r--         0     20000  /dev/__properties__/properties_serial
f6fbb000-f6fbbfff rw-         0      1000  [anon:linker_alloc_vector]
f6fbc000-f6fbcfff rw-         0      1000  [anon:linker_alloc_small_objects]
f6fbd000-f6fbdfff rw-         0      1000  [anon:linker_alloc_vector]
f6fbe000-f6fbffff rw-         0      2000  [anon:linker_alloc]
f6fc0000-f6fc0fff r--         0      1000  [anon:linker_alloc]
f6fc1000-f6fc1fff rw-         0      1000  [anon:linker_alloc_lob]
f6fc2000-f6fc2fff r--         0      1000  [anon:linker_alloc]
f6fc3000-f6fc3fff rw-         0      1000  [anon:linker_alloc_vector]
f6fc4000-f6fc4fff rw-         0      1000  [anon:linker_alloc_small_objects]
f6fc5000-f6fc5fff rw-         0      1000  [anon:linker_alloc_vector]
f6fc6000-f6fc6fff rw-         0      1000  [anon:linker_alloc_small_objects]
f6fc7000-f6fc7fff rw-         0      1000  [anon:arc4random _rsx structure]
f6fc8000-f6fc8fff rw-         0      1000  [anon:arc4random _rs structure]
f6fc9000-f6fc9fff r--         0      1000  [anon:atexit handlers]
f6fca000-f6fcafff ---         0      1000  [anon:thread signal stack guard page]

Kể từ Android 5.0, thư viện C đặt tên cho hầu hết các khu vực được ánh xạ ẩn danh để có ít khu vực bí ẩn hơn.

f6fcb000-f6fccfff rw- 0 2000 [stack:5081]

Khu vực có tên [stack:tid] là các ngăn xếp của các khu vực đã cho luồng.

f6fcd000-f702afff r-x         0     5e000  /system/bin/linker (BuildId: 84f1316198deee0591c8ac7f158f28b7)
f702b000-f702cfff r--     5d000      2000  /system/bin/linker
f702d000-f702dfff rw-     5f000      1000  /system/bin/linker
f702e000-f702ffff rw-         0      2000
f7030000-f7030fff r--         0      1000
f7031000-f7032fff rw-         0      2000
ffcd7000-ffcf7fff rw-         0     21000
ffff0000-ffff0fff r-x         0      1000  [vectors]

Việc bạn thấy [vector] hay [vdso] tuỳ thuộc vào cấu trúc. ARM sử dụng [vector], trong khi tất cả kiến trúc khác đều sử dụng [vdso].