gcc vs clang: Einfügen einer Funktion mit -fPIC

8

Betrachten Sie diesen Code:

%Vor%

Beim Kompilieren mit gcc 7.2:

%Vor%

Dies emittiert:

%Vor%

Wenn Sie jedoch den gleichen Code mit denselben Flags unter Verwendung von clang 3.9 erstellen:

%Vor%

gcc ruft next() über den PLT auf, clang inline es. Beide suchen immer noch last von der GOT. Für das Kompilieren unter Linux ist es richtig, diese Optimierung zu machen, und gcc fehlt beim einfachen Inlining, oder ist falsch falsch, um diese Optimierung zu machen, oder ist das ein reines QoI-Problem?

    
Barry 30.08.2017, 23:24
quelle

1 Antwort

13

Ich glaube nicht, dass der Standard so sehr ins Detail geht. Es sagt nur, dass wenn das Symbol eine externe Verbindung in verschiedenen Übersetzungseinheiten hat, es dasselbe Symbol ist. Das macht die Version von clang korrekt.

Von da an sind wir nach meinem besten Wissen nicht mehr im Standard. Die Auswahlmöglichkeiten von Compilern unterscheiden sich darin, was sie als nützliche -fPIC -Ausgabe betrachten.

Beachten Sie, dass g++ -c -std=c++11 -O3 -fPIE outputs:

%Vor%

GCC weiß also, wie man das optimiert. Es wählt nur nicht, wenn -fPIC verwendet wird. Aber warum? Ich kann nur eine Erklärung sehen: es ist möglich, das Symbol während der dynamischen Verknüpfung zu überschreiben und die Effekte konsistent zu sehen. Die Technik ist als Symbol interposition bekannt.

Wenn index in einer gemeinsam genutzten Bibliothek next aufruft, da next global sichtbar ist, muss gcc die Möglichkeit in Betracht ziehen, dass next eingefügt werden könnte. Es nutzt also den PLT. Wenn Sie -fPIE verwenden, dürfen Sie jedoch keine Symbole einfügen, daher aktiviert gcc die Optimierung.

Stimmt das falsch? Nein. Aber gcc scheint die Symbolinterposition besser zu unterstützen, was praktisch ist, um den Code zu instrumentieren. Es tut dies auf Kosten von etwas Gemeinkosten, wenn man -fPIC anstelle von -fPIE benutzt, um seine ausführbare Datei zu erstellen.

Zusätzliche Hinweise:

In diesem Blogeintrag von einem der gcc-Entwickler, erwähnt er, gegen Ende der Post:

  

Beim Vergleich einiger Benchmarks mit clang habe ich festgestellt, dass clang die ELF-Interpositionsregeln ignoriert. Während es ein Fehler ist, habe ich beschlossen, -fno-semantic-interposition flag zu GCC hinzuzufügen, um ein ähnliches Verhalten zu erhalten. Wenn Interposition nicht erwünscht ist, ist die offizielle Antwort von ELF, versteckte Sichtbarkeit zu verwenden, und wenn das Symbol exportiert werden soll, definieren Sie einen Alias. Dies ist nicht immer praktisch mit der Hand zu tun.

Nachdem ich diesen Vorsprung erreicht hatte, landete ich auf der x86-64-ABI-Spezifikation . In Abschnitt 3.5.5 schreibt es vor, dass alle Funktionen, die ein global sichtbares Symbol aufrufen, den PLT durchlaufen müssen (bis zur Definition der genauen Befehlsfolge, die je nach Speichermodell zu verwenden ist).

Obwohl es den C ++ - Standard nicht verletzt, scheint das Ignorieren der semantischen Interposition die ABI zu verletzen.

Letztes Wort: Ich wusste nicht, wo ich das hinstellen sollte, aber es könnte Sie interessieren. Ich erspare Ihnen die Dumps, aber meine Tests mit objdump und Compiler-Optionen haben gezeigt, dass:

Auf der gcc-Seite der Dinge:

  • gcc -fPIC : Zugriffe auf last gehen durch GOT, Aufrufe von next() durchläuft PLT.
  • gcc -fPIC -fno-semantic-interposition : last läuft über GOT, next() ist inline.
  • gcc -fPIE : last ist IP-relativ, next() ist inline.
  • -fPIE bedeutet -fno-semantic-interposition

Auf der klirrenden Seite der Dinge:

  • clang -fPIC : last läuft über GOT, next() ist inline.
  • clang -fPIE : last läuft über GOT, next() ist inline.

Und eine modifizierte Version, die kompiliert zu IP-relativ, inline auf beiden Compilern:

%Vor%

Grundsätzlich bedeutet dies ausdrücklich, dass wir, obwohl sie global verfügbar sind, eine versteckte Version dieser Symbole verwenden, die jede Art von Interposition ignorieren. Beide Compiler optimieren dann die Zugriffe vollständig, unabhängig von den übergebenen Optionen.

    
spectras 31.08.2017, 02:26
quelle

Tags und Links