2011-09-04 24 views
12

मैंने कोड का एक टुकड़ा बनाया जिसमें एक गतिशील पुस्तकालय (lib.c), और एक मुख्य निष्पादन योग्य (main.c) शामिल है। दोनों फाइलों में मैं एक वैश्विक चर नामित करता हूं: int global। बहुत स्मार्ट नहीं है लेकिन यह सवाल नहीं है।वैश्विक चर, साझा पुस्तकालय और -एफपीआईसी प्रभाव

जब मैं गतिशील पुस्तकालय संकलन -fPIC विकल्प अनिवार्य लगता है:

gcc lib.c -fPIC -shared -o lib.so 

अन्यथा मैं:

/usr/bin/ld: /tmp/ccpUvIPj.o: relocation R_X86_64_32 against '.rodata' can not be used when making a shared object; recompile with -fPIC 

जब मैं निष्पादन योग्य संकलन ऐसा नहीं है।

gcc main.c -fPIC -ldl 
gcc main.c -ldl 

दोनों काम, लेकिन अलग-अलग व्यवहार हैं जिन्हें मैं समझा नहीं सकता, क्या आप? :

global main: 23 (0x601050) 
global lib: 23 (0x601050) 
-fPIC बिना

, lib.c में वैश्विक main.c में वैश्विक सहसंबद्ध नहीं है:

-fPIC, main.c में वैश्विक और lib.c में वैश्विक साथ

एक ही चर हैं :

global main: 23 (0x601048) 
global lib: 0 (0x7f7742e64028) 

यहाँ स्रोत है:

lib.c

#include <stdio.h> 
#include <stdlib.h> 

int global; 

int f_one() { 

    printf("global lib: %d (%p)\n", global, &global); 

    return EXIT_SUCCESS; 
} 

main.c

#include <stdio.h> 
#include <stdlib.h> 
#include <dlfcn.h> 

void * handle; 
int global; 

int main() { 

    int q = 7; 

    int (* f_one_p)(int a) = NULL; 

    global = 23; 

    handle = dlopen("./lib.so", RTLD_NOW); 

    if (handle == 0) { 
     return EXIT_FAILURE; 
    } 

    f_one_p = dlsym(handle, "f_one"); 

    printf("global main: %d (%p)\n", global, &global); 

    f_one_p(q); 

    return EXIT_SUCCESS; 

} 

जीसीसी --version: जीसीसी (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2

uname -एक: लिनक्स xxx 2.6.38-11-जेनेरिक # 48-उबंटू SMP शुक्र जुला 29 19:02:55 यूटीसी 2011 x86_64 x86_64 x86_64 जीएनयू/लिनक्स

संपादित: कोड रवि/SPARC के तहत परीक्षण किया है और अप्रत्याशित साझा वैश्विक चर का एक ही प्रकार के साथ 86/लिनक्स आर्किटेक्चर (साथ -fPIC)।

+0

संबंधित: http://stackoverflow.com/q/7216244/168175 – Flexo

उत्तर

7

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

आप दो साझा वस्तु -fPIC के साथ जोड़ा था, लेकिन अपने मुख्य कार्यक्रम तो आप अब भी दो पते int global के लिए, वैश्विक ऑफसेट तालिका का उपयोग कर एक और एक जो सिर्फ गैर पीआईसी कोड के लिए स्थानीय था होता नहीं है।

यदि आप आगे पढ़ना चाहते हैं तो really great discussion on PIC vs pic vs non PIC है।

1

डिफ़ॉल्ट रूप से, चर के निष्पादन योग्य संदर्भों का निर्माण करते समय आंतरिक रूप से एक निश्चित ऑफसेट और कोई स्थानांतरण नहीं किया जाता है।

हालांकि, आप -fPIC पास कर रहे हैं और वैश्विक डेटा तक पहुंच को GOT और GOT स्थानान्तरण के माध्यम से एक्सेस में परिवर्तित कर दिया गया है।