제가 작성하고 있는 일부 소프트웨어가 충돌을 일으키고 있는데, 두 개의 서로 다른 공유 라이브러리 사이의 기호 충돌로 인해 발생한 것으로 의심됩니다(공유 라이브러리 중 하나를 비활성화하면 다른 하나가 작동하기 시작합니다).
프로그램에 의해 로드된 라이브러리를 보고 둘 이상의 라이브러리에 정의된 기호가 있는지 알려주는 데 사용할 수 있는 도구가 있습니까?
답변1
문제를 해결하기 위해 쉘 스크립트에 사용할 수 있는 몇 가지 일반적인 유틸리티가 있습니다(비록 문제를 해결하기 위해 이들을 결합한 스크립트를 본 기억은 없지만). 이것nm
개체 파일이나 실행 파일에서 기호를 찾는 유틸리티입니다. 대부분의 시스템에서는ldd
( otool
macOS의 경우) 실행 파일에서 사용하는 공유 라이브러리를 표시합니다. 예를 들어 전자의 경우 스크립트(listused.sh
)는 ncurses에 라이브러리의 모든 기호와 해당 라이브러리를 사용하는 프로그램에서 이러한 기호를 테스트할 수 있는지 여부를 나열합니다(참조보고서존재하다test/README
).
이 -C
옵션은 유용하지만(C++ 라이브러리에 관심이 있는 경우) 이러한 라이브러리는벗겨진(디버깅 정보가 누락되었습니다.) 하지만,-D
옵션("최근" 시스템, 즉 지난 10~15년 동안 업데이트된 거의 모든 시스템에서 사용 가능)은 다음 기호를 제공합니다.동적도서관:
- GNU 바이너리틸, 1999년부터
일반 기호 대신 동적 기호를 표시합니다. 이는 특정 유형의 공유 라이브러리와 같은 동적 개체에만 적합합니다.
- ELF 도구 체인, 2008년부터
동적 기호만 표시됩니다. 이 옵션은 공유 라이브러리에만 적합합니다.
기호 정보를 표시합니다
SHT_DYNSYM
. 이것은 ld.so.1에서 사용되는 기호 테이블이며 제거된 동적 실행 파일에도 존재합니다. 만약에–D
지정되지 않은 경우 기본 동작은SHT_SYMTAB
기호 정보를 표시하는 것입니다.
적어도 해당 문서에 따르면 이는 최신 시스템의 기능이 아닙니다.
(누군가는 이 기능 도입 일정을 즉시 알 수 있습니다.)
나는 다음과 같은 일부 스크립트에서 이 기능을 사용했습니다.analyze-curses-symbols
.
추가 자료:
- 공유 라이브러리 기호 충돌(Linux)이 목적으로 이를 사용하는 방법을 보여주는 예를 제공하십시오
nm
. - 3장 동적 공유 객체 사용이전 SGI 매뉴얼에는
elfdump
관련 옵션이 있다고 언급되어 있습니다:
-quickstart_info 옵션을 사용하면 충돌이 발생하면 ld가 이를 알려줍니다. 또한 충돌을 찾으려면 -Dc 옵션과 함께 elfdump를 실행하라는 메시지도 표시됩니다. elfdump에서 생성된 출력을 읽는 방법에 대한 자세한 내용은 elfdump(1) 매뉴얼 페이지를 참조하십시오.
답변2
nm -C library.so | grep -i symbol
당신이 찾고있는 것일 수도 있습니다. 그러나 제거된 라이브러리에서는 작동하지 않을 수 있습니다.
답변3
Linux 동적 링커는 이러한 문제를 디버깅하기 위한 몇 가지 방법도 제공합니다. 예를 들어 export LD_DEBUG=bindings
모든 기호 바인딩에 대한 많은 정보를 얻을 수 있습니다 . 이 모든 출력을 하나의 파일에 수집하고 다양한 시나리오의 출력을 비교하면 일부 기호가 다른 파일에 연결되어 있음을 알 수 있습니다. 보다ld.so 문서더 많은 선택을 위해.
예를 들어 TensorFlow를 바이너리에 연결하고 일부 내장된 Python을 사용할 때 충돌을 추적하고 있습니다. 사고를 import hashlib
. TensorFlow를 연결하지 않아도 충돌이 발생하지 않습니다. (이것도 보고된 것을 발견했습니다.여기그리고여기.)
TF를 연결하면 다음과 같은 출력을 얻습니다.
2306643: binding file /u/zeyer/.linuxbrew/Cellar/[email protected]/3.11.2_1/lib/python3.11/lib-dynload/_hashlib.cpython-311-x86_64-linux-gnu.so [0] to /u/zeyer/.local/lib/python3.11/site-packages/tensorflow/libtensorflow_framework.so.2 [0]: normal symbol `EVP_MD_size' [OPENSSL_1_1_0]
그냥 실행하면 python -c "import hashlib"
다음과 같은 결과가 나타납니다.
2307740: binding file /u/zeyer/.linuxbrew/Cellar/[email protected]/3.11.2_1/lib/python3.11/lib-dynload/_hashlib.cpython-311-x86_64-linux-gnu.so [0] to /work/tools/users/zeyer/linuxbrew/lib/libcrypto.so.1.1 [0]: normal symbol `EVP_MD_size' [OPENSSL_1_1_0]
보시다시피, TF를 사용하는 경우 OpenSSL 관련 기호를 에서 찾고 , 다른 경우에는 (해야 하는 대로) libtensorflow_framework.so.2
에서 해당 기호를 찾습니다 .libcrypto.so.1.1
우리의 해결책은 -L/work/tools/users/zeyer/linuxbrew/lib -Wl,-rpath,/work/tools/users/zeyer/linuxbrew/lib -Wl,-no-as-needed -lcrypto
TF 라이브러리를 연결하기 전에 링커 플래그를 추가하는 것이었습니다. 그래서 libcrypto.so.1.1
먼저 강제로 로드합니다. 이것으로 문제가 해결됩니다. 바라보다여기내 컴파일 스크립트를 위해.