/*
名称:实验检测编译过程中的链接作用
说明:以前一直不太了解编译过程中链接是到底干嘛的(其具体的作用是什么),只浅浅的了解到这个阶段就是将各个目标文件连接在一起,至于为什么要连接,怎么连接,不是很清楚。
最近在复习操作系统的时候,了解到,链接阶段的一个功能就是将各个目标文件中的逻辑地址转化为最终可执行文件的的统一的逻辑地址。
这么说吧,每一个源文件生成单独生成的目标文件,其地址(逻辑地址)都是从0x0开始的,而最终生成的可执行文件的逻辑地址也是从0x0开始的,这样的话,那不是有很多个从0x0开始的指令了吗?链接过程就是解决这样的问题的,在这个阶段,所有的目标文件逻辑地址被统一编址,
原来的各个目标文件的指令的地址在可执行文件中被重新安排。
下面的反汇编程序可以看出这一点。
00000000004004ed : //(test_a:在最终可执行文件中开始的地址)
00000000004004fb : //(test_b:在最终可执行文件中开始的地址)
0000000000400516 : //(main:在最终可执行文件中开始的地址)
同时通过反汇编程序,也能了解到每一种可执行文件确实有差别(window下的和linux等不同操作系统下的)。每个可执行文件的开头还有一些初始化部分等。
*/
//文件test_a中的代码:
void test_a()
{
int a = 10;
return ;
}
//文件test_a.o的反汇编
test_a.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 :
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: c7 45 fc 0a 00 00 00 movl $0xa,-0x4(%rbp)
b: 90 nop
c: 5d pop %rbp
d: c3 retq
代码说明:虽然具体的汇编指令看不懂什么意思,但第一行是第一条指令的逻辑地址。
各列的意思大概是,(地址,指令所对应的机器代码,最后一列是汇编代码)
//文件test_a中的代码:
void test_b()
{
int b = 5;
return ;
}
//文件test_b.o的反汇编
test_b.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 :
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: c7 45 fc 05 00 00 00 movl $0x5,-0x4(%rbp)
b: 90 nop
c: 5d pop %rbp
d: c3 retq
代码说明:可以看到第一条指令也是从地址0x00开始的。
//文件main中的代码:
#include "test.h"
void test_c()
{
int c = 30;
}
int main()
{
int m = 20;
test_a();
test_b();
return 0;
}
//文件main.o的反汇编
main.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 :
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: c7 45 fc 1e 00 00 00 movl $0x1e,-0x4(%rbp)
b: 5d pop %rbp
c: c3 retq
000000000000000d :
d: 55 push %rbp
e: 48 89 e5 mov %rsp,%rbp
11: 48 83 ec 10 sub $0x10,%rsp
15: c7 45 fc 14 00 00 00 movl $0x14,-0x4(%rbp)
1c: b8 00 00 00 00 mov $0x0,%eax
21: e8 00 00 00 00 callq 26 0x19>
26: b8 00 00 00 00 mov $0x0,%eax
2b: e8 00 00 00 00 callq 30 0x23>
30: b8 00 00 00 00 mov $0x0,%eax
35: c9 leaveq
36: c3 retq
代码说明:main函数第一条指令也是从0x00开始的(这里的第一条指令不是main函数而是test_c的相关内容)
//最后链接完成的可执行文件的反汇编
main: file format elf64-x86-64
Disassembly of section .init:
00000000004003a8 <_init>:
4003a8: 48 83 ec 08 sub $0x8,%rsp
4003ac: 48 8b 05 45 0c 20 00 mov 0x200c45(%rip),%rax # 600ff8 <_DYNAMIC+0x1d0>
4003b3: 48 85 c0 test %rax,%rax
4003b6: 74 05 je 4003bd <_init+0x15>
4003b8: e8 33 00 00 00 callq 4003f0 <__gmon_start__@plt>
4003bd: 48 83 c4 08 add $0x8,%rsp
4003c1: c3 retq
Disassembly of section .plt:
00000000004003d0 <__libc_start_main@plt-0x10>:
4003d0: ff 35 32 0c 20 00 pushq 0x200c32(%rip) # 601008 <_GLOBAL_OFFSET_TABLE_+0x8>
4003d6: ff 25 34 0c 20 00 jmpq *0x200c34(%rip) # 601010 <_GLOBAL_OFFSET_TABLE_+0x10>
4003dc: 0f 1f 40 00 nopl 0x0(%rax)
00000000004003e0 <__libc_start_main@plt>:
4003e0: ff 25 32 0c 20 00 jmpq *0x200c32(%rip) # 601018 <_GLOBAL_OFFSET_TABLE_+0x18>
4003e6: 68 00 00 00 00 pushq $0x0
4003eb: e9 e0 ff ff ff jmpq 4003d0 <_init+0x28>
00000000004003f0 <__gmon_start__@plt>:
4003f0: ff 25 2a 0c 20 00 jmpq *0x200c2a(%rip) # 601020 <_GLOBAL_OFFSET_TABLE_+0x20>
4003f6: 68 01 00 00 00 pushq $0x1
4003fb: e9 d0 ff ff ff jmpq 4003d0 <_init+0x28>
Disassembly of section .text:
0000000000400400 <_start>:
400400: 31 ed xor %ebp,%ebp
400402: 49 89 d1 mov %rdx,%r9
400405: 5e pop %rsi
400406: 48 89 e2 mov %rsp,%rdx
400409: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp
40040d: 50 push %rax
40040e: 54 push %rsp
40040f: 49 c7 c0 b0 05 40 00 mov $0x4005b0,%r8
400416: 48 c7 c1 40 05 40 00 mov $0x400540,%rcx
40041d: 48 c7 c7 16 05 40 00 mov $0x400516,%rdi
400424: e8 b7 ff ff ff callq 4003e0 <__libc_start_main@plt>
400429: f4 hlt
40042a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
0000000000400430 :
400430: b8 3f 10 60 00 mov $0x60103f,%eax
400435: 55 push %rbp
400436: 48 2d 38 10 60 00 sub $0x601038,%rax
40043c: 48 83 f8 0e cmp $0xe,%rax
400440: 48 89 e5 mov %rsp,%rbp
400443: 77 02 ja 400447 0x17>
400445: 5d pop %rbp
400446: c3 retq
400447: b8 00 00 00 00 mov $0x0,%eax
40044c: 48 85 c0 test %rax,%rax
40044f: 74 f4 je 400445 0x15>
400451: 5d pop %rbp
400452: bf 38 10 60 00 mov $0x601038,%edi
400457: ff e0 jmpq *%rax
400459: 0f 1f 80 00 00 00 00 nopl 0x0(%rax)
0000000000400460 :
400460: b8 38 10 60 00 mov $0x601038,%eax
400465: 55 push %rbp
400466: 48 2d 38 10 60 00 sub $0x601038,%rax
40046c: 48 c1 f8 03 sar $0x3,%rax
400470: 48 89 e5 mov %rsp,%rbp
400473: 48 89 c2 mov %rax,%rdx
400476: 48 c1 ea 3f shr $0x3f,%rdx
40047a: 48 01 d0 add %rdx,%rax
40047d: 48 d1 f8 sar %rax
400480: 75 02 jne 400484 0x24>
400482: 5d pop %rbp
400483: c3 retq
400484: ba 00 00 00 00 mov $0x0,%edx
400489: 48 85 d2 test %rdx,%rdx
40048c: 74 f4 je 400482 0x22>
40048e: 5d pop %rbp
40048f: 48 89 c6 mov %rax,%rsi
400492: bf 38 10 60 00 mov $0x601038,%edi
400497: ff e2 jmpq *%rdx
400499: 0f 1f 80 00 00 00 00 nopl 0x0(%rax)
00000000004004a0 <__do_global_dtors_aux>:
4004a0: 80 3d 91 0b 20 00 00 cmpb $0x0,0x200b91(%rip) # 601038 <__TMC_END__>
4004a7: 75 11 jne 4004ba <__do_global_dtors_aux+0x1a>
4004a9: 55 push %rbp
4004aa: 48 89 e5 mov %rsp,%rbp
4004ad: e8 7e ff ff ff callq 400430
4004b2: 5d pop %rbp
4004b3: c6 05 7e 0b 20 00 01 movb $0x1,0x200b7e(%rip) # 601038 <__TMC_END__>
4004ba: f3 c3 repz retq
4004bc: 0f 1f 40 00 nopl 0x0(%rax)
00000000004004c0 :
4004c0: 48 83 3d 58 09 20 00 cmpq $0x0,0x200958(%rip) # 600e20 <__JCR_END__>
4004c7: 00
4004c8: 74 1e je 4004e8 0x28>
4004ca: b8 00 00 00 00 mov $0x0,%eax
4004cf: 48 85 c0 test %rax,%rax
4004d2: 74 14 je 4004e8 0x28>
4004d4: 55 push %rbp
4004d5: bf 20 0e 60 00 mov $0x600e20,%edi
4004da: 48 89 e5 mov %rsp,%rbp
4004dd: ff d0 callq *%rax
4004df: 5d pop %rbp
4004e0: e9 7b ff ff ff jmpq 400460
4004e5: 0f 1f 00 nopl (%rax)
4004e8: e9 73 ff ff ff jmpq 400460
00000000004004ed :
4004ed: 55 push %rbp
4004ee: 48 89 e5 mov %rsp,%rbp
4004f1: c7 45 fc 0a 00 00 00 movl $0xa,-0x4(%rbp)
4004f8: 90 nop
4004f9: 5d pop %rbp
4004fa: c3 retq
00000000004004fb :
4004fb: 55 push %rbp
4004fc: 48 89 e5 mov %rsp,%rbp
4004ff: c7 45 fc 05 00 00 00 movl $0x5,-0x4(%rbp)
400506: 90 nop
400507: 5d pop %rbp
400508: c3 retq
0000000000400509 :
400509: 55 push %rbp
40050a: 48 89 e5 mov %rsp,%rbp
40050d: c7 45 fc 1e 00 00 00 movl $0x1e,-0x4(%rbp)
400514: 5d pop %rbp
400515: c3 retq
0000000000400516 :
400516: 55 push %rbp
400517: 48 89 e5 mov %rsp,%rbp
40051a: 48 83 ec 10 sub $0x10,%rsp
40051e: c7 45 fc 14 00 00 00 movl $0x14,-0x4(%rbp)
400525: b8 00 00 00 00 mov $0x0,%eax
40052a: e8 be ff ff ff callq 4004ed
40052f: b8 00 00 00 00 mov $0x0,%eax
400534: e8 c2 ff ff ff callq 4004fb
400539: b8 00 00 00 00 mov $0x0,%eax
40053e: c9 leaveq
40053f: c3 retq
0000000000400540 <__libc_csu_init>:
400540: 41 57 push %r15
400542: 41 89 ff mov %edi,%r15d
400545: 41 56 push %r14
400547: 49 89 f6 mov %rsi,%r14
40054a: 41 55 push %r13
40054c: 49 89 d5 mov %rdx,%r13
40054f: 41 54 push %r12
400551: 4c 8d 25 b8 08 20 00 lea 0x2008b8(%rip),%r12 # 600e10 <__frame_dummy_init_array_entry>
400558: 55 push %rbp
400559: 48 8d 2d b8 08 20 00 lea 0x2008b8(%rip),%rbp # 600e18 <__init_array_end>
400560: 53 push %rbx
400561: 4c 29 e5 sub %r12,%rbp
400564: 31 db xor %ebx,%ebx
400566: 48 c1 fd 03 sar $0x3,%rbp
40056a: 48 83 ec 08 sub $0x8,%rsp
40056e: e8 35 fe ff ff callq 4003a8 <_init>
400573: 48 85 ed test %rbp,%rbp
400576: 74 1e je 400596 <__libc_csu_init+0x56>
400578: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1)
40057f: 00
400580: 4c 89 ea mov %r13,%rdx
400583: 4c 89 f6 mov %r14,%rsi
400586: 44 89 ff mov %r15d,%edi
400589: 41 ff 14 dc callq *(%r12,%rbx,8)
40058d: 48 83 c3 01 add $0x1,%rbx
400591: 48 39 eb cmp %rbp,%rbx
400594: 75 ea jne 400580 <__libc_csu_init+0x40>
400596: 48 83 c4 08 add $0x8,%rsp
40059a: 5b pop %rbx
40059b: 5d pop %rbp
40059c: 41 5c pop %r12
40059e: 41 5d pop %r13
4005a0: 41 5e pop %r14
4005a2: 41 5f pop %r15
4005a4: c3 retq
4005a5: 66 66 2e 0f 1f 84 00 data32 nopw %cs:0x0(%rax,%rax,1)
4005ac: 00 00 00 00
00000000004005b0 <__libc_csu_fini>:
4005b0: f3 c3 repz retq
Disassembly of section .fini:
00000000004005b4 <_fini>:
4005b4: 48 83 ec 08 sub $0x8,%rsp
4005b8: 48 83 c4 08 add $0x8,%rsp
4005bc: c3 retq
代码说明:可以看到这里的test_a、test_b、main函数等内容已经不是从0x00开始了,而是按照指令的位置重新排序了。
要说明的是,这个简短的程序的第一条指令并不是就运行main函数中的内容,而是要做一定的初始化工作。如切换上下文中的环境等。