Під час компіляції спільних бібліотек у gcc параметр -fPIC компілює код як незалежний від позиції. Чи є якась причина (продуктивність чи інша), чому ви не скомпілювали б усі позиції коду незалежними?
Під час компіляції спільних бібліотек у gcc параметр -fPIC компілює код як незалежний від позиції. Чи є якась причина (продуктивність чи інша), чому ви не скомпілювали б усі позиції коду незалежними?
Відповіді:
У цій статті пояснюється, як працює PIC, та порівнюється з альтернативою - перенесенням часу завантаження . Я думаю, це відповідає вашому питанню.
Так, є причини ефективності. Деякі доступні фактично перебувають під іншим непрямим шаром, щоб отримати абсолютну позицію в пам'яті.
Існує також GOT (глобальна таблиця зсувів), яка зберігає зміщення глобальних змінних. Для мене це просто виглядає як таблиця виправлення IAT, яка класифікується як залежна від положення wikipedia та кількома іншими джерелами.
Крім прийнятої відповіді. Одна річ, яка сильно шкодить продуктивності коду PIC, - це відсутність "відносної адресації IP" на x86. За допомогою "відносної адресації IP" ви можете запитати дані, які становлять X байт з поточного вказівника інструкцій. Це зробило б код PIC набагато простішим.
Стрибки та дзвінки, як правило, відносно EIP, тому це насправді не створює проблем. Однак для доступу до даних знадобиться трохи додаткових хитрощів. Іноді реєстр буде тимчасово зарезервований як "базовий вказівник" на дані, які вимагає код. Наприклад, поширеною технікою є зловживання роботою викликів на 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
Цей та інші прийоми додають рівень непрямості до доступу до даних. Наприклад, GOT (глобальна таблиця зсувів), що використовується компіляторами gcc.
x86-64 додав режим "RIP відносний", що робить речі набагато простішими.
Оскільки реалізація повністю незалежного від позиції коду додає обмеження до генератора коду, що може запобігти використанню швидших операцій, або додає додаткові кроки для збереження цього обмеження.
Це може бути прийнятним компромісом, щоб отримати багатопроцесорну обробку без системи віртуальної пам’яті, де ви довіряєте процесам не вторгатись у пам’ять один одного і, можливо, доведеться завантажити певний додаток за будь-якою базовою адресою.
У багатьох сучасних системах компроміси з продуктивністю різні, і переїзд навантажувача часто є менш дорогим (він коштує будь-якого часу, коли код завантажується спочатку), ніж найкраще, що може зробити оптимізатор, якщо воно вільне. Крім того, наявність віртуальних адресних просторів приховує в першу чергу більшу частину мотивації незалежності позицій.
Крім того, апаратне забезпечення віртуальної пам’яті в більшості сучасних процесорів (використовується більшістю сучасних ОС) означає, що багато коду (всі програми користувацького простору, за винятком химерного використання mmap тощо) не повинні бути незалежними від позиції. Кожна програма отримує власний адресний простір, який, на її думку, починається з нуля.
В даний час операційна система та компілятор за замовчуванням роблять весь код як незалежний від позиції код. Спробуйте скомпілювати без прапорця -fPIC, код буде скомпільовано нормально, але ви просто отримаєте попередження. ОС, як Windows, використовує техніку, яка називається відображенням пам'яті для досягнення цього.
Питання датується 2009 роком. Минуло десять років, і тепер весь код фактично не залежить від позиції. Зараз це забезпечується операційними системами та компіляторами. Немає можливості відмовитись. Весь код компілюється за допомогою PIE, а прапорець -no-pic / -no-pie ігнорується, як частина цього виправдання ASLR. Причиною цього є уповільнення раніше швидких програм та продаж нового обладнання під виглядом підвищеної безпеки. Це абсолютно ірраціонально, адже зараз великі обсяги пам'яті дозволяють нам взагалі позбутися пекла динамічного зв’язування, збираючи всі програми статично.
Те саме траплялося і раніше, коли люди мовчки приймали реальний режим та відбирання інших свобод. І я пам’ятаю, MMU зазнає значного уповільнення через перемикання контексту та затримку перекладу адрес. Ви не знайдете MMU у критично важливих системах, таких як ті, що використовуються вченими для вибірки фізичних експериментів.
Ви не скаржитесь, бо навіть не знаєте, що всі ці тренувальні колеса обмежують ваш код. Що я можу сказати? Насолоджуйтесь програмним забезпеченням PIC у 2 рази повільніше! Навіть більше, з появою LLVM, незабаром буде застосовано JIT (керований код), без доступу до вбудованої збірки x86, що ще більше уповільнить будь-який код C / C ++. "Ті, хто жертвує свободою заради безпеки, не заслуговують ні того, ні іншого".