2011-09-04 28 views
12

Tôi đã tạo một đoạn mã bao gồm thư viện động (lib.c) và một tệp thực thi chính (main.c). Trong cả hai tệp, tôi xác định biến toàn cầu có tên: int global. Không thông minh lắm nhưng không phải là câu hỏi.Biến toàn cục, thư viện được chia sẻ và hiệu ứng -fPIC

Khi tôi biên soạn các thư viện động tùy chọn -fPIC dường như bắt buộc:

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

nếu không tôi nhận được:

/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 

Khi tôi biên dịch thực thi nó không phải là.

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

Cả hai công việc, nhưng có những hành vi khác nhau tôi không thể giải thích, có thể không? :

với -fPIC, toàn cầu trong main.c và toàn cầu trong lib.c là các biến giống nhau:

global main: 23 (0x601050) 
global lib: 23 (0x601050) 

mà không -fPIC, toàn cầu trong lib.c không tương quan với toàn cầu trong main.c :

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

Dưới đây là nguồn:

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; 

} 

gcc --version: gcc (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2

uname -a: Linux xxx 2.6.38-11-generiC# 48-Ubuntu SMP Fri Jul 29 19:02:55 UTC 2011 x86_64 x86_64 x86_64 GNU/Linux

chỉnh sửa: mã kiểm tra dưới SUN/sparc và x86/kiến ​​trúc Linux với cùng một loại biến toàn cầu chia sẻ bất ngờ (với -fPIC).

+0

Liên quan: http://stackoverflow.com/q/7216244/168175 – Flexo

Trả lời

7

Khi bạn biên dịch với -fPIC đối tượng được đề cập sẽ xác định địa chỉ của biểu tượng chung bằng cách sử dụng Bảng bù toàn cầu. Điều gì xảy ra mặc dù khi một phần của mã là -fPIC và một phần không phải là một trong số int global s của bạn sẽ sử dụng bảng này để xác định địa chỉ trong khi phần kia không có.

Nếu bạn có hai đối tượng được chia sẻ được liên kết với -fPIC, nhưng chương trình chính của bạn thì bạn vẫn có hai địa chỉ cho int global, một sử dụng bảng bù toàn cục và một địa chỉ chỉ là cục bộ cho mã không phải PIC.

Có một số really great discussion on PIC vs pic vs non PIC nếu bạn muốn đọc thêm.

1

Theo mặc định, khi xây dựng một tham chiếu thực thi cho các biến được thực hiện nội bộ, với một bù đắp cố định và không di dời.

Tuy nhiên, bạn đang vượt qua -fPIC và quyền truy cập vào dữ liệu chung được chuyển đổi thành quyền truy cập thông qua chuyển đổi GOT và GOT được thêm vào.

Các vấn đề liên quan