2011-08-27 21 views
25

Gần đây tôi đã nhận được:Tại sao fPIC hoàn toàn cần thiết trên 64 chứ không phải trên nền tảng 32 bit?

... di dời R_X86_64_32 đối với `biểu tượng địa phương 'không thể được sử dụng khi tạo đối tượng được chia sẻ; biên dịch lại với -fPIC

lỗi khi cố gắng biên dịch chương trình làm thư viện được chia sẻ. Bây giờ giải pháp cho điều này không quá khó (biên dịch lại tất cả các phụ thuộc với -fPIC), nhưng sau một số nghiên cứu, nó chỉ ra rằng vấn đề này chỉ xuất hiện trên các nền tảng x86-64. Trên 32 bit bất kỳ mã phụ thuộc vị trí nào vẫn có thể được di chuyển bởi trình tải động.

tốt nhất answer tôi có thể tìm thấy là:

x86 có hỗ trợ cho .text di dời (đó là những gì sẽ xảy ra khi bạn có mã vị trí-dependend). Hỗ trợ này có chi phí, tức là mỗi trang chứa việc di dời như vậy sẽ không được chia sẻ về cơ bản, ngay cả khi nó nằm trong thư viện được chia sẻ, do đó làm hỏng khái niệm chia sẻ của libs được chia sẻ. Do đó chúng tôi quyết định không cho phép này trên amd64 (cộng với nó tạo ra vấn đề nếu giá trị cần hơn 32bit, bởi vì tất cả relocs .text chỉ có kích thước 'word32')

Nhưng tôi không tìm thấy điều này khá đầy đủ . Nếu nó là trường hợp mà relocations làm hỏng khái niệm của thư viện được chia sẻ, tại sao nó có thể được thực hiện trên nền tảng 32bit? Ngoài ra, nếu có những thay đổi cần thiết cho định dạng ELF để hỗ trợ 64bit, thì tại sao không phải tất cả các trường đều tăng kích thước để phù hợp?

Đây có thể là một điểm nhỏ, nhưng được thúc đẩy bởi thực tế là a) mã được đề cập là mã khoa học và sẽ rất tuyệt nếu không phải thực hiện lần truy cập và b) thông tin này là không thể để tìm thấy ở nơi đầu tiên!

[Edit: 'Trả lời'

@awoodlands answer có lẽ là 'câu trả lời theo nghĩa đen' tốt nhất, @servn added một số thông tin tốt.

Trong một tìm kiếm để tìm thêm về các loại khác nhau của di dời tôi thấy this và cuối cùng là một x86_64 ABI reference (xem trang 68) ]

+1

Tôi không biết câu trả lời cho câu hỏi của bạn, nhưng bạn nên lưu ý rằng ' -FPIC' hiệu suất hit được giảm bớt trên x86-64 (tương đối so với x86-32) bởi vì nó có nhiều thanh ghi, địa chỉ liên quan đến PC, và một ABI được thiết kế với PIC trong tâm trí. Tôi sẽ không nói rằng nó đã biến mất *, nhưng hãy đo nó và bạn có thể ngạc nhiên. – zwol

+0

Điều đó dường như là sự đồng thuận, một hình phạt nhỏ về hiệu suất cho những gì được thừa nhận là một sự thuận tiện lớn. Tôi sẽ phải tự mình thử. –

+0

Câu hỏi chính là tất nhiên tại sao một trình biên dịch có một "tùy chọn bắt buộc". "Bạn không nói từ ma thuật" là một trò chơi khá trẻ con. – MSalters

Trả lời

10

Theo tôi được biết vấn đề là x86-64 dường như giới thiệu một mới hơn, nhanh hơn cách tham chiếu dữ liệu liên quan đến con trỏ chỉ dẫn, không tồn tại cho x86-32.

This article có một tốt đẹp trong phân tích sâu về nó, và cung cấp cho các tóm tắt như sau:

Khả năng của x86-64 sử dụng hướng dẫn con trỏ tương đối bù đến các địa chỉ dữ liệu là một tối ưu hóa tốt đẹp, nhưng trong thư viện chung giả định tình huống về vị trí tương đối của dữ liệu không hợp lệ và không thể sử dụng được. Trong trường hợp này, quyền truy cập vào dữ liệu chung (tức là mọi thứ có thể được thay đổi xung quanh bạn) phải trải qua một lớp trừu tượng, cụ thể là bảng bù toàn cầu.

I.e. -fPIC giải quyết thêm một lớp trừu tượng để giải quyết, để làm cho những gì trước đây có thể (và một tính năng mong muốn) theo kiểu địa chỉ thông thường vẫn hoạt động với kiến ​​trúc mới hơn.

+0

Đó là một bài viết tuyệt vời, cảm ơn! –

7

Nhưng tôi không thấy điều này khá đầy đủ. Nếu nó là trường hợp mà relocations làm hỏng khái niệm của thư viện được chia sẻ, tại sao nó có thể được thực hiện trên nền tảng 32bit?

Nó có thể được thực hiện, nó không phải là đặc biệt hiệu quả ... tính toán relocations có chi phí thời gian chạy, thực thi relocated mất bộ nhớ bổ sung, và cơ chế giới thiệu rất nhiều phức tạp vào loader thực thi. Ngoài ra, các bản phân phối Linux thực sự muốn khuyến khích tất cả các mã được biên dịch bằng -fPIC vì việc thay đổi địa chỉ cơ sở của một tệp thực thi là một chiến lược giảm thiểu khiến việc khai thác bằng văn bản cho các lỗ hổng bảo mật trở nên khó khăn hơn.

Điều đáng nói đến là -fPIC thường không phải là chi phí hiệu suất đáng kể, đặc biệt nếu bạn sử dụng - khả năng ẩn = ẩn hoặc tương đương.

tại sao không phải tất cả các trường đều tăng kích thước để phù hợp?

"Trường" được đề cập là trường trực tiếp của chế độ địa chỉ x86-64, không nằm dưới sự kiểm soát của các nhà phát triển ELF.

+0

Cảm ơn câu trả lời của bạn, nó thực sự thêm rất nhiều liên kết được cung cấp bởi @awoodland - đặc biệt là sự thừa nhận rằng nó _can_ được thực hiện nhưng tại một điểm trở nên ngớ ngẩn. Để làm rõ: fvisibility = hidden nghĩa là tất cả các chức năng không được xuất khẩu rõ ràng sẽ không được gọi thông qua PLT và do đó mức độ bỏ qua được loại bỏ? –

+0

Có, fvisibility = hidden sẽ loại bỏ các PLT indirection. – servn