Linux, GNU GCC, ld, 버전 스크립트 및 ELF 바이너리 형식 - 어떻게 작동하나요?

Linux, GNU GCC, ld, 버전 스크립트 및 ELF 바이너리 형식 - 어떻게 작동하나요?

저는 Linux의 라이브러리 버전 관리와 이를 모두 작동시키는 방법에 대해 자세히 알아보려고 합니다. 컨텍스트는 다음과 같습니다.

libsome1.so- 및 와 같은 동일한 인터페이스 세트를 노출하는 두 가지 버전의 동적 라이브러리가 있습니다 libsome2.so.

- 에 연결된 애플리케이션 libsome1.so.

- 애플리케이션은 libdl.so다른 모듈(예: )을 동적으로 로드하는 데 사용됩니다 libmagic.so.

- 이제 libmagic.so푹 빠졌어요 libsome2.so. 분명히 런타임에 숨겨진 링커 스크립트의 libmagic.so인터페이스에 대한 모든 호출 은 . 이는 매크로 값과 비교하여 반환된 값을 확인하여 확인할 수 있습니다 .libsome2.solibsome1.solibVersion()LIB_VERSION

-- 그래서 다음 으로 정의되고 내보내지는 libmagic.so3을 제외한 모든 기호를 숨기는 링커 스크립트를 사용하여 컴파일하고 링크하려고 했습니다 . libmagic.so이것은 작동합니다...또는 적어도 값 libVersion()과 일치합니다 (그리고 1 대신 버전 2를 보고합니다).LIB_VERSION

-- 그러나 특정 데이터 구조가 디스크에 직렬화될 때 일부 손상이 발견되었습니다. 응용 프로그램 디렉터리에서 을 libsome1.so가리키는 소프트 링크를 제거하고 생성하면 libsome2.so모든 것이 예상대로 작동하고 동일한 손상이 발생하지 않습니다.

나는 이것이 런타임 링커의 기호 해석에 충돌이 있기 때문에 발생할 수 있다고 생각하지 않을 수 없습니다. 나는 libsome2.so모든 기호가 정렬되도록 연결하는 것과 같은 여러 가지 시도를 했습니다. (명령이 여전히 기호를 대신 나열하기 symbol@@VER_2때문에 이것에 대해 여전히 혼란스럽습니다 .)... 아무것도 작동하지 않는 것 같습니다! 돕다! ! ! ! ! !nm -CD libsome2.sosymbolsymbol@@VER_2

답변1

귀하의 질문에 대한 정확한 답변은 아니지만 ...

우선, ELF는 리눅스에서 실행 파일(프로그램), 공유 라이브러리, 객체 파일(소프트웨어를 컴파일할 때 발견되는 중간 파일)에 사용되는 사양입니다. 개체 파일은 .o로 끝나고, 공유 라이브러리는 .so로 끝나고, 그 뒤에 마침표로 구분된 0개 이상의 숫자가 오고, 실행 파일에는 일반적으로 확장자가 없습니다.

일반적으로 공유 라이브러리 이름 지정에는 세 가지 형태가 있으며, 그 중 첫 번째는 단순히 .so로 끝납니다. 예를 들어, readline이라는 라이브러리는 libreadline.so라는 파일에 저장되며 일반적으로 /lib, /usr/lib 또는 /usr/local/lib 중 하나에 위치합니다. 이 파일은 -lreadline과 같은 옵션을 사용하여 소프트웨어를 컴파일할 때 발견됩니다. -l은 컴파일러에게 다음 라이브러리에 대해 링크하도록 지시합니다. 라이브러리는 수시로 변경되기 때문에 오래될 수 있으므로 라이브러리에는 SONAME이라는 항목이 포함되어 있습니다. readline의 SONAME은 libreadline의 두 번째 주요 버전인 libreadline.so.2와 유사할 수 있습니다. 소프트웨어를 다시 컴파일할 필요가 없는 readline의 호환 가능한 부 버전이 많이 있을 수도 있습니다. readline의 마이너 버전 이름은 libreadline.so.2.14일 수 있습니다. 일반적으로 libreadline.so는 readline의 최신 주요 버전(이 경우 libreadline.so.2)에 대한 심볼릭 링크일 뿐입니다. libreadline.so.2는 실제로 사용되는 파일인 libreadline.so.2.14에 대한 심볼릭 링크이기도 합니다.

라이브러리의 SONAME은 라이브러리 파일 자체에 포함되어 있습니다. libreadline.so.2.14 파일 내 어딘가에 libreadline.so.2 문자열이 있습니다. 프로그램이 readline을 사용하여 컴파일되고 링크되면 libreadline.so 파일을 찾아 여기에 포함된 SONAME을 읽습니다. 나중에 프로그램이 실제로 실행되면 libreadline.so뿐만 아니라 libreadline.so.2도 로드됩니다. 이는 처음 연결되었을 때 읽은 SONAME이기 때문입니다. 이를 통해 시스템은 호환되지 않는 여러 버전의 readline을 설치할 수 있으며, 각 프로그램은 그에 연결된 적절한 주요 버전을 로드합니다. 또한 readline을 2.17로 업그레이드할 때 기존 라이브러리와 함께 libreadline.so.2.17을 설치할 수 있었고, libreadline.so.2.13에서 libreadline.so.2.17로 심볼릭 링크 libreadline.so.2를 옮기자 모든 소프트웨어가 동일한 메이저 버전을 사용하면 이제 새로운 마이너 업데이트가 표시됩니다.

관련 정보