web-dev-qa-db-fra.com

Pourquoi tous les codes compilés ne sont-ils pas indépendants des positions?

Lors de la compilation de bibliothèques partagées dans gcc, l'option -fPIC compile le code indépendamment de la position. Existe-t-il une raison (performance ou autre) pour laquelle vous ne compileriez pas tous les codes indépendamment du code? 

68
ojblass

Cela ajoute une indirection. Avec un code indépendant de la position, vous devez charger l’adresse de votre fonction puis y accéder. Normalement, l'adresse de la fonction est déjà présente dans le flux d'instructions.

58
wowest

Cet article explique le fonctionnement du PIC et le compare à l’alternative - temps de chargement . Je pense que cela concerne votre question.

26
Eli Bendersky

Oui, il y a des raisons de performance. Certains accès sont effectivement sous une autre couche d'indirection pour obtenir la position absolue en mémoire.

Il y a aussi le GOT (Global Offset Table) qui stocke les décalages des variables globales. Pour moi, cela ressemble à une table de correction IAT, qui est classée en tant que position dépendante par wikipedia et quelques autres sources.

http://en.wikipedia.org/wiki/Position_independent_code

26
Unknown

En plus de la réponse acceptée. Une des choses qui nuit le plus aux performances du code PIC est l’absence "d’adressage relatif IP" sur x86. Avec "adressage relatif IP", vous pouvez demander des données représentant X octets à partir du pointeur d'instruction en cours. Cela rendrait le code PIC beaucoup plus simple.

Les sauts et les appels sont généralement relatifs à EIP, ils ne posent donc pas vraiment de problème. Cependant, accéder aux données demandera un peu plus de tricherie. Parfois, un registre sera temporairement réservé en tant que "pointeur de base" aux données requises par le code. Par exemple, une technique courante consiste à abuser de la façon dont les appels fonctionnent sur 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

Cette technique et d'autres techniques ajoutent une couche d'indirection aux accès aux données. Par exemple, le GOT (Global offset table) utilisé par les compilateurs gcc.

x86-64 a ajouté un mode "RIP relatif" qui simplifie les choses lot.

17
Evan Teran

L'implémentation de code totalement indépendant de la position ajoute une contrainte au générateur de code, qui peut empêcher l'utilisation d'opérations plus rapides, ou ajouter des étapes supplémentaires pour préserver cette contrainte.

Cela peut être un compromis acceptable pour obtenir un multitraitement sans système de mémoire virtuelle, dans lequel vous faites confiance aux processus pour ne pas envahir la mémoire de l'autre et qui peuvent nécessiter le chargement d'une application particulière à n'importe quelle adresse de base.

Dans de nombreux systèmes modernes, les compromis en termes de performances sont différents et un chargeur de localisation est souvent moins coûteux (il coûte chaque fois que le code est chargé en premier) que ce que l'optimiseur peut faire de mieux s'il a le temps libre. En outre, la disponibilité d'espaces d'adresses virtuels masque en grande partie la motivation pour l'indépendance de la position.

2
RBerteig

De plus, le matériel de mémoire virtuelle de la plupart des processeurs modernes (utilisé par la plupart des systèmes d'exploitation modernes) signifie que beaucoup de code (toutes les applications d'espace utilisateur, à l'exception de l'utilisation insolite de mmap ou similaire) n'a pas besoin d'être indépendant de la position. Chaque programme obtient son propre espace d'adressage qui, à son avis, commence à zéro.

1
smcameron

position-independent code a une surcharge de performances sur la plupart des architectures, car elle nécessite un registre supplémentaire.

Donc, ceci est à des fins de performance.

1
Eric Wang

La question date de 2009. Dix ans ont passé et maintenant tout le code est indépendant de la position. Cela est maintenant appliqué par les systèmes d'exploitation et les compilateurs. Il n'y a aucun moyen de se retirer. Tout le code est forcé avec PIE et le drapeau -no-pic/-no-pie est ignoré dans le cadre de cette excuse ASLR. La raison en est de ralentir les applications jadis rapides et de vendre du matériel plus récent, sous prétexte d’une sécurité accrue. C'est complètement irrationnel, car les grandes tailles de mémoire nous permettent maintenant de nous débarrasser de l'enfer de la liaison dynamique, en compilant toutes les applications de manière statique.

Même chose avant, quand les gens acceptaient silencieusement le mode réel et que d’autres libertés s’enlevaient. Et je vous dérange, MMU subit un fort ralentissement en raison de changements de contexte et du temps de latence de la traduction des adresses. Vous ne trouverez pas MMU dans les systèmes à performances critiques, tels que ceux utilisés par les scientifiques pour échantillonner des expériences de physique.

Vous ne vous plaignez pas, car vous ne savez même pas que votre code est handicapé par toutes ces roues d'entraînement. Que puis-je dire? Profitez dès maintenant du logiciel 2 fois plus lent avec leur PIC! De plus, avec l'avènement de LLVM, il y aura bientôt un JIT (code managé) imposé, sans accès à l'assembly inline x86, ce qui ralentira davantage le code C/C++. "Ceux qui sacrifient la liberté pour la sécurité ne méritent ni l'un ni l'autre."

1
SmugLispWeenie

De nos jours, le système d'exploitation et le compilateur font de tout le code par défaut un code indépendant de la position. Essayez de compiler sans l'indicateur -fPIC, le code se compilera bien mais vous obtiendrez juste un avertissement.OS comme Windows utilisent une technique appelée mappage de mémoire pour y parvenir. 

0
Govardhan Murali