केवल टिप्पणियों वाले कार्यक्रमों के दो बायनेरिज़ जीसीसी में बिल्कुल मेल नहीं खाते हैं?


110

मैंने दो C प्रोग्राम बनाए

  1. कार्यक्रम 1

    int main()
    {
    }
  2. कार्यक्रम 2

    int main()
    {
    //Some Harmless comments
    }

AFAIK, जब संकलन करते हैं, संकलक (gcc) को टिप्पणियों और निरर्थक व्हाइटस्पेस को अनदेखा करना चाहिए, और इसलिए आउटपुट समान होना चाहिए।

लेकिन जब मैंने आउटपुट बायनेरिज़ के md5sums की जाँच की, तो वे मेल नहीं खाते। मैंने अनुकूलन के साथ संकलन करने का भी प्रयास किया -O3और -Ofastफिर भी वे मेल नहीं खाते।

यहाँ क्या हो रहा है?

EDIT: सटीक कमांड और वहाँ md5sums हैं (t1.c प्रोग्राम 1 है और t2.c प्रोग्राम 2 है)

gcc ./t1.c -o aaa
gcc ./t2.c -o bbb
98c1a86e593fd0181383662e68bac22f  aaa
c10293cbe6031b13dc6244d01b4d2793  bbb

gcc ./t2.c -Ofast -o bbb
gcc ./t1.c -Ofast -o aaa
2f65a6d5bc9bf1351bdd6919a766fa10  aaa
c0bee139c47183ce62e10c3dbc13c614  bbb


gcc ./t1.c -O3 -o aaa
gcc ./t2.c -O3 -o bbb
564a39d982710b0070bb9349bfc0e2cd  aaa
ad89b15e73b26e32026fd0f1dc152cd2  bbb

और हाँ, md5sums एक ही झंडे के साथ कई संकलन में मेल खाते हैं।

BTW मेरा सिस्टम है gcc (GCC) 5.2.0औरLinux 4.2.0-1-MANJARO #1 SMP PREEMPT x86_64 GNU/Linux


17
कृपया अपने सटीक कमांड लाइन झंडे शामिल करें। उदाहरण के लिए, क्या डिबग की जानकारी बायनेरिज़ में शामिल है? यदि हां, तो बदलती संख्या स्पष्ट रूप से इसे प्रभावित करेगी ...
जॉन स्कीट

4
क्या MD5 का योग एक ही कोड के कई बिल्ड्स पर संगत है?
अनथेनोरिसिसर

3
मैं इसे पुन: पेश नहीं कर सकता। मुझे लगता है कि यह इस तथ्य के कारण होता है कि जीसीसी बायनाटिस में मेटाडेटा का एक पूरा गुच्छा एम्बेड करता है जब उन्हें (टाइमस्टैम्प सहित) संकलित किया जाता है। यदि आप अपने द्वारा उपयोग की जाने वाली सटीक कमांड लाइन के झंडे जोड़ सकते हैं , तो यह उपयोगी होगा।
सीपर

2
MD5sums की सिर्फ जाँच करने और अटक जाने के बजाय, हेक्सडम्प और देखने के लिए कि बाइट्स अलग
MM

12
हालांकि सवाल का जवाब "दो संकलक आउटपुट के बीच क्या अलग है?" दिलचस्प है, मैं ध्यान देता हूं कि प्रश्न में एक अनुचित धारणा है: कि दो आउटपुट समान होना चाहिए और हमें कुछ स्पष्टीकरण की आवश्यकता है कि वे अलग क्यों हैं। सभी कंपाइलर आपसे वादा करते हैं कि जब आप इसे एक कानूनी सी प्रोग्राम देते हैं, तो आउटपुट एक कानूनी निष्पादन योग्य होता है जो उस प्रोग्राम को लागू करता है। संकलक के किसी भी दो निष्पादन एक ही बाइनरी का उत्पादन करते हैं जो सी मानक की गारंटी नहीं है।
एरिक लिपर्ट

जवाबों:


159

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

इसे इस्तेमाल करे:

$ cp code.c code2.c subdir/code.c
$ gcc code.c -o a
$ gcc code2.c -o b
$ gcc subdir/code.c -o a2
$ diff a b
Binary files a and b differ
$ diff a2 b
Binary files a2 and b differ
$ diff -s a a2
Files a and a2 are identical

यह बताता है कि क्यों आपके md5sums बिल्ड के बीच नहीं बदलते हैं, लेकिन वे अलग-अलग फ़ाइलों के बीच भिन्न होते हैं। यदि आप चाहते हैं, तो आप वह कर सकते हैं जो जेन्स ने सुझाया था और stringsप्रत्येक बाइनरी के लिए आउटपुट की तुलना करके आप देखेंगे कि फ़ाइल नाम बाइनरी में एम्बेडेड हैं। यदि आप इसे "ठीक" करना चाहते हैं, तो आप stripबायनेरिज़ और मेटाडेटा को हटा सकते हैं:

$ strip a a2 b
$ diff -s a b
Files a and b are identical
$ diff -s a2 b
Files a2 and b are identical
$ diff -s a a2
Files a and a2 are identical

संपादित करें: यह कहने के लिए कि आप समस्या को "ठीक" करने के लिए बायनेरिज़ छीन सकते हैं।
cyphar

30
और यही कारण है कि आपको विधानसभा आउटपुट की तुलना करनी चाहिए, एमडी 5 चेकसम की नहीं।
को ऑर्बिट में

1
मैंने यहां एक अनुवर्ती प्रश्न पूछा है
फेडरिको पोलोनी

4
ऑब्जेक्ट फ़ाइल प्रारूप के आधार पर संकलन समय भी ऑब्जेक्ट फ़ाइलों में संग्रहीत किया जाता है। इसलिए उदाहरण के लिए COFF फ़ाइलों का उपयोग करना a और a2 समान नहीं होगा।
मार्टिन रोसेनौ

28

सबसे आम कारण संकलक द्वारा दर्ज किए गए फ़ाइल नाम और समय टिकट हैं (आमतौर पर ईएलएफ अनुभागों के डिबग जानकारी भाग में)।

दौड़ने की कोशिश करो

 $ strings -a program > x
 ...recompile program...
 $ strings -a program > y
 $ diff x y

और आप इसका कारण देख सकते हैं। मैंने एक बार इसका उपयोग यह पता लगाने के लिए किया था कि एक ही स्रोत अलग-अलग निर्देशिकाओं में संकलित होने पर अलग कोड क्यों होगा। यह खोज थी कि __FILE__मैक्रो का विस्तार पूर्ण फ़ाइल नाम के साथ हुआ, दोनों पेड़ों में अलग-अलग।


1
के अनुसार gcc.gnu.org/ml/gcc-help/2007-05/msg00138.html (पुराने, मुझे पता है) वे timestamps सेव न करें और यह एक लिंकर मुद्दा हो सकता है। हालांकि, मुझे हाल ही में एक कहानी पढ़ना याद है कि कैसे एक सुरक्षा फर्म ने अपने बायनेरिज़ में जीसीसी टाइमस्टैम्प की जानकारी का उपयोग करते हुए एक हैकिंग टीम की कामकाजी आदतों को प्रोफाइल किया।
cyphar

3
और यह उल्लेख नहीं करने के लिए कि ओपी कहता है कि "md5sums एक ही झंडे के साथ कई संकलन में मेल खाते हैं" जो इंगित करता है कि यह संभवतः टाइमस्टैम्प नहीं है जो समस्या पैदा कर रहे हैं। यह शायद इस तथ्य के कारण है कि वे अलग-अलग फ़ाइल नाम हैं।
cyphar

1
@ साइपर विभिन्न फ़ाइल नामों को स्ट्रिंग्स द्वारा पकड़ा जाना चाहिए / साथ ही साथ अलग-अलग दृष्टिकोण।
जेन्स

15

नोट : याद रखें कि स्रोत फ़ाइल का नाम अनस्ट्रिप्ड बाइनरी में जाता है, इसलिए अलग-अलग नाम की स्रोत फ़ाइलों से आने वाले दो कार्यक्रमों में अलग-अलग हैश होंगे।

समान स्थितियों में, उपरोक्त को लागू नहीं करना चाहिए , आप कोशिश कर सकते हैं:

  • stripकुछ वसा को हटाने के लिए बाइनरी के खिलाफ चल रहा है । यदि छीन ली गई बायनेरी समान हैं तो यह कुछ मेटाडेटा था जो प्रोग्राम ऑपरेशन के लिए आवश्यक नहीं है।
  • यह सुनिश्चित करने के लिए असेंबली इंटरमीडिएट आउटपुट जेनरेट कर रहा है कि अंतर वास्तविक सीपीयू निर्देशों में नहीं है (या, हालांकि, बेहतर पिनपॉइंट पर जहां वास्तव में अंतर है )।
  • उपयोग करें strings, या दोनों प्रोग्राम को हेक्स पर डंप करें और दो हेक्स डंप पर एक अंतर चलाएं। एक बार अंतर (ओं) को स्थित करने के बाद, आप कोशिश कर सकते हैं और देख सकते हैं कि उनके लिए कुछ तुकबंदी या कारण है (पीआईडी, टाइमस्टैम्प, स्रोत फ़ाइल टाइमस्टैम्प ...)। उदाहरण के लिए आपको नैदानिक ​​उद्देश्यों के लिए संकलन समय पर टाइमस्टैम्प का भंडारण करने की दिनचर्या हो सकती है ।

मेरा सिस्टम है gcc (GCC) 5.2.0औरLinux 4.2.0-1-MANJARO #1 SMP PREEMPT x86_64 GNU/Linux
रजिस्टर्ड यूजर

2
आपको वास्तव में दो अलग-अलग फाइलें बनाने की कोशिश करनी चाहिए । मैं इसे एकल फ़ाइल को संशोधित करने के साथ पुन: पेश नहीं कर सका।
cyphar

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