1) Ubuntu 10.04에서 OpenSSL 0.9.8 사용:

1) Ubuntu 10.04에서 OpenSSL 0.9.8 사용:

prog소스에서 빌드하고 설치된 OpenSSL 1.0.2 베타에 프로그램을 컴파일하고 연결하려고 합니다 /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) Debian Wheezy에서 OpenSSL 1.0.1 사용:

같은 단계, 다른 결과.

$ ./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)
  • 런타임 라이브러리 경로(LDFLAGS, LD_RUN_PATH또는 ) LD_LIBRARY_PATH를 통해ld.so.conf

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

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

export CFLAGS="-Wl,-t"

이렇게 하면 추적 옵션이 링커에 전달됩니다. make 프로세스 중에 간결한 "CC" 및 "LD" 줄만 출력되는 경우 -tmake 명령에 또는 를 추가해야 할 수도 있습니다 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).

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

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

최후의 수단으로 "공유" 또는 "아무것도 공유하지 않음" 없이 OpenSSL을 구축할 수 있습니다. 그러면 이 문제가 없는 정적 라이브러리가 제공됩니다(그러나 ELF에서 사용될 때와 같은 다른 문제가 발생할 가능성이 높습니다. 그래서 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()이제 더 이상 사용되지 않으며 (에 따라 ) 올바른 API 함수에 대해 -d OPENSSL_API_COMPAT가 될 수 있습니다 .#defineOpenSSL_version()

답변2

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

#ldconfig -v

캐시를 재구축합니다. 충분히 빠르게 조치를 취하면 인쇄된 긴 목록에 새 라이브러리가 표시됩니다(또는 또는 로 파이프 grep) less.

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

관련 정보