2013-09-08 10 views
5

आदमी पेज के लिए प्रतीकों पा सकते हैं, लिनक्स पर backtrace() समारोह का कहना है:वैकल्पिक है कि स्थिर कार्यों

ध्यान दें कि "स्थिर" कार्यों के नाम उजागर नहीं कर रहे हैं, और जीता बैकट्रैस में उपलब्ध नहीं होगा।

हालांकि, डिबगिंग प्रतीकों के साथ सक्षम (-g), addr2line और gdb जैसे कार्यक्रमों अभी भी स्थिर कार्यों के नाम मिल सकता है। प्रक्रिया के भीतर से प्रोग्रामिक रूप से स्थैतिक कार्यों के नाम प्राप्त करने का कोई तरीका है?

उत्तर

2

हां, उदाहरण के लिए अपने स्वयं के निष्पादन योग्य (/proc/self/exe) की जांच करके वास्तविक प्रतीकों को स्वयं पार्स करने के लिए libbfd या ईएलएफ फ़ाइल पार्सिंग लाइब्रेरी। अनिवार्य रूप से, आप सी कोड इस तरह

env LANG=C LC_ALL=C readelf -s executable | awk '($5 == "LOCAL" && $8 ~ /^[^_]/ && $8 !~ /\./)' 

कुछ के बराबर जहाँ तक मुझे पता के रूप में करता है लिखते हैं, लिनक्स (<dlfcn.h>) में गतिशील लिंकर इंटरफ़ेस स्थिर (स्थानीय) प्रतीकों के लिए पतों वापस नहीं करता है।

आपके प्रोग्राम से readelf या objdump निष्पादित करने के लिए एक सरल और सुंदर मजबूत दृष्टिकोण है। ध्यान दें कि आप उन्हें /proc/self/exe छद्म-फ़ाइल पथ नहीं दे सकते हैं, क्योंकि यह हमेशा प्रक्रिया को अपने निष्पादन योग्य को संदर्भित करता है। इसके बजाए, आपको उदाहरण का उपयोग करना होगा। वर्तमान निष्पादन योग्य के लिए एक गतिशील आवंटित पूर्ण पथ प्राप्त करने के लिए realpath("/proc/self/exe", NULL) आप आदेश को आपूर्ति कर सकते हैं। आप निश्चित रूप से यह सुनिश्चित करना चाहते हैं कि पर्यावरण में LANG=C और LC_ALL=C शामिल है, ताकि कमांड का आउटपुट आसानी से पारदर्शी हो (और वर्तमान उपयोगकर्ता पसंदीदा भाषा के लिए स्थानीयकृत नहीं है)। यह थोड़ा सा झुकाव महसूस कर सकता है, लेकिन इसे केवल binutils पैकेज को काम पर स्थापित करने की आवश्यकता है, और आपको नवीनतम कार्यक्रमों को बनाए रखने के लिए अपने प्रोग्राम या लाइब्रेरी को अपडेट करने की आवश्यकता नहीं है, इसलिए मुझे लगता है कि यह समग्र रूप से एक बहुत अच्छा दृष्टिकोण है ।

क्या आपको एक उदाहरण चाहिए?

इसे आसान बनाने का एक तरीका है संकलन समय पर प्रतीक जानकारी के साथ अलग-अलग सरणी उत्पन्न करना। मूल रूप से, के बाद वस्तु फ़ाइलों उत्पन्न कर रहे हैं, एक अलग स्रोत फ़ाइल गतिशील objdump या readelf संबंधित वस्तु फ़ाइलों पर चल रहा है, निर्यात एक साधारण खोज समारोह के साथ

const struct { 
    const char *const name; 
    const void *const addr; 
} local_symbol_names[] = { 
    /* Filled in using objdump or readelf and awk, for example */ 
    { NULL, NULL } 
}; 

शायद करने के लिए नाम और संकेत दिए गए समान की एक सरणी पैदा करने से उत्पन्न होता है एक हेडर फ़ाइल में, ताकि अंतिम निष्पादन योग्य लिंक होने पर, यह स्थानीय प्रतीकों की सरणी को आसानी से और कुशलता से एक्सेस कर सके।

यह कुछ डेटा डुप्लिकेट करता है, क्योंकि वही जानकारी पहले ही निष्पादन योग्य फ़ाइल में है, और यदि मुझे सही याद है, तो आपको पहले अंतिम निष्पादन योग्य को प्रतीकों के वास्तविक पते प्राप्त करने के लिए स्टब सरणी से लिंक करना होगा, और फिर प्रतीक सरणी के साथ रिलिकिंक करें, इसे संकलन समय पर परेशानी का थोड़ा सा बना दें .. लेकिन यह binutils पर रन-टाइम निर्भरता रखने से बचाता है।

3

यदि आपके निष्पादन योग्य (और लिंक किए गए पुस्तकालय) डिबगिंग जानकारी के साथ संकलित किए गए हैं (यानी।gcc या g++ करने के लिए -g ध्वज के साथ) तो आप इस्तेमाल कर सकते हैं इयान टेलर की libbacktrace (घोषणा here) जीसीसी अंदर से - अपने कोड here

कि पुस्तकालय (BSD मुफ्त सॉफ्टवेयर लाइसेंस प्राप्त देखें) निष्पादनयोग्य से DWARF डिबग जानकारी और साझा पुस्तकालयों जुड़ा हुआ उपयोग कर रहा है प्रक्रिया द्वारा। इसकी README फ़ाइल देखें।

सावधान रहें कि यदि आप अनुकूलन के साथ संकलन, कुछ कार्यों inlined किया जा सकता है (यहां तक ​​कि स्पष्ट रूप से किया जा रहा बिना स्रोत कोड में टैग inline, और static inlined कार्यों किसी भी उचित ही कोड नहीं हो सकता)। फिर बैकट्रैसिंग उनके बारे में ज्यादा नहीं बताएगा।

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