2009-10-19 46 views
26

Ít nhất là trên Linux và Solaris, các thư viện tĩnh thực sự chỉ là một bó được biên dịch .o được đưa vào một tệp lớn. Khi biên dịch một thư viện tĩnh, thường cờ -fpic được ommited, do đó, mã được tạo ra phụ thuộc vào vị trí.Liên kết thư viện được chia sẻ với thư viện tĩnh: thư viện tĩnh có được biên dịch khác với một ứng dụng đang liên kết nó không?

Bây giờ hãy nói thư viện tĩnh của tôi là B. Tôi đã xây dựng nó và có tệp .a thực sự là một tập hợp tất cả các tệp .o phụ thuộc vào vị trí. Bây giờ tôi có một thư viện chia sẻ tôi muốn xây dựng, A, và tôi muốn nó liên kết tĩnh B. Khi tôi xây dựng A, tự nhiên tôi sẽ sử dụng cờ -fpic để làm cho vị trí mã được tạo ra độc lập. Nhưng nếu tôi liên kết với B, tôi có đang trộn vị trí phụ thuộc và vị trí các tệp đối tượng độc lập không?

Tôi nhận được rất nhiều lỗi di chuyển văn bản trừ khi tôi cũng chỉ định văn bản -mimpure và tôi nghĩ đây có thể là nguyên nhân. Dường như khi tôi biên dịch một thư viện, tôi thực sự cần biên dịch nó lần, một phiên bản được chia sẻ, một phiên bản tĩnh và một phiên bản tĩnh-có-thể-được-dùng-chia-libs. Tôi có đúng không? Tôi chỉ có thể tiếp tục sử dụng văn bản -mimpure nhưng trang g ++ man nói rằng nếu bạn làm điều đó đối tượng không thực sự kết thúc được chia sẻ (nó không rõ ràng nếu nó là tất cả unshared hoặc chỉ các phần liên kết tĩnh mặc dù, không ai biết?) .

+0

Câu hỏi được nêu chính xác, anh ta bỏ qua ''-fpic' trong đoạn đầu tiên, dẫn đến mã phụ thuộc vào vị trí, sau đó sử dụng nó trong đoạn thứ hai, dẫn đến mã vị trí độc lập. –

Trả lời

24

Bạn không phải sử dụng mã PIC trong các đối tượng được chia sẻ (như bạn đã phát hiện ra bạn có thể sử dụng tùy chọn -mimpure-text để cho phép điều đó).

Điều đó nói rằng, mã không phải PIC trong các đối tượng được chia sẻ nặng hơn. Với mã PIC, các trang văn bản trong bộ nhớ chỉ là ánh xạ bộ nhớ trực tiếp của các trang văn bản trên đĩa. Điều này có nghĩa là nếu nhiều tiến trình đang sử dụng đối tượng được chia sẻ, chúng có thể chia sẻ trang bộ nhớ.

Nhưng nếu bạn không có mã PIC, khi trình liên kết thời gian chạy tải đối tượng được chia sẻ, nó sẽ phải áp dụng sửa lỗi cho các trang văn bản. Điều này có nghĩa là mọi quá trình sử dụng đối tượng chia sẻ sẽ có phiên bản duy nhất của bất kỳ trang văn bản nào có sửa chữa trên nó (ngay cả khi đối tượng được chia sẻ được tải tại cùng một địa chỉ như copy-on-write chỉ thông báo rằng trang đó sửa đổi và không phải là nó đã được sửa đổi trong cùng một cách).

Với tôi, vấn đề quan trọng là liệu bạn sẽ đồng thời có nhiều quy trình đang chạy mà mỗi quá trình tải đối tượng được chia sẻ. Nếu bạn làm, nó chắc chắn là giá trị đảm bảo tất cả các mã trong SO là PIC.

Nhưng nếu đó không phải là trường hợp và chỉ có một quá trình duy nhất có đối tượng được chia sẻ được tải, nó không gần như là quan trọng.

+0

Trên thực tế, nếu bạn biết chỉ có một quá trình sẽ tải nó, nó không thể là một lợi ích hiệu suất để biên dịch mà không có pic? Bởi vì tiết kiệm một đăng ký. –

+1

@JosephGarvin PIC tiêu thụ một đăng ký trong mã 32 bit x86, nhưng không phải trong mã 64 bit. Bộ chỉ lệnh x64 hỗ trợ định địa chỉ truy cập chương trình tương đối - dữ liệu tải được bù đắp NNNN byte từ địa chỉ bộ nhớ của lệnh (lệnh tiếp theo sau) hiện đang thực hiện lệnh.Mã PIC trong x64 không yêu cầu đăng ký con trỏ GOT. – dthorpe

+0

Cảm ơn bạn đã giải thích tuyệt vời! – rkellerm

1

Là một cách tiếp cận thay thế, hãy gửi hai thư viện: thư viện được chia sẻ của bạn và miền tĩnh bạn đang liên kết với nhau. Họ nên liên kết vào tệp thực thi cuối cùng một cách chính xác.

3

Tôi làm như sau trong giai đoạn liên kết cho phiên bản thư viện đối tượng được chia sẻ của thư viện tĩnh: g ++ -shared -o libshared.so -Wl, - toàn bộ lưu trữ -fPIC -lstatic -Wl, - no- toàn bộ lưu trữ. Kể từ khi - lưu trữ -whole liên kết mọi đối tượng trong một danh sách (libs tĩnh) (của libstatic.a dạng) Tôi tin rằng trước đó (danh sách) với -fPIC là tất cả các OP cần làm.

+0

bạn có thể giải thích rõ ràng hơn không? – gyro

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