Compile

반응형

컴파일(Compile)

  • 소스코드를 컴퓨터가 이해할 수 있는 기계어 형식으로 번역하는 것
  • 어떤 언어로 작성된 소스 코드(Source Code)를 다른 언어의 목적 코드(Object Code)로 번역하는 것

컴파일러(Compiler)

  • 컴파일을 해주는 소프트웨어

컴파일 과정(C → Binary)

  • C 언어로 작성된 코드는 일반적으로 전처리(Preprocess), 컴파일(Compile), 어셈블(Assemble), 링크(Link)의 과정을 거쳐 바이너리로 번역
  • 컴파일러는 코드를 번역할 때, 조건을 만족하면 최적화 기술을 적용하여 효율적인 어셈블리 코드를 생성
  • gcc 에서는 -O -O0 -O1 -O2 -O3 -Os -Ofast -Og 등의 옵션을 사용하여 최적화를 적용할 수 있음
  • 예를 들어 a.c를 최적화하여 컴파일 하면, 컴파일러는 반복문을 어셈블리어로 옮기는 것이 아님
    → 반복문의 결과로 'x'가 가질 값을 직접 계산하여 이를 대입하는 코드를 생성
 사용자가 작성한 소스 코드와 연산결과는 같으면서도, 최적화를 적용하지 않았을 때보다 짧고, 실행시간이 단축되는 어셈블러 코드가 만들어짐
// Name: a.c
// Compile: gcc -o opt a.c -O2
#include <stdio.h>
int main() {
  int x = 0;
  for (int i = 0; i < 100; i++) x += i; // x에 0부터 99까지의 값 더하기
  printf("%d", x);
}

 

 

  • gcc 이용 시 -S 옵션을 이용하면 소스 코드를 어셈블리 코드로 컴파일 할 수 있음
$ gcc -S [소스 코드 파일명] -o [어셈블리 코드로 저장할 파일명]

 

어셈블(Assemble)

  • 컴파일로 생성된 어셈블리어 코드 ELF형식의 목적 파일(Object file)로 변환하는 과정
$ gcc -c [어셈블리어 코드] -o [저장할 목적 파일명]
$ file [저장한 목적 파일명]
//파일에 관한 정보 중 ELF 파일임을 확인 가능
$ hexdump -C [저장한 목적 파일명]
//결과로 나온 파일을 16진수로 출력

# ELF : 리눅스 실행파일 형식

# 윈도우에서 어셈블하게 되면 목적 파일은 PE형식임

 

링크(Link)

  • 여러 목적 파일들을 연결하여 실행 가능한 바이너리로 만드는 과정
  • 아래 코드는 printf 함수를 호출하지만, printf 함수의 정의는 libc라는 공유 라이브러리에 존재
  • libc는 gcc의 기본 라이브러리 경로에 있어 링커는 바이너리가 printf를 호출하면 libc의 함수가 실행될 수 있도록 연결
  • 링크를 거치고 나면 실행할 수 있는 프로그램이 완성
// Name: hello-world.c
// Compile: gcc -o hello-world hello-world.c
#include <stdio.h>
int main() { printf("Hello, world!"); }
  • 일반 파일에 링크로 연결하는 명령어
  • 링크 과정에서 링커는 main 함수를 찾는데 [파일]에는 main 함수의 정의가 없다는 가정하에 에러가 발생될 수 있음
  • 에러 방지를 위해 --unresolved-symbols를 옵션으로 추가
$ gcc [링크로 연결될 파일] -o [파일] -Xlinker --unresolved-symbols=ignore-in-object-files
$ file add

전처리(Preprocessing) 

  • 컴파일러가 소스 코드를 어셈블리어로 컴파일하기 전에, 필요한 형식으로 가공하는 과정
  • 언어마다 조금씩 다르지만, 컴파일 언어의 대부분은 전처리 과정을 거침
  1. 주석 제거
    - 주석은 개발자가 자신과 개발자들의 코드 이해를 돕기위해 작성하는 메모
    - 프로그램의 동작과 상관이 없으므로 전처리 단계에서 모두 제거
  2. 매크로 치환
    - #define으로 정의한 매크로는 자주 쓰이는 코드나 상숫값을 단어로 정의한 것으로,
       전처리 과정에서 매크로의 이름은 값으로 치환
  3. 파일 병합
    - 여러 개의 소스와 헤더 파일을 합치고 컴파일
      (컴파일러가 여러 개의 소스와 헤더 파일을 컴파일해서 합치기도 함)

인터프리팅(Interpreting)

Python, Javascript 등의 언어는 사용자의 입력, 사용자가 작성한 스크립트를 그때 그때 번역하여 CPU에 전달하여 통역하는 역할

 

인터프리터(Interpreter)

인터프리팅을 처리해주는 프로그램

 

 

'Reverse Engineering' 카테고리의 다른 글

Basic  (0) 2023.03.30
Revers Engineering이란?  (0) 2023.03.29