gcc编译过程

现代编译器常见的编译过程: 
源文件-->预处理-->编译/优化-->汇编-->链接-->可执行文件

对于gcc而言:

第一步 预处理
       命令: gcc -o test.i -E test.c
             或者 cpp -o test.i test.c (这里cpp不是值c plus plus,而是the C Preprocessor)
       结果:  生成预处理后的文件test.i(可以打开后与预处理前进行比对,当然长度会吓你一跳)     
       作用:  读取c源程序,对伪指令和特殊符号进行处理。包括宏,条件编译,包含的头文件,以及一些特殊符号。基本上是一个replace的过程。

第二步 编译及优化
        命令:  gcc -o test.s -S test.i
             或者 /路径/cc1 -o test.s test.i
        结果: 生成汇编文件test.s(可打开后查看源文件生成的汇编码)
        作用: 通过词法和语法分析,确认所有指令符合语法规则(否则报编译错),之后翻译成对应的中间码,在linux中被称为RTL(Register Transfer Language),通常是平台无关的,这个过程也被称为编译前端。编译后端对RTL树进行裁减,优化,得到在目标机上可执行的汇编代码。gcc采用as作为其汇编器,所以汇编码是AT&T格式的,而不是Intel格式,所以在用gcc编译嵌入式汇编时,也要采用AT&T格式。
        
第三步 汇编
        命令: gcc -o test.o -c test.s
               或者 as -o test.o test.s
        结果:   生成目标机器指令文件test.o(可用objdump查看)
        作用:  把汇编语言代码翻译成目标机器指令, 用file test.o 可以看到test.o是一个relocatable的ELF文件,通常包含.text .rodata代码段和数据段。可用readelf -r test.o查看需要relocation的部分。
        
第四步 链接
        命令: gcc -o test test.o
               或者 ld -o test test.o
        结果:   生成可执行文件test (可用objdump查看) 
        作用:  将在一个文件中引用的符号同在另外一个文件中该符号的定义链接起来,使得所有的这些目标文件链接成为一个能被操作系统加载到内存的执行体。(如果有不到的符号定义,或者重复定义等,会报链接错)。用file test 可以看到test是一个executable的ELF文件。
        
        当然链接的时候还会用到静态链接库,和动态连接库。静态库和动态库都是.o目标文件的集合。
        静态库:
        命令:ar -v -q test.a test.o
        结果: 生成静态链接库test.a
        作用: 静态库是在链接过程中将相关代码提取出来加入可执行文件的库(即在链接的时候将函数的代码将从其所在地静态链接库中被拷贝到最终的可执行程序中),ar只是将一些别的文件集合到一个文件中。可以打包,当然也可以解包。
        
        动态库:  
        命令:  gcc -shared test.so test.o 
             或者/PATH/collect2 -shared test.so test.o (省略若干参数)
        结果:  生成动态连接库test.so
        作用: 动态库在链接时只创建一些符号表,而在运行的时候才将有关库的代码装入内存,映射到运行时相应进程的虚地址空间。如果出错,如找不到对应的.so文件,会在执行的时候报动态连接错(可用LD_LIBRARY_PATH指定路径)。用file test.so可以看到test.so是shared object的ELF文件。
        
当然以上各步可以一步或若干步一起完成,如gcc -o test test.c直接得到可执行文件。

附:
    ELF文件格式
    ELF文件格式是ABI(Application Binary Interface)的一部分,被Tool Interface Standards committee作为在32位Intel架构下可移植的目标文件格式。其格式比较复杂,这里就不细讲了,只说说其类型。
    在specification 1.1中定义了的类型。表示在ELF header中的e_type
    Name        Value  Meaning
    ====        =====  =======
    ET_NONE         0  No file type
    ET_REL          1  Relocatable file
    ET_EXEC         2  Executable file
    ET_DYN          3  Shared object file
    ET_CORE         4  Core file
    ET_LOPROC  0xff00  Processor-specific
    ET_HIPROC  0xffff  Processor-specific
    
    主要的有4种
    1. Relocatable file 保留了代码和数据,被用来和其他的object file一起创建可执行的文件或者是shared object file. (也就是我们常见的.o文件)
    2. Executable file 保留了用来执行的程序,该文件可以被系统exec()加载用以创建程序进程。(也就是我们常说的可执行文件) 
    3. Shared object file 保留了代码和数据,以在两种情况下被连接,一是link editor如ld,可以用它与其他的Relocateble或者Shared的object file一起创建另一个object file. 二是与Executable file或者其他的Shared object file动态链接成为一个进程映像。(也就是我们常说的动态链接库,或者.so文件)    
    4. Core file 的内容在规范中没有指明,目前多用来记录core dump信息。

原文地址:http://blog.csdn.net/lychee007/article/details/4123018

unix gcc编译过程的更多相关文章

  1. Linux学习---GCC编译过程

    (一)GCC编译过程 预处理 cpp -o a.i a.c     //生成预处理文件 等同于[gcc -E] //预处理为将宏定义(#define)等进行替换. 编译 /user/lib/gcc/i ...

  2. GCC编译过程与动态链接库和静态链接库

    1. 库的介绍 库是写好的现有的,成熟的,可以复用的代码.现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常. 本质上来说库是一种可执行代码的二进制形式,可 ...

  3. 1.GCC编译过程

    一. GCC编译过程 gcc -E hello.c -o hello.i // 预处理.将代码中包含的头文件和宏进行替换 gcc -S hello.i -o hello.s // 汇编.将当前文本转换 ...

  4. gcc 编译过程

    gcc 编译过程从 hello.c 到 hello(或 a.out)文件, 必须历经 hello.i. hello.s. hello.o,最后才得到 hello(或a.out)文件,分别对应着预处理. ...

  5. system 系统调用、gcc编译过程

    system 库函数的功能是执行操作系统的命令或者运行指定的程序 #include <stdio.h> #include <stdlib.h>//引入库 int main() ...

  6. GCC编译过程

    以下是C程序一般的编译过程: gcc的编译流程分为四个步骤,分别为:· 预处理(Pre-Processing) 对C语言进行预处理,生成*.i文件.· 编译(Compiling) 将上一步生成的*.i ...

  7. Linux系统GCC常用命令和GCC编译过程描述

    前言: GCC 原名为 GNU C 语言编译器(GNU C Compiler),因为它原本只能处理 C语言.GCC 很快地扩展,变得可处理 C++.后来又 扩展能够支持更多编程语言,如Fortran. ...

  8. gcc编译过程简述

    在linux系统上,从源文件到目标文件的转化是由编译器完成的.以hello.c程序的编译为例,如下: dfcao@linux: gcc -o hello hello.c 在这里,gcc编译器读取源文件 ...

  9. 和菜鸟一起学c之gcc编译过程及其常用编译选项【转】

    转自:http://blog.csdn.net/eastmoon502136/article/details/8162626 版权声明:本文为博主东月之神原创文章,未经博主允许不得转载. 上篇文章,知 ...

随机推荐

  1. Maven的学习资料收集--(六) 构建Hibernate项目

    前面我们使用Maven构建了Struts2项目,这里我们来试一下Hibernate项目: 这里的例子,大体框架应该是正确的,但是,对于Maven的很多约定都没有掌握,估计包的命名都不是非常好,等以后, ...

  2. net 提供了Thread类用于线程的操作

    net 提供了Thread类用于线程的操作. 当初始化一个线程,把Thread.IsBackground=true的时候,指示该线程为后台线程.后台线程将会随着主线程的推出而退出.后台线程不妨碍程序的 ...

  3. Device

    #import "AppDelegate.h" #import "RootViewController.h" @implementation AppDelega ...

  4. Fiddler 抓包工具总结(转)

    Fiddler 抓包工具总结   阅读目录 1. Fiddler 抓包简介 1). 字段说明 2). Statistics 请求的性能数据分析 3). Inspectors 查看数据内容 4). Au ...

  5. jquery初始

    今天我们来学习Jquery的一些基本知识,jquery相对来说还是比较重要的,所以还是要好好学习的. 首先要了解什么是jQuery? l类似于python里面的模块,可以看成是一种库或者插件. 在学习 ...

  6. html的语法 3

    <html> <head> <title>这是第一节课网页标题</title> <!--meta charset="UTF-8" ...

  7. Android 从零开始搭建一个主流项目框架—RxJava2.0+Retrofit2.0+OkHttp

    我这里的网络请求是用的装饰者模式去写的,什么是装饰者模式呢?在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能.它是通过创建一个包装对象,也就是装饰来包裹真实的对象.我的理解就是一个接口, ...

  8. .net密码找回

    using System; using System.Collections.Generic; using System.Text; using System.Net.Mail; using Syst ...

  9. Git 推送和删除标签

    事实上Git 的推送和删除远程标签命令是相同的,删除操作实际上就是推送空的源标签refs:git push origin 标签名相当于git push origin refs/tags/源标签名:re ...

  10. I-129表

    http://www.uscis.gov/i-129 移民局使用的非移民性质的工作身份申请表(I-129)表格将于下月底正式作废,4月30日之后,公民和移民服务局只接受新的I-129表格. 据了解,非 ...