2013-08-02 4 views
6

मैं डीबगिंग उद्देश्य के लिए अपने एंड्रॉइड एनडीके ऐप में SIGSEGV जैसे संकेतों को पकड़ने की कोशिश कर रहा हूं। इसके लिए, मैंने एक सिग्नेशन स्थापित किया है जिसे बुलाया जाता है।एंड्रॉइड _Unwind_Backtrace सिग्नेशन के अंदर

अब मैं कॉल का ढेर पाने की कोशिश कर रहा हूं। समस्या यह है कि _Unwind_Backtrace केवल वर्तमान स्टैक पर काम करता है और सिग्नेशन अपने स्वयं के ढेर के अंदर चलता है।

तो, क्या सिग्नल प्राप्त करने वाले निष्पादन सूचक के ढेर को पाने का कोई तरीका है? (मूल रूप से _Unwind_Backtrace बता वर्तमान की तुलना में एक और स्टैक के लिए?)

मैं कहना चाहिए कि:

  • backtrace() का उपयोग करना और backtrace_symbols() एक विकल्प के बाद से उन कार्यों एंड्रॉयड NDK

  • में नहीं दिया जाता है नहीं है
  • मैं अपने स्थानीय उपकरणों पर दुर्घटनाओं की जांच के लिए जीडीबी का उपयोग कर रहा हूं। मैं जीडीबी को प्रतिस्थापित नहीं करना चाहता, मैं क्लाइंट से अर्थपूर्ण स्टैक निशान प्राप्त करने में सक्षम होना चाहता हूं जब मैं उसे टेस्ट बिल्ड भेजता हूं।

संपादित करें: मैं के रूप में FADDEN द्वारा प्रस्तावित लेकिन जब मैं का उपयोग यह unwind_backtrace_signal_arch समारोह है, मैं एक अजीब पश्व-अनुरेखन कि दुर्घटना का प्रतिनिधित्व नहीं करते प्राप्त प्रणाली/कोर से Android के libcorkscrew उपयोग करने की कोशिश की है।

उत्तर

3

आप pthread_getattr_np और pthread_attr_getstack के साथ स्टैक बेस पता प्राप्त कर सकते हैं, लेकिन आपको वास्तव में क्रैश के समय पीसी और एसपी की आवश्यकता है। लिनक्स पर, आप इन्हें ucontext से बाहर खींच सकते हैं।

यदि आप सिग्नल हैंडलर को कॉन्फ़िगर करते समय SA_SIGINFO ध्वज सेट करते हैं, तो आपके हैंडलर फ़ंक्शन को एक के बजाय तीन तर्क मिलते हैं। तीसरा void* तर्क ucontext सूचक है। this question के स्वीकृत उत्तर थोड़ा और बताते हैं।

एक बार जब आप सब कुछ प्राप्त कर लें तो आप ढेर को खोल सकते हैं। यदि आपको एनडीके द्वारा प्रदान की जाने वाली सीमाओं के बाहर कदम उठाने में कोई फर्क नहीं पड़ता है, तो एंड्रॉइड के libcorkscrew में ऐसे फ़ंक्शन हैं जो ढेर को खोल सकते हैं और परिणामों को आउटपुट कर सकते हैं। लॉग फ़ाइल में मूल क्रैश को डंप करने के लिए डीबगर डीमन द्वारा इसका उपयोग किया जाता है।

यह जानना उपयोगी हो सकता है कि डीबगर द्वारा लॉग किए गए देशी क्रैश /data/tombstones/ में स्टैक डंप उत्पन्न करते हैं। फ़ाइल अनुमतियां इसे सामान्य ऐप्स के लिए पहुंच योग्य नहीं देती हैं, लेकिन एक संशोधित डिवाइस पर आप इन्हें बाहर खींच सकते हैं और उन्हें भेज सकते हैं।

+3

मैंने खोज की है लेकिन मैं आपके उत्तर से यह नहीं समझ सकता कि कैसे एक ucontext सूचक के साथ एक ढेर को खोलना है। क्या आप कोई उदाहरण देते हैं? –

+0

ucontext.h बायोनिक में प्रदान नहीं किया गया है, जो एंड्रॉइड का उपयोग करता है। मुझे इस प्लेटफॉर्म पर इस संरचना से जानकारी खींचने में भी बहुत दिलचस्पी है जहां संरचना मौजूद नहीं है। क्या मुझे विश्वास है कि यह वही सदस्य आदेश है जो लिनक्स में है, और बस पीसी और एसपी को स्मृति पते से बाहर खींचें? – codetaku

+0

ucontext।एच बायोनिक का हिस्सा है, हालांकि यह एनडीके से उपलब्ध नहीं हो सकता है (https://android.googlesource.com/platform/bionic/+/kitkat-release/libc/kernel/arch-arm/asm/ucontext.h देखें)। ऐसा नहीं है कि यह बहुत अच्छा करता है - इसकी बजाय सामान्य परिभाषा है। AFAIK में ucontext के लिए कोई एंड्रॉइड-विशिष्ट अनुकूलन नहीं है। – 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); 
} 
संबंधित मुद्दे