编译和链接(一)

读《程序员自我修养----链接,装载与库》第二章总结:

   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.i

    gcc -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.sfile_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