LD_DEBUG 환경 변수 (2012)

발행: (2026년 6월 10일 AM 02:29 GMT+9)
6 분 소요

출처: Hacker News

원본 게시일: 2012년 4월 23일, 2019년 9월 10일 업데이트(문제 해결 도구 링크 추가), 2019년 10월 18일 업데이트(Jekyll로 이전), 2023년 4월 3일 업데이트(다른 도구 링크 추가)

많은 공유(동적) 라이브러리를 사용하는 대규모 시스템을 개발하면, 진단하기 어려운 짜증나는 버그가 발생할 수 있습니다. 이러한 버그는 시스템에 여러 버전의 라이브러리가 존재하고, 개발자가 의도한 버전이 아닌 “잘못된” 버전이 로드될 때 흔히 발생합니다.

Note Linux에서 링크 문제를 진단하기 위한 온라인 도구 를 제공하고 있습니다. 현재 전문가 시스템으로 구현 중이며, 작성 시점에도 이미 유용하게 사용할 수 있습니다.

예전에는 strace 명령어(man strace)와 함께 어떤 라이브러리가 접근되는지 확인하면서 비교적 효율적으로 문제를 디버깅했습니다. 하지만 공유 라이브러리 로딩 문제를 디버깅하는 덜 알려진 더 효율적인 방법이 있습니다: LD_DEBUG 환경 변수입니다.

LD_DEBUG 변수를 설정하면 Linux 동적 링커가 디버그 정보를 출력합니다. 이를 통해 대부분의 로딩 문제를 매우 빠르게 해결할 수 있습니다. 사용 가능한 옵션을 확인하려면 변수에 help를 지정하고 프로그램을 실행하면 됩니다.

LD_DEBUG=help cat
Valid options for the LD_DEBUG environment variable are:

  libs        display library search paths
  reloc       display relocation processing
  files       display progress for input file
  symbols     display symbol table processing
  bindings    display information about symbol binding
  versions    display version dependencies
  all         all previous options combined
  statistics  display relocation statistics
  unused      determined unused DSOs
  help        display this help message and exit

To direct the debugging output into a file instead of standard output
a filename can be specified using the LD_DEBUG_OUTPUT environment
variable.

Note 링크 문제를 다루는 데 유용한 다른 도구들도 많이 있습니다:

  • strace 프로그램은 시스템 콜 전체를 보여주며, 동적 라이브러리 검색·열기 과정을 확인할 수 있습니다.
  • ldd 프로그램은 동적 라이브러리 의존성을 해석합니다.
  • objdump -x YOURFILE | grep NEEDED 명령은 프로그램이나 라이브러리 안에 어떤 다른 라이브러리가 필요한지 보여줍니다.
  • patchelf 프로그램을 사용하면 ELF 실행 파일의 rpath를 쉽게 바꿔 내장 검색 순서를 조정할 수 있습니다.
  • LD_PRELOAD 환경 변수를 이용하면 동적 라이브러리를 손쉽게 교체할 수 있습니다.

추가 조언이 필요하신가요? 20년 이상의 경험을 바탕으로 저희가 도와드릴 수 있습니다 – 연락처: webs@bnikolic.co.uk

Note 이 변수는 Linux 전용입니다. Windows에서는 “Show Loader Snaps”를 활성화하면 비슷한 정보를 얻을 수 있습니다(https://abitofscotland.wordpress.com/2019/12/20/dll-load-failure/). gflags.exe 프로그램으로 해당 옵션을 켜고 windbg로 로그를 확인하면 됩니다. 예시:

  • gflagswindbg가 포함된 Windows SDK를 설치합니다. winget install Microsoft.WindowsSDK.10.0.19041 (또는 Microsoft 웹사이트에서 다운로드)
  • 실행 파일에 ShowLoaderSnaps를 활성화합니다. 예: PowerShell에서 &"C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\gflags.exe" /i notepad.exe +sls
  • notepad.exe를 WinDbg에서 실행합니다. 상세한 DLL 로딩 로그가 표시됩니다.

아래는 제 노트북에서 실행한 예시입니다:

 LD_DEBUG=all cat
 28504:	
 28504:	file=libc.so.6 [0];  needed by cat [0]
 28504:	find library=libc.so.6 [0]; searching
 28504:	 search path=/home/bnikolic/s/lib/tls/x86_64:/home/bnikolic/s/lib/tls:/home/bnikolic/s/lib/x86_64:/home/bnikolic/s/lib:tls/x86_64:tls:x86_64::/home/bnikolic/d/p/R-2.14.1bin/lib/R/lib/tls/x86_64:/home/bnikolic/d/p/R-2.14.1bin/lib/R/lib/tls:/home/bnikolic/d/p/R-2.14.1bin/lib/R/lib/x86_64:/home/bnikolic/d/p/R-2.14.1bin/lib/R/lib		(LD_LIBRARY_PATH)
 28504:	  trying file=/home/bnikolic/s/lib/tls/x86_64/libc.so.6
 28504:	  trying file=/home/bnikolic/s/lib/tls/libc.so.6
 28504:	  trying file=/home/bnikolic/s/lib/x86_64/libc.so.6
 28504:	  trying file=/home/bnikolic/s/lib/libc.so.6
 28504:	  trying file=tls/x86_64/libc.so.6
 28504:	  trying file=tls/libc.so.6
 28504:	  trying file=x86_64/libc.so.6
 28504:	  trying file=libc.so.6
 28504:	  trying file=/home/bnikolic/d/p/R-2.14.1bin/lib/R/lib/tls/x86_64/libc.so.6
 28504:	  trying file=/home/bnikolic/d/p/R-2.14.1bin/lib/R/lib/tls/libc.so.6
 28504:	  trying file=/home/bnikolic/d/p/R-2.14.1bin/lib/R/lib/x86_64/libc.so.6
 28504:	  trying file=/home/bnikolic/d/p/R-2.14.1bin/lib/R/lib/libc.so.6
 28504:	 search cache=/etc/ld.so.cache
 28504:	  trying file=/lib/x86_64-linux-gnu/libc.so.6
 28504:	
 28504:	file=libc.so.6 [0];  generating link map
 28504:	  dynamic: 0x00007fc38e525b40  base: 0x00007fc38e18c000   size: 0x00000000003a0368
 28504:	    entry: 0x00007fc38e1ad420  phdr: 0x00007fc38e18c040  phnum:                 10
 28504:	
 28504:	checking for version `GLIBC_2.4' in file /lib/x86_64-linux-gnu/libc.so.6 [0] required by file cat [0]
 28504:	checking for version `GLIBC_2.3' in file /lib/x86_64-linux-gnu/libc.so.6 [0] required by file cat [0]
 28504:	checking for version `GLIBC_2.3.4' in file /lib/x86_64-linux-gnu/libc.so.6 [0] required by file cat [0]
 28504:	checking for version `GLIBC_2.2.5' in file /lib/x86_64-linux-gnu/libc.so.6 [0] required by file cat [0]
 28504:	checking for version `GLIBC_2.3' in file /lib64/ld-linux-x86-64.so.2 [0] required by file /lib/x86_64-linux-gnu/libc.so.6 [0]
 28504:	checking for version `GLIBC_PRIVATE' in file /lib64/ld-linux-x86-64.so.2 [0] required by file /lib/x86_64-linux-gnu/libc.so.6 [0]
 28504:	
 28504:	relocation processing: /lib/x86_64-linux-gnu/libc.so.6 (lazy)
 28504:	symbol=_res;  lookup in file=cat [0]
 28504:	symbol=_res;  lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
 28504:	binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `_res' [GLIBC_2.2.5]
 28504:	symbol=_IO_file_close;  lookup in file=cat [0]
 28504:	symbol=_IO_file_close;  lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
 28504:	binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `_IO_file_close' [GLIBC_2.2.5]
 28504:	symbol=stderr;  lookup in file=cat [0]
 28504:	binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to cat [0]: normal symbol `stderr' [GLIBC_2.2.5]
 28504:	symbol=error_one_per_line;  lookup in file=cat [0]
 28504:	symbol=error_one_per_line;  lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
 28504:	binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to /lib/x86_64-linux-gnu
0 조회
Back to Blog

관련 글

더 보기 »

생물학적 진화와 정보 획득

A few weeks ago we lookedhttps://www.construction-physics.com/p/information-and-technological-evolution at a simulation of technological evolutionhttps://sites....

단순 HTML의 놀라운 효과 (2021)

I've told this story at conferences - but due to the general situation I thought I'd retell it here. A few years ago I was doing policy research in a housing be...