GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Strippen von gemeinsam genutzten Linux-Bibliotheken

Wenn Sie Ihren privaten Teil in einem anonymen Namensraum verpacken, dann weder std::abs noch private_function ist in der Symboltabelle ersichtlich:

namespace{
#include<cmath>
  float private_function(float f)
  {
    return std::abs(f);
  }
}
extern "C" float public_function(float f)
{
        return private_function(f);
}

Kompilieren (g++ 4.3.3):

g++ -shared -o libtest.so test.cpp -s

Inspektion:

# nm -DC libtest.so
         w _Jv_RegisterClasses
0000200c A __bss_start
         w __cxa_finalize
         w __gmon_start__
0000200c A _edata
00002014 A _end
000004a8 T _fini
000002f4 T _init
00000445 T public_function

Nur um anzumerken, dass Ulrich Drepper einen Aufsatz über (alle?) Aspekte des Schreibens gemeinsam genutzter Bibliotheken für Linux/Unix geschrieben hat, der neben vielen anderen Themen die Kontrolle exportierter Symbole behandelt.

Dies war sehr praktisch, um zu verdeutlichen, wie man nur Funktionen auf einer Whitelist aus einer gemeinsam genutzten Bibliothek exportiert.


Ihre Verwendung des Standard-Sichtbarkeitsattributs und -fvisibility=hidden sollte durch -fvisibility-inlines-hidden.

ergänzt werden

Sie sollten auch den Versuch vergessen, stdlib-Exporte zu verstecken, siehe diesen GCC-Fehler für den Grund.

Wenn Sie alle Ihre öffentlichen Symbole in einem bestimmten Header haben, können Sie sie auch in #pragma GCC visibility push(default) einschließen und #pragma GCC visibility pop anstatt Attribute zu verwenden. Wenn Sie jedoch eine plattformübergreifende Bibliothek erstellen, werfen Sie einen Blick auf Steuern exportierter Symbole gemeinsam genutzter Bibliotheken, um eine Technik zum Vereinheitlichen Ihrer Windows-DLL- und Linux-DSO-Exportstrategie zu finden.


Die Lösung, die wir jetzt haben, lautet also wie folgt:

test.cpp

#include <cmath>
#include <vector>
#include <typeinfo>

struct private_struct
{
    float f;
};

float private_function(float f)
{
    return std::abs(f);
}

void other_private_function()
{
    std::vector<private_struct> f(1);
}

extern "C" void __attribute__ ((visibility ("default"))) public_function2()
{
    other_private_function();
}

extern "C" float __attribute__ ((visibility ("default"))) public_function1(float f)
{
    return private_function(f);
}

exports.version

LIBTEST 
{
global:
    public*;
local:
    *;
};

kompiliert mit

g++ -shared test.cpp -o libtest.so -fvisibility=hidden -fvisibility-inlines-hidden -s -Wl,--version-script=exports.version

gibt

00000000 A LIBTEST
         w _Jv_RegisterClasses
         U _Unwind_Resume
         U std::__throw_bad_alloc()
         U operator delete(void*)
         U operator new(unsigned int)
         w __cxa_finalize
         w __gmon_start__
         U __gxx_personality_v0
000005db T public_function1
00000676 T public_function2

Was dem, was wir suchen, ziemlich nahe kommt. Es gibt jedoch ein paar Fallstricke:

  • Wir müssen sicherstellen, dass wir nicht das Präfix "exportiert" (in diesem einfachen Beispiel "öffentlich", aber in unserem Fall offensichtlich etwas nützlicheres) im internen Code verwenden.
  • Viele Symbolnamen landen immer noch in der String-Tabelle, was anscheinend auf RTTI zurückzuführen ist, -fno-rtti lässt sie in meinen einfachen Tests verschwinden, ist aber eine ziemlich nukleare Lösung.

Ich nehme gerne jede bessere Lösung an, die jemand hat!


Linux
  1. „welches“ Äquivalent für gemeinsam genutzte Bibliotheken?

  2. Linux 3D-Grafikbibliotheken?

  3. ipcs-Befehlsbeispiele unter Linux

  4. Wie zeigt man alle gemeinsam genutzten Bibliotheken an, die von ausführbaren Dateien in Linux verwendet werden?

  5. C++ Dynamic Shared Library unter Linux

Ein Leitfaden zum Verständnis von Linux-Softwarebibliotheken in C

Erkennen Sie veraltete gemeinsam genutzte Bibliotheken im Speicher mit UChecker

So listen Sie gemeinsam genutzte Bibliotheken auf, die von ausführbaren Dateien in Linux verwendet werden

Wie wird die Versionierung einer gemeinsam genutzten Bibliothek unter Linux durchgeführt?

So richten Sie googleTest als gemeinsam genutzte Bibliothek unter Linux ein

Warum sind gemeinsam genutzte Bibliotheken unter Linux ausführbar?