2013년 12월 2일 월요일

[번역중] GCC의 linker를 위한 linker command language(ld 파일 명령어) 설명서.

[출처 : https://web.eecs.umich.edu/~prabal/teaching/eecs373-f11/readings/Linker.pdf]

3. Linker Scripts

모든 link(ld라는 오브젝트 파일 합성 프로그램)는 linker script의 의해서 제어된다. 이 스크립트는 linker command language로 쓰여 진다.

linker script의 주된 목적은 어떻게 입력 파일들(컴파일된 모든 오브젝트 파일)의 모든 섹션들을 출력 파일(컴파일 최종 단계의 실행 파일)에 위치 시켜야 하는지 어떻게 출력 파일의 메모리 구성을 설정해야 하는지에 대해서 설명한다. 대부분의 linker script들은 이것 이상의 아무것도 하지 않는다. 그러나, 필요하다면, linker script는 아래에서 설명할 명령어들을 이용해서 많은 다른 동작을 하도록 linker를 지시할 수 있다.

linker는 항상 linker script를 사용한다. 만약 여러분이 직접 이것을 제공하지 않다면, linker는 실행 가능한 linker로써 컴파일되는 기본 스크립트를 사용할 것이다. 여러분은 기본 linker script를 보기 위해서 '--verbos' 명령행 옵션을 사용할 수 있다. '-r'이나 '-N' 같은 어떤 명령행 옵션들은 이 기본 linker script에 영향을 준다.

여러분은 '-T' 명령행 옵션을 이용해서 여러분 자신의 linker script를 사용할 수 도 있다.
여러분이 이것을 사용할 때, 여러분의 linker script는 이 기본 linker script를 대체할 것이다.

여러분은 또한 linker script가 링크될 파일일 지라도 linker의 입력 파일로서 이름 짓음으로써 암시적으로 사용수도 있다. 섹션 3.11[Implicit Linker Scripts], 페이지 74를 보라.

3.1. 기본적인 linker script의 개념

우리는 linker script 언어를 설명하기 위해서 몇 가지 기본 개념과 문법을 정의 할 필요가 있다. 
linker는 여러 개의 입력 파일을 합성해서 하나의 출력 파일로 만든다. 출력파일과 각각의 입력 파일은 object file format으로 알려진 특수한 데이터 포멧으로 되어 있다. 그리고 각 파일은 object 파일이라고 부르고 출력 파일은 executable(실행파일)이라고 부른다. 그러나 우리의 목적에 따라 우리는 출력파일도 object 파일이라고 부르겠다. 각각의 object 파일은 sections 항목을 가지고 있다. 우리는 앞으로 종종 input section이 입력 파일의 section을 의미하는 것으로 사용할 것이다. 이와 유사하게 출력 파일의 section은 output section으로 ...

object 파일의 각 section은 이름과 크기를 갖는다. 대부분의 section 들은 또한 section contents로 알려진 각 section에 관련된 데이타 블럭을 가지고 있다. section은 loadable로 표시되기도 하는데 이것은 출력 파일이 실행될때 이 section의 내용들이 메모리로 적재되어야 한다는 것을 의미한다. 내용물이 없는 section은 동적할당(allocatable) 으로 표시되기도하는데 이것은 메모리의 한 공간이 사용되지 말고 확보되어져 있어야 하고 특별히 그곳에 어떠한 내용이 적재되어 지지않아야 한다는 것을 의미한다. ( 어떠한 경우에는 이러한 메모리 공간은 '0'으로 채워져야 하는 때도 있다.) loadable혹은 allocatable 둘다 아닌 section은 보통 디버깅정보와 같은 종류의 내용들을 포함하고 있다.

모든 loadable 혹은 allocatable 형태의 output section은 두 개의 address들을 가지고 있다. 하나는 VMA 혹은 가상 메모리 주소(virtual memory address)이다. 이것은 출력 파일이 실행 될때 section이 가지게 될 주소이다. 그리고 다른 하나는 LMA 혹은 적재 메모리 주소(load memory address)라는 것이다. 이것은 section이 적재되어야 하는 주소이다. 대부분의 경우 이 두 주소는 동일하다. 이 둘이 다르게 될때의 예는 data section이 ROM 영역에 적재되고 프로그램이 시작될때 RAM 영역으로 복사되는 경우이다. ( 이러한 기법은 ROM 기반의 시스템에서 전역 변수를 초기화 하고자할 때 자주 사용된다.) 이러한 경우 ROM영역의 주소는 LMA가 되고 RAM영역의 주소는 VMA가 될 것이다.

여러분은 '-h' 옵션을 갖는 objdump 프로그램을 사용해서 object 파일의 모든 sections들을 볼 수 있다. 모든 object 파일은 또한 symbol table이라고 알려진 symbol의 리스트를 가지고 있다. symbol은 정의되어 질 수도 있고 아닐 수 도 있다. 각각의 symbol은 이름을 가지고 있고 각각의 정의된 symbol은 주소를 가지고 있다. 여러분이 C나 C++ 코드를 object 파일로 컴파일 한다면, 모든 정의된 함수화 전역혹은 지역 변수에 대한 정의된 symbol을 갖게 될 것이다. 입력 파일에서 참조 되는 모든 정의되지 않은 함수 혹은 전역 변수는 정의되지 않은 symbol이 될 것이다.

여러분은 nm 프로그램이나 '-t' 옵션을 갖는 objdump 프로그램을 사용해서 object 파일의 symbol들을 살펴 볼 수 있다.

3.2. Linker Script Format

linker scripts는 텍스트 파일이다.

여러분은 여러개의 명령어의 조합으로 linker script를 작성한다. 각각의 명령어는 매개변수에의해서 부차적으로 따라붙는 keyword이거나, symbol의 배치중의 하나일 것이다. 여러분은 ';'을 이용해서 명령어를 구분할 수 있다. whitespace(탭, 스페이스, 등등)는 일반적으로 무시된다.

파일이나 format 명과 같은 문자열은 통상 직접적으로 입력 되어 질 수 있다. 만약 파일 이름이 파일 이름들을 구분하는 용도로 사용되는 ','와 같은 특수 문자를 포함하고 있다면, 여러분은 " " 사이에 파일 이름을 집어 넣어야 한다. 파일이름에 "를 사용하지는 않는다.

여러분은 C 언어에서와 같은 '/*', '*/'로 linker script에 주석을 달수도 있다. C에서 처럼 주석은 문법적으로 whitespace와 같다.

3.3. 간단한 linker script 예제

많은 linker script들은 대체적으로 단순하다.

가장 단순한 가능한 linker script는 단 하나의 명령어:'SECTIONS' 를 갖는다. 여러분은 출력 파일의 메모리 배치를 설명하는데 'SECTIONS' 명령어를 사용한다.

'SECTIONS' 명령어는 강력한 명령어이다. 여기서 우리는 이것의 단순한 사용을 설명할 것이다. 여러분의 프로그램이 code와 초기화된 data, 그리고 초기화 되지 않은 data만 가지고 있다고 가정하자. 그럼 순서에 따라 각각 그에 해당하는  '.text', '.data'그리고 '.bss' section 들이 존재하게 될 것이다. 그럼 여러분의 입력 파일에 나타나는 유일한 sections만 있다고 가정 할 수 있다.

이 예제에서 code는 0x10000에 적재되어야하고 data는 0x8000000에서 시작되어야 한다고 말해보자. 여기에 이것을 수행하는 linker script가 있다.

 SECTIONS  
 {  
 . = 0x10000;  
 .text : { *(.text) }  
 . = 0x8000000;  
 .data : { *(.data) }  
 .bss : { *(.bss) }  
 }  

여러분은 'SECTIONS' 키워드와 symbol 배치와 꼬부라진 괄호로 묶여진 출력 section description들의 나열을 사용해서 'SECTIONS' 명령어를 작성하였다.

위의 예제의 'SECTIONS' 명령어 안의 첫번째 줄은 location counter인 '.'의 특수기호의 값을 설정한다. 만약 여러분이 어떤 다른 방법으로(다른 방법은 나중에 설명할 것이다.) 출력 section의 주소를 지정하지 않는다면, 주소는 location counter의 현재 값으로 지정된다. 그럼 location counter는 출력 section의 크기 만큼 증가된다. 'SECTIONS' 명령어가 시작할때 location counter는 '0' 값을 갖는다.

둘째 줄은 '.text'의 출력 section을 정의하고 있다. ':'은 지금은 내용상 무시해도 되지만 요구되는 문법이다. 출력 section 이름 이후에 꼬부라진 괄호를 가지고 여러분은 이 출력 section에 위치해야할 입력 section의 이름을 나열 할 수 있다. '*(.text)'라는 표현은 모든 입력 파일에 있는 모든 '.text' 입력 section들을 의미한다.

출력 section '.text'가 정의된 곳의 location counter가 '0x10000'이기 때문에 linker는 출력 파일에 있는 '.text' section의 주소가 '0x10000'이 되도록 설정할 것이다.

나머지 줄들은 출력파일의 '.data'와 '.bss' section들을 정의한다. linker는 '.data' section을 '0x8000000'에 위치 시킬 것이다. linker가  '.data' 출력 section을 위치시킨후, location counter의 값은 '0x8000000'에 '.data' section의 크기가 더해진 값이 될 것이다. 그 영향으로 linker는 '.bss' 출력 section을 메모리의 '.data' 출력 section 바로 뒤에 위치 시킬 것이다.

linker는 필요에 따라서 location counter를 증가시면서 각각의 출력 section이 잘 짜여진 배치를 갖도록 할 것이다. 이 예제에서 '.text'와 '.data' section들을 위해 특정 지어진 주소는 아마도 어떤 메모리 배치 요구사항을 만족할 것이다. 그러나 linker는 '.data'와 '.bss' section 사이에 작은 여유 공간을 만들게 될지도 모른다.

이것이 바로 간단하고 완벽한 linker script이다!

3.4. 간단한 linker script 명령어들

이번 절에서는 간단한 linker script 명령어들을 설명한다.

3.4.1. entry point 지정하기

프로그램에서 실행되는 첫 번째 코드(instruction)은 entry point라고 불린다. 여러분은 이 entry point를 지정하는데 ENTRY linker script 명령어를 사용할 수 있다. 그리고 그 매개변수는 symbol 이름이 된다:

 ENTRY(symbol)  

entry point를 지정하는 몇 가지 방법들이 존재한다. linker는 순서대로 다음 방법 중 하나를 시도하여 entry point를 지정하고 그들 중 하나가 성공적일 때 멈출 것이다.

 명령행 에서 '-e'옵션을 지정하기;  
 linker script에서 ENTRY(symbol) 명령어로 지정하기;  
 start symbol의 값을 지정해서 지정하기;  
 '.text' section의 첫 번째 바이트의 주소를 지정하기;  
 주소 '0'을 지정하기;  

3.4.2. 파일들을 다루는 명령어들

파일들을 다루는 몇 가지 linker script 명령어들.

INCLUDE filename

linker script 파일이름을 포함시킨다. 파일은 현재 디렉토리에서 검색되어 지거나 '-L' 옵션으로 지정된 어떤 디렉토리에서도 검색되어 질 것이다. 여러분은 10단계의 까지의 INCLUDE 중첩 호출을 할 수 있다.

여러분은 MEMORY나 SECTIONS 명령어 혹은 출력 section description의 가장 상위 레벨에서 INCLUDE 지시어를 위치 시킬 수 있다.

INPUT(file, file, ...)
INPUT(file file ...)

INPUT 명령어는 명령행에서 파일 이름이 지정되는 것 처럼 link 과정에서 이름 지어진 파일들을 포함하도록 linker에게 지시한다.

예를 들자면, 여러분이 link를 수행할때 언제라도 항상 'subr.o'을 포함하고자 하지만, 매번 link 명령행에 이것을 집어 넣는 것을 성가셔 할 수 있다면(?), 여러분은 여러분의 linker script에 'INPUT(subr.o)'을 추가해서도 같은 효과를 볼 수 있다. 사실 여러분만 좋다면, linker script에 입력 파일 모두를 나열할 수 있고 그렇게 해서 '-T' 옵션만 제외하고 다른 옵션은 전혀 사용하지 않고linker의 기능을 수행할 수 있다. 컴파일러의 sysroot 첨두어가 설정되고 파일 이름이 '/' 문자로 시작 된 경우. 처리되는 script는 sysroot 첨두어로 설정된 경로의 내부에 위치해야 하고, 해당 파일들은 sysroot 첨두어에 설정된 경로에서 찾아 지게 될 것이다. 다른 경우에는 linker는 현재 디렉토리에서 파일을 찾을 것이다. 만약 찾을 수 없다면, linker는 archive library 탐색 경로들에서 이것들을 찾을 것이다. 좀 자세한 것은 section 2.1 [명령행의 옵션]의 세번째 페이지에 있는 '-L' 옵션에 대한 설명을 보기 바란다.

만약 여러분이 'INPUT (-lfile)'형태로 사용한다면, ld는 명령행 옵션 '-l'함께 있는 것처럼 이름을 libfile.a의 형태로 변경할 것이다.

여러분이 암시적인 linker script에서 INPUT 명령어를 사용할 때, 파일들은 linker script 파일이 포함되게 되는 지점에 link에 포함되게 될 것이다. 이것들은 archive(라이브러리 파일)를 탐색하는 것에도 영향을 줄 수 있다.

GROUP(file, file, ...)
GROUP(file file ...)

GROUP 명령어는 파일들이 모두 archives 형태를 가져야 하고 그들은 어떤 새로운 정의 되지 않은 참조사항들이 발생되지 않을때까지 반복적으로 탐색되어 진다는 점을 제외하고 INPUT과 유사하다. 자세한 사항은 section 2.1 [명령행 옵션들]의 세번째 페이지에 있는 '-(' 옵션의 설명을 보기 바란다.

AS_NEEDED(file, file, ...)
AS_NEEDED(file file ...)

This construct can appear only inside of the INPUT or GROUP commands, among
other filenames. The files listed will be handled as if they appear directly in the
INPUT or GROUP commands, with the exception of ELF shared libraries, that
will be added only when they are actually needed. This construct essentially
enables ‘--as-needed’ option for all the files listed inside of it and restores
previous ‘--as-needed’ resp. ‘--no-as-needed’ setting afterwards.

댓글 없음:

댓글 쓰기