♧ 통상 GNU/리눅스의 공유 라이브러리를 만들 때는
각각의 .C 파일을 PIC(Position Independent Code)가 되도록 컴파일 한다.
그러나 실은 PIC로 컴파일 하지 안아도 공유 라이브러리는 만들 수 있다.
그러면 굳이 PIC로 컴파일 하는 이유가 있는 것일까?
▶ fpic.c 작성
#include <stdio.h>
void func() {
printf("");
printf("");
printf("");
}
☞ PIC로 컴파일하기 위해 gcc -fpic 또는 fPIC 옵션을 지정한다.
-fpic :: 좀더 고속으로 코드를 생성할 가능성이 있지만,
CPU에 따라 -fpic로 생성할 수 있는 GOT(Glocal Offset Table)의 크기에 제한이 있다.
-fPIC :: CPU에 관계없이 사용할 수 있다. 여기서는 -fPIC를 사용한다.
(※ x86에서는 -fpic와 -fPIC가 동일)
% gcc -o fpic-no-pic.s -S fpic.c
% gcc -fPIC -o fpic-pic.s -S fpic.c
위와 같이 생성된 어셈블리어의 소스코드를 보면 PIC 버전은 printf를
PLT(Procedure Linkage Table)를 경유해서 호출하는 것을 알 수 있다.
(※ 우분투 7.04에서 테스트)
다음에는 공유 라이브러리를 만든다.
% gcc -shared -o fpic-no-pic.so fpic.c
% gcc -shared -fPIC -o fpic-pic.so fpic.c
▷ 위 공유 라이브러리의 동적 섹션(dynamic section)을 readelf 명령으로 보면,
비 PIC공유 라이브러리에서는 TEXTREL 이라는 엔트리가 있고 (텍스트 내의 재배치 필요),
RELCOUNT(재배치 수)가 5로, PIC 공유 라이브러리보다 3만큼 크다.
그 이유는 printf()를 3회 호출하기 때문이다.
▷ PIC 공유 라이브러리에서의 RELCOUNT가 0이 아닌 이유는 gcc가 기본적으로 사용하는
시작 파일에 포함된 코드 때문이다. gcc에 -nostartfiles 옵션을 지정하면 이 값은 0이 된다.