OS/AIX::

AIX 동적 라이브러리 컴파일 방법 (dynamic, *.so) - 3

장피디 2014. 1. 10. 15:59
반응형


런타임 링킹을 사용하려면, 주 프로그램과 링크하기 이전에 이미 런타임 링킹 공유 오브젝트를 만들어 놓아야 한다. 런타임 링킹 공유 오브젝트를 만들려면 다음과 같다.


1. 소스 파일을 컴파일 한 다음 오브젝트 파일을 만든다.

2. -G 링커 옵션을 사용하여 오브젝트 파일을 다시 링크시킨 다음 런타임 링킹 공유 오브젝트 (.so)를 만든다.

(여러 오브젝트 파일로 한 개의 런타임 링킹 공유 오브젝트를 만들 수 있다.)

3. 런타임 링킹 공유 오브젝트를 라이브러리 아카이브(libname.a)에 넣는다. 이 과정은 필수과정은 아니다.


특정 옵션을 사용한다는 점만 제외하고, 위 과정은 보통의 공유 오브젝트를 만드는 과정과 동일하다.


func1.c, func2.c, func3.c 세 개의 파일로 런타임 링킹 공유 오브젝트를 만들려면 다음과 같이 하면 된다.

$ xlc -c func1.c func2.c func3.c

func1.c:

func2.c:

func3.c:

$ ld -G -o func1.so func1.o -bnoentry -bexpall

$ ld -G -o func2.so func2.o -bnoentry -bexpall -lc

$ ld -G -o func3.so func3.o -bnoentry -bexpall -lc

$ ls *.o *.so

func1.o func1.so func2.o func2.so func3.o func3.so


위 예제에서 사용한 링커 옵션은 다음과 같다.


-bnoentry

결과파일에는 시작위치(entry point)가 없다. 필요한 심볼을 유지하려면 -u 플랙을 사용하거나 반출파일을 사용해야 한다. -r, -bnogc, -bgcbtpass 옵션을 사용하면 오브젝트 파일에 모든 반출 심볼을 유지할 수 있다. -bnoentry 옵션이나 -bnox 옵션 중 어느것도 사용하지 않으면 시작위치(entry point)를 찾지 못하므로 경고메시지가 나온다.


-bexpall

반입심볼, 아카이브 멤버의 참조되지 않은 심볼, _로 시작하는 심볼을 제외하고 모든 전역심볼을 반출한다. 반출파일에 심볼을 명시하면 더 많은 심볼을 반출할 수 있다. 이 옵션은 -bautoexp 옵션으로 반출한 심볼에 영향을 주지 않는다. 이 옵션은 AIX 4.2 이후 버전에서만 적용된다.

이 옵션을 사용하면 반출파일을 따로 사용하지 않아도 된다. 그러나 반출파일을 사용하면 어떤 심볼을 반출할 지에 대해 확실히 지정할 수 있으며, 공유 오브젝트안의 전역심볼을 사용할 때 다른 공유 오브젝트에서 반출된 심볼과 충돌이 일어날 염려를 줄여줄 수 있다. 디폴트는 -bnoexpall 이다.


-lc

참조할 라이브러리를 지정한다. func2.o나 func3.o의 경우 printf()같은 심볼을 해석하려면 표준 C 라이브러리를 지정해야 한다. func1.o의 경우 func3함수를 호출하는 외에는 다른 함수를 호출하지 않기 때문에 라이브러리를 지정하지 않아도 된다.


-G

-G 링커 옵션을 사용하면 아래의 모든 옵션을 지정한 것과 동일하게 된다. 컴파일러 드라이버도 -G 옵션이 있다. 오브젝트 파일로 런타임 링킹 공유 오브젝트를 만들 때 컴파일러의 -G 옵션을 사용하지 마시오.


 옵션

 설명

 -berok

 해석하지 못한 심볼이 있어도 억지로 오브젝트 파일을 생성한다.

 -brtl

 런타임 링킹을 가능하게 한다. 명령행에서 나열한 모든 공유 오브젝트 (아카이브 멤버가 아닌 파일들)는 출력파일에 나열된다. 어플리케이션 프로그램을 시작할 때 시스템 로더는 모든 공유 모듈을 로드하고, 이 공유 오브젝트에서 반출된 심볼은 런타임 링커에서 사용된다.

 -bsymbolic

 특별히 특성을 지정하지 않고 심볼을 반출한 경우 심볼에 특성을 할당한다.

 -bnoautoexp

 런타임 링커 라이브러리에 대한 참조를 제거한다. -G 옵션으로 만든 모듈(-bnortllib 옵션을 포함한다)을 런타임 링킹시 활성화시키지만, 런타임 링커 라이브러리에 대한 참조는 제거된다. 런타임 라이브러리는 주요 실행파일과 링크할 때만 참조되어야 한다.

 -bnoautoexp

 심볼이 자동으로 반출되지 못하도록 한다.

 -bM:SRE

 공유(shared)되면서 다시 사용할 수 있는(reusable) 상태로 모듈을 만든다.



런타임 링킹 공유 오브젝트와 링크시켜서 프로그램을 만들려면 다음 과정을 따라야 한다.

1. main() 함수를 포함하는 소스 프로그램을 컴파일하여 오브젝트 파일을 만든다.

2. -G 링커 옵션으로 오브젝트 파일을 다시 링크시켜서 런타임 링킹 공유 오브젝트 (.so)를 만든다.

3. main 소스 프로그램과 런타임 링킹 공유 오브젝트를 -brtl 링커 옵션을 사용하여 링크한다.


main()이 포함된 소스 프로그램으로 만든 오브젝트 파일이 런타임 링킹 기능이 활성화되어 있지 않다면 다음과 같은 작업을 해줘야 한다.

적절한 컴파일러 드라이버를 사용해서(링커가 아니다) main()을 포함하는 소스 프로그램을 컴파일한 다음 -brtl 옵션을 사용하여 런타임 링킹 공유 오브젝트 파일과 링크시켜야 한다.


예제에서는 좀더 간단한 방법으로 a.out 을 만들었다.

$ ls *.o *.so

func1.o func1.so func2.o func2.so func3.o func3.so

$ xlc main.c func1.so func2.so func3.so -brtl

$ ls a.out

a.out

프로그램을 실행하면 의존하는 모듈인 func1.so를 시스템 로더가 찾을 수 없기 때문에 프로그램은 다음과 같은 에러메시지를 내보내며 수행되지 않는다.


$ ./a.out

exec(): 0509-036 Cannot load program ./a.out because of the following errors:

0509-150 Dependent module func1.so could not be loaded.

0509-022 Cannot load module func1.so.

0509-026 System error: A file or directory in the path name does not exist.


LIBPATH 값이 정의되어 있다면 다음처럼 동작할 것이다.

$ export LIBPATH=$PWD

$ ./a.out

within function func1 at line number: 7 in func1.c

within function func3 at line number: 7 in func3.c


컴파일러 드라이버(xlc)대신 링커 명령(ld)을 사용하면 다음과 같다.

$ xl-c main.c

$ ld main.o func1.so func2.so func3.so -brtl


생성한 실행파일이 필요한 시작(startup) 루틴을 가지고 있지 않기 때문에 다음과 같은 에러를 발생시킨다.

$ export LIBPATH=$PWD

$ ./a.out

exec(): 0509-036 Cannot load program ./a.out because of the following errors:

0509-151 The program does not have an entry point or the o_snentry field in the auxiliary header is invalid.

0509-194 Examine file headers with the 'dump -ohv' command.




반응형