IT한 것/unix

Position Independent Code

lovian 2009. 1. 23. 14:26
원문: (어디인지 찾는 중..)

동적 실행파일 내에 위치한 코드는 보통 PIC이고, 메모리상에 고정된 주소에 연결되어 있다. 반면에 공유 객체들(Shared Objects)는 다른 프로세스들과 다른 메모리 주소들에 놓여(be loaded)질 수 있다.
PIC는 명확한 주소에 묶여 있지 않다. 이 독립성은 이 코드가 이 코드를 사용하는 각 프로세스의 다른 주소에서 효율적으로 실행할 수 있게 해준다.

컴파일러는 -K pic 옵션을 주어 PIC를 생성할 수 있다.

만일 공유객체가 PIC로 만들어졌다면, 텍스트 세그먼트는 실행시(runtime)에 부분적인 변경을 요구 할 수 있다. 이 변경은 재배치 가능한 참조들(reallocatable references)을 그 객체가 놓여(loaded)질 위치에 설정할 수 있게 한다.
텍스트 세그먼트의 재배치는 쓰기가능한 다시매핑(be remapped)된 세그먼트를 요구한다. 이 작업은 임시공간의 예약, 그 프로세스의 텍스트 세그먼트의 비밀 복사본으로 요청한다(This modification requires a swap space reservation, and results in a private copy of the text segment for the process). 텍스트 세그먼트는 더이상 복수의 프로세스 사이에 공유 할 수 있는 것이 아니다. PIC는 일반적으로 유사한 PIC보다 더 많은 runtime relocations을 요구한다. 전반적으로 텍스트 재배치를 수행하는 부하는 심각한 성능 감소를 야기 할 수 있다.

공유된 객체가 PIC에서 생성되었을때 재배치가능한 참조들은 공유된 객체의 데이터 세그먼트를 통해서 간접적으로 생성된다. 텍스트 세그먼트에 있는 코드는 부분적인 변경을 요구하지 않는다. 모든 재배치 갱신작업은 데이터 세그먼트 내의 일치하는 입구(entries)들에 적용된다. 간접기술명세에 대한 더 자세한 정보는 Global Offset Table (Processor-Specific)과 Procedure Linkage Table(Processor-Specific)을 참조하면 된다.

The runtime linker attempts to handle text relocations should these relocations exist. However, some relocations can not be satisfied at runtime.

x64 PIC 순서는 보통 오로지 메모리의 하위 32-bit 영역에 놓여지는 코드를 생성한다. 어떤 주소의 상위 32비트는 모두 0으로 채워져 있어야한다. 공유된 객체들이 메모리의 상위에 놓여지기 때문에 한개의 주소의 상위 32비트가 요청되어진다. 그러므로 x64 공유 객체의 PIC는 재배치 요구사항을 만족하기에 불충분하다. 공유객체에서 이러한 코드이용은 실행시간 재배치 오류를 발생시킬 수 있다.

$ prof
ld.so.1: prog: fatal: relocation error: R_AMD64_32: file \
     libfoo.so.1: symbol (unknown): value 0xfffffd7fff0cd457 does not fit


PIC는 메모리의 어떤 영역에도 놓여질 수 있기 때문에 x64용 공유객체의 요구사항을 만족시킬 수 있다.

이 상황은 64비트 SPARCV9 코드에서 사용하는 기본 ABS64모드와는 다르다. 이 PIC는 보통 완전한 64비트 주소 영역과 호환된다. 그래서 PIC 순서는 SPARCV9 공유 객체 내에 존재할 수 있다. ABS32나, 64비트 SPARCV9코드를 위한 ABS64 모드를 이용하는 것 역시 실행시간에 찾아내지 못하는 재배치 문제를 발생시킬 수 있다. 그러나 이러한 모드들이 각각 텍스트 세그먼트를 재배치하기 위한 실행시간 linker를 요구한다.

실행시간 linkers의 능력, 또는 재배치 요구사항의 차이점에 개의치 않는 공유된 객체는 PIC를 이용하여 만들어져야한다.

독자는 자신의 텍스트 세그먼트에 대립되는 재배치를 요구하는 공유된 객체를 식별 할 수 있다. 아래의 예제는 TEXTREL entry가 동적으로 존재하는지 아닌지 확인 하기위해 dump(1)를 이용한다.

$ cc -o libfoo.so.1 -G -R. foo.c
$ dump -Lv libfoo.so.1 | grep TEXTREL
[9] TEXTREL 0
Note -
TEXTREL entry의 값은 부적절하다. 공유된 객체에 이 엔트리가 있음은 텍스트 재배치가 존재함을 나타낸다.

-----------------------------------------------------------------------------------------
텍스트 재배치를 가지는 공유된 객체의 생성을 방지하려면 link-editor의 -z text flag를 사용한다. 이 flag는 link-editor에게 입력에 사용된 모든 PIC의 소스의 진단법을 생성하게 한다. 아래의 예제는 PIC가 어떻게 공유된 객체 생성에 실패하는지 보여준다.

$ cc -o libfoo.so.1 -z text -G -R. foo.c
Text relocation remains referenced
against symbol offset in file
foo 0x0 foo.o
bar 0x8 foo.o
ld: fatal: relocations remain against allocatable but \
non-writable sections

두 재배치는 foo.o 파일에서 생성된 PIC가 아닌 대립되는 텍스트 세그먼트로 생성되었다.