Paylaşılan kitaplıkları gcc'de derlerken -fPIC seçeneği kodu konumdan bağımsız olarak derler. Tüm kod konumlarını bağımsız olarak derlememenizin herhangi bir nedeni (performans veya başka türlü) var mı?
Paylaşılan kitaplıkları gcc'de derlerken -fPIC seçeneği kodu konumdan bağımsız olarak derler. Tüm kod konumlarını bağımsız olarak derlememenizin herhangi bir nedeni (performans veya başka türlü) var mı?
Yanıtlar:
Bir yönlendirme ekler. Konumdan bağımsız kodla, işlevinizin adresini yüklemeniz ve ardından ona atlamanız gerekir. Normalde, fonksiyonun adresi komut akışında zaten mevcuttur.
Bu makale, PIC'in nasıl çalıştığını açıklar ve onu alternatif yükleme süresi yer değiştirmeyle karşılaştırır . Sorunuzla alakalı olduğunu düşünüyorum.
Evet, performans nedenleri var. Bazı erişimler, bellekteki mutlak konumu elde etmek için etkin bir şekilde başka bir yönlendirme katmanı altındadır.
Global değişkenlerin ofsetlerini saklayan GOT (Global ofset tablosu) da vardır. Bana göre bu, wikipedia ve diğer birkaç kaynak tarafından konuma bağlı olarak sınıflandırılan bir IAT düzeltme tablosuna benziyor.
Kabul edilen cevaba ek olarak. PIC kod performansına çok zarar veren bir şey, x86'da "IP'ye göre adresleme" olmamasıdır. "IP'ye göre adresleme" ile mevcut komut işaretçisinden X bayt olan verileri isteyebilirsiniz. Bu, PIC kodunu çok daha basit hale getirir.
Atlamalar ve çağrılar genellikle EIP'ye bağlıdır, bu nedenle bunlar gerçekten bir sorun oluşturmaz. Bununla birlikte, verilere erişmek biraz ekstra hile gerektirecektir. Bazen bir kayıt, kodun gerektirdiği verilere geçici olarak bir "temel işaretçi" olarak ayrılacaktır. Örneğin, yaygın bir teknik, çağrıların x86'da çalışma şeklini kötüye kullanmaktır:
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
Bu ve diğer teknikler, veri erişimlerine bir dolaylılık katmanı ekler. Örneğin, gcc derleyicileri tarafından kullanılan GOT (Global ofset tablosu).
x86-64, işleri çok daha basit hale getiren bir "RIP göreli" modu ekledi .
Çünkü tamamen konumdan bağımsız kod uygulamak, kod üretecine daha hızlı işlemlerin kullanılmasını engelleyebilecek bir kısıtlama ekler veya bu kısıtlamayı korumak için fazladan adımlar ekleyebilir.
Bu, birbirlerinin belleğini işgal etmeyecek süreçlere güvendiğiniz ve herhangi bir temel adreste belirli bir uygulamayı yüklemeniz gerekebileceği bir sanal bellek sistemi olmadan çoklu işlemeyi elde etmek için kabul edilebilir bir takas olabilir.
Pek çok modern sistemde performans ödünleşmeleri farklıdır ve yer değiştiren bir yükleyici genellikle daha ucuzdur (kodun ilk yüklendiği her zaman maliyeti vardır), bir optimize edicinin serbest saltanatı varsa yapabileceği en iyisinden daha ucuzdur. Ayrıca, sanal adres alanlarının mevcudiyeti, ilk etapta konum bağımsızlığı motivasyonunun çoğunu gizler.
Ayrıca, çoğu modern işlemcideki sanal bellek donanımı (çoğu modern işletim sistemi tarafından kullanılır), çok sayıda kodun (mmap veya benzerinin ilginç kullanımı dışında tüm kullanıcı alanı uygulamaları) konumdan bağımsız olması gerekmediği anlamına gelir. Her program, sıfırdan başladığını düşündüğü kendi adres alanını alır.
position-independent code
Ekstra bir kayıt gerektirdiği için çoğu mimaride bir performans ek yükü vardır.
Yani, bu performans amaçlıdır.
Günümüzde işletim sistemi ve derleyici varsayılan olarak tüm kodu konumdan bağımsız kod yapar. -FPIC bayrağı olmadan derlemeyi deneyin, kod iyi derlenir, ancak yalnızca bir uyarı alırsınız. OS benzeri pencereler bunu başarmak için bellek eşleme adı verilen bir teknik kullanır.
Soru 2009'a tarihleniyor. On yıl geçti ve şimdi tüm kodlar aslında konumdan bağımsız. Bu artık işletim sistemleri ve derleyiciler tarafından uygulanmaktadır. Vazgeçmenin bir yolu yok. Tüm kod PIE ile zorla derlenir ve bu ASLR bahanesinin bir parçası olarak -no-pic / -no-pasta bayrağı göz ardı edilmektedir. Bunun nedeni, eskiden hızlı uygulamaları yavaşlatmak ve artırılmış güvenlik kisvesi altında daha yeni donanımlar satmaktır. Bu tamamen mantıksız, çünkü artık büyük bellek boyutları, tüm uygulamaları statik olarak derleyerek dinamik bağlantıların cehenneminden kurtulmamızı sağlıyor.
Aynı şey daha önce insanlar sessizce gerçek modu ve diğer özgürlüklerin ellerinden alınmasını kabul ettiklerinde oldu. Ve umursuyorum, MMU bağlam anahtarları ve adres çeviri gecikmesi nedeniyle ağır bir yavaşlama yaşıyor. Bilim adamlarının fizik deneylerini örneklemek için kullandıkları gibi performans açısından kritik sistemlerde MMU bulamazsınız.
Şikayet etmiyorsunuz, çünkü kodunuzun tüm bu eğitim çarkları tarafından engellendiğini bile bilmiyorsunuz. Ne söyleyebilirim? Şimdi PIC'leriyle 2 kat daha yavaş yazılımın keyfini çıkarın! Dahası, LLVM'nin gelişiyle, yakında x86 satır içi derlemesine erişimi olmayan zorunlu JIT (yönetilen kod) olacak ve bu da herhangi bir C / C ++ kodunu daha da yavaşlatacaktır. "Güvenlik için özgürlüğü feda edenler ikisini de hak etmiyor."