2011-05-23 5 views
33

निम्न त्रुटि समझे:R_X86_64_32S और R_X86_64_64 स्थानांतरण का क्या अर्थ है? जब मैं 64-बिट FreeBSD में एक सी आवेदन संकलित करने के लिए करने की कोशिश की

स्थानांतरण R_X86_64_32S जब एक साझा वस्तु बनाने के लिए इस्तेमाल नहीं किया जा सकता; -fPIC

R_X86_64_32S स्थानांतरण क्या है और क्या R_X86_64_64 है के साथ पुन: संयोजित?

मैंने त्रुटि के बारे में गुमराह किया है, और यह संभव कारण है - अगर कोई यह बता सकता है कि R_X86_64_32S वास्तव में क्या मतलब है तो यह बहुत अच्छा होगा।

+1

संबंधित: Linux distros हाल ही में ** ** स्थिति स्वतंत्र निष्पादनयोग्य सक्षम करने के लिए जीसीसी के लिए डिफ़ॉल्ट रूप से शुरू कर दिया है। किसी भी गैर-पीआईसी कोड को निष्पादन योग्य में जोड़ने का प्रयास करते समय आपको यह त्रुटि मिल जाएगी, जिसमें 'ली $ प्रतीक,% rip),% rdi' के बजाय 'mov $ प्रतीक,% edi' जैसे कुछ का उपयोग किया जाता है। देखें [32-बिट पूर्ण पते अब x86-64 लिनक्स में अनुमति नहीं है?] (Https://stackoverflow.com/questions/43367427/32-bit-absolute-addresses-no-longer-allowed-in-x86-64- लिनक्स) पारंपरिक स्थिति-निर्भर निष्पादन योग्य बनाने के लिए 'gcc -no-pie -fno-pie' का उपयोग करने के बारे में जानकारी के लिए यदि आप यही चाहते हैं। –

उत्तर

28

R_X86_64_32S और R_X86_64_64 amd64 आर्किटेक्चर के लिए संकलित कोड के लिए स्थानांतरण स्थान के नाम हैं। आप उन सभी को amd64 ABI में देख सकते हैं। इसके अनुसार R_X86_64_64 करने के लिए नीचे दिया गया है:

  • R_X86_64 - डायरेक्ट 64 बिट स्थानांतरण

और R_X86_64_32S करने के लिए - सभी के नाम इस

  • 64 लगी होती हैं:

    • R_X86_64 - उपसर्ग
    • 32S - 32 बिट्स को छोटा करने और साइन-विस्तार

    जिसका मूल रूप से अर्थ है कि "इस स्थानांतरण द्वारा इंगित प्रतीक का मूल्य, साथ ही कोई भी जोड़", दोनों मामलों में। R_X86_64_32S के लिए लिंकर तब सत्यापित करता है कि जेनरेट किया गया मान साइन-मूल मूल 64-बिट मान तक फैला हुआ है।

    अब, निष्पादन योग्य फ़ाइल में, कोड और डेटा सेगमेंट को एक निर्दिष्ट आभासी आधार पता दिया जाता है। निष्पादन योग्य कोड साझा नहीं किया जाता है, और प्रत्येक निष्पादन योग्य अपना स्वयं का नया पता स्थान प्राप्त करता है। इसका मतलब है कि संकलक जानता है कि डेटा अनुभाग कहां होगा, और इसे सीधे संदर्भित कर सकता है। दूसरी तरफ, पुस्तकालय केवल यह जान सकते हैं कि उनका डेटा अनुभाग आधार पते से निर्दिष्ट ऑफसेट पर होगा; उस बेस पते का मूल्य केवल रनटाइम पर ही जाना जा सकता है। इसलिए, सभी पुस्तकालयों को कोड के साथ बनाया जाना चाहिए जो इसे किसी भी मामले में निष्पादित नहीं कर सकता है, जहां इसे स्मृति में रखा गया है, जिसे स्थिति स्वतंत्र कोड (या संक्षिप्त के लिए पीआईसी) कहा जाता है।

    अब जब आपकी समस्या का समाधान करने की बात आती है, तो त्रुटि संदेश स्वयं के लिए बोलता है।

  • 2

    इसका मतलब है कि के रूप में आप चाहिए -fPIC ध्वज का उपयोग किए बिना एक साझा वस्तु संकलित:

    gcc -shared foo.c -o libfoo.so # Wrong 
    

    आप

    gcc -shared -fPIC foo.c -o libfoo.so # Right 
    
    ELF मंच के तहत

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

    +0

    मुझे एक ही समस्या है, लेकिन मुझे अभी भी -fPIC के साथ भी त्रुटि मिलती है: 'gcc -std = c99 -Wall -pedantic -shared -fopenmp -fPIC -static test.c -o libtest.so'। कोई विचार क्यों? धन्यवाद! –

    2

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

    +0

    यह समझ में आता है कि एक स्थिर पुस्तकालय '-एफपीआईसी' के बिना बनाया गया होगा, और इस प्रकार कुछ पूर्ण स्थानान्तरण का उपयोग करेगा। इस प्रकार आप उस कोड को एक स्थानांतरित साझा ऑब्जेक्ट में लिंक नहीं कर सकते हैं। –

    15

    इस में से किसी के लिए समझ बनाने के लिए, आपको पहले करना होगा: https://stackoverflow.com/a/30648229/895245

    : https://stackoverflow.com/a/30507725/895245

  • एक ELF फ़ाइल की बुनियादी संरचना को समझने:

    • स्थानांतरण का एक न्यूनतम उदाहरण देखें मानकों

      R_X86_64_64, R_X86_64_32 और R_X86_64_32S सभी को System V AMD ABI द्वारा परिभाषित किया गया है, जिसमें ईएलएफ फ़ाइल प्रारूप का AMD64 विनिर्देश शामिल है।

      वे ELF32_R_TYPE के लिए सभी संभावित मान हैं, जो System V ABI 4.1 (1997) में निर्दिष्ट हैं, जो ईएलएफ प्रारूप के आर्किटेक्चर तटस्थ भागों को निर्दिष्ट करते हैं। वह मानक केवल फ़ील्ड निर्दिष्ट करता है, लेकिन यह आर्क आश्रित मान नहीं है।

      Name   Field Calculation 
      ------------ ------ ----------- 
      R_X86_64_64 word64 A + S 
      R_X86_64_32 word32 A + S 
      R_X86_64_32S word32 A + S 
      

      हम इस तालिका बाद में समझा जाएगा:

      4.4.1 के तहत "पुनर्वास प्रकार" हम सारांश तालिका देखें।

      और ध्यान दें:

      R_X86_64_32 और R_X86_64_32S relocations 32-बिट तक परिकलित मान काटना। लिंकर को यह सत्यापित करना होगा कि मूल 64-बिट मान में R_X86_64_32 (R_X86_64_32S) स्थानांतरण शून्य-विस्तार (साइन-विस्तार) के लिए जेनरेट किया गया मान। R_X86_64_64 और R_X86_64_32 की

      उदाहरण

      आइए R_X86_64_64 और R_X86_64_32 में फर्स्ट लुक:

      .section .text 
          /* Both a and b contain the address of s. */ 
          a: .long s 
          b: .quad s 
          s: 
      
      फिर

      :

      as --64 -o main.o main.S 
      objdump -dzr main.o 
      

      शामिल है:

      0000000000000000 <a>: 
          0: 00 00     add %al,(%rax) 
               0: R_X86_64_32 .text+0xc 
          2: 00 00     add %al,(%rax) 
      
      0000000000000004 <b>: 
          4: 00 00     add %al,(%rax) 
               4: R_X86_64_64 .text+0xc 
          6: 00 00     add %al,(%rax) 
          8: 00 00     add %al,(%rax) 
          a: 00 00     add %al,(%rax) 
      

      उबंटू 14.04, बिनुटिल्स 2.24 पर परीक्षण किया गया।

      अब के लिए डिस्सेप्लोरर्स को अनदेखा करें (जो डेटा है क्योंकि यह अर्थहीन है), और केवल लेबल, बाइट्स और स्थानान्तरणों को देखें।

      पहले स्थान परिवर्तन:

      0: R_X86_64_32 .text+0xc 
      

      जिसका मतलब है:

      • 0: बाइट 0 पर कार्य करता है (लेबल a)
      • R_X86_64_: उपसर्ग AMD64 प्रणाली वी के सभी स्थानांतरण प्रकार के द्वारा प्रयोग किया एबीआई
      • 32: लेबल s लेबल का 64-बिट पता trunca है टेड एक 32 बिट पता करने के लिए है क्योंकि हम केवल निर्दिष्ट एक .long (4 बाइट्स)
      • .text:
      • 0xc हम .text खंड पर कर रहे हैं: इस योज्य, जो स्थानांतरण प्रविष्टि का एक क्षेत्र है है

      स्थानांतरण के पते के रूप की जाती है:

      A + S 
      

      कहाँ:

      • A: योज्य, यहाँ 0xC
      • S: स्थानांतरण से पहले प्रतीक के मान, यहाँ 00 00 00 00 == 0

      इसलिए, स्थान परिवर्तन के बाद, नए पते 0xC == 12 बाइट्स में .text हो जाएगा अनुभाग।

      यह वही है जो हम उम्मीद करते हैं, क्योंकि s.long (4 बाइट्स) और .quad (8 बाइट्स) के बाद आता है।

      R_X86_64_64 समान, लेकिन सरल है, क्योंकि यहां s के पते को कम करने की आवश्यकता नहीं है। यह Field कॉलम पर word32 के बजाय word64 के माध्यम से मानक द्वारा इंगित किया गया है।

      R_X86_64_32S बनाम R_X86_64_32

      बनाम R_X86_64_32R_X86_64_32S के बीच अंतर है लिंकर "स्थानांतरण फिट करने के लिए छोटा कर दिया साथ" शिकायत:

      • 32: यदि छोटा कर दिया के बाद स्थानांतरण मूल्य करता है शिकायत शून्य पुराने मान का विस्तार नहीं करता है, यानी कटा हुआ बाइट शून्य होना चाहिए:

        ईजी: FF FF FF FF 80 00 00 00 से 80 00 00 00 शिकायत उत्पन्न करता है क्योंकि FF FF FF FF शून्य नहीं है।

      • 32S: अगर शिकायत मूल्य के बाद छंटनी sign extend पुरानी मान नहीं है तो शिकायत करता है।

        उदा।: FF FF FF FF 80 00 00 0080 00 00 00 करने के लिए, ठीक है क्योंकि 80 00 00 00 के अंतिम बिट और छोटा कर दिया बिट्स सभी 1.

      भी देखें हैं:

      .section .text 
      .global _start 
      _start: 
          mov s, %eax 
          s: 
      

      तब: What does this GCC error "... relocation truncated to fit..." mean?

      R_X86_64_32S साथ उत्पन्न किया जा सकता :

      as --64 -o main.o main.S 
      objdump -dzr main.o 
      

      देता है:

      0000000000000000 <_start>: 
          0: 8b 04 25 00 00 00 00 mov 0x0,%eax 
               3: R_X86_64_32S .text+0x7 
      

      अब हम "स्थानांतरण" छोटा कर दिया निरीक्षण एक लिंकर स्क्रिप्ट के साथ 32S पर फिट करने के लिए कर सकते हैं:,

      ld -Tlink.ld a.o 
      

      ठीक है क्योंकि::

      SECTIONS 
      { 
          . = 0xFFFFFFFF80000000; 
          .text : 
          { 
           *(*) 
          } 
      } 
      

      अब 0xFFFFFFFF8000000080000000 में छंटनी हो जाती है, जो एक साइन एक्सटेंशन है।

      लेकिन अगर हम करने के लिए लिंकर स्क्रिप्ट बदलने के लिए:

      . = 0xFFFF0FFF80000000; 
      

      अब यह त्रुटि, उत्पन्न करता है, क्योंकि वह 0 बना यह नहीं एक संकेत विस्तार अब और हो। immediates के लिए स्मृति पहुँच के लिए 32S लेकिन 32 प्रयोग करने के लिए

      दलील: When is it better for an assembler to use sign extended relocation like R_X86_64_32S instead of zero extension like R_X86_64_32?

  • 1

    मेरे मामले में मुद्दा उपस्थित हुआ क्योंकि कार्यक्रम, एक दूरस्थ निर्देशिका में साझा पुस्तकालयों को खोजने के लिए उम्मीद संकलित करने के लिए, जबकि केवल इसी स्थिर पुस्तकालयों वहाँ थे एक गलती में

    दरअसल, यह स्थानांतरण त्रुटि भेजी गई एक फ़ाइल-त्रुटि नहीं मिली थी।

    मैं विस्तृत कैसे मैं इस दूसरे सूत्र में इसके साथ सामना https://stackoverflow.com/a/42388145/5459638

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

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