__printf:
0x0000000000064f00 <+0>: sub rsp,0xd8
0x0000000000064f07 <+7>: test al,al
0x0000000000064f09 <+9>: mov QWORD PTR [rsp+0x28],rsi
0x0000000000064f0e <+14>: mov QWORD PTR [rsp+0x30],rdx
0x0000000000064f13 <+19>: mov QWORD PTR [rsp+0x38],rcx
0x0000000000064f18 <+24>: mov QWORD PTR [rsp+0x40],r8
0x0000000000064f1d <+29>: mov QWORD PTR [rsp+0x48],r9
0x0000000000064f22 <+34>: je 0x64f5b <__printf+91>
0x0000000000064f24 <+36>: movaps XMMWORD PTR [rsp+0x50],xmm0
0x0000000000064f29 <+41>: movaps XMMWORD PTR [rsp+0x60],xmm1
0x0000000000064f2e <+46>: movaps XMMWORD PTR [rsp+0x70],xmm2
0x0000000000064f33 <+51>: movaps XMMWORD PTR [rsp+0x80],xmm3
0x0000000000064f3b <+59>: movaps XMMWORD PTR [rsp+0x90],xmm4
0x0000000000064f43 <+67>: movaps XMMWORD PTR [rsp+0xa0],xmm5
0x0000000000064f4b <+75>: movaps XMMWORD PTR [rsp+0xb0],xmm6
0x0000000000064f53 <+83>: movaps XMMWORD PTR [rsp+0xc0],xmm7
0x0000000000064f5b <+91>: mov rax,QWORD PTR fs:0x28
0x0000000000064f64 <+100>: mov QWORD PTR [rsp+0x18],rax
...
- /lib/x86_64-linux-gnu/libc-2.27.so에 정의된 printf
링크는 많은 프로그래밍 언어에서 컴파일의 마지막 단계로 알려져 있으며, 프로그램에서 어떤 라이브러리의 함수를 사용한다면, 호출된 함수와 실제 라이브러리의 함수가 링크 과정에서 연결됨
#include <stdio.h>
int main() {
puts("Hello, world!");
return 0;
}
다음과 같은 코드를 오브젝트 파일로 변환한 후에 다음 명령어를 실행해본다.
$ readelf -s hello-world.o | grep puts
11: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND puts
puts의 선언이 stdio.h에 있어서 심볼로는 기록되어 있지만, 심볼에 대한 자세한 내용은 하나도 기록되어 있지 않음 -> 심볼과 관련된 정보를 찾아서 최종 실행 파일에 기록하는 것이 링크 과정에서 하는 일 중 하나임
예제를 완전히 컴파일하고 다음 명령어를 통해 링크되기 전과 비교해보면, libc에서 puts의 정의를 찾아 연결한 것을 확인할 수 있음
$ gcc -o hello-world hello-world.c
$ readelf -s hello-world | grep puts
2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@GLIBC_2.2.5 (2)
46: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@@GLIBC_2.2.5
$ ldd hello-world
linux-vdso.so.1 (0x00007ffec3995000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fee37831000)
/lib64/ld-linux-x86-64.so.2 (0x00007fee37e24000)
여기서 libc를 같이 컴파일하지 않았음에도 libc에서 해당 심볼을 탐색한 것은, libc가 있는 /lib/x86_64-linux-gnu/가 표준 라이브러리 경로에 포함되어 있기 때문임, gcc는 소스 코드를 컴파일할 때 표준 라이브러리의 라이브러리 파일들을 모두 탐색함
$gcc -o static hello-world.c -static
$gcc -o dynamic hello-world.c -no-pie$ ls -lh ./static ./dynamic
-rwxr-xr-x 1 dreamhack dreamhack 8.2K Nov 9 10:24 dynamic
-rwxr-xr-x 1 dreamhack dreamhack 825K Nov 9 10:23 static