[so] [TechQ] LD_LIBRARY_PATH
Adrian Scoica
adrian.scoica at gmail.com
Fri Apr 15 21:40:38 EEST 2011
>> > Ce rol are LD_LIBRARY_PATH? Cum este folosită și de cine? Se poate
>> > îndeplini și altfel rolul de care este responsabilă variabila?
Atunci cand un ELF foloseste biblioteci partajate, in mometul
executiei este necesara rezolvarea dependintelor pentru simbolurile
externe. Cu alte cuvinte, executabilul vine cu un set de simboluri
nerezolvate despre care se "promite" ca se vor pune in legatura cu cod
real abia in momentul rularii.
Un executabil se asteapta sa gaseasca simbolurile sale nerezolvate in
biblioteci partajate (care au un anumit nume). Aceste dependinte se
pot vedea folosind "ldd". De exemplu, asa:
marcvs at kriegspire:~/tools/eclipse$ ldd eclipse
linux-gate.so.1 => (0x0072b000)
libpthread.so.0 => /lib/libpthread.so.0 (0x00179000)
libdl.so.2 => /lib/libdl.so.2 (0x00133000)
libc.so.6 => /lib/libc.so.6 (0x003e7000)
/lib/ld-linux.so.2 (0x005a9000)
Dupa cum se vede, executabilul are niste asteptari despre respectivele
biblioteci, pe langa nume, el se asteapta sa le gaseasca intr-un loc
"conventional" pe sistemul gazda (mai ales directorul /lib pe Linux).
Asta poate fi si bine si rau...
Bine pentru ca:
* exista o conventie astfel incat lumea sa stie unde sa instaleze un
*.so ca sa il gaseasca aplicatiile care au nevoie de el
* sunt grupate, in directoare cu privilegiile corect setate, departe
de riscul de a fi sterge/suprascrise accidental
Rau pentru ca:
* s-ar putea sa fie situatii in care biblioteca partajata nu este
instalata efectiv in acel director, sau chiar daca este instalata in
/lib, am dori sa folosim o alta varianta (de exemplu, una la care
lucram si pe care tocmai am compilat-o).
In aceste conditii, am vrea sa specificam sa caute fisierele partajate
in alte locatii. Putem instrui loaderul cu privire la locatia unde sa
caute preferential folosidn variabila de mediu LD_LIBRARY_PATH. Cel
mai simplu se vede daca folosesc un exemplu concret:
== inainte (LD_LIBRARY_PATH nesetata)
marcvs at kriegspire:~/Desktop/working/SO/tema2/linux$ ldd client
linux-gate.so.1 => (0x00166000)
libcrypto.so => /usr/lib/libcrypto.so (0x00a79000)
librt.so.1 => /lib/librt.so.1 (0x006dc000)
== dupa (LD_LIBRARY_PATH setata la ".")
marcvs at kriegspire:~/Desktop/working/SO/tema2/linux$ export LD_LIBRARY_PATH=.
marcvs at kriegspire:~/Desktop/working/SO/tema2/linux$ ldd client
linux-gate.so.1 => (0x00986000)
libcrypto.so => ./libcrypto.so (0x002ec000)
librt.so.1 => /lib/librt.so.1 (0x006dc000)
Devine evident ca loaderul stie acum sa caute in alta parte respectiva
biblioteca. In cazul in care ea nu ar fi gasita, se face fallback pe
locatia standard (cum se vede cu librt.so.1, care nu exista in . asa
ca tot cea din /lib e folosita)
Mai mult, se poate face urmatorul experiment :D
marcvs at kriegspire:~/Desktop/working/SO/tema2/linux$ touch librt.so.1
marcvs at kriegspire:~/Desktop/working/SO/tema2/linux$ ls -l
ls: error while loading shared libraries: ./librt.so.1: file too short
LD_LIBRARY_PATH era directorul curent. Ceea ce am facut eu a fost sa
creez un fisier care, dupa nume, "pare" a fi o biblioteca partajata
(librt). Imediat dupa asta, cand am incercat sa apelez "ls", s-a
intamplat ceva interesant, pentru ca "ls" foloseste la randul sau
librt, si a incercat sa foloseasca fisierul librt.so.1 din directorul
curent, care evident ca nu este o biblioteca corecta, asa ca mi-a
crapat inclusiv "ls"-ul :-"...
And here is the actual proof:
marcvs at kriegspire:~/Desktop/working/SO/tema2/linux$ ldd /bin/ls
linux-gate.so.1 => (0x00fc8000)
libselinux.so.1 => /lib/libselinux.so.1 (0x00d21000)
librt.so.1 => /lib/librt.so.1 (0x00bae000)
Din aceste motive, n-ar trebui sa se abuzeze de aceasta variabila de
mediu, si este chiar contraindicat sa scrii executabile care folosesc
biblioteci partajate si au pretentia ca acele biblioteci sa fie in
alte locatii non-standard, pentru ca nu ar trebui sa pretinzi de la
saracul user sa "dea la fire" pana ii pleaca aplicatia din loc.
More information about the so
mailing list