2008-12-26 11 views
20

मैं लिनक्स स्थिर पुस्तकालय (संग्रह) में निर्यात किए गए सी प्रतीकों की संख्या को सीमित करने के तरीकों की तलाश में हूं। मैं इन्हें केवल उन प्रतीकों तक सीमित करना चाहता हूं जो लाइब्रेरी के लिए आधिकारिक API का हिस्सा हैं। मैं पहले से ही अधिकांश कार्यों को स्थिर के रूप में घोषित करने के लिए 'स्थैतिक' का उपयोग करता हूं, लेकिन इससे उन्हें दायरे को दायर करने के लिए प्रतिबंधित किया जाता है। मैं पुस्तकालय में गुंजाइश तक सीमित करने का एक तरीका ढूंढ रहा हूं।लिनक्स स्थैतिक पुस्तकालय में प्रतीकों को प्रतिबंधित करना

मैं Ulrich Drepper के How to Write Shared Libraries में तकनीकों का उपयोग करके साझा पुस्तकालयों के लिए ऐसा कर सकता हूं, लेकिन मैं इन तकनीकों को स्थिर अभिलेखागार में लागू नहीं कर सकता। अपने पहले Good Practices in Library Design पत्र में, वे लिखते हैं:

केवल संभावना सभी वस्तु फ़ाइलें जो 'ld -r' का उपयोग कर और फिर प्रतीकों जो इस संयुक्त द्वारा निर्यात किया जाता है प्रतिबंधित एक में कुछ आंतरिक संसाधनों की जरूरत गठबंधन करने के लिए है ऑब्जेक्ट फ़ाइल जीएनयू लिंकर के पास विकल्प हैं।

क्या कोई मुझे यह जानने में मदद कर सकता है कि ये विकल्प क्या हो सकते हैं? मुझे 'स्ट्रिप-डब्ल्यू-के प्रीफिक्स_ *' के साथ कुछ सफलता मिली है, लेकिन यह क्रूर लगता है। आदर्श रूप में, मुझे एक समाधान चाहिए जो जीसीसी 3 और 4 दोनों के साथ काम करेगा।

धन्यवाद!

उत्तर

0

ऐसा करने का मेरा तरीका उन सभी चीज़ों को चिह्नित करना है जो आंतरिक, में सभी को चिह्नित करने के लिए है। सभी फाइलों को संरक्षित करें, डीआईटीटरनल = और संकलन रिलीज एक एकल .c फ़ाइल के साथ बनाता है जिसमें सभी शामिल हैं अन्य पुस्तकालय .c फाइलें-DINTERNAL = स्थिर।

+0

यदि आपके पास एक फ़ाइल में सब कुछ है या आप इसे संकलित कर सकते हैं तो यह काम करेगा। अक्सर आप नहीं करते हैं। कभी-कभी आपको अन्य भाषाओं के साथ गठबंधन करने के लिए छोटी फाइलें रखने की आवश्यकता होती है (उदाहरण के लिए हास्केल - यही कारण है कि मुझे यह पृष्ठ मिला)। –

+0

@Maciej: ठीक ओपी ने जीसीसी के बारे में पूछा ... – Joshua

10

स्टेटिक लाइब्रेरी जो भी आप जीसीसी 3.x या 4.x के साथ संकलित कोड के लिए नहीं चाहते हैं।

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

एक संस्करण स्क्रिप्ट प्रविष्टि foo बताते हैं और जनता के बार में आता है और अन्य सभी इंटरफेस खाल की सामग्री:

{ global: foo; bar; local: *; }; 

पर ld दस्तावेज़ देखें: http://sourceware.org/binutils/docs/ld/VERSION.html#VERSION

मैं का एक बड़ा वकील हूँ साझा पुस्तकालय, और ग्लोबल्स की दृश्यता को सीमित करने की यह क्षमता उनके महान गुण हैं।

एक दस्तावेज है कि साझा वस्तुओं के लाभों में से अधिक प्रदान करता है, लेकिन सोलारिस के लिए लिखा (खुश स्मृति के ग्रेग Nakhimovsky द्वारा), http://developers.sun.com/solaris/articles/linker_mapfiles.html

पर मुझे आशा है कि इस मदद करता है।

9

मुझे विश्वास नहीं है कि जीएनयू एलडी के पास ऐसे कोई विकल्प हैं; Ulrich का मतलब objcopy होना चाहिए, जिसमें ऐसे कई विकल्प हैं: --localize-hidden, --localize-symbol=symbolname, --localize-symbols=filename

--localize-hidden विशेष रूप से किसी को एक बहुत अच्छा नियंत्रण रखने की अनुमति देता है जिस पर प्रतीकों का खुलासा किया जाता है।पर विचार करें:

int foo() { return 42; } 
int __attribute__((visibility("hidden"))) bar() { return 24; } 

gcc -c foo.c 
nm foo.o 
000000000000000b T bar 
0000000000000000 T foo 

objcopy --localize-hidden foo.o bar.o 
nm bar.o 
000000000000000b t bar 
0000000000000000 T foo 

तो bar() नहीं रह गया है वस्तु (भले ही यह अभी भी वर्तमान और डीबगिंग के लिए प्रयोग करने योग्य है) से निर्यात किया जाता है। आप bar() को objcopy --strip-unneeded के साथ सभी को भी हटा सकते हैं।

+0

एक समस्या जो मैं इसके साथ देखता हूं, यह है कि आपको इसे सभी ऑब्जेक्ट फ़ाइलों पर करना है। एक और समस्या ओपी का मामला है, जब आप कई ऑब्जेक्ट फ़ाइलों पर फैले एक स्थिर लाइब्रेरी में आंतरिक फ़ंक्शन चाहते हैं, यदि आप एक ऑब्जेक्ट फ़ाइल में एक प्रतीक को "छुपाएं" करते हैं, तो इसे किसी अन्य ऑब्जेक्ट फ़ाइल से कैसे एक्सेस किया जा सकता है एक ही स्थिर पुस्तकालय? –

+0

धन्यवाद। ओबजॉपी अस्तित्व में नहीं था और यह सिर्फ मेरे लिए एक प्रमुख सिरदर्द हल किया गया था। –

6

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

-fvisibility=hidden 
-fvisibility=default 

इसका मतलब है एक डिफ़ॉल्ट दृश्यता के साथ एक एकल फाइल "interface.c" और की एक बड़ी संख्या को संकलित कर सकते हैं:

संकलन समय, एक संकलन इकाई के भीतर सभी प्रतीकों की दृश्यता का उपयोग कर सेट किया जा सकता स्रोत को एनोटेट किए बिना छुपा दृश्यता के साथ कार्यान्वयन फाइलें। एक पुनर्निधारणीय लिंक फिर एक ही वस्तु फ़ाइल जहां गैर-api कार्यों "छिपा" कर रहे हैं उत्पादन करेगा:

ld -r interface.o implementation0.o implementation1.o -o relocatable.o 

संयुक्त वस्तु फ़ाइल अब objcopy के अधीन किया जा सकता है:

objcopy --localize-hidden relocatable.o mylibrary.o 

इस प्रकार हम एक है एकल ऑब्जेक्ट फ़ाइल "लाइब्रेरी" या "मॉड्यूल" जो केवल इच्छित एपीआई का खुलासा करता है।


उपरोक्त रणनीति लिंक समय अनुकूलन के साथ मामूली अच्छी तरह से बातचीत करती है। -flto साथ संकलित करें और संकलक के माध्यम से लिंकर को -r पास करके पुनर्निधारणीय लिंक करते हैं: objcopy

gcc -fuse-linker-plugin -flto -nostdlib -Wl,-r {objects} -o relocatable.o 

उपयोग के रूप में पहले छुपे हुए प्रतीकों स्थानीय बनाना है, तो लिंकर स्थानीय प्रतीकों पट्टी एक अंतिम समय फोन करके पोस्ट-एलटीओ ऑब्जेक्ट में जो भी अन्य मृत कोड मिल सकता है। दुःख की बात है relocatable.o किसी भी LTO संबंधित जानकारी को बरकरार रखा है की संभावना नहीं है:

gcc -nostdlib -Wl,-r,--discard-all relocatable.o mylibrary.o 

LTO की वर्तमान कार्यान्वयन पुनर्निधारणीय लिंक चरण के दौरान सक्रिय होने के लिए दिखाई देते हैं। एलटीओ के साथ, छुपा => स्थानीय प्रतीक अंतिम स्थानापन्न लिंक द्वारा छीन लिया गया था। एलटीओ के बिना, छुपा => स्थानीय प्रतीक अंतिम स्थानापन्न लिंक से बच गए।

लेटो के भविष्य के कार्यान्वयन, स्थानांतरित लिंक चरण के माध्यम से आवश्यक मेटाडेटा को संरक्षित करने की संभावना प्रतीत होते हैं, लेकिन वर्तमान में स्थानांतरित लिंक का परिणाम एक सादा पुरानी ऑब्जेक्ट फ़ाइल प्रतीत होता है।

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