Symbol은 linker가 알아볼 수 있는 기본 단위이며 고유의 주소를 가지는 단위이다. c언어 코드를 컴파일 하는 과정에서 고유한 주소를 가져야 하는 변수가 무엇인지 생각해보면 전역변수, 함수, static 변수 등이 있는데 elf 파일에서 이런 것들을 symbol table로 정리해서 관리한다.
linking은 여러 object 파일을 읽어서 하나의 .out파일을 만드는과정이라고 앞 포스팅에서 얘기했는데, symbol table은 이 과정에서 linker가 필요한 정보를 수집하는데 사용된다.
예를 들어 a.c에서 선언된 함수와 전역변수를 b.c에서 사용할 경우, a.o에 있는 symbol table을 참조하여 b.c의 logic을 완성할 수 있는 것이다. 이같은 간단한 case만 생각해보아도 왜 함수와 전역변수가 고유한 주소를 가지는 symbol에 포함되는지 이해할 수 있을 것이다.
지역변수는 선언된 block에서만 유효하기 때문에 다른 파일에서 사용될 일이 없고 그 말은 즉슨 여러 object를 link할 때 사용되지 않는다는 의미이다. 그래서 지역변수는 Symbol에 포함되지 않는 것이다.
Symbol은 RW, ZI, RO로 구분된다.
RW는 read-write로 초기값이 있는 전역변수를 의미하고, ZI는 zero-initialized로 초기값이 0인 전역변수를 의미하고, RO는 read-only로 수정이 불가능한 전역변수와 text를 의미한다.
고유한 주소를 갖지 않는 변수는 동적할당변수와 지역변수가 있다. 지역변수는 stack에 저장되고, 동적할당변수는 heap에 저장된다. 이런 변수들은 굳이 Symbol로 저장될 필요가 없다.
코드 예제를 통해 각 메모리 영역을 구분해보겠다.
코드에서 각 변수를 위에서부터 순서대로 구분하겠다.
1) a는 전역변수이므로 RW다.
2) ‘b’는 0으로 초기화되었기 때문에 ZI다.
3) ‘arrary’는 초기화 되지 않은 전역변수이므로 ZI다.
4) ‘img’는 const 전역변수이기 때문에 RO다.
5) ‘pData’는 전역변수이므로 RW다.
6) ‘main’은 함수이기 때문에 RO다.
7) ‘c’는 초기화 되지 않은 static이므로 ZI다.
8) ‘d’는 초기화 된 static이므로 RW다.
9) ‘pLabel’은 동적할당되는 지역변수이므로 heap이다.
Stack과 Heap는 전역변수 배열로 선언될 경우 ZI에 포함된다.