C언어

error while loading shared libraries

고요한하늘... 2013. 4. 21. 21:14

C로 프로그램을 하다 보면 정적 라이브러리 외에 동적 라이브러리를 사용해야 하는 경우가 있다.

보통의 경우 /etc/ld.so.conf에 경로를 저장해 놓거나

LD_LIBRARY에 경로를 설정해 놓는다.


이 방법의 단점은 사용자가 동적 라이브러리 경로를 직접 설정해줘야하는 것이다.

이런 번거로움을 손쉽게 해결하는 방법으로  rpath를 이용할수 있다.


rpath를 설정하기 전에 간단히 사전 지식을 설명하면


동적 라이브러리에 어떤 정보로 빌드가 되었는지 확인할때 쓰는 명령어가 있다.

ELF 파일을 읽는 방법인데

readelf -d so파일명 


정상적으로 빌드가 되었으면 아래와 같이 보일 것이다.( 아래 so 파일은 autotools로 빌드하였다. )


 

Dynamic section at offset 0x2420 contains 21 entries:

  Tag        Type                         Name/Value

 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

 0x000000000000000e (SONAME)             Library soname: [libtest.so]

 0x000000000000000c (INIT)               0xbe0

 0x000000000000000d (FINI)               0x1ea8

 0x000000006ffffef5 (GNU_HASH)           0x158

 0x0000000000000005 (STRTAB)             0x668

 0x0000000000000006 (SYMTAB)             0x230

 0x000000000000000a (STRSZ)              578 (bytes)

 0x000000000000000b (SYMENT)             24 (bytes)

 0x0000000000000003 (PLTGOT)             0x2025e0

 0x0000000000000002 (PLTRELSZ)           528 (bytes)

 0x0000000000000014 (PLTREL)             RELA

 0x0000000000000017 (JMPREL)             0x9d0

 0x0000000000000007 (RELA)               0x928

 0x0000000000000008 (RELASZ)             168 (bytes)

 0x0000000000000009 (RELAENT)            24 (bytes)

 0x000000006ffffffe (VERNEED)            0x908

 0x000000006fffffff (VERNEEDNUM)         1

 0x000000006ffffff0 (VERSYM)             0x8aa

 0x000000006ffffff9 (RELACOUNT)          1

 0x0000000000000000 (NULL)               0x0


반면에 수작업으로

 

gcc -Wall  -g -shared -Wl,-soname, libtest.so -o libtest.so file1.o file2.o


처럼 빌드하면

 

Dynamic section at offset 0x2e20 contains 21 entries:

  Tag        Type                         Name/Value

 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

 0x000000000000000e (SONAME)             Library soname: []

 0x000000000000000c (INIT)               0xa28

 0x000000000000000d (FINI)               0x2758

 0x000000006ffffef5 (GNU_HASH)           0x158

 0x0000000000000005 (STRTAB)             0x5a0

 0x0000000000000006 (SYMTAB)             0x240

 0x000000000000000a (STRSZ)              533 (bytes)

 0x000000000000000b (SYMENT)             24 (bytes)

 0x0000000000000003 (PLTGOT)             0x202ff0

 0x0000000000000002 (PLTRELSZ)           288 (bytes)

 0x0000000000000014 (PLTREL)             RELA

 0x0000000000000017 (JMPREL)             0x908

 0x0000000000000007 (RELA)               0x830

 0x0000000000000008 (RELASZ)             216 (bytes)

 0x0000000000000009 (RELAENT)            24 (bytes)

 0x000000006ffffffe (VERNEED)            0x800

 0x000000006fffffff (VERNEEDNUM)         1

 0x000000006ffffff0 (VERSYM)             0x7b6

 0x000000006ffffff9 (RELACOUNT)          1

 0x0000000000000000 (NULL)               0x0


 


 

정상적인것과의 차이를 살펴보면 다음과 같다.

Library soname: 이 존재하지 않는다.

-Wl,-soname -Wl,libtest.so
-Wl : 링커에게 전달하는 옵션( 링커에게 Lbrary soname을 알려준다 )


gcc -shared file1.o file2.o  \
                -o libtest.so  \
                -Wl,-soname libtest.so -o libtest.so  \       <- soname 설정
                -Wl,-rpath /data2/lib                                 <- rpath 설정

soname과 rpath를 linker에 넘겨줄때 위와 같이 설정한다.
0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
0x000000000000000e (SONAME)             Library soname: [libtest.so]
0x000000000000000f (RPATH)              Library rpath: [/data2/lib]


이용시에도
-Wl,-rpath=/data2/lib/
처럼 rpath를 설정하면
[jchern@search-nlp-anal1 src]$ ldd test
        libtest.so => /data2/lib/libtest.so (0x00002b4b7bd60000)
        libc.so.6 => /lib64/libc.so.6 (0x0000003f41a00000)
        /lib64/ld-linux-x86-64.so.2 (0x0000003f41600000)
위처럼 linking 되는것을 알수 있다.

해당 라이브러리에 rpath 옵션으로 해당 동적 라이브러리의 경로를 기록해 놓고
사용시에도 rpath를 동일하게 사용해서 linking해서 사용하면 된다.


gcc -shared file0.o file1.o                   \
                -Wl,-soname,libtest.so -o libtest.so  \
                -Wl,-rpath,/data2/lib

-------------------------------------------------------------------------------

본인은 정확히 작성을 했는데
해당 프로그램에서 라이브러리를 못찾고 "error while loading shared libraries"를 뿌려주는 경우
objdump -x 실행파일명
으로 rpath가 어디로 설정돼 있는지 확인할수 있다.
여기에 설정된 경로와 so에 기록된 rpath가 같으면 문제 없이 동작할 것이다.



한줄요약 : 프로그램을 실행할때 "error while loading shared libraries" 이런 에러메세지가 나타나면 해당 프로그램 컴파일시에 -Wl,-rpath,"라이브러리경로" 를 넣어주면 된다.