初探gcc编辑器

从经典的hello world开始

gcc -o hello hello.c
-o选项告知gcc编译器将hello.c文件编译为hello文件:
-o选项的格式为:
-o [file] [file2]
直接:gcc file
生成 a.out 命名

gcc编译流程

  • gcc编译器在编译一个C语言程序预处理,生成.i文件.
  • 预处理后的.i文件编译成为汇编语言,生成.s文件.
  • 将汇编语言文件经过汇编,生成目标文件.o文件.
  • 将各个模块.o文件链接起来生成一个可执行程序文件.

gcc常用选项

gcc常用选项汇总

gcc编译选项

选项的意义

-c

编译,汇编指定的源文件,但是不进行链接

-S

编译指定的源文件,但不进行汇编

-E

预处理指定的源文件,不进行编译

-o[file1][file2]

将文件file2编译成可执行文件file1

-I directory

指定include包含文件的搜索目录

-g

生成调试信息,该程序可以被调试器调试

-c选项

gcc -c test1.c test2.c test3.c

-S选项

gcc -S test.c

-E选项

-o选项

gcc main.c calculate.c -o app

-I选项

gcc -c calculate.c
gcc -c main.c
gcc calculate.o main. -c app

-g选项

链接原理

链接器的任务

链接器将多个目标文件链接成一个完整的,可加载,可执行的目标文件.其输入是一组可重定位的目标文件.链接的两个主要任务如下.

  • 符号解析:将目标文件内的引用符号和该符号的定义联系起来.
  • 将符号定义与存储器的位置联系起来,修改对这些符号的引用.

目标文件

  • 可重定位目标文件:该文件中包含二进制代码和数据,这些代码和数据已经转换成了机器指令代码和数据 .o 文件后缀.
  • 可执行目标文件:进行了链接.
  • 共享目标文件:需要时动态加载的 .so 文件.

ELF格式的可重定位的目标文件

ELF(Wxecutable Linkable File)时Linux环境下最常用的目标文件格式,在大多数情况下,无论是可重定位的目标文件还是可执行的目标文件均采用这种格式.

ELF文件由ELF文件头和目标文件的段组成.

由一下几个段组成:

段头部表

.strtab

.line

.debug

.re1.data

.re1.text

symtab

.bss

.data

.rodata

.text

ELF头

  • .text:代码段
  • .rodata:只读数据段.
  • .data:数据段.
  • .bss:块存储段.

以上的4个段会实际加载到内存中,是实实在在的程序段.目标文件中还有一些辅助程序进行链接和加载的信息,这些信息并不加载到内存中.事实上这些信息在生成最终的可执行目标文件时就已经被去掉了.

  • .symtab:符号表.
  • .re1.text:代码段中需要重定位的信息.
  • .re1.data:数据段中需要重定位的信息.
  • .debug:调试信息.
  • .line:源程序的行号映射.
  • .strtab:字符串表.

目标文件中的符号表

这些符号分为3类:

  • 本模块中引用的其他模块所定义的全局符号.
  • 本模块中定义的全局符号.
  • 本模块中定义和引用的局部符号.

重定位的概念

重定位分为一下两部分进行:
1. 重定位段.
2. 重定位符号引用.

符号的重定位信息

关于库

使用库的优势

从链接方式上分为两种:

  • 静态库:实在可执行程序运行前就已经加入到执行码中,成为执行程序的一部分来执行的.
  • 动态库:是在执行程序启动时加载到执行程序中,可以被多个执行程序共享使用.

静态库的概念

静态库是一些目标代码的集合.文件后缀时.a ,Linux环境下使用ar命令创建一个静态库.

创建静态库

功能:创建静态库
命令:ar rcs 静态库名 目标文件1 目标文件2 … 目标文件n
参数:
r 把列表中的目标文件加入到静态库中.
c 若指定的库不存在则创建该库文件.
s 更新静态库文件的索引,使之包含新加入的目标文件文件的内容.

使用静态库

为了使应用程序可以正确应用该库中的全局符号,需要制作一个包含该静态库中全局符号的头文件.
1. 创建头文件 static_lib.h.
2. 引用头文件 include “static_lib.h”
3. 链接静态库

gcc -L/home/linux_c/Linux main.c -lstatic_lib -o app
gcc -L. main.c -lstatic_lib -o app
gcc main.c -static ./libstatic_lib.a -o app
-l选项指定静态库,-L参数来指定库文件的搜索路径. 它俩都不带空格.或者使用’.’作为静态库的搜索路径,表示在当前目录下搜索需要的静态库文件.也支持-static选项对静态库进行链接.

动态库的概念

动态库又称为共享库或者动态链接库.

创建动态库

gcc -shared -fPIC -o share_lib.so share_lib.c
-fPIC 用于生成位置无关的代码. -shared将位置无关的代码只作为动态库.

使用动态库

gcc main1.c ./static_lib.so -o app1
gcc main2.c ./static_lib.so -o app2

gcc工具链

gcc的整套编译开发工具链包括一下工具.
Binutils:一组用于编译,链接,汇编和其他调试目的程序,如下.

工具名

作用

ar

生成静态库

as

汇编器

ld

链接器.在链接过程中,由gcc条用链接器ld,将用户编译生成的目标文件连同系统的glibc启动代码链接在一起,形成最终的可执行文件

nm

查看目标文件中的符号

objcopy

将原目标文件中的内容复制到新的目标文件中,可以通过不同的命令选项调整目标文件中的格式,例如去除某些ELF文件头

ranlib

为静态库文件创建索引,相当于ar命令的的s选项

readelf

解读ELF文件头

size

列出目标文件每一个段的大小和总的大小

strings

列出目标文件中的字符串

strip

去除目标文件中的所有符号,时目标文件尺寸减小

gcc: linux默认编译器集合.
glibc: GNU的C语言标准函数库.