2013-10-03 4 views
6

Ho scritto una libreria condivisa con diverse versioni incompatibili. Ho cambiato soname, così vengono chiamati:Rileva due versioni ABI incompatibili della mia libreria condivisa caricate nel programma singolo

  • lib_mylib.so.1.0.0 (vecchia libreria)
  • lib_mylib.so.2.0.0

Ci sono alcune funzioni solo in mylib. so.1, altri sono solo in mylib.so.2 e molte funzioni sono comuni (ma molti hanno cambiato il conteggio degli argomenti)

E temo che sia possibile collegare entrambe le versioni di mylib in una singola applicazione, ad esempio quando l'applicazione stessa è grande e comprende molte librerie. Quando l'applicazione viene ricostruito in parte, non ci può essere tale situazione:

  • Applicazione
  • app_lib1.so (è stato costruito con mylib.so.1 - prima versione del mio lib)
  • app_lib2.so (è stato ricostruito con mylib.so.2 - seconda versione)

Ho già visto l'applicazione con entrambe le versioni caricate in esso (report ldd entrambi).

Quindi, è possibile aggiungere del codice di controllo a mylib.so.2 per rilevare che sono già caricate entrambe le versioni della libreria e che hanno ABI/Interfaccia in conflitto. (Non posso modificare lib_mylib.so.1 di aggiungere qualcosa in esso)

risposta

1

È possibile analizzare /proc/self/maps per ottenere l'elenco degli oggetti attualmente caricati.

+0

Posso solo analizzare '/ proc/self/maps' nel costruttore della mia libreria. Penso che sia possibile, al momento dell'esecuzione del mio costruttore dalla seconda libreria, la prima libreria non sarà ancora caricata in memoria (caso 1: mylib2 è precedente a mylib1 nella lista delle librerie; caso 2: mylib1 sarà caricato usando dlopen a qualche tempo dopo) – osgx

3

È possibile modificare la libreria della versione 2 per risolvere alcuni simboli specifici della versione 1 (dlsym(3)) durante init e crash quando trovati.

Esempio:

extern __attribute__((constructor)) void _version_check2() 
{ 
    if (dlsym(RTLD_DEFAULT, "version_1_function")) 
     abort(); 
} 

Una soluzione più elegante è quello di lasciare la versione 2 della libreria simulare il comportamento della versione 1, ma che introduce il codice legacy.

EDIT

Per essere a prova di futuro, è anche possibile introdurre una variabile versione statica e tutte le chiamate di funzione dovrebbe verificare se corrisponde la corrente. Quindi nelle versioni future hai solo bisogno di cambiare il valore di quella variabile e crash se mismatch.

EDIT 2

È inoltre possibile chiamare questa funzione su ogni funzione versione 2 in modo che prima o poi, quando la versione 1 viene caricato di crash del app.

+0

O forse il 'dlopen 'specifico per linux (RTLD_NOLOAD," lib_mylib.so.1.0.0 ")'. – rodrigo

Problemi correlati