2009-10-19 21 views
26

Almeno su Linux e Solaris, le librerie statiche sono in realtà solo un mucchio di .o compilato in un unico grande file. Quando si compila una libreria statica, in genere il flag -fpic è ommited, quindi il codice generato dipende dalla posizione.Collegamento di una libreria condivisa a una libreria statica: la libreria statica deve essere compilata in modo diverso rispetto a quando un'applicazione lo stava collegando?

Ora dire che la mia libreria statica è B. L'ho creata e ho il file .a risultante che è in realtà solo un glob di tutti i file .o dipendenti dalla posizione. Ora ho una libreria condivisa che vorrei costruire, A, e voglio che leghi staticamente B. Quando costruisco A, naturalmente userò il flag -fpic per rendere indipendente la posizione del codice generato. Ma se collego B, non sto mixando la posizione dipendente e posiziono i file oggetto indipendenti?

Ho un sacco di errori di trasferimento del testo a meno che non specifichi anche -mimpure-text, e penso che questa sia la causa. Sembra che quando compilo una libreria, ho davvero bisogno di compilarlo volte, una versione condivisa, una versione statica e una versione statica-che-può-essere-usata-per-condivisa-libs. Ho ragione? Potrei continuare a usare -mimpure-text ma la pagina man di g ++ dice che se lo fai l'oggetto non finisce per essere condiviso (non è chiaro se sia tutto condiviso o solo le parti collegate staticamente, qualcuno lo sa?) .

+0

La domanda si afferma in modo corretto, si '-fpic' 'omette' nel primo paragrafo, che porta al codice dipendente dalla posizione, poi lo usa nel secondo paragrafo, che porta a codice indipendente dalla posizione. –

risposta

24

Non è necessario utilizzare il codice PIC in oggetti condivisi (come hai scoperto puoi usare l'opzione -mimpure-text per permetterlo).

Detto questo, il codice non PIC in oggetti condivisi è più pesante. Con il codice PIC, le pagine di testo in memoria sono solo mappature di memoria diretta delle pagine di testo su disco. Ciò significa che se più processi stanno utilizzando l'oggetto condiviso, possono condividere la pagina di memoria.

Ma se non si dispone di codice PIC, quando il linker di runtime carica l'oggetto condiviso, dovrà applicare correzioni alle pagine di testo. Ciò significa che ogni processo che utilizza l'oggetto condiviso avrà la sua versione univoca di qualsiasi pagina di testo che ha una correzione su di esso (anche se l'oggetto condiviso è caricato nello stesso indirizzo in cui il copy-on-write nota solo che la pagina era modificato e non che sia stato modificato allo stesso modo).

Per me, la questione importante è se si contemporaneamente avere più processi in esecuzione che ogni carico l'oggetto condiviso. Se lo fai, vale sicuramente la pena assicurarsi che tutto il codice all'interno della SO sia PIC.

Ma se questo non è il caso e solo un singolo processo ha l'oggetto condiviso caricato, non è quasi critico.

+0

In realtà, se sai che solo un processo lo caricherà, non può essere un vantaggio in termini di prestazioni compilare senza un'immagine? A causa del salvataggio di un registro. –

+1

@JosephGarvin PIC utilizza un registro in codice x86 a 32 bit, ma non nel codice a 64 bit. Il set di istruzioni x64 supporta l'indirizzamento relativo del contatore di programma - carica i dati che sono i byte NNNN sfalsati dall'indirizzo di memoria della (istruzione successiva che segue l'istruzione attualmente in esecuzione).Il codice PIC in x64 non richiede il registro del puntatore GOT. – dthorpe

+0

Grazie per l'ottima spiegazione! – rkellerm

1

Come approccio alternativo, spedisci due librerie: quella condivisa e quella statica a cui stai collegando a fianco. Dovrebbero collegarsi correttamente all'eseguibile finale.

3

faccio quanto segue nella fase di collegamento per la versione della libreria di oggetti condivisi di una libreria statica: g ++ -o -shared libshared.so -Wl, - intero archivio -fPIC -lstatic -Wl, - no- intero-archivio. Dal momento che - tutto-archivio collega ogni oggetto in una (lista di) librerie statiche (della forma libstatic.a) credo che prima (lista) con -fPIC sia tutto ciò che l'OP deve fare.

+0

potresti per favore spiegare più chiaramente? – gyro

Problemi correlati