IT한 것/unix

링킹 뭘로 할까 gcc/cc, ld ??

lovian 2012. 5. 2. 10:48

최근 특이한 일을 겪었다.


solaris x86 플랫폼에서 빌드 할 일이 있었는데,


c 소스를 gcc로 컴파일하고 ld로 링킹을 하고 있었다.


이 과정까지는 문제가 없었는데, 실행파일을 만들고 실행을하면.

모든 로직을 수행 후, segmentation fault가 발생한다.

※심지어는 hello world만 찍어도 그렇다.


이미 소스코드 레벨의 문제가 아니라는 것이 확인되었으니, 링커를 변경해봤다.

gcc/cc로 링킹을 해보니 정상적으로 작동한다.


응? 뭐지?


뭔가 그 동안 잘못 알고 있는게 아닌가 싶어서 oracle에 접속.

그리고 발견


gcc/cc 가 그간 알아서 해주던 entry point 설정 작업 등이. ld를 이용할 때에는 알아서 해야한다는 소리.


이미 다 아는 내용이겠지만.

많은 unix들이 실행파일을 만드는 최종 과정에서

main 함수를 호출하는 __start 함수를 가진 사전에 컴파일 된 crt.o 를 결과물에 합쳐준다.


cc a.c 를 수행하면 실제로는


cc -c a.c

ld a.o crt.o [기타옵션]

위의 두 명령이 실행되는 것이다.


ld a.o

라고 명령을 수행하면.

__start 함수가 없는 실행 파일을 만드므로 gnu ld는 경고를 내준다.


gld: warning: cannot find entry symbol _start; defaulting to 0000000000010058

entry point가 없으므로 기본 위치를 강제로 잡아주겠다는 경고.

(이 때문에 코드 수행은 되지만 calling convention에 의한 뒷처리가 빠져있어 segmantation fault가 발생하는 것으로 보인다.)


ld가 이 경고를 때려주지 않아서 한참 돌아온 듯 하네.



어쨋든, 시스템 설정 상 crt.o가 어디 있는지 파악하기도 그렇고, 특정 시스템에 종속되는 것은 특수한 상황이 아니면 바람직하지 않은 것일테니, gcc/cc로 링킹하자.

끝.