स्थानांतरण का एक न्यूनतम उदाहरण देखें मानकों 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_32
R_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 00
80 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 :
{
*(*)
}
}
अब 0xFFFFFFFF80000000
80000000
में छंटनी हो जाती है, जो एक साइन एक्सटेंशन है।
लेकिन अगर हम करने के लिए लिंकर स्क्रिप्ट बदलने के लिए:
. = 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?
संबंधित: 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' का उपयोग करने के बारे में जानकारी के लिए यदि आप यही चाहते हैं। –