2013-08-02 54 views
6

我想在我的Android NDK應用程序中捕獲SIGSEGV等信號以進行調試。爲此,我建立了一個被稱爲的sigaction。Android _Unwind_Backtrace裏面的sigaction

我現在正試圖獲得該通話的堆棧。問題是_Unwind_Backtrace只適用於當前堆棧,sigaction在它自己​​的堆棧中運行。

那麼,有沒有辦法讓接收到信號的執行指針堆棧? (基本上告訴_Unwind_Backtrace放鬆另一個堆比目前?)

我要指出的是:

  • 使用backtrace()backtrace_symbols()是不是因爲這些功能都沒有在Android NDK

  • 交付選項
  • 我正在使用GDB調查本地設備上的崩潰。我不想替換GDB,當我給他發送測試版本時,我希望能夠從客戶端接收到有意義的堆棧跟蹤。

編輯: 使用Android的libcorkscrew從系統/核心所建議的法登,但是當我使用它的unwind_backtrace_signal_arch功能,我得到一個奇怪的回溯不代表死機我都試過了。

回答

3

您可以通過pthread_getattr_nppthread_attr_getstack獲得堆棧基址,但您真正需要的是PC和SP在發生崩潰時的情況。在Linux上,你可以從ucontext中取出這些。

如果您在配置信號處理程序時設置了SA_SIGINFO標誌,則您的處理程序函數會獲取三個參數而不是一個參數。第三個參數void*ucontext指針。 this question接受的答案解釋更多一點。

一旦你有所有可以展開堆棧。如果您不介意跳出NDK提供的界限,Android的libcorkscrew具有可以展開堆棧並輸出結果的功能。 debuggerd守護程序使用該選項將本地崩潰轉儲到日誌文件。

瞭解由debuggerd記錄的本機崩潰在/data/tombstones/中生成堆棧轉儲可能很有用。文件權限使其無法訪問正常的應用程序,但在修改的設備上,您可以將其取出併發送出去。

+3

我已經搜索,但我無法從你的答案中找出如何用ucontext指針展開堆棧。你有沒有例子? –

+0

ucontext.h不是在仿生中提供的,這是android使用的。我也非常感興趣的是如何在結構不存在的平臺上從這個結構中提取信息。我是否應該相信它與Linux中的成員順序相同,只需通過內存地址提取PC和SP? – codetaku

+0

ucontext。h是仿生學的一部分,但它可能不能從NDK獲得(參見https://android.googlesource.com/platform/bionic/+/kitkat-release/libc/kernel/arch-arm/asm/ucontext.h )。並不是說它做得很好 - 它有一個相當通用的定義。 AFAIK沒有針對ucontext的特定於Android的定製。 – fadden

2

在我的練習標準_Unwind_Backtrace未能切換到預信號堆棧。

我已經設法通過調用內部libgcc __gnu_Unwind_Backtrace來獲得一些信號之前的堆棧 - 它有一個額外的「當前註冊表值」 - 因此它在給定的堆棧上運行,而不是在當前的堆棧上運行。

//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); 
}