티스토리 뷰

2018/4/1


링커가 하는 가장 중요한 일 중 하나인 Relocation


왼쪽 .o 파일이 다른 .o파일들과 합쳐져서 오른쪽 그림의 수행파일을 만드는 과정을 보여주는 그림이다.


char c1 = 'c';

char *p=&c1;

 

main {

f(c1);

}


이런 코드가 어셈블리어로 바꼈을때 왼쪽 .o 파일처럼 나오게 된다. 그런데 링커가 .o파일들을 합치고 나면 오른쪽 그림처럼 변수(c)의 주소나 코드상의 주소(load R1, (100))를 바꿔주어야 한다. 이것이 링커가 하는 가장 중요한 역할중 하나인 Relocation(재배치)이다.


수행파일로 합쳐지기전 .o파일은 char 'c'를 담은 변수인 c1의 주소가 100번지이다. 또한, c1의 주소를 포인터변수 p에 담고 있고, p는 200번지에 할당 되어 있다. 200번지를 참조하면 c1의 주소(100)가 들어 있는데, 이 100이라는 값을 주소 상수라고 한다.


주소 상수 : 말그대로 주소값 그자체인데, 변하지 않는 상수라는 뜻.


위의 방법은 base register를 사용한 Relocation 방법이다. 다시말해서 R5라는 레지스터에 합쳐지고 난 뒤에 .O파일의 시작 주소를 넣어 놓고 합쳐지기 전 .o파일에 있던 주소에 R5의 값을 더해서 코드 및 데이터를 재배치 하는 방식이다.

하지만, 이 방법을 사용하게 됬을때 주소 상수 값은 여전히 재배치가 필요하나 이것은 링커가 해주지 못한다.


쉽게 말하면, 주소상수값은 p가 갖고 있는 주소값을 의미하는데, 원래 합쳐지기전 .o파일에서 이 주소값은 100번지를 의미했다. 하지만 합쳐지고 나서 이 .o파일이 200번지 부터 시작하므로 사실상 100번지->300번지로 주소 상수 값을 수정해 주어야 하지만, 이것을 자동으로 링커가 해주지 못한다는 뜻.


------------------------------------------------------------------------------------------


오브젝트 파일에는 3가지 종류가 있다.

1. Relocatable Object File - 그냥 컴파일의 결과로 생성되는 일반적인 .o파일이다.

2. Executable Object File - .o파일을 합쳐서 수행파일을 만든다고 했었다. 이 수행파일도 결국엔 오브젝트 파일이다.

3. Shared Object File - DLL에서 사용하는 오브젝트 파일이다. .so의 확장자 명을 갖는다.


이 3개의 오브젝트 파일은 ELF포맷을 사용한다. 

ELF -Executable and Linkable File Format의 약자이다. 

다시 말해서 오브젝트 파일들은 아래 그림처럼 구성되어 있다는 뜻이다. 



.text section - 코드가 들어간다.

.data section - 초기화된 전역 변수가 들어간다. int x = 10;

.bss section - better save space의 약자로, 초기화 되지 않은 전역 변수가 들어간다. 


만약 int x;로 전역변수를 선언하면 4바이트의 공간을 할당할것이라는 정보만 갖고 있다가 나중에 수행파일이 되어서 메모리에 올라가 이 프로그램이 가상주소공간을 갖게 되면 그때 실제로 메모리 공간을 차지하게 된다.

c언어에서 int x;와 같이 전역변수를 선언하면 x에 아무것도 넣어주지 않아도 0으로 초기화 되는것이 이 x가 .bss영역에 할당되기 때문이다.


링커정리1 포스팅에 보면 오브젝트 파일에 심볼테이블이 저장되어 있다고 했었다. 위에 보면 .symtab section이 존재한다.

이곳에 Relocation해야 할 코드들의 정보가 들어가 있다.


.rel. txt section에는 재배치 되어야할 코드의 위치 정보가 들어가있고,

.rel. data section에는 재배치 되어야 할 변수의 위치 정보가 들어가 있다.



------------------------------------------------------------------------------------------


링커가 참조하는 심볼은 3가지 종류가 존재 한다.

1. Global Symbol
흔히 말하는 전역변수를 의미한다. A라는 파일에 저장된 전역변수 INT A;가 B라는 파일에서 참조 될 수 있다.

2. External Symbol
마찬 가지로 전역변수이지만, 그 파일에서 선언된 변수가 아니라, 다른 파일에 선언된 전역변수를 현재 파일에서 참조하겠다는 뜻이다.
예를들어 printf 라는것이 컴파일되어 libc.o 라는 오브젝트 파일 안에 존재한다. 우리가 따로 선언하지 않아도 링커가 자동적으로 libc.o를 포함해서 수행파일을 만들어 주기 때문에 우리가 printf,scanf와 같은 함수를 그냥 바로 사용할수 있는것이다. 이런 것들은 그 파일에서 선언된 함수가 아니다. 외부에서 선언된 심볼이다. 이런것들을 External Symbol이라고 한다.
한마디로, 외부에서 선언된 전역함수 또는 전역변수정도?

3. Local Symbol
우리가 흔히 말하는 함수 내에서 선언된 지역변수를 의미하지 않는다. 로컬 심볼이라는것은 쉽게 말해서 static 변수이다.
static 변수는 라이프 사이클이 프로그램의 실행과 종료와 똑같다. 하지만 scope는 함수내부이다. 

------------------------------------------------------------------------------------------




main.c의 입장에서 sum이라는 함수는 extern symbol이다. array는 global symbol이다. 
main 함수 내에 선언된 val이라는 지역 변수(로컬 심볼이 아닌, 스택심볼이라고 한다)는 링커가 Relocation할때 전혀 신경 쓰지 않아도 된다. 왜냐면 스택심볼은 


'컴퓨터 공학과 졸업 > 시스템프로그래밍' 카테고리의 다른 글

Thread-safe, Reentrant 함수  (0) 2018.05.31
링커 정리  (1) 2018.03.30
댓글
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함