카테고리

asm (27) bootloader_x86_grub (1) C (92) compile (11) config (76) CPP (13) CSS (1) debugging (7) gimp (1) Go (1) html (1) Java (1) JavaScript (1) kernel (19) LibreOffice (3) Linux system progamming (21) MFC (1) opencv (4) OpenGL (1) PHP (1) Python (4) qemu (29) shell (3) socket (7) troubleshooting (2) ubuntu18.04 (2) windows (1)

2018/12/16

shared library 동적 라이브러리 링커 해석 정리

동적 공유 라이브러리 객체

1.공유 라이브러리(.so)
공유 라이브러리는 객체 파일 그룹 이므로, 정적 라이브러리와 유사하다. 링커와 로더가 모두 동적 라이브러리와 다르게 동작하므로 공유 라이브러리는 정적 라이브러리와는 다른 구조의 라이브러리 체계이다.

링커에 의해 수정 되지 않고 모든 주소에서 로드되고 실행 될 수 있는 코드는 독립적인 코드 라고 하며, gcc에 대 한 -fPIC 옵션은 컴파일러가 독립적인 코드 위치를 생성 하도록 지정 한다. 이는 공유 라이브러리 코드가 메모리에 위치 하게 될 링크 시간을 알 수 없기 때문에 공유 라이브러리에 생성시 필요한 옵션이다.

공유 라이브러리를 만드는 단계는 다음과 같다.
1 단계: 객체 파일을 만들려면 -fPIC 플래그를 사용해 각 .c 파일을 컴파일 하여, 오브젝트 파일을 생성한다.

shell> gcc -c -fPIC myadd.c mysub.c mydiv.c mymul.c

2 단계: 공유 라이브러리 객체를 생성한 후 다른 객체와 링크하여 실행 파일을 만든다.
shell> gcc -shared myadd.o mysub.o mydiv.o mymul.o -o libarifmath.so

오브젝트 파일 생성
shell> gcc -c *.c
shell> tree
.
├── driver
│   ├── prog1.c
├── libarifmath.so
├── myadd.c
├── myadd.o
├── mydiv.c
├── mydiv.o
├── mymath.h
├── mymul.c
├── mymul.o
├── mysub.c
└── mysub.o

동적 라이브러리 생성
shell> gcc -shared *.o -o libarifmath.so
shell> tree
.
├── driver
│   ├── prog1.c
├── libarifmath.so
├── myadd.c
├── myadd.o
├── mydiv.c
├── mydiv.o
├── mymath.h
├── mymul.c
├── mymul.o
├── mysub.c
└── mysub.o

생성된 공유라이브러리 어셈블러 구조 확인
shell> objdump -d -M intel libarifmath.so | less

공유라이브러리 링커의 동작을 이해하기 위해 컴파일
shell> gcc -c prog1.c
prog1.c:8:10: fatal error: mymath.h: 그런 파일이나 디렉터리가 없습니다
 #include <mymath.h>
          ^~~~~~~~~~

헤더 정보를 지정해 준다.
shell> gcc -c prog1.c -I../
shell> tree
.
├── driver
│   ├── prog1.c
│   └── prog1.o
├── libarifmath.so
├── myadd.c
├── myadd.o
├── mydiv.c
├── mydiv.o
├── mymath.h
├── mymul.c
├── mymul.o
├── mysub.c
└── mysub.o

실행 파일 컴파일.
shell> gcc prog1.o -o test_lee
prog1.o: In function `main':
prog1.c:(.text+0x80): undefined reference to `myadd'
prog1.c:(.text+0xa4): undefined reference to `mysub'
prog1.c:(.text+0xc8): undefined reference to `mymul'
prog1.c:(.text+0xec): undefined reference to `mydiv'
collect2: error: ld returned 1 exit status
동적 라이브러리 위치를 지정해 줘야 한다.

동적 라이브러리 시스템 기본 경로 지정후 컴파일
shell> gcc prog1.o -o test_lee -larifmath

/usr/bin/ld: cannot fin2d -larifmath
collect2: error: ld returned 1 exit status

동적 라이브러리 파일 경로 위치 지정 컴파일
shell> gcc prog1.o -o test_lee -larifmath -L../

실행 파일 형식 확인
shell> file test_lee
test_lee: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=d5005aeaaa53773267a76dafff74226f1f03c46b, not stripped

동적 라이브러리 사용 메모리 위치 확인
shell> ldd test_lee
linux-vdso.so.1 (0x00007ffc0a5db000)
libarifmath.so => not found
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb402c73000)
/lib64/ld-linux-x86-64.so.2 (0x00007fb403266000)

심볼 테이블 구조 확인
shell> nm test_lee

실행
shell> ./test_lee
./test_lee: error while loading shared libraries: libarifmath.so: cannot open shared object file: No such file or directory

ldd가 파일 경로를 확인 할 수 없다.
공유 라이브러리 경로 지정
shell> export LD_LIBRARY_PATH=$LD-LIBRARY_PATH:`pwd`:../
shell> ./test_lee
Enter first number: 8
Enter second number: 5
a + b =   13.00
a - b =    3.00
a * b =   40.00
a/b   =    1.60

2. 로드시 동적 링크
shell> gcc -c -fPIC myadd.c mysub.c mydiv.c mymul.c
shell> -shared myadd.o mysub.o mydiv.o mymu.o -o libarifmath.so

.
├── driver
│   ├── test_lee
│   ├── prog1.c
│   └── prog1.o
├── libarifmath.so
├── myadd.c
├── myadd.o
├── mydiv.c
├── mydiv.o
├── mymath.h
├── mymul.c
├── mymul.o
├── mysub.c
└── mysub.o

drvier.c mymath.h -> Translators(cpp, ccl, as) -> driver.o(재배치 가능 객체파일) -> Linker(ld) -> driver(디스크에 저장된 부분적으로 링크된 실행 가능 객체 파일) -> Loader(execve) -> Dynamic Linker(ld-linux.so) -> libarifmath.so, libc.so(code and data) -> 전체 링크된 메모리 실행 가능

libarifmath.so, lib.so(relocation symbol and table info) -> Linker(ld) -> driver(디스크에 저장된 부분적으로 링크된 실행 가능 객체 파일) -> Loader(execve) -> Dynamic Linker(ld-linux.so) -> libarifmath.so libc.so(Code and data) -> 전체 링크된 메모리 실행 가능

댓글 없음:

댓글 쓰기