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ả crasher
và crasher64
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]
.