2013-08-02 14 views
6

Tôi đang cố gắng nắm bắt các tín hiệu như SIGSEGV trong ứng dụng NDK của Android để gỡ lỗi. Đối với điều đó, tôi đã thiết lập một sigaction được gọi là.Android _Unwind_Backtrace bên trong sigaction

Tôi hiện đang cố gắng thu thập cuộc gọi. Vấn đề là _Unwind_Backtrace chỉ hoạt động trên stack và sigaction hiện tại chạy bên trong ngăn xếp của chính nó.

Vì vậy, có cách nào để có được ngăn xếp của con trỏ thực hiện nhận tín hiệu không? (Về cơ bản nói _Unwind_Backtrace để thư giãn ngăn xếp khác so với hiện tại?)

Tôi phải chỉ ra rằng:

  • Sử dụng backtrace()backtrace_symbols() không phải là một lựa chọn từ những chức năng này không được giao trong Android NDK

  • Tôi đang sử dụng GDB để điều tra sự cố trên thiết bị cục bộ của mình. Tôi không muốn thay thế GDB, tôi muốn có thể nhận được dấu vết ngăn xếp có ý nghĩa từ khách hàng khi tôi gửi cho anh ta một bản dựng thử nghiệm.

EDIT: Tôi đã cố gắng sử dụng libcorkscrew Android từ hệ thống/lõi theo đề nghị của Fadden nhưng khi tôi sử dụng chức năng của nó unwind_backtrace_signal_arch, tôi nhận được một vết lùi lạ mà không đại diện cho các vụ tai nạn.

Trả lời

3

Bạn có thể lấy địa chỉ cơ sở ngăn xếp với pthread_getattr_nppthread_attr_getstack, nhưng những gì bạn thực sự cần là PC và SP tại thời điểm xảy ra sự cố. Trên Linux, bạn có thể kéo chúng ra khỏi số ucontext.

Nếu bạn đặt cờ SA_SIGINFO khi bạn định cấu hình trình xử lý tín hiệu, hàm xử lý của bạn nhận được ba đối số thay vì một đối số. Đối số thứ ba void* là con trỏ ucontext. Câu trả lời được chấp nhận cho this question giải thích thêm một chút.

Khi bạn đã có tất cả những gì bạn có thể thư giãn ngăn xếp. Nếu bạn không phiền khi bước ra ngoài giới hạn những gì NDK cung cấp, thì libcorkscrew của Android có các chức năng có thể làm giảm các ngăn xếp và xuất kết quả. Điều này được sử dụng bởi trình gỡ lỗi trình gỡ lỗi để đổ các lỗi gốc vào tệp nhật ký.

Có thể hữu ích khi biết rằng các sự cố nguyên bản được ghi lại bởi trình gỡ rối tạo ra các vùng xếp chồng trong /data/tombstones/. Các quyền của tệp cho phép nó không thể truy cập được vào các ứng dụng thông thường, nhưng trên một thiết bị đã sửa đổi, bạn có thể kéo chúng ra và gửi chúng.

+3

Tôi đã tìm kiếm nhưng tôi không thể tìm ra câu trả lời của bạn cách thư giãn một ngăn xếp bằng con trỏ ucontext. Bạn có ahave ví dụ nào không? –

+0

ucontext.h không được cung cấp trong bionic, đó là những gì android sử dụng. Tôi cũng rất quan tâm đến cách kéo thông tin ra khỏi cấu trúc này trên một nền tảng mà cấu trúc không tồn tại. Tôi có nên tin tưởng nó là cùng một thành viên đặt hàng như trong Linux, và chỉ cần rút ra PC và SP theo địa chỉ bộ nhớ? – codetaku

+0

ucontext.h là một phần của bionic, mặc dù nó có thể không có sẵn từ NDK (xem https://android.googlesource.com/platform/bionic/+/kitkat-release/libc/kernel/arch-arm/asm/ucontext.h). Không phải là nó tốt lắm - nó có một định nghĩa khá chung chung. AFAIK không có tùy chỉnh dành riêng cho Android cho ucontext. – fadden

2

Trong tiêu chuẩn thực hành của tôi _Unwind_Backtrace thất bại trong việc chuyển sang ngăn xếp tín hiệu trước.

Tôi đã quản lý để nhận một số ngăn xếp tín hiệu trước bằng cách gọi nội bộ libgcc __gnu_Unwind_Backtrace - nó có thêm agrument là "giá trị đăng ký hiện tại" - vì vậy nó hoạt động trên stack, chứ không phải trên stack hiện tại.

//definitions copied from arm-specific libgcc 4.8 sources. 
struct core_regs 
{ 
    _uw r[16]; 
}; 

typedef struct 
{ 
    _uw demand_save_flags; 
    struct core_regs core; 
} phase2_vrs; 

extern "C" 
_Unwind_Reason_Code 
__gnu_Unwind_Backtrace(_Unwind_Trace_Fn trace, void * trace_argument, 
       phase2_vrs * entry_vrs); 

// Getting backtrace with those definitions 
//istead of _Unwind_Backtrace(tracer, &state); 
if (const ucontext_t* signal_context = last_sigaction_parameter) 
{ 
     phase2_vrs pre_signal_state = {}; 
     pre_signal_state.core = *reinterpret_cast<const core_regs*>(&(signal_context->uc_mcontext.arm_r0)); 
     __gnu_Unwind_Backtrace(tracer, &state, &pre_signal_state); 
} 
Các vấn đề liên quan