동적 라이브러리
안녕하세요.
저는 공부삼아서, 리눅스 부팅 디스켓을 직접 만들고 있습니다.
인터넷 여기저기를 돌아다니다가, 미리 만들어진 디스켓 이미지를 찾았습니다.
그런데, 그 이미지로 부팅해보면, 커널도 꽤 옛날 것이고, /lib에 있는 라이브러리들도 옛날 것이라서 크기가 아주 작답니다.
저는 wowlinux 7.3을 쓰고 있는데, 커널도 크고, /lib 버전도 높고 크기도 큽니다.
만약, 제 시스템의 커널과 라이브러리를 사용해서 같은 형태의 부팅 디스켓을 만든다면, 크기가 너무 커져서, 두장의 디스켓에 넣어야 할 것 같습니다.
그래서, 부팅 디스켓은 옛날 커널과 옛날 라이브러리로 구성하고, 몇가지 제가 필요한 프로그램은 wowlinux7.3 에서 컴파일해서 디스켓에 넣고 싶습니다.
문제는 제 pc에서 hello.c 프로그램을 컴파일해서, 옛날 커널, 옛날 라이브러리가 있는 디스켓 부팅 후에 실행해보면, segmentation fault 가 납니다.
커널 버전이 달라서 문제인것 같지는 않고, 라이브러리가 달라서 문제인것 같은데요...
제 시스템을 아주 옛날 것으로 되돌릴 수는 없고...
그래서 제가 궁금한 것은,
1. 높은 버전의 라이브러리가 설치된 곳에서 컴파일한 실행 파일은 낲은 버전의 라이브러리가 설치된 시스템에서는 실행할 수가 없나요?
2. 저의 시스템에서 여러 버전의 라이브러리를 설치해놓고, 컴파일할 때 어느 버전의 라이브러리와 동적으로 링크할 지를 결정할 수 있을 까요?
Re: 동적 라이브러리
혹시 낮은 버전의 리눅스가 ELF 기반이 아닌 a.out 포맷 기반은 아닙니까? ELF와 a.out은 섞어 쓸 수 없습니다.
높은 버전의 라이브러리에 있는 함수가 낮은 버전과 semantics가 동일하다면(리턴값, 인수 타입, 개수 등등), 실행할 수 있습니다.
ld(1)에 -rpath 옵션을 주면 됩니다. 제 매뉴얼 페이지에는 다음과 같이 나와 있군요:
예를 들어 /usr/lib에 라이브러리 새 버전이, /usr/old/lib에 구 버전이 들어 있다면, 링크할 때 -rpath /usr/old/lib라고 지정해주면, 링커가 ELF 바이너리 안에 있는 DYNAMIC 섹션의 RPATH 필드에다 /usr/old/lib을 기록해 넣습니다. 그러면 나중에 동적 링커가 라이브러리를 로드할 때 이 정보를 참조하게 되죠. 그리고 이 값은 나중에 LD_LIBRARY_PATH 환경 변수를 통해 override가 가능합니다(별로 권장하는 방법은 아닙니다만).
한가지더, ld(1) 말고 gcc(1)에다 옵션을 줄 때에는 -Wl,-rpath,/usr/old/lib처럼 준다는 점을 잊지 마시길...:D
[quote]그리고 이 값은 나중에 LD_LIBRARY_PATH 환경 변
리눅스 glibc 2.2 에서 테스트를 해보니, 언제나 override 되는것이 아니고 rpath 에 해당하는 라이브러리가 없는 경우에만 LD_LIBRARY_PATH 를 찾는것 같습니다.
참고로 man ld 의 -rpath, -rpath-link 부분을 참고해보면 로딩될때 공유라이브러리를 찾는 순서를 알 수 있습니다.
[quote="mushim"]리눅스 glibc 2.2 에서 테스트를 해보
으악, mushim님 말씀이 맞았습니다. ELF 바이너리내에 있는 DT_RPATH 필드를 먼저 찾아보고 없으면 LD_LIBRARY_PATH를 찾는군요(그러니 제가 override한다고 쓴 것도 어폐가 있었습니다). 지적에 감사드립니다. :D
댓글 달기