지난 글에 이어서 Linking을 하는 2가지 방법에 대해서 알아보자
다 쓰고 파일 날아가서 다시 씀
일반적으로 사용하는 함수의 Packaging
- 모든 함수를 하나의 source file에 넣는경우 : 공간과 시간측면에서 비효율적임
- 각각의 함수마다 나누어진 source file에 넣는 경우 : 효율적
Static libraries(.a archive files)
- 여러개의 연관된 파일이 하나의 파일로 묶여있다고 생각한다.
- 일반적으로 사용하는 Static library : libc.a(C standard library), libm.a(C math library)
// main2.c
#include <stdio.h>
#include "vector.h"
int x[2] = {1, 2};
int y[2] = {3, 4};
int z[2];
int main(){
addvec(x, y, z, 2);
printf("z = [%d %d]\n", z[0], z[1]);
return;
}
//libvector.a
// addvec.c
void addvec(int *x, int *y, int *z, int n){
int i;
for(i = 0; i < n; i++){
z[i] = x[i] + y[i];
}
}
// multvec.c
void multvec(int *x, int *y, int *z, int n){
int i;
for(i = 0; i < n; i++){
z[i] = x[i] * y[i];
}
}
Linking 과정 : Compile-time
- addvec.c와 multvec.c를 컴파일 해서 .o파일을 생성하고 .o파일들을 묶어서 libvector.a 라이브러리를 만들어준다.
- main2.c를 컴파일해서 main2.o를 생성한다.
- linking과정에서 libvector.a 의 addvec.o를 가져오고, printf함수도 사용하기 때문에 libc.a(C Standard library)에서 printf.o 를 가져온다
- Fully linked executable object file을 생성하고 실행한다(메모리에 load).
Static library의 단점
- 중복되는 함수를 모든 프로세서에서 사용할 때 각각의 프로세서 모두 해당 함수에대한 바이너리 코드를 가지고 있기 때문에 메모리 측면에서 좋지않다.
- 함수에 버그가 발생하면 linking파일을 새로 만들어야 한다.
* Linker 알고리즘
- .a파일에 있는 .o파일을 순차적으로 탐색한다.
- unresolved references(main2.c의 addvec처럼 아직 연결되지 못한 함수)를 찾아서 list에 추가한다.
- addvec 같은 함수에 대한 symbols table을 구성한다.
Shared libraries : 프로그램을 실제로 실행할 때(프로그램이 memory로 load될 때) 사용한다.
- 실행파일이 메모리에 처음 올라올 때 linking을 수행하는 경우(load-time linking) ex) libc.so
- 프로그램 실행 도중 실제로 해당 라이브러리 함수가 호출 될 때 linking을 수행하는 경우(run-time linking) : ex) web server(라이브러리가 업데이트 되더라도 계속 실행 가능)
Linking 과정 : Load-time
- addvec.c와 multvec.c를 컴파일 해서 .o파일을 생성한다.
- gcc -shared -o libvector.so addvec.o multvec.o : -shared 옵션을 사용해서 addvec.o 와 multvec.o 를 libvector.so 라는 하나의 shared library를 만들어준다.
- main2.c를 컴파일해서 main2.o를 생성한다.
- main2.o의 addvec, printf등의 함수에 대해서 linking이 필요하다는 정보만 기록해두고 해당 함수의 라이브러리를 실행파일에 넣지는 않는다.
- Partitially linked executable object file을 만들고 이를 실행할 때(메모리에 load될 때) libvector.so 의 addvec.o를 가져오고, printf함수도 사용하기 때문에 libc.so(C Standard library)에서 printf.o 를 가져온다
- Fully linked executable object file을 생성한다.
Linking 과정 : Run-time (코드로 설명)
// dll.c
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
int x[2] = {1, 2};
int y[2] = {3, 4};
int z[2];
int main(){
void *handle;
void(*addvec)(int*,int*,int*,int);
char *error;
// addvec()을 가지고있는 라이브러리를 동적으로 load한다.
handle = dlopen("./libvector.so", RTLD_LAZY);
if(!handle)
...
// 라이브러리에서 addvec()에 대한 pointer를 받아온다
addvec = dlsym(handle, "addvec");
if((error = dlerror()) != NULL)
...
// 일반적인 함수를 사용하는 것 처럼 사용한다
addvec(x, y, z, 2);
printf("z = [%d %d]\n", z[0], z[1]);
// unload the shared library
...
return;
}
*dlopen() : 함수에 대한 일종의 key를 받는다고 생각
Dynamic linking(Run-time) : 코드를 작성할 때부터 해당 함수를 동적으로 Linking 하겠다고 명시해야한다. (코드 작성이 어려워짐)
'CS > SystemSoftware' 카테고리의 다른 글
SystemSoftware - Exceptional Control Flow #2 (0) | 2021.06.05 |
---|---|
SystemSoftware - Exceptional Control Flow #1 (0) | 2021.06.05 |
SystemSoftware - Linking #1 (0) | 2021.06.03 |
Attack Lab Solution Phase_1 ~ Phase_5 (3) | 2021.05.31 |
SystemSoftware - Buffer OverFlow #2 (0) | 2021.05.19 |