컴파일된 object 파일들을 linking해서 exe파일로 만드는 과정에서 어떤 일들이 일어나는지 알아보자
// main.c
int sum(int *a, int n)
int array[2] = {1, 2}
int main(){
int val = sum(array, 2);
return val;
}
// sum.c
int sum(int *a, int n){
int i, s = 0;
for(i = 0; i < n; i++){
s += a[i];
}
return s;
}
main.c의 sum 함수는 어떤 과정을 통해서 sum.c의 sum 함수를 불러와서 기능을 수행할 수 있을까?
위와 같이 여러 개로 이루어진 파일들을 연결하는 과정을 Linking이라고 한다.
- 먼저 cpp(C Pre-Processor 전처리) 과정을 거친다. #include, #define 같은 과정을 통해 code에서 해당하는 부분들을 전처리해준다.
- cc1이라는 과정을 통해서 어셈블러 코드로 변환된다 C->assembly
- 마지막으로 어셈블러 코드를 통해 .o파일(바이너리 파일)을 만들어 준다.
위 과정을 거치면 main.c, sum.c 파일 모두. o파일이 생기게 된다.
이때 생성된 .o파일들은 Linker를 통해서 실행 가능한 object파일로 변환된다.
위와 같은 방법을 통해 Linking을 하는 이유
- 모듈화(printf 같은 함수가 모듈화가 되었기 때문에 쉽게 불러와서 사용할 수 있다.)
- 효율성(개별 컴파일 가능, (Static Linking, Dynamic Linking) 나중에 설명.)
Linker는 무슨 일을 하는가?
- 심볼들을 연결시켜 준다.(Symbol : 변수명, 함수명, etc..)
Object 파일들의 종류
- Relocatable object file (.o file) : 컴파일이 다 된 바이너리 파일이지만 실제 메모리에 로드되어 실행될 수 없는 상태, 심볼들의 연결이 아직 이루어지지 않음
- Executable object file (a.out file) : 실제로 실행 가능한 object 파일
- Shared object file (.so file) : 일반적으로 '라이브러리' 라고 불리는 파일, 동적으로 Link 될 수 있는 파일
Excutable and Linkable Format (ELF) 에는 어떤 정보들이 있는가
- ELF header : 파일의 type, 단어의 크기 등과 같은 아주 기본적인 정보가 있는 부분
- Segment header table : Page Size, 가상 메모리 segments, segment 크기 등 파일 실행에 필요한 정보들이 있는 부분
- .text section : 일반적인 코드가 있는 부분
- .rodata section : jump tables 같은 읽기 전용 데이터가 있는 부분
- .data section : 초기화된 전역변수 부분
- .bss section : 초기화되지 않은 전역변수, (Block Started by Symbol, Better Save Space 의 약자)
- .symtab section : Symbol table, static변수 부분
- .rel .text section : .text section의 정보를 재조정 하기위한 정보를 가짐
- .rel .data section : .date section의 전역변수들의 정보를 재배치 하기위한 정보를 가짐
- .debug section : 디버깅을 위한 정보를 가짐(gcc -g)
Linker Symbols
- global symbols : non-static 전역변수, non-static 함수
- External symbol : 외부 변수를 참조할 때 사용하는 symbole
- Local symbols : 내부 함수, static 전역변수 (지역변수와는 다름 -> stack에 생성되는 변수(.data section, .bss section 과 연결). 실행 시점과는 연관X)
// main.c
int sum(int *a, int n)
//array : global symbol
int array[2] = {1, 2}
//main : global symbol
int main(){
// Linking을 하기전에는 sum이라는 함수의 주소를 알 수 없어서 비워둠
// Linking이후에 sum.c에서 sum함수를 연결하고, sum의 주소를 입력해줌
int val = sum(array, 2);
// val : stack에 생성(Linker 는 local variable에는 관여 X)
return val;
}
// sum.c
//sum : global symbol
int sum(int *a, int n){
//(Linker 는 local variable에는 관여 X)
int i, s = 0;
for(i = 0; i < n; i++){
s += a[i];
}
return s;
}
//symbols.c
int time;
int foo(int a){
int b = a + 1;
return b;
}
int main(int argc, char* argv[]){
printf("%d\n", foo(5));
return 0;
}
위 symbols.c에서 symbol table(global v, function, static local...)에 포함되는 변수는 어떤게 있을까?
Names:
- time : global 변수
- foo : 함수
- a : 지역변수 (symbol table X)
- b : 지역변수 (symbol table X)
- argc : 지역변수 (symbol table X)
- argv : 지역변수 (symbol table X)
- main : 함수
- printf : 함수
$ readelf -s symbols.o
gcc -c를 이용해 .o 파일을 만든 후, 위 코드를 이용해서 Symbol table을 확인할 수 있다.
Local Symbols
- local non-static variables : stack에 저장
- local static variables : .bss or .data에 저장
static int x = 15;
int f(){
static int x = 17;
return x++;
}
int g(){
static int x = 19;
return x += 14;
}
int h(){
return x += 27;
}
위 코드에서 x라는 변수가 많이 사용된다. f, g함수 내부에서 static int로 x를 선언해서 사용하고, h 함수에서도 x를 사용한다. 변수명이 같은 경우(f, g 함수 내부) x의 symbol은 x.1721, x.1724 같은 유니크한 심볼로 만들어 진다.(충돌 방지)
- Strong : 초기화된 전역변수
- Weak : 초기화되지 않은 전역변수, extern 으로 선언된 변수
만약 변수명이 같아 충돌이 일어난다면 Symbols Rules에 따라서 변수를 linking 한다
Rule1 : Strong 우선(가까이 있는 변수 우선 X), Strong 이 2개 이상이면 error
Rule2 : Weak만 여러개 있는 경우 : Weak 변수중 아무거나 사용(danger)
Global 변수의 사용법
//c1.c
#include "global.h"
int f(){
return g+1;
}
//global.h
#ifdef INITIALIZE
int g = 23;
static int init = 1;
#else
extern int g;
static int init = 0;
#endif
//c2.c
#define INITIALIZE
#include <stdio.h>
#include "global.h"
int g = 0;
int main(){
if(init)
// something
int t = f();
printf("Call f %d\n", t);
return 0;
}
global symbol에 대해서 "global.h"를 사용해 깔끔하게 코딩하는 방법
'CS > SystemSoftware' 카테고리의 다른 글
SystemSoftware - Exceptional Control Flow #1 (0) | 2021.06.05 |
---|---|
SystemSoftware - Linking #2 (0) | 2021.06.04 |
Attack Lab Solution Phase_1 ~ Phase_5 (3) | 2021.05.31 |
SystemSoftware - Buffer OverFlow #2 (0) | 2021.05.19 |
SystemSoftware - Buffer OverFlow #1 (0) | 2021.05.19 |