GCC编译流程

Posted qiulinzhang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GCC编译流程相关的知识,希望对你有一定的参考价值。

源文件到可执行文件的转换流程:
源文件->预处理->编译->汇编->链接

参考程序:hello.c

#include<stdio.h>
int main()
{
  printf("Hello World
");
  return 0;
}

1. 预处理:gcc -o hello.i -E hello.c 或cpp -o hello.i hello.c

编译器cpp(the C Preprocessor)把以#开头的代码进行预处理,即替换;比如hello.c中的第一行为#include<stdio.h>,预处理器便将stdio.h的内容直接插入到程序中,可以看到代码从6行扩展到854行。

823 extern FILE *popen (const char *__command, const char *__modes) ;
824 
825 
826 
827 
828 
829 extern int pclose (FILE *__stream);
830 
831 
832 
833 
834 
835 extern char *ctermid (char *__s) __attribute__ ((__nothrow__ , __leaf__));
836 # 912 "/usr/include/stdio.h" 3 4
837 extern void flockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
838 
839 
840 
841 extern int ftrylockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;
842 
843 
844 extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
845 # 942 "/usr/include/stdio.h" 3 4
846 
847 # 2 "hello.c" 2
848 
849 # 2 "hello.c"
850 int main()
851 {
852  printf("Hello World");
853  return 0;
854 }         

2. 编译:gcc -o hello.s -S hello.i或 ccl -o hello.s hello.i

编译器ccl将文本文件hello.i编译成hello.s,这个文件里面包含一个汇编程序

        .file   "hello.c"
        .section        .rodata
.LC0:
        .string "Hello World"
        .text
        .globl  main
        .type   main, @function
main:
.LFB0:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        movl    $.LC0, %edi
        call    puts
        movl    $0, %eax
        popq    %rbp
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE0:
        .size   main, .-main
        .ident  "GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609"
        .section        .note.GNU-stack,"",@progbits
~                                   

3. 汇编阶段:gcc -o hello.o -c hello.s 或 as -o hello.o hello.s

汇编器as将hello.s翻译成机器语言保留在hello.o中,这个就是二进制文件,可以用hexdump hello.o打开(hexdump 16进制查看器)

0000010 0001 003e 0001 0000 0000 0000 0000 0000
0000020 0000 0000 0000 0000 02a0 0000 0000 0000
0000030 0000 0000 0040 0000 0000 0040 000d 000a
0000040 4855 e589 00bf 0000 e800 0000 0000 00b8
0000050 0000 5d00 48c3 6c65 6f6c 5720 726f 646c
0000060 0000 4347 3a43 2820 6255 6e75 7574 3520
0000070 342e 302e 362d 6275 6e75 7574 7e31 3631
0000080 302e 2e34 2934 3520 342e 302e 3220 3130
0000090 3036 3036 0039 0000 0014 0000 0000 0000
00000a0 7a01 0052 7801 0110 0c1b 0807 0190 0000
00000b0 001c 0000 001c 0000 0000 0000 0015 0000
00000c0 4100 100e 0286 0d43 5006 070c 0008 0000
00000d0 0000 0000 0000 0000 0000 0000 0000 0000
00000e0 0000 0000 0000 0000 0001 0000 0004 fff1
00000f0 0000 0000 0000 0000 0000 0000 0000 0000
0000100 0000 0000 0003 0001 0000 0000 0000 0000
0000110 0000 0000 0000 0000 0000 0000 0003 0003
0000120 0000 0000 0000 0000 0000 0000 0000 0000
0000130 0000 0000 0003 0004 0000 0000 0000 0000
0000140 0000 0000 0000 0000 0000 0000 0003 0005
0000150 0000 0000 0000 0000 0000 0000 0000 0000
0000160 0000 0000 0003 0007 0000 0000 0000 0000
0000170 0000 0000 0000 0000 0000 0000 0003 0008
0000180 0000 0000 0000 0000 0000 0000 0000 0000
0000190 0000 0000 0003 0006 0000 0000 0000 0000
00001a0 0000 0000 0000 0000 0009 0000 0012 0001
00001b0 0000 0000 0000 0000 0015 0000 0000 0000
00001c0 000e 0000 0010 0000 0000 0000 0000 0000
00001d0 0000 0000 0000 0000 6800 6c65 6f6c 632e
00001e0 6d00 6961 006e 7570 7374 0000 0000 0000
00001f0 0005 0000 0000 0000 000a 0000 0005 0000
0000200 0000 0000 0000 0000 000a 0000 0000 0000
0000210 0002 0000 000a 0000 fffc ffff ffff ffff
0000220 0020 0000 0000 0000 0002 0000 0002 0000
0000230 0000 0000 0000 0000 2e00 7973 746d 6261
0000240 2e00 7473 7472 6261 2e00 6873 7473 7472
0000250 6261 2e00 6572 616c 742e 7865 0074 642e
0000260 7461 0061 622e 7373 2e00 6f72 6164 6174
0000270 2e00 6f63 6d6d 6e65 0074 6e2e 746f 2e65
0000280 4e47 2d55 7473 6361 006b 722e 6c65 2e61
0000290 6865 665f 6172 656d 0000 0000 0000 0000
00002a0 0000 0000 0000 0000 0000 0000 0000 0000
*
00002e0 0020 0000 0001 0000 0006 0000 0000 0000
00002f0 0000 0000 0000 0000 0040 0000 0000 0000
0000300 0015 0000 0000 0000 0000 0000 0000 0000
0000310 0001 0000 0000 0000 0000 0000 0000 0000
0000320 001b 0000 0004 0000 0040 0000 0000 0000
0000330 0000 0000 0000 0000 01f0 0000 0000 0000
0000340 0030 0000 0000 0000 000b 0000 0001 0000
0000350 0008 0000 0000 0000 0018 0000 0000 0000
0000360 0026 0000 0001 0000 0003 0000 0000 0000
0000370 0000 0000 0000 0000 0055 0000 0000 0000
0000380 0000 0000 0000 0000 0000 0000 0000 0000
0000390 0001 0000 0000 0000 0000 0000 0000 0000
00003a0 002c 0000 0008 0000 0003 0000 0000 0000
00003b0 0000 0000 0000 0000 0055 0000 0000 0000
00003c0 0000 0000 0000 0000 0000 0000 0000 0000
00003d0 0001 0000 0000 0000 0000 0000 0000 0000
00003e0 0031 0000 0001 0000 0002 0000 0000 0000
00003f0 0000 0000 0000 0000 0055 0000 0000 0000
0000400 000c 0000 0000 0000 0000 0000 0000 0000
0000410 0001 0000 0000 0000 0000 0000 0000 0000
0000420 0039 0000 0001 0000 0030 0000 0000 0000
0000430 0000 0000 0000 0000 0061 0000 0000 0000
0000440 0035 0000 0000 0000 0000 0000 0000 0000
0000450 0001 0000 0000 0000 0001 0000 0000 0000
0000460 0042 0000 0001 0000 0000 0000 0000 0000
0000470 0000 0000 0000 0000 0096 0000 0000 0000
0000480 0000 0000 0000 0000 0000 0000 0000 0000
0000490 0001 0000 0000 0000 0000 0000 0000 0000
00004a0 0057 0000 0001 0000 0002 0000 0000 0000
00004b0 0000 0000 0000 0000 0098 0000 0000 0000
00004c0 0038 0000 0000 0000 0000 0000 0000 0000
00004d0 0008 0000 0000 0000 0000 0000 0000 0000
00004e0 0052 0000 0004 0000 0040 0000 0000 0000
00004f0 0000 0000 0000 0000 0220 0000 0000 0000
0000500 0018 0000 0000 0000 000b 0000 0008 0000
0000510 0008 0000 0000 0000 0018 0000 0000 0000
0000520 0011 0000 0003 0000 0000 0000 0000 0000
0000530 0000 0000 0000 0000 0238 0000 0000 0000
0000540 0061 0000 0000 0000 0000 0000 0000 0000
0000550 0001 0000 0000 0000 0000 0000 0000 0000
0000560 0001 0000 0002 0000 0000 0000 0000 0000
0000570 0000 0000 0000 0000 00d0 0000 0000 0000
0000580 0108 0000 0000 0000 000c 0000 0009 0000
0000590 0008 0000 0000 0000 0018 0000 0000 0000
00005a0 0009 0000 0003 0000 0000 0000 0000 0000
00005b0 0000 0000 0000 0000 01d8 0000 0000 0000
00005c0 0013 0000 0000 0000 0000 0000 0000 0000
00005d0 0001 0000 0000 0000 0000 0000 0000 0000
00005e0

4. 链接:gcc -o hello hello.o 或 ld -o hello hello.o

hello.c调用了printf函数,而printf是标准C库的一个函数,他保存在一个名为printf.o 的文件中,这个文件必须以某种方式合并到我们的hello.o的程序中
编译器ld就是负责这种合并,结果得到hello可执行文件,可以被加载到到内存中由系统执行

最后执行:./hello

Hello World

参考:GCC编译过程简述




以上是关于GCC编译流程的主要内容,如果未能解决你的问题,请参考以下文章

gcc编译流程

GCC:编译成程序集并明确与代码的对应关系?

GCC编译器

C程序存储结构

OpenJDK系列:从JVM谈C/C++编译流程

OpenJDK系列:从JVM谈C/C++编译流程