1) Ubuntu 10.04, OpenSSL 0.9.8:

1) Ubuntu 10.04, OpenSSL 0.9.8:

프로그램을 컴파일 prog하고 소스에서 빌드하고 /usr/local/ssl-1.0.2. 0.9.8을 사용하는 이전 시스템에서는 큰 문제 없이 작동합니다. 1.0.1이 설치된 최신 시스템에서는 약간의 작업이 더 필요합니다. 이유가 궁금합니다.

1) Ubuntu 10.04, OpenSSL 0.9.8:

1.0.2에 대해 컴파일하고 링크하기 위해 따르는 단계는 다음과 같습니다.

$ ./config shared --openssldir=/usr/local/ssl-1.0.2 && make && make install
$ ldconfig
$ ldconfig -p | grep libcrypto

=> 0.9.8 파일만 나오므로 1.0.2 파일 경로를 추가해보겠습니다...

$ ldconfig /usr/local/ssl-1.0.2/lib
$ ldconfig -p | grep libcrypto

=>

 libcrypto.so.1.0.0 (libc6) => /usr/local/ssl-1.0.2/lib/libcrypto.so.1.0.0
 libcrypto.so.0.9.8 (libc6, hwcap: 0x0008000000008000) => /lib/i686/cmov/libcrypto.so.0.9.8
 libcrypto.so.0.9.8 (libc6, hwcap: 0x0004000000000000) => /lib/i586/libcrypto.so.0.9.8
 libcrypto.so.0.9.8 (libc6, hwcap: 0x0002000000000000) => /lib/i486/libcrypto.so.0.9.8
 libcrypto.so.0.9.8 (libc6) => /lib/libcrypto.so.0.9.8
 libcrypto.so.0.9.8 (libc6) => /usr/lib/libcrypto.so.0.9.8
 libcrypto.so (libc6) => /usr/local/ssl-1.0.2/lib/libcrypto.so

그래서 컴파일할 수 있습니다 prog...

$ gcc -o prog ... -L/usr/local/ssl-1.0.2/lib -lcrypto
$ ldd prog

=>

    libcrypto.so.1.0.0 => /usr/local/ssl-1.0.2/lib/libcrypto.so.1.0.0 (0x0083b000)

... 그리고 1.0.2와 올바르게 연결되어 있습니다.

2) OpenSSL 1.0.1을 사용하는 Debian Wheezy에서:

같은 단계, 다른 결과.

$ ./config shared --openssldir=/usr/local/ssl-1.0.2 && make && make install
$ ldconfig
$ ldconfig -p | grep libcrypto

=>

 libcrypto.so.1.0.0 (libc6, hwcap: 0x0008000000008000) => /usr/lib/i386-linux-gnu/i686/cmov/libcrypto.so.1.0.0
 libcrypto.so.1.0.0 (libc6, hwcap: 0x0004000000000000) => /usr/lib/i386-linux-gnu/i586/libcrypto.so.1.0.0
 libcrypto.so.1.0.0 (libc6) => /usr/lib/i386-linux-gnu/libcrypto.so.1.0.0

마찬가지로 1.0.2에 경로를 추가합니다...

$ ldconfig /usr/local/ssl-1.0.2/lib
$ ldconfig -p | grep libcrypto

=>

 libcrypto.so.1.0.0 (libc6, hwcap: 0x0008000000008000) => /usr/lib/i386-linux-gnu/i686/cmov/libcrypto.so.1.0.0
 libcrypto.so.1.0.0 (libc6, hwcap: 0x0004000000000000) => /usr/lib/i386-linux-gnu/i586/libcrypto.so.1.0.0
 libcrypto.so.1.0.0 (libc6) => /usr/local/ssl-1.0.2/lib/libcrypto.so.1.0.0
 libcrypto.so.1.0.0 (libc6) => /usr/lib/i386-linux-gnu/libcrypto.so.1.0.0
 libcrypto.so (libc6) => /usr/local/ssl-1.0.2/lib/libcrypto.so

그럼 컴파일을 해보는데...

$ gcc -o prog ... -L/usr/local/ssl-1.0.2/lib -lcrypto
$ ldd prog

=>

    libcrypto.so.1.0.0 => /usr/lib/i386-linux-gnu/i686/cmov/libcrypto.so.1.0.0 (0xb7591000)

그러나 여기서는 1.0.2와 연결되지 않습니다. 컴파일 타임 라이브러리 경로는 정확하지만( 로 지정되지 -L않으면 gcc에서 사용된 일부 함수가 1.0.2에만 해당되므로 실패할 수 있음 prog) 런타임 경로는 올바르지 않습니다.

3) Wheezy에서 작동시키는 방법

실행 여부에 관계없이 ldconfig /usr/local/ssl-1.0.2/lib:

$ gcc -o prog ... -Wl,--rpath=/usr/local/ssl-1.0.2/lib -L/usr/local/ssl-1.0.2/lib -lcrypto
$ ldd prog

=>

    libcrypto.so.1.0.0 => /usr/local/ssl-1.0.2/lib/libcrypto.so.1.0.0 (0xb7592000)

또는 export LD_LIBRARY_PATH=/usr/local/ssl-1.0.2/lib실행하기 전에 실행하세요 gcc.

내가 알고 싶은 것

mr.spuratic의 제안에 따라 LD_DEBUG=libs ./prog경로가 /etc/ld.so.cache. 해당 파일을 열었고 .so가 조회되는 순서가 .so의 출력과 일치한다는 것을 알았습니다 ldconfig -p.

실제 질문은 다음과 같습니다.

  • 1.0.2 파일이 1)에서는 ldconfig 목록의 맨 위에 있지만 2)에서는 그렇지 않은 이유는 무엇입니까? 순수한 무작위성? 1.0.1과 1.0.2 파일의 접미사가 동일하여 혼란이 있습니까? ("1.0.0")

아니면 다르게 말하면,

  • 3)에 추가된 플래그가 1)에 필요하지 않은 이유는 무엇입니까?

답변1

기본이 아닌 패키지에 대해 컴파일/링크할 때 주의해야 할 세 가지 사항이 있습니다.

  • 헤더(보통 CFLAGS)
  • 컴파일 타임 라이브러리 경로(일반적으로 LDFLAGS)
  • 런타임 라이브러리 경로(rpathLDFLAGS, LD_RUN_PATH또는 ) LD_LIBRARY_PATH을 통해ld.so.conf

당신은 그것이 무엇인지 말하지 않았기 prog때문에 그 구성이 얼마나 잘 작동할지 알 수 없습니다(또는 그것이 autoconf를 사용한다면?). 처음 두 단계만 안정적으로 수행하는 많은 것을 보았습니다.

CFLAGS링크 단계에서는 라이브러리 경로 순서가 관련됩니다. GNU 툴체인(gcc 및 binutils)을 사용한다고 가정하면 이전에 설정 configure하거나 직접 설정하여 무슨 일이 일어나고 있는지 확인할 수 있습니다 Makefile.

export CFLAGS="-Wl,-t"

그러면 -t추적 옵션이 링커에 전달됩니다. make 중에 간결한 "CC" 및 "LD" 행만 출력되는 경우 make 명령에 V=1또는 를 추가해야 할 수도 있습니다 .)VERBOSE=1

런타임 시 ld.so신중하게 설정하여 시도하는 내용을 확인할 수 있습니다 LD_DEBUG. 예:

LD_DEBUG=libs ./myprog

(또는 자세한 내용을 보려면 files또는 값을 사용해 보세요)symbols

빌드 시 세 가지 매개변수를 모두 올바르게 지정하려면 다음을 수행할 수 있어야 합니다.

  • export CFLAGS="-I/usr/local/ssl-1.0.2/include"
  • export LDFLAGS="-L/usr/local/ssl-1.0.2/lib -R/usr/local/ssl-1.0.2/lib"

그런 다음 재구성/재컴파일하십시오.

--openssldir더 일반적인 방법보다는 사용하고 있습니다 --prefix(후자를 권장하며 make install_sw기본 설치에서 제공하는 1000개 정도의 매뉴얼 페이지 및 심볼릭 링크가 필요하지 않은 경우에도 사용합니다). 이것이 문제의 일부일 수 있습니다. 어떤 이유로 표시되는 .so 라이브러리에는 ld.so버전 접미사(예: )가 없는 것으로 알려져 있으므로 .so.1.0.2적절한 " make install"가 이를 설정해야 합니다( link-sharedmain 의 대상을 통해 Makefile).

이 옵션은 런타임 링커( )가 일반적으로 제공하는 -R기본값에 의존할 필요가 없도록 특정 OpenSSL 라이브러리에 대한 실행 가능 출력에 RPATH를 포함하도록 링커에 지시합니다 . ld.so다음을 사용하여 기존 바이너리를 수정할 수 있습니다.chrpath대신에.

이는 내보내기와 거의 동일합니다 LD_LIBRARY_PATH=/usr/local/ssl-1.0.2/lib. RPATH 및 관련 RUNPATH에 대한 자세한 내용은 여기에서 확인할 수 있습니다.http://blog.tremily.us/posts/rpath/

최후의 수단으로 "shared" 없이 또는 "noshared"를 사용하여 OpenSSL을 구축할 수 있습니다. 이렇게 하면 이 문제가 없는 정적 라이브러리가 제공됩니다(그러나 ELF .so 내에서 사용하는 경우 PIC가 발생하는 등의 다른 문제가 있을 수 있습니다). /PIE 문제)


업데이트된 세부 정보에 따르면 문제는 1.0.1과 1.0.2beta가 모두 .so 버전 접미사(SONAME)를 1.0.0으로 설정했다는 것입니다. 0.9.8만 있는 첫 번째 시스템에서는 문제가 발생하지 않습니다. 두 번째 버전에서는 1.0.1과 1.0.2가 모두 1.0.0으로 버전이 지정되어 있으며 순서에 따라 "첫 번째 경기에서 승리합니다"입니다 ld.so.{conf,d}. ld컴파일 타임 링커는 ld.so런타임 링커와 다른 프로그램이며 동작이 다를 수 있다는 점을 기억하십시오 (보시다시피 일반적으로 기호 오류 또는 더 심각한 결과를 초래함).

$ cd /usr/local/src/openssl/openssl/1.0.2beta1
$ readelf -a libssl.so | grep SONAME
0x0000000e (SONAME)                     Library soname: [libssl.so.1.0.0]

$ cat verchk.c
int main(int argc, char *argv[]) {
    printf("build: %s\n",OPENSSL_VERSION_TEXT);
    printf("run  : %s\n",SSLeay_version(SSLEAY_VERSION));
    return 0;
}

$ gcc -Wall  -I/usr/local/src/openssl/openssl-1.0.2-beta1/include \
    -Wl,-rpath /usr/local/src/openssl/openssl-1.0.2-beta1/ \
    -o verchk /usr/local/src/openssl/openssl-1.0.2-beta1/libcrypto.so verchk.c

$ ./verchk
build: OpenSSL 1.0.2-beta1 24 Feb 2014
run  : OpenSSL 1.0.2-beta1 24 Feb 2014

$ grep SHLIB_M...R= Makefile
SHLIB_MAJOR=1
SHLIB_MINOR=0.0

업데이트 OpenSSL-1.1에서는 API 수준이 일부 변경되었습니다. 위 코드는 v1.1 헤더 및 이전 라이브러리( undefined reference to `OpenSSL_version')로 컴파일되지 않습니다.

SSLeay_version()이제 더 이상 사용되지 않으며 (에 따라 OPENSSL_API_COMPAT) #define적절한 API 함수에 -d 될 수 있습니다 OpenSSL_version().

답변2

내의 파일 중 하나에 새 lib의 경로가 있습니까 /etc/ld.so.conf.d? 다음 실행:-

#ldconfig -v

캐시를 다시 작성합니다. 빠르면 인쇄된 긴 목록에서 새 라이브러리를 볼 수 있습니다(또는 또는 파이프로 파이프 grep) less.

경로가 이미 첫 번째 서버에는 있었지만 두 번째 서버에는 없었을 수도 있습니다.

관련 정보