※ 질문/내용오류/공유할 내용이 있다면 jinkilee73@gmail.com으로 메일 주세요 :-)


어제에 이어서 다음에 이어질 내용을 공부해보자. object file 중에서 relocatable object file을 중점적으로 보기로 했다. 이전에도 말했지만 object file이 별게 아니다. 그냥 우리가 구현한 C 소스에서 사용한 함수나 변수 혹은 그 외의 여러 정보들을 일정 포멧에 맞춰서 binary 형태로 나열한 단순한 파일일 뿐이다. 그것을 우리는 유식하게 object file이라고 부르는 것 뿐이다. 그렇다면 relocatable object file은 어떤 형태를 띄고 있을까? 아래와 같다. 



하나의 relocatable object file은 위와 같은 형태의 구조로 되어있다. 당연한 말이지만 ELF header 역시 나름의 구조가 있다. 그런데 지금은 그냥 ELF header라는 것이 존재한다는 것만 기억하고 넘어가보자. 


위의 그림에서 각각이 어떤 내용을 담고 있는지 이야기해보자.


.text

이 부분은 코드를 포함하고 있다. 물론 printf();와 같은 형태의 코드가 아니라 machine code를 의미한다. 


.rodata

read-only data 영역이다. 수정하지 못 하고 읽기만 할 수 있는 영역이라는 말이다. 그렇다면 이 부분에는 어떤 정보들이 들어가 있을까? 가령 printf("hello world");라는 함수를 소스파일에서 호출했다면 "hello world"라는 스트링이 저장되기도 한다. 또는 switch 문에서의 jump table 등이 이 영역에 저장된다고 한다. 


.data

말 그대로 data 영역이다. 이 부분은 global variable 중에서 초기화된 global variable의 정보를 포함한다. global variable로 아래와 같이 선언되었다고 가정해보자.

int a = 1;

int b;

a는 선언도 되고 초기화도 되어있는 것을 알 수 있고, b는 선언은 되어있되 초기화는 되지 않은 것을 알 수 있다. data 영역은 int b에 대한 정보는 담지 않고 초기화된 int a에 대한 정보를 담고 있다. 그렇다면 초기화되지 않은 int b와 같은 정보는 어디에 포함되는가?


.bss

이 부분이 바로 초기화되지 않은 global variable에 대한 정보를 포함한다. 여기서 하나 중요한 부분을 집고 넘어가자. 이 부분이 .data section과 다른 점은 바로 실제 사이즈가 0이라는 점이다. 아래의 예시를 보자.



위의 swap.c에서 보면 bufp0은 선언과 초기화가 되어있고 bufp1는 선언만 되어있다. 따라서 bufp0은 .data section에 포함되며 bufp1은 .bss section에 포함된다. swap.c로부터 생성한 swap.o 파일을 readelf 명령어를 통해 확인해보면 아래와 같은 내용을 확인할 수 있다.



.bss 영역의 크기는 0이다. 반면 .data 영역의 크기는 4 byte이다. (이 결과물을 얻기 위한 objdump 명령어의 option은 --headers이다. 이 옵션은 section header 정보를 프린트해준다.) 실제 section 내용을 볼까? 아래의 내용은 section 내용의 일부라는 점을 알아두자. 



.data section 후에 바로 .comment section 으로 넘어간 것을 알 수 있다. .comment section 은 위의 ELF format 그림에서 다뤄지지 않은 부분이다. 조금 구글링을 통해 알아보니 아래의 링크에서 어느 정도의 답을 찾을 수 있었다.

http://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/specialsections.html


특별한 형태의 section 중의 하나가 .comment section이라네... 아무튼 중요한 사실은 .bss 영역이 안 보인다는 것이다. 그렇다 .bss 영역은 section header에는 포함되는 내용이나 실제로 section에서 사이즈를 차지하고 있지는 않다는 것이다. 


.symtab

symbol table 영역을 의미한다. symbol이란 무엇일까? symbol은 하나의 object file이 가지고 있는 변수나 함수 또는 다른 추가적인 정보들을 각각 symbol이라고 한다. 따라서 하나의 object file에는 여러 개의 symbol이 있을 것이다. 아래의 그림을 보면 어떤 정보를 포함하는지 확실히 알 수 있을 것이다.



readelf tool을 이용해서 main.o 파일을 확인해보면 위와 같이 나와있다. 여기서 말하는 main.o의 c파일인 main.c는 아래와 같다. 아래의 코드와 잘 비교해서 봐보라.



C 파일에서 사용한 함수 변수명 등이 symtab에 있다. 그런데 위의 두 그림으로는 알 수 없는 것이 한 가지 있다. local variable이 사용되면 어떻게 될까? local variable은 위의 symtab에 나오지 않는다. 이 부분은 프로그램 실행시 stack에 임시적으로 쌓였다가 사라지는 부분이므로 symtab에서는 확인되지 않는다.



.rel.text

.rel.data : 

이 부분은 각각 .text와 .data section을 relocation할 때 필요한 정보들이다. 이 부분에 대한 자세한 relocation algorithm은 나중에 설명할 예정이다.

 

.debug : 

.line : 

위의 두 부분은 컴파일할 때 -g 옵션을 통해 컴파일되어서 디버깅 관련 정보를 포함하고 있을 때만 선언된다.


.strtab : 

strtab은 문자열에 대한 정보를 포함하는 부분인데 정확하게는 잘 모르겠다.


많은 중요한 정보들이 있다. 하지만 위의 정보 중에서 가장 중요한 정보는 아마도 symbol이나 symbol table에 관한 정보가 아닌가 싶다. 다음 포스팅에서는 symbol에 대해서 조금 더 자세하게 공부해보자. .rel.text와 .rel.data에 대해서는 굉장히 중요한 부분이라고 나는 생각한다. 따라서 그 부분 역시 나중에 자세하게 하나의 포스팅으로 다룰 생각이다.

Posted by 빛나유
,