2009-09-20 11 views
43

है इसलिए हर कोई शायद जानता है कि ग्लिब के /lib/libc.so.6 को सामान्य निष्पादन योग्य की तरह खोल में निष्पादित किया जा सकता है, जिसमें मामलों में यह इसकी संस्करण जानकारी प्रिंट करता है और बाहर निकलता है। यह .so में एक प्रविष्टि बिंदु को परिभाषित करके किया जाता है। कुछ मामलों के लिए यह अन्य परियोजनाओं के लिए भी इसका उपयोग करना दिलचस्प हो सकता है। दुर्भाग्यवश, निम्न स्तर के एंट्री पॉइंट जिसे आप ld's -e विकल्प द्वारा सेट कर सकते हैं वह बहुत कम स्तर वाला है: गतिशील लोडर उपलब्ध नहीं है, इसलिए आप किसी भी उचित लाइब्रेरी फ़ंक्शंस को कॉल नहीं कर सकते हैं। इस कारण के लिए glibc इस प्रविष्टि बिंदु में एक नग्न सिस्टम कॉल के माध्यम से लिखने() सिस्टम कॉल लागू करता है।एक .so का निर्माण करना जो एक निष्पादन योग्य

मेरा प्रश्न अब है, क्या कोई इस बात से अच्छा सोच सकता है कि कोई उस प्रविष्टि बिंदु से एक पूर्ण गतिशील लिंकर को कैसे बूट कर सकता है ताकि कोई अन्य से कार्यों तक पहुंच सके।

+5

'/ lib/ld-linux.so.2' सिर्फ एक और उदाहरण है :) –

उत्तर

43

साथ अपनी साझा लाइब्रेरी बिल्डिंगविकल्प आपको वह सब कुछ देता है जो आपको चाहिए:

/* pie.c */ 
#include <stdio.h> 
int foo() 
{ 
    printf("in %s %s:%d\n", __func__, __FILE__, __LINE__); 
    return 42; 
} 
int main() 
{ 
    printf("in %s %s:%d\n", __func__, __FILE__, __LINE__); 
    return foo(); 
} 


/* main.c */ 
#include <stdio.h> 

extern int foo(void); 
int main() 
{ 
    printf("in %s %s:%d\n", __func__, __FILE__, __LINE__); 
    return foo(); 
} 


$ gcc -fPIC -pie -o pie.so pie.c -Wl,-E 
$ gcc main.c ./pie.so 


$ ./pie.so 
in main pie.c:9 
in foo pie.c:4 
$ ./a.out 
in main main.c:6 
in foo pie.c:4 
$ 

पीएस glibc write(3) सिस्टम कॉल के माध्यम से लागू करता है क्योंकि इसमें कॉल करने के लिए कहीं और नहीं है (यह निम्नतम स्तर पहले से ही है)। libc.so.6 निष्पादित करने में सक्षम होने के साथ इसका कोई लेना-देना नहीं है।

+0

मुझे पता चला कि' -shared' विकल्प इसे काम करने से रोक सकता है, और आपको सेगमेंटेशन गलती देता है। आपको यह सुनिश्चित करना होगा कि '-shared' विकल्प वहां नहीं है या इसे '-पी' से पहले रखा गया है, इसलिए इसे अनदेखा कर दिया जाता है। –

1

कोई अच्छा तरीका नहीं है, लेकिन मैं चारों ओर एक छोटा रैपर निष्पादन योग्य बनाउंगा। इसलिए एंट्री पॉइंट फ़ंक्शन जिसे मैं चलाने के लिए कहता हूं।

0

मुझे लगता है कि आपके पास ld -e बिंदु एक प्रविष्टि बिंदु पर होगा जो तब dlopen() शेष गतिशील लिंकर को खोजने और बूटस्ट्रैप करने के लिए कार्यों का परिवार उपयोग करेगा। बेशक आप यह सुनिश्चित करें कि dlopen() ही या तो स्थिर जोड़ा गया था होगा या आप अपने स्वयं लिंकर ठूंठ के लिए पर्याप्त यह (कम से प्राप्त करने के लिए सिस्टम कॉल इंटरफेस ऐसे mmap() के रूप में बस के रूप में खुद को libc कर रहा है का उपयोग कर लागू करने के लिए हो सकता है।

इनमें से कोई भी मेरे लिए "अच्छा" नहीं लगता है। वास्तव में केवल glibc स्रोतों को पढ़ने का विचार (और ld-linux स्रोत कोड, एक उदाहरण के रूप में) नौकरी के आकार का आकलन करने के लिए पर्याप्त मेरे लिए बहुत सावधान लगता है। यह भी हो सकता है पोर्टेबिलिटी बुरा सपना। कैसे लिनक्स ld-linux लागू करता है और कैसे संबंधों ओपनसोलारिस, FreeBSD के तहत किया जाता है, और इसी तरह के बीच प्रमुख अंतर हो सकता है। (मैं नहीं जानता)।

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