Gcc工具在源程序文件到可执行文件的应用

Gcc工具在源程序文件到可执行文件的应用,第1张

GCC工具在源程序文件到可执行文件的应用

文章目录
  • GCC工具在源程序文件到可执行文件的应用
    • 一.GCC:
    • 二.Binutils:
    • 三.C运行库
      • 1.准备工作
      • 2.编译过程
        • (1).预处理
        • (2).编译
        • (3).汇编
        • (4).链接
      • 3.分析ELF文件
        • 1.ELF文件的段
        • 2.反汇编ELF
    • 四.总结:
    • 五.参考资料:


一.GCC:

GCC(GNU C Compiler )是编译工具。文本所要介绍的将C/C++语言编写的程序转换为处理器能够执行的是二进制代码的过程即由编译器完成。

二.Binutils:

一组二进制程序处理工具,包括:addr2line、ar、objcopy、objdump、as、ld、ldd、readelf、size等.这一组工具是开发和调试不可缺少的工具,分别简介如下:

  • addr2line:用来将程序地址转换成其所对应的程序源文件以及所对应的代码行,也可以得到所对应的函数.该工具将帮助调试器在调试的过程中对定位对应的源代码位置.
  • as:主要用于汇编,有关汇编的详细介绍参考后文
  • ld:主要用于链接,有关链接的详细介绍参见后文
  • ar:主要用于创建静态库:

    1.如果要将多个.o目标文件生成一个库文件,则存在两种类型的库,一种是静态库,另一种是动态库.


    2.在windows中静态库是以.lib为后缀的文件,共享库是以.dll为后缀的文件.在linux中静态库是以.a为后缀的文件,共享库是以.so为后缀的文件.


    3.如果一个系统中存在多个需要同时运行的程序且这些程序之间存在共享库,那么采用动态库的形式将更节省内存.

  • ldd:可以用于查看一个可执行程序依赖的共享库.
  • objcopy:将一种对象文件翻译成另一种格式,譬如将.bin转换成.elf 、或者将.elf转换成.bin等.
  • objdump:主要的作用是反汇编.有关反汇编的详细介绍,请参见后文.
  • readelf:显示有关ELF文件的信息,请参见后文了解更多信息.
  • size:列出可知性文件每个部分的尺寸和总尺寸、代码段、数据段、总大小等,请参见后文了解使用size的具体使用实例.
三.C运行库
  • C语言标准主要由两部分组成:一部分描述C的语法,另一部分描述C标准库。C标准库定义了一组标准头文件,每个头文件中包含一些相关的函数、变量、类型声明和宏定义,譬如常见的printf函数便是一个C标准库函数,其原型定义在stdio头文件中。
  • C语言标准仅仅定义了C标准库函数原型,并没有提供实现。因此,C语言编译器通常需要一个C运行时库(C Run Time Libray,CRT)的支持。C运行时库又常简称为C运行库。与C语言类似,C++也定义了自己的标准,同时提供相关支持库,成为C++运行时库。

1.准备工作

由于GCC工具链主要是在Linux环境中进行使用,因此本文也将以Linux系统作为工作环境。为了能够演示编译的整个过程,县创建一个工作目录test0,然后用文本编辑其生成一个C语言编写的简单hello.c程序为例。

		mkdir test0 
		cd test0/
		touch hello.c
	    vim hello.c

键入一个Hello World的简单程序:

#include
int main(void)

{
	printf("Hello World! \n");
	return 0;
}
2.编译过程 (1).预处理

使用gcc进行预处理的命令如下:

	gcc -E hello.c -o hello.i
  • 将源文件hello.c 文件预处理生成hello.i
  • GCC的选项-E使GCC在进行完预处理后立即停止

(2).编译

编译过程就是对预处理完的文件进行一系列的词法分析,语法分析,语义分析以及优化后生成的相应汇编代码。

使用gcc进行编译的命令如下:

	gcc -S hello.i -o hello.s
  • 将预处理生成的hello.i 文件编译生成汇编程序hello.s
    GCC的选项-S使GCC在执行完编译后停止,生成汇编程序

(3).汇编
  • 汇编过程调用对汇编代码进行处理,生成处理器能识别的指令,保存在后缀为.o的目标文件中。由于每一个汇编豫剧机会都对应一条处理器指令,因此,汇编相对于编译过程来说比较简单,通过调用Binutils中的汇编其as根据汇编指令和处理器指令的对照表一一翻译即可。
  • 当程序由多个源代码文件构成时,每个文件都要先完成汇编工作。生成.o目标文件后,才能进入下一步的链接工作。注意:目标文件已经是最终程序的某一部分了,但是在链接之前还不能执行。

使用gcc进行编译的命令如下:

	gcc -c hello.s -o hello.o
  • 将编译生成的hello.s文件汇编生成目标文件hello.o
    GCC的选项-c使GCC在执行完汇编之后停止,生成目标文件

(4).链接

链接也分为静态链接和动态链接,其要点如下:

(1)静态链接是指在编译阶段直接把静态库加入到可执行文件中去,这样可执行文件会比较大。链接器将函数的代码从其所在地(不同的目标文件或静态链接库中)拷贝到最终的可执行程序中。为创建可执行文件,链接器必须要完成的主要任务是:符号解析(把目标文件中符号的定义和引用联系起来)和重定位(把符号定义和内存地址对应起来然后修改所有对符号的引用)。


(2)动态链接则是指链接阶段仅仅只加入一些描述信息,而程序执行时再从系统中把相应动态库加载到内存中去。

注意:由于链接动态库和静态库的路径可能有重合,所以如果在路径中有同名的静态库文件和动态库文件,比如libtest.a和 libtest.so,gcc链接时默认优先选择动态库,会链接libtest.so,如果要让gcc选择链接libtest.a则可以指定gcc选项-static,该选项会强制使用静态库进行链接。

使用命令“gcc hello.c -o hello”则会使用动态库进行链接,生成的ELF可执行文件的大小(使用Binutils的size命令查看)和链接的动态库(使用Binutils的ldd命令查看)



若使用命令“gcc -static hello.c -o hello”则会使用静态库进行链接,生成的ELF可执行文件的大小(使用Binutils的size命令查看)和链接的动态库(使用Binutils的ldd命令查看)


链接器链接后生成的最终文件为ELF格式可执行文件,一个ELF可执行文件通常被链接为不同的段,常见的段譬如.text、.data、.rodata、.bss等段。

3.分析ELF文件
1.ELF文件的段
  • *ELF文件格式如下图,位于ELF Header 和 Section Header Table 之间的都是段(Section)。一个典型的ELF文件包含下面几个段:
  • .text: 已编译程序的指令代码段。

  • .rodata: ro代表read only,即只读数据(譬如常数const)。

  • .data: 已初始化的C程序全局变量和静态局部变量。

  • .bss: 未初始化的C程序全局变量和静态局部变量。

  • .debug: 调试符号表,调试器用此段的信息帮助调试。

	可以用readelf -S查看其各个section的信息如下:
	readelf -S hello

2.反汇编ELF

由于ELF文件无法被当作普通文本文件打开,如果希望直接查看一个ELF文件包含的指令和数据,需要使用反汇编的方法。

使用objdump -D 对其进行反汇编如下:
	objdump -D hello


使用objdump -S将其反汇编并且将其C语言源代码混合显示出来:
	gcc -o hello -g hello.c   //要加上-g选项
	
	objdump -S hello


四.总结:

仔细学习了参考的两篇文章,按照原文的要求照做了一遍。理解了GCC编译器以及其背后的原理,学习了一些GCC工具的常用命令,熟悉掌握了从源程序文件到可执行文件过程中经过的预处理、编译、汇编、链接的几个过程的顺序和作用。

五.参考资料:
https://mooc1.chaoxing.com/ueditorupload/read?objectId=b9616c5b28b9b0b12e4df8411148087e&fileOriName=GCC%25E7%25BC%2596%25E8%25AF%2591%25E5%2599%25A8%25E8%2583%258C%25E5%2590%258E%25E7%259A%2584%25E6%2595%2585%25E4%25BA%258B.pdf

https://mooc1.chaoxing.com/ueditorupload/read?objectId=94fdef0ff9306a1d78c5d95704d1e248&fileOriName=Linux%2520GCC%25E5%25B8%25B8%25E7%2594%25A8%25E5%2591%25BD%25E4%25BB%25A4.pdf

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/2991258.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-09-23
下一篇 2022-09-23

发表评论

登录后才能评论

评论列表(0条)

保存