서로 다른 위치에 있는 동일한 실행 파일이 서로 다른 libc.so를 로드하는 이유는 무엇입니까?

서로 다른 위치에 있는 동일한 실행 파일이 서로 다른 libc.so를 로드하는 이유는 무엇입니까?

간단한 C(빈 기본 함수만 포함) 파일을 a.out으로 컴파일하고 다른 위치에서 실행했습니다.

user@host:~$ md5sum /home/work/a.out /tmp/a.out
dcbdb836569b99a7dc83366ba9bb3588  /home/work/a.out
dcbdb836569b99a7dc83366ba9bb3588  /tmp/a.out
user@host:~$
user@host:~$
user@host:~$ ldd /home/work/a.out
    linux-vdso.so.1 (0x00007fffe11fa000)
    libc.so.6 => /opt/compiler/gcc-4.8.2/lib/libc.so.6 (0x00007f42b8bca000)    <--
    /opt/compiler/gcc-4.8.2/lib64/ld-linux-x86-64.so.2 (0x00007f42b8f77000)
user@host:~$
user@host:~$ ldd /tmp/a.out
    linux-vdso.so.1 (0x00007fff6ba41000)
    libc.so.6 => /tmp/../lib64/tls/libc.so.6 (0x0000003f0b000000)    <--
    /opt/compiler/gcc-4.8.2/lib64/ld-linux-x86-64.so.2 (0x00007f12f537a000)

왜 다른 libc.so를 로드합니까?


@qubert 덕분에 더 많은 정보를 얻을 수 있습니다.

$ readelf -a ./a.out | fgrep ORIGIN
0x000000000000000f (RPATH)              Library rpath: [$ORIGIN:$ORIGIN/lib:$ORIGIN/lib64:$ORIGIN/../lib:$ORIGIN/../lib64:/opt/compiler/gcc-4.8.2/lib:/opt/compiler/gcc-4.8.2/lib64]

$ gcc -v -g 1.c 2>&1 | fgrep collect
/home/opt/gcc-4.8.2.xxx-r4/gcc-4.8.2.xxx-r4/sbin/../libexec/gcc/x86_64-xxx-linux-gnu/4.8.2/collect2 -rpath $ORIGIN:$ORIGIN/lib:$ORIGIN/lib64:$ORIGIN/../lib:$ORIGIN/../lib64:/opt/compiler/gcc-4.8.2/lib:/opt/compiler/gcc-4.8.2/lib64 --sysroot=/home/opt/gcc-4.8.2.xxx-r4/gcc-4.8.2.xxx-r4/sbin/../x86_64-xxx-linux-gnu/sys-root --eh-frame-hdr -m elf_x86_64 -dynamic-linker /opt/compiler/gcc-4.8.2/lib64/ld-linux-x86-64.so.2 /home/opt/gcc-4.8.2.xxx-r4/gcc-4.8.2.xxx-r4/sbin/../lib/gcc/x86_64-xxx-linux-gnu/4.8.2/../../../../lib64/crt1.o /home/opt/gcc-4.8.2.xxx-r4/gcc-4.8.2.xxx-r4/sbin/../lib/gcc/x86_64-xxx-linux-gnu/4.8.2/../../../../lib64/crti.o /home/opt/gcc-4.8.2.xxx-r4/gcc-4.8.2.xxx-r4/sbin/../lib/gcc/x86_64-xxx-linux-gnu/4.8.2/crtbegin.o -L/home/opt/gcc-4.8.2.xxx-r4/gcc-4.8.2.xxx-r4/sbin/../lib/gcc/x86_64-xxx-linux-gnu/4.8.2 -L/home/opt/gcc-4.8.2.xxx-r4/gcc-4.8.2.xxx-r4/sbin/../lib/gcc -L/home/opt/gcc-4.8.2.xxx-r4/gcc-4.8.2.xxx-r4/sbin/../lib/gcc/x86_64-xxx-linux-gnu/4.8.2/../../../../lib64 -L/home/opt/gcc-4.8.2.xxx-r4/gcc-4.8.2.xxx-r4/sbin/../x86_64-xxx-linux-gnu/sys-root/lib/../lib64 -L/home/opt/gcc-4.8.2.xxx-r4/gcc-4.8.2.xxx-r4/sbin/../x86_64-xxx-linux-gnu/sys-root/usr/lib/../lib64 -L/home/opt/gcc-4.8.2.xxx-r4/gcc-4.8.2.xxx-r4/sbin/../lib/gcc/x86_64-xxx-linux-gnu/4.8.2/../../../../x86_64-xxx-linux-gnu/lib -L/home/opt/gcc-4.8.2.xxx-r4/gcc-4.8.2.xxx-r4/sbin/../lib/gcc/x86_64-xxx-linux-gnu/4.8.2/../../.. -L/home/opt/gcc-4.8.2.xxx-r4/gcc-4.8.2.xxx-r4/sbin/../x86_64-xxx-linux-gnu/sys-root/lib -L/home/opt/gcc-4.8.2.xxx-r4/gcc-4.8.2.xxx-r4/sbin/../x86_64-xxx-linux-gnu/sys-root/usr/lib /tmp/ccbKeW7k.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /home/opt/gcc-4.8.2.xxx-r4/gcc-4.8.2.xxx-r4/sbin/../lib/gcc/x86_64-xxx-linux-gnu/4.8.2/crtend.o /home/opt/gcc-4.8.2.xxx-r4/gcc-4.8.2.xxx-r4/sbin/../lib/gcc/x86_64-xxx-linux-gnu/4.8.2/../../../../lib64/crtn.o

답변1

DT_RPATH귀하의 컴파일러는 기본적 으로 내장된 사양 설정을 사용하도록 구성되어 있습니다 $ORIGIN.

목적 $ORIGIN은 의존하는 공유 라이브러리와 함께 다른 곳으로 이동할 수 있는 실행 파일을 만드는 것입니다. 바이너리가 이동되어 실행 경로에 /alt/opt/bin있으면 $ORIGIN/../lib동적 링커가 먼저 ./alt/opt/libld.so(8)

컴파일러의 문제는 항상 먼저 검색하고 재정의를 전달하지 못하는 더 이상 사용되지 않는 컴파일러 DT_RPATH(대신 )를 사용한다는 것입니다 . 이를 방지하려면 다음을 사용해 보세요 .DT_RUNPATHLD_LIBRARY_PATH-Wl,--enable-new-dtagsgcc

gcc -Wl,--enable-new-dtags file.c

이는 명령줄에서 설정하든 사양을 통해 설정하든 상관없이 링커에게 options DT_RUNPATH대신 사용하도록 지시합니다. 이전 시스템은 이것을 지원해서는 안 되지만, 제가 기억하는 한 그것은 오래 전 일이었습니다.DT_RPATH-rpath

관련 정보