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. java环境安装(win7)

    首先,你应该已经安装了 java 的 JDK 了,笔者安装的是:jdk-7u13-windows-x64 接下来主要讲怎么配置 java 的环境变量,也是为了以后哪天自己忘记了做个备份 1.进入&qu ...

  2. Redis中String类型的Value最大可以容纳数据长度

    项目中使用redis存储,key-value方式,在Redis中字符串类型的Value最多可以容纳的数据长度是512M 官方信息: A String value can be at max 512 M ...

  3. iOS开发ReactiveCocoa学习笔记(六)

    RAC操作方法三. demo地址:https://github.com/SummerHH/ReactiveCocoa.git doNext deliverOn timeout interval del ...

  4. Spring Cloud(1):微服务简介

    架构的演进: 1.十年前:用户->单一服务器->单一数据库(支持十万级用户) 2.五年前:用户->负载均衡器->多台服务器->缓存集群->主从数据库(支持百万级用户 ...

  5. 《Head First 设计模式》之适配器模式与外观模式

    适配器模式(Adapter) 适配器(adapter-pattern):将一个类的接口,转换成客户期望的另一个接口.适配器让原来接口不兼容的类可以合作无间.两种形式: 对象适配器(组合) 类适配器(多 ...

  6. Flask蓝图的增删改查

    怎样用flask蓝图来实现增删改查呢?请看下面的内容 这是我们的目录结构 从图中可以看出每一个功能都有一个各自的文件夹 首先我们要自己先来创建一个数据,在Flask_data.py中写入如下内容: S ...

  7. socket网络套节字---聊天室

    一:服务端: 1.创建客户端: package com.ywh.serversocket; import java.io.InputStream; import java.io.OutputStrea ...

  8. Java开发工具IntelliJ IDEA创建Andriod项目示例说明

    IntelliJ IDEA社区版作为一个轻量级的Java开发IDE,是一个开箱即用的Android开发工具. 注意:在本次的教程中我们将以Android平台2.2为例进行IntelliJ IDEA的使 ...

  9. Spring Boot概要

    1.Spring Boot使用“习惯优于配置”(项目中存在大量的配置,此外还内置了一个习惯性的配置)的理念,使用户的项目实现快速运行.通过学习Spring Boot中的配置文件application. ...

  10. /usr/local/sbin/dsniff

    /usr/local/sbin/dsniff 捕获可用的密码