Khi biên dịch các thư viện được chia sẻ trong gcc, tùy chọn -fPIC sẽ biên dịch mã dưới dạng độc lập về vị trí. Có bất kỳ lý do nào (hiệu suất hoặc cách khác) tại sao bạn không biên dịch tất cả các vị trí mã độc lập?
Khi biên dịch các thư viện được chia sẻ trong gcc, tùy chọn -fPIC sẽ biên dịch mã dưới dạng độc lập về vị trí. Có bất kỳ lý do nào (hiệu suất hoặc cách khác) tại sao bạn không biên dịch tất cả các vị trí mã độc lập?
Câu trả lời:
Bài viết này giải thích cách thức hoạt động của PIC và so sánh nó với giải pháp thay thế - di dời thời gian tải . Tôi nghĩ nó có liên quan đến câu hỏi của bạn.
Có, có lý do hiệu suất. Một số truy cập có hiệu quả nằm dưới một lớp định hướng khác để có được vị trí tuyệt đối trong bộ nhớ.
Ngoài ra còn có GOT (Bảng bù toàn cục) lưu trữ hiệu số của các biến toàn cục. Đối với tôi, đây chỉ giống như một bảng sửa lỗi IAT, được phân loại là phụ thuộc vào vị trí theo wikipedia và một số nguồn khác.
Ngoài câu trả lời được chấp nhận. Một điều làm ảnh hưởng đến hiệu suất mã PIC là thiếu "địa chỉ IP tương đối" trên x86. Với "địa chỉ IP tương đối", bạn có thể yêu cầu dữ liệu là X byte từ con trỏ hướng dẫn hiện tại. Điều này sẽ làm cho mã PIC đơn giản hơn rất nhiều.
Các bước nhảy và cuộc gọi, thường là EIP tương đối, vì vậy chúng không thực sự gây ra vấn đề. Tuy nhiên, việc truy cập dữ liệu sẽ cần thêm một chút thủ thuật. Đôi khi, một thanh ghi sẽ được bảo lưu tạm thời như một "con trỏ cơ sở" tới dữ liệu mà mã yêu cầu. Ví dụ, một kỹ thuật phổ biến là lạm dụng cách gọi hoạt động trên x86:
call label_1
.dd 0xdeadbeef
.dd 0xfeedf00d
.dd 0x11223344
label_1:
pop ebp ; now ebp holds the address of the first dataword
; this works because the call pushes the **next**
; instructions address
; real code follows
mov eax, [ebp + 4] ; for example i'm accessing the '0xfeedf00d' in a PIC way
Kỹ thuật này và các kỹ thuật khác thêm một lớp chuyển hướng vào các truy cập dữ liệu. Ví dụ, GOT (Bảng bù toàn cục) được sử dụng bởi trình biên dịch gcc.
x86-64 đã thêm chế độ "RIP tương đối" giúp mọi thứ đơn giản hơn rất nhiều .
Bởi vì việc triển khai mã hoàn toàn độc lập về vị trí sẽ thêm một ràng buộc vào trình tạo mã, điều này có thể ngăn việc sử dụng các hoạt động nhanh hơn hoặc thêm các bước bổ sung để bảo toàn ràng buộc đó.
Đây có thể là một sự đánh đổi có thể chấp nhận được để có được đa xử lý mà không cần hệ thống bộ nhớ ảo, nơi bạn tin tưởng các quá trình không xâm phạm bộ nhớ của nhau và có thể cần tải một ứng dụng cụ thể tại bất kỳ địa chỉ cơ sở nào.
Trong nhiều hệ thống hiện đại, sự cân bằng hiệu suất là khác nhau và bộ tải định vị lại thường ít tốn kém hơn (tốn bất kỳ thời gian nào mã được tải lần đầu tiên) so với điều tốt nhất mà trình tối ưu hóa có thể làm nếu nó có quyền thống trị tự do. Ngoài ra, sự sẵn có của không gian địa chỉ ảo ẩn phần lớn động lực cho sự độc lập về vị trí ngay từ đầu.
Ngoài ra, phần cứng bộ nhớ ảo trong hầu hết các bộ vi xử lý hiện đại (được hầu hết các hệ điều hành hiện đại sử dụng) có nghĩa là rất nhiều mã (tất cả các ứng dụng không gian người dùng, cấm sử dụng mmap kỳ quặc hoặc tương tự) không cần phải độc lập về vị trí. Mọi chương trình đều có không gian địa chỉ riêng mà nó cho rằng bắt đầu từ 0.
Ngày nay hệ điều hành và trình biên dịch theo mặc định làm cho tất cả mã dưới dạng mã độc lập về vị trí. Hãy thử biên dịch mà không có cờ -fPIC, mã sẽ biên dịch tốt nhưng bạn sẽ chỉ nhận được một cảnh báo. Giống như các cửa sổ của hệ điều hànhOS sử dụng một kỹ thuật được gọi là ánh xạ bộ nhớ để đạt được điều này.
Câu hỏi bắt đầu từ năm 2009. Mười năm đã trôi qua, và bây giờ tất cả các mã thực sự là độc lập về vị trí. Điều đó hiện được thực thi bởi hệ điều hành và trình biên dịch. Không có cách nào để chọn không tham gia. Tất cả mã được biên dịch bắt buộc bằng PIE và cờ -no-pic / -no-pie đang bị bỏ qua, như một phần của lý do ASLR này. Lý do là để làm chậm các ứng dụng nhanh trước đây và bán phần cứng mới hơn, dưới chiêu bài tăng cường bảo mật. Điều đó là hoàn toàn không hợp lý, bởi vì hiện nay kích thước bộ nhớ lớn cho phép chúng ta thoát khỏi địa ngục của liên kết động, biên dịch tất cả các ứng dụng một cách tĩnh.
Điều tương tự đã xảy ra trước đây, khi mọi người im lặng chấp nhận chế độ thực và các quyền tự do khác đang bị tước đoạt. Và tôi phiền bạn, MMU bị chậm nặng do chuyển đổi ngữ cảnh và độ trễ dịch địa chỉ. Bạn sẽ không tìm thấy MMU trong các hệ thống quan trọng về hiệu suất, giống như những hệ thống được các nhà khoa học sử dụng để lấy mẫu thí nghiệm vật lý.
Bạn không phàn nàn, bởi vì bạn thậm chí không biết rằng mã của bạn đang bị hạn chế bởi tất cả các bánh xe đào tạo này. Tôi có thể nói gì? Tận hưởng phần mềm chậm hơn 2 lần với PIC của họ ngay bây giờ! Hơn nữa, với sự ra đời của LLVM, sẽ sớm có JIT (mã được quản lý) được thực thi, không có quyền truy cập vào cấu trúc nội tuyến x86, điều này sẽ tiếp tục làm chậm bất kỳ mã C / C ++ nào. "Những người hy sinh tự do vì an ninh cũng không xứng đáng."