실행 파일이 사용하는 공유 라이브러리의 절대 경로 찾기

실행 파일이 사용하는 공유 라이브러리의 절대 경로 찾기

예제 lshw프로그램으로 다음이 ldd제공됩니다.

$ ldd /usr/sbin/lshw    

linux-vdso.so.1 =>  (0x00007fff8bdaf000)
libresolv.so.2 => /lib64/libresolv.so.2 (0x000000360e400000)
libsqlite3.so.0 => /lib64/libsqlite3.so.0 (0x0000003631600000)
libstdc++.so.6 => /lib64/libstdc++.so.6 (0x000000360ec00000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x000000360d800000)
libc.so.6 => /lib64/libc.so.6 (0x000000360c000000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x000000360cc00000)
libdl.so.2 => /lib64/libdl.so.2 (0x000000360c800000)
libm.so.6 => /lib64/libm.so.6 (0x000000360c400000)
/lib64/ld-linux-x86-64.so.2 (0x000000360bc00000)

공유 라이브러리의 절대 위치를 찾고 싶다면(그리고 명백한 이유로 linux-vdso.so.1을 제외하고 싶다면) 어떻게 해야 합니까? 정규 표현식과 함께 awk를 사용하면 취약해 보입니다. ldd공유 라이브러리에 대한 전체 경로를 인쇄하는 자세한 플래그(-v)가 있지만 기계에서 읽을 수는 없습니다.

이 문제를 해결할 다른 방법이 있나요? 누군가 이 작업을 수행하는 시스템 호출을 알고 있다면 나도 동의할 것입니다.

추신: 어떤 상황에서는 이 프로그램을 감옥에서 실행하고 싶기 chroot때문에 공유 라이브러리를 모두 사용할 수 있는지 확인해야 합니다. 이를 정적으로 컴파일하면 이 모든 드라마를 피할 수 있지만 그것이 제가 피하고 싶은 경로입니다.

고쳐 쓰다:

나는 나를 그리워한다가능한나는 Michael Kerrisk의 책 "Linux 프로그래밍 인터페이스"를 읽으면서 더 적합할 수 있는 것을 발견했습니다. 프로그램을 실행하면 $ LD_DEBUG=libs lshw온갖 유용한 정보가 출력됩니다. 예를 들어:

$ LD_DEBUG=libs lshw 
     32058:     find library=libresolv.so.2 [0]; searching
     32058:      search cache=/etc/ld.so.cache
     32058:       trying file=/lib64/libresolv.so.2
     32058:
     32058:     find library=libstdc++.so.6 [0]; searching
     32058:      search cache=/etc/ld.so.cache
     32058:       trying file=/lib64/libstdc++.so.6
     32058:
     32058:     find library=libgcc_s.so.1 [0]; searching
     32058:      search cache=/etc/ld.so.cache
     32058:       trying file=/lib64/libgcc_s.so.1
     32058:
     32058:     find library=libc.so.6 [0]; searching
     32058:      search cache=/etc/ld.so.cache
     32058:       trying file=/lib64/libc.so.6
     32058:
     32058:     find library=libm.so.6 [0]; searching
     32058:      search cache=/etc/ld.so.cache
     32058:       trying file=/lib64/libm.so.6
     32058:
     32058:
     32058:     prelink checking: ok
     32058:
     32058:     calling init: /lib64/ld-linux-x86-64.so.2
     32058:
     32058:
     32058:     calling init: /lib64/libc.so.6
     32058:
     32058:
     32058:     calling init: /lib64/libm.so.6
     32058:
     32058:
     32058:     calling init: /lib64/libgcc_s.so.1
     32058:
     32058:
     32058:     calling init: /lib64/libstdc++.so.6
     32058:
     32058:
     32058:     calling init: /lib64/libresolv.so.2


     <more output>

"calling init" 라인을 찾으면 프로그램 실행을 시작하기 전에 초기화되는 공유 라이브러리 경로를 갖게 될 것이라고 생각합니다.

답변1

정규식을 사용하지 않고 awk를 시도해 볼 수 있습니다.

ldd /bin/ls | awk 'NF == 4 {print $3}; NF == 2 {print $1}'

산출:

/lib/x86_64-linux-gnu/libselinux.so.1
/lib/x86_64-linux-gnu/librt.so.1
/lib/x86_64-linux-gnu/libacl.so.1
/lib/x86_64-linux-gnu/libc.so.6
/lib/x86_64-linux-gnu/libdl.so.2
/lib64/ld-linux-x86-64.so.2
/lib/x86_64-linux-gnu/libpthread.so.0
/lib/x86_64-linux-gnu/libattr.so.1

답변2

정규식이 필요하지 않다고 말씀하셨지만 해당 줄의 "=>"를 사용하면 구문 분석이 쉬워집니다. 장황한 모드에서도 이를 사용하므로 장황한 출력을 정규식에 전달할 수도 있습니다(일부 조정 포함). 나는 chroot 환경을 설정하기 위해 루프 변수 목록(for i in ...)으로 이와 같은 명령을 사용합니다.

먼저 sed를 사용하는 두 가지 방법을 알려 드리겠습니다.

    ldd /path/to/binary | egrep -v 'linux-vdso|ld-linux-x86-64' | sed 's/.*\=> \(.*\) (.*/\1/'

또는 다음과 같이 공백과 잘라내기를 사용하여 구문 분석해 볼 수도 있습니다.

    ldd /path/to/binary | egrep -v 'linux-vdso|ld-linux-x86-64' | cut -f 3 -d ' '

이 두 가지 모두 나에게 다음을 제공합니다.

    ldd /bin/ls | egrep -v 'linux-vdso|ld-linux-x86-64' | cut -f 3 -d ' '
    /lib/libselinux.so.1
    /lib/librt.so.1
    /lib/libacl.so.1
    /lib/libc.so.6
    /lib/libdl.so.2
    /lib/libpthread.so.0 
    /lib/libattr.so.1

답변3

GNU grep을 사용하십시오:

ldd /usr/sbin/lshw | grep -Po '/.*(?= \(0x)'

이러한 경로에 공백 문자가 포함되지 않는다고 보장할 수 있다면 다음과 같이 단순화할 수 있습니다.

ldd /usr/sbin/lshw | grep -o '/[^ ]*'

그리고 sed:

ldd /usr/sbin/lshw | sed -n 's,[^/]*\(/.*\) (0x.*,\1,p'

아이디어는 처음 부터 마지막까지 /모든 것을 얻는 것입니다.(0x

관련 정보