작업 패키지에 일부 라이브러리에 대해 ldd가 "찾을 수 없음"을 반환한 일부 파일이 포함되어 있는 것을 많이 발견했습니다. 예를 들어...
/usr/lib64/thunderbird/libprldap60.so
libldap60.so => not found
/usr/lib64/libreoffice/program/libofficebean.so
libjawt.so => not found
Thunderbird와 Libre Office를 사용하는 수백 명의 사용자가 있는데 아무도 문제를 보고하지 않았습니다. 다음 파일이 시스템에 존재합니다.
/usr/lib64/thunderbird/libldap60.so
/usr/lib/jvm/java-1.6.0-openjdk-1.6.0.33.x86_64/jre/lib/amd64/libjawt.so
/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.71.x86_64/jre/lib/amd64/libjawt.so
이 예에서 /usr/bin/thunderbird 및 /usr/bin/libreoffice는 모두 해당 프로그램을 시작하는 데 사용되는 래퍼 스크립트입니다. 이 스크립트가 이러한 라이브러리가 표시되도록 환경을 설정한다고 예상했지만 그렇지 않습니다. . 이것은 다음과 같습니다. 이것은 스크립트에서 발생합니다.
우리 시스템에는 이와 같은 예가 수백 개가 있습니다. 예를 들어 이 두 가지만 선택하겠습니다. 무슨 일인지 설명해 줄 수 있는 사람 있나요?
답변1
간단하고 아마도 분명한 대답은 보고 있는 라이브러리의 검색 경로에 ldd
라이브러리 자체 종속성이 있는 디렉터리가 포함되어 있지 않다는 것입니다. 일반적으로 라이브러리의 종속성이 시스템 전체의 표준 위치에서 발견되지 않는 한 지정된 실행 경로(환경 변수 $LD_RUN_PATH
또는 적절한 링커 옵션 사용)를 사용하여 라이브러리를 빌드해야 합니다. 그렇지 않으면 NET에서처럼 나중에 런타임 시 이러한 라이브러리를 찾을 수 없습니다 ldd
.
그렇다면 왜 Thunderbird는 이러한 "문제"에도 불구하고 여전히 작동합니까?
실행 경로가 부족함에도 불구하고 필요한 라이브러리를 찾는 방법에는 여러 가지가 있습니다.
- 환경 변수는
$LD_LIBRARY_PATH
런타임 시 설정되며 검색할 추가 디렉터리 목록을 제공합니다. - 필요한 디렉토리는 현재 라이브러리 이전에 로드되는 관련 없는 다른 라이브러리의 실행 경로에서 발견되므로 검색 경로에 이미 포함되어 있을 수 있습니다. 그런데 이것이 표준에 명시된 구현 사고인지 확실하지 않습니다. 그럼에도 불구하고 라이브러리가 로드되는 정확한 순서에 크게 의존하기 때문에 취약합니다.
dlopen()
라이브러리는 전체 경로 이름이 지정된 함수를 사용하여 애플리케이션에 의해 수동으로 로드되었을 수 있습니다 .
Thunderbird는 이 마지막 기술을 사용하고 있는 것으로 보입니다. 시작 시 출력을 살펴본 strace
결과 다음과 같은 것 같습니다.
- 자체 바이너리가 있는 디렉터리를 찾으세요. Thunderbird를 시작하는 쉘 스크립트 도우미가 이를 수행하기 위해 전체 경로 이름을 사용하기 때문에 이는 항상 가능합니다.
dependentlibs.list
이 디렉터리에 있는 텍스트 파일을 엽니다.- 이 텍스트 파일의 각 파일 이름에 대해 전체 경로 이름을 구성하기 위해 동일한 디렉터리를 앞에 추가하고
dlopen()
. - 이제 언급한 모든 종속 라이브러리
libldap60.so
는 "사전 로드"되어 있으며 이를 필요로 하는 다른 라이브러리는 해당 라이브러리를 다시 찾을 필요가 없습니다.
에 나열된 순서나 파일이 dependentlibs.list
중요하다는 점에 유의하세요.
Thunderbird가 이렇게 하는 이유는 해당 디렉토리가 애플리케이션이나 내부 라이브러리의 실행 경로에 하드 코딩될 필요가 없기 때문입니다.
Java가 무엇을 하는지는 모르지만 비슷한 것이 있다는 것은 의심할 여지가 없습니다.