PDA

View Full Version : Dubbio su librerie dinamiche


Sabonis
20-03-2008, 11:31
Se eseguo il comando ldd nano ottengo la lista delle librerie utilizzate dal programma nano.
linux-gate.so.1 => (0xffffe000)
libncursesw.so.5 => /lib/libncursesw.so.5 (0xb7e9d000)
libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb7d53000)
libdl.so.2 => /lib/tls/i686/cmov/libdl.so.2 (0xb7d4e000)

Se nel sistema è presente libncursesw.so.6 anzichè libncursesw.so.5 nano funziona lo stesso? E' possibile creare un pacchetto contenente tutte le librerie richieste da un programma nella versione esatta richiesta e installare il tutto in una cartella senza casini? Volevo provare qualcosa del genere per un programmino realizzato da me.

ilsensine
20-03-2008, 11:40
Se nel sistema è presente libncursesw.so.6 anzichè libncursesw.so.5 nano funziona lo stesso?
Dipende, molte librerie sono retrocompatibili. Mi sembra che con le ncurses non ci siano problemi. Probabilmente però devi creare il symlink libncursesw.so.5 manualmente.

E' possibile creare un pacchetto contenente tutte le librerie richieste da un programma nella versione esatta richiesta e installare il tutto in una cartella senza casini?
Sì ci sono tecniche per forzare il programma a usare quelle specifiche librerie.
Oppure, puoi compilare il programma con le librerie statiche.

Sabonis
20-03-2008, 11:53
Grazie della disponibilità! Io pensavo di creare una cartella con tutte le librerie richieste dal programma e l'esegubile e poi modificare LD_LIBRARY_PATH per fare in modo che vada a cercare le librerie anche in quella cartella.
Supponi che io tenga solo l'esegubile nella cartella, lo lancio e lamenta la mancanza di varie librerie, se aggiungo una a una le librerie che non trova riesco a far funzionare il tutto senza problemi ma se invece copio tutte le librerie che servono (comprese quelle che esistono anche in /usr/lib o in altre cartelle di sistema) allora il programma va in segmentation fault e vanno in segmentation fault anche ls e altri comandi se li eseguo.
Nota che il programma è stato originariamente compilato in un'altra macchina e tutte queste librerie di cui ti parlo le ho prese una a una controllando l'output di ld.

ilsensine
20-03-2008, 12:02
No non sovrascrivere librerie di una versione differente nelle directory di sistema. Usa LD_LIBRARY_PATH, LD_PRELOAD, "-Wl,--rpath", -static...le soluzioni non mancano di certo.

ilsensine
20-03-2008, 12:04
e inoltre hai fatto un altro errore grave...non bisogna MAI sovrascrivere le librerie in uso! Devi cancellare la vecchia libreria (è ammesso anche se è in uso, l'inode non viene distrutto), e creare la libreria nuova.

gurutech
20-03-2008, 12:18
Grazie della disponibilità! Io pensavo di creare una cartella con tutte le librerie richieste dal programma e l'esegubile e poi modificare LD_LIBRARY_PATH per fare in modo che vada a cercare le librerie anche in quella cartella.
Supponi che io tenga solo l'esegubile nella cartella, lo lancio e lamenta la mancanza di varie librerie, se aggiungo una a una le librerie che non trova riesco a far funzionare il tutto senza problemi ma se invece copio tutte le librerie che servono (comprese quelle che esistono anche in /usr/lib o in altre cartelle di sistema) allora il programma va in segmentation fault e vanno in segmentation fault anche ls e altri comandi se li eseguo.
Nota che il programma è stato originariamente compilato in un'altra macchina e tutte queste librerie di cui ti parlo le ho prese una a una controllando l'output di ld.

ciao,
la tecnica che dici funziona quasi sempre, io l'ho usata diverse volte. Stai solo attento a non sovrascrivere pezzi di sistema. In genere non e' una buona idea ricopiare pezzi di libc da altre parti, cerca di capire l'insieme minimo di librerie senza le quali non parte. mklibs http://packages.debian.org/unstable/devel/mklibs puo' aiutarti in questo.


Esempio: gnudoku per Debian Sarge
http://icculus.org/~jcspray/GNUDoku/

Sabonis
20-03-2008, 12:20
Come temevo non sono riuscito a spiegarmi bene.
Allora ho una macchina A in cui compilo un programma che dipende da N librerie.

Ora voglio che il programma giri sulla macchina B. Nella macchina B creo una cartella PROVA con l'esegubile preso dalla macchina A. Se lo lancio naturalmente non funziona perchè non trova le librerie.
Provo ad aggiungere la cartella PROVA a LD_LIBRARY_PATH e aggiungo nella cartella PROVA una a una tutte le librerie che il programma non trova (librerie prese dalla macchina A), allora il programma funziona.

Il programma non funziona se invece nella cartella PROVA aggiungo tutte le librerie segnalate da ldd. In questo caso il programma va in segmentation fault così come tutti i comandi della shell.

In pratica se nella cartella PROVA copio solo le librerie che mancano nella macchina A il programma funziona, se invece ci metto tutte le librerie che segnala ldd (e quindi qualcuna magari è contemporaneamente presente in /usr/lib e in PROVA), in questo caso ho i segmentation fault.

ilsensine
20-03-2008, 12:26
Il programma non funziona se invece nella cartella PROVA aggiungo tutte le librerie segnalate da ldd. In questo caso il programma va in segmentation fault così come tutti i comandi della shell.
Comprese le librerie di sistema come le libc? Sì può capitare.
Se vuoi portarti dietro anche le libc serve un'altra variabile di ambiente, per specificare l'interpreter ld-linux.so corretto. Altrimenti di default viene usato quello in /lib, indipendentemente da LD_LIBRARY_PATH.

Sabonis
20-03-2008, 14:15
Avevo copiato tutte le librerie ad eccezione di linux-gate.so.1 (che non esiste realmente come file o sbaglio?) e ld-linux.so.2....
Copio nella cartella PROVA anche ld-linux.so.2 e cambio la variabile d'ambiente che mi hai detto affinchè usi il file ld-linux.so fornito da me?
Come si chiama questa variabile d'ambiente?

ilsensine
20-03-2008, 14:35
Non mi ricordo...

Puoi comunque invocare l'interpreter direttamente (non è una libreria qualsiasi!).

/path/di/ld-linux.so.2 --library-path <path librerie> <path eseguibile> <parametri eseguibile>


Ad es:
./ld-linux.so.2 --library-path ./ ./myprog [args...]

Però scusa se mi ripeto -- se senti la necessità di portarti dietro tutte le librerie, perché non compili semplicemente staticamente?

Sabonis
20-03-2008, 14:58
Penso che proverò a compilare staticamente ma dimmi non è sconveniente?
Non dico per la dimensione del pacchetto perchè tanto le librerie me le devo portare dietro comunque o come .so o compilate staticamente, ma per l'occupazione di memoria non è un problema? Insomma col metodo a cui stavo pensando se per caso è presente la versione esatta già in memoria non dovrebbe caricarla due volte, mentre invece se compilo staticamente si o sbaglio?

ilsensine
20-03-2008, 15:54
Penso che proverò a compilare staticamente ma dimmi non è sconveniente?
Non dico per la dimensione del pacchetto perchè tanto le librerie me le devo portare dietro comunque o come .so o compilate staticamente, ma per l'occupazione di memoria non è un problema? Insomma col metodo a cui stavo pensando se per caso è presente la versione esatta già in memoria non dovrebbe caricarla due volte, mentre invece se compilo staticamente si o sbaglio?
Ne avessi azzeccata una :D
L'_unico_ caso in cui il footprint può essere (globalmente) minore è se la libreria è condivisa con altri programmi diversi dal tuo. In soldoni, se stai usando le librerie native del s/o. E non perché il tuo programma occupa meno memoria, ma perché condivide del codice con altri programmi. Se ti porti dietro le tue librerie e le usi, non c'è differenza con una compilazione statica.

Se compili un eseguibile statico e lo strippi, vedrai che la sua dimensione è minore (a volte di molto!) dell'eseguibile dinamico + librerie.
L'occupazione di memoria non cambia: vanno in memoria solo le pagine necessarie all'esecuzione, indipendentemente se stanno nell'eseguibile o in qualche libreria.

Sabonis
20-03-2008, 16:19
Ne avessi azzeccata una :D
L'_unico_ caso in cui il footprint può essere (globalmente) minore è se la libreria è condivisa con altri programmi diversi dal tuo. In soldoni, se stai usando le librerie native del s/o. E non perché il tuo programma occupa meno memoria, ma perché condivide del codice con altri programmi.
Se ti porti dietro le tue librerie e le usi, non c'è differenza con una compilazione statica.

Ma non è quello che ho detto???!!

Se compili un eseguibile statico e lo strippi, vedrai che la sua dimensione è minore (a volte di molto!) dell'eseguibile dinamico + librerie.
Non ne avevo idea!

ilsensine
20-03-2008, 20:46
Non ne avevo idea!
Un archivio statico .a (quello che viene linkato quando indichi -static) non è altro che un insieme di file, generalmente file oggetto .o (prova ad aprirne uno con ark!)
Una libreria .so ovviamente contiene tutti gli oggetti, mentre quando fai il link statico vengono inclusi nell'eseguibile solo i .o necessari a risolvere i simboli richiesti; gli altri .o vengono scartati.

Sabonis
21-03-2008, 14:26
Ho notato che su due distro diverse l'output di ldd cambia..da cosa può dipendere?

ilsensine
21-03-2008, 20:09
ldd mostra anche le dipendenze delle librerie usate dal programma.