Domanda

Voglio creare una libreria condivisa che utilizza le funzioni da una libreria statica 3rd-party. Ad esempio, foo e bar da libfoobar.a. So che la mia domanda principale è anche utilizzando foo e verrà esportando quel simbolo. Così Voglio semplicemente collegare in bar per salvare le dimensioni del codice e lasciare 'foo' irrisolto (come sarà fornita dal ricorso principale). Se includo libfoobar.a, il linker ld includerà entrambe le funzioni nella mia libreria condivisa. Se non includo libfoobar.a, mia biblioteca non avrà accesso alla funzione bar perché l'applicazione in sé non è il collegamento in bar. Domande:

  • C'è un modo per dire ld per risolvere solo alcuni simboli quando si costruisce la libreria condivisa?
  • Accendere libfoobar.a in una libreria condivisa?
  • Estrai file contenente la funzione bar da libfoobar.a e specificare che sulla linea linker?
  • Non ti preoccupare, il caricatore runtime utilizzerà bar dalla propria applicazione in modo che la copia della bar nella libreria condivisa non verrà caricata?
È stato utile?

Soluzione

Il seguenti punti tentativo di rispondere alle domande che avevo poste:

  • ld non sembra consentire di omettere il collegamento in certi simboli da una libreria statica. L'utilizzo di --just-symbols o --undefined (o il comando EXTERN script del linker) non impedirà ld dalla collega i simboli.
  • Per convertire una libreria statica, libfoobar.a , in un condiviso uno, libfoobar.so.1.0 , e l'esportazione di tutti i simboli visibili. È inoltre possibile utilizzare --version-script e altri metodi per esportare solo un sottoinsieme di simboli.

    ld -shared -soname libfoobar.so.1 -o libfoobar.so.1.0 --whole-archive libfoobar.a --no-whole-archive

  • E 'meglio per Elimina membri dell'archivio da un copia della tua libreria statica che è di estrarli perché ci potrebbero essere delle dipendenze interne si deve gestire . Per esempio, supponendo che si sta esportando tutti i simboli, è possibile generare un file di mappa dal tuo eseguibile principale. È quindi possibile grep per tutti i membri dell'archivio che l'eseguibile tirato dalla copia della libreria statica ed eliminarli dalla copia. Così, quando il vostro DSO è il collegamento nella libreria statica, lascerà gli stessi simboli irrisolto.

  • E 'possibile specificare il principale eseguibile come libreria condivisa per il vostro DSO se si compila il file eseguibile con l'opzione --pie. Il tuo DSO collegherà primo a vostro eseguibile se preceduto la libreria statica nel comando di collegamento. L'avvertenza è che l'eseguibile principale deve essere disponibile tramite LD_LIBRARY_PATH o -rpath. Inoltre, utilizzando strace rivela che, dal momento che l'eseguibile è una dipendenza della vostra libreria, viene caricato di nuovo quando i carichi DSO.

    ld -shared -rpath '$ORIGIN' -L. -lc -ldl -o DSO.so DSO.o app libfoobar.a

  • Il linker dinamico utilizzerà la versione del file eseguibile di pippo prima a meno che non si chiama dlopen () con la bandiera RTLD_DEEPBIND. Usando strace rivela che l'intero DSO è file mappato mmap2 () in memoria. Tuttavia, Wikipedia afferma che per mmap "L'attuale legge dal disco vengono eseguite in 'pigro' maniera, dopo una posizione specifica si accede." Se questo è vero, allora il duplicato pippo non verrà caricato. Si noti che l'override avviene solo se il vostro DSO ha esportato la funzione pippo . In caso contrario, la funzione di pippo che è stato staticamente legata nel vostro DSO sarà utilizzato ogni volta che le chiamate DSO foo .

In conclusione, se mmap () utilizza una lettura pigra, allora la soluzione migliore è quella di collegare il vostro DSO in modo normale e lasciare che il linker dinamico e Linux si prendono cura di tutto il resto.

Altri suggerimenti

Io non sono il più grande esperto di librerie condivise, così che io possa essere sbagliato qui!

Se sto cercando di indovinare ragione su quello che si sta cercando di fare, basta collegare il tuo lib condivisa contro libc.so. Se non si desidera una copia extra del sscanf incorporato nella vostra libreria.

ho risposto alle vostre domande prima avevo ancora capito che cosa stavate arrivare, nel caso in cui siete interessati alle risposte.

  

C'è un modo per dire ld a risolvere solo alcuni simboli quando si costruisce la libreria condivisa?

solo esterno, non statici, le funzioni e le variabili vanno nella tabella dei simboli della libreria condivisa.

Quando si genera il libreria condivisa, i simboli non si trovano in oggetti sulla riga di comando di linker rimarranno irrisolti. Se il linker si lamenta che, probabilmente avete bisogno di collegare il tuo lib condivisa contro condiviso libc. Si può avere librerie condivise che dipendono da altre librerie condivise, e ld.so può trattare con le catene di dipendenza.

Se avessi più rep, mi piacerebbe chiedere questo come un commento:  Avete una versione personalizzata di sprintf / sscanf, o sarebbe ok per il vostro lib condivisa per utilizzare l'implementazione in -lc? Se -lc va bene, allora la mia risposta probabilmente risolve il problema. Se no, allora avete bisogno di costruire la vostra lib condivisa dagli oggetti che hanno solo le funzioni necessarie. vale a dire non collegare contro /usr/lib/libc.a.

Forse mi sto confuso dal

  

libc.a (in realtà non la libc "reale")    linea. /usr/lib/libc.a è davvero glibc (su linux). Si tratta di una copia collegata in modo statico dello stesso codice in libc.so. A meno che non si sta parlando proprio libc.a (che è quello che pensavo in un primo momento) ...

     

Trasforma libc.a in una libreria condivisa?    Probabilmente si può, ma non lo fanno, perché è probabilmente non compilato come codice indipendente dalla posizione, quindi sarebbe richiede un sacco di delocalizzazioni da ld.so in fase di esecuzione.

     

Estratto sscanf da libc.a e specificare che sulla linea linker?

Può essere possibile. ar t /usr/lib/libc.a alla lista contenuti. (Args di AR sono simili a catrame. Tar è stato ar per i nastri .... Vecchia scuola Unix qui.) Probabilmente non è così facile, perché probabilmente sscanf dipende da simboli in altri file .o nel .a.

rispondere alla tua domanda più rivisto-chiaro.

Tieni presente che normalmente il punto di un lib condivisa è che più programmi possono collegare contro di essa. Quindi, l'ottimizzazione di utilizzare il simbolo del programma principale per una funzione è necessario funzionerà solo se il programma principale prevede sempre quel simbolo (tramite un lib statica o in altro modo). Questo non è di solito quello che la gente vuole fare.

Se è solo un paio di piccole funzioni, probabilmente si dovrebbe lasciare che sia. Probabilmente finisce con due copie del codice per le funzioni, uno nella vostra shlib, e uno nel programma principale. Se sono piccole (o almeno non enorme), o no chiamato spesso e non le prestazioni critiche, allora il codice-size / I-cache colpito da avere due copie non è qualcosa di cui preoccuparsi. (Traduzione:. Non so come evitarlo è fuori dalla parte superiore della mia testa, quindi potrei non prendere il tempo di guardare in su e fare un Makefile più complesso per evitarlo)

Vedi la mia altra risposta per alcuni commenti su guai con ar per estrarre roba da una libreria statica. sintesi:. Probabilmente non banale, dal momento che non si conoscono le dipendenze tra i vari file .o nel .a

E 'possibile fare quello che stai sperando di avere la libreria condivisa esportare i simboli che tira dentro dalla libreria statica. Poi, quando si collega l'applicazione principale, mettere la vostra libreria condivisa prima della lib statica sulla riga di comando del linker. ld troverà "pippo" nel vostro shlib, e l'uso che la copia (se questo trucco ri-esportazione è possibile), ma per "bar" che dovrà includere una copia dal lib statica.

ld --export-dinamica può essere ciò che è necessario esportare tutti i simboli nella tabella dei simboli dinamica. Prova questo. E la ricerca di "esportazione" nella pagina docs / man. "Esportazione" è il gergo per fare un simbolo visibile in una libreria. --export-tutti-i simboli è nel i386 PE (DLL di Windows) sezione, altrimenti probabilmente sarebbe fare il trucco.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top