从源文件到可执行程序(二)

关于目标文件源程序经过编译器编译后生成目标文件。目标文件的格式基本和可执行文件相同,只是在进行链接之前,有些符号和函数的地址是未知的,还需要经过链接来进行调整。Linux系统中采用的可执行文件格式是ELF,因此目标文件也采用这种格式进行存储。不光目标文件,静态库文件(其实就是多个目标文件以及一些索引)和动态库文件也都采用这种格式进行存储。使用命令file可以查看文件格式。$ file example.oexample.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped目标文件属于可重定位文件类型,这类文件(包括静态链接库)可以连接成可执行文件或者共享目标文件,通常对应于后缀名为.o的文件。(当然,linux并不以后缀名作为判断文件类型的唯一依据)$ file /bin/bash/bin/bash: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, stripped程序属于可执行文件类型,这类文件通常没有后缀名$ file /lib/ld-2.11.1.so /lib/ld-2.11.1.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, stripped动态链接库属于共享文件类型,通常对应于后缀名为.so的文件。还有另外一种文件也采用ELF文件格式进行存储,那就是core文件(Linux下文件名一般为core.pid,其中pid为进程标识符)。这类文件在调试时很有用,如果程序在运行时崩溃,系统会创建一个对应的core文件,这个文件是程序所占用内存的一个镜像,分析此文件,可以了解程序崩溃时的状态,分析并解决bug。可以看出,虽然很多文件都采用ELF文件格式,但是其具体类型是不同的。ELF文件一般包含很多个段,如代码段,数据段等,每一个段存储程序的不同部分。如文件头(file header)—-文件头,描述文件属性,入口地址,目标操作系统等,其中最重要的就是一个段表。段表时描述各个段的一个数组,描述了各个段的偏移量等所有信息。代码段(code section/text section)—-存储程序指令数据段(data section)—-存储已初始化的全局变量和静态变量符号段(bss section)—-未初始化的全局变量和静态变量代码段和数据段很简单,为了更好的利用程序局部性提高性能,同时利用共享指令来节省空间,代码和数据分开存储。bss段,这个段其实并不占据执行文件的任何空间,只是记录了未初始化的全局变量和静态变量所占的空间,当文件被载入内存执行时,系统为其分配相应的空间。

这是一个示例程序sample.c,终端中输入命令gcc -c sample.c,得到其对应的目标文件sample.o。再利用命令objdump查看该目标文件。$ objdump -h sample.osample.o: file format elf32-i386Sections:Idx Name Size VMA LMA File off Algn 0 .text 0000003c 00000000 00000000 00000034 2**2 CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE 1 .data 00000008 00000000 00000000 00000070 2**2 CONTENTS, ALLOC, LOAD, DATA 2 .bss 00000004 00000000 00000000 00000078 2**2 ALLOC 3 .rodata 00000004 00000000 00000000 00000078 2**0 CONTENTS, ALLOC, LOAD, READONLY, DATA 4 .comment 00000024 00000000 00000000 0000007c 2**0 CONTENTS, READONLY 5 .note.GNU-stack 00000000 00000000 00000000 000000a0 2**0 CONTENTS, READONLYSize和File Off分别代表每个段的长度和位置(以偏移量来表示),CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE表示段的属性。CONTENTS表示这些段在文件中存在,从这里可以进一步确定bss在文件中并不占据任何空间。最诡异的是.note.GNU-stack段,CONTENTS属性表明其存在,但Size却为0。使用size命令可以查看文件各个段的长度。$ size sample.o text data bss dec hex filename 64 8 4 76 4c sample.o

这一生我只牵你的手,因为今生有你早已足够。

从源文件到可执行程序(二)

相关文章:

你感兴趣的文章:

标签云: