GLIBC_2\.[0-9]+ NOT FOUND 시 대처법

blackridge의 이미지

LINUX 에서 DNS 에서 MX 레코드를 알아오려고 resolv 라이브러리를 링크시켜서 잘 돌아가는 것 확인하고
실행파일을 원격의 서버에 복사하고 실행했더니...


/lib64/libresolv.so.2: version `GLIBC_2.9' not found

일단 문제를 해결할 수 있다는 가정으로 시작하자. 이런 메시지에 짜증내면 지는거다.

이건 빌드하는 쪽의 GLIBC 버전 확인


$ rpm -qa | grep glibc
glibc-devel-2.12-1.80.el6_3.6.x86_64
glibc-2.12-1.80.el6_3.6.x86_64
glibc-common-2.12-1.80.el6_3.6.x86_64
glibc-2.12-1.80.el6_3.6.i686
glibc-headers-2.12-1.80.el6_3.6.x86_64
glibc-static-2.12-1.80.el6_3.6.x86_64

이건 타깃 쪽의 GLIBC 버전 확인


$ rpm -qa | grep glibc
glibc-2.5-81
compat-glibc-2.3.4-2.26
glibc-2.5-81
glibc-devel-2.5-81
glibc-common-2.5-81
glibc-headers-2.5-81
compat-glibc-2.3.4-2.26
glibc-devel-2.5-81
compat-glibc-headers-2.3.4-2.26

위에서 보는 바와 같이 확실히 타깃쪽이 버전이 더 낮다. 그렇다고 타깃의 버전을 무작정 올릴 수는 없다. 혼자 쓰는 피씨도 아니고 운영중인 서버에 맘대로 라이브러리 버전 올리는 것은 꿈도 못꾼다고 보면 된다. 일단 resolv 라이브러리가 GLIBC 를 우회하도록 resolv 라이브러리를 정적으로 링크하도록 시도해본다.

실제 옵션을 사용하는 방법은 예를 들어 다음과 같다. 단지 -Wl,-Bstatic-Wl,-Bdynamic 옵션사이에 정적으로 링크해야할 라이브러리 링크 옵션을 집어넣고 링크하기만 하면 된다.


cc -L /usr/lib -L /usr/local/lib -g -O0 \
무슨무슨파일.o 그런그런파일.o 이런이런파일.o 저런저런파일.o \
-l pthread \
-Wl,-Bstatic -l resolv -Wl,-Bdynamic \
-o 실행파일명

이상없이 잘 컴파일되고 문제있었던 서버에 바이너리를 다시 배포해보니 잘 동작한다.

그렇다면 이러한 문제를 어떻게 미리 예측/파악하고, 또 미리 회피할 수 있을까?
답은 프로그램이나 라이브러리의 심볼테이블을 확인하는 nm 명령에 있다.


$ nm GLIBC_호환성_문제있는_프로그램명 | grep @GLIBC_
U __ctype_b_loc@@GLIBC_2.3
U __dn_expand@@GLIBC_2.2.5
U __errno_location@@GLIBC_2.2.5
U __libc_start_main@@GLIBC_2.2.5
U __res_search@@GLIBC_2.2.5
U access@@GLIBC_2.2.5
U backtrace@@GLIBC_2.2.5
U backtrace_symbols@@GLIBC_2.2.5
U close@@GLIBC_2.2.5
U connect@@GLIBC_2.2.5
U fcntl@@GLIBC_2.2.5
U fflush@@GLIBC_2.2.5
U fprintf@@GLIBC_2.2.5
U free@@GLIBC_2.2.5
U freopen@@GLIBC_2.2.5
U gethostbyname_r@@GLIBC_2.2.5
U getopt@@GLIBC_2.2.5
U getpid@@GLIBC_2.2.5
U gettimeofday@@GLIBC_2.2.5
U htons@@GLIBC_2.2.5
U ioctl@@GLIBC_2.2.5
U localtime_r@@GLIBC_2.2.5
U malloc@@GLIBC_2.2.5
U memcpy@@GLIBC_2.2.5
U memmove@@GLIBC_2.2.5
U memset@@GLIBC_2.2.5
U ns_initparse@@GLIBC_2.9
U ns_parserr@@GLIBC_2.9
U ns_sprintrr@@GLIBC_2.9
0000000000606a00 B optarg@@GLIBC_2.2.5
U poll@@GLIBC_2.2.5
U printf@@GLIBC_2.2.5
U pthread_create@@GLIBC_2.2.5
U pthread_mutex_lock@@GLIBC_2.2.5
U pthread_mutex_unlock@@GLIBC_2.2.5
U pthread_self@@GLIBC_2.2.5
U recv@@GLIBC_2.2.5
U send@@GLIBC_2.2.5
U snprintf@@GLIBC_2.2.5
U socket@@GLIBC_2.2.5
0000000000606a10 B stdout@@GLIBC_2.2.5
U strchr@@GLIBC_2.2.5
U strcpy@@GLIBC_2.2.5
U strdup@@GLIBC_2.2.5
U strerror@@GLIBC_2.2.5
U strftime@@GLIBC_2.2.5
U strlen@@GLIBC_2.2.5
U strrchr@@GLIBC_2.2.5
U time@@GLIBC_2.2.5
U vfprintf@@GLIBC_2.2.5

위에서 보는 바와 같이 GLIBC 2.9 버전이상의 라이브러리가 필요한 함수는 ns_initparse, ns_parserr, ns_sprintrr 이렇게 3개의 함수이다.
나머지는 모두 2.2 대 버전을 사용한다는 것을 알 수 있다.
각 함수가 어떤 라이브러리에 속해있는지 알려면 다시 여러 라이브러리 디렉토리에서 find 명령을 사용하여 해당 라이브러리에 대한 nm 명령의 결과로 "T 함수명" 을 가지고 있는지 보면 된다. 그렇게 알아낸 라이브러리명을 사용하여 스태틱라이브러리가 있으면 스태틱으로 링크하면 되는 것이다.

여튼 이러한 문제를 일으키는 함수들, 즉, 공유 라이브러리 전체를 대상으로 GLIBC_2.5 이상을 필요로 하는 함수들은 다음과 같이 찾아볼 수 있다.


$ find /lib* /usr/lib* -type f -name '*.so' | xargs -i nm {} | grep "GLIBC_2.[5-9]" > GLIBC_2.5
$ cat GLIBC_2.5
00000000 A GLIBC_2.7
00000000 A GLIBC_2.9
U ns_get16@@GLIBC_2.9
00000000 A GLIBC_2.5
00000000 A GLIBC_2.6
00000000 A GLIBC_2.7
00000000 A GLIBC_2.8
00000000 A GLIBC_2.9
00000000 A GLIBC_2.5
00000000 A GLIBC_2.6
00000000 A GLIBC_2.7
00000000 A GLIBC_2.8
00000000 A GLIBC_2.9
0000000000000000 A GLIBC_2.7
0000000000000000 A GLIBC_2.9
U ns_get16@@GLIBC_2.9
0000000000000000 A GLIBC_2.5
0000000000000000 A GLIBC_2.6
0000000000000000 A GLIBC_2.7
0000000000000000 A GLIBC_2.8
0000000000000000 A GLIBC_2.9

문제를 일으키는 함수는 ns_get16 밖에 없다. 그러니까 위에서 발견했던 ns_initparse, ns_parserr, ns_sprintrr함수들이 바로 이 함수를 내부적으로 호출하기때문에 상위버전의 GLIBC 가 링크되었던 것이다. ㅡ.ㅡ; 결국 libresolv 너님이 트러블메이커였구나라는 결론에 도달...
두개가 나오는데... 하나는 32비트용, 다른 하나는 64비트용일 것이다. (앞의 주소길이가 말해주고 있다...)

LINUX 배포판만들때 방금 위의 명령으로 체크해보면 문제를 일으킬만한 함수들과 라이브러리들을 모두 찾아낼 수 있을 것이다.
또한 나처럼 서버에 바이너리 실행파일들을 배포하는 개발자들에게도 매우 유용할 것이다.



Forums: 

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.