![시작 주소에 대한 정적 및 동적 연결의 영향](https://rvso.com/image/31682/%EC%8B%9C%EC%9E%91%20%EC%A3%BC%EC%86%8C%EC%97%90%20%EB%8C%80%ED%95%9C%20%EC%A0%95%EC%A0%81%20%EB%B0%8F%20%EB%8F%99%EC%A0%81%20%EC%97%B0%EA%B2%B0%EC%9D%98%20%EC%98%81%ED%96%A5.png)
간단한 C 프로그램이 있습니다. 난 달린다:
$ gcc Q1.c -Wall -save-temps -o Q1
그런 다음 생성된 실행 파일을 검사합니다.
$ objdump -f Q1
Q1: file format elf32-i386
architecture: i386, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x080483b0
그런 다음 정적 링크를 사용하여 컴파일합니다.
$ gcc Q1.c -Wall -save-temps -static -o Q1
파일을 다시 검사합니다.
$ objdump -f Q1
Q1: file format elf32-i386
architecture: i386, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x08048e08
정적 및 동적 링크는 프로그램의 시작 주소에 어떤 영향을 줍니까? 시작주소는 의 주소겠죠 main()
?
답변1
시작주소는 의 주소겠죠 main()
?
실제로는 아님: 프로그램의 시작은 실제로 main()
. 기본적으로 GCC는 시작 주소가 _start
기호에 해당하는 실행 파일을 생성합니다. 를 해보면 알 수 있습니다 objdump --disassemble Q1
. 다음은 return 0;
다음에서만 수행되는 간단한 프로그램의 출력입니다 main()
.
0000000000400e30 <_start>:
400e30: 31 ed xor %ebp,%ebp
400e32: 49 89 d1 mov %rdx,%r9
400e35: 5e pop %rsi
400e36: 48 89 e2 mov %rsp,%rdx
400e39: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp
400e3d: 50 push %rax
400e3e: 54 push %rsp
400e3f: 49 c7 c0 a0 15 40 00 mov $0x4015a0,%r8
400e46: 48 c7 c1 10 15 40 00 mov $0x401510,%rcx
400e4d: 48 c7 c7 40 0f 40 00 mov $0x400f40,%rdi
400e54: e8 f7 00 00 00 callq 400f50 <__libc_start_main>
400e59: f4 hlt
400e5a: 66 90 xchg %ax,%ax
400e5c: 0f 1f 40 00 nopl 0x0(%rax)
address 에서 볼 수 있듯이 400e54
차례로 _start()
호출하여 __libc_start_main
필요한 항목(pthreads, atexit 등)을 초기화하고 마지막으로 main()
적절한 인수(argc, argv 및 env)를 사용하여 호출합니다.
좋습니다. 그런데 시작 주소가 변경되는 것과 무슨 관련이 있나요?
정적으로 링크하도록 요청한다는 것은 gcc
위에서 언급한 모든 초기화가 실행 파일에 있는 함수를 사용하여 수행되어야 함을 의미합니다. 실제로 두 실행 파일의 크기를 살펴보면 정적 버전이 훨씬 더 크다는 것을 알 수 있습니다. 내 테스트에서 정적 버전은 800K이고 공유 버전은 6K에 불과합니다.
추가 기능은 앞에 배치되므로 _start()
시작 주소가 변경됩니다. 다음은 정적 실행 파일의 레이아웃입니다 start()
.
000000000049e960 r translit_from_tbl
0000000000400a76 t _i18n_number_rewrite
0000000000400bc0 t fini
0000000000400bd0 t init_cacheinfo
0000000000400e30 T _start
0000000000400e60 t deregister_tm_clones
0000000000400e90 t register_tm_clones
0000000000400ed0 t __do_global_dtors_aux
공유 실행 파일의 레이아웃은 다음과 같습니다.
00000000004003c0 T _start
00000000004003f0 t deregister_tm_clones
00000000004004b0 T main
00000000004004c0 T __libc_csu_init
00000000006008a0 B _end
0000000000400370 T _init
결과적으로 약간 다른 시작 주소를 얻게 됩니다. 정적 경우에는 0x400e30이고 공유 경우에는 0x4003c0입니다.