Go to the first, previous, next, last section, table of contents.


BFD

링커는 BFD 라이브러리들을 사용해서 오브젝트와 아카이브 파일들을 억세스한다. 이런 라이브러리들은 링커가, 오브젝트 파일의 포멧이 무엇이든 오브젝트 파일들에 대한 작업을 할 때 동일한 루틴들을 사용하도록 한다. 다른 오브젝트 파일 포멧은 새로운 BFD 백엔드를 만들어 라이브러리에 추가함으로써 쉽게 지원될 수 있다. 그러나 실시간 메모리를 보호하기 위해서 링커와 관련된 툴들은 보통, 사용가능한 오브젝트 파일 포멧들 중에서 일부 부분집합만을 지원하도록 설정된다. 여러분은 objdump -i (see section `objdump' in The GNU Binary Utilities)를 사용해서 여러분의 설정에 대해서 사용가능한 모든 포멧의 리스트를 볼 수 있다.

대부분의 구현에서와 같이, BFD는 여러 상충하는 요구조건들간의 타협안이다. BFD 설계에 영향을 미친 주요 인자는 효율성이다: 포멧들간 변환에 사용되는 시간은 BFD가 포함되지 않으면 소비되지 않을 시간이다. 이것은 부분적으로 추상화 payback에 의한 격차이다; BFD가 어플리케이션들과 백엔드들을 단순화하기 때문에 좀 더 많은 시간과 조심이 좀 더 높은 속도를 위해서 최적화 알고리즘들을 소비할 수 있다.

기억해야만 할 BFD 솔루션의 한가지 작은 부산물은 정보 손실의 잠재성이다. BFD 메카니즘을 사용할 때 유용한 정보가 손실될 수 있는 위치가 두개 있다: 변환할 때와 출력할 때. See section 정보 유실(Information Loss).

작동 방법: BFD의 개관(How it works: an outline of BFD)

오브젝트 파일이 하나 오픈되면 BFD 서브루틴들이 자동으로 이 입력 오브젝트 파일의 포멧을 결정한다. 그리고 나서 오브젝트 파일의 데이터 구조체들의 요소들을 억세스하는 데 사용될 루틴들에 대한 포인터들로 디스크립터를 메모리에 빌드한다.

오브젝트 파일들로부터 다른 정보가 필요할 때 BFD 는 그 파일의 다른 섹션들을 읽어들이고 이들을 처리한다. 예를 들어서 링커의 아주 일반적인 작업은 심벌 테이블들을 처리하는 것이다. 각 BFD 백엔드는 심벌들에 대한 오브젝트 파일의 표현과 내부 규준(cannoical) 포멧 간 변환을 위한 루틴을 제공한다. 링커가 오브젝트 파일의 심벌 테이블을 요구할 때 관련 BFD 백엔드에 있는 루틴에 대한 메모리 포인터를 통해서 요청한다. 이 루틴은 테이블을 읽고 규준 형태로 변환하는 것이다. 변환이 되면 링커는 이 규준 형태위에서 작업한다. 링크가 끝나고 링커가 결과 파일의 심벌 테이블을 작성할 때 다른 BFD 백엔드 루틴이 새로 생성된 심벌 테이블을 취해서 이것을 선택된 출력 포멧으로 변환하기 위해서 호출된다.

정보 유실(Information Loss)

정보들이 출력시 유실될 수 있다. BFD 에 의해서 지원되는 출력 포멧들은 동일한 기능들을 제공하지 않으며 한가지 형태로 기술될 수 있는 정보는 다른 포멧에서는 갈 데가 없다. 이런 것의 한가지 예는 b.out 의 정렬 정보(alignment information) 이다. a.out 포멧 파일에는 포함된 데이터에다 그런 정렬 정보를 저장할 곳이 없다. 그래서 어떤 파일이 b.out 로부터 링크되어 a.out 이미지가 생성된다면 결과 파일에 정렬 정보가 전달되지 않을 것이다. (링커는 그러나 정렬 정보를 내부적으로 사용할 것이다. 그래서 그 링크는 정확하게 실행된다).

다른 예제는 COFF 포멧의 섹션 이름(section names)이다. COFF 파일들은 무제한으로 섹션들을 가질 수 있고 이들 각각은 텍스트 섹션 이름을 가질 수 있다. 링크의 타겟이 섹션들을 많이 가질 수 없는 포멧이라면(예, a.out) 또는 이름을 갖지 않는 섹션을 가지는 포멧이라면(예, Oasys 포멧), 링크는 단순하게 수행될 수 없다. 이런 문제를, 원하는 입력-to-출력 섹션 맵핑을 링커 명령 언어로 기술함으로써 돌아갈 수 있다.

규준화(canonicalization) 도중에 정보가 유실될 수 있다. 외부 포멧에 대한 BFD 내부 규준 형태는 완전한(exhaustive) 것이 아니다; 내부적으로 직접적인 표현법이 없는 것에 대한 구조체들이 입력 포멧들 중에 있다. 이것은 BFD 백엔드들이 외부에서 내부로 변환하고 다시 거꾸로 외부 포멧으로 변환하는 것을 통해서 모든 가능한 데이터를 유지할 수 없다는 것을 의미한다.

이런 제한은 어떤 어플리케이션이 한 포멧을 읽고 다른 포멧으로 쓸 때만 문제이다. 각 BFD 백엔드는 가능한 한 많은 데이터를 관리하는 책임이 있고 내부 BFD 규준형은 BFD 코어에 불투명한 구조체들을 가지며 백엔드에만 익스포트된다. 어떤 파일이 한 포멧으로 읽히면 BFD 와 어플리케이션을 위한 규준형이 생성된다. 동시에 백엔드는 그렇지 않으면 유실될 수 있는 정보들을 따로 저장한다. 그리고 나서 데이터가 다시 동일한 포멧으로 쓰여지게 된다면 백엔드 루틴은 BFD 코어에 의해서 제공된 규준형과 이것이 더 이전에 준비한 정보를 같이 사용할 수 있을 것이다. 다음 백엔드들간에 상당히 많은 공통점들이 있기 때문에 빅-엔디안 COFF 에서 리틀-엔디안 COFF 으로, 또는 a.out 에서 b.out 으로 링크하거나 복사할 때 유실되는 정보가 없다. 혼재된 포멧들이 링크될 때 목적물과 다른 포멧을 가진 파일들로부터만 정보가 유실된다.

BFD 규준 오브젝트-파일 포멧(The BFD canonical object-file format)

정보 유실의 가능성이 가장 큰 것은 규준 포멧으로 저장된 소스 포멧으로 제공된 정보와 목적 포멧에 의해서 필요한 정보 간의 동일한 부분이 가장 적을 때이다. 규준 폼에 대한 간략한 설명은 어떤 종류의 데이터들이 변환 과정을 거친후 보존되는 것으로 기대할 수 있는가를 알아낼 때 도움을 줄 수 있다.

파일(files)
타겟 머쉰 아키텍쳐, 특별한 구현 포멧 타입, 요구 페이징 가능 비트(demand pageable bit), 그리고 기록 보호 비트(write protected bit) 를 포함하는 파일별 기반으로 저장된 정보. 유닉스 매직 넘버와 유사한 정보는 여기에 저장되지 않는다---매직 넘버들의 의미, 그래서 ZMAGIC 파일은 요구 페이징 가능 비트와 기록 보호 텍스트 비트 집합 둘다 가지게 될 것이다. 타겟의 바이트 순서는 파일별 기반으로 저장되기 때문에 빅-엔디안과 리틀-엔디안 오브젝트 파일들은 개별적으로 저장될 수 있다.
섹션(sections)
입력 파일의 각 섹션은 섹션의 이름, 오브젝트 파일안의 섹션의 오리지널 주소, 크기 및 정렬 정보, 다양한 플래그들, 그리고 다른 BFD 데이터 구조들안으로의 포인터들을 포함한다.
심벌(symbols)
각 심벌은 원래 이것을 정의한 오브젝트 파일에 대한 정보, 이것의 이름, 이것의 값, 그리고 여러 플래그 비트들에 대한 포인터를 담고 있다. BFD 백-엔드가 심벌 테이블을 읽을 때 모든 심벌들이 정의된 섹션의 베이스에 상대적으로 만들기 위해서 이들을 재할당한다. 이렇게 하는 것은 각 심벌이 담겨진 섹션에 포인팅하도록 하는 것이다. 각 심벌은 또한 BFD 백-엔드를 위한 다양한 양의 숨겨진 사적인 데이터를 또한 가진다. 이 심벌이 오리지널 파일에 대해서 포인팅하기 때문에 그 심벌에 대한 사적인 데이터 포멧은 억세스 가능하다. ld는 아무 문제 없이 아주 다른 포멧들의 심벌들 모음위에서 작동할 수 있다. 일반적인 글로벌 및 단순한 로컬 심벌들은 출력할 때 관리된다. 그래서 출력 파일은(이것의 포멧에 상관없이) 함수와 글로벌, 정적, 그리고 공용 변수들에 대한 심벌 포인팅을 간직할 것이다. 어떤 심벌 정보는 간직할 필요가 없다; a.out에서 타입 정보는 심벌 이름들과 마찬가지로 심벌 테이블안에 저장된다. 이 정보는 대부분의 COFF 디버거들에 대해서 의미가 없다; 링커는 사용자들이 이것을 버리도록 하는 명령행 옵션들을 갖는다. 심벌안에는 타입 정보를 표현한 한 단어가 있기 때문에 포멧이 심벌안에 있는 심벌 타입 정보를 지원한다면(예를 들어서 COFF, IEEE, Oasys) 그리고 그 타입이 한 단어안에 넣어질만큼 충분히 단순하다면(집합 표현을 제외한 거의 모든 것) 그 정보는 보존될 것이다.
재배치 레벨(relocation level)
각 규준 BFD 재배치 레코드(relocation record)는 재배치될 타입 기술자(type descriptor)에 대한 포인터, 재배치할 데이터의 오프셋, 데이터가 들어갈 섹션, 그리고 재배치할 심벌에 대한 포인터를 담고 있다. 재배치는 재배치 타입 기술자를 통해서 메시지들을 보냄으로써 수행된다. 그러므로 재배치들은 입력 포멧들중의 하나에서만 사용가능한 재배치 메소드를 사용한 출력 데이터에서 수행될 수 있다. 예를 들어서 Oasys는 바이트 재배치 포멧을 제공한다. 이런 재배치 타입을 요구하는 재배치 레코드는 이것을 수행하는 루틴에 간접적으로 포인트할 것이기 때문에 재배치는 68k COFF 파일에 기록되는 한 바이트 위에서 수행될 수 있다. 비록 68k COFF가 그런 재배치 타입을 가지지 않는다 하더라도 말이다.
라인 번호들(line numbers)
오브젝트 포멧들은, 디버깅 목적들을 위해서, 심벌들, 소스 라인 넘버들, 그리고 출력 파일의 주소들 간의 어떤 맵핑 형태를 가질 수 있다. 이런 주소들은 심벌 정보들에 따라서 재배치되어져야 한다. 관련된 라인 번호 레코들을 가지는 각 심벌은 리스트의 첫번째 레코드를 포인트한다. 라인 번호 리스트의 헤드는 그 심벌에 대한 포인터로 이루어진다. 이것은 라인 번호가 기술되고 있는 함수의 주소를 찾는 것을 가능하게 한다. 이 리스트의 나머지는 다음과 같은 페어(쌍)들로 이루어진다: 섹션안의 오프셋과 라인 넘버들. 이 정보를 단순하게 유도할 수 있는 임의의 포멧은 포멧들간에 성공적으로 이것을 전달할 수 있다(COFF, IEEE 그리고 Oasys).


Go to the first, previous, next, last section, table of contents.