linux X86_64 एबीआई में टेक्स्ट सेगमेंट की शुरुआत के रूप में चुना गया पता 0x400000 क्यों है?



memory x86-64 (1)

निचली पंक्ति: कुछ तकनीकी सीमाएं जो amd64 बड़े पते का उपयोग करने में है, सुझाव देता है कि निम्न 2 2GiB पता स्थान को दक्षता के लिए कोड और डेटा पर समर्पित किया 2GiB इस प्रकार ढेर को इस सीमा से बाहर स्थानांतरित कर दिया गया है।

i386 एबीआई 1 में

  • ढेर कोड से पहले स्थित है, जो 0x8048000 नीचे से बढ़ रहा है। जो "स्टैक के लिए 128 एमबी से थोड़ा अधिक और पाठ और डेटा के लिए लगभग 2 जीबी" प्रदान करता है (पृष्ठ 3-22)।
  • गतिशील खंड 0x80000000 (2 जीआईबी) से शुरू होते हैं,
  • और कर्नेल शीर्ष पर "आरक्षित क्षेत्र" पर कब्जा करता है, जिसकी कल्पना कम से कम 0xC0000000 (पृष्ठ 3-21) ( जो आमतौर पर करता है ) से शुरू होने पर 1 1GiB तक हो 1GiB
  • मुख्य कार्यक्रम को स्थिति-स्वतंत्र होने की आवश्यकता नहीं है।
  • शून्य सूचक पहुंच (पी 3-21) को पकड़ने के लिए एक कार्यान्वयन की आवश्यकता नहीं है, लेकिन उम्मीद है कि 128MiB (जो 288KiB ) से ऊपर की कुछ स्टैक स्पेस उस उद्देश्य के लिए आरक्षित होगी।

amd64 ( uclibc.org/docs/psABI-x86_64.pdf i386 एक (पी। 9) में संशोधन के रूप में तैयार किया गया है) में काफी बड़ा (48-बिट) पता स्थान है लेकिन अधिकांश निर्देश केवल 32-बिट तत्काल ऑपरेंड स्वीकार करते हैं (जिसमें सीधे निर्देशों और सीधे निर्देशों में ऑफसेट शामिल हैं ), बड़े मूल्यों को संभालने के लिए अधिक काम और कम कुशल कोड की आवश्यकता होती है (विशेष रूप से जब निर्देश परस्पर निर्भरता को ध्यान में रखते हैं)। इन सीमाओं के आसपास काम करने के उपाय कुछ "कोड मॉडल" पेश करके लेखकों द्वारा संक्षेप में सारांशित किए जाते हैं, जिन्हें वे "बेहतर कोड उत्पन्न करने की अनुमति देते हैं" का उपयोग करने की सलाह देते हैं। (पृष्ठ 33)

  • विशेष रूप से, उनमें से पहला, "छोटा कोड मॉडल", 0 से 2 31 -2 24 -1 या 0x00000000 से 0x7effffff तक की सीमा में पते का उपयोग करने का सुझाव देता है " जो कुछ बहुत ही सापेक्ष रिश्तेदार संदर्भ और सरणी पुनरावृत्ति की अनुमति देता है। यह 1.98GiB जो कई कार्यक्रमों के लिए पर्याप्त है।
  • "मध्यम कोड मॉडल" पिछले एक पर आधारित है, जो डेटा को उपरोक्त सीमा के नीचे "तेज़" भाग में विभाजित करता है और "धीमे" शेष भाग को एक्सेस करने के लिए एक विशेष निर्देश की आवश्यकता होती है। जबकि कोड सीमा के नीचे रहता है।
  • और केवल "बड़ा" मॉडल आकारों के बारे में कोई धारणा नहीं करता है, संकलक की आवश्यकता होती है " movabs कोड के अंदर पते से निपटने के लिए भी, मध्यम कोड मॉडल में, movabs निर्देश का उपयोग करने के लिए। इसके अतिरिक्त, अप्रत्यक्ष शाखाओं को पते पर ब्रांच करने की आवश्यकता होती है वर्तमान निर्देश सूचक से जिसका ऑफ़सेट अज्ञात है। " वे कई साझा पुस्तकालयों में कोड बेस को विभाजित करने का सुझाव देते हैं क्योंकि ये उपायों ऑफसेट्स के सापेक्ष संदर्भों के लिए लागू नहीं होते हैं जो सीमाओं के भीतर होने के लिए जाने जाते हैं (जैसा कि "छोटे स्थान स्वतंत्र कोड मॉडल" में उल्लिखित है)।

इस प्रकार ढेर को साझा लाइब्रेरी स्पेस ( 0x80000000000 , 128GiB ) के अंतर्गत ले जाया गया था क्योंकि इसके पते कभी भी तत्काल संचालन नहीं होते हैं, हमेशा अप्रत्यक्ष रूप से या किसी अन्य संदर्भ से lea / 128GiB साथ संदर्भित होते हैं, इस प्रकार केवल सापेक्ष ऑफसेट सीमाएं लागू होती हैं।

उपरोक्त बताता है कि लोडिंग पता को निम्न पते पर क्यों ले जाया गया था। अब, यह वास्तव में 0x400000 (4 4MiB ) क्यों ले जाया गया था? यहां, मैं खाली आया, इसलिए मैंने एबीआई चश्मा में जो पढ़ा है उसे संक्षेप में, मैं केवल अनुमान लगा सकता हूं कि यह "ठीक है" महसूस किया:

  • यह किसी भी संभावित गलत संरचना ऑफसेट को पकड़ने के लिए काफी बड़ा है, जो amd64 पर बड़ी डेटा इकाइयों को 2GiB की 2GiB , फिर भी पता 2GiB के लिए बहुत कम मूल्यवान 2 2GiB पता स्थान को बर्बाद न करने के लिए पर्याप्त छोटा है।
  • यह आज के सबसे बड़े व्यावहारिक पृष्ठ आकार के बराबर है और यह अन्य सभी वर्चुअल मेमोरी यूनिट आकारों में से एक है जो कोई सोच सकता है।

1 ध्यान दें कि वास्तविक एक्स 32 लिनक्स समय-समय पर इस लेआउट से विचलित हो रहे हैं। लेकिन हम यहां एबीआई स्पेक के बारे में बात कर रहे हैं क्योंकि amd64 एक औपचारिक रूप से किसी व्युत्पन्न लेआउट के बजाय इसके आधार पर आधारित है (उद्धरण के लिए इसके पैराग्राफ को देखें)।

पी पर this दस्तावेज़ में। 27 यह कहता है कि पाठ खंड 0x400000 से शुरू होता है। यह विशेष पता क्यों चुना गया था? क्या इसके लिए कोई कारण है? Linux पर GNU ld में एक ही पता चुना गया है:

$ ld -verbose | grep -i text-segment
  PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;

यह आश्चर्य की बात है क्योंकि यह पता 32-बिट x86 निष्पादन योग्य में बड़ा है:

$ ld -verbose | grep -i text-segment
  PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x08048000)); . = SEGMENT_START("text-segment", 0x08048000) + SIZEOF_HEADERS;

मैंने इस सवाल को पढ़ा जो चर्चा करता है कि i386 के लिए 0x080xxxxx पता क्यों चुना गया था लेकिन यह x86_64 में बदलाव की व्याख्या नहीं करता है। उस मामले पर कोई स्पष्टीकरण खोजना मुश्किल है। क्या किसी के पास कोई सुराग है?





abi