2011-08-05 27 views
13

Biên dịch mã thành tệp đối tượng cần phải được thực hiện độc lập nếu tệp đối tượng được dự định được tải dưới dạng thư viện được chia sẻ (.so), vì địa chỉ ảo cơ sở mà tệp đối tượng được chia sẻ được tải vào trong các quy trình khác nhau có thể khác nhau.Mã 32 bit x86 có cần phải được biên dịch PIC đặc biệt cho các tệp thư viện được chia sẻ không?

Hiện tại, tôi không gặp phải lỗi khi cố gắng tải tệp .so được biên dịch và liên kết mà không cần tùy chọn -fpic GCC trên máy tính 32 bit x86, trong khi máy tính không hoạt động trên máy tính 64 bit bit x86.

Trang web ngẫu nhiên tôi thấy rằng tôi không cần -fpic trên 32 bit vì mã được biên dịch không -fpic hoạt động theo trùng hợp ngẫu nhiên theo X86 32bit ABI cũng được sử dụng theo cách độc lập. Nhưng tôi vẫn tìm thấy phần mềm có các phiên bản riêng biệt của thư viện trong các phiên bản 32bit của họ: Một cho PIC, và một cho non-PIC. Ví dụ, trình biên dịch intel đi kèm với libirc.alibirc_pic.a, sau đó được biên dịch cho chế độ độc lập vị trí (nếu muốn liên kết tệp .a đó thành tệp .so).

Tôi tự hỏi sự khác biệt chính xác giữa việc sử dụng -fpic và không sử dụng mã cho mã 32 bit là gì và tại sao một số gói, như trình biên dịch intel vẫn gửi với các phiên bản riêng biệt của thư viện?

+0

Bạn đã thử sử dụng TLS chưa biên dịch mã không? Hoặc tải một số thư viện non-pic với phạm vi bộ nhớ chồng chéo? Riêng biệt libs tĩnh là để liên kết vào các chương trình tĩnh (libirc.a; không có pic là một chút nhanh hơn) và vào thư viện .so tĩnh (_pic.a phiên bản). – osgx

+0

Xem http://stackoverflow.com/questions/3146744/difference-in-position-independent-code-x86-vs-x86-64 – AProgrammer

Trả lời

0

địa chỉ ảo cơ sở mà các đối tượng tập tin chia sẻ được nạp vào trong các quá trình khác nhau thể thể khác nhau

Bởi vì đối tượng chia sẻ thường tải tại địa chỉ ưa thích của họ, họ có thể xuất hiện để làm việc một cách chính xác . Nhưng fPIC là ý tưởng hay cho tất cả mã được chia sẻ.

Tôi tin rằng lý do không thường có hai phiên bản của thư viện là nhiều bản phân phối sử dụng fPIC làm mặc định cho tất cả các mã.

+3

Các đối tượng chia sẻ thường được liên kết để tải tại địa chỉ 0 và chúng chắc chắn không tải đó. –

+0

Điều gì mà người Nga đã nói. Ngoài ra, bạn có thể 'prelink' thư viện để làm cho họ có một địa chỉ cơ sở ưa thích, nhưng nó là một bước riêng biệt (và tùy chọn) từ liên kết bình thường. – ninjalj

+1

@Tiếng Nga được khai thác: Đó có phải là điều duy nhất trong linux không?Các hệ điều hành khác không quá ngu xuẩn như mặc định đối với xung đột địa chỉ cơ sở 100%. –

10

Nó không phải là mã không phải PIC hoạt động "trùng hợp ngẫu nhiên" trên x86 (32-bit). Đó là liên kết động cho x86 hỗ trợ "textrels" cần thiết cần thiết để làm cho nó hoạt động. Điều này xảy ra với chi phí rất cao trong tiêu thụ bộ nhớ và thời gian khởi động, vì về cơ bản toàn bộ đoạn mã phải được vá tại thời gian tải (và do đó trở thành bộ nhớ không thể chia sẻ).

Trình duy trì liên kết động tuyên bố rằng thư viện chia sẻ non-PIC không thể được hỗ trợ trên x86_64 vì các vấn đề cơ bản trong kiến ​​trúc (chuyển vị địa chỉ ngay không được lớn hơn 32 bit) nhưng vấn đề này có thể được giải quyết dễ dàng bằng cách luôn tải các thư viện trong 4gb đầu tiên của không gian địa chỉ ảo. Tất nhiên mã PIC là rất rẻ tiền trên x86_64 (PIC không phải là một kẻ giết người hiệu suất như nó là trên 32-bit x86) vì vậy họ có lẽ phải để giữ cho nó không được hỗ trợ và ngăn chặn kẻ ngu từ làm thư viện non-PIC ...

+0

Cảm ơn, điều đó có ý nghĩa. Nếu tôi biên dịch một PIC lib trên x86, nó không sử dụng textrels nữa, tôi nghi ngờ? Tại sao nó vẫn là một kẻ giết người thực hiện? –

+6

Mã PIC yêu cầu đăng ký bổ sung để giữ địa chỉ cơ sở. Trên x86 bạn đã có quá ít thanh ghi, do đó, đặt trước thêm một lần nữa làm cho trình biên dịch tràn vào sổ đăng ký vào bộ nhớ thậm chí thường xuyên hơn. –

+2

PIC là một kẻ giết người thực hiện trên x86 vì việc tải thanh ghi GOT là tốn kém. Nó đòi hỏi một cuộc gọi chức năng và đọc/lưu địa chỉ trả về khỏi ngăn xếp. x86_64 có địa chỉ tương đối 'eip' làm cho nó không cần đăng ký GOT. –