2015-01-07 10 views
8

में अलग ऑफसेट मैं अपने कार्यक्रम में किसी बिंदु पर एक स्टैक ट्रेस बना देता हूं। एक बार libc के backtrace_symbols() फ़ंक्शन और libunwind से एक बार।libc के backtrace_symbols() और libunwind के unw_ce_proc_name()

backtrace_symbols() उत्पादन:

/home/jj/test/mylib.so(+0x97004)[0x7f6b47ce9004] 

unw_get_proc_name() उत्पादन:

ip: 0x7f6b47ce9004, offset: 0x458e4 

यहां आप देख अनुदेश सूचक पता (0x7f6b47ce9004) एक ही है और सही है कि । समारोह एक मैं unw_get_proc_name() (0x458e4) से प्राप्त backtrace_symbols() भी सही है लेकिन नहीं से 0x97004 ऑफसेट।

क्या किसी के पास कोई संकेत है कि यहां क्या हो रहा है और ऑफसेट में यह अंतर क्या हो सकता है?)

पश्व-अनुरेखन (:

दोनों ही तरीकों से एक ऐसी ही निम्न उदाहरण की तरह कोड का उपयोग

void *array[10]; 
size_t size; 

size = backtrace(array, 10); 
backtrace_symbols_fd(array, size, STDERR_FILENO); 

libunwind:

unw_cursor_t cursor; 
unw_context_t context; 

unw_getcontext(&context); 
unw_init_local(&cursor, &context); 

while (unw_step(&cursor) > 0) { 
    unw_word_t offset, pc; 
    char  fname[64]; 

    unw_get_reg(&cursor, UNW_REG_IP, &pc); 

    fname[0] = '\0'; 
    (void) unw_get_proc_name(&cursor, fname, sizeof(fname), &offset); 

    printf ("%p : (%s+0x%x) [%p]\n", pc, fname, offset, pc); 
} 
+0

आप unw_get_proc_name से वापसी मूल्य की जांच नहीं कर रहे हैं। शायद यह सफल नहीं है और एक त्रुटि कोड देता है?ऐसा प्रतीत नहीं होता है, लेकिन आईएमओ आपको अभी भी करना चाहिए। इसके अलावा आप बैकट्रैक() के लिए printf नहीं दिखा रहे हैं। Libunwind के लिए एक सुझाव दे सकता है कि आपके प्रिंटफ्स गलत तरीके से हैं। – Krzak

उत्तर

1

मुझे लगता है कि unw_get_proc_name गणना एक से ऑफसेट अज्ञात आंतरिक फ्रेम।

उदाहरण के लिए:

void f() { 
    int i; 
    while (...) { 
    int j; 
    } 
} 

सूचना वहाँ पाश ब्लॉक के अंदर एक चर घोषणा है। इस मामले में (और अनुकूलन के स्तर के आधार पर), कंपाइलर लूप के लिए एक फ्रेम (और संबंधित अनदेखी जानकारी) बना सकता है। नतीजतन, unw_get_proc_name फ़ंक्शन की शुरुआत के बजाय इस लूप से ऑफसेट की गणना करें।

यह unw_get_proc_name आदमी पेज में समझाया गया है:

नोट प्रक्रिया के नाम और साधारण लेबल के बीच भेद करने के लिए कोई विश्वसनीय तरीका है कि वहाँ कुछ प्लेटफार्मों पर। इसके अलावा, यदि प्रतीक जानकारी किसी प्रोग्राम से छीन ली गई है, तो प्रक्रिया नाम पूरी तरह से अनुपलब्ध हो सकते हैं या गतिशील प्रतीक तालिका के माध्यम से निर्यात किए गए लोगों तक ही सीमित हो सकते हैं। ऐसे मामलों में, unw_get_proc_name() किसी लेबल या पूर्ववर्ती (आस-पास) प्रक्रिया का नाम वापस कर सकता है।

आप फिर से लेकिन अलग करना बिना परीक्षण करने के लिए कोशिश कर सकते हैं अपनी बाइनरी (के बाद से unw_get_proc_name फ़ंक्शन का नाम ढूँढने में सक्षम नहीं है, मुझे लगता है कि अपने द्विआधारी छीन जाता है)।

+0

दस्तावेज में उस वाक्य को देखा और यह समझ में आता है। लेकिन बैकट्रैक() फिर असली ऑफसेट की गणना करने में सक्षम क्यों है? मुझे लगता है कि मेरी समस्या किसी अन्य कारण से संबंधित है। – tur1ng

+0

खैर ... मैं अंत में खुद को एक ही प्रश्न पूछता हूं ... :-(मुझे केवल एक चीज है जो i386/x86_64 पर है, या तो बैकट्रैक ('libgcc_s.so' का उपयोग करके) और 'libunwind' .eh_frame जानकारी पर निर्भर करता है। नतीजतन, ये अंतर 'libunwind' और 'libgcc_s' के कार्यान्वयन से आते हैं। जबकि' libunwind' स्पष्ट रूप से समस्या का पर्दाफाश करता है, मुझे इसके बारे में 'libgcc_s.so' में कोई संदर्भ नहीं मिलता है। – Jezz

संबंधित मुद्दे