生成可执行程序的四个步骤

您所在的位置:网站首页 程序设计步骤六个步骤 生成可执行程序的四个步骤

生成可执行程序的四个步骤

2024-07-13 23:39:33| 来源: 网络整理| 查看: 265

目录

导读

一.预编译

二.编译

三.汇编

四.链接

五.扩展

六.例子

生成.o目标文件(编译间段)

查看符号表信息(编译间段)

.o目标文件的文件格式

查看.o文件的段头信息(编译间段)

 查看汇编代码(编译间段)

查看链接后文件的符号表(链接间段)

查看汇编代码(链接间段)

查看段头信息(链接间段)

查看段表信息(链接间段)

可执行文件的加载过程

导读

相信大家对下列这段代码都不陌生

a.c

#include int main() { printf("Hello World!\n"); return 0; }

在Linux中,当我们使用gcc来编译这个程序时,只需使用最简单的命令

gcc -o a a.c

实际上,上述过程可以分解为4个步骤,分别是预处理(又可以被称为预编译),编译,汇编,链接。

用命令来体现就是如下四个步骤:

预处理 gcc -E a.c -o a.i 编译 gcc -s a.i -o a.s 汇编 gcc -c a.s -o a.o 链接 gcc a.o -o a//gcc -o a a.o 一.预编译

预编译过程主要处理那些源代码文件中的以“#”开始的预编译指令,比如“#include”,“#define”等,主要处理规则如下:

将所有的“#define”删除,并且展开所有的宏定义。处理所有条件预编译指令,比如“#if”,“#ifdef”,“#elif”,“#else”,“#endif”。处理“#include”预编译指令,将被包含的文件插入到该预编译指令的位置。注意,这个过程是递归进行的,也就是说被包含的文件可能还包含其他文件。删除所有的注释“//”和“/**/”。添加行号和文件名标识,比如#2“a.c”2,以便于编译时编译器产生调试用的行号信息及用于编译时产生编译错误或警告时能够显示行号。保留所有的#pragma编译器指令,因为编译器需要使用它们。 二.编译

编译过程就是把预处理完的文件进行一系列词法分析,语法分析,语义分析,代码优化及优化后生成相应的汇编代码文件。

代码优化的优缺点:

优点:提高效率缺点:多线程下不可控 三.汇编

汇编过程就是由汇编器将汇编代码转变成机器可以执行的二进制指令。

四.链接

链接的主要内存就是把各个模块之间相互引用长度部分都处理好,使得各个模块之间能够正确的衔接。简单的理解为将各个目标文件链接起来生成最终的可执行文件。

链接过程可以具体的分为以下四步:

合并段和符号表,合并多个文件的符号表及各段内容,放入一个新的文件中。符号解析,在每个文件符号引用(引用外部符号)的地方找到符号的定义。这就是符号解析。地址和空间分配,符号解析成功后,为程序分配虚拟地址空间。符号重定位 // 指令段,符号重定向就是对.o文件中.text段指令中的无效地址给出具体的虚拟地址或者相对位移偏移量。

链接又分为

静态链接动态链接 五.扩展

目标文件就是源代码经过编译后但未进行链接的那些中间文件。Linux下的 .o文件就是目标文件,目标文件和可执行文件内容和 格式几乎都一样,所以我们可以广义地将目标文件和可执行文化看成一类型文件。

目标文件除了含有汇编后的机器指令代码,数据外,还包括了链接时所需要的一些信息,比如符号表,调试信息,字符串等。一般目标文件将这些信息按不同的属性,以“节”的形式存储,有时候也叫做“段”。

程序源代码编译后的机器指令经常被放在.text段,已初始化的全局变量和局部静态变量都保存在.data段,未初始化的全局变量和局部静态变量一般放在.bss段。注意,.bss段只是为未初始化的全局变量和局部静态变量预留位置而已,它并没有内容,所以它在文件中也不占据空间。.rodata段存放的是只读数据。

六.例子

现在有上述三个文件,在这里需要注意,我们定义全局变量gdata时,不能将它定义在 sum.h文件中,否则会引起gdata的多重定义,而是应该将它定义在sum.c中,并且当我们在main.cpp中引用gdata时,应该加上 extern int gdata这一句。extern是计算机语言中的一个关键字,可置于变量或者函数前,以表示变量或者函数的定义在别的文件中。提示编译器遇到此变量或函数时,在其它模块中寻找其定义,另外,extern也可用来进行链接指定。

生成.o目标文件(编译间段) gcc -c sum.c gcc -c main.c

执行后,就会生成sum.o 和 main.o

查看符号表信息(编译间段) objdump -t main.o objdump -t sum-o

来看一下这两个.o文件中的段信息。如下

main.o: 文件格式 elf64-x86-64 SYMBOL TABLE: 0000000000000000 l df *ABS* 0000000000000000 main.c 0000000000000000 l d .text 0000000000000000 .text 0000000000000000 l d .data 0000000000000000 .data 0000000000000000 l d .bss 0000000000000000 .bss 0000000000000000 l d .rodata 0000000000000000 .rodata 0000000000000000 l d .note.GNU-stack 0000000000000000 .note.GNU-stack 0000000000000000 l d .eh_frame 0000000000000000 .eh_frame 0000000000000000 l d .comment 0000000000000000 .comment 0000000000000000 g O .data 0000000000000004 data 0000000000000000 g F .text 0000000000000049 main 0000000000000000 *UND* 0000000000000000 gdata 0000000000000000 *UND* 0000000000000000 _GLOBAL_OFFSET_TABLE_ 0000000000000000 *UND* 0000000000000000 sum 0000000000000000 *UND* 0000000000000000 printf sum.o: 文件格式 elf64-x86-64 SYMBOL TABLE: 0000000000000000 l df *ABS* 0000000000000000 sum.c 0000000000000000 l d .text 0000000000000000 .text 0000000000000000 l d .data 0000000000000000 .data 0000000000000000 l d .bss 0000000000000000 .bss 0000000000000000 l d .note.GNU-stack 0000000000000000 .note.GNU-stack 0000000000000000 l d .eh_frame 0000000000000000 .eh_frame 0000000000000000 l d .comment 0000000000000000 .comment 0000000000000000 g O .data 0000000000000004 gdata 0000000000000000 g F .text 0000000000000014 sum

关于objdump命令:

objdump  -h  xxxx.o

        打印主要段的信息

objdump  -x  xxxx.o             打印更多的详细信息 objdump  -s  xxx.o             将所有段的内容以16进制方式打印出来 objdump  -d  xxx.o  或者-S             将所有包含指令的段反汇编 objdump   -t   xxx.o             查看所有的符号以及他们所在段 readelf  -h   xxx.o             查看.o文件的文件头详细信息 readelf   -S   xxx.o             显示.o文件中的所有段,即查看段表 size xxx.o             查看.o文件中各个段所占大小 nm xxx.o             查看.o文件中所有的符号

 我们看到虽然gdata和sum函数并不是在main.c中定义的,但编译后的main.o也产生了他们的符号,main.o符号表中*gdata与_Z3sumii都是*UND*未定义,表明未在本文件中定义,引用于其他文件。第二列的 l (local)表示只能在当前文件中可见,g(global)表示其他文件中可见。编译过程中符号是不分配虚拟地址的,只有在进行链接后(进行完符号解析后)才会给符号表分配虚拟地址。

.o目标文件的文件格式

查看.o文件的段头信息(编译间段) readelf -h main.o readelf -h sum.o

结果如下:

ELF 头: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 类别: ELF64 数据: 2 补码,小端序 (little endian) 版本: 1 (current) OS/ABI: UNIX - System V ABI 版本: 0 类型: REL (可重定位文件) 系统架构: Advanced Micro Devices X86-64 版本: 0x1 入口点地址: 0x0 程序头起点: 0 (bytes into file) Start of section headers: 920 (bytes into file) 标志: 0x0 本头的大小: 64 (字节) 程序头大小: 0 (字节) Number of program headers: 0 节头大小: 64 (字节) 节头数量: 13 字符串表索引节头: 12 ELF 头: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 类别: ELF64 数据: 2 补码,小端序 (little endian) 版本: 1 (current) OS/ABI: UNIX - System V ABI 版本: 0 类型: REL (可重定位文件) 系统架构: Advanced Micro Devices X86-64 版本: 0x1 入口点地址: 0x0 程序头起点: 0 (bytes into file) Start of section headers: 568 (bytes into file) 标志: 0x0 本头的大小: 64 (字节) 程序头大小: 0 (字节) Number of program headers: 0 节头大小: 64 (字节) 节头数量: 11 字符串表索引节头: 10  查看汇编代码(编译间段) objdump -S main.o

结果如下

main.o: 文件格式 elf64-x86-64 Disassembly of section .text: 0000000000000000 : 0: 55 push %rbp 1: 48 89 e5 mov %rsp,%rbp 4: 48 83 ec 10 sub $0x10,%rsp 8: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # e e: 89 45 fc mov %eax,-0x4(%rbp) 11: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # 17 17: 89 45 f8 mov %eax,-0x8(%rbp) 1a: 8b 55 f8 mov -0x8(%rbp),%edx 1d: 8b 45 fc mov -0x4(%rbp),%eax 20: 89 d6 mov %edx,%esi 22: 89 c7 mov %eax,%edi 24: e8 00 00 00 00 callq 29 29: 89 45 f4 mov %eax,-0xc(%rbp) 2c: 8b 45 f4 mov -0xc(%rbp),%eax 2f: 89 c6 mov %eax,%esi 31: 48 8d 3d 00 00 00 00 lea 0x0(%rip),%rdi # 38 38: b8 00 00 00 00 mov $0x0,%eax 3d: e8 00 00 00 00 callq 42 42: b8 00 00 00 00 mov $0x0,%eax 47: c9 leaveq 48: c3 retq

我们可以看到其中的多条指令显示,他们在执行时对 0x0 地址进行了相关操作,很明显这两句指令不可能执行成功,原因就在于该处指令中用到的符号地址不确定,暂时用 0x0 代替。而在链接后通过符号重定位这一步可以把这些暂时不确定的符号地址重新改写为确定的地址。

查看链接后文件的符号表(链接间段) gcc -o main main.o sum.o objdump -t main main: 文件格式 elf64-x86-64 SYMBOL TABLE: 0000000000000238 l d .interp 0000000000000000 .interp 0000000000000254 l d .note.ABI-tag 0000000000000000 .note.ABI-tag 0000000000000274 l d .note.gnu.build-id 0000000000000000 .note.gnu.build-id 0000000000000298 l d .gnu.hash 0000000000000000 .gnu.hash 00000000000002b8 l d .dynsym 0000000000000000 .dynsym 0000000000000378 l d .dynstr 0000000000000000 .dynstr 0000000000000410 l d .gnu.version 0000000000000000 .gnu.version 0000000000000420 l d .gnu.version_r 0000000000000000 .gnu.version_r 0000000000000440 l d .rela.dyn 0000000000000000 .rela.dyn 0000000000000518 l d .rela.plt 0000000000000000 .rela.plt 0000000000000530 l d .init 0000000000000000 .init 0000000000000550 l d .plt 0000000000000000 .plt 0000000000000570 l d .plt.got 0000000000000000 .plt.got 0000000000000580 l d .text 0000000000000000 .text 0000000000000784 l d .fini 0000000000000000 .fini 0000000000000790 l d .rodata 0000000000000000 .rodata 0000000000000798 l d .eh_frame_hdr 0000000000000000 .eh_frame_hdr 00000000000007e0 l d .eh_frame 0000000000000000 .eh_frame 0000000000200dd8 l d .init_array 0000000000000000 .init_array 0000000000200de0 l d .fini_array 0000000000000000 .fini_array 0000000000200de8 l d .jcr 0000000000000000 .jcr 0000000000200df0 l d .dynamic 0000000000000000 .dynamic 0000000000200fd0 l d .got 0000000000000000 .got 0000000000201000 l d .got.plt 0000000000000000 .got.plt 0000000000201020 l d .data 0000000000000000 .data 0000000000201038 l d .bss 0000000000000000 .bss 0000000000000000 l d .comment 0000000000000000 .comment 0000000000000000 l df *ABS* 0000000000000000 crtstuff.c 0000000000200de8 l O .jcr 0000000000000000 __JCR_LIST__ 00000000000005b0 l F .text 0000000000000000 deregister_tm_clones 00000000000005f0 l F .text 0000000000000000 register_tm_clones 0000000000000640 l F .text 0000000000000000 __do_global_dtors_aux 0000000000201038 l O .bss 0000000000000001 completed.6972 0000000000200de0 l O .fini_array 0000000000000000 __do_global_dtors_aux_fini_array_entry 0000000000000680 l F .text 0000000000000000 frame_dummy 0000000000200dd8 l O .init_array 0000000000000000 __frame_dummy_init_array_entry 0000000000000000 l df *ABS* 0000000000000000 main.c 0000000000000000 l df *ABS* 0000000000000000 sum.c 0000000000000000 l df *ABS* 0000000000000000 crtstuff.c 0000000000000908 l O .eh_frame 0000000000000000 __FRAME_END__ 0000000000200de8 l O .jcr 0000000000000000 __JCR_END__ 0000000000000000 l df *ABS* 0000000000000000 0000000000200de0 l .init_array 0000000000000000 __init_array_end 0000000000200df0 l O .dynamic 0000000000000000 _DYNAMIC 0000000000200dd8 l .init_array 0000000000000000 __init_array_start 0000000000000798 l .eh_frame_hdr 0000000000000000 __GNU_EH_FRAME_HDR 0000000000201000 l O .got.plt 0000000000000000 _GLOBAL_OFFSET_TABLE_ 0000000000000780 g F .text 0000000000000002 __libc_csu_fini 0000000000000000 w *UND* 0000000000000000 _ITM_deregisterTMCloneTable 0000000000201020 w .data 0000000000000000 data_start 0000000000201034 g O .data 0000000000000004 gdata 0000000000201038 g .data 0000000000000000 _edata 0000000000000784 g F .fini 0000000000000000 _fini 0000000000000000 F *UND* 0000000000000000 printf@@GLIBC_2.2.5 0000000000000000 F *UND* 0000000000000000 __libc_start_main@@GLIBC_2.2.5 0000000000201020 g .data 0000000000000000 __data_start 0000000000000000 w *UND* 0000000000000000 __gmon_start__ 0000000000201028 g O .data 0000000000000000 .hidden __dso_handle 00000000000006f9 g F .text 0000000000000014 sum 0000000000000790 g O .rodata 0000000000000004 _IO_stdin_used 0000000000201030 g O .data 0000000000000004 data 0000000000000710 g F .text 0000000000000065 __libc_csu_init 0000000000201040 g .bss 0000000000000000 _end 0000000000000580 g F .text 000000000000002b _start 0000000000201038 g .bss 0000000000000000 __bss_start 00000000000006b0 g F .text 0000000000000049 main 0000000000000000 w *UND* 0000000000000000 _Jv_RegisterClasses 0000000000201038 g O .data 0000000000000000 .hidden __TMC_END__ 0000000000000000 w *UND* 0000000000000000 _ITM_registerTMCloneTable 0000000000000000 w F *UND* 0000000000000000 __cxa_finalize@@GLIBC_2.2.5 0000000000000530 g F .init 0000000000000000 _init

可以看到此时所有的符号都已经分配了虚拟地址。并且已经进行了符号解析。

查看汇编代码(链接间段) objdump -S main main: 文件格式 elf64-x86-64 Disassembly of section .init: 0000000000000530 : 530: 48 83 ec 08 sub $0x8,%rsp 534: 48 8b 05 a5 0a 20 00 mov 0x200aa5(%rip),%rax # 200fe0 53b: 48 85 c0 test %rax,%rax 53e: 74 02 je 542 540: ff d0 callq *%rax 542: 48 83 c4 08 add $0x8,%rsp 546: c3 retq Disassembly of section .plt: 0000000000000550 : 550: ff 35 b2 0a 20 00 pushq 0x200ab2(%rip) # 201008 556: ff 25 b4 0a 20 00 jmpq *0x200ab4(%rip) # 201010 55c: 0f 1f 40 00 nopl 0x0(%rax) 0000000000000560 : 560: ff 25 b2 0a 20 00 jmpq *0x200ab2(%rip) # 201018 566: 68 00 00 00 00 pushq $0x0 56b: e9 e0 ff ff ff jmpq 550 Disassembly of section .plt.got: 0000000000000570 : 570: ff 25 82 0a 20 00 jmpq *0x200a82(%rip) # 200ff8 576: 66 90 xchg %ax,%ax Disassembly of section .text: 0000000000000580 : 580: 31 ed xor %ebp,%ebp 582: 49 89 d1 mov %rdx,%r9 585: 5e pop %rsi 586: 48 89 e2 mov %rsp,%rdx 589: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp 58d: 50 push %rax 58e: 54 push %rsp 58f: 4c 8d 05 ea 01 00 00 lea 0x1ea(%rip),%r8 # 780 596: 48 8d 0d 73 01 00 00 lea 0x173(%rip),%rcx # 710 59d: 48 8d 3d 0c 01 00 00 lea 0x10c(%rip),%rdi # 6b0 5a4: ff 15 2e 0a 20 00 callq *0x200a2e(%rip) # 200fd8 5aa: f4 hlt 5ab: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) 00000000000005b0 : 5b0: 48 8d 3d 81 0a 20 00 lea 0x200a81(%rip),%rdi # 201038 5b7: 48 8d 05 81 0a 20 00 lea 0x200a81(%rip),%rax # 20103f 5be: 55 push %rbp 5bf: 48 29 f8 sub %rdi,%rax 5c2: 48 89 e5 mov %rsp,%rbp 5c5: 48 83 f8 0e cmp $0xe,%rax 5c9: 76 15 jbe 5e0 5cb: 48 8b 05 fe 09 20 00 mov 0x2009fe(%rip),%rax # 200fd0 5d2: 48 85 c0 test %rax,%rax 5d5: 74 09 je 5e0 5d7: 5d pop %rbp 5d8: ff e0 jmpq *%rax 5da: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1) 5e0: 5d pop %rbp 5e1: c3 retq 5e2: 0f 1f 40 00 nopl 0x0(%rax) 5e6: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 5ed: 00 00 00 00000000000005f0 : 5f0: 48 8d 3d 41 0a 20 00 lea 0x200a41(%rip),%rdi # 201038 5f7: 48 8d 35 3a 0a 20 00 lea 0x200a3a(%rip),%rsi # 201038 5fe: 55 push %rbp 5ff: 48 29 fe sub %rdi,%rsi 602: 48 89 e5 mov %rsp,%rbp 605: 48 c1 fe 03 sar $0x3,%rsi 609: 48 89 f0 mov %rsi,%rax 60c: 48 c1 e8 3f shr $0x3f,%rax 610: 48 01 c6 add %rax,%rsi 613: 48 d1 fe sar %rsi 616: 74 18 je 630 618: 48 8b 05 d1 09 20 00 mov 0x2009d1(%rip),%rax # 200ff0 61f: 48 85 c0 test %rax,%rax 622: 74 0c je 630 624: 5d pop %rbp 625: ff e0 jmpq *%rax 627: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1) 62e: 00 00 630: 5d pop %rbp 631: c3 retq 632: 0f 1f 40 00 nopl 0x0(%rax) 636: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 63d: 00 00 00 0000000000000640 : 640: 80 3d f1 09 20 00 00 cmpb $0x0,0x2009f1(%rip) # 201038 647: 75 27 jne 670 649: 48 83 3d a7 09 20 00 cmpq $0x0,0x2009a7(%rip) # 200ff8 650: 00 651: 55 push %rbp 652: 48 89 e5 mov %rsp,%rbp 655: 74 0c je 663 657: 48 8b 3d ca 09 20 00 mov 0x2009ca(%rip),%rdi # 201028 65e: e8 0d ff ff ff callq 570 663: e8 48 ff ff ff callq 5b0 668: 5d pop %rbp 669: c6 05 c8 09 20 00 01 movb $0x1,0x2009c8(%rip) # 201038 670: f3 c3 repz retq 672: 0f 1f 40 00 nopl 0x0(%rax) 676: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 67d: 00 00 00 0000000000000680 : 680: 48 8d 3d 61 07 20 00 lea 0x200761(%rip),%rdi # 200de8 687: 48 83 3f 00 cmpq $0x0,(%rdi) 68b: 75 0b jne 698 68d: e9 5e ff ff ff jmpq 5f0 692: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1) 698: 48 8b 05 49 09 20 00 mov 0x200949(%rip),%rax # 200fe8 69f: 48 85 c0 test %rax,%rax 6a2: 74 e9 je 68d 6a4: 55 push %rbp 6a5: 48 89 e5 mov %rsp,%rbp 6a8: ff d0 callq *%rax 6aa: 5d pop %rbp 6ab: e9 40 ff ff ff jmpq 5f0 00000000000006b0 : 6b0: 55 push %rbp 6b1: 48 89 e5 mov %rsp,%rbp 6b4: 48 83 ec 10 sub $0x10,%rsp 6b8: 8b 05 76 09 20 00 mov 0x200976(%rip),%eax # 201034 6be: 89 45 fc mov %eax,-0x4(%rbp) 6c1: 8b 05 69 09 20 00 mov 0x200969(%rip),%eax # 201030 6c7: 89 45 f8 mov %eax,-0x8(%rbp) 6ca: 8b 55 f8 mov -0x8(%rbp),%edx 6cd: 8b 45 fc mov -0x4(%rbp),%eax 6d0: 89 d6 mov %edx,%esi 6d2: 89 c7 mov %eax,%edi 6d4: e8 20 00 00 00 callq 6f9 6d9: 89 45 f4 mov %eax,-0xc(%rbp) 6dc: 8b 45 f4 mov -0xc(%rbp),%eax 6df: 89 c6 mov %eax,%esi 6e1: 48 8d 3d ac 00 00 00 lea 0xac(%rip),%rdi # 794 6e8: b8 00 00 00 00 mov $0x0,%eax 6ed: e8 6e fe ff ff callq 560 6f2: b8 00 00 00 00 mov $0x0,%eax 6f7: c9 leaveq 6f8: c3 retq 00000000000006f9 : 6f9: 55 push %rbp 6fa: 48 89 e5 mov %rsp,%rbp 6fd: 89 7d fc mov %edi,-0x4(%rbp) 700: 89 75 f8 mov %esi,-0x8(%rbp) 703: 8b 55 fc mov -0x4(%rbp),%edx 706: 8b 45 f8 mov -0x8(%rbp),%eax 709: 01 d0 add %edx,%eax 70b: 5d pop %rbp 70c: c3 retq 70d: 0f 1f 00 nopl (%rax) 0000000000000710 : 710: 41 57 push %r15 712: 41 56 push %r14 714: 41 89 ff mov %edi,%r15d 717: 41 55 push %r13 719: 41 54 push %r12 71b: 4c 8d 25 b6 06 20 00 lea 0x2006b6(%rip),%r12 # 200dd8 722: 55 push %rbp 723: 48 8d 2d b6 06 20 00 lea 0x2006b6(%rip),%rbp # 200de0 72a: 53 push %rbx 72b: 49 89 f6 mov %rsi,%r14 72e: 49 89 d5 mov %rdx,%r13 731: 4c 29 e5 sub %r12,%rbp 734: 48 83 ec 08 sub $0x8,%rsp 738: 48 c1 fd 03 sar $0x3,%rbp 73c: e8 ef fd ff ff callq 530 741: 48 85 ed test %rbp,%rbp 744: 74 20 je 766 746: 31 db xor %ebx,%ebx 748: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1) 74f: 00 750: 4c 89 ea mov %r13,%rdx 753: 4c 89 f6 mov %r14,%rsi 756: 44 89 ff mov %r15d,%edi 759: 41 ff 14 dc callq *(%r12,%rbx,8) 75d: 48 83 c3 01 add $0x1,%rbx 761: 48 39 dd cmp %rbx,%rbp 764: 75 ea jne 750 766: 48 83 c4 08 add $0x8,%rsp 76a: 5b pop %rbx 76b: 5d pop %rbp 76c: 41 5c pop %r12 76e: 41 5d pop %r13 770: 41 5e pop %r14 772: 41 5f pop %r15 774: c3 retq 775: 90 nop 776: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 77d: 00 00 00 0000000000000780 : 780: f3 c3 repz retq Disassembly of section .fini: 0000000000000784 : 784: 48 83 ec 08 sub $0x8,%rsp 788: 48 83 c4 08 add $0x8,%rsp 78c: c3 retq

我们可以看到,在 .o 文件中没有确定的地址已经被重定向至正确的地址。

查看段头信息(链接间段) readelf -h main ELF 头: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 类别: ELF64 数据: 2 补码,小端序 (little endian) 版本: 1 (current) OS/ABI: UNIX - System V ABI 版本: 0 类型: DYN (共享目标文件) 系统架构: Advanced Micro Devices X86-64 版本: 0x1 入口点地址: 0x580 程序头起点: 64 (bytes into file) Start of section headers: 6776 (bytes into file) 标志: 0x0 本头的大小: 64 (字节) 程序头大小: 56 (字节) Number of program headers: 9 节头大小: 64 (字节) 节头数量: 31 字符串表索引节头: 30 查看段表信息(链接间段) readelf -l main Elf 文件类型为 DYN (共享目标文件) 入口点 0x580 共有 9 个程序头,开始于偏移量64 程序头: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align PHDR 0x0000000000000040 0x0000000000000040 0x0000000000000040 0x00000000000001f8 0x00000000000001f8 R E 0x8 INTERP 0x0000000000000238 0x0000000000000238 0x0000000000000238 0x000000000000001c 0x000000000000001c R 0x1 [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2] LOAD 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x000000000000090c 0x000000000000090c R E 0x200000 LOAD 0x0000000000000dd8 0x0000000000200dd8 0x0000000000200dd8 0x0000000000000260 0x0000000000000268 RW 0x200000 DYNAMIC 0x0000000000000df0 0x0000000000200df0 0x0000000000200df0 0x00000000000001e0 0x00000000000001e0 RW 0x8 NOTE 0x0000000000000254 0x0000000000000254 0x0000000000000254 0x0000000000000044 0x0000000000000044 R 0x4 GNU_EH_FRAME 0x0000000000000798 0x0000000000000798 0x0000000000000798 0x0000000000000044 0x0000000000000044 R 0x4 GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 RW 0x10 GNU_RELRO 0x0000000000000dd8 0x0000000000200dd8 0x0000000000200dd8 0x0000000000000228 0x0000000000000228 R 0x1 Section to Segment mapping: 段节... 00 01 .interp 02 .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .plt.got .text .fini .rodata .eh_frame_hdr .eh_frame 03 .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss 04 .dynamic 05 .note.ABI-tag .note.gnu.build-id 06 .eh_frame_hdr 07 08 .init_array .fini_array .jcr .dynamic .got

可以看到在程序的头部信息中,有两个 LOAD(加载器),在执行程序时分别对指令和数据进行加载,这是可执行文件和目标文件的一个区别。

可执行文件的加载过程

在程序运行时,首先创建虚拟地址空间和物理内存的映射(创建内核映射结构体PCB),创建页目录,页表。通过两个加载器把程序的指令和数据加载至虚拟内存空间中。虚拟空间的用户程序并不直接被加载到真实的物理内存上,而是把该程序需要被访问的部分映射到真实的物理地址上,而暂时没有被访问到的部分任然存在于虚拟内存中。通过这样的方式我们发现每个程序的虚拟地址空间可以远大于实际的物理地址空间,使之可以运行远大于自身内存的程序,同时虚拟地址空间也可以小于实际的物理地址空间,使之可以同时运行多个程序。加载完指令和数据后,接着将程序的入口地址写入到下一行指令寄存器。这样,程序就可以被执行了。



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭