목차
1. 시작하는 말
1.1. ELF 와 a.out
2. 필요한 것을 어디에서 얻을 수 있는가?
3. GCC 설치와 설정
4. 포팅과 컴파일링
4.1. 자동적으로 정의되는 심볼들
4.2. 컴파일러 부르기
4.3. 포팅(Portability)
5. 디버깅 & Profiling
6. 링크
7. 동적 로딩(Dynamic Loading)
1.1. ELF 와 a.out
2. 필요한 것을 어디에서 얻을 수 있는가?
3. GCC 설치와 설정
4. 포팅과 컴파일링
4.1. 자동적으로 정의되는 심볼들
4.2. 컴파일러 부르기
4.3. 포팅(Portability)
5. 디버깅 & Profiling
6. 링크
7. 동적 로딩(Dynamic Loading)
본문내용
버전과 호환되도록 고려하면서 말이다.
- ld: output file needs shared library libc.so.4
이러한 문구는 보통 libc 가 아닌 라이브러리들( 즉, X 윈도우 라이브러리들... )
하고 링크하려고 할 때 발생한다. -static 을 함께 사용하지 않고 링크 시에 -g 옵
션을 주었을 때이다.
공유 라이브러리에 대한 .sa 화일은 보통 정의되지 않은 _NEEDS_SHRLIB_libc_4
라는 심볼을 가지고 있는데 나중에 libc.sa 에서 해결된다. 하지만 -g 옵션을 주게
되면 libg.a 또는 libc.a 와 링크되게 되므로 그 심볼은 해결이 되지 않게 되고 위
와 같은 에러 메세지가 뜨게 되는 것이다.
결론적으로 -g 플래그로 컴파일할 때는 -static 이라는 옵션을 함께 주기 바란
다. 또는 -g 로 컴파일하지 않으면 된다. 링크할 것 없이 원하는 부분만 -g 옵션을
주고 컴파일해도 충분한 디버깅 정보를 얻을 수 있다.
7. 동적 로딩(Dynamic Loading)
이번 섹션은 지금 현재로선 아주 적은 내용만을 가지고 있다. ELF 하우투 문서을
발췌함으로써 그 내용이 계속적으로 늘어나게 될 것이다.
7.1 개념 잡기
리눅스는 공유 라이브러리를 가지고 있다. 이 글 전체를 읽는 동안 이제는 이런
말 듣는 것도 질렸을 것이다. 전통적으로 프로그램 링크 과정에서 행한 작업은
로딩 과정에서 그 반대 과정을 거쳐야 한다.
7.2 에러 메세지
- can't load library: /lib/libxxx.so, Incompatible version
a.out 에서만 일어나는데, 이 말은 여러분의 라이브러리 메이저 버전이 틀리다는
말이다. 다른 버전을 가지고 있다고 해서 눈가림식으로 심볼릭 링크하는 것으로 안
된다. 된다 할지라도 결국엔 세그폴트를 일으킬 것이다. 새로운 버전을 가져오라.
ELF에서도 비스한 메세지가 나온다.
ftp: can't load library 'libreadline.so.2'
- warning using incompatible library version xxx
a.out의 경우이다. 프로그램 컴파일한 사람보다 낮은 마이너 버전의 라이브러리를
갖고 있기 때문에 발생하는 경고 메세지이다. 프로그램이 실행되기는 할 것이다.
업그레이드하는 것이 어떨까?
7.3 동적 로더의 작동 제어하기
많은 환경 변수들이 동적 로더에 관계한다. 대부분은 일반 사용자보다는 ldd 에게
유용하다. ldd 에 다양한 스위치를 줌으로써 쉽게 세팅할 수 있다.
● LD_BIND_NOW
일반적으로 함수가 호출되기 전까지는 라이브러리에서 찾아보지 않는다. 이 플래
그를 세팅해주면 라이브러리 적재시에 모든 체크를 하게 되고 시작은 상당히 느
리게 된다. 이것은 여러분이 만든 프로그램이 모든 것들과 제대로 링크가 되었는
지 시험해볼 때 유용하다.
● LD_PRELOAD
overriding 함수 정의를 가지고 있는 화일에 세팅될 수 있다. 예를 들어서 메모리
할당 방법을 테스팅하려고 하며, malloc 를 교체하려고 할 때는 여러분이 원하는
루틴으로 만든 후에 교체할 수가 있다. malloc.o 라는 이름으로 컴파일한 후 다음과
같이 해보자.
$ LD_PRELOAD=malloc.o; export LD_PRELOAD
$ some_test_program
LD_ELF_PRELOAD 와 LD_AOUT_PRELOAD 이 둘은 비슷하다. 하지만 각각 특정 형태에
만 관계한다. 만약 LD_ELF_PRELOAD와 LD_PRELOAD 가 둘 다 사용되었다면 좀 더 자
세히 지정한 전자 LD_ELF_PRELOAD가 사용된다.
● LD_LIBRARY_PATH
이것은 공유 라이브러리를 찾을 때 참고할 디렉토리를 콜론(:)을 분리자로 써서
표현한 리스트이다. 그것은 ld 에 영향을 주지는 못한다. 단지 실행시에만 관계한
다. 또한 setuid나 setgid 를 갖는 프로그램에 대해서는 무용지물이다. 마찬가지
로 LD_ELF_LIBRARY_PATH 와 LD_AOUT_LIBRARY_PATH 는 각각의 바이너리 형식에만
적용되도록 하고 있다. LD_LIBRARY_PATH는 정상적인 경우 그렇게 필요하진 않다.
대신에 /etc/ld.so.conf/ 에 디렉토리를 추가하고 ldconfig 를 다시 한 번 실행
시키는게 좋다.
● LD_NOWARN
이는 a.out 에만 적용된다. 예를 들어 다음과 같이 세팅하면 LD_NOWARN=true;
export LD_NOWARN) 마이너 버전이 다르다든지 하는, 크게 심각하지 않는 경고
를 표시하지 않도록 한다.
● LD_WARN
이는 ELF 에만 해당된다. 세팅되면 일반적으로 ``Can't find library''와 같은
심각한 에러를 경고로 바꾸어준다. 별로 필요없는 옵션이다.
● LD_TRACE_LOADED_OBJECTS
ELF 에만 적용된다. 프로그램으로 하여금 ldd 하에서 실행되고 있다고 생각하게
끔 만든다.
$ LD_TRACE_LOADED_OBJECTS=true /usr/bin/lynx
libncurses.so.1 => /usr/lib/libncurses.so.1.9.6
libc.so.5 => /lib/libc.so.5.2.18
7.4. 동적 로딩을 사용하는 프로그램 만들기
이는 솔라리스 2.x의 동적 로딩 지원이 이뤄지즌 방식과 매우 흡사하다. H J Lu
의 ELF 프로그래밍 문서에 자세히 나와 있으며 dlopen(3) 맨페이지에 아주 잘 나와
있다. 맨페이지는 ld.so 패키지에 들어있다. 다음 프로그램을 -ldl 옵션을 주고
링크하라.
#include
#include
main()
{
void *libc;
void (*printf_call)();
if(libc=dlopen("/lib/libc.so.5",RTLD_LAZY))
{
printf_call=dlsym(libc,"printf");
(*printf_call)("hello, world\n");
}
}
8. 개발자와 연락하기
9. 나머지
이후는 생략합니다. 조만간 완전한 버전의 번역문을 올리겠습니다.
- ld: output file needs shared library libc.so.4
이러한 문구는 보통 libc 가 아닌 라이브러리들( 즉, X 윈도우 라이브러리들... )
하고 링크하려고 할 때 발생한다. -static 을 함께 사용하지 않고 링크 시에 -g 옵
션을 주었을 때이다.
공유 라이브러리에 대한 .sa 화일은 보통 정의되지 않은 _NEEDS_SHRLIB_libc_4
라는 심볼을 가지고 있는데 나중에 libc.sa 에서 해결된다. 하지만 -g 옵션을 주게
되면 libg.a 또는 libc.a 와 링크되게 되므로 그 심볼은 해결이 되지 않게 되고 위
와 같은 에러 메세지가 뜨게 되는 것이다.
결론적으로 -g 플래그로 컴파일할 때는 -static 이라는 옵션을 함께 주기 바란
다. 또는 -g 로 컴파일하지 않으면 된다. 링크할 것 없이 원하는 부분만 -g 옵션을
주고 컴파일해도 충분한 디버깅 정보를 얻을 수 있다.
7. 동적 로딩(Dynamic Loading)
이번 섹션은 지금 현재로선 아주 적은 내용만을 가지고 있다. ELF 하우투 문서을
발췌함으로써 그 내용이 계속적으로 늘어나게 될 것이다.
7.1 개념 잡기
리눅스는 공유 라이브러리를 가지고 있다. 이 글 전체를 읽는 동안 이제는 이런
말 듣는 것도 질렸을 것이다. 전통적으로 프로그램 링크 과정에서 행한 작업은
로딩 과정에서 그 반대 과정을 거쳐야 한다.
7.2 에러 메세지
- can't load library: /lib/libxxx.so, Incompatible version
a.out 에서만 일어나는데, 이 말은 여러분의 라이브러리 메이저 버전이 틀리다는
말이다. 다른 버전을 가지고 있다고 해서 눈가림식으로 심볼릭 링크하는 것으로 안
된다. 된다 할지라도 결국엔 세그폴트를 일으킬 것이다. 새로운 버전을 가져오라.
ELF에서도 비스한 메세지가 나온다.
ftp: can't load library 'libreadline.so.2'
- warning using incompatible library version xxx
a.out의 경우이다. 프로그램 컴파일한 사람보다 낮은 마이너 버전의 라이브러리를
갖고 있기 때문에 발생하는 경고 메세지이다. 프로그램이 실행되기는 할 것이다.
업그레이드하는 것이 어떨까?
7.3 동적 로더의 작동 제어하기
많은 환경 변수들이 동적 로더에 관계한다. 대부분은 일반 사용자보다는 ldd 에게
유용하다. ldd 에 다양한 스위치를 줌으로써 쉽게 세팅할 수 있다.
● LD_BIND_NOW
일반적으로 함수가 호출되기 전까지는 라이브러리에서 찾아보지 않는다. 이 플래
그를 세팅해주면 라이브러리 적재시에 모든 체크를 하게 되고 시작은 상당히 느
리게 된다. 이것은 여러분이 만든 프로그램이 모든 것들과 제대로 링크가 되었는
지 시험해볼 때 유용하다.
● LD_PRELOAD
overriding 함수 정의를 가지고 있는 화일에 세팅될 수 있다. 예를 들어서 메모리
할당 방법을 테스팅하려고 하며, malloc 를 교체하려고 할 때는 여러분이 원하는
루틴으로 만든 후에 교체할 수가 있다. malloc.o 라는 이름으로 컴파일한 후 다음과
같이 해보자.
$ LD_PRELOAD=malloc.o; export LD_PRELOAD
$ some_test_program
LD_ELF_PRELOAD 와 LD_AOUT_PRELOAD 이 둘은 비슷하다. 하지만 각각 특정 형태에
만 관계한다. 만약 LD_ELF_PRELOAD와 LD_PRELOAD 가 둘 다 사용되었다면 좀 더 자
세히 지정한 전자 LD_ELF_PRELOAD가 사용된다.
● LD_LIBRARY_PATH
이것은 공유 라이브러리를 찾을 때 참고할 디렉토리를 콜론(:)을 분리자로 써서
표현한 리스트이다. 그것은 ld 에 영향을 주지는 못한다. 단지 실행시에만 관계한
다. 또한 setuid나 setgid 를 갖는 프로그램에 대해서는 무용지물이다. 마찬가지
로 LD_ELF_LIBRARY_PATH 와 LD_AOUT_LIBRARY_PATH 는 각각의 바이너리 형식에만
적용되도록 하고 있다. LD_LIBRARY_PATH는 정상적인 경우 그렇게 필요하진 않다.
대신에 /etc/ld.so.conf/ 에 디렉토리를 추가하고 ldconfig 를 다시 한 번 실행
시키는게 좋다.
● LD_NOWARN
이는 a.out 에만 적용된다. 예를 들어 다음과 같이 세팅하면 LD_NOWARN=true;
export LD_NOWARN) 마이너 버전이 다르다든지 하는, 크게 심각하지 않는 경고
를 표시하지 않도록 한다.
● LD_WARN
이는 ELF 에만 해당된다. 세팅되면 일반적으로 ``Can't find library''와 같은
심각한 에러를 경고로 바꾸어준다. 별로 필요없는 옵션이다.
● LD_TRACE_LOADED_OBJECTS
ELF 에만 적용된다. 프로그램으로 하여금 ldd 하에서 실행되고 있다고 생각하게
끔 만든다.
$ LD_TRACE_LOADED_OBJECTS=true /usr/bin/lynx
libncurses.so.1 => /usr/lib/libncurses.so.1.9.6
libc.so.5 => /lib/libc.so.5.2.18
7.4. 동적 로딩을 사용하는 프로그램 만들기
이는 솔라리스 2.x의 동적 로딩 지원이 이뤄지즌 방식과 매우 흡사하다. H J Lu
의 ELF 프로그래밍 문서에 자세히 나와 있으며 dlopen(3) 맨페이지에 아주 잘 나와
있다. 맨페이지는 ld.so 패키지에 들어있다. 다음 프로그램을 -ldl 옵션을 주고
링크하라.
#include
#include
main()
{
void *libc;
void (*printf_call)();
if(libc=dlopen("/lib/libc.so.5",RTLD_LAZY))
{
printf_call=dlsym(libc,"printf");
(*printf_call)("hello, world\n");
}
}
8. 개발자와 연락하기
9. 나머지
이후는 생략합니다. 조만간 완전한 버전의 번역문을 올리겠습니다.