2011-06-06 17 views
13

पर _Unwind_Backtrace का उपयोग कर fullstacktrace पाने के लिए मैं कोड से SIGSEGV संभाल:कैसे SIGSEGV

int C() 
{ 
    int *i = NULL; 
    *i = 10; // Crash there 
} 

int B() 
{ 
    return C(); 
} 

int A() 
{ 
    return B(); 
} 

int main(void) 
{ 
    struct sigaction handler; 
    memset(&handler,0,sizeof(handler)); 
    handler.sa_sigaction = handler_func; 
    handler.sa_flags = SA_SIGINFO; 
    sigaction(SIGSEGV,&handler,NULL); 
    return(C()); 
} 

कहाँ हैंडलर कोड हैं:

static int handler_func(int signal, siginfo_t info, void* rserved) 
{ 
    const void* stack[MAX_DEPTH]; 
    StackCrowlState state; 
    state.addr = stack; 
    state.count = MAX_DEPTH; 

    _Unwind_Reason_Code code = _Unwind_Backtrace(trace_func,&state); 
    printf("Stack trace count: %d, code: %d\n",MAX_DEPTH - state.count, code); 

    kill(getpid(),SIGKILL); 
} 

static _Unwind_Reason_Code trace_func(void* context, void* arg) 
{ 
    StackCrowlState *state = (StackCrowlState *)arg; 
    if(state->count>0) 
    { 
    void *ip = (void *)_Unwind_GetIP(context); 
    if(ip) 
    { 
     state->addr[0] = ip; 
     state->count--; 
     state->addr++; 
    } 
    } 
    return(_URC_NO_REASON); 
} 

लेकिन trace_func जहां केवल एक बार कहा जाता है, और _Unwind_Backtrace केवल पर कॉल को दर्शाता है। क्या कोड का स्टैकट्रैक प्राप्त करना संभव है जिससे SUSESEGV सिग्नल _Unwind_Backtrace का उपयोग कर सकता है?

thnx

उत्तर

0

बेहतर आप पश्व-अनुरेखन का उपयोग करें और एक संकेत हैंडलर से एक स्टैकट्रेस पाने के लिए backtrace_symbols_fd।

+11

प्लेटफार्मों कि जीसीसी उपयोग करते हैं, और इस प्रकार '_Unwind_Backtrace' है, लेकिन libc जीएनयू नहीं, और इस प्रकार' backtrace' और 'backtrace_symbols_fd' की जरूरत नहीं है पर छोड़कर। –

5

आप सिग्नल ट्रिगरिंग फ़ंक्शन से बैकट्रैक करना चाहते हैं, लेकिन आप सिग्नल हैंडलर फ़ंक्शन से पीछे हटना चाहते हैं। यह दो अलग-अलग ढेर हैं। (ध्यान दें, sigaction में SA_ONSTACK झंडा अपने प्रश्न का कोई वास्ता नहीं है।)

ट्रिगर समारोह के के ढेर सूचक ढूंढने के लिए, हैंडलर की तीसरी पैरामीटर का उपयोग करें, अर्थात शून्य * rserved। आप इस प्रश्न में उत्तर का संदर्भ दे सकते हैं: Getting the saved instruction pointer address from a signal handler

+2

क्या आपको पता है कि सिग्नल हैंडलर के तीसरे तर्क से पुनर्प्राप्त होने के बाद ट्रिगरिंग फ़ंक्शन के स्टैक पॉइंटर के साथ क्या करना है? क्या आप अभी भी _Unwind_Backtrace का उपयोग कर सकते हैं? मेरे पास यह सही समस्या है और मैं वास्तव में समझ नहीं पा रहा हूं कि आपका उत्तर पढ़ने के बाद क्या करना है। – P1r4nh4

+0

यह एक और वर्ष है + बाद में और मुझे यह भी नहीं पता कि इस मामले में क्या करना है ... मैं वास्तव में पुराने स्टैक पॉइंटर के साथ _Unwind_Backtrace कैसे काम करूं? – codetaku

+0

एक और साल और एक ही सवाल: मुझे पता है कि एसपी कैसे प्राप्त करें, लेकिन मुझे नहीं पता कि इसके साथ क्या करना है! –

0

आप इसके बजाय __gnu_Unwind_Backtrace का उपयोग कर सकते हैं। ARM32 के लिए उदाहरण:

typedef struct 
{ 
    uintptr_t r[16]; 
} core_regs; 

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

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

int AndroidGetBackTraceWithContext(VOID **stack, UINT32 size, ucontext_t *ctx) 
{ 
    ANDROID_UNWIND_STATE state; 
    state.count = size; 
    state.stack = stack; 

    // First call stack is current pc 
    state.stack[0] = (VOID *)ctx->uc_mcontext.arm_pc; 
    state.stack++; 
    state.count--; 

    phase2_vrs pre_signal_state; 
    pre_signal_state.demand_save_flags = 0; 
    pre_signal_state.core = *reinterpret_cast<const core_regs*>(&(ctx->uc_mcontext.arm_r0)); 

    // Return value is of no use and might be wrong on some systems 
    __gnu_Unwind_Backtrace(DmpAndroidUnwindCallback, &state, &pre_signal_state); 

    return size - state.count; 
} 
संबंधित मुद्दे