从C文件到可执行elf文件
摘要:本文主要为你解释一个C文件是如何被一步步处理成可执行的elf格式文件的。
本文来源: 从C文件到ELF
说明:所有本文的用例是以下hello.c程序:
#include<stdio.h>int main(int argc, char *argv[]){ printf("hello world\n"); return 0;}
1.预处理
作用:预处理器是在真正的编译开始之前由编译器调用的独立程序。预处理器可以删除注释、包含其他文件以及执行宏(宏macro是一段重复文字的简短描写)替代。我们来看看hello.c经过预处理以后的结果:gcc -E hello.c -o hello.i
gcc -S hello.i -o hello.sgcc的-S选项,表示在程序编译期间,在生成汇编代码后,停止,-o输出汇编代码文件。我们同样可以用vim打开观看:
gcc -c hello.s -o hello.o说明,这一步将程序划分为若干段(数据段,代码段等),可以用objdump命令来查看这些目标文件的内容。
$ objdump -x hello.o hello.o: file format elf32-i386hello.oarchitecture: i386, flags 0x00000011:HAS_RELOC, HAS_SYMSstart address 0x00000000Sections:Idx Name Size VMA LMA File off Algn 0 .text 0000001c 00000000 00000000 00000034 2**2 CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE 1 .data 00000000 00000000 00000000 00000050 2**2 CONTENTS, ALLOC, LOAD, DATA 2 .bss 00000000 00000000 00000000 00000050 2**2 ALLOC 3 .rodata 0000000c 00000000 00000000 00000050 2**0 CONTENTS, ALLOC, LOAD, READONLY, DATA 4 .comment 0000002b 00000000 00000000 0000005c 2**0 CONTENTS, READONLY 5 .note.GNU-stack 00000000 00000000 00000000 00000087 2**0 CONTENTS, READONLY 6 .eh_frame 00000038 00000000 00000000 00000088 2**2 CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATASYMBOL TABLE:00000000 l df *ABS*00000000 hello.c00000000 l d .text00000000 .text00000000 l d .data00000000 .data
4连接(Linking)链接:连接器的目的主要是进行重定位和符号解析,gcc连接器是gas提供的,负责将程序的目标文件与所需的所有附加的目标文件连接起来,最终生成可执行文件。附加的目标文件包括静态连接库和动态连接库。
对于上一小节中生成的test.o,将其与C标准输入输出库进行连接,最终生成程序test
gcc hello.o -o hello可以用readelf命令查看elf文件的详细内容:
Histogram for `.gnu.hash' bucket list length (total of 2 buckets): Length Number % of total Coverage 0 1 ( 50.0%) 1 1 ( 50.0%) 100.0%Version symbols section '.gnu.version' contains 5 entries: Addr: 0000000008048266 Offset: 0x000266 Link: 5 (.dynsym) 000: 0 (*local*) 2 (GLIBC_2.0) 0 (*local*) 2 (GLIBC_2.0) 004: 1 (*global*) Version needs section '.gnu.version_r' contains 1 entries: Addr: 0x0000000008048270 Offset: 0x000270 Link: 6 (.dynstr) 000000: Version: 1 File: libc.so.6 Cnt: 1 0x0010: Name: GLIBC_2.0 Flags: none Version: 2Notes at offset 0x00000168 with length 0x00000020: Owner Data sizeDescription GNU 0x00000010NT_GNU_ABI_TAG (ABI version tag) OS: Linux, ABI: 2.6.24在命令行窗口中,执行./hello, 让它说HelloWorld吧!