2012-05-14 18 views
5

Tôi có một số câu hỏi về thứ tự liên kết gcc. Người đàn ông GCC nói các biểu tượng tìm kiếm liên kết từ trái sang phải mà không cần tìm kiếm lặp lại theo mặc định. Đây là thử nghiệm của tôi:một số câu hỏi về thứ tự tìm kiếm của GCC linker

main.c

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

int main() 
{ 
     printf("HELLO WROLD\n"); 
     return 0; 
} 

printf.c

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

int printf(const char *fmt, ...) 
{ 
     write(1, "AAA\n", 4); 
} 

[[email protected] testcode]# gcc -c -fno-builtin-printf *.c 
[[email protected] testcode]# gcc -o test main.o printf.o 
[[email protected] testcode]# ./test 
AAA 
[[email protected] testcode]# gcc -o test printf.o main.o 
[[email protected] testcode]# ./test 
AAA 


[[email protected] testcode]# ar rcs libprintf.a printf.o 
[[email protected] testcode]# gcc -o test libprintf.a main.o 
[[email protected] testcode]# ./test 
HELLO WROLD 
[[email protected] testcode]# gcc -o test main.o libprintf.a 
[[email protected] testcode]# ./test 
AAA 


[[email protected] testcode]# gcc -shared -o libprintf.so printf.o 
[[email protected] testcode]# gcc -o test libprintf.so main.o 
[[email protected] testcode]# export LD_LIBRARY_PATH=. 
[[email protected] testcode]# ./test 
AAA 
[[email protected] testcode]# gcc -o test main.o libprintf.so 
[[email protected] testcode]# ./test 
AAA 

Từ kết quả, chúng ta có thể thấy thứ tự của .o và .o, .o và .so làm cho không có sự khác biệt, chỉ có trật tự của .o và .a có hiệu lực. Nhưng điều đó không phù hợp với trang người dùng gcc. Vậy tại sao?

+0

Tôi đã sử dụng -v, nhưng tôi vẫn không hiểu tại sao. Bạn có thể giải thích chi tiết điều này không? – D3Hunter

+0

Tôi không thể sử dụng -nodefaultlibs, đối với một số chức năng trong crt như _start nên tồn tại. – D3Hunter

+0

Tôi đoán tôi TL, DR-ed trước đây. Theo cách nào bạn nghĩ 'nó' không phù hợp với trang gcc amn? – sehe

Trả lời

8

gcc thực sự xử lý các tệp đối tượng từ trái sang phải. Khi bạn có

gcc -o test libprintf.a main.o 

Tệp đối tượng đầu tiên gcc thấy là libprintf.a. Không có biểu tượng chưa được giải quyết cho đối tượng đầu ra tại thời điểm này, vì vậy không có gì từ libprintf.a được sử dụng/cần thiết. Tiếp theo, main.o được xử lý, trình liên kết tạo ghi chú về thực tế là printf chưa được giải quyết và sau đó tiếp tục xử lý các thư viện tiềm ẩn, nơi nó có thể phân giải biểu tượng printf chưa được giải quyết in main.o.

Tương tự như vậy, khi bạn có:

gcc -o test main.o libprintf.a 

Các tập tin đối tượng đầu tiên được xử lý được main.o, nơi biểu tượng chưa được giải quyết printf được ghi nhận, tiếp theo để được xử lý là libprintf.a mà từ đó các mối liên kết có thể giải quyết printf. Khi libc cuối cùng được xử lý, printf đã được giải quyết sao cho trường hợp printf trong libc không được sử dụng.

Khi liên kết với các tập tin .o:

gcc -o test main.o printf.o 

Thư viện libc một lần nữa đối xử như thể nó đã được chỉ định vào cuối dòng lệnh, vì vậy biểu tượng printf được giải quyết từ đầu tiên (từ trái sang -right) tập tin đối tượng xác định nó.

Đối với cả hai trường hợp libprintf.so, thư viện libc lại được xử lý như thể nó được chỉ định ở cuối dòng lệnh. Điều khác biệt với trường hợp thư viện tĩnh là thứ tự từ trái sang phải của các thư viện *.so xác định thứ tự tìm kiếm ký hiệu động thời gian chạy. Vì đơn đặt hàng này có libprintf.so trước khi ẩn libc.so, phiên bản printf trong libprintf.so được sử dụng.

gcc -o test libprintf.so main.o 
gcc -o test main.o libprintf.so 

Như một thí nghiệm bổ sung, bạn có thể thử:

gcc -o test main.o -lc libprintf.so 

này nên hiển thị các phiên bản của printf được sử dụng từ libc.so thay vì libprintf.so-lc đến trước libprintf.so theo thứ tự từ trái sang phải.

+0

Vậy tại sao .o và .o, .o và .so không hoạt động? – D3Hunter

+0

Đã chỉnh sửa để thêm giải thích cho những trường hợp này ... xin lỗi vì bỏ qua những người trong phản hồi ban đầu. –