Warum wird nicht der gesamte Code kompiliert Position unabhängig?
-
03-07-2019 - |
Frage
Wenn Shared Libraries kompilieren in der -fPIC Option gcc kompiliert den Code als Position unabhängig. Gibt es einen Grund (Leistung oder aus anderen Gründen), warum Sie nicht alle Codeposition unabhängig kompilieren würden?
Lösung
Es fügt eine Indirektion. Mit Position unabhängigen Code müssen Sie die Adresse Ihrer Funktion laden und dann auf sie zu springen. Normalerweise ist die Adresse der Funktion ist bereits in dem Befehlsstrom.
Andere Tipps
Ja, es gibt Performance-Gründen. Einige Zugriffe effektiv unter einer anderen Schicht Indirektionsebene die absolute Position im Speicher zu erhalten.
Es gibt auch die GOT (Global-Offset-Tabelle), die Offsets der globalen Variablen speichert. Für mich sieht das wie eine IAT-Fixup-Tabelle, die als Position klassifiziert wird abhängig von wikipedia und einigen anderen Quellen.
Dieser Artikel erklärt, wie PIC arbeitet und vergleicht sie mit der Alternative -
Neben der akzeptierten Antwort. Eine Sache, die PIC-Code Leistung schmerzt viel ist der Mangel an „IP relative Adressierung“ auf x86. Mit „IP relativer Adressierung“ können Sie für Daten fragen, die X-Bytes aus dem aktuellen Befehlszeiger ist. Dies wäre viel einfacher PIC-Code machen. Sprünge und Anrufe, sind in der Regel EIP relativ, so dass diese Pose nicht wirklich ein Problem. Allerdings wird Zugriff auf die Daten ein wenig zusätzliche Tricks erfordern. Manchmal wird ein Register vorübergehend als „Basiszeiger“, um Daten reserviert wird, dass der Code erfordert. Zum Beispiel ist eine übliche Technik, die Art und Weise Anrufe arbeiten auf x86 zu missbrauchen: Diese und andere Techniken fügen Sie eine Schicht von Dereferenzierung auf die Daten zugreift. Zum Beispiel (Offset Globale Tabelle) die GOT von gcc-Compiler verwendet. x86-64 hinzugefügt, um eine "RIP relativ" die Dinge ein Los einfacher. 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
Da unabhängigen Code vollständig positioniert Implementierung fügt eine Beschränkung auf den Code-Generator, der die Verwendung von schnellen Operationen verhindern kann, oder zusätzliche Schritte hinzufügen, um diese Einschränkung zu erhalten.
Dies könnte ein akzeptabler Kompromiss sein, ohne ein virtuelles Speichersystem Multiprozessing zu bekommen, wo man Prozesse vertrauen nicht den Speichers jeden anderen eindringen und könnte für eine bestimmte Anwendung zu jeder Basisadresse geladen werden muß.
In vielen modernen Systemen die Leistungskompromisse sind unterschiedlich, und ein relocating Loader ist oft weniger teuer (es kostet jeder Zeitcode zuerst geladen wird) als die am besten ein Optimierer tun kann, wenn es freie Herrschaft hat. Auch die Verfügbarkeit der virtuellen Adressräume verbirgt sich der größte Teil der Motivation für die Position der Unabhängigkeit an erster Stelle.
Auch virtuelle Speicher-Hardware in den meisten modernen Prozessoren (von den meisten modernen Betriebssystemen verwendet wird) bedeutet, dass viele Code (alle User-Space-Anwendungen, abgesehen von schrulliger Verwendung von mmap oder dergleichen) muss nicht Stellung unabhängig sein. Jedes Programm hat seinen eigenen Adressraum, die es beginnt bei Null denkt.
position-independent code
hat eine Performance-Overhead auf den meisten Architektur, weil sie ein zusätzliches Register erforderlich ist.
Also, das ist für die Leistung Zweck.
Heute-Betriebssystem und Compiler standardmäßig machen den Code als Position unabhängiger Code. Versuchen Sie, ohne die -fPIC Flags kompilieren, wird der Code kompiliert in Ordnung, aber Sie werden nur einen warning.OS die bekommen wie Fenster eine Technik, die als Speicher-Mapping genannt, dies zu erreichen.