2010-06-30 10 views
22

मैं हाल ही में, एक निश्चित साझा लाइब्रेरी (ELF) x86-64 वास्तुकला को निशाना बनाने का निर्माण किया गया था इस तरह बनाम:अंतर: 86 x86-64

g++ -o binary.so -shared --no-undefined ... -lfoo -lbar 

यह निम्न त्रुटि के साथ विफल:

relocation R_X86_64_32 against `a local symbol' can not be used when making a shared object; recompile with -fPIC

बेशक, इसका मतलब है कि मुझे इसे स्थिति-स्वतंत्र कोड के रूप में पुनर्निर्माण करने की आवश्यकता है, इसलिए यह साझा लाइब्रेरी में जोड़ने के लिए उपयुक्त है।

लेकिन यह बिल्कुल उसी निर्माण तर्क के साथ x86 पर पूरी तरह से अच्छा काम करता है। तो सवाल यह है कि x86-64 से अलग x86 पर स्थानांतरण कैसे है और मुझे पूर्व में -fPIC के साथ संकलन करने की आवश्यकता क्यों नहीं है?

+1

मैंने इसे कभी नहीं समझा है। यदि संकलक आपको बता सकता है कि स्वचालित रूप से किस विकल्प का उपयोग करना है, तो यह आवश्यक है कि आप इसे सही तरीके से संचालित करने के लिए जादू शब्द कहें? Grrr .. –

+0

@ बिली ओनेल, अब मुझे विश्वास है कि यह लीकी अबास्ट्रक्शन का मामला है। वे वैश्विक डेटा को लोड करने में भिन्न होते हैं, जो प्रभावित करता है कि पीआईसी की आवश्यकता है या नहीं। –

+0

मैं अंतर की आवश्यकता को समझता हूं। मुझे समझ में नहीं आता है कि आपको कंपाइलर को ऐसा करने के लिए एक स्विच देने की आवश्यकता क्यों है। –

उत्तर

16

मैं a nice and detailed explanation पाया है, जो करने के लिए नीचे फोड़े:

  1. x86-64 का उपयोग करता है आईपी रिश्तेदार वैश्विक डेटा लोड करने के ऑफसेट, x86-32 नहीं कर सकते हैं, तो यह एक वैश्विक ऑफसेट dereferences।
  2. आईपी-रिश्तेदार ऑफसेट साझा पुस्तकालयों के लिए काम नहीं करता है, क्योंकि वैश्विक प्रतीकों को ओवरराइड किया जा सकता है, इसलिए x86-64 पीआईसी के साथ निर्मित नहीं होने पर टूट जाता है।
  3. यदि पीआईसी के साथ बनाया गया x86-64, आईपी-रिश्तेदार ऑफसेट डीरेंसेंस अब को GOT प्रविष्टि पर एक सूचक प्राप्त करता है, जिसे तब संदर्भित किया जाता है।
  4. x86-32, हालांकि, पहले से ही वैश्विक ऑफसेट की कमी का उपयोग करता है, इसलिए इसे सीधे जीओटी प्रविष्टि में बदल दिया जाता है।
4

यह एक कोड मॉडल मुद्दे है। डिफ़ॉल्ट रूप से, स्थिर कोड यह मानते हुए बनाया जाता है कि पूरा प्रोग्राम स्मृति पता स्थान के निचले 2 जी भाग में रहेगा। साझा पुस्तकालयों के लिए कोड को किसी अन्य मेमोरी मॉडल, या तो पीआईसी, या -एमसीएमडेल = बड़े के साथ संकलित करने की आवश्यकता है जो उस धारणा के बिना संकलित होगा।

ध्यान दें कि -एमसीएमडेल = बड़े पुराने जीसीसी संस्करण में लागू नहीं किया गया है (यह 4.4 में है, यह 4.2 में नहीं है, मुझे 4.3 के लिए पता नहीं है)। ।

+0

यह समझ में आता है - 32 बिट पूर्ण पता को रिश्तेदार स्थानांतरित नहीं किया जा सकता है, क्योंकि लाइब्रेरी का लोड पता> 2 जीबी हो सकता है। – caf

+0

हां, मैं समझता हूं कि जंप ऑफसेट की गणना करने में स्थिति-स्वतंत्र कोड को अलग करने की आवश्यकता है, लेकिन मुझे यह समझने में संघर्ष है कि यह * * * fpic' के बिना x86 * पर क्यों काम करता है। –

+0

@ एलेक्स, डायनामिक लोडर कुछ को संभालने में सक्षम है लेकिन सभी स्थानांतरण रिकॉर्ड नहीं है और जिसके कारण कुछ स्थानांतरण रिकॉर्ड प्रबंधित नहीं किए जाते हैं, यह है कि वे ऐसी स्थिति मानते हैं जो सत्य नहीं है। केवल एक गैर पीआईसी 32 बिट मेमोरी मॉडल है और वह मॉडल केवल स्थानांतरित स्थानांतरण रिकॉर्ड का उपयोग करता है। कई गैर पीआईसी 64 बिट मेमोरी मॉडल हैं, कुछ गतिशील स्थानांतरण के साथ संगत हैं, कुछ नहीं। यदि आप gc 4.4 के साथ -mcmodel = बड़े का उपयोग करते हैं, तो आपको -fpic की आवश्यकता नहीं है। – AProgrammer

0

यह एबीआई लोगों ने हमें लगाए जाने की पूरी तरह से मनमानी आवश्यकता है। कोई तर्कसंगत कारण नहीं है कि x86_64 पर डायनामिक लिंकर गैर-पीआईसी पुस्तकालयों का समर्थन नहीं कर सका। हालांकि, चूंकि x86_64 इस तरह के भयानक रजिस्टर दबाव में नहीं है क्योंकि x86 (और पीआईसी के लिए बेहतर सुविधाएं हैं), मुझे पीआईसी का उपयोग न करने के किसी भी महत्वपूर्ण कारण के बारे में पता नहीं है।

+0

छोड़कर यह गैर-पीआईसी पुस्तकालयों का समर्थन करता है। यह कुछ रिलायंस रिकॉर्ड्स का समर्थन नहीं करता है क्योंकि आमतौर पर इस तरह से लोड किया जाता है कि इन स्थानांतरण रिकॉर्ड्स द्वारा किए गए अनुमान मान्य नहीं हैं, लेकिन यदि आप उनका उपयोग नहीं करते हैं, तो कोई समस्या नहीं है। – AProgrammer

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