본문 바로가기

ARM/강의

링커 스크립트 분석

/* elf32-littlearm.lds 파일 */

//이 부분은 arm-linux-ld가 만들어 낼 최종 결과 파일의 포맷을 나타낸다.
//즉, little endian 포맷의 파일을 생성할 것인지,
//big endian 포맷의 파일을 생성할 것인지를 결정하는 역할을 한다.
OUTPUT_FORMAT("elf32-littlearm""elf32-littlearm""elf32-littlearm")

//이 부분은 최종 결과 파일이 동작할 CPU의 architecture를 나타낸다.
//즉, 이 파일은 ARM CPU 상에서 동작한다는 의미이다.
OUTPUT_ARCH(arm)

//최종 결과 파일의 시작 지점을 나타낸다.
//즉, 여기서 파일의 시작 지점은 reset_handler가 된다.
//reset_handler는 Cstartup.s 파일에 정의되어 있다.
ENTRY(reset_handler)

//SECTIONS{ ... }부분은 링커(arm-linux-ld)가 입력 파일들의 섹션들을
//결과 파일의 어떤 섹션들로 위치시킬지를 결정하는 역할을 한다.
SECTIONS
{
    .text : {          //프로그램의 코드영역
        _stext = .;      //코드영역의 시작주소를 makefile로 부터 가져온다.
        *(.text)        //모든 입력 파일들(*)의 .text 섹션을 결과 파일의 .text 섹션에 위치시킨다.
        *(.rodata)      //readonly 파일들을 .text 섹션에 위치시킨다.
        *(.rodata*)    //그외 모든 데이터들을 .text 섹션에 위치시킨다.
        . = ALIGN(4);  //현재의 위치에서 4 바이트 단위로 놓겠다는 의미이다.
                                 // 즉, 4바이트 단위로 메모리를 정렬한다.
         _etext = . ;    //코드영역의 끝을 현재 위치포인트로 하겠다는 의미이다.
    }

    //데이터 영역
     //코드영역 시작주소부터 코드영역의 크기만큼 더한다음 주소 즉, 코드영역 다음 주소
    .data : AT ( ADDR (.text) + SIZEOF (.text) ) {  
        _sdata = .;
        *(.vectors)    //모든 입력 파일의 벡터 테이블을 데이터 영역에 포함
        *(.data)       //모든 입력 파일의 초기화 된 데이터를 데이터 영역에 포함
        _edata = .;
    }

     //bss 영역
     //noload = 적재하지 않는다. 
    .bss (NOLOAD) : { 
        . = ALIGN(4);
        _sbss = .;
        *(.bss)         //모든 입력 파일의 bss영역을 출력파일의 bss영역에 포함한다.
        _ebss = .;
    }
}
end = .;

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")

이 부분은 링킹 후 만들어 낼 최종 결과 파일의 포맷을 나타냅니다.

little endian 포맷의 파일을 생성할 것인지, big endian 포맷의 파일을 생성할 것인지를 결정하는 역할을 합니다. OUTPUT_FORMAT 명령어를 세개의 인자를 이용하여 사용한다면, command line option 에 '-EB' 또는 '-EL' 을 사용함으로써 다른 format으로 지정할수 있습니다. 만약 -EB를 사용할 경우 두 번째 항목에 해당하는 포맷의 파일을 생성해 내며(elf32-littlearm), -EL을 사용할 경우 세 번째 항목에 해당하는 파일 포맷을 생성해 낸다(elf32-littlearm). 만약 '-EB' 와 '-EL' 둘다 지정하지 않는다면 디폴트로 첫 번째 항목에 해당하는 파일 포맷을 생성해 낸다(elf32-littlearm). 여기선 어떤 경우이던 elf32-littlearm 포맷의 파일을 생성하게 됩니다.

OUTPUT_ARCH(arm)

최종 결과 파일이 동작 할 CPU의 architecture를 나타냅니다.

즉, 이 파일은 ARM CPU 상에서 동작한다는 의미입니다.

ENTRY(reset_handler)

최종 결과 파일의 시작 지점을 나타냅니다. 여기서 파일의 시작 지점은 reset_handler가 됩니다. reset_handler는 cstartup.S 파일에 정의되어 있습니다.

다음과 같은 방법으로 엔트리를 설정한다.

옵션에 '-e' 사용하기.

linker script 에 ENTRY(symbol) 명령어 사용하기.

(정의되어있다면) symbol start 값.

(정의되어있다면) '.text' section의 첫번째 byte 주소.

'0' 주소값

SECTIONS{…}

결과 파일의 메모리 레이아웃을 설명하기 위해 사용되며 섹션 범위안에 메모리의 범위와 그곳에 놓일 정보들을 설정할 수 있습니다.

.text : {...}

메모리의 text(code) 영역을 설정하는 부분.

_stext = .;

text 영역의 시작 번지를 설정하며 make 파일에서 정의한 text 영역 시작 주소를 참조한 상대주소 (.)로 지정합니다.

*(.text)

모든 파일의 함수를 text 영역에 포함 시킵니다.

*(.rodata)

모든 파일의 읽기 전용 데이터를 text 영역에 포함 시킵니다.

*(.rodata*)

그 외의 읽기 전용 데이터들을 text 영역에 포함 시킵니다.

. = ALIGN(4);

메모리 정렬의 시작 주소 설정 이후로 메모리의 단위를 4바이트 단위로 정렬합니다.

_etext = .;

text 영역의 마지막 번지를 설정하며 위의 작업을 마치고 난 다음의 번지를 참조하여 상대주소 (.)로 지정합니다.

.data : AT ( ADDR (.text) + SIZEOF (.text) ) {...}

메모리의 data 영역을 설정하는 부분.

text 영역의 시작 번지와 text 영역의 크기를 더하여 data 영역의 시작 번지를 지정합니다.

_sdata = .;

data 영역의 시작 번지를 지정하며 make 파일에서 정의한 data 영역 시작 주소를 참조한 상대주소 (.)로 지정합니다.

*(.vectors)

모든 파일의 벡터 테이블을 data 영역에 포함 시킵니다.

*(.data)

모든 파일의 초기화 된 전역 변수를 data 영역에 포함 시킵니다.

_edata = .;

data 영역의 마지막 번지를 설정하며 위의 작업을 마치고 난 다음의 번지를 참조하여 상대주소 (.)로 지정합니다.

.bss (NOLOAD) : {...}

메모리의 bss 영역을 설정하는 부분.

NOLOAD는 적재하지 않는 다는 뜻입니다.

bss 영역은 초기화 되지 않은 전역 변수들의 영역이라 데이터를 저장 할 필요가 없기 때문에

실행 파일에는 초기화 되지 않은 전역 변수들을 bss 영역에 공간을 할당 하라는 명령만 들어가고

런타임 시에 bss 영역에 변수들의 공간을 할당하고 0으로 초기화 시켜줍니다.

. = ALIGN(4);

메모리 정렬의 시작 주소 설정 이후로 메모리의 단위를 4바이트 단위로 정렬합니다.

_sbss = .;

bss 영역의 시작 번지를 지정하며 make 파일에서 정의한 bss 영역 시작 주소를 참조한 상대주소 (.)로 지정합니다.

*(.bss)

모든 파일의 초기화 되지 않은 전역 변수를 bss 영역에 포함 시킵니다.

_ebss = .;

bss 영역의 마지막 번지를 설정하며 위의 작업을 마치고 난 다음의 번지를 참조하여 상대주소 (.)로 지정합니다.

end = .;

'ARM > 강의' 카테고리의 다른 글

LCD + 센서 제어 프로그래밍  (0) 2011.02.25
AT91SAM7S256의 내부 구조  (0) 2011.02.16
A/D 컨버터(ADC)  (0) 2011.02.14
시리얼 통신으로 문자열 출력 함수 만들기!!  (0) 2011.02.14
LED 제어 테스트  (0) 2011.02.09