본문 바로가기

개발

컴파일&링킹 요약 정리

==== 개요 ====
  * 소스 구현 후 실행 파일이 만들어지기까지의 전반적인 흐름을 소개.

==== 전체 흐름 ====
  * bash$ gcc -o test test.c 이와 같은 명령어를 실행 하면 실제 동작은 다음과 같다.

test.c->|전처리기|->test.i->|C컴파일러|->test.s->|어셈블러|->test.o->|링커|->test

  * 위와 같이 4단계를 거쳐서 최종 실행 파일을 생성한다.

==== 세부 사항 ====
    - 전처리기
      * cpp0 이라는 프로그램이 수행
      * 역할 - 헤더파일 삽입 & 매크로 치환 및 적용
      * *.i 파일 생성
    - C 컴파일러
      * cc1 이라는 프로그램이 수행
      * 어휘분석->구문분석->의미분석->중간언어생성->최적화->목적코드생성

        - 어휘분석 : 스캐너에 의해 *.i 파일을 읽어 토큰 단위로 나눔
        - 구문분석 : 파서가 담당하며 문법적 오류 검사 후 중간언어생성 위해 파서트리 생성
        - 중간언어생성 : 언어 종속적인 부분과 기계 종속적인 부분 분리, 컴파일러 모듈화 와 최적화
                                위해 중간 언어(RTL코드:Register Transfer Language,lisp 언어 기반)생성
        - 최적화 : 기능은 같으나 크기가 작고 빠르며 메모리 적게 사용하도록 코드 변경
          - 중간코드(RTL)최적화 : 1.지역최적화, 2.전역최적화, 3. 루프최적화
          - 목적코드 최적화 : 1. 최대한 레지스터 사용토록 함, 2. 효율적인 인스트럭션 선택, 3. 메모
                                      리접근 최적화
        - 목적코드생성 : 어셈블리 언어, 재배치 가능한 코드를 생성
    - as 컴파일러 (어셈블러)
      * as 라는 프로그램이 수행
      * *.s파일을 인스트럭션과 DATA가 들어있는 *.o (ELF 바이너리 포맷 구조)파일 생성
    - collect2 링커
      * ld(gcc 구 버전) 혹은 collect2(gcc 최신 버전) 라는 프로그램이 수행
      * *.o 파일과 표준 C 라이브러리를 포함한 그 외 라이브러리와 링크를 수행하여 실행파일 생성

==== 프로그램 실행 순서 ====
  * 실제 프로그램을 실행 시키면 맨처음 main()함수가 호출 되는 것으로 알고
있지만 실제 동작은 그렇지 않다.

  - 커널의 execve() 시스템 콜이 프로그램을 메모리에 적재
  - main(int argc, char argv[][], char envp[][])함수에서 사용하는 인자
     (실행 인자 갯수, 인자, 환경 변수)들을 프로세스의 스택에 push
  - _start 수행
  - _start는 커널이 저장한 정보를 꺼내고 -> _libc_start_main을 호출
  - _libc_start_main 은 필요한 초기화를 수행
  - _libc_start_main -> main ()함수를 호출

반응형