编译和链接(一)
读《程序员自我修养----链接,装载与库》第二章总结:
GCC编译过程如下图中,4个绿色模块为编译过程的4个步骤。分别如下:
(1) 预编译(Propressing)
(2) 编译(Compilation)
(3) 汇编 (Assembly)
(4) 链接(Linking)
示例工程源码:
1 预编译处理
预编译过程主要处理那些源代码文件中的以“#”开始的预编译指令。如“#include”,"#define"等。主要的处理规则如下:
- 将所有的#define删除,并且展开所有的宏定义
- 处理所有的条件预编译指令,比如#if #ifdef #elif #else #endif等.
- 处理#include 预编译指令,将被包含的文件插入到该预编译指令的位置。
- 删除所有注释 “//”和”/* */”.
- 添加行号和文件标识,以便编译时产生调试用的行号及编译错误警告行号。
-
保留所有的#pragma编译器指令,因为编译器需要使用它们。
通常使用以下命令来进行预处理:
gcc -E main.c -o main.igcc -E file_a.c -o file_a.i
gcc -E fie_b.c -o file_b.i
参数-E表示只进行预处理 或者也可以使用以下指令完成预处理过程
cpp xxx.c > xxx.i /* cpp – The C Preprocessor */
预处理后得到main.i, file_a.i, ile_b.i如下:
2 编译
编译过程就是把预处理完的文件进行一系列的词法分析,语法分析,语义分析及优化后生成相应的汇编代码。
$gcc –S main.i –o main.s
$gcc –S file_a.i –o file_a.s
$gcc –S file_b.i –o file_b.s
执行上述指令后,得到的main.s,file_a.s,file_b.s如下图:
3 汇编
汇编器是将汇编代码转变成机器可以执行的命令,每一个汇编语句几乎都对应一条机器指令。汇编相对于编译过程比较简单,根据汇编指令和机器指令的对照表一一翻译即可。
$ gcc –c main.c –o main.o$ gcc –c file_a.c –o file_a.o
$ gcc –c file_b.c –o file_b.o
执行上述指令后,得到的main.o , file_a.o, file_b.o内容如下图:
----------------------------------------------------------------------------------------------------------------------------
main.o:
文件格式 elf64-x86-64
Idx Name Size VMA LMA File off Algn
0 .text 00000048 0000000000000000 0000000000000000 00000040 2**0
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
1 .data 00000000 0000000000000000 0000000000000000 00000088 2**0
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000000 0000000000000000 0000000000000000 00000088 2**0
ALLOC
3 .rodata 0000000d 0000000000000000 0000000000000000 00000088 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .comment 0000002c 0000000000000000 0000000000000000 00000095 2**0
CONTENTS, READONLY
5 .note.GNU-stack 00000000 0000000000000000 0000000000000000 000000c1 2**0
CONTENTS, READONLY
6 .eh_frame 00000038 0000000000000000 0000000000000000 000000c8 2**3
CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
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 F .text 0000000000000048 main
0000000000000000 *UND* 0000000000000000 printf
0000000000000000 *UND* 0000000000000000 gub_a
0000000000000000 *UND* 0000000000000000 function_a
0000000000000000 *UND* 0000000000000000 gub_b
0000000000000000 *UND* 0000000000000000 function_b
RELOCATION RECORDS FOR [.text]:
OFFSET TYPE VALUE
0000000000000010 R_X86_64_32 .rodata
000000000000001a R_X86_64_PC32 printf-0x0000000000000004
0000000000000020 R_X86_64_PC32 gub_a-0x0000000000000004
0000000000000027 R_X86_64_PC32 function_a-0x0000000000000004
000000000000002d R_X86_64_PC32 gub_b-0x0000000000000004
0000000000000034 R_X86_64_PC32 function_b-0x0000000000000004
000000000000003a R_X86_64_PC32 gub_a-0x0000000000000004
RELOCATION RECORDS FOR [.eh_frame]:
OFFSET TYPE VALUE
0000000000000020 R_X86_64_PC32 .text
----------------------------------------------------------------------------------------------------------------------------
file_a.o: 文件格式 elf64-x86-64
Idx Name Size VMA LMA File off Algn
0 .text 0000001c 0000000000000000 0000000000000000 00000040 2**0
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
1 .data 00000000 0000000000000000 0000000000000000 0000005c 2**0
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000004 0000000000000000 0000000000000000 0000005c 2**2
ALLOC
3 .comment 0000002c 0000000000000000 0000000000000000 0000005c 2**0
CONTENTS, READONLY
4 .note.GNU-stack 00000000 0000000000000000 0000000000000000 00000088 2**0
CONTENTS, READONLY
5 .eh_frame 00000038 0000000000000000 0000000000000000 00000088 2**3
CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
SYMBOL TABLE:
0000000000000000 l df *ABS* 0000000000000000 file_a.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 .bss 0000000000000004 gub_a
0000000000000000 g F .text 000000000000001c function_a
RELOCATION RECORDS FOR [.text]:
OFFSET TYPE VALUE
0000000000000016 R_X86_64_PC32 gub_a-0x0000000000000004
RELOCATION RECORDS FOR [.eh_frame]:
OFFSET TYPE VALUE
0000000000000020 R_X86_64_PC32 .text
----------------------------------------------------------------------------------------------------------------------------
file_b.o: 文件格式 elf64-x86-64
Idx Name Size VMA LMA File off Algn
0 .text 00000021 0000000000000000 0000000000000000 00000040 2**0
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
1 .data 00000000 0000000000000000 0000000000000000 00000061 2**0
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000004 0000000000000000 0000000000000000 00000064 2**2
ALLOC
3 .comment 0000002c 0000000000000000 0000000000000000 00000064 2**0
CONTENTS, READONLY
4 .note.GNU-stack 00000000 0000000000000000 0000000000000000 00000090 2**0
CONTENTS, READONLY
5 .eh_frame 00000038 0000000000000000 0000000000000000 00000090 2**3
CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
SYMBOL TABLE:
0000000000000000 l df *ABS* 0000000000000000 file_b.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 .bss 0000000000000004 gub_b
0000000000000000 g F .text 0000000000000021 function_b
0000000000000000 *UND* 0000000000000000 gub_a
RELOCATION RECORDS FOR [.text]:
OFFSET TYPE VALUE
0000000000000010 R_X86_64_PC32 gub_a-0x0000000000000004
000000000000001b R_X86_64_PC32 gub_b-0x0000000000000004
RELOCATION RECORDS FOR [.eh_frame]:
OFFSET TYPE VALUE
0000000000000020 R_X86_64_PC32 .text
--------------------------------------------------------------------------------------------------------------------------
4 链接
通过调用链接器ld来链接程序运行需要的一大堆目标文件,以及所依赖的其它库文件,最后生成可执行文件.
可以直接输入如下指令生成 a.out 可执行文件
$ gcc main.c file_a.c file_b.c