क्या किसी प्रोग्राम को दोबारा शुरू करने से बिट-फॉर-बिट समान बाइनरी का उत्पादन होता है?


25

अगर मैं किसी प्रोग्राम को सिंगल बाइनरी में संकलित करता, एक चेकसम बनाता, और फिर उसी मशीन पर उसी कंपाइलर और कंपाइलर सेटिंग्स के साथ फिर से जोड़ देता और recompiled प्रोग्राम को चेकसम करता, तो चेकसम विफल हो जाता?

यदि हां, तो यह क्यों है? यदि नहीं, तो क्या एक गैर-समान बाइनरी में एक अलग सीपीयू परिणाम होगा?


8
यह कंपाइलर पर निर्भर करता है। उनमें से कुछ समय टिकटों को एम्बेड करते हैं, इसलिए उत्तर उन लोगों के लिए "नहीं" है।
ta.speot.is

वास्तव में यह निष्पादन योग्य प्रारूप पर निर्भर करता है , संकलक पर नहीं। विंडोज के पीई प्रारूप जैसे कुछ निष्पादन योग्य स्वरूपों में एक टाइमस्टैम्प शामिल होता है, जिसे संकलन समय और तारीख को स्पर्श किया जाता है, जबकि लिनक्स 'ईएलएफ प्रारूप जैसे अन्य प्रारूप नहीं होते हैं। किसी भी तरह से, यह प्रश्न "समान बाइनरी" की परिभाषा पर टिका है। यदि एक ही स्रोत फ़ाइल को एक ही कंपाइलर और लाइब्रेरी और स्विचेस और सब कुछ के साथ संकलित किया जाता है, तो छवि स्वयं / बिट के समान होगी, लेकिन हेडर और अन्य मेटाडेटा अलग-अलग हो सकते हैं।
Synetech

जवाबों:


19
  1. एक ही मशीन पर समान सेटिंग्स के साथ एक ही कार्यक्रम संकलित करें:

    यद्यपि इसका निश्चित उत्तर "यह निर्भर करता है" है, यह अपेक्षा करना उचित है कि अधिकांश कंपाइलर्स ज्यादातर समय नियतात्मक होंगे, और उत्पादित बायनेरिज़ समान होना चाहिए। दरअसल, कुछ संस्करण नियंत्रण प्रणाली इस पर निर्भर करते हैं। फिर भी, हमेशा अपवाद होते हैं; यह बहुत संभव है कि कुछ संकलक कहीं न कहीं टाइमस्टैम्प डालने का फैसला करेंगे या कुछ इस तरह (iirc, Delphi does, उदाहरण के लिए)। या निर्माण प्रक्रिया ही ऐसा कर सकती है; मैंने सी प्रोग्राम के लिए मेकफाइल्स देखा है जो वर्तमान टाइमस्टैम्प में प्रीप्रोसेसर मैक्रो सेट करता है। (मुझे लगता है कि एक अलग संकलक सेटिंग के रूप में गिना जाएगा, हालांकि।)

    यह भी जान लें कि यदि आप बाइनरी को स्टेटिकली लिंक करते हैं, तो आप अपनी मशीन पर सभी संबंधित पुस्तकालयों की स्थिति को प्रभावी रूप से शामिल कर रहे हैं, और उनमें से किसी एक में कोई परिवर्तन भी आपके बाइनरी को प्रभावित करेगा। तो यह सिर्फ संकलक सेटिंग्स नहीं है जो प्रासंगिक हैं।

  2. एक अलग सीपीयू के साथ एक अलग मशीन पर एक ही कार्यक्रम संकलित करें।

    यहां, सभी दांव बंद हैं। अधिकांश आधुनिक संकलक लक्ष्य-विशिष्ट अनुकूलन करने में सक्षम हैं; यदि यह विकल्प सक्षम है, तो बायनेरिज़ तब तक अलग होने की संभावना है जब तक सीपीयू समान नहीं होते हैं (और तब भी, यह संभव है)। इसके अलावा, स्थैतिक लिंकिंग के बारे में उपरोक्त नोट देखें: कॉन्फ़िगरेशन वातावरण कंपाइलर सेटिंग्स से बहुत आगे निकल जाता है। जब तक आपके पास बहुत सख्त कॉन्फ़िगरेशन नियंत्रण नहीं है, यह बेहद संभावना है कि दोनों मशीनों के बीच कुछ अलग हो।


1
कहो कि मैं जीसीसी का उपयोग कर रहा था, और मैं मार्च विकल्प (सीपीयू के विशिष्ट परिवार के लिए बाइनरी का अनुकूलन करने वाला विकल्प) का उपयोग नहीं कर रहा था, और मुझे एक सीपीयू के साथ एक बाइनरी संकलित करना था, और फिर दूसरे सीपीयू के साथ एक होना चाहिए अंतर?
डेविड

1
@ डेविड: यह अब भी निर्भर करता है। सबसे पहले, आपके द्वारा लिंक किए जा रहे पुस्तकालयों में वास्तुकला-विशिष्ट बिल्ड हो सकते हैं। तो उत्पादन gcc -cअच्छी तरह से समान हो सकता है, लेकिन लिंक किए गए संस्करण भिन्न होते हैं। इसके अलावा, यह सिर्फ नहीं है -march; वहाँ भी है -mtune/-mcpu और -mfpmatch(और संभवतः अन्य)। इनमें से कुछ में अलग-अलग प्रतिष्ठानों पर अलग-अलग चूक हो सकती हैं, इसलिए आपको अपनी मशीनों के लिए सबसे खराब स्थिति को स्पष्ट रूप से लागू करने की आवश्यकता हो सकती है; ऐसा करने से प्रदर्शन में काफी कमी आ सकती है, खासकर यदि आप बिना s3 के i386 पर वापस जाते हैं। और, निश्चित रूप से, अगर आपका एक cpus एक ARM है और दूसरा एक i686 ...
rici

1
इसके अलावा, GCC प्रश्न में संकलक में से एक है जो बायनेरिज़ के लिए टाइमस्टैम्प को जोड़ता है?
डेविड

@ दाविद: अफाक, नहीं।
रिक्की

8

आपकी पूछ क्या है "आउटपुट निर्धारक है ।" यदि आपने प्रोग्राम को एक बार संकलित किया है, तो तुरंत इसे फिर से संकलित करें आप शायद उसी आउटपुट फ़ाइल के साथ समाप्त हो जाएंगे। हालांकि, अगर कुछ भी बदल गया - यहां तक ​​कि एक छोटा सा बदलाव - विशेष रूप से एक घटक में संकलित कार्यक्रम का उपयोग करता है, तो संकलक का उत्पादन भी बदल सकता है।


2
बहुत अच्छी बात है। इस लेख में कुछ बहुत ही रोचक टिप्पणियां हैं। विशेष रूप से, जीसीसी के साथ संकलन कुछ मामलों में इनपुट के संबंध में निर्धारक नहीं हो सकता है, उदाहरण के लिए, यह कैसे अनाम नाम स्थान में कार्य करता है, जिसके लिए यह आंतरिक रूप से एक यादृच्छिक संख्या जनरेटर का उपयोग करता है। इस विशेष मामले में नियतत्ववाद प्राप्त करने के लिए, विकल्प निर्दिष्ट करके प्रारंभिक यादृच्छिक बीज की आपूर्ति करें -frandom-seed=string
एके

7

क्या किसी प्रोग्राम को दोबारा शुरू करने से बिट-फॉर-बिट समान बाइनरी का उत्पादन होता है?

सभी संकलक के लिए? नहीं। सी # संकलक, कम से कम, की अनुमति नहीं है।

एरिक लिपर्ट का बहुत गहन विराम है कि संकलक का उत्पादन नियतात्मक क्यों नहीं है

[T] वह डिजाइन द्वारा C # संकलक कभी भी एक ही बाइनरी दो बार पैदा नहीं करता है। सी # कंपाइलर हर विधानसभा में एक नए सिरे से तैयार किए गए GUID को एम्बेड करता है, हर बार जब आप इसे चलाते हैं, जिससे यह सुनिश्चित होता है कि कोई भी दो असेंबली कभी बिट-टू-बिट समान नहीं हैं। सीएलआई विनिर्देश से उद्धृत करने के लिए:

Mvid कॉलम एक अद्वितीय GUID [...] को अनुक्रमणित करेगा जो मॉड्यूल के इस उदाहरण की पहचान करता है। [...] Mvid को हर मॉड्यूल के लिए नया बनाया जाना चाहिए [...] जबकि [runtime] खुद Mvid का उपयोग नहीं करता है, अन्य उपकरण (जैसे डीबगर्स [...]) इस तथ्य पर भरोसा करते हैं कि एमवीआईडी ​​लगभग हमेशा एक मॉड्यूल से दूसरे में भिन्न होता है।

यद्यपि यह C # संकलक के एक संस्करण के लिए विशिष्ट है, लेख में कई बिंदुओं को किसी भी संकलक पर लागू किया जा सकता है ।

सबसे पहले, हम यह मान रहे हैं कि हमें हर बार फ़ाइलों की सूची समान क्रम में मिलती है। लेकिन यह कुछ मामलों में ऑपरेटिंग सिस्टम तक है। जब आप "csc * .cs" कहते हैं, जिस क्रम में ऑपरेटिंग सिस्टम मेलिंग फ़ाइलों की सूची को पसंद करता है, वह ऑपरेटिंग सिस्टम का कार्यान्वयन विवरण है; संकलक उस सूची को एक विहित क्रम में क्रमबद्ध नहीं करता है।


इसे निर्मित प्रतिलिपि प्रस्तुत करने योग्य नहीं बनाया जाना चाहिए (संकलन समय और असेंबली GUID जैसे कुछ आसानी से छूटे हुए क्षेत्रों के अलावा)। उदाहरण के लिए, कैनोनिकल ऑर्डर में इनपुट फ़ाइलों को छांटना एक-लाइनर है। यहां तक ​​कि GUID नए उत्पन्न होने के बजाय विधानसभा के शेष का हैश हो सकता है।
कोडइन्चौस

मुझे लगता है कि आप Microsoft C # संकलक का मतलब है, या यह विनिर्देश की आवश्यकता है?
डेविड

@ डेविड सीएलआई युक्ति की आवश्यकता है। मोनो के सी # कंपाइलर को ऐसा ही करना होगा। किसी VB .NET कंपाइलर के लिए Ditto।
ta.speot.is

4
ईसीएमए मानक में टाइमस्टैम्प या एमवीआईडी ​​अंतर नहीं है। उन लोगों के बिना, सी # में समान बायनेरिज़ के लिए कम से कम संभव है। इस प्रकार मुख्य कारण एक संदिग्ध डिजाइन निर्णय है और वास्तविक तकनीकी बाधा नहीं है।
शिव

7
  • -frandom-seed=123कुछ जीसीसी आंतरिक यादृच्छिकता को नियंत्रित करता है। man gccकहते हैं:

    यह विकल्प एक बीज प्रदान करता है जिसका उपयोग जीसीसी यादृच्छिक संख्याओं के स्थान पर कुछ प्रतीक नामों के निर्माण में करता है जिन्हें हर संकलित फ़ाइल में अलग होना चाहिए। इसका उपयोग कवरेज डेटा फ़ाइलों और उन्हें उत्पन्न करने वाली ऑब्जेक्ट फ़ाइलों में अद्वितीय टिकट लगाने के लिए भी किया जाता है। आप reproducibly समान ऑब्जेक्ट फ़ाइलों का उत्पादन करने के लिए -frandom-बीज विकल्प का उपयोग कर सकते हैं।

  • __FILE__: स्रोत को एक निश्चित फ़ोल्डर में रखें (जैसे /tmp/build)

  • के लिए __DATE__, __TIME__, __TIMESTAMP__:
    • libfaketime: https://github.com/wolfcw/libfaketime
    • उन मैक्रोज़ को ओवरराइड करें -D
    • -Wdate-timeया -Werror=date-time: यदि या तो चेतावनी दी जाए या विफल हो __TIME__, __DATE__या __TIMESTAMP__उपयोग किया जाता है। लिनक्स कर्नेल 4.4 डिफ़ॉल्ट रूप से इसका उपयोग करता है।
  • का उपयोग Dके साथ झंडा ar, या का उपयोग https://github.com/nh2/ar-timestamp-wiper/tree/master टिकटों साफ करने के लिए
  • -fno-guess-branch-probability: पुराने मैनुअल संस्करण कहते हैं कि यह गैर-नियतत्ववाद का एक स्रोत है, लेकिन अब और नहीं । सुनिश्चित नहीं है कि यह कवर किया गया है -frandom-seedया नहीं।

डेबियन रिप्रोड्यूसबल, बाइट-बाय-बाइट को मानकीकृत करने के प्रोजेक्ट प्रयासों का निर्माण करता है, और हाल ही में लिनक्स लिनक्स अनुदान प्राप्त किया है । जिसमें सिर्फ संकलन से अधिक शामिल है, लेकिन यह रुचि का होना चाहिए।

बिल्डरोट के पास एक BR2_REPRODUCIBLEविकल्प है जो पैकेज स्तर पर कुछ विचार दे सकता है, लेकिन यह इस बिंदु पर पूर्ण से बहुत दूर है।

संबंधित सूत्र:


3

प्रोजेक्ट https://reproducible-builds.org/ इस बारे में है, और आपके प्रश्न "नहीं, वे अलग नहीं होंगे" का उत्तर यथासंभव अधिक से अधिक स्थानों पर देने के लिए पुरजोर कोशिश कर रहे हैं। निक्सोस और डेबियन अब अपने पैकेज के लिए 90% से अधिक प्रतिलिपि प्रस्तुत करने योग्य हैं।

यदि आप एक बाइनरी संकलित करते हैं, और मैं एक बाइनरी संकलित करता हूं, और वे बिट-फॉर-बिट समान हैं, तो मुझे आश्वस्त किया जा सकता है कि स्रोत कोड और टूल वही हैं जो आउटपुट निर्धारित करते हैं, और यह कि आप कुछ में चुपके नहीं थे जिस तरह से ट्रोजन कोड।

यदि हम मानव-पठनीय स्रोत से बूटस्ट्रैपबिलिटी के साथ प्रतिलिपि प्रस्तुत करने योग्यता को जोड़ते हैं, जैसा कि http://bootstrappable.org/ कर रहा है, तो हम मानव-पठनीय स्रोत द्वारा जमीन से निर्धारित एक प्रणाली प्राप्त करते हैं, और उसके बाद ही हम एक बिंदु पर होते हैं हम भरोसा कर सकते हैं कि हम जानते हैं कि सिस्टम क्या कर रहा है।


1
कूल लिंक। मैं एक बिल्डरोट फैनबॉय हूँ, लेकिन अगर कोई मुझे NEM ARM क्रॉस आर्क सेटअप देता है जो QEMU पर बूट करता है, तो मुझे खुशी होगी :-)
Ciro Santilli 新疆 fan fan fan 事件

मैंने Guix का उल्लेख नहीं किया क्योंकि मुझे नहीं पता कि उनकी संख्या कहाँ से मिली, लेकिन वे सत्यापन टूलिंग के साथ रिपुसिबिलिटी ट्रेन में NixOS से पहले थे और इसलिए, मुझे यकीन है कि वे समान स्तर पर या बेहतर हैं।
क्लेक

2

मैं कहता हूँ नहीं, यह 100% नियतात्मक नहीं है। मैंने पहले जीसीसी के एक संस्करण के साथ काम किया था जो हिताची एच 8 प्रोसेसर के लिए लक्ष्य बायनेरिज़ बनाता है।

यह समय की मोहर के साथ कोई समस्या नहीं है। भले ही समय स्टाम्प मुद्दे को नजरअंदाज कर दिया गया हो, लेकिन विशिष्ट प्रोसेसर आर्किटेक्चर उसी निर्देश को 2 अलग-अलग तरीकों से एन्कोड करने की अनुमति दे सकता है जहां कुछ बिट्स 1 या 0. हो सकते हैं। मेरा पिछला अनुभव बताता है कि उत्पन्न बायनेरिज़ उसी समय के अधिकांश थे लेकिन कभी-कभार gcc बायनेरिज़ को समान आकार के साथ उत्पन्न करता है, लेकिन कुछ बाइट्स केवल 1 बिट से भिन्न होते हैं जैसे 0XE0 0XE1 बन जाता है।


और क्या इससे अलग व्यवहार या "गंभीर समस्याएं" पैदा हुईं?
फ्लोरियन स्ट्राब

1

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.