GNU/Linux >> Linux Esercitazione >  >> Linux

Rimozione delle librerie condivise di Linux

Se avvolgi la tua parte privata in uno spazio dei nomi anonimo, allora nemmeno std::absprivate_function può essere visto nella tabella dei simboli:

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

compilazione (g++ 4.3.3):

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

ispezionando:

# 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

Solo per notare che Ulrich Drepper ha scritto un saggio riguardante (tutti?) gli aspetti della scrittura di librerie condivise per Linux/Unix, che copre il controllo dei simboli esportati tra molti altri argomenti.

Questo è stato molto utile per chiarire come esportare solo le funzioni su una whitelist da una libreria condivisa.


Il tuo utilizzo dell'attributo di visibilità predefinito e -fvisibility=hidden dovrebbe essere potenziato con -fvisibility-inlines-hidden.

Dovresti anche dimenticare di provare a nascondere le esportazioni stdlib, vedi questo bug GCC per il motivo.

Inoltre, se hai tutti i tuoi simboli pubblici in intestazioni specifiche, puoi racchiuderli in #pragma GCC visibility push(default) e #pragma GCC visibility pop invece di utilizzare gli attributi. Tuttavia, se stai creando una libreria multipiattaforma, dai un'occhiata a Controllo dei simboli esportati delle librerie condivise per una tecnica per unificare la tua DLL di Windows e la strategia di esportazione DSO di Linux.


Quindi la soluzione che abbiamo per ora è la seguente:

prova.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:
    *;
};

compilato con

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

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

Che è abbastanza vicino a quello che stiamo cercando. Ci sono alcuni trucchi però:

  • Dobbiamo assicurarci di non utilizzare il prefisso "esportato" (in questo semplice esempio "pubblico", ma ovviamente qualcosa di più utile nel nostro caso) nel codice interno.
  • Molti nomi di simboli finiscono ancora nella tabella delle stringhe, che sembra dipendere da RTTI, -fno-rtti li fa sparire nei miei semplici test, ma è una soluzione piuttosto nucleare.

Sono felice di accettare qualsiasi soluzione migliore che qualcuno propone!


Linux
  1. Una guida per comprendere le librerie software Linux in C

  2. Come gestire le librerie dinamiche e statiche in Linux

  3. "quale" equivalente per le biblioteche condivise?

  4. Esempi di comandi ipcs in Linux

  5. Come mostrare tutte le librerie condivise utilizzate dagli eseguibili in Linux?

Rileva librerie condivise obsolete in memoria con UChecker

Come elencare le librerie condivise utilizzate dagli eseguibili in Linux

Introduzione alle librerie condivise Linux (come creare librerie condivise)

Errore Linux durante il caricamento delle librerie condivise:impossibile aprire il file oggetto condiviso:file o directory non presenti

Come inizializzare una libreria condivisa su Linux

Come configurare googleTest come libreria condivisa su Linux