[linux] Linux 동적 링커에서 “사용 가능한 버전 정보 없음”오류는 무엇을 의미합니까?

우리 제품에는 “libpam”과 같은 시스템 라이브러리에 동적으로 연결되는 일부 Linux 바이너리가 포함되어 있습니다. 일부 고객 시스템에서는 프로그램이 실행될 때 stderr에서 다음 오류가 발생합니다.

./authpam: /lib/libpam.so.0: no version information available (required by authpam)

응용 프로그램이 제대로 실행되고 동적 라이브러리에서 코드를 실행합니다. 따라서 이것은 치명적인 오류가 아니라 단지 경고 일뿐입니다.

시스템 설치된 라이브러리에 실행 파일이 기대하는 것이 누락되었을 때 이것이 동적 링커에서 발생하는 오류라고 생각합니다. 동적 연결 프로세스의 내부에 대해 많이 알지 못합니다. 주제를 검색하는 것은별로 도움이되지 않습니다. 🙁

누구나이 오류의 원인을 알고 있습니까? … 원인을 어떻게 진단 할 수 있습니까? … 그리고이 문제를 피하기 위해 실행 파일을 어떻게 변경할 수 있습니까?

업데이트 : 고객이 최신 버전의 데비안 “테스트”로 업그레이드했는데 동일한 오류가 발생했습니다. 따라서 오래된 libpam 라이브러리가 아닙니다. 링커가 불평하는 내용을 이해하고 싶습니까? 근본 원인 등을 어떻게 조사 할 수 있습니까?



답변

“사용 가능한 버전 정보 없음”은 공유 객체에서 라이브러리 버전 번호가 더 낮음을 의미합니다. 예를 들어, 바이너리를 빌드 한 시스템에서 major.minor.patch 번호가 7.15.5이고 설치 시스템에서 major.minor.patch 번호가 7.12.1이면 ld는 경고를 인쇄합니다.

대상 OS와 함께 제공되는 공유 객체 버전과 일치하는 라이브러리 (헤더 및 공유 객체)로 컴파일하여이 문제를 해결할 수 있습니다. 예를 들어 RedHat 3.4.6-9에 설치하려는 경우 Debian 4.1.1-21에서 컴파일하고 싶지 않습니다. 이것이 대부분의 배포판이 특정 Linux 배포판 번호로 제공되는 이유 중 하나입니다.

그렇지 않으면 정적으로 링크 할 수 있습니다. 그러나 PAM과 같은 방식으로이 작업을 수행하고 싶지 않기 때문에 클라이언트의 프로덕션 환경과 일치하는 개발 환경을 실제로 설치하려고합니다 (또는 최소한 올바른 라이브러리 버전에 대해 설치하고 연결).

.so 파일의 이름을 바꾸라는 조언 (버전 번호로 패딩)은 공유 객체 라이브러리가 버전이 지정된 기호를 사용하지 않았을 때 발생합니다. 따라서 .so.nnn 이름 지정 체계를 사용하는 것이 도움이 될 것이라고 기대하지 마십시오 (많은-시스템이 폐기 된 경우 도움이 될 수 있습니다).

마지막 옵션은 http://www.redhat.com/docs/manuals/enterprise/RHEL-4-Manual/gnu-linker/scripts 와 같은 사용자 지정 연결 스크립트를 사용하여 다른 부 버전 번호를 가진 라이브러리로 컴파일하는 것
입니다. HTML

이렇게하려면 사용자 지정 스크립트를 작성해야하며 사용자 지정 스크립트를 사용하여 클라이언트의 공유 개체에 대해 ld를 실행하는 사용자 지정 설치 프로그램이 필요합니다. 이를 위해서는 클라이언트의 프로덕션 시스템에 gcc 또는 ld가 있어야합니다.


답변

glibc 동적 링커의이 메시지가 실제로 의미하는 것은 언급 된 라이브러리 ( /lib/libpam.so.0귀하의 경우)에는 VERDEFELF 섹션 이없는 반면 바이너리 ( authpam귀하의 경우)에는 VERNEED이 라이브러리 (아마도 libpam.so.0)에 대한 섹션에 버전 정의가 있다는 것 입니다. 당신은 쉽게 그것을 볼 수있는 readelf단지를 보면, .gnu.version_d.gnu.version_r섹션 (또는 그 부족).

바이너리가를 통해 일부 특정 버전을 얻을 원한다면 있기 때문에, 심볼 버전이 일치하지 그래서 VERNEED라이브러리는 실제에서 제공하지 않은 VERDEF, 즉 하드 링커 오류가 될 것이며, 바이너리가 전혀 실행되지 않을 것 같은 ( 이것 또는 저것 과 비교 ). 바이너리는 일부 버전을 원하지만 라이브러리는 버전에 대한 정보를 제공하지 않습니다.

실제로 그것은 무엇을 의미합니까? 일반적으로이 예제에서 볼 수있는 것과 정확히 일치합니다. 아무것도, 버전 관리를 무시하고 작동합니다. 일이 깨질 수 있습니까? 물론, 그렇습니다. 다른 답변은 런타임에 바이너리가 빌드 타임에 링크 된 라이브러리와 동일한 라이브러리를 사용해야한다는 사실에서 정확합니다.

더 자세한 정보는 Ulrich Dreppers “ELF Symbol Versioning” 에서 찾을 수 있습니다 .


답변

Fwiw, zenoss 모니터링 시스템이 설치된 시스템에서 check_nrpe를 실행할 때이 문제가 발생했습니다. 혼란을 더하기 위해 루트 사용자로는 잘 작동했지만 zenoss 사용자로는 제대로 작동하지 않았습니다.

zenoss 사용자에게 LD_LIBRARY_PATH가있어 zenoss 라이브러리를 사용하여 이러한 경고를 발생시키는 것으로 나타났습니다. 즉 :

root@monitoring:$ echo $LD_LIBRARY_PATH

su - zenoss
zenoss@monitoring:/root$ echo $LD_LIBRARY_PATH
/usr/local/zenoss/python/lib:/usr/local/zenoss/mysql/lib:/usr/local/zenoss/zenoss/lib:/usr/local/zenoss/common/lib::
zenoss@monitoring:/root$ /usr/lib/nagios/plugins/check_nrpe -H 192.168.61.61 -p 6969 -c check_mq
/usr/lib/nagios/plugins/check_nrpe: /usr/local/zenoss/common/lib/libcrypto.so.0.9.8: no version information available (required by /usr/lib/libssl.so.0.9.8)
(...)
zenoss@monitoring:/root$ LD_LIBRARY_PATH= /usr/lib/nagios/plugins/check_nrpe -H 192.168.61.61 -p 6969 -c check_mq
(...)

어쨌든, 내가 말하려는 것은 LD_LIBRARY_PATH, LD_PRELOAD 등과 같은 변수도 확인하십시오.


답변

앱을 어떻게 컴파일하고 있습니까? 어떤 컴파일러 플래그?

내 경험상, Linux 시스템의 광대 한 영역을 대상으로 할 때 지원하려는 가장 오래된 버전에 패키지를 빌드하고 더 많은 시스템이 이전 버전과 호환되는 경향이 있으므로 앱이 계속 작동합니다. 사실 이것은 이전 버전과의 호환성을 보장하는 라이브러리 버전 관리의 전체 이유입니다.


답변

당신은 본 적 이미? 원인은 아마도 해당 고객의 측면에서 매우 오래된 libpam으로 보입니다.

또는 버전에 대한 링크가 누락되었을 수 있습니다. http://www.linux.org/docs/ldp/howto/Program-Library-HOWTO/shared-libraries.html


답변