2015-04-09 15 views
5

Trước hết: câu hỏi này đã được hỏi một vài lần và một số câu trả lời hữu ích, nhưng không có câu trả lời nào cung cấp giải pháp làm việc. Tôi bắt đầu bằng cách thử mã từ this answer. Điều đáng ngạc nhiên là nó có một vấn đề lớn: cách duy nhất để gọi mã này tôi có thể nghĩ là xử lý SIGSEGV, và nó có ngăn xếp riêng của nó - vì vậy tôi không thể nhận được chồng thực sự của ứng dụng bị hỏng của tôi giống như cái đó.Bắt dấu vết ngăn xếp trên Android NDK

Sau đó, tôi đã thử kết hợp this answer. Nó tốt hơn một chút - nó mang lại mục đầu tiên của ngăn xếp (phương thức xảy ra sự cố). Nhưng đó là trong - không có backtrace thực tế. Vì vậy, ngay sau khi vụ tai nạn xảy ra bên trong thư viện của bên thứ ba (hoặc thư viện chuẩn), thông tin này là vô nghĩa.

Làm cách nào để cải thiện thêm mã và cuối cùng nhận được dấu vết ngăn xếp cho ứng dụng bị lỗi kém của tôi?

P. S. Đã thử nghiệm trên Android 4.0.3 và Android 5.0, cho đến nay, hành vi là như nhau. Tôi muốn hỗ trợ ít nhất 5.0 và các phiên bản trước đây như 4.3-4.4.

+0

Chỉ cần rõ ràng: bạn đang cố gắng viết trình xử lý sự cố trong ứng dụng để ghi lại dấu vết ngăn xếp sau khi lỗi? Trình xử lý tín hiệu không có ngăn xếp riêng của nó trừ khi 'sigaltstack' được sử dụng, mặc dù có thể ngăn xếp ngăn xếp không biết cách bước qua khung ngăn xếp tín hiệu. Mục tiêu cuối cùng của bạn là gì? ACRA cho NDK? – fadden

+0

@fadden: đúng, tôi muốn nhận dấu vết ngăn xếp sau dấu vết. Nó sẽ xuất hiện như là trình xử lý tín hiệu có ngăn xếp riêng của nó, nó bắt nguồn từ 'art :: handleFault' hoặc một cái gì đó tương tự (trên 5.0). ACRA là gì? –

+0

Tôi nghe một tin đồn rằng ART đã cung cấp bộ xử lý tín hiệu riêng của mình bị xích vào người xử lý trước đó; nếu đó là trường hợp, bạn sẽ thấy hành vi khác nhau trên 5.0 so với 4.x với Dalvik. Đây là trên đầu trang của trình xử lý tín hiệu được cài đặt hệ thống, cung cấp trình xử lý hệ thống debuggerd (kết quả này sẽ xuất ra dấu vết ngăn xếp tới tệp nhật ký sau khi xảy ra lỗi gốc). Tôi không nghĩ rằng lib pthread Android đang sử dụng 'sigaltstack', nhưng tôi đã không kiểm tra trong một thời gian. Bạn sẽ cần phải đào SP ra khỏi khung tín hiệu và sử dụng nó như là điểm thư giãn của bạn, thay vì SP hiện tại. – fadden

Trả lời

1

Bạn đã thử thư viện coffeecatch?

Đây là bộ thu tín hiệu JNI cho phép chuyển tín hiệu SIGSEGV (+) thành ngoại lệ java với dấu chéo jni/java hỗn hợp. Nó hoạt động lên đến API-19, nhưng tôi không có cơ hội để kiểm tra nó trên API> 19. Nó cung cấp các địa chỉ chương trình có thể được chuyển tới addr2line để lấy các tham chiếu cuối cùng tới một nguồn.

Mã mẫu:

#include "coffeejni.h" 
#include "coffeecatch.h" 

void MyClass::foo(JNIEnv *env, int arg1, int arg2) { 
    .... 
    int rc; 
    COFFEE_TRY_JNI(env, rc = crashInside(arg1, arg2)); 
    .... 
} 

Ví dụ về các dấu vết:

F/myapp (24535): "DESIGN ERROR": thread=t1 
F/myapp (24535): java.lang.Error: signal 11 (Address not mapped to object) at address 0xdeadbaad [at libc.so:0x18282] 
F/myapp (24535): at com.example.NativeSupport.nsc(Native Method) 
F/myapp (24535): at com.example.NativeSupport.nsc_quiet(NativeSupport.java:328) 
F/myapp (24535): at com.example.NativeSupport.loop(NativeSupport.java:287) 
F/myapp (24535): at com.example.NativeSupport.access$2(NativeSupport.java:274) 
F/myapp (24535): at com.example.NativeSupport$2.run(NativeSupport.java:124) 
F/myapp (24535): at java.lang.Thread.run(Thread.java:856) 
F/myapp (24535): Caused by: java.lang.Error: signal 11 (Address not mapped to object) at address 0xdeadbaad [at libc.so:0x18282] 
F/myapp (24535): at system.lib.libc_so.0x18282(Native Method) 
F/myapp (24535): at system.lib.libc_so.0xdc04(abort:0x4:0) 
F/myapp (24535): at data.data.example.lib.libexample_so.0xf147(Native Method) 
F/myapp (24535): at data.data.example.lib.libexample_so.0x12d1b(Native Method) 
F/myapp (24535): at data.data.example.lib.libexample_so.0x1347b(Native Method) 
F/myapp (24535): at data.data.example.lib.libexample_so.0x13969(Native Method) 
F/myapp (24535): at data.data.example.lib.libexample_so.0x13ab3(Native Method) 
F/myapp (24535): at data.data.example.lib.libexample_so.0x17a9b(Native Method) 
F/myapp (24535): at system.lib.libdvm_so.0x1f4b0(dvmPlatformInvoke:0x70:0) 
F/myapp (24535): at system.lib.libdvm_so.0x4dfa5(dvmCallJNIMethod(unsigned int const*, JValue*, Method const*, Thread*):0x164:0) 
F/myapp (24535): at system.lib.libdvm_so.0x28920(Native Method) 
F/myapp (24535): at system.lib.libdvm_so.0x2d0b0(dvmInterpret(Thread*, Method const*, JValue*):0xb4:0) 
F/myapp (24535): at system.lib.libdvm_so.0x5f599(dvmCallMethodV(Thread*, Method const*, Object*, bool, JValue*, std::__va_list):0x110:0) 
F/myapp (24535): at system.lib.libdvm_so.0x5f5c3(dvmCallMethod(Thread*, Method const*, Object*, JValue*, ...):0x14:0) 
F/myapp (24535): at system.lib.libdvm_so.0x549eb(Native Method) 
F/myapp (24535): at system.lib.libc_so.0x12dd0(__thread_entry:0x30:0) 
F/myapp (24535): at system.lib.libc_so.0x12534(pthread_create:0xac:0) 

Native (JNI) một phần của stack trace là:

F/myapp (24535): at data.data.example.lib.libexample_so.0xf147(Native Method) 
F/myapp (24535): at data.data.example.lib.libexample_so.0x12d1b(Native Method) 
F/myapp (24535): at data.data.example.lib.libexample_so.0x1347b(Native Method) 
F/myapp (24535): at data.data.example.lib.libexample_so.0x13969(Native Method) 
F/myapp (24535): at data.data.example.lib.libexample_so.0x13ab3(Native Method) 
F/myapp (24535): at data.data.example.lib.libexample_so.0x17a9b(Native Method) 

Và cuối cùng có được một humanoid- backtrace có thể đọc được:

cd android-ndk/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin 
./arm-linux-androideabi-addr2line -e /home/joe/myproj/obj/local/armeabi-v7a/libexample.so 0xf147 0x12d1b 0x1347b 0x13969 0x13ab3 0x17a9b 
+1

Tôi đã thử nó và không thể làm những gì tôi muốn. Nhưng tôi cũng không tìm được cách để có được ngăn xếp (có thể là địa chỉ hoặc ký hiệu). Có phải trong API Coffecatch không? Bạn có mã ví dụ nào không? Ngoài ra, các địa chỉ có tương thích với 'dladdr' không? –

+0

Xem câu trả lời đã thay đổi của tôi ở trên. + hãy chắc chắn rằng bạn sử dụng phiên bản mới nhất từ ​​git, các phiên bản cũ không hoạt động với ndk hiện đại. – Fvwm

+0

Cảm ơn. Tôi đã thấy rằng nó có thể ném một ngoại lệ Java với một số loại dấu vết ngăn xếp, nhưng tôi cần những địa chỉ đó trong khối 'COFFEE_CATCH', sẽ khó sửa đổi nguồn coffecatch như thế nào để truy cập vào danh sách địa chỉ đó? Ngoài ra, phải quấn từng phương thức trong 'try/catch' là một trở ngại lớn. Tôi có hàng trăm (trên 100, đó là chắc chắn) phương pháp bản địa, và mỗi phải được sửa đổi. Trình xử lý tín hiệu toàn cầu vô cùng tiện lợi hơn ... miễn là nó hoạt động. –

Các vấn đề liên quan